2 * IWineD3DDevice implementation
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Stefan Dösinger for CodeWeavers
10 * Copyright 2006 Henri Verbeet
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light = {
41 WINED3DLIGHT_DIRECTIONAL, /* Type */
42 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
44 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
45 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
46 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
49 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
54 /* x11drv GDI escapes */
55 #define X11DRV_ESCAPE 6789
56 enum x11drv_escape_codes
58 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
59 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
60 X11DRV_GET_FONT, /* get current X font for a DC */
63 /* retrieve the X display to use on a given DC */
64 inline static Display *get_display( HDC hdc )
67 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
69 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
70 sizeof(display), (LPSTR)&display )) display = NULL;
74 /* allocate one pbuffer per surface */
75 BOOL pbuffer_per_surface = FALSE;
77 /* static function declarations */
78 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
80 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil);
83 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
85 #define D3DCREATEOBJECTINSTANCE(object, type) { \
86 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
87 D3DMEMCHECK(object, pp##type); \
88 object->lpVtbl = &IWineD3D##type##_Vtbl; \
89 object->wineD3DDevice = This; \
90 object->parent = parent; \
92 *pp##type = (IWineD3D##type *) object; \
95 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
96 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
97 D3DMEMCHECK(object, pp##type); \
98 object->lpVtbl = &IWineD3D##type##_Vtbl; \
99 object->parent = parent; \
101 object->baseShader.device = (IWineD3DDevice*) This; \
102 *pp##type = (IWineD3D##type *) object; \
105 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
106 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
107 D3DMEMCHECK(object, pp##type); \
108 object->lpVtbl = &IWineD3D##type##_Vtbl; \
109 object->resource.wineD3DDevice = This; \
110 object->resource.parent = parent; \
111 object->resource.resourceType = d3dtype; \
112 object->resource.ref = 1; \
113 object->resource.pool = Pool; \
114 object->resource.format = Format; \
115 object->resource.usage = Usage; \
116 object->resource.size = _size; \
117 /* Check that we have enough video ram left */ \
118 if (Pool == WINED3DPOOL_DEFAULT) { \
119 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
120 WARN("Out of 'bogus' video memory\n"); \
121 HeapFree(GetProcessHeap(), 0, object); \
123 return WINED3DERR_OUTOFVIDEOMEMORY; \
125 globalChangeGlRam(_size); \
127 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
128 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
129 FIXME("Out of memory!\n"); \
130 HeapFree(GetProcessHeap(), 0, object); \
132 return WINED3DERR_OUTOFVIDEOMEMORY; \
134 *pp##type = (IWineD3D##type *) object; \
135 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
136 TRACE("(%p) : Created resource %p\n", This, object); \
139 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
140 _basetexture.levels = Levels; \
141 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
142 _basetexture.LOD = 0; \
143 _basetexture.dirty = TRUE; \
146 /**********************************************************
147 * Global variable / Constants follow
148 **********************************************************/
149 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
151 /**********************************************************
152 * Utility functions follow
153 **********************************************************/
154 /* Convert the WINED3DLIGHT properties into equivalent gl lights */
155 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
158 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
161 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
162 glMatrixMode(GL_MODELVIEW);
164 glLoadMatrixf((float *)&This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
167 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
168 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
169 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
170 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
171 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
172 checkGLcall("glLightfv");
175 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
176 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
177 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
178 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
179 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
180 checkGLcall("glLightfv");
183 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
184 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
185 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
186 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
187 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
188 checkGLcall("glLightfv");
190 /* Attenuation - Are these right? guessing... */
191 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
192 checkGLcall("glLightf");
193 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
194 checkGLcall("glLightf");
196 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
197 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
199 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
202 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
203 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
204 checkGLcall("glLightf");
206 switch (lightInfo->OriginalParms.Type) {
207 case WINED3DLIGHT_POINT:
209 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
210 checkGLcall("glLightfv");
211 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
212 checkGLcall("glLightf");
216 case WINED3DLIGHT_SPOT:
218 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
219 checkGLcall("glLightfv");
221 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
222 checkGLcall("glLightfv");
223 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
224 checkGLcall("glLightf");
225 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
226 checkGLcall("glLightf");
230 case WINED3DLIGHT_DIRECTIONAL:
232 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
233 checkGLcall("glLightfv");
234 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
235 checkGLcall("glLightf");
236 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
237 checkGLcall("glLightf");
241 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
244 /* Restore the modelview matrix */
248 /**********************************************************
249 * GLSL helper functions follow
250 **********************************************************/
252 /** Detach the GLSL pixel or vertex shader object from the shader program */
253 static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
255 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
257 if (shaderObj != 0 && programId != 0) {
258 TRACE_(d3d_shader)("Detaching GLSL shader object %u from program %u\n", shaderObj, programId);
259 GL_EXTCALL(glDetachObjectARB(programId, shaderObj));
260 checkGLcall("glDetachObjectARB");
264 /** Delete a GLSL shader program */
265 static void delete_glsl_shader_program(IWineD3DDevice *iface, GLhandleARB obj) {
267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
270 TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", obj);
271 GL_EXTCALL(glDeleteObjectARB(obj));
272 checkGLcall("glDeleteObjectARB");
276 /** Delete the list of linked programs this shader is associated with.
277 * Also at this point, check to see if there are any objects left attached
278 * to each GLSL program. If not, delete the GLSL program object.
279 * This will be run when a device is released. */
280 static void delete_glsl_shader_list(IWineD3DDevice* iface) {
282 struct list *ptr = NULL;
283 struct glsl_shader_prog_link *curLink = NULL;
284 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
288 GLhandleARB objList[2]; /* There should never be more than 2 objects attached
289 (one pixel shader and one vertex shader at most) */
291 ptr = list_head( &This->glsl_shader_progs );
293 /* First, get the current item,
294 * save the link to the next pointer,
295 * detach and delete shader objects,
296 * then de-allocate the list item's memory */
297 curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
298 ptr = list_next( &This->glsl_shader_progs, ptr );
300 /* See if this object is still attached to the program - it may have been detached already */
301 GL_EXTCALL(glGetAttachedObjectsARB(curLink->programId, 2, &numAttached, objList));
302 TRACE_(d3d_shader)("%i GLSL objects are currently attached to program %u\n", numAttached, curLink->programId);
303 for (i = 0; i < numAttached; i++) {
304 detach_glsl_shader(iface, objList[i], curLink->programId);
307 delete_glsl_shader_program(iface, curLink->programId);
309 /* Free the uniform locations */
310 HeapFree(GetProcessHeap(), 0, curLink->vuniformF_locations);
311 HeapFree(GetProcessHeap(), 0, curLink->puniformF_locations);
313 /* Free the memory for this list item */
314 HeapFree(GetProcessHeap(), 0, curLink);
318 /**********************************************************
319 * IUnknown parts follows
320 **********************************************************/
322 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
326 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
327 if (IsEqualGUID(riid, &IID_IUnknown)
328 || IsEqualGUID(riid, &IID_IWineD3DBase)
329 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
330 IUnknown_AddRef(iface);
335 return E_NOINTERFACE;
338 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
340 ULONG refCount = InterlockedIncrement(&This->ref);
342 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
346 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
348 ULONG refCount = InterlockedDecrement(&This->ref);
350 TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
354 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
357 HeapFree(GetProcessHeap(), 0, This->render_targets);
359 HeapFree(GetProcessHeap(), 0, This->draw_buffers);
361 /* TODO: Clean up all the surfaces and textures! */
362 /* NOTE: You must release the parent if the object was created via a callback
363 ** ***************************/
365 /* Delete any GLSL shader programs that may exist */
366 if (This->vs_selected_mode == SHADER_GLSL ||
367 This->ps_selected_mode == SHADER_GLSL)
368 delete_glsl_shader_list(iface);
370 /* Release the update stateblock */
371 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
372 if(This->updateStateBlock != This->stateBlock)
373 FIXME("(%p) Something's still holding the Update stateblock\n",This);
375 This->updateStateBlock = NULL;
376 { /* because were not doing proper internal refcounts releasing the primary state block
377 causes recursion with the extra checks in ResourceReleased, to avoid this we have
378 to set this->stateBlock = NULL; first */
379 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
380 This->stateBlock = NULL;
382 /* Release the stateblock */
383 if(IWineD3DStateBlock_Release(stateBlock) > 0){
384 FIXME("(%p) Something's still holding the Update stateblock\n",This);
388 if (This->resources != NULL ) {
389 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
390 dumpResources(This->resources);
393 if(This->contexts) ERR("Context array not freed!\n");
395 IWineD3D_Release(This->wineD3D);
396 This->wineD3D = NULL;
397 HeapFree(GetProcessHeap(), 0, This);
398 TRACE("Freed device %p\n", This);
404 /**********************************************************
405 * IWineD3DDevice implementation follows
406 **********************************************************/
407 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
409 *pParent = This->parent;
410 IUnknown_AddRef(This->parent);
414 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
415 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
416 GLenum error, glUsage;
417 DWORD vboUsage = object->resource.usage;
418 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
419 WARN("Creating a vbo failed once, not trying again\n");
423 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
426 /* Make sure that the gl error is cleared. Do not use checkGLcall
427 * here because checkGLcall just prints a fixme and continues. However,
428 * if an error during VBO creation occurs we can fall back to non-vbo operation
429 * with full functionality(but performance loss)
431 while(glGetError() != GL_NO_ERROR);
433 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
434 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
435 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
436 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
437 * to check if the rhw and color values are in the correct format.
440 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
441 error = glGetError();
442 if(object->vbo == 0 || error != GL_NO_ERROR) {
443 WARN("Failed to create a VBO with error %d\n", error);
447 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
448 error = glGetError();
449 if(error != GL_NO_ERROR) {
450 WARN("Failed to bind the VBO, error %d\n", error);
454 /* Don't use static, because dx apps tend to update the buffer
455 * quite often even if they specify 0 usage
457 switch(vboUsage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC) ) {
458 case D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC:
459 TRACE("Gl usage = GL_STREAM_DRAW\n");
460 glUsage = GL_STREAM_DRAW_ARB;
462 case D3DUSAGE_WRITEONLY:
463 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
464 glUsage = GL_DYNAMIC_DRAW_ARB;
466 case D3DUSAGE_DYNAMIC:
467 TRACE("Gl usage = GL_STREAM_COPY\n");
468 glUsage = GL_STREAM_COPY_ARB;
471 TRACE("Gl usage = GL_DYNAMIC_COPY\n");
472 glUsage = GL_DYNAMIC_COPY_ARB;
476 /* Reserve memory for the buffer. The amount of data won't change
477 * so we are safe with calling glBufferData once with a NULL ptr and
478 * calling glBufferSubData on updates
480 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
481 error = glGetError();
482 if(error != GL_NO_ERROR) {
483 WARN("glBufferDataARB failed with error %d\n", error);
491 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
492 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
493 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
495 object->Flags |= VBFLAG_VBOCREATEFAIL;
500 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
501 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
503 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
504 IWineD3DVertexBufferImpl *object;
505 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
506 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
508 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
510 TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
511 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
513 if(Size == 0) return WINED3DERR_INVALIDCALL;
515 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
516 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
520 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
521 * drawStridedFast (half-life 2).
523 * Basically converting the vertices in the buffer is quite expensive, and observations
524 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
525 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
527 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
528 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
529 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
530 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
532 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
533 * more. In this call we can convert dx7 buffers too.
535 conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
536 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
537 (dxVersion > 7 || !conv) ) {
540 /* DX7 buffers can be locked directly into the VBO (no conversion, see above */
541 if(dxVersion == 7 && object->vbo) {
542 HeapFree(GetProcessHeap(), 0, object->resource.allocatedMemory);
543 object->resource.allocatedMemory = NULL;
550 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
551 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
552 HANDLE *sharedHandle, IUnknown *parent) {
553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
554 IWineD3DIndexBufferImpl *object;
555 TRACE("(%p) Creating index buffer\n", This);
557 /* Allocate the storage for the device */
558 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
561 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
562 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
565 TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
566 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
567 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
572 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
575 IWineD3DStateBlockImpl *object;
579 D3DCREATEOBJECTINSTANCE(object, StateBlock)
580 object->blockType = Type;
582 /* Special case - Used during initialization to produce a placeholder stateblock
583 so other functions called can update a state block */
584 if (Type == WINED3DSBT_INIT) {
585 /* Don't bother increasing the reference count otherwise a device will never
586 be freed due to circular dependencies */
590 temp_result = allocate_shader_constants(object);
591 if (WINED3D_OK != temp_result)
594 /* Otherwise, might as well set the whole state block to the appropriate values */
595 if (This->stateBlock != NULL)
596 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
598 memset(object->streamFreq, 1, sizeof(object->streamFreq));
600 /* Reset the ref and type after kludging it */
601 object->wineD3DDevice = This;
603 object->blockType = Type;
605 TRACE("Updating changed flags appropriate for type %d\n", Type);
607 if (Type == WINED3DSBT_ALL) {
609 TRACE("ALL => Pretend everything has changed\n");
610 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
612 } else if (Type == WINED3DSBT_PIXELSTATE) {
614 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
615 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
617 object->changed.pixelShader = TRUE;
619 /* Pixel Shader Constants */
620 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
621 object->changed.pixelShaderConstantsF[i] = TRUE;
622 for (i = 0; i < MAX_CONST_B; ++i)
623 object->changed.pixelShaderConstantsB[i] = TRUE;
624 for (i = 0; i < MAX_CONST_I; ++i)
625 object->changed.pixelShaderConstantsI[i] = TRUE;
627 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
628 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
630 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
631 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
632 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
635 for (j = 0 ; j < 16; j++) {
636 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
638 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
642 } else if (Type == WINED3DSBT_VERTEXSTATE) {
644 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
645 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
647 object->changed.vertexShader = TRUE;
649 /* Vertex Shader Constants */
650 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
651 object->changed.vertexShaderConstantsF[i] = TRUE;
652 for (i = 0; i < MAX_CONST_B; ++i)
653 object->changed.vertexShaderConstantsB[i] = TRUE;
654 for (i = 0; i < MAX_CONST_I; ++i)
655 object->changed.vertexShaderConstantsI[i] = TRUE;
657 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
658 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
660 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
661 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
662 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
665 for (j = 0 ; j < 16; j++){
666 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
667 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
671 /* Duplicate light chain */
673 PLIGHTINFOEL *src = NULL;
674 PLIGHTINFOEL *dst = NULL;
675 PLIGHTINFOEL *newEl = NULL;
676 src = This->stateBlock->lights;
677 object->lights = NULL;
681 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
682 if (newEl == NULL) return WINED3DERR_OUTOFVIDEOMEMORY;
683 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
685 newEl->changed = TRUE;
686 newEl->enabledChanged = TRUE;
688 object->lights = newEl;
699 FIXME("Unrecognized state block type %d\n", Type);
702 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
707 /* ************************************
709 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
712 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
714 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.
716 ******************************** */
718 static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
719 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
720 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
721 unsigned int pow2Width, pow2Height;
722 unsigned int Size = 1;
723 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
724 TRACE("(%p) Create surface\n",This);
726 /** FIXME: Check ranges on the inputs are valid
729 * [in] Quality level. The valid range is between zero and one less than the level
730 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
731 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
732 * values of paired render targets, depth stencil surfaces, and the MultiSample type
734 *******************************/
739 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
741 * If this flag is set, the contents of the depth stencil buffer will be
742 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
743 * with a different depth surface.
745 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
746 ***************************/
748 if(MultisampleQuality < 0) {
749 FIXME("Invalid multisample level %d\n", MultisampleQuality);
750 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
753 if(MultisampleQuality > 0) {
754 FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
755 MultisampleQuality=0;
758 /** FIXME: Check that the format is supported
760 *******************************/
762 /* Non-power2 support */
763 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
767 /* Find the nearest pow2 match */
768 pow2Width = pow2Height = 1;
769 while (pow2Width < Width) pow2Width <<= 1;
770 while (pow2Height < Height) pow2Height <<= 1;
773 if (pow2Width > Width || pow2Height > Height) {
774 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
775 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
776 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
777 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
778 This, Width, Height);
779 return WINED3DERR_NOTAVAILABLE;
783 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
784 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
786 *********************************/
787 if (WINED3DFMT_UNKNOWN == Format) {
789 } else if (Format == WINED3DFMT_DXT1) {
790 /* DXT1 is half byte per pixel */
791 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
793 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
794 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
795 Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
797 /* The pitch is a multiple of 4 bytes */
798 Size = ((pow2Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
802 /** Create and initialise the surface resource **/
803 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
804 /* "Standalone" surface */
805 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
807 object->currentDesc.Width = Width;
808 object->currentDesc.Height = Height;
809 object->currentDesc.MultiSampleType = MultiSample;
810 object->currentDesc.MultiSampleQuality = MultisampleQuality;
812 /* Setup some glformat defaults */
813 object->glDescription.glFormat = tableEntry->glFormat;
814 object->glDescription.glFormatInternal = tableEntry->glInternal;
815 object->glDescription.glType = tableEntry->glType;
817 object->glDescription.textureName = 0;
818 object->glDescription.level = Level;
819 object->glDescription.target = GL_TEXTURE_2D;
822 object->pow2Width = pow2Width;
823 object->pow2Height = pow2Height;
826 object->Flags = 0; /* We start without flags set */
827 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
828 object->Flags |= Discard ? SFLAG_DISCARD : 0;
829 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
830 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
833 if (WINED3DFMT_UNKNOWN != Format) {
834 object->bytesPerPixel = tableEntry->bpp;
835 object->pow2Size = ((pow2Width * object->bytesPerPixel) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
836 object->pow2Size *= pow2Height;
838 object->bytesPerPixel = 0;
839 object->pow2Size = 0;
842 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
844 TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
846 /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
847 * this function is too deep to need to care about things like this.
848 * Levels need to be checked too, and possibly Type since they all affect what can be done.
849 * ****************************************/
851 case WINED3DPOOL_SCRATCH:
853 FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
854 "which are mutually exclusive, setting lockable to TRUE\n");
857 case WINED3DPOOL_SYSTEMMEM:
858 if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
859 "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
860 case WINED3DPOOL_MANAGED:
861 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a "
862 "Usage of DYNAMIC which are mutually exclusive, not doing "
863 "anything just telling you.\n");
865 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
866 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
867 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
868 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
871 FIXME("(%p) Unknown pool %d\n", This, Pool);
875 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
876 FIXME("Trying to create a render target that isn't in the default pool\n");
879 /* mark the texture as dirty so that it gets loaded first time around*/
880 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
881 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
882 This, Width, Height, Format, debug_d3dformat(Format),
883 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
885 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
886 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
887 This->ddraw_primary = (IWineD3DSurface *) object;
889 /* Look at the implementation and set the correct Vtable */
892 /* Nothing to do, it's set already */
896 object->lpVtbl = &IWineGDISurface_Vtbl;
900 /* To be sure to catch this */
901 ERR("Unknown requested surface implementation %d!\n", Impl);
902 IWineD3DSurface_Release((IWineD3DSurface *) object);
903 return WINED3DERR_INVALIDCALL;
906 /* Call the private setup routine */
907 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
911 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
912 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
913 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
914 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
916 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
917 IWineD3DTextureImpl *object;
922 unsigned int pow2Width;
923 unsigned int pow2Height;
926 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
927 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
928 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
930 /* TODO: It should only be possible to create textures for formats
931 that are reported as supported */
932 if (WINED3DFMT_UNKNOWN >= Format) {
933 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
934 return WINED3DERR_INVALIDCALL;
937 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
938 D3DINITIALIZEBASETEXTURE(object->baseTexture);
939 object->width = Width;
940 object->height = Height;
942 /** Non-power2 support **/
943 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
947 /* Find the nearest pow2 match */
948 pow2Width = pow2Height = 1;
949 while (pow2Width < Width) pow2Width <<= 1;
950 while (pow2Height < Height) pow2Height <<= 1;
953 /** FIXME: add support for real non-power-two if it's provided by the video card **/
954 /* Precalculated scaling for 'faked' non power of two texture coords */
955 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
956 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
957 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
959 /* Calculate levels for mip mapping */
961 TRACE("calculating levels %d\n", object->baseTexture.levels);
962 object->baseTexture.levels++;
965 while (tmpW > 1 || tmpH > 1) {
966 tmpW = max(1, tmpW >> 1);
967 tmpH = max(1, tmpH >> 1);
968 object->baseTexture.levels++;
970 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
973 /* Generate all the surfaces */
976 for (i = 0; i < object->baseTexture.levels; i++)
978 /* use the callback to create the texture surface */
979 hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
980 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
981 FIXME("Failed to create surface %p\n", object);
983 object->surfaces[i] = NULL;
984 IWineD3DTexture_Release((IWineD3DTexture *)object);
990 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
991 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
992 /* calculate the next mipmap level */
993 tmpW = max(1, tmpW >> 1);
994 tmpH = max(1, tmpH >> 1);
997 TRACE("(%p) : Created texture %p\n", This, object);
1001 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
1002 UINT Width, UINT Height, UINT Depth,
1003 UINT Levels, DWORD Usage,
1004 WINED3DFORMAT Format, WINED3DPOOL Pool,
1005 IWineD3DVolumeTexture **ppVolumeTexture,
1006 HANDLE *pSharedHandle, IUnknown *parent,
1007 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
1009 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1010 IWineD3DVolumeTextureImpl *object;
1016 /* TODO: It should only be possible to create textures for formats
1017 that are reported as supported */
1018 if (WINED3DFMT_UNKNOWN >= Format) {
1019 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1020 return WINED3DERR_INVALIDCALL;
1023 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
1024 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1026 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1027 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1029 object->width = Width;
1030 object->height = Height;
1031 object->depth = Depth;
1033 /* Calculate levels for mip mapping */
1035 object->baseTexture.levels++;
1039 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
1040 tmpW = max(1, tmpW >> 1);
1041 tmpH = max(1, tmpH >> 1);
1042 tmpD = max(1, tmpD >> 1);
1043 object->baseTexture.levels++;
1045 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1048 /* Generate all the surfaces */
1053 for (i = 0; i < object->baseTexture.levels; i++)
1055 /* Create the volume */
1056 D3DCB_CreateVolume(This->parent, parent, Width, Height, Depth, Format, Pool, Usage,
1057 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
1059 /* Set its container to this object */
1060 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
1062 /* calcualte the next mipmap level */
1063 tmpW = max(1, tmpW >> 1);
1064 tmpH = max(1, tmpH >> 1);
1065 tmpD = max(1, tmpD >> 1);
1068 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
1069 TRACE("(%p) : Created volume texture %p\n", This, object);
1073 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
1074 UINT Width, UINT Height, UINT Depth,
1076 WINED3DFORMAT Format, WINED3DPOOL Pool,
1077 IWineD3DVolume** ppVolume,
1078 HANDLE* pSharedHandle, IUnknown *parent) {
1080 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1081 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1082 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
1084 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
1086 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
1087 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
1089 object->currentDesc.Width = Width;
1090 object->currentDesc.Height = Height;
1091 object->currentDesc.Depth = Depth;
1092 object->bytesPerPixel = formatDesc->bpp;
1094 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
1095 object->lockable = TRUE;
1096 object->locked = FALSE;
1097 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
1098 object->dirty = TRUE;
1100 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
1103 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
1104 UINT Levels, DWORD Usage,
1105 WINED3DFORMAT Format, WINED3DPOOL Pool,
1106 IWineD3DCubeTexture **ppCubeTexture,
1107 HANDLE *pSharedHandle, IUnknown *parent,
1108 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
1110 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1111 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1115 unsigned int pow2EdgeLength = EdgeLength;
1117 /* TODO: It should only be possible to create textures for formats
1118 that are reported as supported */
1119 if (WINED3DFMT_UNKNOWN >= Format) {
1120 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1121 return WINED3DERR_INVALIDCALL;
1124 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1125 D3DINITIALIZEBASETEXTURE(object->baseTexture);
1127 TRACE("(%p) Create Cube Texture\n", This);
1129 /** Non-power2 support **/
1131 /* Find the nearest pow2 match */
1133 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1135 object->edgeLength = EdgeLength;
1136 /* TODO: support for native non-power 2 */
1137 /* Precalculated scaling for 'faked' non power of two texture coords */
1138 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1140 /* Calculate levels for mip mapping */
1142 object->baseTexture.levels++;
1145 tmpW = max(1, tmpW >> 1);
1146 object->baseTexture.levels++;
1148 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1151 /* Generate all the surfaces */
1153 for (i = 0; i < object->baseTexture.levels; i++) {
1155 /* Create the 6 faces */
1156 for (j = 0; j < 6; j++) {
1158 hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1159 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1161 if(hr!= WINED3D_OK) {
1165 for (l = 0; l < j; l++) {
1166 IWineD3DSurface_Release(object->surfaces[j][i]);
1168 for (k = 0; k < i; k++) {
1169 for (l = 0; l < 6; l++) {
1170 IWineD3DSurface_Release(object->surfaces[l][j]);
1174 FIXME("(%p) Failed to create surface\n",object);
1175 HeapFree(GetProcessHeap(),0,object);
1176 *ppCubeTexture = NULL;
1179 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1180 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1182 tmpW = max(1, tmpW >> 1);
1185 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1186 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1190 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1191 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1192 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1194 if (NULL == ppQuery) {
1195 /* Just a check to see if we support this type of query */
1196 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1198 case WINED3DQUERYTYPE_OCCLUSION:
1199 TRACE("(%p) occlusion query\n", This);
1200 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1203 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1205 case WINED3DQUERYTYPE_VCACHE:
1206 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1207 case WINED3DQUERYTYPE_VERTEXSTATS:
1208 case WINED3DQUERYTYPE_EVENT:
1209 case WINED3DQUERYTYPE_TIMESTAMP:
1210 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1211 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1212 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1213 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1214 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1215 case WINED3DQUERYTYPE_PIXELTIMINGS:
1216 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1217 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1219 FIXME("(%p) Unhandled query type %d\n", This, Type);
1224 D3DCREATEOBJECTINSTANCE(object, Query)
1225 object->type = Type;
1226 /* allocated the 'extended' data based on the type of query requested */
1228 case WINED3DQUERYTYPE_OCCLUSION:
1229 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1230 TRACE("(%p) Allocating data for an occlusion query\n", This);
1231 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1232 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1235 case WINED3DQUERYTYPE_VCACHE:
1236 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1237 case WINED3DQUERYTYPE_VERTEXSTATS:
1238 case WINED3DQUERYTYPE_EVENT:
1239 case WINED3DQUERYTYPE_TIMESTAMP:
1240 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1241 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1242 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1243 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1244 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1245 case WINED3DQUERYTYPE_PIXELTIMINGS:
1246 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1247 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1249 object->extendedData = 0;
1250 FIXME("(%p) Unhandled query type %d\n",This , Type);
1252 TRACE("(%p) : Created Query %p\n", This, object);
1256 /*****************************************************************************
1257 * IWineD3DDeviceImpl_SetupFullscreenWindow
1259 * Helper function that modifies a HWND's Style and ExStyle for proper
1263 * iface: Pointer to the IWineD3DDevice interface
1264 * window: Window to setup
1266 *****************************************************************************/
1267 static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window) {
1268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1270 LONG style, exStyle;
1271 /* Don't do anything if an original style is stored.
1272 * That shouldn't happen
1274 TRACE("(%p): Setting up window %p for exclusive mode\n", This, window);
1275 if (This->style && This->exStyle) {
1276 ERR("(%p): Want to change the window parameters of HWND %p, but "
1277 "another style is stored for restoration afterwards\n", This, window);
1280 /* Get the parameters and save them */
1281 style = GetWindowLongW(window, GWL_STYLE);
1282 exStyle = GetWindowLongW(window, GWL_EXSTYLE);
1283 This->style = style;
1284 This->exStyle = exStyle;
1286 /* Filter out window decorations */
1287 style &= ~WS_CAPTION;
1288 style &= ~WS_THICKFRAME;
1289 exStyle &= ~WS_EX_WINDOWEDGE;
1290 exStyle &= ~WS_EX_CLIENTEDGE;
1292 /* Make sure the window is managed, otherwise we won't get keyboard input */
1293 style |= WS_POPUP | WS_SYSMENU;
1295 TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1296 This->style, This->exStyle, style, exStyle);
1298 SetWindowLongW(window, GWL_STYLE, style);
1299 SetWindowLongW(window, GWL_EXSTYLE, exStyle);
1301 /* Inform the window about the update. */
1302 SetWindowPos(window, HWND_TOP, 0, 0,
1303 This->ddraw_width, This->ddraw_height, SWP_FRAMECHANGED);
1304 ShowWindow(window, TRUE);
1307 /*****************************************************************************
1308 * IWineD3DDeviceImpl_RestoreWindow
1310 * Helper function that restores a windows' properties when taking it out
1311 * of fullscreen mode
1314 * iface: Pointer to the IWineD3DDevice interface
1315 * window: Window to setup
1317 *****************************************************************************/
1318 static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) {
1319 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1321 /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1322 * switch, do nothing
1324 if (!This->style && !This->exStyle) return;
1326 TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1327 This, window, This->style, This->exStyle);
1329 SetWindowLongW(window, GWL_STYLE, This->style);
1330 SetWindowLongW(window, GWL_EXSTYLE, This->exStyle);
1332 /* Delete the old values */
1336 /* Inform the window about the update */
1337 SetWindowPos(window, 0 /* InsertAfter, ignored */,
1338 0, 0, 0, 0, /* Pos, Size, ignored */
1339 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
1342 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1343 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1345 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1346 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1350 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1351 HRESULT hr = WINED3D_OK;
1352 IUnknown *bufferParent;
1355 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1357 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1358 * does a device hold a reference to a swap chain giving them a lifetime of the device
1359 * or does the swap chain notify the device of its destruction.
1360 *******************************/
1362 /* Check the params */
1363 if(*pPresentationParameters->BackBufferCount > D3DPRESENT_BACK_BUFFER_MAX) {
1364 ERR("App requested %d back buffers, this is not supported for now\n", *pPresentationParameters->BackBufferCount);
1365 return WINED3DERR_INVALIDCALL;
1366 } else if (*pPresentationParameters->BackBufferCount > 1) {
1367 FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
1370 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1372 /*********************
1373 * Lookup the window Handle and the relating X window handle
1374 ********************/
1376 /* Setup hwnd we are using, plus which display this equates to */
1377 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1378 if (!object->win_handle) {
1379 object->win_handle = This->createParms.hFocusWindow;
1382 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1383 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1384 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1385 return WINED3DERR_NOTAVAILABLE;
1387 hDc = GetDC(object->win_handle);
1388 display = get_display(hDc);
1389 ReleaseDC(object->win_handle, hDc);
1390 TRACE("Using a display of %p %p\n", display, hDc);
1392 if (NULL == display || NULL == hDc) {
1393 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1394 return WINED3DERR_NOTAVAILABLE;
1397 if (object->win == 0) {
1398 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1399 return WINED3DERR_NOTAVAILABLE;
1402 object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1403 object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1405 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1406 * then the corresponding dimension of the client area of the hDeviceWindow
1407 * (or the focus window, if hDeviceWindow is NULL) is taken.
1408 **********************/
1410 if (*(pPresentationParameters->Windowed) &&
1411 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1412 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1415 GetClientRect(object->win_handle, &Rect);
1417 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1418 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1419 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1421 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1422 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1423 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1427 /* Put the correct figures in the presentation parameters */
1428 TRACE("Copying across presentation parameters\n");
1429 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1430 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1431 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1432 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1433 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1434 object->presentParms.MultiSampleQuality = NULL == pPresentationParameters->MultiSampleQuality ? 0 : *(pPresentationParameters->MultiSampleQuality);
1435 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1436 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1437 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1438 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1439 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1440 object->presentParms.Flags = *(pPresentationParameters->Flags);
1441 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1442 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1444 TRACE("calling rendertarget CB\n");
1445 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1447 object->presentParms.BackBufferWidth,
1448 object->presentParms.BackBufferHeight,
1449 object->presentParms.BackBufferFormat,
1450 object->presentParms.MultiSampleType,
1451 object->presentParms.MultiSampleQuality,
1452 TRUE /* Lockable */,
1453 &object->frontBuffer,
1454 NULL /* pShared (always null)*/);
1455 if (object->frontBuffer != NULL) {
1456 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1458 ERR("Failed to create the front buffer\n");
1463 * Create an opengl context for the display visual
1464 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1465 * use different properties after that point in time. FIXME: How to handle when requested format
1466 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1467 * it chooses is identical to the one already being used!
1468 **********************************/
1470 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1472 object->context = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, display, object->win);
1475 if (!object->context) {
1476 ERR("Failed to create a new context\n");
1477 hr = WINED3DERR_NOTAVAILABLE;
1480 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld)\n",
1481 object->win_handle, object->context->glCtx, object->win);
1484 /*********************
1485 * Windowed / Fullscreen
1486 *******************/
1489 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1490 * so we should really check to see if there is a fullscreen swapchain already
1491 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1492 **************************************/
1494 if (!*(pPresentationParameters->Windowed)) {
1501 /* Get info on the current display setup */
1503 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1506 /* Change the display settings */
1507 memset(&devmode, 0, sizeof(DEVMODEW));
1508 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1509 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1510 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1511 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1512 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1513 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1515 /* For GetDisplayMode */
1516 This->ddraw_width = devmode.dmPelsWidth;
1517 This->ddraw_height = devmode.dmPelsHeight;
1518 This->ddraw_format = *(pPresentationParameters->BackBufferFormat);
1520 IWineD3DDeviceImpl_SetupFullscreenWindow(iface, object->win_handle);
1522 /* And finally clip mouse to our screen */
1523 SetRect(&clip_rc, 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight);
1524 ClipCursor(&clip_rc);
1527 /*********************
1528 * Create the back, front and stencil buffers
1529 *******************/
1530 if(object->presentParms.BackBufferCount > 0) {
1533 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1534 if(!object->backBuffer) {
1535 ERR("Out of memory\n");
1540 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1541 TRACE("calling rendertarget CB\n");
1542 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1544 object->presentParms.BackBufferWidth,
1545 object->presentParms.BackBufferHeight,
1546 object->presentParms.BackBufferFormat,
1547 object->presentParms.MultiSampleType,
1548 object->presentParms.MultiSampleQuality,
1549 TRUE /* Lockable */,
1550 &object->backBuffer[i],
1551 NULL /* pShared (always null)*/);
1552 if(hr == WINED3D_OK && object->backBuffer[i]) {
1553 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1555 ERR("Cannot create new back buffer\n");
1559 glDrawBuffer(GL_BACK);
1560 checkGLcall("glDrawBuffer(GL_BACK)");
1564 object->backBuffer = NULL;
1566 /* Single buffering - draw to front buffer */
1568 glDrawBuffer(GL_FRONT);
1569 checkGLcall("glDrawBuffer(GL_FRONT)");
1573 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1574 if (*(pPresentationParameters->EnableAutoDepthStencil) && hr == WINED3D_OK) {
1575 TRACE("Creating depth stencil buffer\n");
1576 if (This->depthStencilBuffer == NULL ) {
1577 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1579 object->presentParms.BackBufferWidth,
1580 object->presentParms.BackBufferHeight,
1581 object->presentParms.AutoDepthStencilFormat,
1582 object->presentParms.MultiSampleType,
1583 object->presentParms.MultiSampleQuality,
1584 FALSE /* FIXME: Discard */,
1585 &This->depthStencilBuffer,
1586 NULL /* pShared (always null)*/ );
1587 if (This->depthStencilBuffer != NULL)
1588 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1591 /** TODO: A check on width, height and multisample types
1592 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1593 ****************************/
1594 object->wantsDepthStencilBuffer = TRUE;
1596 object->wantsDepthStencilBuffer = FALSE;
1599 TRACE("Created swapchain %p\n", object);
1600 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1604 if (object->backBuffer) {
1606 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1607 if(object->backBuffer[i]) {
1608 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1609 IUnknown_Release(bufferParent); /* once for the get parent */
1610 if (IUnknown_Release(bufferParent) > 0) {
1611 FIXME("(%p) Something's still holding the back buffer\n",This);
1615 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1616 object->backBuffer = NULL;
1618 if(object->context) {
1619 DestroyContext(This, object->context);
1621 if(object->frontBuffer) {
1622 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1623 IUnknown_Release(bufferParent); /* once for the get parent */
1624 if (IUnknown_Release(bufferParent) > 0) {
1625 FIXME("(%p) Something's still holding the front buffer\n",This);
1628 if(object) HeapFree(GetProcessHeap(), 0, object);
1632 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1633 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1634 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1635 TRACE("(%p)\n", This);
1637 return This->NumberOfSwapChains;
1640 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1642 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1644 if(iSwapChain < This->NumberOfSwapChains) {
1645 *pSwapChain = This->swapchains[iSwapChain];
1646 IWineD3DSwapChain_AddRef(*pSwapChain);
1647 TRACE("(%p) returning %p\n", This, *pSwapChain);
1650 TRACE("Swapchain out of range\n");
1652 return WINED3DERR_INVALIDCALL;
1657 * Vertex Declaration
1659 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1660 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1661 IWineD3DVertexDeclarationImpl *object = NULL;
1662 HRESULT hr = WINED3D_OK;
1663 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1664 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1667 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1672 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1673 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, CONST DWORD *pDeclaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1674 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1675 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1676 HRESULT hr = WINED3D_OK;
1677 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1678 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1680 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1682 /* If a vertex declaration has been passed, save it to the vertex shader, this affects d3d8 only. */
1683 /* Further it needs to be set before calling SetFunction as SetFunction needs the declaration. */
1684 if (pDeclaration != NULL) {
1685 IWineD3DVertexDeclaration *vertexDeclaration;
1686 hr = IWineD3DDevice_CreateVertexDeclaration(iface, pDeclaration, &vertexDeclaration ,NULL);
1687 if (WINED3D_OK == hr) {
1688 TRACE("(%p) : Setting vertex declaration to %p\n", This, vertexDeclaration);
1689 object->vertexDeclaration = vertexDeclaration;
1691 FIXME("(%p) : Failed to set the declaration, returning WINED3DERR_INVALIDCALL\n", iface);
1692 IWineD3DVertexShader_Release(*ppVertexShader);
1693 return WINED3DERR_INVALIDCALL;
1697 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1699 if (WINED3D_OK != hr) {
1700 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1701 IWineD3DVertexShader_Release(*ppVertexShader);
1702 return WINED3DERR_INVALIDCALL;
1705 #if 0 /* TODO: In D3D* SVP is atatched to the shader, in D3D9 it's attached to the device and isn't stored in the stateblock. */
1706 if(Usage == WINED3DUSAGE_SOFTWAREVERTEXPROCESSING) {
1717 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1719 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1720 HRESULT hr = WINED3D_OK;
1722 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
1723 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1724 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1725 if (WINED3D_OK == hr) {
1726 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1728 WARN("(%p) : Failed to create pixel shader\n", This);
1734 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1736 IWineD3DPaletteImpl *object;
1738 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1740 /* Create the new object */
1741 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1743 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1744 return E_OUTOFMEMORY;
1747 object->lpVtbl = &IWineD3DPalette_Vtbl;
1749 object->Flags = Flags;
1750 object->parent = Parent;
1751 object->wineD3DDevice = This;
1752 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1754 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1757 HeapFree( GetProcessHeap(), 0, object);
1758 return E_OUTOFMEMORY;
1761 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1763 IWineD3DPalette_Release((IWineD3DPalette *) object);
1767 *Palette = (IWineD3DPalette *) object;
1772 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1774 IWineD3DSwapChainImpl *swapchain;
1777 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1778 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1780 /* TODO: Test if OpenGL is compiled in and loaded */
1782 /* Initialize the texture unit mapping to a 1:1 mapping */
1783 for(state = 0; state < MAX_SAMPLERS; state++) {
1784 This->texUnitMap[state] = state;
1786 This->oneToOneTexUnitMap = TRUE;
1788 /* Setup the implicit swapchain */
1789 TRACE("Creating implicit swapchain\n");
1790 if (D3D_OK != D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) || swapchain == NULL) {
1791 WARN("Failed to create implicit swapchain\n");
1792 return WINED3DERR_INVALIDCALL;
1795 This->NumberOfSwapChains = 1;
1796 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1797 if(!This->swapchains) {
1798 ERR("Out of memory!\n");
1799 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1800 return E_OUTOFMEMORY;
1802 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1804 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
1805 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1806 This->render_targets[0] = swapchain->backBuffer[0];
1807 This->lastActiveRenderTarget = swapchain->backBuffer[0];
1810 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1811 This->render_targets[0] = swapchain->frontBuffer;
1812 This->lastActiveRenderTarget = swapchain->frontBuffer;
1814 IWineD3DSurface_AddRef(This->render_targets[0]);
1815 This->activeContext = swapchain->context;
1817 /* Depth Stencil support */
1818 This->stencilBufferTarget = This->depthStencilBuffer;
1819 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1820 set_depth_stencil_fbo(iface, This->depthStencilBuffer);
1822 if (NULL != This->stencilBufferTarget) {
1823 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1826 /* Set up some starting GL setup */
1829 * Initialize openGL extension related variables
1830 * with Default values
1833 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->context->display);
1834 /* Setup all the devices defaults */
1835 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1837 IWineD3DImpl_CheckGraphicsMemory();
1840 /* Initialize our list of GLSL programs */
1841 list_init(&This->glsl_shader_progs);
1843 { /* Set a default viewport */
1847 vp.Width = *(pPresentationParameters->BackBufferWidth);
1848 vp.Height = *(pPresentationParameters->BackBufferHeight);
1851 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1854 /* Initialize the current view state */
1855 This->view_ident = 1;
1856 This->contexts[0]->last_was_rhw = 0;
1857 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1858 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1859 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1862 /* Clear the screen */
1863 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL, WINED3DCLEAR_STENCIL|WINED3DCLEAR_ZBUFFER|WINED3DCLEAR_TARGET, 0x00, 1.0, 0);
1865 This->d3d_initialized = TRUE;
1869 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
1870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1873 TRACE("(%p)\n", This);
1875 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1877 /* Delete the pbuffer context if there is any */
1878 if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
1880 /* Delete the mouse cursor texture */
1881 if(This->cursorTexture) {
1883 glDeleteTextures(1, &This->cursorTexture);
1885 This->cursorTexture = 0;
1888 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
1889 IWineD3DDevice_SetTexture(iface, sampler, NULL);
1892 /* Release the buffers (with sanity checks)*/
1893 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1894 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1895 if(This->depthStencilBuffer != This->stencilBufferTarget)
1896 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1898 This->stencilBufferTarget = NULL;
1900 TRACE("Releasing the render target at %p\n", This->render_targets[0]);
1901 if(IWineD3DSurface_Release(This->render_targets[0]) >0){
1902 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1904 TRACE("Setting rendertarget to NULL\n");
1905 This->render_targets[0] = NULL;
1907 if (This->depthStencilBuffer) {
1908 if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
1909 FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
1911 This->depthStencilBuffer = NULL;
1914 for(i=0; i < This->NumberOfSwapChains; i++) {
1915 TRACE("Releasing the implicit swapchain %d\n", i);
1916 if (D3DCB_DestroySwapChain(This->swapchains[i]) > 0) {
1917 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1921 HeapFree(GetProcessHeap(), 0, This->swapchains);
1922 This->swapchains = NULL;
1923 This->NumberOfSwapChains = 0;
1925 This->d3d_initialized = FALSE;
1929 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
1930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1931 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
1933 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
1934 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
1935 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
1938 This->ddraw_fullscreen = fullscreen;
1941 static HRESULT WINAPI IWineD3DDeviceImpl_EnumDisplayModes(IWineD3DDevice *iface, DWORD Flags, UINT Width, UINT Height, WINED3DFORMAT pixelformat, LPVOID context, D3DCB_ENUMDISPLAYMODESCALLBACK callback) {
1942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1946 const PixelFormatDesc *formatDesc = getFormatDescEntry(pixelformat);
1948 TRACE("(%p)->(%x,%d,%d,%d,%p,%p)\n", This, Flags, Width, Height, pixelformat, context, callback);
1950 for (i = 0; EnumDisplaySettingsExW(NULL, i, &DevModeW, 0); i++) {
1951 /* Ignore some modes if a description was passed */
1952 if ( (Width > 0) && (Width != DevModeW.dmPelsWidth)) continue;
1953 if ( (Height > 0) && (Height != DevModeW.dmPelsHeight)) continue;
1954 if ( (pixelformat != WINED3DFMT_UNKNOWN) && ( formatDesc->bpp != DevModeW.dmBitsPerPel) ) continue;
1956 TRACE("Enumerating %dx%d@%s\n", DevModeW.dmPelsWidth, DevModeW.dmPelsHeight, debug_d3dformat(pixelformat_for_depth(DevModeW.dmBitsPerPel)));
1958 if (callback((IUnknown *) This, (UINT) DevModeW.dmPelsWidth, (UINT) DevModeW.dmPelsHeight, pixelformat_for_depth(DevModeW.dmBitsPerPel), 60.0, context) == DDENUMRET_CANCEL)
1965 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1969 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
1972 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1974 /* Resize the screen even without a window:
1975 * The app could have unset it with SetCooperativeLevel, but not called
1976 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1977 * but we don't have any hwnd
1980 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1981 devmode.dmBitsPerPel = formatDesc->bpp * 8;
1982 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1983 devmode.dmPelsWidth = pMode->Width;
1984 devmode.dmPelsHeight = pMode->Height;
1986 devmode.dmDisplayFrequency = pMode->RefreshRate;
1987 if (pMode->RefreshRate != 0) {
1988 devmode.dmFields |= DM_DISPLAYFREQUENCY;
1991 /* Only change the mode if necessary */
1992 if( (This->ddraw_width == pMode->Width) &&
1993 (This->ddraw_height == pMode->Height) &&
1994 (This->ddraw_format == pMode->Format) &&
1995 (pMode->RefreshRate == 0) ) {
1999 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
2000 if (ret != DISP_CHANGE_SUCCESSFUL) {
2001 if(devmode.dmDisplayFrequency != 0) {
2002 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2003 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
2004 devmode.dmDisplayFrequency = 0;
2005 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
2007 if(ret != DISP_CHANGE_SUCCESSFUL) {
2008 return DDERR_INVALIDMODE;
2012 /* Store the new values */
2013 This->ddraw_width = pMode->Width;
2014 This->ddraw_height = pMode->Height;
2015 This->ddraw_format = pMode->Format;
2017 /* Only do this with a window of course */
2018 if(This->ddraw_window)
2019 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
2021 /* And finally clip mouse to our screen */
2022 SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
2023 ClipCursor(&clip_rc);
2028 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
2029 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2030 *ppD3D= This->wineD3D;
2031 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
2032 IWineD3D_AddRef(*ppD3D);
2036 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
2037 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
2038 * into the video ram as possible and seeing how many fit
2039 * you can also get the correct initial value from nvidia and ATI's driver via X
2040 * texture memory is video memory + AGP memory
2041 *******************/
2042 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2043 static BOOL showfixmes = TRUE;
2045 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
2046 (wined3d_settings.emulated_textureram/(1024*1024)),
2047 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2050 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
2051 (wined3d_settings.emulated_textureram/(1024*1024)),
2052 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
2053 /* return simulated texture memory left */
2054 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
2062 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
2063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2065 /* Update the current state block */
2066 This->updateStateBlock->changed.fvf = TRUE;
2067 This->updateStateBlock->set.fvf = TRUE;
2069 if(This->updateStateBlock->fvf == fvf) {
2070 TRACE("Application is setting the old fvf over, nothing to do\n");
2074 This->updateStateBlock->fvf = fvf;
2075 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
2076 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2081 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
2082 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2083 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
2084 *pfvf = This->stateBlock->fvf;
2089 * Get / Set Stream Source
2091 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2093 IWineD3DVertexBuffer *oldSrc;
2095 /**TODO: instance and index data, see
2096 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2098 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/SetStreamSourceFreq.asp
2101 /* D3d9 only, but shouldn't hurt d3d8 */
2104 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2106 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2107 FIXME("stream index data not supported\n");
2109 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2110 FIXME("stream instance data not supported\n");
2114 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2116 if (StreamNumber >= MAX_STREAMS) {
2117 WARN("Stream out of range %d\n", StreamNumber);
2118 return WINED3DERR_INVALIDCALL;
2121 oldSrc = This->stateBlock->streamSource[StreamNumber];
2122 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
2124 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2125 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
2127 if(oldSrc == pStreamData &&
2128 This->updateStateBlock->streamStride[StreamNumber] == Stride &&
2129 This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes &&
2130 This->updateStateBlock->streamFlags[StreamNumber] == streamFlags) {
2131 TRACE("Application is setting the old values over, nothing to do\n");
2135 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
2137 This->updateStateBlock->streamStride[StreamNumber] = Stride;
2138 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
2140 This->updateStateBlock->streamFlags[StreamNumber] = streamFlags;
2142 /* Handle recording of state blocks */
2143 if (This->isRecordingState) {
2144 TRACE("Recording... not performing anything\n");
2148 /* Same stream object: no action */
2149 if (oldSrc == pStreamData)
2152 /* Need to do a getParent and pass the reffs up */
2153 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2154 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2155 so for now, just count internally */
2156 if (pStreamData != NULL) {
2157 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2158 InterlockedIncrement(&vbImpl->bindCount);
2160 if (oldSrc != NULL) {
2161 InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2164 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2169 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2173 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2174 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2177 streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2179 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2180 FIXME("stream index data not supported\n");
2182 if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2183 FIXME("stream instance data not supported\n");
2187 StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2189 if (StreamNumber >= MAX_STREAMS) {
2190 WARN("Stream out of range %d\n", StreamNumber);
2191 return WINED3DERR_INVALIDCALL;
2193 *pStream = This->stateBlock->streamSource[StreamNumber];
2194 *pStride = This->stateBlock->streamStride[StreamNumber];
2196 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2199 if (*pStream != NULL) {
2200 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2205 /*Should be quite easy, just an extension of vertexdata
2207 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2209 The divider is a bit odd though
2211 VertexOffset = StartVertex / Divider * StreamStride +
2212 VertexIndex / Divider * StreamStride + StreamOffset
2215 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2218 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2219 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
2221 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2222 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2223 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2225 if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2226 FIXME("Stream indexing not fully supported\n");
2232 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2233 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2235 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2236 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2238 TRACE("(%p) : returning %d\n", This, *Divider);
2244 * Get / Set & Multiply Transform
2246 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2247 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2249 /* Most of this routine, comments included copied from ddraw tree initially: */
2250 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2252 /* Handle recording of state blocks */
2253 if (This->isRecordingState) {
2254 TRACE("Recording... not performing anything\n");
2255 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2256 This->updateStateBlock->set.transform[d3dts] = TRUE;
2257 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2262 * If the new matrix is the same as the current one,
2263 * we cut off any further processing. this seems to be a reasonable
2264 * optimization because as was noticed, some apps (warcraft3 for example)
2265 * tend towards setting the same matrix repeatedly for some reason.
2267 * From here on we assume that the new matrix is different, wherever it matters.
2269 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2270 TRACE("The app is setting the same matrix over again\n");
2273 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2277 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2278 where ViewMat = Camera space, WorldMat = world space.
2280 In OpenGL, camera and world space is combined into GL_MODELVIEW
2281 matrix. The Projection matrix stay projection matrix.
2284 /* Capture the times we can just ignore the change for now */
2285 if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2286 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2287 /* Handled by the state manager */
2290 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2294 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2296 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2297 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2301 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2302 WINED3DMATRIX *mat = NULL;
2305 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2306 * below means it will be recorded in a state block change, but it
2307 * works regardless where it is recorded.
2308 * If this is found to be wrong, change to StateBlock.
2310 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2311 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2313 if (State < HIGHEST_TRANSFORMSTATE)
2315 mat = &This->updateStateBlock->transforms[State];
2317 FIXME("Unhandled transform state!!\n");
2320 multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2322 /* Apply change via set transform - will reapply to eg. lights this way */
2323 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2329 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2330 you can reference any indexes you want as long as that number max are enabled at any
2331 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2332 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2333 but when recording, just build a chain pretty much of commands to be replayed. */
2335 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2337 PLIGHTINFOEL *object, *temp;
2339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2340 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2342 /* If recording state block, just add to end of lights chain */
2343 if (This->isRecordingState) {
2344 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2345 if (NULL == object) {
2346 return WINED3DERR_OUTOFVIDEOMEMORY;
2348 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2349 object->OriginalIndex = Index;
2350 object->glIndex = -1;
2351 object->changed = TRUE;
2353 /* Add to the END of the chain of lights changes to be replayed */
2354 if (This->updateStateBlock->lights == NULL) {
2355 This->updateStateBlock->lights = object;
2357 temp = This->updateStateBlock->lights;
2358 while (temp->next != NULL) temp=temp->next;
2359 temp->next = object;
2361 TRACE("Recording... not performing anything more\n");
2365 /* Ok, not recording any longer so do real work */
2366 object = This->stateBlock->lights;
2367 while (object != NULL && object->OriginalIndex != Index) object = object->next;
2369 /* If we didn't find it in the list of lights, time to add it */
2370 if (object == NULL) {
2371 PLIGHTINFOEL *insertAt,*prevPos;
2373 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2374 if (NULL == object) {
2375 return WINED3DERR_OUTOFVIDEOMEMORY;
2377 object->OriginalIndex = Index;
2378 object->glIndex = -1;
2380 /* Add it to the front of list with the idea that lights will be changed as needed
2381 BUT after any lights currently assigned GL indexes */
2382 insertAt = This->stateBlock->lights;
2384 while (insertAt != NULL && insertAt->glIndex != -1) {
2386 insertAt = insertAt->next;
2389 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2390 This->stateBlock->lights = object;
2391 } else if (insertAt == NULL) { /* End of list */
2392 prevPos->next = object;
2393 object->prev = prevPos;
2394 } else { /* Middle of chain */
2395 if (prevPos == NULL) {
2396 This->stateBlock->lights = object;
2398 prevPos->next = object;
2400 object->prev = prevPos;
2401 object->next = insertAt;
2402 insertAt->prev = object;
2406 /* Initialize the object */
2407 TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2408 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2409 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2410 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2411 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2412 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2413 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2415 /* Save away the information */
2416 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2418 switch (pLight->Type) {
2419 case WINED3DLIGHT_POINT:
2421 object->lightPosn[0] = pLight->Position.x;
2422 object->lightPosn[1] = pLight->Position.y;
2423 object->lightPosn[2] = pLight->Position.z;
2424 object->lightPosn[3] = 1.0f;
2425 object->cutoff = 180.0f;
2429 case WINED3DLIGHT_DIRECTIONAL:
2431 object->lightPosn[0] = -pLight->Direction.x;
2432 object->lightPosn[1] = -pLight->Direction.y;
2433 object->lightPosn[2] = -pLight->Direction.z;
2434 object->lightPosn[3] = 0.0;
2435 object->exponent = 0.0f;
2436 object->cutoff = 180.0f;
2439 case WINED3DLIGHT_SPOT:
2441 object->lightPosn[0] = pLight->Position.x;
2442 object->lightPosn[1] = pLight->Position.y;
2443 object->lightPosn[2] = pLight->Position.z;
2444 object->lightPosn[3] = 1.0;
2447 object->lightDirn[0] = pLight->Direction.x;
2448 object->lightDirn[1] = pLight->Direction.y;
2449 object->lightDirn[2] = pLight->Direction.z;
2450 object->lightDirn[3] = 1.0;
2453 * opengl-ish and d3d-ish spot lights use too different models for the
2454 * light "intensity" as a function of the angle towards the main light direction,
2455 * so we only can approximate very roughly.
2456 * however spot lights are rather rarely used in games (if ever used at all).
2457 * furthermore if still used, probably nobody pays attention to such details.
2459 if (pLight->Falloff == 0) {
2462 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2464 if (rho < 0.0001) rho = 0.0001f;
2465 object->exponent = -0.3/log(cos(rho/2));
2466 if (object->exponent > 128.0) {
2467 object->exponent = 128.0;
2469 object->cutoff = pLight->Phi*90/M_PI;
2475 FIXME("Unrecognized light type %d\n", pLight->Type);
2478 /* Update the live definitions if the light is currently assigned a glIndex */
2479 if (object->glIndex != -1) {
2480 setup_light(iface, object->glIndex, object);
2485 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2486 PLIGHTINFOEL *lightInfo = NULL;
2487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2488 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2490 /* Locate the light in the live lights */
2491 lightInfo = This->stateBlock->lights;
2492 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2494 if (lightInfo == NULL) {
2495 TRACE("Light information requested but light not defined\n");
2496 return WINED3DERR_INVALIDCALL;
2499 memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2504 * Get / Set Light Enable
2505 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2507 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2508 PLIGHTINFOEL *lightInfo = NULL;
2509 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2510 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2512 /* Tests show true = 128...not clear why */
2514 Enable = Enable? 128: 0;
2516 /* If recording state block, just add to end of lights chain with changedEnable set to true */
2517 if (This->isRecordingState) {
2518 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2519 if (NULL == lightInfo) {
2520 return WINED3DERR_OUTOFVIDEOMEMORY;
2522 lightInfo->OriginalIndex = Index;
2523 lightInfo->glIndex = -1;
2524 lightInfo->enabledChanged = TRUE;
2525 lightInfo->lightEnabled = Enable;
2527 /* Add to the END of the chain of lights changes to be replayed */
2528 if (This->updateStateBlock->lights == NULL) {
2529 This->updateStateBlock->lights = lightInfo;
2531 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2532 while (temp->next != NULL) temp=temp->next;
2533 temp->next = lightInfo;
2535 TRACE("Recording... not performing anything more\n");
2539 /* Not recording... So, locate the light in the live lights */
2540 lightInfo = This->stateBlock->lights;
2541 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2543 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2544 if (lightInfo == NULL) {
2546 TRACE("Light enabled requested but light not defined, so defining one!\n");
2547 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2549 /* Search for it again! Should be fairly quick as near head of list */
2550 lightInfo = This->stateBlock->lights;
2551 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2552 if (lightInfo == NULL) {
2553 FIXME("Adding default lights has failed dismally\n");
2554 return WINED3DERR_INVALIDCALL;
2558 /* OK, we now have a light... */
2561 /* If we are disabling it, check it was enabled, and
2562 still only do something if it has assigned a glIndex (which it should have!) */
2563 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2564 TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2566 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2567 checkGLcall("glDisable GL_LIGHT0+Index");
2570 TRACE("Nothing to do as light was not enabled\n");
2572 lightInfo->lightEnabled = Enable;
2575 /* We are enabling it. If it is enabled, it's really simple */
2576 if (lightInfo->lightEnabled) {
2578 TRACE("Nothing to do as light was enabled\n");
2580 /* If it already has a glIndex, it's still simple */
2581 } else if (lightInfo->glIndex != -1) {
2582 TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2583 lightInfo->lightEnabled = Enable;
2585 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2586 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2589 /* Otherwise got to find space - lights are ordered gl indexes first */
2591 PLIGHTINFOEL *bsf = NULL;
2592 PLIGHTINFOEL *pos = This->stateBlock->lights;
2593 PLIGHTINFOEL *prev = NULL;
2597 /* Try to minimize changes as much as possible */
2598 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2600 /* Try to remember which index can be replaced if necessary */
2601 if (bsf==NULL && !pos->lightEnabled) {
2602 /* Found a light we can replace, save as best replacement */
2606 /* Step to next space */
2612 /* If we have too many active lights, fail the call */
2613 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2614 FIXME("Program requests too many concurrent lights.\n");
2615 return WINED3DERR_INVALIDCALL;
2617 /* If we have allocated all lights, but not all are enabled,
2618 reuse one which is not enabled */
2619 } else if (Index == This->maxConcurrentLights) {
2620 /* use bsf - Simply swap the new light and the BSF one */
2621 PLIGHTINFOEL *bsfNext = bsf->next;
2622 PLIGHTINFOEL *bsfPrev = bsf->prev;
2625 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2626 if (bsf->prev != NULL) {
2627 bsf->prev->next = lightInfo;
2629 This->stateBlock->lights = lightInfo;
2632 /* If not side by side, lots of chains to update */
2633 if (bsf->next != lightInfo) {
2634 lightInfo->prev->next = bsf;
2635 bsf->next->prev = lightInfo;
2636 bsf->next = lightInfo->next;
2637 bsf->prev = lightInfo->prev;
2638 lightInfo->next = bsfNext;
2639 lightInfo->prev = bsfPrev;
2643 bsf->prev = lightInfo;
2644 bsf->next = lightInfo->next;
2645 lightInfo->next = bsf;
2646 lightInfo->prev = bsfPrev;
2651 glIndex = bsf->glIndex;
2653 lightInfo->glIndex = glIndex;
2654 lightInfo->lightEnabled = Enable;
2656 /* Finally set up the light in gl itself */
2657 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2659 setup_light(iface, glIndex, lightInfo);
2660 glEnable(GL_LIGHT0 + glIndex);
2661 checkGLcall("glEnable GL_LIGHT0 new setup");
2664 /* If we reached the end of the allocated lights, with space in the
2665 gl lights, setup a new light */
2666 } else if (pos->glIndex == -1) {
2668 /* We reached the end of the allocated gl lights, so already
2669 know the index of the next one! */
2671 lightInfo->glIndex = glIndex;
2672 lightInfo->lightEnabled = Enable;
2674 /* In an ideal world, it's already in the right place */
2675 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2676 /* No need to move it */
2678 /* Remove this light from the list */
2679 lightInfo->prev->next = lightInfo->next;
2680 if (lightInfo->next != NULL) {
2681 lightInfo->next->prev = lightInfo->prev;
2684 /* Add in at appropriate place (inbetween prev and pos) */
2685 lightInfo->prev = prev;
2686 lightInfo->next = pos;
2688 This->stateBlock->lights = lightInfo;
2690 prev->next = lightInfo;
2693 pos->prev = lightInfo;
2697 /* Finally set up the light in gl itself */
2698 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
2700 setup_light(iface, glIndex, lightInfo);
2701 glEnable(GL_LIGHT0 + glIndex);
2702 checkGLcall("glEnable GL_LIGHT0 new setup");
2711 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2713 PLIGHTINFOEL *lightInfo = NULL;
2714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2715 TRACE("(%p) : for idx(%d)\n", This, Index);
2717 /* Locate the light in the live lights */
2718 lightInfo = This->stateBlock->lights;
2719 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2721 if (lightInfo == NULL) {
2722 TRACE("Light enabled state requested but light not defined\n");
2723 return WINED3DERR_INVALIDCALL;
2725 *pEnable = lightInfo->lightEnabled;
2730 * Get / Set Clip Planes
2732 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2733 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2734 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2736 /* Validate Index */
2737 if (Index >= GL_LIMITS(clipplanes)) {
2738 TRACE("Application has requested clipplane this device doesn't support\n");
2739 return WINED3DERR_INVALIDCALL;
2742 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2743 This->updateStateBlock->set.clipplane[Index] = TRUE;
2744 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2745 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2746 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2747 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2749 /* Handle recording of state blocks */
2750 if (This->isRecordingState) {
2751 TRACE("Recording... not performing anything\n");
2759 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2760 glMatrixMode(GL_MODELVIEW);
2762 glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2764 TRACE("Clipplane [%f,%f,%f,%f]\n",
2765 This->updateStateBlock->clipplane[Index][0],
2766 This->updateStateBlock->clipplane[Index][1],
2767 This->updateStateBlock->clipplane[Index][2],
2768 This->updateStateBlock->clipplane[Index][3]);
2769 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2770 checkGLcall("glClipPlane");
2778 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2779 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2780 TRACE("(%p) : for idx %d\n", This, Index);
2782 /* Validate Index */
2783 if (Index >= GL_LIMITS(clipplanes)) {
2784 TRACE("Application has requested clipplane this device doesn't support\n");
2785 return WINED3DERR_INVALIDCALL;
2788 pPlane[0] = This->stateBlock->clipplane[Index][0];
2789 pPlane[1] = This->stateBlock->clipplane[Index][1];
2790 pPlane[2] = This->stateBlock->clipplane[Index][2];
2791 pPlane[3] = This->stateBlock->clipplane[Index][3];
2796 * Get / Set Clip Plane Status
2797 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2799 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2800 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2801 FIXME("(%p) : stub\n", This);
2802 if (NULL == pClipStatus) {
2803 return WINED3DERR_INVALIDCALL;
2805 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2806 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2810 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2811 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2812 FIXME("(%p) : stub\n", This);
2813 if (NULL == pClipStatus) {
2814 return WINED3DERR_INVALIDCALL;
2816 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2817 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2822 * Get / Set Material
2824 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2827 This->updateStateBlock->changed.material = TRUE;
2828 This->updateStateBlock->set.material = TRUE;
2829 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2831 /* Handle recording of state blocks */
2832 if (This->isRecordingState) {
2833 TRACE("Recording... not performing anything\n");
2838 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2839 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2840 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2841 pMaterial->Ambient.b, pMaterial->Ambient.a);
2842 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2843 pMaterial->Specular.b, pMaterial->Specular.a);
2844 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2845 pMaterial->Emissive.b, pMaterial->Emissive.a);
2846 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2848 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2849 checkGLcall("glMaterialfv(GL_AMBIENT)");
2850 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2851 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2853 /* Only change material color if specular is enabled, otherwise it is set to black */
2854 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2855 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2856 checkGLcall("glMaterialfv(GL_SPECULAR");
2858 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2859 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2860 checkGLcall("glMaterialfv(GL_SPECULAR");
2862 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2863 checkGLcall("glMaterialfv(GL_EMISSION)");
2864 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2865 checkGLcall("glMaterialf(GL_SHININESS");
2871 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2872 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2873 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2874 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2875 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2876 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2877 pMaterial->Ambient.b, pMaterial->Ambient.a);
2878 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2879 pMaterial->Specular.b, pMaterial->Specular.a);
2880 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2881 pMaterial->Emissive.b, pMaterial->Emissive.a);
2882 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2890 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2891 UINT BaseVertexIndex) {
2892 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2893 IWineD3DIndexBuffer *oldIdxs;
2894 UINT oldBaseIndex = This->updateStateBlock->baseVertexIndex;
2896 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2897 oldIdxs = This->updateStateBlock->pIndexData;
2899 This->updateStateBlock->changed.indices = TRUE;
2900 This->updateStateBlock->set.indices = TRUE;
2901 This->updateStateBlock->pIndexData = pIndexData;
2902 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2904 /* Handle recording of state blocks */
2905 if (This->isRecordingState) {
2906 TRACE("Recording... not performing anything\n");
2910 /* So far only the base vertex index is tracked */
2911 if(BaseVertexIndex != oldBaseIndex) {
2912 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2917 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2920 *ppIndexData = This->stateBlock->pIndexData;
2922 /* up ref count on ppindexdata */
2924 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2925 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2926 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2928 TRACE("(%p) No index data set\n", This);
2930 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2935 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2936 static HRESULT WINAPI IWineD3DDeviceImpl_SetBasevertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
2937 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2938 TRACE("(%p)->(%d)\n", This, BaseIndex);
2940 if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2941 TRACE("Application is setting the old value over, nothing to do\n");
2945 This->updateStateBlock->baseVertexIndex = BaseIndex;
2947 if (This->isRecordingState) {
2948 TRACE("Recording... not performing anything\n");
2951 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2956 * Get / Set Viewports
2958 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2959 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2961 TRACE("(%p)\n", This);
2962 This->updateStateBlock->changed.viewport = TRUE;
2963 This->updateStateBlock->set.viewport = TRUE;
2964 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2966 /* Handle recording of state blocks */
2967 if (This->isRecordingState) {
2968 TRACE("Recording... not performing anything\n");
2972 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2973 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2975 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2980 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2981 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2982 TRACE("(%p)\n", This);
2983 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2988 * Get / Set Render States
2989 * TODO: Verify against dx9 definitions
2991 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2993 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2994 DWORD oldValue = This->stateBlock->renderState[State];
2996 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2998 This->updateStateBlock->changed.renderState[State] = TRUE;
2999 This->updateStateBlock->set.renderState[State] = TRUE;
3000 This->updateStateBlock->renderState[State] = Value;
3002 /* Handle recording of state blocks */
3003 if (This->isRecordingState) {
3004 TRACE("Recording... not performing anything\n");
3008 /* Compared here and not before the assignment to allow proper stateblock recording */
3009 if(Value == oldValue) {
3010 TRACE("Application is setting the old value over, nothing to do\n");
3012 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
3018 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
3019 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3020 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
3021 *pValue = This->stateBlock->renderState[State];
3026 * Get / Set Sampler States
3027 * TODO: Verify against dx9 definitions
3030 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3032 DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
3035 * SetSampler is designed to allow for more than the standard up to 8 textures
3036 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3037 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3039 * http://developer.nvidia.com/object/General_FAQ.html#t6
3041 * There are two new settings for GForce
3043 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3044 * and the texture one:
3045 * GL_MAX_TEXTURE_COORDS_ARB.
3046 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3048 /** NOTE: States are applied in IWineD3DBaseTextre ApplyStateChanges the sampler state handler**/
3049 if(Sampler > GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3050 FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
3051 Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
3052 return WINED3DERR_INVALIDCALL;
3055 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
3056 debug_d3dsamplerstate(Type), Type, Value);
3057 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3058 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
3059 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3061 /* Handle recording of state blocks */
3062 if (This->isRecordingState) {
3063 TRACE("Recording... not performing anything\n");
3067 if(oldValue == Value) {
3068 TRACE("Application is setting the old value over, nothing to do\n");
3072 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
3077 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3078 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3079 /** TODO: check that sampler is in range **/
3080 *Value = This->stateBlock->samplerState[Sampler][Type];
3081 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
3086 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3091 This->updateStateBlock->set.scissorRect = TRUE;
3092 This->updateStateBlock->changed.scissorRect = TRUE;
3093 memcpy(&This->updateStateBlock->scissorRect, pRect, sizeof(*pRect));
3095 if(This->isRecordingState) {
3096 TRACE("Recording... not performing anything\n");
3100 GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
3101 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3102 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3104 winHeight = windowRect.bottom - windowRect.top;
3105 TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
3106 pRect->right - pRect->left, pRect->bottom - pRect->top);
3108 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3109 checkGLcall("glScissor");
3115 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3118 memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
3119 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3123 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3124 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3125 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3127 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3129 This->updateStateBlock->vertexDecl = pDecl;
3130 This->updateStateBlock->changed.vertexDecl = TRUE;
3131 This->updateStateBlock->set.vertexDecl = TRUE;
3133 if (This->isRecordingState) {
3134 TRACE("Recording... not performing anything\n");
3136 } else if(pDecl == oldDecl) {
3137 /* Checked after the assignment to allow proper stateblock recording */
3138 TRACE("Application is setting the old declaration over, nothing to do\n");
3142 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
3146 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3147 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3149 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3151 *ppDecl = This->stateBlock->vertexDecl;
3152 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3156 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3158 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3160 This->updateStateBlock->vertexShader = pShader;
3161 This->updateStateBlock->changed.vertexShader = TRUE;
3162 This->updateStateBlock->set.vertexShader = TRUE;
3164 if (This->isRecordingState) {
3165 TRACE("Recording... not performing anything\n");
3167 } else if(oldShader == pShader) {
3168 /* Checked here to allow proper stateblock recording */
3169 TRACE("App is setting the old shader over, nothing to do\n");
3173 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3175 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3180 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3181 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3183 if (NULL == ppShader) {
3184 return WINED3DERR_INVALIDCALL;
3186 *ppShader = This->stateBlock->vertexShader;
3187 if( NULL != *ppShader)
3188 IWineD3DVertexShader_AddRef(*ppShader);
3190 TRACE("(%p) : returning %p\n", This, *ppShader);
3194 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3195 IWineD3DDevice *iface,
3197 CONST BOOL *srcData,
3200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3201 int i, cnt = min(count, MAX_CONST_B - start);
3203 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3204 iface, srcData, start, count);
3206 if (srcData == NULL || cnt < 0)
3207 return WINED3DERR_INVALIDCALL;
3209 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3210 for (i = 0; i < cnt; i++)
3211 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3213 for (i = start; i < cnt + start; ++i) {
3214 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
3215 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
3218 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3223 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3224 IWineD3DDevice *iface,
3229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3230 int cnt = min(count, MAX_CONST_B - start);
3232 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3233 iface, dstData, start, count);
3235 if (dstData == NULL || cnt < 0)
3236 return WINED3DERR_INVALIDCALL;
3238 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3242 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3243 IWineD3DDevice *iface,
3248 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3249 int i, cnt = min(count, MAX_CONST_I - start);
3251 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3252 iface, srcData, start, count);
3254 if (srcData == NULL || cnt < 0)
3255 return WINED3DERR_INVALIDCALL;
3257 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3258 for (i = 0; i < cnt; i++)
3259 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3260 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3262 for (i = start; i < cnt + start; ++i) {
3263 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
3264 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
3267 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3272 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3273 IWineD3DDevice *iface,
3278 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3279 int cnt = min(count, MAX_CONST_I - start);
3281 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3282 iface, dstData, start, count);
3284 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3285 return WINED3DERR_INVALIDCALL;
3287 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3291 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3292 IWineD3DDevice *iface,
3294 CONST float *srcData,
3297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3298 int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3300 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3301 iface, srcData, start, count);
3303 if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
3304 return WINED3DERR_INVALIDCALL;
3306 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3307 for (i = 0; i < cnt; i++)
3308 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3309 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3311 for (i = start; i < cnt + start; ++i) {
3312 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
3313 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3315 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3316 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
3318 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3321 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3326 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3327 IWineD3DDevice *iface,
3332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3333 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3335 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3336 iface, dstData, start, count);
3338 if (dstData == NULL || cnt < 0)
3339 return WINED3DERR_INVALIDCALL;
3341 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3345 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3347 for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3348 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3352 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3354 /* This code can assume that GL_NV_register_combiners are supported, otherwise
3355 * it is never called.
3358 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3359 * that would be really messy and require shader recompilation
3360 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3361 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3362 * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3363 * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3365 if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3366 if(This->oneToOneTexUnitMap) {
3367 TRACE("Not touching 1:1 map\n");
3370 TRACE("Restoring 1:1 texture unit mapping\n");
3371 /* Restore a 1:1 mapping */
3372 for(i = 0; i < MAX_SAMPLERS; i++) {
3373 if(This->texUnitMap[i] != i) {
3374 This->texUnitMap[i] = i;
3375 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3376 markTextureStagesDirty(This, i);
3379 This->oneToOneTexUnitMap = TRUE;
3382 /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3383 * First, see if we can succeed at all
3386 for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3387 if(This->stateBlock->textures[i] == NULL) tex++;
3390 if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3391 FIXME("Too many bound textures to support the combiner settings\n");
3395 /* Now work out the mapping */
3397 This->oneToOneTexUnitMap = FALSE;
3398 WARN("Non 1:1 mapping UNTESTED!\n");
3399 for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3400 /* Skip NULL textures */
3401 if (!This->stateBlock->textures[i]) {
3402 /* Map to -1, so the check below doesn't fail if a non-NULL
3403 * texture is set on this stage */
3404 TRACE("Mapping texture stage %d to -1\n", i);
3405 This->texUnitMap[i] = -1;
3410 TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3411 if(This->texUnitMap[i] != tex) {
3412 This->texUnitMap[i] = tex;
3413 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3414 markTextureStagesDirty(This, i);
3422 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3424 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
3425 This->updateStateBlock->pixelShader = pShader;
3426 This->updateStateBlock->changed.pixelShader = TRUE;
3427 This->updateStateBlock->set.pixelShader = TRUE;
3429 /* Handle recording of state blocks */
3430 if (This->isRecordingState) {
3431 TRACE("Recording... not performing anything\n");
3434 if (This->isRecordingState) {
3435 TRACE("Recording... not performing anything\n");
3439 if(pShader == oldShader) {
3440 TRACE("App is setting the old pixel shader over, nothing to do\n");
3444 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3445 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3447 /* Rebuild the texture unit mapping if nvrc's are supported */
3448 if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3449 IWineD3DDeviceImpl_FindTexUnitMap(This);
3455 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3456 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3458 if (NULL == ppShader) {
3459 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3460 return WINED3DERR_INVALIDCALL;
3463 *ppShader = This->stateBlock->pixelShader;
3464 if (NULL != *ppShader) {
3465 IWineD3DPixelShader_AddRef(*ppShader);
3467 TRACE("(%p) : returning %p\n", This, *ppShader);
3471 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3472 IWineD3DDevice *iface,
3474 CONST BOOL *srcData,
3477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3478 int i, cnt = min(count, MAX_CONST_B - start);
3480 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3481 iface, srcData, start, count);
3483 if (srcData == NULL || cnt < 0)
3484 return WINED3DERR_INVALIDCALL;
3486 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3487 for (i = 0; i < cnt; i++)
3488 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3490 for (i = start; i < cnt + start; ++i) {
3491 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3492 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
3495 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3500 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3501 IWineD3DDevice *iface,
3506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3507 int cnt = min(count, MAX_CONST_B - start);
3509 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3510 iface, dstData, start, count);
3512 if (dstData == NULL || cnt < 0)
3513 return WINED3DERR_INVALIDCALL;
3515 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3519 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3520 IWineD3DDevice *iface,
3525 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3526 int i, cnt = min(count, MAX_CONST_I - start);
3528 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3529 iface, srcData, start, count);
3531 if (srcData == NULL || cnt < 0)
3532 return WINED3DERR_INVALIDCALL;
3534 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3535 for (i = 0; i < cnt; i++)
3536 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3537 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3539 for (i = start; i < cnt + start; ++i) {
3540 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3541 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
3544 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3549 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3550 IWineD3DDevice *iface,
3555 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3556 int cnt = min(count, MAX_CONST_I - start);
3558 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3559 iface, dstData, start, count);
3561 if (dstData == NULL || cnt < 0)
3562 return WINED3DERR_INVALIDCALL;
3564 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3568 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3569 IWineD3DDevice *iface,
3571 CONST float *srcData,
3574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3575 int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3577 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3578 iface, srcData, start, count);
3580 if (srcData == NULL || cnt < 0)
3581 return WINED3DERR_INVALIDCALL;
3583 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3584 for (i = 0; i < cnt; i++)
3585 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3586 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3588 for (i = start; i < cnt + start; ++i) {
3589 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3590 constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3592 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3593 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3595 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3598 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3603 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3604 IWineD3DDevice *iface,
3609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3610 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3612 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3613 iface, dstData, start, count);
3615 if (dstData == NULL || cnt < 0)
3616 return WINED3DERR_INVALIDCALL;
3618 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3622 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3624 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3625 char *dest_ptr, *dest_conv = NULL;
3627 DWORD DestFVF = dest->fvf;
3629 WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3633 if (SrcFVF & WINED3DFVF_NORMAL) {
3634 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3637 if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3638 ERR("Source has no position mask\n");
3639 return WINED3DERR_INVALIDCALL;
3642 /* We might access VBOs from this code, so hold the lock */
3645 if (dest->resource.allocatedMemory == NULL) {
3646 /* This may happen if we do direct locking into a vbo. Unlikely,
3647 * but theoretically possible(ddraw processvertices test)
3649 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3650 if(!dest->resource.allocatedMemory) {
3652 ERR("Out of memory\n");
3653 return E_OUTOFMEMORY;
3657 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3658 checkGLcall("glBindBufferARB");
3659 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3661 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3663 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3664 checkGLcall("glUnmapBufferARB");
3668 /* Get a pointer into the destination vbo(create one if none exists) and
3669 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3671 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3676 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3677 dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
3679 ERR("glMapBuffer failed\n");
3680 /* Continue without storing converted vertices */
3685 * a) WINED3DRS_CLIPPING is enabled
3686 * b) WINED3DVOP_CLIP is passed
3688 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3689 static BOOL warned = FALSE;
3691 * The clipping code is not quite correct. Some things need
3692 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3693 * so disable clipping for now.
3694 * (The graphics in Half-Life are broken, and my processvertices
3695 * test crashes with IDirect3DDevice3)
3701 FIXME("Clipping is broken and disabled for now\n");
3703 } else doClip = FALSE;
3704 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3706 dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3709 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3712 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3713 WINED3DTS_PROJECTION,
3715 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3716 WINED3DTS_WORLDMATRIX(0),
3719 TRACE("View mat:\n");
3720 TRACE("%f %f %f %f\n", view_mat.u.s._11, view_mat.u.s._12, view_mat.u.s._13, view_mat.u.s._14);
3721 TRACE("%f %f %f %f\n", view_mat.u.s._21, view_mat.u.s._22, view_mat.u.s._23, view_mat.u.s._24);
3722 TRACE("%f %f %f %f\n", view_mat.u.s._31, view_mat.u.s._32, view_mat.u.s._33, view_mat.u.s._34);
3723 TRACE("%f %f %f %f\n", view_mat.u.s._41, view_mat.u.s._42, view_mat.u.s._43, view_mat.u.s._44);
3725 TRACE("Proj mat:\n");
3726 TRACE("%f %f %f %f\n", proj_mat.u.s._11, proj_mat.u.s._12, proj_mat.u.s._13, proj_mat.u.s._14);
3727 TRACE("%f %f %f %f\n", proj_mat.u.s._21, proj_mat.u.s._22, proj_mat.u.s._23, proj_mat.u.s._24);
3728 TRACE("%f %f %f %f\n", proj_mat.u.s._31, proj_mat.u.s._32, proj_mat.u.s._33, proj_mat.u.s._34);
3729 TRACE("%f %f %f %f\n", proj_mat.u.s._41, proj_mat.u.s._42, proj_mat.u.s._43, proj_mat.u.s._44);
3731 TRACE("World mat:\n");
3732 TRACE("%f %f %f %f\n", world_mat.u.s._11, world_mat.u.s._12, world_mat.u.s._13, world_mat.u.s._14);
3733 TRACE("%f %f %f %f\n", world_mat.u.s._21, world_mat.u.s._22, world_mat.u.s._23, world_mat.u.s._24);
3734 TRACE("%f %f %f %f\n", world_mat.u.s._31, world_mat.u.s._32, world_mat.u.s._33, world_mat.u.s._34);
3735 TRACE("%f %f %f %f\n", world_mat.u.s._41, world_mat.u.s._42, world_mat.u.s._43, world_mat.u.s._44);
3737 /* Get the viewport */
3738 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3739 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3740 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3742 multiply_matrix(&mat,&view_mat,&world_mat);
3743 multiply_matrix(&mat,&proj_mat,&mat);
3745 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3747 for (i = 0; i < dwCount; i+= 1) {
3748 unsigned int tex_index;
3750 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3751 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3752 /* The position first */
3754 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3756 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3758 /* Multiplication with world, view and projection matrix */
3759 x = (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0 * mat.u.s._41);
3760 y = (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0 * mat.u.s._42);
3761 z = (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0 * mat.u.s._43);
3762 rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0 * mat.u.s._44);
3764 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3766 /* WARNING: The following things are taken from d3d7 and were not yet checked
3767 * against d3d8 or d3d9!
3770 /* Clipping conditions: From
3771 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3773 * A vertex is clipped if it does not match the following requirements
3777 * 0 < rhw ( Not in d3d7, but tested in d3d7)
3779 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3780 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3785 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3786 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3789 /* "Normal" viewport transformation (not clipped)
3790 * 1) The values are divided by rhw
3791 * 2) The y axis is negative, so multiply it with -1
3792 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3793 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3794 * 4) Multiply x with Width/2 and add Width/2
3795 * 5) The same for the height
3796 * 6) Add the viewpoint X and Y to the 2D coordinates and
3797 * The minimum Z value to z
3798 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3800 * Well, basically it's simply a linear transformation into viewport
3812 z *= vp.MaxZ - vp.MinZ;
3814 x += vp.Width / 2 + vp.X;
3815 y += vp.Height / 2 + vp.Y;
3820 /* That vertex got clipped
3821 * Contrary to OpenGL it is not dropped completely, it just
3822 * undergoes a different calculation.
3824 TRACE("Vertex got clipped\n");
3831 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3832 * outside of the main vertex buffer memory. That needs some more
3837 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3840 ( (float *) dest_ptr)[0] = x;
3841 ( (float *) dest_ptr)[1] = y;
3842 ( (float *) dest_ptr)[2] = z;
3843 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3845 dest_ptr += 3 * sizeof(float);
3847 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3848 dest_ptr += sizeof(float);
3853 ( (float *) dest_conv)[0] = x * w;
3854 ( (float *) dest_conv)[1] = y * w;
3855 ( (float *) dest_conv)[2] = z * w;
3856 ( (float *) dest_conv)[3] = w;
3858 dest_conv += 3 * sizeof(float);
3860 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3861 dest_conv += sizeof(float);
3865 if (DestFVF & WINED3DFVF_PSIZE) {
3866 dest_ptr += sizeof(DWORD);
3867 if(dest_conv) dest_conv += sizeof(DWORD);
3869 if (DestFVF & WINED3DFVF_NORMAL) {
3871 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3872 /* AFAIK this should go into the lighting information */
3873 FIXME("Didn't expect the destination to have a normal\n");
3874 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3876 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3880 if (DestFVF & WINED3DFVF_DIFFUSE) {
3882 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3884 static BOOL warned = FALSE;
3887 ERR("No diffuse color in source, but destination has one\n");
3891 *( (DWORD *) dest_ptr) = 0xffffffff;
3892 dest_ptr += sizeof(DWORD);
3895 *( (DWORD *) dest_conv) = 0xffffffff;
3896 dest_conv += sizeof(DWORD);
3900 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3902 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
3903 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3904 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3905 dest_conv += sizeof(DWORD);
3910 if (DestFVF & WINED3DFVF_SPECULAR) {
3911 /* What's the color value in the feedback buffer? */
3913 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3915 static BOOL warned = FALSE;
3918 ERR("No specular color in source, but destination has one\n");
3922 *( (DWORD *) dest_ptr) = 0xFF000000;
3923 dest_ptr += sizeof(DWORD);
3926 *( (DWORD *) dest_conv) = 0xFF000000;
3927 dest_conv += sizeof(DWORD);
3931 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3933 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
3934 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3935 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3936 dest_conv += sizeof(DWORD);
3941 for (tex_index = 0; tex_index < numTextures; tex_index++) {
3943 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
3944 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3946 ERR("No source texture, but destination requests one\n");
3947 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3948 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3951 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3953 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3960 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3961 checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
3968 #undef copy_and_next
3970 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3971 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3972 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
3973 WineDirect3DVertexStridedData strided;
3974 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3977 WARN("NULL source vertex buffer\n");
3978 return WINED3DERR_INVALIDCALL;
3980 /* We don't need the source vbo because this buffer is only used as
3981 * a source for ProcessVertices. Avoid wasting resources by converting the
3982 * buffer and loading the VBO
3985 TRACE("Releasing the source vbo, it won't be needed\n");
3987 if(!SrcImpl->resource.allocatedMemory) {
3988 /* Rescue the data from the buffer */
3990 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
3991 if(!SrcImpl->resource.allocatedMemory) {
3992 ERR("Out of memory\n");
3993 return E_OUTOFMEMORY;
3997 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
3998 checkGLcall("glBindBufferARB");
4000 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4002 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
4005 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4006 checkGLcall("glUnmapBufferARB");
4011 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
4012 checkGLcall("glBindBufferARB");
4013 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
4014 checkGLcall("glDeleteBuffersARB");
4020 memset(&strided, 0, sizeof(strided));
4021 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0);
4023 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4027 * Get / Set Texture Stage States
4028 * TODO: Verify against dx9 definitions
4030 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4032 DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4034 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4036 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4038 /* Reject invalid texture units */
4039 if (Stage >= GL_LIMITS(texture_stages)) {
4040 TRACE("Attempt to access invalid texture rejected\n");
4041 return WINED3DERR_INVALIDCALL;
4044 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4045 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
4046 This->updateStateBlock->textureState[Stage][Type] = Value;
4048 if (This->isRecordingState) {
4049 TRACE("Recording... not performing anything\n");
4053 /* Checked after the assignments to allow proper stateblock recording */
4054 if(oldValue == Value) {
4055 TRACE("App is setting the old value over, nothing to do\n");
4059 if(Stage > This->stateBlock->lowest_disabled_stage &&
4060 StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4061 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4062 * Changes in other states are important on disabled stages too
4067 if(Type == WINED3DTSS_COLOROP) {
4070 if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4071 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4072 * they have to be disabled
4074 * The current stage is dirtified below.
4076 for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4077 TRACE("Additionally dirtifying stage %d\n", i);
4078 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4080 This->stateBlock->lowest_disabled_stage = Stage;
4081 TRACE("New lowest disabled: %d\n", Stage);
4082 } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4083 /* Previously disabled stage enabled. Stages above it may need enabling
4084 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4085 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4087 * Again stage Stage doesn't need to be dirtified here, it is handled below.
4090 for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
4091 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4094 TRACE("Additionally dirtifying stage %d due to enable\n", i);
4095 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4097 This->stateBlock->lowest_disabled_stage = i;
4098 TRACE("New lowest disabled: %d\n", i);
4100 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4101 /* TODO: Built a stage -> texture unit mapping for register combiners */
4105 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4107 /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
4108 * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
4109 * will call FindTexUnitMap too.
4111 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4112 IWineD3DDeviceImpl_FindTexUnitMap(This);
4117 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4118 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4119 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4120 *pValue = This->updateStateBlock->textureState[Stage][Type];
4127 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4129 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4130 IWineD3DBaseTexture *oldTexture;
4132 oldTexture = This->updateStateBlock->textures[Stage];
4133 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
4135 #if 0 /* TODO: check so vertex textures */
4136 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4137 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4142 /* Reject invalid texture units */
4143 if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
4144 WARN("Attempt to access invalid texture rejected\n");
4145 return WINED3DERR_INVALIDCALL;
4148 if(pTexture != NULL) {
4149 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
4151 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4152 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4153 return WINED3DERR_INVALIDCALL;
4155 This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4158 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4159 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4161 This->updateStateBlock->set.textures[Stage] = TRUE;
4162 This->updateStateBlock->changed.textures[Stage] = TRUE;
4163 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4164 This->updateStateBlock->textures[Stage] = pTexture;
4166 /* Handle recording of state blocks */
4167 if (This->isRecordingState) {
4168 TRACE("Recording... not performing anything\n");
4172 if(oldTexture == pTexture) {
4173 TRACE("App is setting the same texture again, nothing to do\n");
4177 /** NOTE: MSDN says that setTexture increases the reference count,
4178 * and the the application nust set the texture back to null (or have a leaky application),
4179 * This means we should pass the refcount up to the parent
4180 *******************************/
4181 if (NULL != This->updateStateBlock->textures[Stage]) {
4182 IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4183 ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4185 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4186 if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4187 /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4188 * so the COLOROP and ALPHAOP have to be dirtified.
4190 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4191 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4193 if(bindCount == 1) {
4194 new->baseTexture.sampler = Stage;
4196 /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4200 if (NULL != oldTexture) {
4201 IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4202 LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4204 IWineD3DBaseTexture_Release(oldTexture);
4205 if(pTexture == NULL && Stage < MAX_TEXTURES) {
4206 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4207 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4210 if(bindCount && old->baseTexture.sampler == Stage) {
4212 /* Have to do a search for the other sampler(s) where the texture is bound to
4213 * Shouldn't happen as long as apps bind a texture only to one stage
4215 TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4216 for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
4217 if(This->updateStateBlock->textures[i] == oldTexture) {
4218 old->baseTexture.sampler = i;
4225 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4227 /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
4228 * pixel shader is used
4230 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4231 IWineD3DDeviceImpl_FindTexUnitMap(This);
4237 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4239 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4241 /* Reject invalid texture units */
4242 if (Stage >= GL_LIMITS(sampler_stages)) {
4243 TRACE("Attempt to access invalid texture rejected\n");
4244 return WINED3DERR_INVALIDCALL;
4246 *ppTexture=This->stateBlock->textures[Stage];
4248 IWineD3DBaseTexture_AddRef(*ppTexture);
4256 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4257 IWineD3DSurface **ppBackBuffer) {
4258 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4259 IWineD3DSwapChain *swapChain;
4262 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4264 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4265 if (hr == WINED3D_OK) {
4266 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4267 IWineD3DSwapChain_Release(swapChain);
4269 *ppBackBuffer = NULL;
4274 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4275 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4276 WARN("(%p) : stub, calling idirect3d for now\n", This);
4277 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4280 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4281 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4282 IWineD3DSwapChain *swapChain;
4285 if(iSwapChain > 0) {
4286 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4287 if (hr == WINED3D_OK) {
4288 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4289 IWineD3DSwapChain_Release(swapChain);
4291 FIXME("(%p) Error getting display mode\n", This);
4294 /* Don't read the real display mode,
4295 but return the stored mode instead. X11 can't change the color
4296 depth, and some apps are pretty angry if they SetDisplayMode from
4297 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4299 Also don't relay to the swapchain because with ddraw it's possible
4300 that there isn't a swapchain at all */
4301 pMode->Width = This->ddraw_width;
4302 pMode->Height = This->ddraw_height;
4303 pMode->Format = This->ddraw_format;
4304 pMode->RefreshRate = 0;
4311 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4313 TRACE("(%p)->(%p)\n", This, hWnd);
4315 This->ddraw_window = hWnd;
4319 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4320 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4321 TRACE("(%p)->(%p)\n", This, hWnd);
4323 *hWnd = This->ddraw_window;
4328 * Stateblock related functions
4331 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4333 IWineD3DStateBlockImpl *object;
4334 HRESULT temp_result;
4336 TRACE("(%p)\n", This);
4338 if (This->isRecordingState) {
4339 return WINED3DERR_INVALIDCALL;
4342 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4343 if (NULL == object ) {
4344 FIXME("(%p)Error allocating memory for stateblock\n", This);
4345 return E_OUTOFMEMORY;
4347 TRACE("(%p) created object %p\n", This, object);
4348 object->wineD3DDevice= This;
4349 /** FIXME: object->parent = parent; **/
4350 object->parent = NULL;
4351 object->blockType = WINED3DSBT_ALL;
4353 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4355 temp_result = allocate_shader_constants(object);
4356 if (WINED3D_OK != temp_result)
4359 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4360 This->updateStateBlock = object;
4361 This->isRecordingState = TRUE;
4363 TRACE("(%p) recording stateblock %p\n",This , object);
4367 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4368 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4370 if (!This->isRecordingState) {
4371 FIXME("(%p) not recording! returning error\n", This);
4372 *ppStateBlock = NULL;
4373 return WINED3DERR_INVALIDCALL;
4376 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4377 This->isRecordingState = FALSE;
4378 This->updateStateBlock = This->stateBlock;
4379 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4380 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4381 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4386 * Scene related functions
4388 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4389 /* At the moment we have no need for any functionality at the beginning
4391 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4392 TRACE("(%p)\n", This);
4395 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4396 return WINED3DERR_INVALIDCALL;
4398 This->inScene = TRUE;
4402 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4404 TRACE("(%p)\n", This);
4406 if(!This->inScene) {
4407 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4408 return WINED3DERR_INVALIDCALL;
4412 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4414 checkGLcall("glFlush");
4417 This->inScene = FALSE;
4421 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4422 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4423 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4425 IWineD3DSwapChain *swapChain = NULL;
4427 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4429 TRACE("(%p) Presenting the frame\n", This);
4431 for(i = 0 ; i < swapchains ; i ++) {
4433 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4434 TRACE("presentinng chain %d, %p\n", i, swapChain);
4435 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4436 IWineD3DSwapChain_Release(swapChain);
4442 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4443 DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4444 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4446 /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
4447 render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
4448 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4449 GLbitfield glMask = 0;
4450 GLboolean old_ztest;
4451 GLfloat old_z_clear_value;
4452 GLint old_stencil_clear_value;
4453 GLfloat old_color_clear_value[4];
4455 CONST WINED3DRECT* curRect;
4457 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4458 Count, pRects, Flags, Z, Stencil);
4462 glEnable(GL_SCISSOR_TEST);
4463 checkGLcall("glEnable GL_SCISSOR_TEST");
4465 if (Count > 0 && pRects) {
4471 /* Only set the values up once, as they are not changing */
4472 if (Flags & WINED3DCLEAR_STENCIL) {
4473 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4474 glClearStencil(Stencil);
4475 checkGLcall("glClearStencil");
4476 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4477 glStencilMask(0xFFFFFFFF);
4480 if (Flags & WINED3DCLEAR_ZBUFFER) {
4481 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4482 glDepthMask(GL_TRUE);
4483 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4485 checkGLcall("glClearDepth");
4486 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4489 if (Flags & WINED3DCLEAR_TARGET) {
4490 TRACE("Clearing screen with glClear to color %x\n", Color);
4491 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4492 glClearColor(D3DCOLOR_R(Color),
4496 checkGLcall("glClearColor");
4498 /* Clear ALL colors! */
4499 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4500 glMask = glMask | GL_COLOR_BUFFER_BIT;
4503 /* Now process each rect in turn */
4504 for (i = 0; i < Count || i == 0; i++) {
4507 /* Note gl uses lower left, width/height */
4508 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4509 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4510 curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4511 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4512 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4513 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4514 checkGLcall("glScissor");
4516 glScissor(This->stateBlock->viewport.X,
4517 (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4518 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4519 This->stateBlock->viewport.Width,
4520 This->stateBlock->viewport.Height);
4521 checkGLcall("glScissor");
4524 /* Clear the selected rectangle (or full screen) */
4526 checkGLcall("glClear");
4528 /* Step to the next rectangle */
4529 if (curRect) curRect = curRect + sizeof(WINED3DRECT);
4532 /* Restore the old values (why..?) */
4533 if (Flags & WINED3DCLEAR_STENCIL) {
4534 glClearStencil(old_stencil_clear_value);
4535 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4537 if (Flags & WINED3DCLEAR_ZBUFFER) {
4538 glDepthMask(old_ztest);
4539 glClearDepth(old_z_clear_value);
4541 if (Flags & WINED3DCLEAR_TARGET) {
4542 glClearColor(old_color_clear_value[0],
4543 old_color_clear_value[1],
4544 old_color_clear_value[2],
4545 old_color_clear_value[3]);
4546 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4547 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4548 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4549 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4552 glDisable(GL_SCISSOR_TEST);
4553 checkGLcall("glDisable");
4562 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4563 UINT PrimitiveCount) {
4565 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4566 This->stateBlock->streamIsUP = FALSE;
4568 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4569 debug_d3dprimitivetype(PrimitiveType),
4570 StartVertex, PrimitiveCount);
4572 if(This->stateBlock->loadBaseVertexIndex != 0) {
4573 This->stateBlock->loadBaseVertexIndex = 0;
4574 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4576 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4577 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4578 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4582 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4583 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4584 WINED3DPRIMITIVETYPE PrimitiveType,
4585 UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4587 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4589 IWineD3DIndexBuffer *pIB;
4590 WINED3DINDEXBUFFER_DESC IdxBufDsc;
4592 pIB = This->stateBlock->pIndexData;
4593 This->stateBlock->streamIsUP = FALSE;
4595 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4596 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4597 minIndex, NumVertices, startIndex, primCount);
4599 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4600 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4606 if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4607 This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4608 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4611 drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4612 idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4617 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4618 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4619 UINT VertexStreamZeroStride) {
4620 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4622 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4623 debug_d3dprimitivetype(PrimitiveType),
4624 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4626 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4627 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4628 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4629 This->stateBlock->streamIsUP = TRUE;
4630 This->stateBlock->loadBaseVertexIndex = 0;
4632 /* TODO: Only mark dirty if drawing from a different UP address */
4633 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4635 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4636 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4638 /* MSDN specifies stream zero settings must be set to NULL */
4639 This->stateBlock->streamStride[0] = 0;
4640 This->stateBlock->streamSource[0] = NULL;
4642 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4643 * the new stream sources or use UP drawing again
4648 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4649 UINT MinVertexIndex, UINT NumVertices,
4650 UINT PrimitiveCount, CONST void* pIndexData,
4651 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4652 UINT VertexStreamZeroStride) {
4654 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4657 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4658 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4659 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4661 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4667 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4668 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4669 This->stateBlock->streamIsUP = TRUE;
4670 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4672 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4673 This->stateBlock->baseVertexIndex = 0;
4674 This->stateBlock->loadBaseVertexIndex = 0;
4675 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4676 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4678 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4680 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4681 This->stateBlock->streamSource[0] = NULL;
4682 This->stateBlock->streamStride[0] = 0;
4683 This->stateBlock->pIndexData = NULL;
4684 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4685 * SetStreamSource to specify a vertex buffer
4691 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4694 /* Mark the state dirty until we have nicer tracking
4695 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4698 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4699 This->stateBlock->baseVertexIndex = 0;
4700 This->up_strided = DrawPrimStrideData;
4701 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4702 This->up_strided = NULL;
4705 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4706 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4707 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4708 HRESULT hr = WINED3D_OK;
4709 WINED3DRESOURCETYPE sourceType;
4710 WINED3DRESOURCETYPE destinationType;
4713 /* TODO: think about moving the code into IWineD3DBaseTexture */
4715 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4717 /* verify that the source and destination textures aren't NULL */
4718 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4719 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4720 This, pSourceTexture, pDestinationTexture);
4721 hr = WINED3DERR_INVALIDCALL;
4724 if (pSourceTexture == pDestinationTexture) {
4725 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4726 This, pSourceTexture, pDestinationTexture);
4727 hr = WINED3DERR_INVALIDCALL;
4729 /* Verify that the source and destination textures are the same type */
4730 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4731 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4733 if (sourceType != destinationType) {
4734 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4736 hr = WINED3DERR_INVALIDCALL;
4739 /* check that both textures have the identical numbers of levels */
4740 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4741 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4742 hr = WINED3DERR_INVALIDCALL;
4745 if (WINED3D_OK == hr) {
4747 /* Make sure that the destination texture is loaded */
4748 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4750 /* Update every surface level of the texture */
4751 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4753 switch (sourceType) {
4754 case WINED3DRTYPE_TEXTURE:
4756 IWineD3DSurface *srcSurface;
4757 IWineD3DSurface *destSurface;
4759 for (i = 0 ; i < levels ; ++i) {
4760 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4761 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4762 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4763 IWineD3DSurface_Release(srcSurface);
4764 IWineD3DSurface_Release(destSurface);
4765 if (WINED3D_OK != hr) {
4766 WARN("(%p) : Call to update surface failed\n", This);
4772 case WINED3DRTYPE_CUBETEXTURE:
4774 IWineD3DSurface *srcSurface;
4775 IWineD3DSurface *destSurface;
4776 WINED3DCUBEMAP_FACES faceType;
4778 for (i = 0 ; i < levels ; ++i) {
4779 /* Update each cube face */
4780 for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4781 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4782 if (WINED3D_OK != hr) {
4783 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4785 TRACE("Got srcSurface %p\n", srcSurface);
4787 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4788 if (WINED3D_OK != hr) {
4789 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4791 TRACE("Got desrSurface %p\n", destSurface);
4793 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4794 IWineD3DSurface_Release(srcSurface);
4795 IWineD3DSurface_Release(destSurface);
4796 if (WINED3D_OK != hr) {
4797 WARN("(%p) : Call to update surface failed\n", This);
4804 #if 0 /* TODO: Add support for volume textures */
4805 case WINED3DRTYPE_VOLUMETEXTURE:
4807 IWineD3DVolume srcVolume = NULL;
4808 IWineD3DSurface destVolume = NULL;
4810 for (i = 0 ; i < levels ; ++i) {
4811 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
4812 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4813 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4814 IWineD3DVolume_Release(srcSurface);
4815 IWineD3DVolume_Release(destSurface);
4816 if (WINED3D_OK != hr) {
4817 WARN("(%p) : Call to update volume failed\n", This);
4825 FIXME("(%p) : Unsupported source and destination type\n", This);
4826 hr = WINED3DERR_INVALIDCALL;
4833 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4834 IWineD3DSwapChain *swapChain;
4836 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4837 if(hr == WINED3D_OK) {
4838 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4839 IWineD3DSwapChain_Release(swapChain);
4844 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4845 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4846 /* return a sensible default */
4848 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4849 FIXME("(%p) : stub\n", This);
4853 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4854 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4856 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4857 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4858 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4859 return WINED3DERR_INVALIDCALL;
4861 for (j = 0; j < 256; ++j) {
4862 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4863 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4864 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4865 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4867 TRACE("(%p) : returning\n", This);
4871 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4872 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4874 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4875 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4876 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4877 return WINED3DERR_INVALIDCALL;
4879 for (j = 0; j < 256; ++j) {
4880 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4881 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4882 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4883 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4885 TRACE("(%p) : returning\n", This);
4889 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4890 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4891 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4892 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4893 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4894 return WINED3DERR_INVALIDCALL;
4896 /*TODO: stateblocks */
4897 This->currentPalette = PaletteNumber;
4898 TRACE("(%p) : returning\n", This);
4902 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4904 if (PaletteNumber == NULL) {
4905 WARN("(%p) : returning Invalid Call\n", This);
4906 return WINED3DERR_INVALIDCALL;
4908 /*TODO: stateblocks */
4909 *PaletteNumber = This->currentPalette;
4910 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4914 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4915 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4916 static BOOL showFixmes = TRUE;
4918 FIXME("(%p) : stub\n", This);
4922 This->softwareVertexProcessing = bSoftware;
4927 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4928 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4929 static BOOL showFixmes = TRUE;
4931 FIXME("(%p) : stub\n", This);
4934 return This->softwareVertexProcessing;
4938 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4939 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4940 IWineD3DSwapChain *swapChain;
4943 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4945 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4946 if(hr == WINED3D_OK){
4947 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4948 IWineD3DSwapChain_Release(swapChain);
4950 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4956 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4957 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4958 static BOOL showfixmes = TRUE;
4959 if(nSegments != 0.0f) {
4961 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4968 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4969 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4970 static BOOL showfixmes = TRUE;
4972 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4978 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4980 /** TODO: remove casts to IWineD3DSurfaceImpl
4981 * NOTE: move code to surface to accomplish this
4982 ****************************************/
4983 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4984 int srcWidth, srcHeight;
4985 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4986 WINED3DFORMAT destFormat, srcFormat;
4988 int srcLeft, destLeft, destTop;
4989 WINED3DPOOL srcPool, destPool;
4991 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4992 glDescriptor *glDescription = NULL;
4993 GLenum textureDimensions = GL_TEXTURE_2D;
4994 IWineD3DBaseTexture *baseTexture;
4996 WINED3DSURFACE_DESC winedesc;
4998 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4999 memset(&winedesc, 0, sizeof(winedesc));
5000 winedesc.Width = &srcSurfaceWidth;
5001 winedesc.Height = &srcSurfaceHeight;
5002 winedesc.Pool = &srcPool;
5003 winedesc.Format = &srcFormat;
5005 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5007 winedesc.Width = &destSurfaceWidth;
5008 winedesc.Height = &destSurfaceHeight;
5009 winedesc.Pool = &destPool;
5010 winedesc.Format = &destFormat;
5011 winedesc.Size = &destSize;
5013 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5015 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
5016 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5017 return WINED3DERR_INVALIDCALL;
5020 if (destFormat == WINED3DFMT_UNKNOWN) {
5021 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5022 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5024 /* Get the update surface description */
5025 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5028 /* Make sure the surface is loaded and up to date */
5029 IWineD3DSurface_PreLoad(pDestinationSurface);
5031 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5035 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5036 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
5037 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
5038 srcLeft = pSourceRect ? pSourceRect->left : 0;
5039 destLeft = pDestPoint ? pDestPoint->x : 0;
5040 destTop = pDestPoint ? pDestPoint->y : 0;
5043 /* This function doesn't support compressed textures
5044 the pitch is just bytesPerPixel * width */
5045 if(srcWidth != srcSurfaceWidth || srcLeft ){
5046 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5047 offset += srcLeft * pSrcSurface->bytesPerPixel;
5048 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5050 /* TODO DXT formats */
5052 if(pSourceRect != NULL && pSourceRect->top != 0){
5053 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5055 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5057 ,glDescription->level
5062 ,glDescription->glFormat
5063 ,glDescription->glType
5064 ,IWineD3DSurface_GetData(pSourceSurface)
5068 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5070 /* need to lock the surface to get the data */
5071 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5074 /* TODO: Cube and volume support */
5076 /* not a whole row so we have to do it a line at a time */
5079 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5080 const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5082 for(j = destTop ; j < (srcHeight + destTop) ; j++){
5084 glTexSubImage2D(glDescription->target
5085 ,glDescription->level
5090 ,glDescription->glFormat
5091 ,glDescription->glType
5092 ,data /* could be quicker using */
5097 } else { /* Full width, so just write out the whole texture */
5099 if (WINED3DFMT_DXT1 == destFormat ||
5100 WINED3DFMT_DXT2 == destFormat ||
5101 WINED3DFMT_DXT3 == destFormat ||
5102 WINED3DFMT_DXT4 == destFormat ||
5103 WINED3DFMT_DXT5 == destFormat) {
5104 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5105 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5106 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5107 FIXME("Updating part of a compressed texture is not supported at the moment\n");
5108 } if (destFormat != srcFormat) {
5109 FIXME("Updating mixed format compressed texture is not curretly support\n");
5111 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5112 glDescription->level,
5113 glDescription->glFormatInternal,
5118 IWineD3DSurface_GetData(pSourceSurface));
5121 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5126 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5128 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5129 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5130 data returned by GetData non-power2 width/height with hardware non-power2
5131 pow2Width/height are set to surface width height, repacking isn't needed so it
5132 doesn't matter which function gets called. */
5133 glTexSubImage2D(glDescription->target
5134 ,glDescription->level
5139 ,glDescription->glFormat
5140 ,glDescription->glType
5141 ,IWineD3DSurface_GetData(pSourceSurface)
5145 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5146 glTexSubImage2D(glDescription->target
5147 ,glDescription->level
5150 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5151 ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5152 ,glDescription->glFormat
5153 ,glDescription->glType
5154 ,IWineD3DSurface_GetData(pSourceSurface)
5160 checkGLcall("glTexSubImage2D");
5161 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
5163 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5164 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5165 * surface bigger than it needs to be hmm.. */
5166 if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5167 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5168 IWineD3DBaseTexture_Release(baseTexture);
5171 glDisable(textureDimensions); /* This needs to be managed better.... */
5177 /* Implementation details at http://developer.nvidia.com/attach/6494
5179 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5180 hmm.. no longer supported use
5181 OpenGL evaluators or tessellate surfaces within your application.
5184 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5185 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5186 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5187 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5188 FIXME("(%p) : Stub\n", This);
5193 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5194 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5195 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5196 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5197 FIXME("(%p) : Stub\n", This);
5201 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5203 TRACE("(%p) Handle(%d)\n", This, Handle);
5204 FIXME("(%p) : Stub\n", This);
5208 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5209 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5210 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5212 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
5214 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5215 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5216 return WINED3DERR_INVALIDCALL;
5219 /* Just forward this to the DirectDraw blitting engine */
5220 memset(&BltFx, 0, sizeof(BltFx));
5221 BltFx.dwSize = sizeof(BltFx);
5222 BltFx.u5.dwFillColor = color;
5223 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
5226 /* rendertarget and deptth stencil functions */
5227 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5228 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5230 if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5231 ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5232 return WINED3DERR_INVALIDCALL;
5235 *ppRenderTarget = This->render_targets[RenderTargetIndex];
5236 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5237 /* Note inc ref on returned surface */
5238 if(*ppRenderTarget != NULL)
5239 IWineD3DSurface_AddRef(*ppRenderTarget);
5243 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5244 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5245 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5246 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5247 IWineD3DSwapChainImpl *Swapchain;
5250 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5252 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5253 if(hr != WINED3D_OK) {
5254 ERR("Can't get the swapchain\n");
5258 /* Make sure to release the swapchain */
5259 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5261 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5262 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5263 return WINED3DERR_INVALIDCALL;
5265 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5266 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5267 return WINED3DERR_INVALIDCALL;
5270 if(Swapchain->frontBuffer != Front) {
5271 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5273 if(Swapchain->frontBuffer)
5274 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5275 Swapchain->frontBuffer = Front;
5277 if(Swapchain->frontBuffer) {
5278 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5282 if(Back && !Swapchain->backBuffer) {
5283 /* We need memory for the back buffer array - only one back buffer this way */
5284 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5285 if(!Swapchain->backBuffer) {
5286 ERR("Out of memory\n");
5287 return E_OUTOFMEMORY;
5291 if(Swapchain->backBuffer[0] != Back) {
5292 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5294 if(!Swapchain->backBuffer[0]) {
5295 /* GL was told to draw to the front buffer at creation,
5298 glDrawBuffer(GL_BACK);
5299 checkGLcall("glDrawBuffer(GL_BACK)");
5300 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5301 Swapchain->presentParms.BackBufferCount = 1;
5303 /* That makes problems - disable for now */
5304 /* glDrawBuffer(GL_FRONT); */
5305 checkGLcall("glDrawBuffer(GL_FRONT)");
5306 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5307 Swapchain->presentParms.BackBufferCount = 0;
5311 if(Swapchain->backBuffer[0])
5312 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5313 Swapchain->backBuffer[0] = Back;
5315 if(Swapchain->backBuffer[0]) {
5316 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5318 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5326 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5327 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5328 *ppZStencilSurface = This->depthStencilBuffer;
5329 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5331 if(*ppZStencilSurface != NULL) {
5332 /* Note inc ref on returned surface */
5333 IWineD3DSurface_AddRef(*ppZStencilSurface);
5338 static void bind_fbo(IWineD3DDevice *iface) {
5339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5342 GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5343 checkGLcall("glGenFramebuffersEXT()");
5345 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5346 checkGLcall("glBindFramebuffer()");
5349 /* TODO: Handle stencil attachments */
5350 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5352 IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5354 This->depth_copy_state = WINED3D_DCS_NO_COPY;
5358 if (depth_stencil_impl) {
5359 GLenum texttarget, target;
5360 GLint old_binding = 0;
5362 IWineD3DSurface_PreLoad(depth_stencil);
5363 texttarget = depth_stencil_impl->glDescription.target;
5364 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5366 glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5367 glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5368 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5369 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5370 glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5371 glBindTexture(target, old_binding);
5373 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5374 checkGLcall("glFramebufferTexture2DEXT()");
5376 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5377 checkGLcall("glFramebufferTexture2DEXT()");
5380 if (!This->render_offscreen) {
5381 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5382 checkGLcall("glBindFramebuffer()");
5386 void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5388 IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5390 if (idx >= GL_LIMITS(buffers)) {
5391 ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5397 GLenum texttarget, target;
5398 GLint old_binding = 0;
5400 IWineD3DSurface_PreLoad(render_target);
5401 texttarget = rtimpl->glDescription.target;
5402 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5404 glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5405 glBindTexture(target, rtimpl->glDescription.textureName);
5406 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5407 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5408 glBindTexture(target, old_binding);
5410 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5411 checkGLcall("glFramebufferTexture2DEXT()");
5413 This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5415 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5416 checkGLcall("glFramebufferTexture2DEXT()");
5418 This->draw_buffers[idx] = GL_NONE;
5421 if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5422 GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5423 checkGLcall("glDrawBuffers()");
5426 if (!This->render_offscreen) {
5427 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5428 checkGLcall("glBindFramebuffer()");
5432 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5434 WINED3DVIEWPORT viewport;
5436 TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5438 if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5439 ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5440 return WINED3DERR_INVALIDCALL;
5443 /* MSDN says that null disables the render target
5444 but a device must always be associated with a render target
5445 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5447 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5450 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5451 FIXME("Trying to set render target 0 to NULL\n");
5452 return WINED3DERR_INVALIDCALL;
5454 if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5455 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5456 return WINED3DERR_INVALIDCALL;
5459 /* If we are trying to set what we already have, don't bother */
5460 if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5461 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5464 if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5465 if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5466 This->render_targets[RenderTargetIndex] = pRenderTarget;
5468 /* Render target 0 is special */
5469 if(RenderTargetIndex == 0) {
5470 /* Finally, reset the viewport as the MSDN states. */
5471 viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5472 viewport.Width = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5475 viewport.MaxZ = 1.0f;
5476 viewport.MinZ = 0.0f;
5477 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5479 /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5481 * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5482 * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5484 ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5486 /* We only get more than 1 render target with fbos, so no need to check the offscreen rendering method */
5487 set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5492 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5493 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5494 HRESULT hr = WINED3D_OK;
5495 IWineD3DSurface *tmp;
5497 TRACE("(%p) Swapping z-buffer\n",This);
5499 if (pNewZStencil == This->stencilBufferTarget) {
5500 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5502 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5503 * depending on the renter target implementation being used.
5504 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5505 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5506 * stencil buffer and incure an extra memory overhead
5507 ******************************************************/
5510 tmp = This->stencilBufferTarget;
5511 This->stencilBufferTarget = pNewZStencil;
5512 /* should we be calling the parent or the wined3d surface? */
5513 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5514 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5516 /** TODO: glEnable/glDisable on depth/stencil depending on
5517 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5518 **********************************************************/
5519 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5520 set_depth_stencil_fbo(iface, pNewZStencil);
5527 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5528 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5530 /* TODO: the use of Impl is deprecated. */
5531 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5533 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5535 /* some basic validation checks */
5536 if(This->cursorTexture) {
5538 glDeleteTextures(1, &This->cursorTexture);
5540 This->cursorTexture = 0;
5544 /* MSDN: Cursor must be A8R8G8B8 */
5545 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5546 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5547 return WINED3DERR_INVALIDCALL;
5550 /* MSDN: Cursor must be smaller than the display mode */
5551 if(pSur->currentDesc.Width > This->ddraw_width ||
5552 pSur->currentDesc.Height > This->ddraw_height) {
5553 ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
5554 return WINED3DERR_INVALIDCALL;
5557 /* TODO: MSDN: Cursor sizes must be a power of 2 */
5558 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
5559 * Texture and Blitting code to draw the cursor
5561 pSur->Flags |= SFLAG_FORCELOAD;
5562 IWineD3DSurface_PreLoad(pCursorBitmap);
5563 pSur->Flags &= ~SFLAG_FORCELOAD;
5564 /* Do not store the surface's pointer because the application may release
5565 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5566 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5568 This->cursorTexture = pSur->glDescription.textureName;
5569 This->cursorWidth = pSur->currentDesc.Width;
5570 This->cursorHeight = pSur->currentDesc.Height;
5571 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
5574 This->xHotSpot = XHotSpot;
5575 This->yHotSpot = YHotSpot;
5579 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5580 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5581 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5583 This->xScreenSpace = XScreenSpace;
5584 This->yScreenSpace = YScreenSpace;
5590 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5592 BOOL oldVisible = This->bCursorVisible;
5593 TRACE("(%p) : visible(%d)\n", This, bShow);
5595 if(This->cursorTexture)
5596 This->bCursorVisible = bShow;
5601 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5602 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5603 TRACE("(%p) : state (%u)\n", This, This->state);
5604 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5605 switch (This->state) {
5608 case WINED3DERR_DEVICELOST:
5610 ResourceList *resourceList = This->resources;
5611 while (NULL != resourceList) {
5612 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5613 return WINED3DERR_DEVICENOTRESET;
5614 resourceList = resourceList->next;
5616 return WINED3DERR_DEVICELOST;
5618 case WINED3DERR_DRIVERINTERNALERROR:
5619 return WINED3DERR_DRIVERINTERNALERROR;
5623 return WINED3DERR_DRIVERINTERNALERROR;
5627 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5628 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5629 /** FIXME: Resource tracking needs to be done,
5630 * The closes we can do to this is set the priorities of all managed textures low
5631 * and then reset them.
5632 ***********************************************************/
5633 FIXME("(%p) : stub\n", This);
5637 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5638 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5639 if(surface->Flags & SFLAG_DIBSECTION) {
5640 /* Release the DC */
5641 SelectObject(surface->hDC, surface->dib.holdbitmap);
5642 DeleteDC(surface->hDC);
5643 /* Release the DIB section */
5644 DeleteObject(surface->dib.DIBsection);
5645 surface->dib.bitmap_data = NULL;
5646 surface->resource.allocatedMemory = NULL;
5647 surface->Flags &= ~SFLAG_DIBSECTION;
5649 surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
5650 surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
5651 if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
5652 surface->pow2Width = *pPresentationParameters->BackBufferWidth;
5653 surface->pow2Height = *pPresentationParameters->BackBufferHeight;
5655 surface->pow2Width = surface->pow2Height = 1;
5656 while (surface->pow2Width < *pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5657 while (surface->pow2Height < *pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5659 if(surface->glDescription.textureName) {
5661 glDeleteTextures(1, &surface->glDescription.textureName);
5663 surface->glDescription.textureName = 0;
5665 if(surface->pow2Width != *pPresentationParameters->BackBufferWidth ||
5666 surface->pow2Height != *pPresentationParameters->BackBufferHeight) {
5667 surface->Flags |= SFLAG_NONPOW2;
5669 surface->Flags &= ~SFLAG_NONPOW2;
5671 HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5672 surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5675 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5676 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5677 IWineD3DSwapChainImpl *swapchain;
5679 BOOL DisplayModeChanged = FALSE;
5680 WINED3DDISPLAYMODE mode;
5681 TRACE("(%p)\n", This);
5683 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5685 ERR("Failed to get the first implicit swapchain\n");
5689 /* Is it necessary to recreate the gl context? Actually every setting can be changed
5690 * on an existing gl context, so there's no real need for recreation.
5692 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5694 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5696 TRACE("New params:\n");
5697 TRACE("BackBufferWidth = %d\n", *pPresentationParameters->BackBufferWidth);
5698 TRACE("BackBufferHeight = %d\n", *pPresentationParameters->BackBufferHeight);
5699 TRACE("BackBufferFormat = %s\n", debug_d3dformat(*pPresentationParameters->BackBufferFormat));
5700 TRACE("BackBufferCount = %d\n", *pPresentationParameters->BackBufferCount);
5701 TRACE("MultiSampleType = %d\n", *pPresentationParameters->MultiSampleType);
5702 TRACE("MultiSampleQuality = %d\n", *pPresentationParameters->MultiSampleQuality);
5703 TRACE("SwapEffect = %d\n", *pPresentationParameters->SwapEffect);
5704 TRACE("hDeviceWindow = %p\n", *pPresentationParameters->hDeviceWindow);
5705 TRACE("Windowed = %s\n", *pPresentationParameters->Windowed ? "true" : "false");
5706 TRACE("EnableAutoDepthStencil = %s\n", *pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5707 TRACE("Flags = %08x\n", *pPresentationParameters->Flags);
5708 TRACE("FullScreen_RefreshRateInHz = %d\n", *pPresentationParameters->FullScreen_RefreshRateInHz);
5709 TRACE("PresentationInterval = %d\n", *pPresentationParameters->PresentationInterval);
5711 /* No special treatment of these parameters. Just store them */
5712 swapchain->presentParms.SwapEffect = *pPresentationParameters->SwapEffect;
5713 swapchain->presentParms.Flags = *pPresentationParameters->Flags;
5714 swapchain->presentParms.PresentationInterval = *pPresentationParameters->PresentationInterval;
5715 swapchain->presentParms.FullScreen_RefreshRateInHz = *pPresentationParameters->FullScreen_RefreshRateInHz;
5717 /* What to do about these? */
5718 if(*pPresentationParameters->BackBufferCount != 0 &&
5719 *pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5720 ERR("Cannot change the back buffer count yet\n");
5722 if(*pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5723 *pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5724 ERR("Cannot change the back buffer format yet\n");
5726 if(*pPresentationParameters->hDeviceWindow != NULL &&
5727 *pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5728 ERR("Cannot change the device window yet\n");
5730 if(*pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5731 ERR("What do do about a changed auto depth stencil parameter?\n");
5734 if(*pPresentationParameters->Windowed) {
5735 mode.Width = swapchain->orig_width;
5736 mode.Height = swapchain->orig_height;
5737 mode.RefreshRate = 0;
5738 mode.Format = swapchain->presentParms.BackBufferFormat;
5740 mode.Width = *pPresentationParameters->BackBufferWidth;
5741 mode.Height = *pPresentationParameters->BackBufferHeight;
5742 mode.RefreshRate = *pPresentationParameters->FullScreen_RefreshRateInHz;
5743 mode.Format = swapchain->presentParms.BackBufferFormat;
5746 /* Should Width == 800 && Height == 0 set 800x600? */
5747 if(*pPresentationParameters->BackBufferWidth != 0 && *pPresentationParameters->BackBufferHeight != 0 &&
5748 (*pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5749 *pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5756 vp.Width = *pPresentationParameters->BackBufferWidth;
5757 vp.Height = *pPresentationParameters->BackBufferHeight;
5761 if(!*pPresentationParameters->Windowed) {
5762 DisplayModeChanged = TRUE;
5764 swapchain->presentParms.BackBufferWidth = *pPresentationParameters->BackBufferWidth;
5765 swapchain->presentParms.BackBufferHeight = *pPresentationParameters->BackBufferHeight;
5767 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5768 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5769 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5772 /* Now set the new viewport */
5773 IWineD3DDevice_SetViewport(iface, &vp);
5776 if((*pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5777 (swapchain->presentParms.Windowed && !*pPresentationParameters->Windowed) ||
5778 DisplayModeChanged) {
5779 IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5782 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5786 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5788 /** FIXME: always true at the moment **/
5789 if(!bEnableDialogs) {
5790 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5796 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5798 TRACE("(%p) : pParameters %p\n", This, pParameters);
5800 *pParameters = This->createParms;
5804 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5805 IWineD3DSwapChain *swapchain;
5806 HRESULT hrc = WINED3D_OK;
5808 TRACE("Relaying to swapchain\n");
5810 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5811 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5812 IWineD3DSwapChain_Release(swapchain);
5817 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5818 IWineD3DSwapChain *swapchain;
5819 HRESULT hrc = WINED3D_OK;
5821 TRACE("Relaying to swapchain\n");
5823 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5824 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5825 IWineD3DSwapChain_Release(swapchain);
5831 /** ********************************************************
5832 * Notification functions
5833 ** ********************************************************/
5834 /** This function must be called in the release of a resource when ref == 0,
5835 * the contents of resource must still be correct,
5836 * any handels to other resource held by the caller must be closed
5837 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5838 *****************************************************/
5839 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5840 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5841 ResourceList* resourceList;
5843 TRACE("(%p) : resource %p\n", This, resource);
5845 EnterCriticalSection(&resourceStoreCriticalSection);
5847 /* add a new texture to the frot of the linked list */
5848 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5849 resourceList->resource = resource;
5851 /* Get the old head */
5852 resourceList->next = This->resources;
5854 This->resources = resourceList;
5855 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5858 LeaveCriticalSection(&resourceStoreCriticalSection);
5863 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5864 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5865 ResourceList* resourceList = NULL;
5866 ResourceList* previousResourceList = NULL;
5868 TRACE("(%p) : resource %p\n", This, resource);
5871 EnterCriticalSection(&resourceStoreCriticalSection);
5873 resourceList = This->resources;
5875 while (resourceList != NULL) {
5876 if(resourceList->resource == resource) break;
5877 previousResourceList = resourceList;
5878 resourceList = resourceList->next;
5881 if (resourceList == NULL) {
5882 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5884 LeaveCriticalSection(&resourceStoreCriticalSection);
5888 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5890 /* make sure we don't leave a hole in the list */
5891 if (previousResourceList != NULL) {
5892 previousResourceList->next = resourceList->next;
5894 This->resources = resourceList->next;
5898 LeaveCriticalSection(&resourceStoreCriticalSection);
5904 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5905 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5908 TRACE("(%p) : resource %p\n", This, resource);
5909 switch(IWineD3DResource_GetType(resource)){
5910 case WINED3DRTYPE_SURFACE:
5911 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5913 case WINED3DRTYPE_TEXTURE:
5914 case WINED3DRTYPE_CUBETEXTURE:
5915 case WINED3DRTYPE_VOLUMETEXTURE:
5916 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5917 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5918 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5919 This->stateBlock->textures[counter] = NULL;
5921 if (This->updateStateBlock != This->stateBlock ){
5922 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5923 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5924 This->updateStateBlock->textures[counter] = NULL;
5929 case WINED3DRTYPE_VOLUME:
5930 /* TODO: nothing really? */
5932 case WINED3DRTYPE_VERTEXBUFFER:
5933 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5936 TRACE("Cleaning up stream pointers\n");
5938 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5939 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5940 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5942 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5943 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5944 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5945 This->updateStateBlock->streamSource[streamNumber] = 0;
5946 /* Set changed flag? */
5949 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
5950 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5951 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5952 This->stateBlock->streamSource[streamNumber] = 0;
5955 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5956 else { /* This shouldn't happen */
5957 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5964 case WINED3DRTYPE_INDEXBUFFER:
5965 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5966 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5967 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5968 This->updateStateBlock->pIndexData = NULL;
5971 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5972 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5973 This->stateBlock->pIndexData = NULL;
5979 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5984 /* Remove the resoruce from the resourceStore */
5985 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5987 TRACE("Resource released\n");
5991 /**********************************************************
5992 * IWineD3DDevice VTbl follows
5993 **********************************************************/
5995 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5997 /*** IUnknown methods ***/
5998 IWineD3DDeviceImpl_QueryInterface,
5999 IWineD3DDeviceImpl_AddRef,
6000 IWineD3DDeviceImpl_Release,
6001 /*** IWineD3DDevice methods ***/
6002 IWineD3DDeviceImpl_GetParent,
6003 /*** Creation methods**/
6004 IWineD3DDeviceImpl_CreateVertexBuffer,
6005 IWineD3DDeviceImpl_CreateIndexBuffer,
6006 IWineD3DDeviceImpl_CreateStateBlock,
6007 IWineD3DDeviceImpl_CreateSurface,
6008 IWineD3DDeviceImpl_CreateTexture,
6009 IWineD3DDeviceImpl_CreateVolumeTexture,
6010 IWineD3DDeviceImpl_CreateVolume,
6011 IWineD3DDeviceImpl_CreateCubeTexture,
6012 IWineD3DDeviceImpl_CreateQuery,
6013 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6014 IWineD3DDeviceImpl_CreateVertexDeclaration,
6015 IWineD3DDeviceImpl_CreateVertexShader,
6016 IWineD3DDeviceImpl_CreatePixelShader,
6017 IWineD3DDeviceImpl_CreatePalette,
6018 /*** Odd functions **/
6019 IWineD3DDeviceImpl_Init3D,
6020 IWineD3DDeviceImpl_Uninit3D,
6021 IWineD3DDeviceImpl_SetFullscreen,
6022 IWineD3DDeviceImpl_EnumDisplayModes,
6023 IWineD3DDeviceImpl_EvictManagedResources,
6024 IWineD3DDeviceImpl_GetAvailableTextureMem,
6025 IWineD3DDeviceImpl_GetBackBuffer,
6026 IWineD3DDeviceImpl_GetCreationParameters,
6027 IWineD3DDeviceImpl_GetDeviceCaps,
6028 IWineD3DDeviceImpl_GetDirect3D,
6029 IWineD3DDeviceImpl_GetDisplayMode,
6030 IWineD3DDeviceImpl_SetDisplayMode,
6031 IWineD3DDeviceImpl_GetHWND,
6032 IWineD3DDeviceImpl_SetHWND,
6033 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6034 IWineD3DDeviceImpl_GetRasterStatus,
6035 IWineD3DDeviceImpl_GetSwapChain,
6036 IWineD3DDeviceImpl_Reset,
6037 IWineD3DDeviceImpl_SetDialogBoxMode,
6038 IWineD3DDeviceImpl_SetCursorProperties,
6039 IWineD3DDeviceImpl_SetCursorPosition,
6040 IWineD3DDeviceImpl_ShowCursor,
6041 IWineD3DDeviceImpl_TestCooperativeLevel,
6042 /*** Getters and setters **/
6043 IWineD3DDeviceImpl_SetClipPlane,
6044 IWineD3DDeviceImpl_GetClipPlane,
6045 IWineD3DDeviceImpl_SetClipStatus,
6046 IWineD3DDeviceImpl_GetClipStatus,
6047 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6048 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6049 IWineD3DDeviceImpl_SetDepthStencilSurface,
6050 IWineD3DDeviceImpl_GetDepthStencilSurface,
6051 IWineD3DDeviceImpl_SetFVF,
6052 IWineD3DDeviceImpl_GetFVF,
6053 IWineD3DDeviceImpl_SetGammaRamp,
6054 IWineD3DDeviceImpl_GetGammaRamp,
6055 IWineD3DDeviceImpl_SetIndices,
6056 IWineD3DDeviceImpl_GetIndices,
6057 IWineD3DDeviceImpl_SetBasevertexIndex,
6058 IWineD3DDeviceImpl_SetLight,
6059 IWineD3DDeviceImpl_GetLight,
6060 IWineD3DDeviceImpl_SetLightEnable,
6061 IWineD3DDeviceImpl_GetLightEnable,
6062 IWineD3DDeviceImpl_SetMaterial,
6063 IWineD3DDeviceImpl_GetMaterial,
6064 IWineD3DDeviceImpl_SetNPatchMode,
6065 IWineD3DDeviceImpl_GetNPatchMode,
6066 IWineD3DDeviceImpl_SetPaletteEntries,
6067 IWineD3DDeviceImpl_GetPaletteEntries,
6068 IWineD3DDeviceImpl_SetPixelShader,
6069 IWineD3DDeviceImpl_GetPixelShader,
6070 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6071 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6072 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6073 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6074 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6075 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6076 IWineD3DDeviceImpl_SetRenderState,
6077 IWineD3DDeviceImpl_GetRenderState,
6078 IWineD3DDeviceImpl_SetRenderTarget,
6079 IWineD3DDeviceImpl_GetRenderTarget,
6080 IWineD3DDeviceImpl_SetFrontBackBuffers,
6081 IWineD3DDeviceImpl_SetSamplerState,
6082 IWineD3DDeviceImpl_GetSamplerState,
6083 IWineD3DDeviceImpl_SetScissorRect,
6084 IWineD3DDeviceImpl_GetScissorRect,
6085 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6086 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6087 IWineD3DDeviceImpl_SetStreamSource,
6088 IWineD3DDeviceImpl_GetStreamSource,
6089 IWineD3DDeviceImpl_SetStreamSourceFreq,
6090 IWineD3DDeviceImpl_GetStreamSourceFreq,
6091 IWineD3DDeviceImpl_SetTexture,
6092 IWineD3DDeviceImpl_GetTexture,
6093 IWineD3DDeviceImpl_SetTextureStageState,
6094 IWineD3DDeviceImpl_GetTextureStageState,
6095 IWineD3DDeviceImpl_SetTransform,
6096 IWineD3DDeviceImpl_GetTransform,
6097 IWineD3DDeviceImpl_SetVertexDeclaration,
6098 IWineD3DDeviceImpl_GetVertexDeclaration,
6099 IWineD3DDeviceImpl_SetVertexShader,
6100 IWineD3DDeviceImpl_GetVertexShader,
6101 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6102 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6103 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6104 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6105 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6106 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6107 IWineD3DDeviceImpl_SetViewport,
6108 IWineD3DDeviceImpl_GetViewport,
6109 IWineD3DDeviceImpl_MultiplyTransform,
6110 IWineD3DDeviceImpl_ValidateDevice,
6111 IWineD3DDeviceImpl_ProcessVertices,
6112 /*** State block ***/
6113 IWineD3DDeviceImpl_BeginStateBlock,
6114 IWineD3DDeviceImpl_EndStateBlock,
6115 /*** Scene management ***/
6116 IWineD3DDeviceImpl_BeginScene,
6117 IWineD3DDeviceImpl_EndScene,
6118 IWineD3DDeviceImpl_Present,
6119 IWineD3DDeviceImpl_Clear,
6121 IWineD3DDeviceImpl_DrawPrimitive,
6122 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6123 IWineD3DDeviceImpl_DrawPrimitiveUP,
6124 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6125 IWineD3DDeviceImpl_DrawPrimitiveStrided,
6126 IWineD3DDeviceImpl_DrawRectPatch,
6127 IWineD3DDeviceImpl_DrawTriPatch,
6128 IWineD3DDeviceImpl_DeletePatch,
6129 IWineD3DDeviceImpl_ColorFill,
6130 IWineD3DDeviceImpl_UpdateTexture,
6131 IWineD3DDeviceImpl_UpdateSurface,
6132 IWineD3DDeviceImpl_GetFrontBufferData,
6133 IWineD3DDeviceImpl_SetupFullscreenWindow,
6134 IWineD3DDeviceImpl_RestoreWindow,
6135 /*** object tracking ***/
6136 IWineD3DDeviceImpl_ResourceReleased
6140 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6141 WINED3DRS_ALPHABLENDENABLE ,
6142 WINED3DRS_ALPHAFUNC ,
6143 WINED3DRS_ALPHAREF ,
6144 WINED3DRS_ALPHATESTENABLE ,
6146 WINED3DRS_COLORWRITEENABLE ,
6147 WINED3DRS_DESTBLEND ,
6148 WINED3DRS_DITHERENABLE ,
6149 WINED3DRS_FILLMODE ,
6150 WINED3DRS_FOGDENSITY ,
6152 WINED3DRS_FOGSTART ,
6153 WINED3DRS_LASTPIXEL ,
6154 WINED3DRS_SHADEMODE ,
6155 WINED3DRS_SRCBLEND ,
6156 WINED3DRS_STENCILENABLE ,
6157 WINED3DRS_STENCILFAIL ,
6158 WINED3DRS_STENCILFUNC ,
6159 WINED3DRS_STENCILMASK ,
6160 WINED3DRS_STENCILPASS ,
6161 WINED3DRS_STENCILREF ,
6162 WINED3DRS_STENCILWRITEMASK ,
6163 WINED3DRS_STENCILZFAIL ,
6164 WINED3DRS_TEXTUREFACTOR ,
6175 WINED3DRS_ZWRITEENABLE
6178 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6179 WINED3DTSS_ADDRESSW ,
6180 WINED3DTSS_ALPHAARG0 ,
6181 WINED3DTSS_ALPHAARG1 ,
6182 WINED3DTSS_ALPHAARG2 ,
6183 WINED3DTSS_ALPHAOP ,
6184 WINED3DTSS_BUMPENVLOFFSET ,
6185 WINED3DTSS_BUMPENVLSCALE ,
6186 WINED3DTSS_BUMPENVMAT00 ,
6187 WINED3DTSS_BUMPENVMAT01 ,
6188 WINED3DTSS_BUMPENVMAT10 ,
6189 WINED3DTSS_BUMPENVMAT11 ,
6190 WINED3DTSS_COLORARG0 ,
6191 WINED3DTSS_COLORARG1 ,
6192 WINED3DTSS_COLORARG2 ,
6193 WINED3DTSS_COLOROP ,
6194 WINED3DTSS_RESULTARG ,
6195 WINED3DTSS_TEXCOORDINDEX ,
6196 WINED3DTSS_TEXTURETRANSFORMFLAGS
6199 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6200 WINED3DSAMP_ADDRESSU ,
6201 WINED3DSAMP_ADDRESSV ,
6202 WINED3DSAMP_ADDRESSW ,
6203 WINED3DSAMP_BORDERCOLOR ,
6204 WINED3DSAMP_MAGFILTER ,
6205 WINED3DSAMP_MINFILTER ,
6206 WINED3DSAMP_MIPFILTER ,
6207 WINED3DSAMP_MIPMAPLODBIAS ,
6208 WINED3DSAMP_MAXMIPLEVEL ,
6209 WINED3DSAMP_MAXANISOTROPY ,
6210 WINED3DSAMP_SRGBTEXTURE ,
6211 WINED3DSAMP_ELEMENTINDEX
6214 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6216 WINED3DRS_AMBIENTMATERIALSOURCE ,
6217 WINED3DRS_CLIPPING ,
6218 WINED3DRS_CLIPPLANEENABLE ,
6219 WINED3DRS_COLORVERTEX ,
6220 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6221 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6222 WINED3DRS_FOGDENSITY ,
6224 WINED3DRS_FOGSTART ,
6225 WINED3DRS_FOGTABLEMODE ,
6226 WINED3DRS_FOGVERTEXMODE ,
6227 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6228 WINED3DRS_LIGHTING ,
6229 WINED3DRS_LOCALVIEWER ,
6230 WINED3DRS_MULTISAMPLEANTIALIAS ,
6231 WINED3DRS_MULTISAMPLEMASK ,
6232 WINED3DRS_NORMALIZENORMALS ,
6233 WINED3DRS_PATCHEDGESTYLE ,
6234 WINED3DRS_POINTSCALE_A ,
6235 WINED3DRS_POINTSCALE_B ,
6236 WINED3DRS_POINTSCALE_C ,
6237 WINED3DRS_POINTSCALEENABLE ,
6238 WINED3DRS_POINTSIZE ,
6239 WINED3DRS_POINTSIZE_MAX ,
6240 WINED3DRS_POINTSIZE_MIN ,
6241 WINED3DRS_POINTSPRITEENABLE ,
6242 WINED3DRS_RANGEFOGENABLE ,
6243 WINED3DRS_SPECULARMATERIALSOURCE ,
6244 WINED3DRS_TWEENFACTOR ,
6245 WINED3DRS_VERTEXBLEND
6248 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6249 WINED3DTSS_TEXCOORDINDEX ,
6250 WINED3DTSS_TEXTURETRANSFORMFLAGS
6253 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6254 WINED3DSAMP_DMAPOFFSET
6257 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6258 DWORD rep = StateTable[state].representative;
6262 WineD3DContext *context;
6265 for(i = 0; i < This->numContexts; i++) {
6266 context = This->contexts[i];
6267 if(isStateDirty(context, rep)) continue;
6269 context->dirtyArray[context->numDirtyEntries++] = rep;
6272 context->isStateDirty[idx] |= (1 << shift);