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-2008 Stefan Dösinger for CodeWeavers
10 * Copyright 2006-2008 Henri Verbeet
11 * Copyright 2007 Andrew Riedi
12 * Copyright 2009 Henri Verbeet for CodeWeavers
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
37 #define GLINFO_LOCATION This->adapter->gl_info
39 /* Define the default light parameters as specified by MSDN */
40 const WINED3DLIGHT WINED3D_default_light
= {
42 WINED3DLIGHT_DIRECTIONAL
, /* Type */
43 { 1.0f
, 1.0f
, 1.0f
, 0.0f
}, /* Diffuse r,g,b,a */
44 { 0.0f
, 0.0f
, 0.0f
, 0.0f
}, /* Specular r,g,b,a */
45 { 0.0f
, 0.0f
, 0.0f
, 0.0f
}, /* Ambient r,g,b,a, */
46 { 0.0f
, 0.0f
, 0.0f
}, /* Position x,y,z */
47 { 0.0f
, 0.0f
, 1.0f
}, /* Direction x,y,z */
50 0.0f
, 0.0f
, 0.0f
, /* Attenuation 0,1,2 */
55 /**********************************************************
56 * Global variable / Constants follow
57 **********************************************************/
58 const float identity
[] =
60 1.0f
, 0.0f
, 0.0f
, 0.0f
,
61 0.0f
, 1.0f
, 0.0f
, 0.0f
,
62 0.0f
, 0.0f
, 1.0f
, 0.0f
,
63 0.0f
, 0.0f
, 0.0f
, 1.0f
,
64 }; /* When needed for comparisons */
66 /* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
67 * actually have the same values in GL and D3D. */
68 static GLenum
gl_primitive_type_from_d3d(WINED3DPRIMITIVETYPE primitive_type
)
70 switch(primitive_type
)
72 case WINED3DPT_POINTLIST
:
75 case WINED3DPT_LINELIST
:
78 case WINED3DPT_LINESTRIP
:
81 case WINED3DPT_TRIANGLELIST
:
84 case WINED3DPT_TRIANGLESTRIP
:
85 return GL_TRIANGLE_STRIP
;
87 case WINED3DPT_TRIANGLEFAN
:
88 return GL_TRIANGLE_FAN
;
90 case WINED3DPT_LINELIST_ADJ
:
91 return GL_LINES_ADJACENCY_ARB
;
93 case WINED3DPT_LINESTRIP_ADJ
:
94 return GL_LINE_STRIP_ADJACENCY_ARB
;
96 case WINED3DPT_TRIANGLELIST_ADJ
:
97 return GL_TRIANGLES_ADJACENCY_ARB
;
99 case WINED3DPT_TRIANGLESTRIP_ADJ
:
100 return GL_TRIANGLE_STRIP_ADJACENCY_ARB
;
103 FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type
));
108 static WINED3DPRIMITIVETYPE
d3d_primitive_type_from_gl(GLenum primitive_type
)
110 switch(primitive_type
)
113 return WINED3DPT_POINTLIST
;
116 return WINED3DPT_LINELIST
;
119 return WINED3DPT_LINESTRIP
;
122 return WINED3DPT_TRIANGLELIST
;
124 case GL_TRIANGLE_STRIP
:
125 return WINED3DPT_TRIANGLESTRIP
;
127 case GL_TRIANGLE_FAN
:
128 return WINED3DPT_TRIANGLEFAN
;
130 case GL_LINES_ADJACENCY_ARB
:
131 return WINED3DPT_LINELIST_ADJ
;
133 case GL_LINE_STRIP_ADJACENCY_ARB
:
134 return WINED3DPT_LINESTRIP_ADJ
;
136 case GL_TRIANGLES_ADJACENCY_ARB
:
137 return WINED3DPT_TRIANGLELIST_ADJ
;
139 case GL_TRIANGLE_STRIP_ADJACENCY_ARB
:
140 return WINED3DPT_TRIANGLESTRIP_ADJ
;
143 FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type
));
144 return WINED3DPT_UNDEFINED
;
148 static BOOL
fixed_get_input(BYTE usage
, BYTE usage_idx
, unsigned int *regnum
)
150 if ((usage
== WINED3DDECLUSAGE_POSITION
|| usage
== WINED3DDECLUSAGE_POSITIONT
) && usage_idx
== 0)
151 *regnum
= WINED3D_FFP_POSITION
;
152 else if (usage
== WINED3DDECLUSAGE_BLENDWEIGHT
&& usage_idx
== 0)
153 *regnum
= WINED3D_FFP_BLENDWEIGHT
;
154 else if (usage
== WINED3DDECLUSAGE_BLENDINDICES
&& usage_idx
== 0)
155 *regnum
= WINED3D_FFP_BLENDINDICES
;
156 else if (usage
== WINED3DDECLUSAGE_NORMAL
&& usage_idx
== 0)
157 *regnum
= WINED3D_FFP_NORMAL
;
158 else if (usage
== WINED3DDECLUSAGE_PSIZE
&& usage_idx
== 0)
159 *regnum
= WINED3D_FFP_PSIZE
;
160 else if (usage
== WINED3DDECLUSAGE_COLOR
&& usage_idx
== 0)
161 *regnum
= WINED3D_FFP_DIFFUSE
;
162 else if (usage
== WINED3DDECLUSAGE_COLOR
&& usage_idx
== 1)
163 *regnum
= WINED3D_FFP_SPECULAR
;
164 else if (usage
== WINED3DDECLUSAGE_TEXCOORD
&& usage_idx
< WINED3DDP_MAXTEXCOORD
)
165 *regnum
= WINED3D_FFP_TEXCOORD0
+ usage_idx
;
168 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n", debug_d3ddeclusage(usage
), usage_idx
);
176 /* Context activation is done by the caller. */
177 void device_stream_info_from_declaration(IWineD3DDeviceImpl
*This
,
178 BOOL use_vshader
, struct wined3d_stream_info
*stream_info
, BOOL
*fixup
)
180 /* We need to deal with frequency data! */
181 IWineD3DVertexDeclarationImpl
*declaration
= (IWineD3DVertexDeclarationImpl
*)This
->stateBlock
->vertexDecl
;
182 UINT stream_count
= This
->stateBlock
->streamIsUP
? 0 : declaration
->num_streams
;
183 const DWORD
*streams
= declaration
->streams
;
186 stream_info
->use_map
= 0;
187 stream_info
->swizzle_map
= 0;
189 /* Check for transformed vertices, disable vertex shader if present. */
190 stream_info
->position_transformed
= declaration
->position_transformed
;
191 if (declaration
->position_transformed
) use_vshader
= FALSE
;
193 /* Translate the declaration into strided data. */
194 for (i
= 0; i
< declaration
->element_count
; ++i
)
196 const struct wined3d_vertex_declaration_element
*element
= &declaration
->elements
[i
];
197 GLuint buffer_object
= 0;
198 const BYTE
*data
= NULL
;
203 TRACE("%p Element %p (%u of %u)\n", declaration
->elements
,
204 element
, i
+ 1, declaration
->element_count
);
206 if (!This
->stateBlock
->streamSource
[element
->input_slot
]) continue;
208 stride
= This
->stateBlock
->streamStride
[element
->input_slot
];
209 if (This
->stateBlock
->streamIsUP
)
211 TRACE("Stream %u is UP, %p\n", element
->input_slot
, This
->stateBlock
->streamSource
[element
->input_slot
]);
213 data
= (BYTE
*)This
->stateBlock
->streamSource
[element
->input_slot
];
217 TRACE("Stream %u isn't UP, %p\n", element
->input_slot
, This
->stateBlock
->streamSource
[element
->input_slot
]);
218 data
= buffer_get_memory(This
->stateBlock
->streamSource
[element
->input_slot
], 0, &buffer_object
);
220 /* Can't use vbo's if the base vertex index is negative. OpenGL doesn't accept negative offsets
221 * (or rather offsets bigger than the vbo, because the pointer is unsigned), so use system memory
222 * sources. In most sane cases the pointer - offset will still be > 0, otherwise it will wrap
223 * around to some big value. Hope that with the indices, the driver wraps it back internally. If
224 * not, drawStridedSlow is needed, including a vertex buffer path. */
225 if (This
->stateBlock
->loadBaseVertexIndex
< 0)
227 WARN("loadBaseVertexIndex is < 0 (%d), not using vbos\n", This
->stateBlock
->loadBaseVertexIndex
);
229 data
= buffer_get_sysmem((struct wined3d_buffer
*)This
->stateBlock
->streamSource
[element
->input_slot
]);
230 if ((UINT_PTR
)data
< -This
->stateBlock
->loadBaseVertexIndex
* stride
)
232 FIXME("System memory vertex data load offset is negative!\n");
238 if (buffer_object
) *fixup
= TRUE
;
239 else if (*fixup
&& !use_vshader
240 && (element
->usage
== WINED3DDECLUSAGE_COLOR
241 || element
->usage
== WINED3DDECLUSAGE_POSITIONT
))
243 static BOOL warned
= FALSE
;
246 /* This may be bad with the fixed function pipeline. */
247 FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
253 data
+= element
->offset
;
255 TRACE("offset %u input_slot %u usage_idx %d\n", element
->offset
, element
->input_slot
, element
->usage_idx
);
259 if (element
->output_slot
== ~0U)
261 /* TODO: Assuming vertexdeclarations are usually used with the
262 * same or a similar shader, it might be worth it to store the
263 * last used output slot and try that one first. */
264 stride_used
= vshader_get_input(This
->stateBlock
->vertexShader
,
265 element
->usage
, element
->usage_idx
, &idx
);
269 idx
= element
->output_slot
;
275 if (!element
->ffp_valid
)
277 WARN("Skipping unsupported fixed function element of format %s and usage %s\n",
278 debug_d3dformat(element
->format_desc
->format
), debug_d3ddeclusage(element
->usage
));
283 stride_used
= fixed_get_input(element
->usage
, element
->usage_idx
, &idx
);
289 TRACE("Load %s array %u [usage %s, usage_idx %u, "
290 "input_slot %u, offset %u, stride %u, format %s, buffer_object %u]\n",
291 use_vshader
? "shader": "fixed function", idx
,
292 debug_d3ddeclusage(element
->usage
), element
->usage_idx
, element
->input_slot
,
293 element
->offset
, stride
, debug_d3dformat(element
->format_desc
->format
), buffer_object
);
295 stream_info
->elements
[idx
].format_desc
= element
->format_desc
;
296 stream_info
->elements
[idx
].stride
= stride
;
297 stream_info
->elements
[idx
].data
= data
;
298 stream_info
->elements
[idx
].stream_idx
= element
->input_slot
;
299 stream_info
->elements
[idx
].buffer_object
= buffer_object
;
301 if (!This
->adapter
->gl_info
.supported
[EXT_VERTEX_ARRAY_BGRA
]
302 && element
->format_desc
->format
== WINED3DFMT_B8G8R8A8_UNORM
)
304 stream_info
->swizzle_map
|= 1 << idx
;
306 stream_info
->use_map
|= 1 << idx
;
310 /* Now call PreLoad on all the vertex buffers. In the very rare case
311 * that the buffers stopps converting PreLoad will dirtify the VDECL again.
312 * The vertex buffer can now use the strided structure in the device instead of finding its
315 * NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
317 for (i
= 0; i
< stream_count
; ++i
)
319 IWineD3DBuffer
*vb
= This
->stateBlock
->streamSource
[streams
[i
]];
320 if (vb
) IWineD3DBuffer_PreLoad(vb
);
324 static void stream_info_element_from_strided(const struct wined3d_gl_info
*gl_info
,
325 const struct WineDirect3DStridedData
*strided
, struct wined3d_stream_info_element
*e
)
327 const struct GlPixelFormatDesc
*format_desc
= getFormatDescEntry(strided
->format
, gl_info
);
328 e
->format_desc
= format_desc
;
329 e
->stride
= strided
->dwStride
;
330 e
->data
= strided
->lpData
;
332 e
->buffer_object
= 0;
335 void device_stream_info_from_strided(const struct wined3d_gl_info
*gl_info
,
336 const struct WineDirect3DVertexStridedData
*strided
, struct wined3d_stream_info
*stream_info
)
340 memset(stream_info
, 0, sizeof(*stream_info
));
342 if (strided
->position
.lpData
)
343 stream_info_element_from_strided(gl_info
, &strided
->position
, &stream_info
->elements
[WINED3D_FFP_POSITION
]);
344 if (strided
->normal
.lpData
)
345 stream_info_element_from_strided(gl_info
, &strided
->normal
, &stream_info
->elements
[WINED3D_FFP_NORMAL
]);
346 if (strided
->diffuse
.lpData
)
347 stream_info_element_from_strided(gl_info
, &strided
->diffuse
, &stream_info
->elements
[WINED3D_FFP_DIFFUSE
]);
348 if (strided
->specular
.lpData
)
349 stream_info_element_from_strided(gl_info
, &strided
->specular
, &stream_info
->elements
[WINED3D_FFP_SPECULAR
]);
351 for (i
= 0; i
< WINED3DDP_MAXTEXCOORD
; ++i
)
353 if (strided
->texCoords
[i
].lpData
)
354 stream_info_element_from_strided(gl_info
, &strided
->texCoords
[i
],
355 &stream_info
->elements
[WINED3D_FFP_TEXCOORD0
+ i
]);
358 stream_info
->position_transformed
= strided
->position_transformed
;
360 for (i
= 0; i
< sizeof(stream_info
->elements
) / sizeof(*stream_info
->elements
); ++i
)
362 if (!stream_info
->elements
[i
].format_desc
) continue;
364 if (!gl_info
->supported
[EXT_VERTEX_ARRAY_BGRA
]
365 && stream_info
->elements
[i
].format_desc
->format
== WINED3DFMT_B8G8R8A8_UNORM
)
367 stream_info
->swizzle_map
|= 1 << i
;
369 stream_info
->use_map
|= 1 << i
;
373 /**********************************************************
374 * IUnknown parts follows
375 **********************************************************/
377 static HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
,REFIID riid
,LPVOID
*ppobj
)
379 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
381 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
382 if (IsEqualGUID(riid
, &IID_IUnknown
)
383 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
384 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
385 IUnknown_AddRef(iface
);
390 return E_NOINTERFACE
;
393 static ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
394 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
395 ULONG refCount
= InterlockedIncrement(&This
->ref
);
397 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
401 static ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
402 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
403 ULONG refCount
= InterlockedDecrement(&This
->ref
);
405 TRACE("(%p) : Releasing from %d\n", This
, refCount
+ 1);
410 for (i
= 0; i
< sizeof(This
->multistate_funcs
)/sizeof(This
->multistate_funcs
[0]); ++i
) {
411 HeapFree(GetProcessHeap(), 0, This
->multistate_funcs
[i
]);
412 This
->multistate_funcs
[i
] = NULL
;
415 /* TODO: Clean up all the surfaces and textures! */
416 /* NOTE: You must release the parent if the object was created via a callback
417 ** ***************************/
419 if (!list_empty(&This
->resources
)) {
420 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This
);
421 dumpResources(&This
->resources
);
424 if(This
->contexts
) ERR("Context array not freed!\n");
425 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
426 This
->haveHardwareCursor
= FALSE
;
428 IWineD3D_Release(This
->wined3d
);
429 This
->wined3d
= NULL
;
430 HeapFree(GetProcessHeap(), 0, This
);
431 TRACE("Freed device %p\n", This
);
437 /**********************************************************
438 * IWineD3DDevice implementation follows
439 **********************************************************/
440 static HRESULT WINAPI
IWineD3DDeviceImpl_GetParent(IWineD3DDevice
*iface
, IUnknown
**pParent
) {
441 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
442 *pParent
= This
->parent
;
443 IUnknown_AddRef(This
->parent
);
447 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice
*iface
, struct wined3d_buffer_desc
*desc
,
448 const void *data
, IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
, IWineD3DBuffer
**buffer
)
450 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
451 struct wined3d_buffer
*object
;
454 TRACE("iface %p, desc %p, data %p, parent %p, buffer %p\n", iface
, desc
, data
, parent
, buffer
);
456 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
459 ERR("Failed to allocate memory\n");
460 return E_OUTOFMEMORY
;
463 FIXME("Ignoring access flags (pool)\n");
465 hr
= buffer_init(object
, This
, desc
->byte_width
, desc
->usage
, WINED3DFMT_UNKNOWN
,
466 WINED3DPOOL_MANAGED
, GL_ARRAY_BUFFER_ARB
, data
, parent
, parent_ops
);
469 WARN("Failed to initialize buffer, hr %#x.\n", hr
);
470 HeapFree(GetProcessHeap(), 0, object
);
473 object
->desc
= *desc
;
475 TRACE("Created buffer %p.\n", object
);
477 *buffer
= (IWineD3DBuffer
*)object
;
482 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
,
483 UINT Size
, DWORD Usage
, WINED3DPOOL Pool
, IWineD3DBuffer
**ppVertexBuffer
,
484 IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
)
486 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
487 struct wined3d_buffer
*object
;
490 TRACE("iface %p, size %u, usage %#x, pool %#x, buffer %p, parent %p, parent_ops %p.\n",
491 iface
, Size
, Usage
, Pool
, ppVertexBuffer
, parent
, parent_ops
);
493 if (Pool
== WINED3DPOOL_SCRATCH
)
495 /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
496 * anyway, SCRATCH vertex buffers aren't usable anywhere
498 WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n");
499 *ppVertexBuffer
= NULL
;
500 return WINED3DERR_INVALIDCALL
;
503 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
506 ERR("Out of memory\n");
507 *ppVertexBuffer
= NULL
;
508 return WINED3DERR_OUTOFVIDEOMEMORY
;
511 hr
= buffer_init(object
, This
, Size
, Usage
, WINED3DFMT_VERTEXDATA
,
512 Pool
, GL_ARRAY_BUFFER_ARB
, NULL
, parent
, parent_ops
);
515 WARN("Failed to initialize buffer, hr %#x.\n", hr
);
516 HeapFree(GetProcessHeap(), 0, object
);
520 TRACE("Created buffer %p.\n", object
);
521 *ppVertexBuffer
= (IWineD3DBuffer
*)object
;
526 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
,
527 UINT Length
, DWORD Usage
, WINED3DPOOL Pool
, IWineD3DBuffer
**ppIndexBuffer
,
528 IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
)
530 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
531 struct wined3d_buffer
*object
;
534 TRACE("(%p) Creating index buffer\n", This
);
536 /* Allocate the storage for the device */
537 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
540 ERR("Out of memory\n");
541 *ppIndexBuffer
= NULL
;
542 return WINED3DERR_OUTOFVIDEOMEMORY
;
545 hr
= buffer_init(object
, This
, Length
, Usage
| WINED3DUSAGE_STATICDECL
,
546 WINED3DFMT_UNKNOWN
, Pool
, GL_ELEMENT_ARRAY_BUFFER_ARB
, NULL
,
550 WARN("Failed to initialize buffer, hr %#x\n", hr
);
551 HeapFree(GetProcessHeap(), 0, object
);
555 TRACE("Created buffer %p.\n", object
);
557 *ppIndexBuffer
= (IWineD3DBuffer
*) object
;
562 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
*iface
,
563 WINED3DSTATEBLOCKTYPE type
, IWineD3DStateBlock
**stateblock
, IUnknown
*parent
)
565 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
566 IWineD3DStateBlockImpl
*object
;
569 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
572 ERR("Failed to allocate stateblock memory.\n");
573 return E_OUTOFMEMORY
;
576 hr
= stateblock_init(object
, This
, type
);
579 WARN("Failed to initialize stateblock, hr %#x.\n", hr
);
580 HeapFree(GetProcessHeap(), 0, object
);
584 TRACE("Created stateblock %p.\n", object
);
585 *stateblock
= (IWineD3DStateBlock
*)object
;
590 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice
*iface
, UINT Width
, UINT Height
,
591 WINED3DFORMAT Format
, BOOL Lockable
, BOOL Discard
, UINT Level
, IWineD3DSurface
**ppSurface
,
592 DWORD Usage
, WINED3DPOOL Pool
, WINED3DMULTISAMPLE_TYPE MultiSample
, DWORD MultisampleQuality
,
593 WINED3DSURFTYPE Impl
, IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
)
595 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
596 IWineD3DSurfaceImpl
*object
;
599 TRACE("(%p) Create surface\n",This
);
601 if (Impl
== SURFACE_OPENGL
&& !This
->adapter
)
603 ERR("OpenGL surfaces are not available without OpenGL.\n");
604 return WINED3DERR_NOTAVAILABLE
;
607 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
610 ERR("Failed to allocate surface memory.\n");
611 return WINED3DERR_OUTOFVIDEOMEMORY
;
614 hr
= surface_init(object
, Impl
, This
->surface_alignment
, Width
, Height
, Level
, Lockable
,
615 Discard
, MultiSample
, MultisampleQuality
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
618 WARN("Failed to initialize surface, returning %#x.\n", hr
);
619 HeapFree(GetProcessHeap(), 0, object
);
623 TRACE("(%p) : Created surface %p\n", This
, object
);
625 *ppSurface
= (IWineD3DSurface
*)object
;
630 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice
*iface
,
631 IWineD3DResource
*resource
, IUnknown
*parent
, IWineD3DRendertargetView
**rendertarget_view
)
633 struct wined3d_rendertarget_view
*object
;
635 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
638 ERR("Failed to allocate memory\n");
639 return E_OUTOFMEMORY
;
642 object
->vtbl
= &wined3d_rendertarget_view_vtbl
;
643 object
->refcount
= 1;
644 IWineD3DResource_AddRef(resource
);
645 object
->resource
= resource
;
646 object
->parent
= parent
;
648 *rendertarget_view
= (IWineD3DRendertargetView
*)object
;
653 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
,
654 UINT Width
, UINT Height
, UINT Levels
, DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
655 IWineD3DTexture
**ppTexture
, IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
)
657 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
658 IWineD3DTextureImpl
*object
;
661 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This
, Width
, Height
, Levels
, Usage
);
662 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, parent %p\n",
663 Format
, debug_d3dformat(Format
), Pool
, ppTexture
, parent
);
665 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
668 ERR("Out of memory\n");
670 return WINED3DERR_OUTOFVIDEOMEMORY
;
673 hr
= texture_init(object
, Width
, Height
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
676 WARN("Failed to initialize texture, returning %#x\n", hr
);
677 HeapFree(GetProcessHeap(), 0, object
);
682 *ppTexture
= (IWineD3DTexture
*)object
;
684 TRACE("(%p) : Created texture %p\n", This
, object
);
689 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
690 UINT Width
, UINT Height
, UINT Depth
, UINT Levels
, DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
,
691 IWineD3DVolumeTexture
**ppVolumeTexture
, IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
)
693 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
694 IWineD3DVolumeTextureImpl
*object
;
697 TRACE("(%p) : W(%u) H(%u) D(%u), Lvl(%u) Usage(%#x), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
698 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
700 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
703 ERR("Out of memory\n");
704 *ppVolumeTexture
= NULL
;
705 return WINED3DERR_OUTOFVIDEOMEMORY
;
708 hr
= volumetexture_init(object
, Width
, Height
, Depth
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
711 WARN("Failed to initialize volumetexture, returning %#x\n", hr
);
712 HeapFree(GetProcessHeap(), 0, object
);
713 *ppVolumeTexture
= NULL
;
717 TRACE("(%p) : Created volume texture %p.\n", This
, object
);
718 *ppVolumeTexture
= (IWineD3DVolumeTexture
*)object
;
723 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
, UINT Width
, UINT Height
,
724 UINT Depth
, DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
, IWineD3DVolume
**ppVolume
,
725 IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
)
727 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
728 IWineD3DVolumeImpl
*object
;
731 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
732 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
734 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
737 ERR("Out of memory\n");
739 return WINED3DERR_OUTOFVIDEOMEMORY
;
742 hr
= volume_init(object
, This
, Width
, Height
, Depth
, Usage
, Format
, Pool
, parent
, parent_ops
);
745 WARN("Failed to initialize volume, returning %#x.\n", hr
);
746 HeapFree(GetProcessHeap(), 0, object
);
750 TRACE("(%p) : Created volume %p.\n", This
, object
);
751 *ppVolume
= (IWineD3DVolume
*)object
;
756 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
, UINT EdgeLength
, UINT Levels
,
757 DWORD Usage
, WINED3DFORMAT Format
, WINED3DPOOL Pool
, IWineD3DCubeTexture
**ppCubeTexture
,
758 IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
)
760 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
761 IWineD3DCubeTextureImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
764 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
767 ERR("Out of memory\n");
768 *ppCubeTexture
= NULL
;
769 return WINED3DERR_OUTOFVIDEOMEMORY
;
772 hr
= cubetexture_init(object
, EdgeLength
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
775 WARN("Failed to initialize cubetexture, returning %#x\n", hr
);
776 HeapFree(GetProcessHeap(), 0, object
);
777 *ppCubeTexture
= NULL
;
781 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
782 *ppCubeTexture
= (IWineD3DCubeTexture
*)object
;
787 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
,
788 WINED3DQUERYTYPE type
, IWineD3DQuery
**query
, IUnknown
*parent
)
790 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
791 IWineD3DQueryImpl
*object
;
794 TRACE("iface %p, type %#x, query %p, parent %p.\n", iface
, type
, query
, parent
);
796 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
799 ERR("Failed to allocate query memory.\n");
800 return E_OUTOFMEMORY
;
803 hr
= query_init(object
, This
, type
, parent
);
806 WARN("Failed to initialize query, hr %#x.\n", hr
);
807 HeapFree(GetProcessHeap(), 0, object
);
811 TRACE("Created query %p.\n", object
);
812 *query
= (IWineD3DQuery
*)object
;
817 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice
*iface
,
818 WINED3DPRESENT_PARAMETERS
*present_parameters
, IWineD3DSwapChain
**swapchain
,
819 IUnknown
*parent
, WINED3DSURFTYPE surface_type
)
821 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
822 IWineD3DSwapChainImpl
*object
;
825 TRACE("iface %p, present_parameters %p, swapchain %p, parent %p, surface_type %#x.\n",
826 iface
, present_parameters
, swapchain
, parent
, surface_type
);
828 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
831 ERR("Failed to allocate swapchain memory.\n");
832 return E_OUTOFMEMORY
;
835 hr
= swapchain_init(object
, surface_type
, This
, present_parameters
, parent
);
838 WARN("Failed to initialize swapchain, hr %#x.\n", hr
);
839 HeapFree(GetProcessHeap(), 0, object
);
843 TRACE("Created swapchain %p.\n", object
);
844 *swapchain
= (IWineD3DSwapChain
*)object
;
849 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
850 static UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
) {
851 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
852 TRACE("(%p)\n", This
);
854 return This
->NumberOfSwapChains
;
857 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
, UINT iSwapChain
, IWineD3DSwapChain
**pSwapChain
) {
858 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
859 TRACE("(%p) : swapchain %d\n", This
, iSwapChain
);
861 if(iSwapChain
< This
->NumberOfSwapChains
) {
862 *pSwapChain
= This
->swapchains
[iSwapChain
];
863 IWineD3DSwapChain_AddRef(*pSwapChain
);
864 TRACE("(%p) returning %p\n", This
, *pSwapChain
);
867 TRACE("Swapchain out of range\n");
869 return WINED3DERR_INVALIDCALL
;
873 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
*iface
,
874 IWineD3DVertexDeclaration
**declaration
, IUnknown
*parent
, const struct wined3d_parent_ops
*parent_ops
,
875 const WINED3DVERTEXELEMENT
*elements
, UINT element_count
)
877 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
878 IWineD3DVertexDeclarationImpl
*object
= NULL
;
881 TRACE("iface %p, declaration %p, parent %p, elements %p, element_count %u.\n",
882 iface
, declaration
, parent
, elements
, element_count
);
884 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
887 ERR("Failed to allocate vertex declaration memory.\n");
888 return E_OUTOFMEMORY
;
891 hr
= vertexdeclaration_init(object
, This
, elements
, element_count
, parent
, parent_ops
);
894 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr
);
895 HeapFree(GetProcessHeap(), 0, object
);
899 TRACE("Created vertex declaration %p.\n", object
);
900 *declaration
= (IWineD3DVertexDeclaration
*)object
;
905 static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl
*This
, /* For the GL info, which has the type table */
906 DWORD fvf
, WINED3DVERTEXELEMENT
** ppVertexElements
) {
908 unsigned int idx
, idx2
;
910 BOOL has_pos
= (fvf
& WINED3DFVF_POSITION_MASK
) != 0;
911 BOOL has_blend
= (fvf
& WINED3DFVF_XYZB5
) > WINED3DFVF_XYZRHW
;
912 BOOL has_blend_idx
= has_blend
&&
913 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB5
) ||
914 (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
) ||
915 (fvf
& WINED3DFVF_LASTBETA_UBYTE4
));
916 BOOL has_normal
= (fvf
& WINED3DFVF_NORMAL
) != 0;
917 BOOL has_psize
= (fvf
& WINED3DFVF_PSIZE
) != 0;
918 BOOL has_diffuse
= (fvf
& WINED3DFVF_DIFFUSE
) != 0;
919 BOOL has_specular
= (fvf
& WINED3DFVF_SPECULAR
) !=0;
921 DWORD num_textures
= (fvf
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
922 DWORD texcoords
= (fvf
& 0xFFFF0000) >> 16;
923 WINED3DVERTEXELEMENT
*elements
= NULL
;
926 DWORD num_blends
= 1 + (((fvf
& WINED3DFVF_XYZB5
) - WINED3DFVF_XYZB1
) >> 1);
927 if (has_blend_idx
) num_blends
--;
929 /* Compute declaration size */
930 size
= has_pos
+ (has_blend
&& num_blends
> 0) + has_blend_idx
+ has_normal
+
931 has_psize
+ has_diffuse
+ has_specular
+ num_textures
;
933 /* convert the declaration */
934 elements
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WINED3DVERTEXELEMENT
));
935 if (!elements
) return ~0U;
939 if (!has_blend
&& (fvf
& WINED3DFVF_XYZRHW
)) {
940 elements
[idx
].format
= WINED3DFMT_R32G32B32A32_FLOAT
;
941 elements
[idx
].usage
= WINED3DDECLUSAGE_POSITIONT
;
943 else if ((fvf
& WINED3DFVF_XYZW
) == WINED3DFVF_XYZW
) {
944 elements
[idx
].format
= WINED3DFMT_R32G32B32A32_FLOAT
;
945 elements
[idx
].usage
= WINED3DDECLUSAGE_POSITION
;
948 elements
[idx
].format
= WINED3DFMT_R32G32B32_FLOAT
;
949 elements
[idx
].usage
= WINED3DDECLUSAGE_POSITION
;
951 elements
[idx
].usage_idx
= 0;
954 if (has_blend
&& (num_blends
> 0)) {
955 if (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
) && (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
))
956 elements
[idx
].format
= WINED3DFMT_B8G8R8A8_UNORM
;
959 case 1: elements
[idx
].format
= WINED3DFMT_R32_FLOAT
; break;
960 case 2: elements
[idx
].format
= WINED3DFMT_R32G32_FLOAT
; break;
961 case 3: elements
[idx
].format
= WINED3DFMT_R32G32B32_FLOAT
; break;
962 case 4: elements
[idx
].format
= WINED3DFMT_R32G32B32A32_FLOAT
; break;
964 ERR("Unexpected amount of blend values: %u\n", num_blends
);
967 elements
[idx
].usage
= WINED3DDECLUSAGE_BLENDWEIGHT
;
968 elements
[idx
].usage_idx
= 0;
972 if (fvf
& WINED3DFVF_LASTBETA_UBYTE4
||
973 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
) && (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)))
974 elements
[idx
].format
= WINED3DFMT_R8G8B8A8_UINT
;
975 else if (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)
976 elements
[idx
].format
= WINED3DFMT_B8G8R8A8_UNORM
;
978 elements
[idx
].format
= WINED3DFMT_R32_FLOAT
;
979 elements
[idx
].usage
= WINED3DDECLUSAGE_BLENDINDICES
;
980 elements
[idx
].usage_idx
= 0;
984 elements
[idx
].format
= WINED3DFMT_R32G32B32_FLOAT
;
985 elements
[idx
].usage
= WINED3DDECLUSAGE_NORMAL
;
986 elements
[idx
].usage_idx
= 0;
990 elements
[idx
].format
= WINED3DFMT_R32_FLOAT
;
991 elements
[idx
].usage
= WINED3DDECLUSAGE_PSIZE
;
992 elements
[idx
].usage_idx
= 0;
996 elements
[idx
].format
= WINED3DFMT_B8G8R8A8_UNORM
;
997 elements
[idx
].usage
= WINED3DDECLUSAGE_COLOR
;
998 elements
[idx
].usage_idx
= 0;
1002 elements
[idx
].format
= WINED3DFMT_B8G8R8A8_UNORM
;
1003 elements
[idx
].usage
= WINED3DDECLUSAGE_COLOR
;
1004 elements
[idx
].usage_idx
= 1;
1007 for (idx2
= 0; idx2
< num_textures
; idx2
++) {
1008 unsigned int numcoords
= (texcoords
>> (idx2
*2)) & 0x03;
1009 switch (numcoords
) {
1010 case WINED3DFVF_TEXTUREFORMAT1
:
1011 elements
[idx
].format
= WINED3DFMT_R32_FLOAT
;
1013 case WINED3DFVF_TEXTUREFORMAT2
:
1014 elements
[idx
].format
= WINED3DFMT_R32G32_FLOAT
;
1016 case WINED3DFVF_TEXTUREFORMAT3
:
1017 elements
[idx
].format
= WINED3DFMT_R32G32B32_FLOAT
;
1019 case WINED3DFVF_TEXTUREFORMAT4
:
1020 elements
[idx
].format
= WINED3DFMT_R32G32B32A32_FLOAT
;
1023 elements
[idx
].usage
= WINED3DDECLUSAGE_TEXCOORD
;
1024 elements
[idx
].usage_idx
= idx2
;
1028 /* Now compute offsets, and initialize the rest of the fields */
1029 for (idx
= 0, offset
= 0; idx
< size
; ++idx
)
1031 const struct GlPixelFormatDesc
*format_desc
= getFormatDescEntry(elements
[idx
].format
, &This
->adapter
->gl_info
);
1032 elements
[idx
].input_slot
= 0;
1033 elements
[idx
].method
= WINED3DDECLMETHOD_DEFAULT
;
1034 elements
[idx
].offset
= offset
;
1035 offset
+= format_desc
->component_count
* format_desc
->component_size
;
1038 *ppVertexElements
= elements
;
1042 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice
*iface
,
1043 IWineD3DVertexDeclaration
**declaration
, IUnknown
*parent
,
1044 const struct wined3d_parent_ops
*parent_ops
, DWORD fvf
)
1046 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1047 WINED3DVERTEXELEMENT
*elements
;
1051 TRACE("iface %p, declaration %p, parent %p, fvf %#x.\n", iface
, declaration
, parent
, fvf
);
1053 size
= ConvertFvfToDeclaration(This
, fvf
, &elements
);
1054 if (size
== ~0U) return E_OUTOFMEMORY
;
1056 hr
= IWineD3DDevice_CreateVertexDeclaration(iface
, declaration
, parent
, parent_ops
, elements
, size
);
1057 HeapFree(GetProcessHeap(), 0, elements
);
1061 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
*iface
,
1062 const DWORD
*pFunction
, const struct wined3d_shader_signature
*output_signature
,
1063 IWineD3DVertexShader
**ppVertexShader
, IUnknown
*parent
,
1064 const struct wined3d_parent_ops
*parent_ops
)
1066 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1067 IWineD3DVertexShaderImpl
*object
;
1070 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1073 ERR("Failed to allocate shader memory.\n");
1074 return E_OUTOFMEMORY
;
1077 hr
= vertexshader_init(object
, This
, pFunction
, output_signature
, parent
, parent_ops
);
1080 WARN("Failed to initialize vertex shader, hr %#x.\n", hr
);
1081 HeapFree(GetProcessHeap(), 0, object
);
1085 TRACE("Created vertex shader %p.\n", object
);
1086 *ppVertexShader
= (IWineD3DVertexShader
*)object
;
1091 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateGeometryShader(IWineD3DDevice
*iface
,
1092 const DWORD
*byte_code
, const struct wined3d_shader_signature
*output_signature
,
1093 IWineD3DGeometryShader
**shader
, IUnknown
*parent
,
1094 const struct wined3d_parent_ops
*parent_ops
)
1096 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1097 struct wined3d_geometryshader
*object
;
1100 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1103 ERR("Failed to allocate shader memory.\n");
1104 return E_OUTOFMEMORY
;
1107 hr
= geometryshader_init(object
, This
, byte_code
, output_signature
, parent
, parent_ops
);
1110 WARN("Failed to initialize geometry shader, hr %#x.\n", hr
);
1111 HeapFree(GetProcessHeap(), 0, object
);
1115 TRACE("Created geometry shader %p.\n", object
);
1116 *shader
= (IWineD3DGeometryShader
*)object
;
1121 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
*iface
,
1122 const DWORD
*pFunction
, const struct wined3d_shader_signature
*output_signature
,
1123 IWineD3DPixelShader
**ppPixelShader
, IUnknown
*parent
,
1124 const struct wined3d_parent_ops
*parent_ops
)
1126 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1127 IWineD3DPixelShaderImpl
*object
;
1130 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1133 ERR("Failed to allocate shader memory.\n");
1134 return E_OUTOFMEMORY
;
1137 hr
= pixelshader_init(object
, This
, pFunction
, output_signature
, parent
, parent_ops
);
1140 WARN("Failed to initialize pixel shader, hr %#x.\n", hr
);
1141 HeapFree(GetProcessHeap(), 0, object
);
1145 TRACE("Created pixel shader %p.\n", object
);
1146 *ppPixelShader
= (IWineD3DPixelShader
*)object
;
1151 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice
*iface
, DWORD Flags
,
1152 const PALETTEENTRY
*PalEnt
, IWineD3DPalette
**Palette
, IUnknown
*Parent
)
1154 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1155 IWineD3DPaletteImpl
*object
;
1157 TRACE("(%p)->(%x, %p, %p, %p)\n", This
, Flags
, PalEnt
, Palette
, Parent
);
1159 /* Create the new object */
1160 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DPaletteImpl
));
1162 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1163 return E_OUTOFMEMORY
;
1166 object
->lpVtbl
= &IWineD3DPalette_Vtbl
;
1168 object
->Flags
= Flags
;
1169 object
->parent
= Parent
;
1170 object
->device
= This
;
1171 object
->palNumEntries
= IWineD3DPaletteImpl_Size(Flags
);
1172 object
->hpal
= CreatePalette((const LOGPALETTE
*)&(object
->palVersion
));
1175 HeapFree( GetProcessHeap(), 0, object
);
1176 return E_OUTOFMEMORY
;
1179 hr
= IWineD3DPalette_SetEntries((IWineD3DPalette
*) object
, 0, 0, IWineD3DPaletteImpl_Size(Flags
), PalEnt
);
1181 IWineD3DPalette_Release((IWineD3DPalette
*) object
);
1185 *Palette
= (IWineD3DPalette
*) object
;
1190 static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl
*This
, const char *filename
) {
1194 HDC dcb
= NULL
, dcs
= NULL
;
1195 WINEDDCOLORKEY colorkey
;
1197 hbm
= LoadImageA(NULL
, filename
, IMAGE_BITMAP
, 0, 0, LR_LOADFROMFILE
| LR_CREATEDIBSECTION
);
1200 GetObjectA(hbm
, sizeof(BITMAP
), &bm
);
1201 dcb
= CreateCompatibleDC(NULL
);
1203 SelectObject(dcb
, hbm
);
1207 /* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
1208 * couldn't be loaded
1210 memset(&bm
, 0, sizeof(bm
));
1215 hr
= IWineD3DDevice_CreateSurface((IWineD3DDevice
*)This
, bm
.bmWidth
, bm
.bmHeight
, WINED3DFMT_B5G6R5_UNORM
, TRUE
,
1216 FALSE
, 0, &This
->logo_surface
, 0, WINED3DPOOL_DEFAULT
, WINED3DMULTISAMPLE_NONE
, 0, SURFACE_OPENGL
,
1217 NULL
, &wined3d_null_parent_ops
);
1219 ERR("Wine logo requested, but failed to create surface\n");
1224 hr
= IWineD3DSurface_GetDC(This
->logo_surface
, &dcs
);
1225 if(FAILED(hr
)) goto out
;
1226 BitBlt(dcs
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, dcb
, 0, 0, SRCCOPY
);
1227 IWineD3DSurface_ReleaseDC(This
->logo_surface
, dcs
);
1229 colorkey
.dwColorSpaceLowValue
= 0;
1230 colorkey
.dwColorSpaceHighValue
= 0;
1231 IWineD3DSurface_SetColorKey(This
->logo_surface
, WINEDDCKEY_SRCBLT
, &colorkey
);
1233 /* Fill the surface with a white color to show that wined3d is there */
1234 IWineD3DDevice_ColorFill((IWineD3DDevice
*) This
, This
->logo_surface
, NULL
, 0xffffffff);
1238 if (dcb
) DeleteDC(dcb
);
1239 if (hbm
) DeleteObject(hbm
);
1242 /* Context activation is done by the caller. */
1243 static void create_dummy_textures(IWineD3DDeviceImpl
*This
)
1245 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1247 /* Under DirectX you can have texture stage operations even if no texture is
1248 bound, whereas opengl will only do texture operations when a valid texture is
1249 bound. We emulate this by creating dummy textures and binding them to each
1250 texture stage, but disable all stages by default. Hence if a stage is enabled
1251 then the default texture will kick in until replaced by a SetTexture call */
1254 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
1256 /* The dummy texture does not have client storage backing */
1257 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
1258 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
1261 for (i
= 0; i
< gl_info
->limits
.textures
; ++i
)
1263 GLubyte white
= 255;
1265 /* Make appropriate texture active */
1266 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
1267 checkGLcall("glActiveTextureARB");
1269 /* Generate an opengl texture name */
1270 glGenTextures(1, &This
->dummyTextureName
[i
]);
1271 checkGLcall("glGenTextures");
1272 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
1274 /* Generate a dummy 2d texture (not using 1d because they cause many
1275 * DRI drivers fall back to sw) */
1276 glBindTexture(GL_TEXTURE_2D
, This
->dummyTextureName
[i
]);
1277 checkGLcall("glBindTexture");
1279 glTexImage2D(GL_TEXTURE_2D
, 0, GL_LUMINANCE
, 1, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
1280 checkGLcall("glTexImage2D");
1283 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
1285 /* Reenable because if supported it is enabled by default */
1286 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
1287 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
1293 /* Context activation is done by the caller. */
1294 static void destroy_dummy_textures(IWineD3DDeviceImpl
*device
, const struct wined3d_gl_info
*gl_info
)
1297 glDeleteTextures(gl_info
->limits
.textures
, device
->dummyTextureName
);
1298 checkGLcall("glDeleteTextures(gl_info->limits.textures, device->dummyTextureName)");
1301 memset(device
->dummyTextureName
, 0, gl_info
->limits
.textures
* sizeof(*device
->dummyTextureName
));
1304 static HRESULT WINAPI
IWineD3DDeviceImpl_Init3D(IWineD3DDevice
*iface
,
1305 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
1307 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1308 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1309 IWineD3DSwapChainImpl
*swapchain
= NULL
;
1310 struct wined3d_context
*context
;
1315 TRACE("(%p)->(%p)\n", This
, pPresentationParameters
);
1317 if(This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
1318 if(!This
->adapter
->opengl
) return WINED3DERR_INVALIDCALL
;
1320 if (!pPresentationParameters
->Windowed
)
1322 This
->focus_window
= This
->createParms
.hFocusWindow
;
1323 if (!This
->focus_window
) This
->focus_window
= pPresentationParameters
->hDeviceWindow
;
1324 if (!wined3d_register_window(This
->focus_window
, This
))
1326 ERR("Failed to register window %p.\n", This
->focus_window
);
1331 TRACE("(%p) : Creating stateblock\n", This
);
1332 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
1333 hr
= IWineD3DDevice_CreateStateBlock(iface
,
1335 (IWineD3DStateBlock
**)&This
->stateBlock
,
1337 if (WINED3D_OK
!= hr
) { /* Note: No parent needed for initial internal stateblock */
1338 WARN("Failed to create stateblock\n");
1341 TRACE("(%p) : Created stateblock (%p)\n", This
, This
->stateBlock
);
1342 This
->updateStateBlock
= This
->stateBlock
;
1343 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
1345 This
->render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1346 sizeof(IWineD3DSurface
*) * gl_info
->limits
.buffers
);
1347 This
->draw_buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1348 sizeof(GLenum
) * gl_info
->limits
.buffers
);
1350 This
->NumberOfPalettes
= 1;
1351 This
->palettes
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PALETTEENTRY
*));
1352 if(!This
->palettes
|| !This
->render_targets
|| !This
->draw_buffers
) {
1353 ERR("Out of memory!\n");
1357 This
->palettes
[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
1358 if(!This
->palettes
[0]) {
1359 ERR("Out of memory!\n");
1363 for (i
= 0; i
< 256; ++i
) {
1364 This
->palettes
[0][i
].peRed
= 0xFF;
1365 This
->palettes
[0][i
].peGreen
= 0xFF;
1366 This
->palettes
[0][i
].peBlue
= 0xFF;
1367 This
->palettes
[0][i
].peFlags
= 0xFF;
1369 This
->currentPalette
= 0;
1371 /* Initialize the texture unit mapping to a 1:1 mapping */
1372 for (state
= 0; state
< MAX_COMBINED_SAMPLERS
; ++state
)
1374 if (state
< gl_info
->limits
.fragment_samplers
)
1376 This
->texUnitMap
[state
] = state
;
1377 This
->rev_tex_unit_map
[state
] = state
;
1379 This
->texUnitMap
[state
] = WINED3D_UNMAPPED_STAGE
;
1380 This
->rev_tex_unit_map
[state
] = WINED3D_UNMAPPED_STAGE
;
1384 if (This
->focus_window
) SetFocus(This
->focus_window
);
1386 /* Setup the implicit swapchain. This also initializes a context. */
1387 TRACE("Creating implicit swapchain\n");
1388 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
1389 pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
);
1392 WARN("Failed to create implicit swapchain\n");
1396 This
->NumberOfSwapChains
= 1;
1397 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(IWineD3DSwapChain
*));
1398 if(!This
->swapchains
) {
1399 ERR("Out of memory!\n");
1402 This
->swapchains
[0] = (IWineD3DSwapChain
*) swapchain
;
1404 if(swapchain
->backBuffer
&& swapchain
->backBuffer
[0]) {
1405 TRACE("Setting rendertarget to %p\n", swapchain
->backBuffer
);
1406 This
->render_targets
[0] = swapchain
->backBuffer
[0];
1409 TRACE("Setting rendertarget to %p\n", swapchain
->frontBuffer
);
1410 This
->render_targets
[0] = swapchain
->frontBuffer
;
1412 IWineD3DSurface_AddRef(This
->render_targets
[0]);
1414 /* Depth Stencil support */
1415 This
->stencilBufferTarget
= This
->auto_depth_stencil_buffer
;
1416 if (NULL
!= This
->stencilBufferTarget
) {
1417 IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
1420 hr
= This
->shader_backend
->shader_alloc_private(iface
);
1422 TRACE("Shader private data couldn't be allocated\n");
1425 hr
= This
->frag_pipe
->alloc_private(iface
);
1427 TRACE("Fragment pipeline private data couldn't be allocated\n");
1430 hr
= This
->blitter
->alloc_private(iface
);
1432 TRACE("Blitter private data couldn't be allocated\n");
1436 /* Set up some starting GL setup */
1438 /* Setup all the devices defaults */
1439 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*)This
->stateBlock
);
1441 context
= context_acquire(This
, swapchain
->frontBuffer
, CTXUSAGE_RESOURCELOAD
);
1443 create_dummy_textures(This
);
1447 /* Initialize the current view state */
1448 This
->view_ident
= 1;
1449 This
->contexts
[0]->last_was_rhw
= 0;
1450 glGetIntegerv(GL_MAX_LIGHTS
, &This
->maxConcurrentLights
);
1451 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1453 switch(wined3d_settings
.offscreen_rendering_mode
) {
1455 This
->offscreenBuffer
= GL_COLOR_ATTACHMENT0
;
1459 This
->offscreenBuffer
= GL_BACK
;
1462 case ORM_BACKBUFFER
:
1464 if (context_get_current()->aux_buffers
> 0)
1466 TRACE("Using auxilliary buffer for offscreen rendering\n");
1467 This
->offscreenBuffer
= GL_AUX0
;
1469 TRACE("Using back buffer for offscreen rendering\n");
1470 This
->offscreenBuffer
= GL_BACK
;
1475 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This
, This
);
1478 context_release(context
);
1480 /* Clear the screen */
1481 IWineD3DDevice_Clear((IWineD3DDevice
*) This
, 0, NULL
,
1482 WINED3DCLEAR_TARGET
| pPresentationParameters
->EnableAutoDepthStencil
? WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
: 0,
1485 This
->d3d_initialized
= TRUE
;
1487 if(wined3d_settings
.logo
) {
1488 IWineD3DDeviceImpl_LoadLogo(This
, wined3d_settings
.logo
);
1490 This
->highest_dirty_ps_const
= 0;
1491 This
->highest_dirty_vs_const
= 0;
1495 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
1496 HeapFree(GetProcessHeap(), 0, This
->draw_buffers
);
1497 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
1498 This
->NumberOfSwapChains
= 0;
1499 if(This
->palettes
) {
1500 HeapFree(GetProcessHeap(), 0, This
->palettes
[0]);
1501 HeapFree(GetProcessHeap(), 0, This
->palettes
);
1503 This
->NumberOfPalettes
= 0;
1505 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) swapchain
);
1507 if(This
->stateBlock
) {
1508 IWineD3DStateBlock_Release((IWineD3DStateBlock
*) This
->stateBlock
);
1509 This
->stateBlock
= NULL
;
1511 if (This
->blit_priv
) {
1512 This
->blitter
->free_private(iface
);
1514 if (This
->fragment_priv
) {
1515 This
->frag_pipe
->free_private(iface
);
1517 if (This
->shader_priv
) {
1518 This
->shader_backend
->shader_free_private(iface
);
1520 if (This
->focus_window
) wined3d_unregister_window(This
->focus_window
);
1524 static HRESULT WINAPI
IWineD3DDeviceImpl_InitGDI(IWineD3DDevice
*iface
,
1525 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
1527 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1528 IWineD3DSwapChainImpl
*swapchain
= NULL
;
1531 /* Setup the implicit swapchain */
1532 TRACE("Creating implicit swapchain\n");
1533 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
1534 pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
);
1537 WARN("Failed to create implicit swapchain\n");
1541 This
->NumberOfSwapChains
= 1;
1542 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(IWineD3DSwapChain
*));
1543 if(!This
->swapchains
) {
1544 ERR("Out of memory!\n");
1547 This
->swapchains
[0] = (IWineD3DSwapChain
*) swapchain
;
1551 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
1555 static HRESULT WINAPI
device_unload_resource(IWineD3DResource
*resource
, void *ctx
)
1557 IWineD3DResource_UnLoad(resource
);
1558 IWineD3DResource_Release(resource
);
1562 static HRESULT WINAPI
IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice
*iface
,
1563 D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain
)
1565 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1566 const struct wined3d_gl_info
*gl_info
;
1567 struct wined3d_context
*context
;
1570 TRACE("(%p)\n", This
);
1572 if(!This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
1574 /* I don't think that the interface guarantees that the device is destroyed from the same thread
1575 * it was created. Thus make sure a context is active for the glDelete* calls
1577 context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
1578 gl_info
= context
->gl_info
;
1580 if(This
->logo_surface
) IWineD3DSurface_Release(This
->logo_surface
);
1582 /* Unload resources */
1583 IWineD3DDevice_EnumResources(iface
, device_unload_resource
, NULL
);
1585 TRACE("Deleting high order patches\n");
1586 for(i
= 0; i
< PATCHMAP_SIZE
; i
++) {
1587 struct list
*e1
, *e2
;
1588 struct WineD3DRectPatch
*patch
;
1589 LIST_FOR_EACH_SAFE(e1
, e2
, &This
->patches
[i
]) {
1590 patch
= LIST_ENTRY(e1
, struct WineD3DRectPatch
, entry
);
1591 IWineD3DDevice_DeletePatch(iface
, patch
->Handle
);
1595 /* Delete the palette conversion shader if it is around */
1596 if(This
->paletteConversionShader
) {
1598 GL_EXTCALL(glDeleteProgramsARB(1, &This
->paletteConversionShader
));
1600 This
->paletteConversionShader
= 0;
1603 /* Delete the pbuffer context if there is any */
1604 if(This
->pbufferContext
) context_destroy(This
, This
->pbufferContext
);
1606 /* Delete the mouse cursor texture */
1607 if(This
->cursorTexture
) {
1609 glDeleteTextures(1, &This
->cursorTexture
);
1611 This
->cursorTexture
= 0;
1614 for (sampler
= 0; sampler
< MAX_FRAGMENT_SAMPLERS
; ++sampler
) {
1615 IWineD3DDevice_SetTexture(iface
, sampler
, NULL
);
1617 for (sampler
= 0; sampler
< MAX_VERTEX_SAMPLERS
; ++sampler
) {
1618 IWineD3DDevice_SetTexture(iface
, WINED3DVERTEXTEXTURESAMPLER0
+ sampler
, NULL
);
1621 /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
1622 * private data, it might contain opengl pointers
1624 if(This
->depth_blt_texture
) {
1626 glDeleteTextures(1, &This
->depth_blt_texture
);
1628 This
->depth_blt_texture
= 0;
1630 if (This
->depth_blt_rb
) {
1632 gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &This
->depth_blt_rb
);
1634 This
->depth_blt_rb
= 0;
1635 This
->depth_blt_rb_w
= 0;
1636 This
->depth_blt_rb_h
= 0;
1639 /* Release the update stateblock */
1640 if(IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
) > 0){
1641 if(This
->updateStateBlock
!= This
->stateBlock
)
1642 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
1644 This
->updateStateBlock
= NULL
;
1646 { /* because were not doing proper internal refcounts releasing the primary state block
1647 causes recursion with the extra checks in ResourceReleased, to avoid this we have
1648 to set this->stateBlock = NULL; first */
1649 IWineD3DStateBlock
*stateBlock
= (IWineD3DStateBlock
*)This
->stateBlock
;
1650 This
->stateBlock
= NULL
;
1652 /* Release the stateblock */
1653 if(IWineD3DStateBlock_Release(stateBlock
) > 0){
1654 FIXME("(%p) Something's still holding the Update stateblock\n",This
);
1658 /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
1659 This
->blitter
->free_private(iface
);
1660 This
->frag_pipe
->free_private(iface
);
1661 This
->shader_backend
->shader_free_private(iface
);
1663 /* Release the buffers (with sanity checks)*/
1664 TRACE("Releasing the depth stencil buffer at %p\n", This
->stencilBufferTarget
);
1665 if(This
->stencilBufferTarget
!= NULL
&& (IWineD3DSurface_Release(This
->stencilBufferTarget
) >0)){
1666 if(This
->auto_depth_stencil_buffer
!= This
->stencilBufferTarget
)
1667 FIXME("(%p) Something's still holding the stencilBufferTarget\n",This
);
1669 This
->stencilBufferTarget
= NULL
;
1671 TRACE("Releasing the render target at %p\n", This
->render_targets
[0]);
1672 if(IWineD3DSurface_Release(This
->render_targets
[0]) >0){
1673 /* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1675 TRACE("Setting rendertarget to NULL\n");
1676 This
->render_targets
[0] = NULL
;
1678 if (This
->auto_depth_stencil_buffer
) {
1679 if (IWineD3DSurface_Release(This
->auto_depth_stencil_buffer
) > 0)
1681 FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This
);
1683 This
->auto_depth_stencil_buffer
= NULL
;
1686 context_release(context
);
1688 for(i
=0; i
< This
->NumberOfSwapChains
; i
++) {
1689 TRACE("Releasing the implicit swapchain %d\n", i
);
1690 if (D3DCB_DestroySwapChain(This
->swapchains
[i
]) > 0) {
1691 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
1695 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
1696 This
->swapchains
= NULL
;
1697 This
->NumberOfSwapChains
= 0;
1699 for (i
= 0; i
< This
->NumberOfPalettes
; i
++) HeapFree(GetProcessHeap(), 0, This
->palettes
[i
]);
1700 HeapFree(GetProcessHeap(), 0, This
->palettes
);
1701 This
->palettes
= NULL
;
1702 This
->NumberOfPalettes
= 0;
1704 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
1705 HeapFree(GetProcessHeap(), 0, This
->draw_buffers
);
1706 This
->render_targets
= NULL
;
1707 This
->draw_buffers
= NULL
;
1709 This
->d3d_initialized
= FALSE
;
1711 if (This
->focus_window
) wined3d_unregister_window(This
->focus_window
);
1716 static HRESULT WINAPI
IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice
*iface
, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain
) {
1717 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1720 for(i
=0; i
< This
->NumberOfSwapChains
; i
++) {
1721 TRACE("Releasing the implicit swapchain %d\n", i
);
1722 if (D3DCB_DestroySwapChain(This
->swapchains
[i
]) > 0) {
1723 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
1727 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
1728 This
->swapchains
= NULL
;
1729 This
->NumberOfSwapChains
= 0;
1733 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
1734 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
1735 * CreateDevice if D3DCREATE_MULTITHREADED is passed.
1737 * There is no way to deactivate thread safety once it is enabled.
1739 static void WINAPI
IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice
*iface
) {
1740 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1742 /*For now just store the flag(needed in case of ddraw) */
1743 This
->createParms
.BehaviorFlags
|= WINED3DCREATE_MULTITHREADED
;
1746 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
,
1747 const WINED3DDISPLAYMODE
* pMode
) {
1749 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1751 const struct GlPixelFormatDesc
*format_desc
= getFormatDescEntry(pMode
->Format
, &This
->adapter
->gl_info
);
1754 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This
, iSwapChain
, pMode
, pMode
->Width
, pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
1756 /* Resize the screen even without a window:
1757 * The app could have unset it with SetCooperativeLevel, but not called
1758 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1759 * but we don't have any hwnd
1762 memset(&devmode
, 0, sizeof(devmode
));
1763 devmode
.dmSize
= sizeof(devmode
);
1764 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
1765 devmode
.dmBitsPerPel
= format_desc
->byte_count
* 8;
1766 devmode
.dmPelsWidth
= pMode
->Width
;
1767 devmode
.dmPelsHeight
= pMode
->Height
;
1769 devmode
.dmDisplayFrequency
= pMode
->RefreshRate
;
1770 if (pMode
->RefreshRate
!= 0) {
1771 devmode
.dmFields
|= DM_DISPLAYFREQUENCY
;
1774 /* Only change the mode if necessary */
1775 if( (This
->ddraw_width
== pMode
->Width
) &&
1776 (This
->ddraw_height
== pMode
->Height
) &&
1777 (This
->ddraw_format
== pMode
->Format
) &&
1778 (pMode
->RefreshRate
== 0) ) {
1782 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
1783 if (ret
!= DISP_CHANGE_SUCCESSFUL
) {
1784 if(devmode
.dmDisplayFrequency
!= 0) {
1785 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1786 devmode
.dmFields
&= ~DM_DISPLAYFREQUENCY
;
1787 devmode
.dmDisplayFrequency
= 0;
1788 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
) != DISP_CHANGE_SUCCESSFUL
;
1790 if(ret
!= DISP_CHANGE_SUCCESSFUL
) {
1791 return WINED3DERR_NOTAVAILABLE
;
1795 /* Store the new values */
1796 This
->ddraw_width
= pMode
->Width
;
1797 This
->ddraw_height
= pMode
->Height
;
1798 This
->ddraw_format
= pMode
->Format
;
1800 /* And finally clip mouse to our screen */
1801 SetRect(&clip_rc
, 0, 0, pMode
->Width
, pMode
->Height
);
1802 ClipCursor(&clip_rc
);
1807 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
*iface
, IWineD3D
**ppD3D
) {
1808 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1809 *ppD3D
= This
->wined3d
;
1810 TRACE("Returning %p.\n", *ppD3D
);
1811 IWineD3D_AddRef(*ppD3D
);
1815 static UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
1816 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1818 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This
,
1819 (This
->adapter
->TextureRam
/(1024*1024)),
1820 ((This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
) / (1024*1024)));
1821 /* return simulated texture memory left */
1822 return (This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
);
1826 * Get / Set Stream Source
1828 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,
1829 IWineD3DBuffer
*pStreamData
, UINT OffsetInBytes
, UINT Stride
)
1831 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1832 IWineD3DBuffer
*oldSrc
;
1834 if (StreamNumber
>= MAX_STREAMS
) {
1835 WARN("Stream out of range %d\n", StreamNumber
);
1836 return WINED3DERR_INVALIDCALL
;
1837 } else if(OffsetInBytes
& 0x3) {
1838 WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes
);
1839 return WINED3DERR_INVALIDCALL
;
1842 oldSrc
= This
->updateStateBlock
->streamSource
[StreamNumber
];
1843 TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This
, StreamNumber
, oldSrc
, pStreamData
, OffsetInBytes
, Stride
);
1845 This
->updateStateBlock
->changed
.streamSource
|= 1 << StreamNumber
;
1847 if(oldSrc
== pStreamData
&&
1848 This
->updateStateBlock
->streamStride
[StreamNumber
] == Stride
&&
1849 This
->updateStateBlock
->streamOffset
[StreamNumber
] == OffsetInBytes
) {
1850 TRACE("Application is setting the old values over, nothing to do\n");
1854 This
->updateStateBlock
->streamSource
[StreamNumber
] = pStreamData
;
1856 This
->updateStateBlock
->streamStride
[StreamNumber
] = Stride
;
1857 This
->updateStateBlock
->streamOffset
[StreamNumber
] = OffsetInBytes
;
1860 /* Handle recording of state blocks */
1861 if (This
->isRecordingState
) {
1862 TRACE("Recording... not performing anything\n");
1863 if (pStreamData
) IWineD3DBuffer_AddRef(pStreamData
);
1864 if (oldSrc
) IWineD3DBuffer_Release(oldSrc
);
1868 if (pStreamData
!= NULL
) {
1869 InterlockedIncrement(&((struct wined3d_buffer
*)pStreamData
)->bind_count
);
1870 IWineD3DBuffer_AddRef(pStreamData
);
1872 if (oldSrc
!= NULL
) {
1873 InterlockedDecrement(&((struct wined3d_buffer
*)oldSrc
)->bind_count
);
1874 IWineD3DBuffer_Release(oldSrc
);
1877 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
1882 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
,
1883 UINT StreamNumber
, IWineD3DBuffer
**pStream
, UINT
*pOffset
, UINT
*pStride
)
1885 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1887 TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This
, StreamNumber
,
1888 This
->stateBlock
->streamSource
[StreamNumber
],
1889 This
->stateBlock
->streamOffset
[StreamNumber
],
1890 This
->stateBlock
->streamStride
[StreamNumber
]);
1892 if (StreamNumber
>= MAX_STREAMS
) {
1893 WARN("Stream out of range %d\n", StreamNumber
);
1894 return WINED3DERR_INVALIDCALL
;
1896 *pStream
= This
->stateBlock
->streamSource
[StreamNumber
];
1897 *pStride
= This
->stateBlock
->streamStride
[StreamNumber
];
1899 *pOffset
= This
->stateBlock
->streamOffset
[StreamNumber
];
1902 if (*pStream
!= NULL
) {
1903 IWineD3DBuffer_AddRef(*pStream
); /* We have created a new reference to the VB */
1908 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
1909 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1910 UINT oldFlags
= This
->updateStateBlock
->streamFlags
[StreamNumber
];
1911 UINT oldFreq
= This
->updateStateBlock
->streamFreq
[StreamNumber
];
1913 /* Verify input at least in d3d9 this is invalid*/
1914 if( (Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && (Divider
& WINED3DSTREAMSOURCE_INDEXEDDATA
)){
1915 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
1916 return WINED3DERR_INVALIDCALL
;
1918 if( (Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && StreamNumber
== 0 ){
1919 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
1920 return WINED3DERR_INVALIDCALL
;
1923 WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
1924 return WINED3DERR_INVALIDCALL
;
1927 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This
, StreamNumber
, Divider
);
1928 This
->updateStateBlock
->streamFlags
[StreamNumber
] = Divider
& (WINED3DSTREAMSOURCE_INSTANCEDATA
| WINED3DSTREAMSOURCE_INDEXEDDATA
);
1930 This
->updateStateBlock
->changed
.streamFreq
|= 1 << StreamNumber
;
1931 This
->updateStateBlock
->streamFreq
[StreamNumber
] = Divider
& 0x7FFFFF;
1933 if(This
->updateStateBlock
->streamFreq
[StreamNumber
] != oldFreq
||
1934 This
->updateStateBlock
->streamFlags
[StreamNumber
] != oldFlags
) {
1935 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
1941 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
1942 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1944 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This
, StreamNumber
, Divider
);
1945 *Divider
= This
->updateStateBlock
->streamFreq
[StreamNumber
] | This
->updateStateBlock
->streamFlags
[StreamNumber
];
1947 TRACE("(%p) : returning %d\n", This
, *Divider
);
1953 * Get / Set & Multiply Transform
1955 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE d3dts
, CONST WINED3DMATRIX
* lpmatrix
) {
1956 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1958 /* Most of this routine, comments included copied from ddraw tree initially: */
1959 TRACE("(%p) : Transform State=%s\n", This
, debug_d3dtstype(d3dts
));
1961 /* Handle recording of state blocks */
1962 if (This
->isRecordingState
) {
1963 TRACE("Recording... not performing anything\n");
1964 This
->updateStateBlock
->changed
.transform
[d3dts
>> 5] |= 1 << (d3dts
& 0x1f);
1965 This
->updateStateBlock
->transforms
[d3dts
] = *lpmatrix
;
1970 * If the new matrix is the same as the current one,
1971 * we cut off any further processing. this seems to be a reasonable
1972 * optimization because as was noticed, some apps (warcraft3 for example)
1973 * tend towards setting the same matrix repeatedly for some reason.
1975 * From here on we assume that the new matrix is different, wherever it matters.
1977 if (!memcmp(&This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(WINED3DMATRIX
))) {
1978 TRACE("The app is setting the same matrix over again\n");
1981 conv_mat(lpmatrix
, &This
->stateBlock
->transforms
[d3dts
].u
.m
[0][0]);
1985 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1986 where ViewMat = Camera space, WorldMat = world space.
1988 In OpenGL, camera and world space is combined into GL_MODELVIEW
1989 matrix. The Projection matrix stay projection matrix.
1992 /* Capture the times we can just ignore the change for now */
1993 if (d3dts
== WINED3DTS_VIEW
) { /* handle the VIEW matrix */
1994 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
1995 /* Handled by the state manager */
1998 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TRANSFORM(d3dts
));
2002 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, WINED3DMATRIX
* pMatrix
) {
2003 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2004 TRACE("(%p) : for Transform State %s\n", This
, debug_d3dtstype(State
));
2005 *pMatrix
= This
->stateBlock
->transforms
[State
];
2009 static HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, CONST WINED3DMATRIX
* pMatrix
) {
2010 const WINED3DMATRIX
*mat
= NULL
;
2013 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2014 * below means it will be recorded in a state block change, but it
2015 * works regardless where it is recorded.
2016 * If this is found to be wrong, change to StateBlock.
2018 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2019 TRACE("(%p) : For state %s\n", This
, debug_d3dtstype(State
));
2021 if (State
<= HIGHEST_TRANSFORMSTATE
)
2023 mat
= &This
->updateStateBlock
->transforms
[State
];
2025 FIXME("Unhandled transform state!!\n");
2028 multiply_matrix(&temp
, mat
, pMatrix
);
2030 /* Apply change via set transform - will reapply to eg. lights this way */
2031 return IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
2037 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2038 you can reference any indexes you want as long as that number max are enabled at any
2039 one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2040 However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2041 but when recording, just build a chain pretty much of commands to be replayed. */
2043 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
2045 struct wined3d_light_info
*object
= NULL
;
2046 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2049 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2050 TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This
, Index
, pLight
, Hi
);
2052 /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2056 WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2057 return WINED3DERR_INVALIDCALL
;
2060 switch(pLight
->Type
) {
2061 case WINED3DLIGHT_POINT
:
2062 case WINED3DLIGHT_SPOT
:
2063 case WINED3DLIGHT_PARALLELPOINT
:
2064 case WINED3DLIGHT_GLSPOT
:
2065 /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2068 if (pLight
->Attenuation0
< 0.0f
|| pLight
->Attenuation1
< 0.0f
|| pLight
->Attenuation2
< 0.0f
)
2070 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2071 return WINED3DERR_INVALIDCALL
;
2075 case WINED3DLIGHT_DIRECTIONAL
:
2076 /* Ignores attenuation */
2080 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2081 return WINED3DERR_INVALIDCALL
;
2084 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
])
2086 object
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2087 if(object
->OriginalIndex
== Index
) break;
2092 TRACE("Adding new light\n");
2093 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2095 ERR("Out of memory error when allocating a light\n");
2096 return E_OUTOFMEMORY
;
2098 list_add_head(&This
->updateStateBlock
->lightMap
[Hi
], &object
->entry
);
2099 object
->glIndex
= -1;
2100 object
->OriginalIndex
= Index
;
2103 /* Initialize the object */
2104 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
,
2105 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
2106 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
2107 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
2108 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
2109 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
2110 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
2112 /* Save away the information */
2113 object
->OriginalParms
= *pLight
;
2115 switch (pLight
->Type
) {
2116 case WINED3DLIGHT_POINT
:
2118 object
->lightPosn
[0] = pLight
->Position
.x
;
2119 object
->lightPosn
[1] = pLight
->Position
.y
;
2120 object
->lightPosn
[2] = pLight
->Position
.z
;
2121 object
->lightPosn
[3] = 1.0f
;
2122 object
->cutoff
= 180.0f
;
2126 case WINED3DLIGHT_DIRECTIONAL
:
2128 object
->lightPosn
[0] = -pLight
->Direction
.x
;
2129 object
->lightPosn
[1] = -pLight
->Direction
.y
;
2130 object
->lightPosn
[2] = -pLight
->Direction
.z
;
2131 object
->lightPosn
[3] = 0.0f
;
2132 object
->exponent
= 0.0f
;
2133 object
->cutoff
= 180.0f
;
2136 case WINED3DLIGHT_SPOT
:
2138 object
->lightPosn
[0] = pLight
->Position
.x
;
2139 object
->lightPosn
[1] = pLight
->Position
.y
;
2140 object
->lightPosn
[2] = pLight
->Position
.z
;
2141 object
->lightPosn
[3] = 1.0f
;
2144 object
->lightDirn
[0] = pLight
->Direction
.x
;
2145 object
->lightDirn
[1] = pLight
->Direction
.y
;
2146 object
->lightDirn
[2] = pLight
->Direction
.z
;
2147 object
->lightDirn
[3] = 1.0f
;
2150 * opengl-ish and d3d-ish spot lights use too different models for the
2151 * light "intensity" as a function of the angle towards the main light direction,
2152 * so we only can approximate very roughly.
2153 * however spot lights are rather rarely used in games (if ever used at all).
2154 * furthermore if still used, probably nobody pays attention to such details.
2156 if (pLight
->Falloff
== 0) {
2157 /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2158 * falloff resp. exponent parameter as an exponent, so the spot light lighting
2159 * will always be 1.0 for both of them, and we don't have to care for the
2160 * rest of the rather complex calculation
2162 object
->exponent
= 0.0f
;
2164 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
2165 if (rho
< 0.0001f
) rho
= 0.0001f
;
2166 object
->exponent
= -0.3f
/logf(cosf(rho
/2));
2168 if (object
->exponent
> 128.0f
)
2170 object
->exponent
= 128.0f
;
2172 object
->cutoff
= pLight
->Phi
*90/M_PI
;
2178 FIXME("Unrecognized light type %d\n", pLight
->Type
);
2181 /* Update the live definitions if the light is currently assigned a glIndex */
2182 if (object
->glIndex
!= -1 && !This
->isRecordingState
) {
2183 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(object
->glIndex
));
2188 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
*pLight
)
2190 struct wined3d_light_info
*lightInfo
= NULL
;
2191 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2192 DWORD Hi
= LIGHTMAP_HASHFUNC(Index
);
2194 TRACE("(%p) : Idx(%d), pLight(%p)\n", This
, Index
, pLight
);
2196 LIST_FOR_EACH(e
, &This
->stateBlock
->lightMap
[Hi
])
2198 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2199 if(lightInfo
->OriginalIndex
== Index
) break;
2203 if (lightInfo
== NULL
) {
2204 TRACE("Light information requested but light not defined\n");
2205 return WINED3DERR_INVALIDCALL
;
2208 *pLight
= lightInfo
->OriginalParms
;
2213 * Get / Set Light Enable
2214 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2216 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
)
2218 struct wined3d_light_info
*lightInfo
= NULL
;
2219 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2220 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2222 TRACE("(%p) : Idx(%d), enable? %d\n", This
, Index
, Enable
);
2224 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
])
2226 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2227 if(lightInfo
->OriginalIndex
== Index
) break;
2230 TRACE("Found light: %p\n", lightInfo
);
2232 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2233 if (lightInfo
== NULL
) {
2235 TRACE("Light enabled requested but light not defined, so defining one!\n");
2236 IWineD3DDeviceImpl_SetLight(iface
, Index
, &WINED3D_default_light
);
2238 /* Search for it again! Should be fairly quick as near head of list */
2239 LIST_FOR_EACH(e
, &This
->updateStateBlock
->lightMap
[Hi
])
2241 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2242 if(lightInfo
->OriginalIndex
== Index
) break;
2245 if (lightInfo
== NULL
) {
2246 FIXME("Adding default lights has failed dismally\n");
2247 return WINED3DERR_INVALIDCALL
;
2252 if(lightInfo
->glIndex
!= -1) {
2253 if(!This
->isRecordingState
) {
2254 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(lightInfo
->glIndex
));
2257 This
->updateStateBlock
->activeLights
[lightInfo
->glIndex
] = NULL
;
2258 lightInfo
->glIndex
= -1;
2260 TRACE("Light already disabled, nothing to do\n");
2262 lightInfo
->enabled
= FALSE
;
2264 lightInfo
->enabled
= TRUE
;
2265 if (lightInfo
->glIndex
!= -1) {
2267 TRACE("Nothing to do as light was enabled\n");
2270 /* Find a free gl light */
2271 for(i
= 0; i
< This
->maxConcurrentLights
; i
++) {
2272 if(This
->updateStateBlock
->activeLights
[i
] == NULL
) {
2273 This
->updateStateBlock
->activeLights
[i
] = lightInfo
;
2274 lightInfo
->glIndex
= i
;
2278 if(lightInfo
->glIndex
== -1) {
2279 /* Our tests show that Windows returns D3D_OK in this situation, even with
2280 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
2281 * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
2282 * as well for those lights.
2284 * TODO: Test how this affects rendering
2286 WARN("Too many concurrently active lights\n");
2290 /* i == lightInfo->glIndex */
2291 if(!This
->isRecordingState
) {
2292 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(i
));
2300 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
)
2302 struct wined3d_light_info
*lightInfo
= NULL
;
2303 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2305 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2306 TRACE("(%p) : for idx(%d)\n", This
, Index
);
2308 LIST_FOR_EACH(e
, &This
->stateBlock
->lightMap
[Hi
])
2310 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2311 if(lightInfo
->OriginalIndex
== Index
) break;
2315 if (lightInfo
== NULL
) {
2316 TRACE("Light enabled state requested but light not defined\n");
2317 return WINED3DERR_INVALIDCALL
;
2319 /* true is 128 according to SetLightEnable */
2320 *pEnable
= lightInfo
->enabled
? 128 : 0;
2325 * Get / Set Clip Planes
2327 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
2328 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2329 TRACE("(%p) : for idx %d, %p\n", This
, Index
, pPlane
);
2331 /* Validate Index */
2332 if (Index
>= This
->adapter
->gl_info
.limits
.clipplanes
)
2334 TRACE("Application has requested clipplane this device doesn't support\n");
2335 return WINED3DERR_INVALIDCALL
;
2338 This
->updateStateBlock
->changed
.clipplane
|= 1 << Index
;
2340 if(This
->updateStateBlock
->clipplane
[Index
][0] == pPlane
[0] &&
2341 This
->updateStateBlock
->clipplane
[Index
][1] == pPlane
[1] &&
2342 This
->updateStateBlock
->clipplane
[Index
][2] == pPlane
[2] &&
2343 This
->updateStateBlock
->clipplane
[Index
][3] == pPlane
[3]) {
2344 TRACE("Application is setting old values over, nothing to do\n");
2348 This
->updateStateBlock
->clipplane
[Index
][0] = pPlane
[0];
2349 This
->updateStateBlock
->clipplane
[Index
][1] = pPlane
[1];
2350 This
->updateStateBlock
->clipplane
[Index
][2] = pPlane
[2];
2351 This
->updateStateBlock
->clipplane
[Index
][3] = pPlane
[3];
2353 /* Handle recording of state blocks */
2354 if (This
->isRecordingState
) {
2355 TRACE("Recording... not performing anything\n");
2359 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_CLIPPLANE(Index
));
2364 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
2365 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2366 TRACE("(%p) : for idx %d\n", This
, Index
);
2368 /* Validate Index */
2369 if (Index
>= This
->adapter
->gl_info
.limits
.clipplanes
)
2371 TRACE("Application has requested clipplane this device doesn't support\n");
2372 return WINED3DERR_INVALIDCALL
;
2375 pPlane
[0] = This
->stateBlock
->clipplane
[Index
][0];
2376 pPlane
[1] = This
->stateBlock
->clipplane
[Index
][1];
2377 pPlane
[2] = This
->stateBlock
->clipplane
[Index
][2];
2378 pPlane
[3] = This
->stateBlock
->clipplane
[Index
][3];
2383 * Get / Set Clip Plane Status
2384 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2386 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
2387 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2388 FIXME("(%p) : stub\n", This
);
2389 if (NULL
== pClipStatus
) {
2390 return WINED3DERR_INVALIDCALL
;
2392 This
->updateStateBlock
->clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
2393 This
->updateStateBlock
->clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
2397 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
2398 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2399 FIXME("(%p) : stub\n", This
);
2400 if (NULL
== pClipStatus
) {
2401 return WINED3DERR_INVALIDCALL
;
2403 pClipStatus
->ClipUnion
= This
->updateStateBlock
->clip_status
.ClipUnion
;
2404 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->clip_status
.ClipIntersection
;
2409 * Get / Set Material
2411 static HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
2412 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2414 This
->updateStateBlock
->changed
.material
= TRUE
;
2415 This
->updateStateBlock
->material
= *pMaterial
;
2417 /* Handle recording of state blocks */
2418 if (This
->isRecordingState
) {
2419 TRACE("Recording... not performing anything\n");
2423 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_MATERIAL
);
2427 static HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
2428 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2429 *pMaterial
= This
->updateStateBlock
->material
;
2430 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
2431 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
2432 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
2433 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
2434 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
2435 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
2436 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
2437 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
2438 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
2446 static HRESULT WINAPI
IWineD3DDeviceImpl_SetIndexBuffer(IWineD3DDevice
*iface
,
2447 IWineD3DBuffer
*pIndexData
, WINED3DFORMAT fmt
)
2449 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2450 IWineD3DBuffer
*oldIdxs
;
2452 TRACE("(%p) : Setting to %p\n", This
, pIndexData
);
2453 oldIdxs
= This
->updateStateBlock
->pIndexData
;
2455 This
->updateStateBlock
->changed
.indices
= TRUE
;
2456 This
->updateStateBlock
->pIndexData
= pIndexData
;
2457 This
->updateStateBlock
->IndexFmt
= fmt
;
2459 /* Handle recording of state blocks */
2460 if (This
->isRecordingState
) {
2461 TRACE("Recording... not performing anything\n");
2462 if(pIndexData
) IWineD3DBuffer_AddRef(pIndexData
);
2463 if(oldIdxs
) IWineD3DBuffer_Release(oldIdxs
);
2467 if(oldIdxs
!= pIndexData
) {
2468 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
2470 InterlockedIncrement(&((struct wined3d_buffer
*)pIndexData
)->bind_count
);
2471 IWineD3DBuffer_AddRef(pIndexData
);
2474 InterlockedDecrement(&((struct wined3d_buffer
*)oldIdxs
)->bind_count
);
2475 IWineD3DBuffer_Release(oldIdxs
);
2482 static HRESULT WINAPI
IWineD3DDeviceImpl_GetIndexBuffer(IWineD3DDevice
*iface
, IWineD3DBuffer
**ppIndexData
)
2484 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2486 *ppIndexData
= This
->stateBlock
->pIndexData
;
2488 /* up ref count on ppindexdata */
2490 IWineD3DBuffer_AddRef(*ppIndexData
);
2491 TRACE("(%p) index data set to %p\n", This
, ppIndexData
);
2493 TRACE("(%p) No index data set\n", This
);
2495 TRACE("Returning %p\n", *ppIndexData
);
2500 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2501 static HRESULT WINAPI
IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice
*iface
, INT BaseIndex
) {
2502 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2503 TRACE("(%p)->(%d)\n", This
, BaseIndex
);
2505 if(This
->updateStateBlock
->baseVertexIndex
== BaseIndex
) {
2506 TRACE("Application is setting the old value over, nothing to do\n");
2510 This
->updateStateBlock
->baseVertexIndex
= BaseIndex
;
2512 if (This
->isRecordingState
) {
2513 TRACE("Recording... not performing anything\n");
2516 /* The base vertex index affects the stream sources */
2517 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2521 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice
*iface
, INT
* base_index
) {
2522 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2523 TRACE("(%p) : base_index %p\n", This
, base_index
);
2525 *base_index
= This
->stateBlock
->baseVertexIndex
;
2527 TRACE("Returning %u\n", *base_index
);
2533 * Get / Set Viewports
2535 static HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
2536 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2538 TRACE("(%p)\n", This
);
2539 This
->updateStateBlock
->changed
.viewport
= TRUE
;
2540 This
->updateStateBlock
->viewport
= *pViewport
;
2542 /* Handle recording of state blocks */
2543 if (This
->isRecordingState
) {
2544 TRACE("Recording... not performing anything\n");
2548 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This
,
2549 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
2551 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
2556 static HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
2557 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2558 TRACE("(%p)\n", This
);
2559 *pViewport
= This
->stateBlock
->viewport
;
2564 * Get / Set Render States
2565 * TODO: Verify against dx9 definitions
2567 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
, WINED3DRENDERSTATETYPE State
, DWORD Value
) {
2569 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2570 DWORD oldValue
= This
->stateBlock
->renderState
[State
];
2572 TRACE("(%p)->state = %s(%d), value = %d\n", This
, debug_d3drenderstate(State
), State
, Value
);
2574 This
->updateStateBlock
->changed
.renderState
[State
>> 5] |= 1 << (State
& 0x1f);
2575 This
->updateStateBlock
->renderState
[State
] = Value
;
2577 /* Handle recording of state blocks */
2578 if (This
->isRecordingState
) {
2579 TRACE("Recording... not performing anything\n");
2583 /* Compared here and not before the assignment to allow proper stateblock recording */
2584 if(Value
== oldValue
) {
2585 TRACE("Application is setting the old value over, nothing to do\n");
2587 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(State
));
2593 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
, WINED3DRENDERSTATETYPE State
, DWORD
*pValue
) {
2594 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2595 TRACE("(%p) for State %d = %d\n", This
, State
, This
->stateBlock
->renderState
[State
]);
2596 *pValue
= This
->stateBlock
->renderState
[State
];
2601 * Get / Set Sampler States
2602 * TODO: Verify against dx9 definitions
2605 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
2606 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2609 TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
2610 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
, Value
);
2612 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
2613 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
2616 if (Sampler
>= sizeof(This
->stateBlock
->samplerState
)/sizeof(This
->stateBlock
->samplerState
[0])) {
2617 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
2618 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
2621 * SetSampler is designed to allow for more than the standard up to 8 textures
2622 * and Geforce has stopped supporting more than 6 standard textures in openGL.
2623 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
2625 * http://developer.nvidia.com/object/General_FAQ.html#t6
2627 * There are two new settings for GForce
2629 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
2630 * and the texture one:
2631 * GL_MAX_TEXTURE_COORDS_ARB.
2632 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
2635 oldValue
= This
->stateBlock
->samplerState
[Sampler
][Type
];
2636 This
->updateStateBlock
->samplerState
[Sampler
][Type
] = Value
;
2637 This
->updateStateBlock
->changed
.samplerState
[Sampler
] |= 1 << Type
;
2639 /* Handle recording of state blocks */
2640 if (This
->isRecordingState
) {
2641 TRACE("Recording... not performing anything\n");
2645 if(oldValue
== Value
) {
2646 TRACE("Application is setting the old value over, nothing to do\n");
2650 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(Sampler
));
2655 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
2656 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2658 TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
2659 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
);
2661 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
2662 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
2665 if (Sampler
>= sizeof(This
->stateBlock
->samplerState
)/sizeof(This
->stateBlock
->samplerState
[0])) {
2666 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
2667 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
2669 *Value
= This
->stateBlock
->samplerState
[Sampler
][Type
];
2670 TRACE("(%p) : Returning %#x\n", This
, *Value
);
2675 static HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
2676 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2678 This
->updateStateBlock
->changed
.scissorRect
= TRUE
;
2679 if(EqualRect(&This
->updateStateBlock
->scissorRect
, pRect
)) {
2680 TRACE("App is setting the old scissor rectangle over, nothing to do\n");
2683 CopyRect(&This
->updateStateBlock
->scissorRect
, pRect
);
2685 if(This
->isRecordingState
) {
2686 TRACE("Recording... not performing anything\n");
2690 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
2695 static HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
2696 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2698 *pRect
= This
->updateStateBlock
->scissorRect
;
2699 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
2703 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
* pDecl
) {
2704 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2705 IWineD3DVertexDeclaration
*oldDecl
= This
->updateStateBlock
->vertexDecl
;
2707 TRACE("(%p) : pDecl=%p\n", This
, pDecl
);
2709 if (pDecl
) IWineD3DVertexDeclaration_AddRef(pDecl
);
2710 if (oldDecl
) IWineD3DVertexDeclaration_Release(oldDecl
);
2712 This
->updateStateBlock
->vertexDecl
= pDecl
;
2713 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
2715 if (This
->isRecordingState
) {
2716 TRACE("Recording... not performing anything\n");
2718 } else if(pDecl
== oldDecl
) {
2719 /* Checked after the assignment to allow proper stateblock recording */
2720 TRACE("Application is setting the old declaration over, nothing to do\n");
2724 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
2728 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
* iface
, IWineD3DVertexDeclaration
** ppDecl
) {
2729 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2731 TRACE("(%p) : ppDecl=%p\n", This
, ppDecl
);
2733 *ppDecl
= This
->stateBlock
->vertexDecl
;
2734 if (NULL
!= *ppDecl
) IWineD3DVertexDeclaration_AddRef(*ppDecl
);
2738 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
* pShader
) {
2739 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2740 IWineD3DVertexShader
* oldShader
= This
->updateStateBlock
->vertexShader
;
2742 This
->updateStateBlock
->vertexShader
= pShader
;
2743 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
2745 if (This
->isRecordingState
) {
2746 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
2747 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
2748 TRACE("Recording... not performing anything\n");
2750 } else if(oldShader
== pShader
) {
2751 /* Checked here to allow proper stateblock recording */
2752 TRACE("App is setting the old shader over, nothing to do\n");
2756 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
2757 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
2758 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
2760 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VSHADER
);
2765 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
** ppShader
) {
2766 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2768 if (NULL
== ppShader
) {
2769 return WINED3DERR_INVALIDCALL
;
2771 *ppShader
= This
->stateBlock
->vertexShader
;
2772 if( NULL
!= *ppShader
)
2773 IWineD3DVertexShader_AddRef(*ppShader
);
2775 TRACE("(%p) : returning %p\n", This
, *ppShader
);
2779 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(
2780 IWineD3DDevice
*iface
,
2782 CONST BOOL
*srcData
,
2785 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2786 unsigned int i
, cnt
= min(count
, MAX_CONST_B
- start
);
2788 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2789 iface
, srcData
, start
, count
);
2791 if (!srcData
|| start
>= MAX_CONST_B
) return WINED3DERR_INVALIDCALL
;
2793 memcpy(&This
->updateStateBlock
->vertexShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
2794 for (i
= 0; i
< cnt
; i
++)
2795 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
2797 for (i
= start
; i
< cnt
+ start
; ++i
) {
2798 This
->updateStateBlock
->changed
.vertexShaderConstantsB
|= (1 << i
);
2801 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
2806 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(
2807 IWineD3DDevice
*iface
,
2812 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2813 int cnt
= min(count
, MAX_CONST_B
- start
);
2815 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2816 iface
, dstData
, start
, count
);
2818 if (dstData
== NULL
|| cnt
< 0)
2819 return WINED3DERR_INVALIDCALL
;
2821 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantB
[start
], cnt
* sizeof(BOOL
));
2825 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(
2826 IWineD3DDevice
*iface
,
2831 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2832 unsigned int i
, cnt
= min(count
, MAX_CONST_I
- start
);
2834 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2835 iface
, srcData
, start
, count
);
2837 if (!srcData
|| start
>= MAX_CONST_I
) return WINED3DERR_INVALIDCALL
;
2839 memcpy(&This
->updateStateBlock
->vertexShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
2840 for (i
= 0; i
< cnt
; i
++)
2841 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
2842 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
2844 for (i
= start
; i
< cnt
+ start
; ++i
) {
2845 This
->updateStateBlock
->changed
.vertexShaderConstantsI
|= (1 << i
);
2848 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
2853 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(
2854 IWineD3DDevice
*iface
,
2859 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2860 int cnt
= min(count
, MAX_CONST_I
- start
);
2862 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2863 iface
, dstData
, start
, count
);
2865 if (dstData
== NULL
|| ((signed int) MAX_CONST_I
- (signed int) start
) <= (signed int) 0)
2866 return WINED3DERR_INVALIDCALL
;
2868 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
2872 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(
2873 IWineD3DDevice
*iface
,
2875 CONST
float *srcData
,
2878 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2881 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2882 iface
, srcData
, start
, count
);
2884 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
2885 if (srcData
== NULL
|| start
+ count
> This
->d3d_vshader_constantF
|| start
> This
->d3d_vshader_constantF
)
2886 return WINED3DERR_INVALIDCALL
;
2888 memcpy(&This
->updateStateBlock
->vertexShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
2890 for (i
= 0; i
< count
; i
++)
2891 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
2892 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
2895 if (!This
->isRecordingState
)
2897 This
->shader_backend
->shader_update_float_vertex_constants(iface
, start
, count
);
2898 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
2901 memset(This
->updateStateBlock
->changed
.vertexShaderConstantsF
+ start
, 1,
2902 sizeof(*This
->updateStateBlock
->changed
.vertexShaderConstantsF
) * count
);
2907 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(
2908 IWineD3DDevice
*iface
,
2913 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2914 int cnt
= min(count
, This
->d3d_vshader_constantF
- start
);
2916 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2917 iface
, dstData
, start
, count
);
2919 if (dstData
== NULL
|| cnt
< 0)
2920 return WINED3DERR_INVALIDCALL
;
2922 memcpy(dstData
, &This
->stateBlock
->vertexShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
2926 static inline void markTextureStagesDirty(IWineD3DDeviceImpl
*This
, DWORD stage
) {
2928 for(i
= 0; i
<= WINED3D_HIGHEST_TEXTURE_STATE
; ++i
)
2930 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, i
));
2934 static void device_map_stage(IWineD3DDeviceImpl
*This
, DWORD stage
, DWORD unit
)
2936 DWORD i
= This
->rev_tex_unit_map
[unit
];
2937 DWORD j
= This
->texUnitMap
[stage
];
2939 This
->texUnitMap
[stage
] = unit
;
2940 if (i
!= WINED3D_UNMAPPED_STAGE
&& i
!= stage
)
2942 This
->texUnitMap
[i
] = WINED3D_UNMAPPED_STAGE
;
2945 This
->rev_tex_unit_map
[unit
] = stage
;
2946 if (j
!= WINED3D_UNMAPPED_STAGE
&& j
!= unit
)
2948 This
->rev_tex_unit_map
[j
] = WINED3D_UNMAPPED_STAGE
;
2952 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl
*This
) {
2955 This
->fixed_function_usage_map
= 0;
2956 for (i
= 0; i
< MAX_TEXTURES
; ++i
) {
2957 WINED3DTEXTUREOP color_op
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLOROP
];
2958 WINED3DTEXTUREOP alpha_op
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAOP
];
2959 DWORD color_arg1
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG1
] & WINED3DTA_SELECTMASK
;
2960 DWORD color_arg2
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG2
] & WINED3DTA_SELECTMASK
;
2961 DWORD color_arg3
= This
->stateBlock
->textureState
[i
][WINED3DTSS_COLORARG0
] & WINED3DTA_SELECTMASK
;
2962 DWORD alpha_arg1
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG1
] & WINED3DTA_SELECTMASK
;
2963 DWORD alpha_arg2
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG2
] & WINED3DTA_SELECTMASK
;
2964 DWORD alpha_arg3
= This
->stateBlock
->textureState
[i
][WINED3DTSS_ALPHAARG0
] & WINED3DTA_SELECTMASK
;
2966 if (color_op
== WINED3DTOP_DISABLE
) {
2967 /* Not used, and disable higher stages */
2971 if (((color_arg1
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG2
)
2972 || ((color_arg2
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG1
)
2973 || ((color_arg3
== WINED3DTA_TEXTURE
) && (color_op
== WINED3DTOP_MULTIPLYADD
|| color_op
== WINED3DTOP_LERP
))
2974 || ((alpha_arg1
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG2
)
2975 || ((alpha_arg2
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG1
)
2976 || ((alpha_arg3
== WINED3DTA_TEXTURE
) && (alpha_op
== WINED3DTOP_MULTIPLYADD
|| alpha_op
== WINED3DTOP_LERP
))) {
2977 This
->fixed_function_usage_map
|= (1 << i
);
2980 if ((color_op
== WINED3DTOP_BUMPENVMAP
|| color_op
== WINED3DTOP_BUMPENVMAPLUMINANCE
) && i
< MAX_TEXTURES
- 1) {
2981 This
->fixed_function_usage_map
|= (1 << (i
+ 1));
2986 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl
*This
) {
2987 unsigned int i
, tex
;
2990 device_update_fixed_function_usage_map(This
);
2991 ffu_map
= This
->fixed_function_usage_map
;
2993 if (This
->max_ffp_textures
== This
->max_ffp_texture_stages
||
2994 This
->stateBlock
->lowest_disabled_stage
<= This
->max_ffp_textures
) {
2995 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
2997 if (!(ffu_map
& 1)) continue;
2999 if (This
->texUnitMap
[i
] != i
) {
3000 device_map_stage(This
, i
, i
);
3001 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3002 markTextureStagesDirty(This
, i
);
3008 /* Now work out the mapping */
3010 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
3012 if (!(ffu_map
& 1)) continue;
3014 if (This
->texUnitMap
[i
] != tex
) {
3015 device_map_stage(This
, i
, tex
);
3016 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3017 markTextureStagesDirty(This
, i
);
3024 static void device_map_psamplers(IWineD3DDeviceImpl
*This
) {
3025 const WINED3DSAMPLER_TEXTURE_TYPE
*sampler_type
=
3026 ((IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
)->baseShader
.reg_maps
.sampler_type
;
3029 for (i
= 0; i
< MAX_FRAGMENT_SAMPLERS
; ++i
) {
3030 if (sampler_type
[i
] && This
->texUnitMap
[i
] != i
)
3032 device_map_stage(This
, i
, i
);
3033 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3034 if (i
< MAX_TEXTURES
) {
3035 markTextureStagesDirty(This
, i
);
3041 static BOOL
device_unit_free_for_vs(IWineD3DDeviceImpl
*This
, const DWORD
*pshader_sampler_tokens
,
3042 const DWORD
*vshader_sampler_tokens
, DWORD unit
)
3044 DWORD current_mapping
= This
->rev_tex_unit_map
[unit
];
3046 /* Not currently used */
3047 if (current_mapping
== WINED3D_UNMAPPED_STAGE
) return TRUE
;
3049 if (current_mapping
< MAX_FRAGMENT_SAMPLERS
) {
3050 /* Used by a fragment sampler */
3052 if (!pshader_sampler_tokens
) {
3053 /* No pixel shader, check fixed function */
3054 return current_mapping
>= MAX_TEXTURES
|| !(This
->fixed_function_usage_map
& (1 << current_mapping
));
3057 /* Pixel shader, check the shader's sampler map */
3058 return !pshader_sampler_tokens
[current_mapping
];
3061 /* Used by a vertex sampler */
3062 return !vshader_sampler_tokens
[current_mapping
- MAX_FRAGMENT_SAMPLERS
];
3065 static void device_map_vsamplers(IWineD3DDeviceImpl
*This
, BOOL ps
) {
3066 const WINED3DSAMPLER_TEXTURE_TYPE
*vshader_sampler_type
=
3067 ((IWineD3DVertexShaderImpl
*)This
->stateBlock
->vertexShader
)->baseShader
.reg_maps
.sampler_type
;
3068 const WINED3DSAMPLER_TEXTURE_TYPE
*pshader_sampler_type
= NULL
;
3069 int start
= min(MAX_COMBINED_SAMPLERS
, This
->adapter
->gl_info
.limits
.combined_samplers
) - 1;
3073 IWineD3DPixelShaderImpl
*pshader
= (IWineD3DPixelShaderImpl
*)This
->stateBlock
->pixelShader
;
3075 /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3076 * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3077 pshader_sampler_type
= pshader
->baseShader
.reg_maps
.sampler_type
;
3080 for (i
= 0; i
< MAX_VERTEX_SAMPLERS
; ++i
) {
3081 DWORD vsampler_idx
= i
+ MAX_FRAGMENT_SAMPLERS
;
3082 if (vshader_sampler_type
[i
])
3084 if (This
->texUnitMap
[vsampler_idx
] != WINED3D_UNMAPPED_STAGE
)
3086 /* Already mapped somewhere */
3090 while (start
>= 0) {
3091 if (device_unit_free_for_vs(This
, pshader_sampler_type
, vshader_sampler_type
, start
))
3093 device_map_stage(This
, vsampler_idx
, start
);
3094 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(vsampler_idx
));
3106 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl
*This
) {
3107 BOOL vs
= use_vs(This
->stateBlock
);
3108 BOOL ps
= use_ps(This
->stateBlock
);
3111 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3112 * that would be really messy and require shader recompilation
3113 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3114 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3117 device_map_psamplers(This
);
3119 device_map_fixed_function_samplers(This
);
3123 device_map_vsamplers(This
, ps
);
3127 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
*pShader
) {
3128 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3129 IWineD3DPixelShader
*oldShader
= This
->updateStateBlock
->pixelShader
;
3130 This
->updateStateBlock
->pixelShader
= pShader
;
3131 This
->updateStateBlock
->changed
.pixelShader
= TRUE
;
3133 /* Handle recording of state blocks */
3134 if (This
->isRecordingState
) {
3135 TRACE("Recording... not performing anything\n");
3138 if (This
->isRecordingState
) {
3139 TRACE("Recording... not performing anything\n");
3140 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3141 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3145 if(pShader
== oldShader
) {
3146 TRACE("App is setting the old pixel shader over, nothing to do\n");
3150 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3151 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3153 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
3154 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
3159 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
**ppShader
) {
3160 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3162 if (NULL
== ppShader
) {
3163 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This
);
3164 return WINED3DERR_INVALIDCALL
;
3167 *ppShader
= This
->stateBlock
->pixelShader
;
3168 if (NULL
!= *ppShader
) {
3169 IWineD3DPixelShader_AddRef(*ppShader
);
3171 TRACE("(%p) : returning %p\n", This
, *ppShader
);
3175 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(
3176 IWineD3DDevice
*iface
,
3178 CONST BOOL
*srcData
,
3181 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3182 unsigned int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3184 TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3185 iface
, srcData
, start
, count
);
3187 if (!srcData
|| start
>= MAX_CONST_B
) return WINED3DERR_INVALIDCALL
;
3189 memcpy(&This
->updateStateBlock
->pixelShaderConstantB
[start
], srcData
, cnt
* sizeof(BOOL
));
3190 for (i
= 0; i
< cnt
; i
++)
3191 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3193 for (i
= start
; i
< cnt
+ start
; ++i
) {
3194 This
->updateStateBlock
->changed
.pixelShaderConstantsB
|= (1 << i
);
3197 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3202 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(
3203 IWineD3DDevice
*iface
,
3208 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3209 int cnt
= min(count
, MAX_CONST_B
- start
);
3211 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3212 iface
, dstData
, start
, count
);
3214 if (dstData
== NULL
|| cnt
< 0)
3215 return WINED3DERR_INVALIDCALL
;
3217 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantB
[start
], cnt
* sizeof(BOOL
));
3221 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(
3222 IWineD3DDevice
*iface
,
3227 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3228 unsigned int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3230 TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3231 iface
, srcData
, start
, count
);
3233 if (!srcData
|| start
>= MAX_CONST_I
) return WINED3DERR_INVALIDCALL
;
3235 memcpy(&This
->updateStateBlock
->pixelShaderConstantI
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3236 for (i
= 0; i
< cnt
; i
++)
3237 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3238 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3240 for (i
= start
; i
< cnt
+ start
; ++i
) {
3241 This
->updateStateBlock
->changed
.pixelShaderConstantsI
|= (1 << i
);
3244 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3249 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(
3250 IWineD3DDevice
*iface
,
3255 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3256 int cnt
= min(count
, MAX_CONST_I
- start
);
3258 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3259 iface
, dstData
, start
, count
);
3261 if (dstData
== NULL
|| cnt
< 0)
3262 return WINED3DERR_INVALIDCALL
;
3264 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantI
[start
* 4], cnt
* sizeof(int) * 4);
3268 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(
3269 IWineD3DDevice
*iface
,
3271 CONST
float *srcData
,
3274 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3277 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3278 iface
, srcData
, start
, count
);
3280 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3281 if (srcData
== NULL
|| start
+ count
> This
->d3d_pshader_constantF
|| start
> This
->d3d_pshader_constantF
)
3282 return WINED3DERR_INVALIDCALL
;
3284 memcpy(&This
->updateStateBlock
->pixelShaderConstantF
[start
* 4], srcData
, count
* sizeof(float) * 4);
3286 for (i
= 0; i
< count
; i
++)
3287 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3288 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3291 if (!This
->isRecordingState
)
3293 This
->shader_backend
->shader_update_float_pixel_constants(iface
, start
, count
);
3294 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3297 memset(This
->updateStateBlock
->changed
.pixelShaderConstantsF
+ start
, 1,
3298 sizeof(*This
->updateStateBlock
->changed
.pixelShaderConstantsF
) * count
);
3303 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(
3304 IWineD3DDevice
*iface
,
3309 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3310 int cnt
= min(count
, This
->d3d_pshader_constantF
- start
);
3312 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3313 iface
, dstData
, start
, count
);
3315 if (dstData
== NULL
|| cnt
< 0)
3316 return WINED3DERR_INVALIDCALL
;
3318 memcpy(dstData
, &This
->stateBlock
->pixelShaderConstantF
[start
* 4], cnt
* sizeof(float) * 4);
3322 /* Context activation is done by the caller. */
3323 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3324 static HRESULT
process_vertices_strided(IWineD3DDeviceImpl
*This
, DWORD dwDestIndex
, DWORD dwCount
,
3325 const struct wined3d_stream_info
*stream_info
, struct wined3d_buffer
*dest
, DWORD dwFlags
,
3328 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
3329 char *dest_ptr
, *dest_conv
= NULL
, *dest_conv_addr
= NULL
;
3332 WINED3DMATRIX mat
, proj_mat
, view_mat
, world_mat
;
3336 if (stream_info
->use_map
& (1 << WINED3D_FFP_NORMAL
))
3338 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3341 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_POSITION
)))
3343 ERR("Source has no position mask\n");
3344 return WINED3DERR_INVALIDCALL
;
3347 /* We might access VBOs from this code, so hold the lock */
3350 if (dest
->resource
.allocatedMemory
== NULL
) {
3351 buffer_get_sysmem(dest
);
3354 /* Get a pointer into the destination vbo(create one if none exists) and
3355 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3357 if (!dest
->buffer_object
&& gl_info
->supported
[ARB_VERTEX_BUFFER_OBJECT
])
3359 dest
->flags
|= WINED3D_BUFFER_CREATEBO
;
3360 IWineD3DBuffer_PreLoad((IWineD3DBuffer
*)dest
);
3363 if (dest
->buffer_object
)
3365 unsigned char extrabytes
= 0;
3366 /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
3367 * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
3368 * this may write 4 extra bytes beyond the area that should be written
3370 if(DestFVF
== WINED3DFVF_XYZ
) extrabytes
= 4;
3371 dest_conv_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwCount
* get_flexible_vertex_size(DestFVF
) + extrabytes
);
3372 if(!dest_conv_addr
) {
3373 ERR("Out of memory\n");
3374 /* Continue without storing converted vertices */
3376 dest_conv
= dest_conv_addr
;
3380 * a) WINED3DRS_CLIPPING is enabled
3381 * b) WINED3DVOP_CLIP is passed
3383 if(This
->stateBlock
->renderState
[WINED3DRS_CLIPPING
]) {
3384 static BOOL warned
= FALSE
;
3386 * The clipping code is not quite correct. Some things need
3387 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3388 * so disable clipping for now.
3389 * (The graphics in Half-Life are broken, and my processvertices
3390 * test crashes with IDirect3DDevice3)
3396 FIXME("Clipping is broken and disabled for now\n");
3398 } else doClip
= FALSE
;
3399 dest_ptr
= ((char *) buffer_get_sysmem(dest
)) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
3401 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
3404 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
3405 WINED3DTS_PROJECTION
,
3407 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
3408 WINED3DTS_WORLDMATRIX(0),
3411 TRACE("View mat:\n");
3412 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
);
3413 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
);
3414 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
);
3415 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
);
3417 TRACE("Proj mat:\n");
3418 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
);
3419 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
);
3420 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
);
3421 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
);
3423 TRACE("World mat:\n");
3424 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
);
3425 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
);
3426 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
);
3427 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
);
3429 /* Get the viewport */
3430 IWineD3DDevice_GetViewport( (IWineD3DDevice
*) This
, &vp
);
3431 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3432 vp
.X
, vp
.Y
, vp
.Width
, vp
.Height
, vp
.MinZ
, vp
.MaxZ
);
3434 multiply_matrix(&mat
,&view_mat
,&world_mat
);
3435 multiply_matrix(&mat
,&proj_mat
,&mat
);
3437 numTextures
= (DestFVF
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
3439 for (i
= 0; i
< dwCount
; i
+= 1) {
3440 unsigned int tex_index
;
3442 if ( ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZ
) ||
3443 ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) ) {
3444 /* The position first */
3445 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_POSITION
];
3446 const float *p
= (const float *)(element
->data
+ i
* element
->stride
);
3448 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
3450 /* Multiplication with world, view and projection matrix */
3451 x
= (p
[0] * mat
.u
.s
._11
) + (p
[1] * mat
.u
.s
._21
) + (p
[2] * mat
.u
.s
._31
) + (1.0f
* mat
.u
.s
._41
);
3452 y
= (p
[0] * mat
.u
.s
._12
) + (p
[1] * mat
.u
.s
._22
) + (p
[2] * mat
.u
.s
._32
) + (1.0f
* mat
.u
.s
._42
);
3453 z
= (p
[0] * mat
.u
.s
._13
) + (p
[1] * mat
.u
.s
._23
) + (p
[2] * mat
.u
.s
._33
) + (1.0f
* mat
.u
.s
._43
);
3454 rhw
= (p
[0] * mat
.u
.s
._14
) + (p
[1] * mat
.u
.s
._24
) + (p
[2] * mat
.u
.s
._34
) + (1.0f
* mat
.u
.s
._44
);
3456 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
3458 /* WARNING: The following things are taken from d3d7 and were not yet checked
3459 * against d3d8 or d3d9!
3462 /* Clipping conditions: From msdn
3464 * A vertex is clipped if it does not match the following requirements
3468 * 0 < rhw ( Not in d3d7, but tested in d3d7)
3470 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3471 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3476 ( (-rhw
-eps
< x
) && (-rhw
-eps
< y
) && ( -eps
< z
) &&
3477 (x
<= rhw
+ eps
) && (y
<= rhw
+ eps
) && (z
<= rhw
+ eps
) &&
3480 /* "Normal" viewport transformation (not clipped)
3481 * 1) The values are divided by rhw
3482 * 2) The y axis is negative, so multiply it with -1
3483 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3484 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3485 * 4) Multiply x with Width/2 and add Width/2
3486 * 5) The same for the height
3487 * 6) Add the viewpoint X and Y to the 2D coordinates and
3488 * The minimum Z value to z
3489 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3491 * Well, basically it's simply a linear transformation into viewport
3503 z
*= vp
.MaxZ
- vp
.MinZ
;
3505 x
+= vp
.Width
/ 2 + vp
.X
;
3506 y
+= vp
.Height
/ 2 + vp
.Y
;
3511 /* That vertex got clipped
3512 * Contrary to OpenGL it is not dropped completely, it just
3513 * undergoes a different calculation.
3515 TRACE("Vertex got clipped\n");
3522 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3523 * outside of the main vertex buffer memory. That needs some more
3528 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
3531 ( (float *) dest_ptr
)[0] = x
;
3532 ( (float *) dest_ptr
)[1] = y
;
3533 ( (float *) dest_ptr
)[2] = z
;
3534 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
3536 dest_ptr
+= 3 * sizeof(float);
3538 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
3539 dest_ptr
+= sizeof(float);
3544 ( (float *) dest_conv
)[0] = x
* w
;
3545 ( (float *) dest_conv
)[1] = y
* w
;
3546 ( (float *) dest_conv
)[2] = z
* w
;
3547 ( (float *) dest_conv
)[3] = w
;
3549 dest_conv
+= 3 * sizeof(float);
3551 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
3552 dest_conv
+= sizeof(float);
3556 if (DestFVF
& WINED3DFVF_PSIZE
) {
3557 dest_ptr
+= sizeof(DWORD
);
3558 if(dest_conv
) dest_conv
+= sizeof(DWORD
);
3560 if (DestFVF
& WINED3DFVF_NORMAL
) {
3561 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_NORMAL
];
3562 const float *normal
= (const float *)(element
->data
+ i
* element
->stride
);
3563 /* AFAIK this should go into the lighting information */
3564 FIXME("Didn't expect the destination to have a normal\n");
3565 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
3567 copy_and_next(dest_conv
, normal
, 3 * sizeof(float));
3571 if (DestFVF
& WINED3DFVF_DIFFUSE
) {
3572 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_DIFFUSE
];
3573 const DWORD
*color_d
= (const DWORD
*)(element
->data
+ i
* element
->stride
);
3574 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_DIFFUSE
)))
3576 static BOOL warned
= FALSE
;
3579 ERR("No diffuse color in source, but destination has one\n");
3583 *( (DWORD
*) dest_ptr
) = 0xffffffff;
3584 dest_ptr
+= sizeof(DWORD
);
3587 *( (DWORD
*) dest_conv
) = 0xffffffff;
3588 dest_conv
+= sizeof(DWORD
);
3592 copy_and_next(dest_ptr
, color_d
, sizeof(DWORD
));
3594 *( (DWORD
*) dest_conv
) = (*color_d
& 0xff00ff00) ; /* Alpha + green */
3595 *( (DWORD
*) dest_conv
) |= (*color_d
& 0x00ff0000) >> 16; /* Red */
3596 *( (DWORD
*) dest_conv
) |= (*color_d
& 0xff0000ff) << 16; /* Blue */
3597 dest_conv
+= sizeof(DWORD
);
3602 if (DestFVF
& WINED3DFVF_SPECULAR
)
3604 /* What's the color value in the feedback buffer? */
3605 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_SPECULAR
];
3606 const DWORD
*color_s
= (const DWORD
*)(element
->data
+ i
* element
->stride
);
3607 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_SPECULAR
)))
3609 static BOOL warned
= FALSE
;
3612 ERR("No specular color in source, but destination has one\n");
3616 *( (DWORD
*) dest_ptr
) = 0xFF000000;
3617 dest_ptr
+= sizeof(DWORD
);
3620 *( (DWORD
*) dest_conv
) = 0xFF000000;
3621 dest_conv
+= sizeof(DWORD
);
3625 copy_and_next(dest_ptr
, color_s
, sizeof(DWORD
));
3627 *( (DWORD
*) dest_conv
) = (*color_s
& 0xff00ff00) ; /* Alpha + green */
3628 *( (DWORD
*) dest_conv
) |= (*color_s
& 0x00ff0000) >> 16; /* Red */
3629 *( (DWORD
*) dest_conv
) |= (*color_s
& 0xff0000ff) << 16; /* Blue */
3630 dest_conv
+= sizeof(DWORD
);
3635 for (tex_index
= 0; tex_index
< numTextures
; tex_index
++) {
3636 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_TEXCOORD0
+ tex_index
];
3637 const float *tex_coord
= (const float *)(element
->data
+ i
* element
->stride
);
3638 if (!(stream_info
->use_map
& (1 << (WINED3D_FFP_TEXCOORD0
+ tex_index
))))
3640 ERR("No source texture, but destination requests one\n");
3641 dest_ptr
+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
3642 if(dest_conv
) dest_conv
+= GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
3645 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
3647 copy_and_next(dest_conv
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
3654 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->buffer_object
));
3655 checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
3656 GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB
, dwDestIndex
* get_flexible_vertex_size(DestFVF
),
3657 dwCount
* get_flexible_vertex_size(DestFVF
),
3659 checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
3660 HeapFree(GetProcessHeap(), 0, dest_conv_addr
);
3667 #undef copy_and_next
3669 static HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
, UINT SrcStartIndex
, UINT DestIndex
,
3670 UINT VertexCount
, IWineD3DBuffer
*pDestBuffer
, IWineD3DVertexDeclaration
*pVertexDecl
, DWORD Flags
,
3673 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3674 struct wined3d_stream_info stream_info
;
3675 struct wined3d_context
*context
;
3676 BOOL vbo
= FALSE
, streamWasUP
= This
->stateBlock
->streamIsUP
;
3679 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
, pVertexDecl
, Flags
);
3682 ERR("Output vertex declaration not implemented yet\n");
3685 /* Need any context to write to the vbo. */
3686 context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
3688 /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
3689 * control the streamIsUP flag, thus restore it afterwards.
3691 This
->stateBlock
->streamIsUP
= FALSE
;
3692 device_stream_info_from_declaration(This
, FALSE
, &stream_info
, &vbo
);
3693 This
->stateBlock
->streamIsUP
= streamWasUP
;
3695 if(vbo
|| SrcStartIndex
) {
3697 /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
3698 * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
3700 * Also get the start index in, but only loop over all elements if there's something to add at all.
3702 for (i
= 0; i
< (sizeof(stream_info
.elements
) / sizeof(*stream_info
.elements
)); ++i
)
3704 struct wined3d_stream_info_element
*e
;
3706 if (!(stream_info
.use_map
& (1 << i
))) continue;
3708 e
= &stream_info
.elements
[i
];
3709 if (e
->buffer_object
)
3711 struct wined3d_buffer
*vb
= (struct wined3d_buffer
*)This
->stateBlock
->streamSource
[e
->stream_idx
];
3712 e
->buffer_object
= 0;
3713 e
->data
= (BYTE
*)((unsigned long)e
->data
+ (unsigned long)buffer_get_sysmem(vb
));
3715 GL_EXTCALL(glDeleteBuffersARB(1, &vb
->buffer_object
));
3716 vb
->buffer_object
= 0;
3719 if (e
->data
) e
->data
+= e
->stride
* SrcStartIndex
;
3723 hr
= process_vertices_strided(This
, DestIndex
, VertexCount
, &stream_info
,
3724 (struct wined3d_buffer
*)pDestBuffer
, Flags
, DestFVF
);
3726 context_release(context
);
3732 * Get / Set Texture Stage States
3733 * TODO: Verify against dx9 definitions
3735 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
) {
3736 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3737 DWORD oldValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
3739 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
3741 if (Stage
>= MAX_TEXTURES
) {
3742 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring\n", Stage
, MAX_TEXTURES
- 1);
3746 This
->updateStateBlock
->changed
.textureState
[Stage
] |= 1 << Type
;
3747 This
->updateStateBlock
->textureState
[Stage
][Type
] = Value
;
3749 if (This
->isRecordingState
) {
3750 TRACE("Recording... not performing anything\n");
3754 /* Checked after the assignments to allow proper stateblock recording */
3755 if(oldValue
== Value
) {
3756 TRACE("App is setting the old value over, nothing to do\n");
3760 if(Stage
> This
->stateBlock
->lowest_disabled_stage
&&
3761 This
->StateTable
[STATE_TEXTURESTAGE(0, Type
)].representative
== STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP
)) {
3762 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3763 * Changes in other states are important on disabled stages too
3768 if(Type
== WINED3DTSS_COLOROP
) {
3771 if(Value
== WINED3DTOP_DISABLE
&& oldValue
!= WINED3DTOP_DISABLE
) {
3772 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3773 * they have to be disabled
3775 * The current stage is dirtified below.
3777 for(i
= Stage
+ 1; i
< This
->stateBlock
->lowest_disabled_stage
; i
++) {
3778 TRACE("Additionally dirtifying stage %u\n", i
);
3779 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
3781 This
->stateBlock
->lowest_disabled_stage
= Stage
;
3782 TRACE("New lowest disabled: %u\n", Stage
);
3783 } else if(Value
!= WINED3DTOP_DISABLE
&& oldValue
== WINED3DTOP_DISABLE
) {
3784 /* Previously disabled stage enabled. Stages above it may need enabling
3785 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3786 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3788 * Again stage Stage doesn't need to be dirtified here, it is handled below.
3791 for (i
= Stage
+ 1; i
< This
->adapter
->gl_info
.limits
.texture_stages
; ++i
)
3793 if(This
->updateStateBlock
->textureState
[i
][WINED3DTSS_COLOROP
] == WINED3DTOP_DISABLE
) {
3796 TRACE("Additionally dirtifying stage %u due to enable\n", i
);
3797 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
3799 This
->stateBlock
->lowest_disabled_stage
= i
;
3800 TRACE("New lowest disabled: %u\n", i
);
3804 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, Type
));
3809 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
* pValue
) {
3810 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3811 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This
, Stage
, Type
, This
->updateStateBlock
->textureState
[Stage
][Type
]);
3812 *pValue
= This
->updateStateBlock
->textureState
[Stage
][Type
];
3819 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
,
3820 DWORD stage
, IWineD3DBaseTexture
*texture
)
3822 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3823 IWineD3DBaseTexture
*prev
;
3825 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
3827 if (stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& stage
<= WINED3DVERTEXTEXTURESAMPLER3
)
3828 stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3830 /* Windows accepts overflowing this array... we do not. */
3831 if (stage
>= sizeof(This
->stateBlock
->textures
) / sizeof(*This
->stateBlock
->textures
))
3833 WARN("Ignoring invalid stage %u.\n", stage
);
3837 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
3838 if (texture
&& ((IWineD3DTextureImpl
*)texture
)->resource
.pool
== WINED3DPOOL_SCRATCH
)
3840 WARN("Rejecting attempt to set scratch texture.\n");
3841 return WINED3DERR_INVALIDCALL
;
3844 This
->updateStateBlock
->changed
.textures
|= 1 << stage
;
3846 prev
= This
->updateStateBlock
->textures
[stage
];
3847 TRACE("Previous texture %p.\n", prev
);
3849 if (texture
== prev
)
3851 TRACE("App is setting the same texture again, nothing to do.\n");
3855 TRACE("Setting new texture to %p.\n", texture
);
3856 This
->updateStateBlock
->textures
[stage
] = texture
;
3858 if (This
->isRecordingState
)
3860 TRACE("Recording... not performing anything\n");
3862 if (texture
) IWineD3DBaseTexture_AddRef(texture
);
3863 if (prev
) IWineD3DBaseTexture_Release(prev
);
3870 IWineD3DBaseTextureImpl
*t
= (IWineD3DBaseTextureImpl
*)texture
;
3871 LONG bind_count
= InterlockedIncrement(&t
->baseTexture
.bindCount
);
3872 UINT dimensions
= IWineD3DBaseTexture_GetTextureDimensions(texture
);
3874 IWineD3DBaseTexture_AddRef(texture
);
3876 if (!prev
|| dimensions
!= IWineD3DBaseTexture_GetTextureDimensions(prev
))
3878 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
3881 if (!prev
&& stage
< MAX_TEXTURES
)
3883 /* The source arguments for color and alpha ops have different
3884 * meanings when a NULL texture is bound, so the COLOROP and
3885 * ALPHAOP have to be dirtified. */
3886 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_COLOROP
));
3887 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_ALPHAOP
));
3890 if (bind_count
== 1) t
->baseTexture
.sampler
= stage
;
3895 IWineD3DBaseTextureImpl
*t
= (IWineD3DBaseTextureImpl
*)prev
;
3896 LONG bind_count
= InterlockedDecrement(&t
->baseTexture
.bindCount
);
3898 IWineD3DBaseTexture_Release(prev
);
3900 if (!texture
&& stage
< MAX_TEXTURES
)
3902 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_COLOROP
));
3903 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_ALPHAOP
));
3906 if (bind_count
&& t
->baseTexture
.sampler
== stage
)
3910 /* Search for other stages the texture is bound to. Shouldn't
3911 * happen if applications bind textures to a single stage only. */
3912 TRACE("Searching for other stages the texture is bound to.\n");
3913 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
3915 if (This
->updateStateBlock
->textures
[i
] == prev
)
3917 TRACE("Texture is also bound to stage %u.\n", i
);
3918 t
->baseTexture
.sampler
= i
;
3925 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(stage
));
3930 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
** ppTexture
) {
3931 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3933 TRACE("(%p) : Stage %#x, ppTexture %p\n", This
, Stage
, ppTexture
);
3935 if (Stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& Stage
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3936 Stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3939 if (Stage
>= sizeof(This
->stateBlock
->textures
)/sizeof(This
->stateBlock
->textures
[0])) {
3940 ERR("Current stage overflows textures array (stage %d)\n", Stage
);
3941 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3944 *ppTexture
=This
->stateBlock
->textures
[Stage
];
3946 IWineD3DBaseTexture_AddRef(*ppTexture
);
3948 TRACE("(%p) : Returning %p\n", This
, *ppTexture
);
3956 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT swapchain_idx
,
3957 UINT backbuffer_idx
, WINED3DBACKBUFFER_TYPE backbuffer_type
, IWineD3DSurface
**backbuffer
)
3959 IWineD3DSwapChain
*swapchain
;
3962 TRACE("iface %p, swapchain_idx %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
3963 iface
, swapchain_idx
, backbuffer_idx
, backbuffer_type
, backbuffer
);
3965 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
3968 WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx
, hr
);
3972 hr
= IWineD3DSwapChain_GetBackBuffer(swapchain
, backbuffer_idx
, backbuffer_type
, backbuffer
);
3973 IWineD3DSwapChain_Release(swapchain
);
3976 WARN("Failed to get backbuffer %u, hr %#x.\n", backbuffer_idx
, hr
);
3983 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
* pCaps
) {
3984 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3985 WARN("(%p) : stub, calling idirect3d for now\n", This
);
3986 return IWineD3D_GetDeviceCaps(This
->wined3d
, This
->adapter
->ordinal
, This
->devType
, pCaps
);
3989 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
3990 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3991 IWineD3DSwapChain
*swapChain
;
3994 if(iSwapChain
> 0) {
3995 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
3996 if (hr
== WINED3D_OK
) {
3997 hr
= IWineD3DSwapChain_GetDisplayMode(swapChain
, pMode
);
3998 IWineD3DSwapChain_Release(swapChain
);
4000 FIXME("(%p) Error getting display mode\n", This
);
4003 /* Don't read the real display mode,
4004 but return the stored mode instead. X11 can't change the color
4005 depth, and some apps are pretty angry if they SetDisplayMode from
4006 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4008 Also don't relay to the swapchain because with ddraw it's possible
4009 that there isn't a swapchain at all */
4010 pMode
->Width
= This
->ddraw_width
;
4011 pMode
->Height
= This
->ddraw_height
;
4012 pMode
->Format
= This
->ddraw_format
;
4013 pMode
->RefreshRate
= 0;
4021 * Stateblock related functions
4024 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
) {
4025 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4026 IWineD3DStateBlock
*stateblock
;
4029 TRACE("(%p)\n", This
);
4031 if (This
->isRecordingState
) return WINED3DERR_INVALIDCALL
;
4033 hr
= IWineD3DDeviceImpl_CreateStateBlock(iface
, WINED3DSBT_RECORDED
, &stateblock
, NULL
);
4034 if (FAILED(hr
)) return hr
;
4036 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
4037 This
->updateStateBlock
= (IWineD3DStateBlockImpl
*)stateblock
;
4038 This
->isRecordingState
= TRUE
;
4040 TRACE("(%p) recording stateblock %p\n", This
, stateblock
);
4045 static HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
, IWineD3DStateBlock
** ppStateBlock
) {
4046 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4047 IWineD3DStateBlockImpl
*object
= This
->updateStateBlock
;
4049 if (!This
->isRecordingState
) {
4050 WARN("(%p) not recording! returning error\n", This
);
4051 *ppStateBlock
= NULL
;
4052 return WINED3DERR_INVALIDCALL
;
4055 stateblock_init_contained_states(object
);
4057 *ppStateBlock
= (IWineD3DStateBlock
*) object
;
4058 This
->isRecordingState
= FALSE
;
4059 This
->updateStateBlock
= This
->stateBlock
;
4060 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
4061 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4062 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This
, *ppStateBlock
);
4067 * Scene related functions
4069 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
4070 /* At the moment we have no need for any functionality at the beginning
4072 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4073 TRACE("(%p)\n", This
);
4076 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4077 return WINED3DERR_INVALIDCALL
;
4079 This
->inScene
= TRUE
;
4083 static HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
)
4085 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4086 struct wined3d_context
*context
;
4088 TRACE("(%p)\n", This
);
4090 if(!This
->inScene
) {
4091 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4092 return WINED3DERR_INVALIDCALL
;
4095 context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
4096 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4098 /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4100 context_release(context
);
4102 This
->inScene
= FALSE
;
4106 static HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
,
4107 const RECT
*pSourceRect
, const RECT
*pDestRect
,
4108 HWND hDestWindowOverride
, const RGNDATA
*pDirtyRegion
)
4110 IWineD3DSwapChain
*swapChain
= NULL
;
4112 int swapchains
= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface
);
4114 TRACE("iface %p.\n", iface
);
4116 for(i
= 0 ; i
< swapchains
; i
++) {
4118 IWineD3DDeviceImpl_GetSwapChain(iface
, i
, &swapChain
);
4119 TRACE("presentinng chain %d, %p\n", i
, swapChain
);
4120 IWineD3DSwapChain_Present(swapChain
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
, 0);
4121 IWineD3DSwapChain_Release(swapChain
);
4127 /* Not called from the VTable (internal subroutine) */
4128 HRESULT
IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl
*This
, IWineD3DSurfaceImpl
*target
, DWORD Count
,
4129 CONST WINED3DRECT
* pRects
, DWORD Flags
, WINED3DCOLOR Color
,
4130 float Z
, DWORD Stencil
) {
4131 GLbitfield glMask
= 0;
4133 WINED3DRECT curRect
;
4135 const WINED3DVIEWPORT
*vp
= &This
->stateBlock
->viewport
;
4136 UINT drawable_width
, drawable_height
;
4137 IWineD3DSurfaceImpl
*depth_stencil
= (IWineD3DSurfaceImpl
*) This
->stencilBufferTarget
;
4138 IWineD3DSwapChainImpl
*swapchain
= NULL
;
4139 struct wined3d_context
*context
;
4141 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
4142 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
4143 * for the cleared parts, and the untouched parts.
4145 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
4146 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
4147 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
4148 * checking all this if the dest surface is in the drawable anyway.
4150 if((Flags
& WINED3DCLEAR_TARGET
) && !(target
->Flags
& SFLAG_INDRAWABLE
)) {
4152 if(vp
->X
!= 0 || vp
->Y
!= 0 ||
4153 vp
->Width
< target
->currentDesc
.Width
|| vp
->Height
< target
->currentDesc
.Height
) {
4154 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
4157 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
] && (
4158 This
->stateBlock
->scissorRect
.left
> 0 || This
->stateBlock
->scissorRect
.top
> 0 ||
4159 This
->stateBlock
->scissorRect
.right
< target
->currentDesc
.Width
||
4160 This
->stateBlock
->scissorRect
.bottom
< target
->currentDesc
.Height
)) {
4161 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
4164 if(Count
> 0 && pRects
&& (
4165 pRects
[0].x1
> 0 || pRects
[0].y1
> 0 ||
4166 pRects
[0].x2
< target
->currentDesc
.Width
||
4167 pRects
[0].y2
< target
->currentDesc
.Height
)) {
4168 IWineD3DSurface_LoadLocation((IWineD3DSurface
*) target
, SFLAG_INDRAWABLE
, NULL
);
4175 context
= context_acquire(This
, (IWineD3DSurface
*)target
, CTXUSAGE_CLEAR
);
4177 target
->get_drawable_size(context
, &drawable_width
, &drawable_height
);
4181 /* Only set the values up once, as they are not changing */
4182 if (Flags
& WINED3DCLEAR_STENCIL
) {
4183 glClearStencil(Stencil
);
4184 checkGLcall("glClearStencil");
4185 glMask
= glMask
| GL_STENCIL_BUFFER_BIT
;
4186 glStencilMask(0xFFFFFFFF);
4189 if (Flags
& WINED3DCLEAR_ZBUFFER
) {
4190 DWORD location
= context
->render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
4191 glDepthMask(GL_TRUE
);
4193 checkGLcall("glClearDepth");
4194 glMask
= glMask
| GL_DEPTH_BUFFER_BIT
;
4195 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZWRITEENABLE
));
4197 if (vp
->X
!= 0 || vp
->Y
!= 0 ||
4198 vp
->Width
< depth_stencil
->currentDesc
.Width
|| vp
->Height
< depth_stencil
->currentDesc
.Height
) {
4199 surface_load_ds_location(This
->stencilBufferTarget
, context
, location
);
4201 else if (This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
] && (
4202 This
->stateBlock
->scissorRect
.left
> 0 || This
->stateBlock
->scissorRect
.top
> 0 ||
4203 This
->stateBlock
->scissorRect
.right
< depth_stencil
->currentDesc
.Width
||
4204 This
->stateBlock
->scissorRect
.bottom
< depth_stencil
->currentDesc
.Height
)) {
4205 surface_load_ds_location(This
->stencilBufferTarget
, context
, location
);
4207 else if (Count
> 0 && pRects
&& (
4208 pRects
[0].x1
> 0 || pRects
[0].y1
> 0 ||
4209 pRects
[0].x2
< depth_stencil
->currentDesc
.Width
||
4210 pRects
[0].y2
< depth_stencil
->currentDesc
.Height
)) {
4211 surface_load_ds_location(This
->stencilBufferTarget
, context
, location
);
4215 if (Flags
& WINED3DCLEAR_TARGET
) {
4216 TRACE("Clearing screen with glClear to color %x\n", Color
);
4217 glClearColor(D3DCOLOR_R(Color
),
4221 checkGLcall("glClearColor");
4223 /* Clear ALL colors! */
4224 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
4225 glMask
= glMask
| GL_COLOR_BUFFER_BIT
;
4228 vp_rect
.left
= vp
->X
;
4229 vp_rect
.top
= vp
->Y
;
4230 vp_rect
.right
= vp
->X
+ vp
->Width
;
4231 vp_rect
.bottom
= vp
->Y
+ vp
->Height
;
4232 if (!(Count
> 0 && pRects
)) {
4233 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
]) {
4234 IntersectRect(&vp_rect
, &vp_rect
, &This
->stateBlock
->scissorRect
);
4236 if (context
->render_offscreen
)
4238 glScissor(vp_rect
.left
, vp_rect
.top
,
4239 vp_rect
.right
- vp_rect
.left
, vp_rect
.bottom
- vp_rect
.top
);
4241 glScissor(vp_rect
.left
, drawable_height
- vp_rect
.bottom
,
4242 vp_rect
.right
- vp_rect
.left
, vp_rect
.bottom
- vp_rect
.top
);
4244 checkGLcall("glScissor");
4246 checkGLcall("glClear");
4248 /* Now process each rect in turn */
4249 for (i
= 0; i
< Count
; i
++) {
4250 /* Note gl uses lower left, width/height */
4251 IntersectRect((RECT
*)&curRect
, &vp_rect
, (const RECT
*)&pRects
[i
]);
4252 if(This
->stateBlock
->renderState
[WINED3DRS_SCISSORTESTENABLE
]) {
4253 IntersectRect((RECT
*) &curRect
, (RECT
*) &curRect
, &This
->stateBlock
->scissorRect
);
4255 TRACE("(%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This
,
4256 pRects
[i
].x1
, pRects
[i
].y1
, pRects
[i
].x2
, pRects
[i
].y2
,
4257 curRect
.x1
, (target
->currentDesc
.Height
- curRect
.y2
),
4258 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
4260 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4261 * The rectangle is not cleared, no error is returned, but further rectanlges are
4262 * still cleared if they are valid
4264 if(curRect
.x1
> curRect
.x2
|| curRect
.y1
> curRect
.y2
) {
4265 TRACE("Rectangle with negative dimensions, ignoring\n");
4269 if (context
->render_offscreen
)
4271 glScissor(curRect
.x1
, curRect
.y1
,
4272 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
4274 glScissor(curRect
.x1
, drawable_height
- curRect
.y2
,
4275 curRect
.x2
- curRect
.x1
, curRect
.y2
- curRect
.y1
);
4277 checkGLcall("glScissor");
4280 checkGLcall("glClear");
4284 /* Restore the old values (why..?) */
4285 if (Flags
& WINED3DCLEAR_STENCIL
) {
4286 glStencilMask(This
->stateBlock
->renderState
[WINED3DRS_STENCILWRITEMASK
]);
4288 if (Flags
& WINED3DCLEAR_TARGET
) {
4289 DWORD mask
= This
->stateBlock
->renderState
[WINED3DRS_COLORWRITEENABLE
];
4290 glColorMask(mask
& WINED3DCOLORWRITEENABLE_RED
? GL_TRUE
: GL_FALSE
,
4291 mask
& WINED3DCOLORWRITEENABLE_GREEN
? GL_TRUE
: GL_FALSE
,
4292 mask
& WINED3DCOLORWRITEENABLE_BLUE
? GL_TRUE
: GL_FALSE
,
4293 mask
& WINED3DCOLORWRITEENABLE_ALPHA
? GL_TRUE
: GL_FALSE
);
4295 /* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
4296 * it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
4298 IWineD3DSurface_ModifyLocation((IWineD3DSurface
*)target
, SFLAG_INDRAWABLE
, TRUE
);
4300 if (Flags
& WINED3DCLEAR_ZBUFFER
) {
4301 /* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
4302 DWORD location
= context
->render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
4303 surface_modify_ds_location(This
->stencilBufferTarget
, location
);
4308 if (SUCCEEDED(IWineD3DSurface_GetContainer((IWineD3DSurface
*)target
, &IID_IWineD3DSwapChain
, (void **)&swapchain
))) {
4309 if (target
== (IWineD3DSurfaceImpl
*) swapchain
->frontBuffer
) {
4312 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
4315 context_release(context
);
4320 static HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD Count
, CONST WINED3DRECT
* pRects
,
4321 DWORD Flags
, WINED3DCOLOR Color
, float Z
, DWORD Stencil
) {
4322 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4323 IWineD3DSurfaceImpl
*target
= (IWineD3DSurfaceImpl
*)This
->render_targets
[0];
4325 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d)\n", This
,
4326 Count
, pRects
, Flags
, Color
, Z
, Stencil
);
4328 if(Flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
) && This
->stencilBufferTarget
== NULL
) {
4329 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4330 /* TODO: What about depth stencil buffers without stencil bits? */
4331 return WINED3DERR_INVALIDCALL
;
4334 return IWineD3DDeviceImpl_ClearSurface(This
, target
, Count
, pRects
, Flags
, Color
, Z
, Stencil
);
4341 static void WINAPI
IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice
*iface
,
4342 WINED3DPRIMITIVETYPE primitive_type
)
4344 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4346 TRACE("iface %p, primitive_type %s\n", iface
, debug_d3dprimitivetype(primitive_type
));
4348 This
->updateStateBlock
->changed
.primitive_type
= TRUE
;
4349 This
->updateStateBlock
->gl_primitive_type
= gl_primitive_type_from_d3d(primitive_type
);
4352 static void WINAPI
IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice
*iface
,
4353 WINED3DPRIMITIVETYPE
*primitive_type
)
4355 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4357 TRACE("iface %p, primitive_type %p\n", iface
, primitive_type
);
4359 *primitive_type
= d3d_primitive_type_from_gl(This
->stateBlock
->gl_primitive_type
);
4361 TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type
));
4364 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, UINT StartVertex
, UINT vertex_count
)
4366 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4368 TRACE("(%p) : start %u, count %u\n", This
, StartVertex
, vertex_count
);
4370 if(!This
->stateBlock
->vertexDecl
) {
4371 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4372 return WINED3DERR_INVALIDCALL
;
4375 /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4376 if(This
->stateBlock
->streamIsUP
) {
4377 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4378 This
->stateBlock
->streamIsUP
= FALSE
;
4381 if(This
->stateBlock
->loadBaseVertexIndex
!= 0) {
4382 This
->stateBlock
->loadBaseVertexIndex
= 0;
4383 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4385 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4386 drawPrimitive(iface
, vertex_count
, StartVertex
/* start_idx */, 0 /* indxSize */, NULL
/* indxData */);
4390 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
, UINT startIndex
, UINT index_count
)
4392 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4394 IWineD3DBuffer
*pIB
;
4397 pIB
= This
->stateBlock
->pIndexData
;
4399 /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4400 * without an index buffer set. (The first time at least...)
4401 * D3D8 simply dies, but I doubt it can do much harm to return
4402 * D3DERR_INVALIDCALL there as well. */
4403 WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This
);
4404 return WINED3DERR_INVALIDCALL
;
4407 if(!This
->stateBlock
->vertexDecl
) {
4408 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4409 return WINED3DERR_INVALIDCALL
;
4412 if(This
->stateBlock
->streamIsUP
) {
4413 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4414 This
->stateBlock
->streamIsUP
= FALSE
;
4416 vbo
= ((struct wined3d_buffer
*) pIB
)->buffer_object
;
4418 TRACE("(%p) : startIndex %u, index count %u.\n", This
, startIndex
, index_count
);
4420 if (This
->stateBlock
->IndexFmt
== WINED3DFMT_R16_UINT
) {
4426 if(This
->stateBlock
->loadBaseVertexIndex
!= This
->stateBlock
->baseVertexIndex
) {
4427 This
->stateBlock
->loadBaseVertexIndex
= This
->stateBlock
->baseVertexIndex
;
4428 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4431 drawPrimitive(iface
, index_count
, startIndex
, idxStride
,
4432 vbo
? NULL
: ((struct wined3d_buffer
*)pIB
)->resource
.allocatedMemory
);
4437 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, UINT vertex_count
,
4438 const void *pVertexStreamZeroData
, UINT VertexStreamZeroStride
)
4440 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4443 TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4444 This
, vertex_count
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4446 if(!This
->stateBlock
->vertexDecl
) {
4447 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4448 return WINED3DERR_INVALIDCALL
;
4451 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4452 vb
= This
->stateBlock
->streamSource
[0];
4453 This
->stateBlock
->streamSource
[0] = (IWineD3DBuffer
*)pVertexStreamZeroData
;
4454 if (vb
) IWineD3DBuffer_Release(vb
);
4455 This
->stateBlock
->streamOffset
[0] = 0;
4456 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
4457 This
->stateBlock
->streamIsUP
= TRUE
;
4458 This
->stateBlock
->loadBaseVertexIndex
= 0;
4460 /* TODO: Only mark dirty if drawing from a different UP address */
4461 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4463 drawPrimitive(iface
, vertex_count
, 0 /* start_idx */, 0 /* indxSize*/, NULL
/* indxData */);
4465 /* MSDN specifies stream zero settings must be set to NULL */
4466 This
->stateBlock
->streamStride
[0] = 0;
4467 This
->stateBlock
->streamSource
[0] = NULL
;
4469 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4470 * the new stream sources or use UP drawing again
4475 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
,
4476 UINT index_count
, const void *pIndexData
, WINED3DFORMAT IndexDataFormat
,
4477 const void *pVertexStreamZeroData
, UINT VertexStreamZeroStride
)
4480 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4484 TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4485 This
, index_count
, pIndexData
, IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4487 if(!This
->stateBlock
->vertexDecl
) {
4488 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4489 return WINED3DERR_INVALIDCALL
;
4492 if (IndexDataFormat
== WINED3DFMT_R16_UINT
) {
4498 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4499 vb
= This
->stateBlock
->streamSource
[0];
4500 This
->stateBlock
->streamSource
[0] = (IWineD3DBuffer
*)pVertexStreamZeroData
;
4501 if (vb
) IWineD3DBuffer_Release(vb
);
4502 This
->stateBlock
->streamIsUP
= TRUE
;
4503 This
->stateBlock
->streamOffset
[0] = 0;
4504 This
->stateBlock
->streamStride
[0] = VertexStreamZeroStride
;
4506 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4507 This
->stateBlock
->baseVertexIndex
= 0;
4508 This
->stateBlock
->loadBaseVertexIndex
= 0;
4509 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4510 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
4511 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4513 drawPrimitive(iface
, index_count
, 0 /* start_idx */, idxStride
, pIndexData
);
4515 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4516 This
->stateBlock
->streamSource
[0] = NULL
;
4517 This
->stateBlock
->streamStride
[0] = 0;
4518 ib
= This
->stateBlock
->pIndexData
;
4520 IWineD3DBuffer_Release(ib
);
4521 This
->stateBlock
->pIndexData
= NULL
;
4523 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4524 * SetStreamSource to specify a vertex buffer
4530 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice
*iface
,
4531 UINT vertex_count
, const WineDirect3DVertexStridedData
*DrawPrimStrideData
)
4533 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
4535 /* Mark the state dirty until we have nicer tracking
4536 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4539 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
4540 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4541 This
->stateBlock
->baseVertexIndex
= 0;
4542 This
->up_strided
= DrawPrimStrideData
;
4543 drawPrimitive(iface
, vertex_count
, 0, 0, NULL
);
4544 This
->up_strided
= NULL
;
4548 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice
*iface
,
4549 UINT vertex_count
, const WineDirect3DVertexStridedData
*DrawPrimStrideData
,
4550 UINT NumVertices
, const void *pIndexData
, WINED3DFORMAT IndexDataFormat
)
4552 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
4553 DWORD idxSize
= (IndexDataFormat
== WINED3DFMT_R32_UINT
? 4 : 2);
4555 /* Mark the state dirty until we have nicer tracking
4556 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4559 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
4560 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4561 This
->stateBlock
->streamIsUP
= TRUE
;
4562 This
->stateBlock
->baseVertexIndex
= 0;
4563 This
->up_strided
= DrawPrimStrideData
;
4564 drawPrimitive(iface
, vertex_count
, 0 /* start_idx */, idxSize
, pIndexData
);
4565 This
->up_strided
= NULL
;
4569 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
4570 static HRESULT
IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice
*iface
,
4571 IWineD3DVolume
*pSourceVolume
, IWineD3DVolume
*pDestinationVolume
)
4573 WINED3DLOCKED_BOX src
;
4574 WINED3DLOCKED_BOX dst
;
4577 TRACE("iface %p, src_volume %p, dst_volume %p.\n",
4578 iface
, pSourceVolume
, pDestinationVolume
);
4580 /* TODO: Implement direct loading into the gl volume instead of using memcpy and
4581 * dirtification to improve loading performance.
4583 hr
= IWineD3DVolume_LockBox(pSourceVolume
, &src
, NULL
, WINED3DLOCK_READONLY
);
4584 if(FAILED(hr
)) return hr
;
4585 hr
= IWineD3DVolume_LockBox(pDestinationVolume
, &dst
, NULL
, WINED3DLOCK_DISCARD
);
4587 IWineD3DVolume_UnlockBox(pSourceVolume
);
4591 memcpy(dst
.pBits
, src
.pBits
, ((IWineD3DVolumeImpl
*) pDestinationVolume
)->resource
.size
);
4593 hr
= IWineD3DVolume_UnlockBox(pDestinationVolume
);
4595 IWineD3DVolume_UnlockBox(pSourceVolume
);
4597 hr
= IWineD3DVolume_UnlockBox(pSourceVolume
);
4602 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice
*iface
,
4603 IWineD3DBaseTexture
*src_texture
, IWineD3DBaseTexture
*dst_texture
)
4605 unsigned int level_count
, i
;
4606 WINED3DRESOURCETYPE type
;
4609 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface
, src_texture
, dst_texture
);
4611 /* Verify that the source and destination textures are non-NULL. */
4612 if (!src_texture
|| !dst_texture
)
4614 WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
4615 return WINED3DERR_INVALIDCALL
;
4618 if (src_texture
== dst_texture
)
4620 WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
4621 return WINED3DERR_INVALIDCALL
;
4624 /* Verify that the source and destination textures are the same type. */
4625 type
= IWineD3DBaseTexture_GetType(src_texture
);
4626 if (IWineD3DBaseTexture_GetType(dst_texture
) != type
)
4628 WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
4629 return WINED3DERR_INVALIDCALL
;
4632 /* Check that both textures have the identical numbers of levels. */
4633 level_count
= IWineD3DBaseTexture_GetLevelCount(src_texture
);
4634 if (IWineD3DBaseTexture_GetLevelCount(dst_texture
) != level_count
)
4636 WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
4637 return WINED3DERR_INVALIDCALL
;
4640 /* Make sure that the destination texture is loaded. */
4641 ((IWineD3DBaseTextureImpl
*)dst_texture
)->baseTexture
.internal_preload(dst_texture
, SRGB_RGB
);
4643 /* Update every surface level of the texture. */
4646 case WINED3DRTYPE_TEXTURE
:
4648 IWineD3DSurface
*src_surface
;
4649 IWineD3DSurface
*dst_surface
;
4651 for (i
= 0; i
< level_count
; ++i
)
4653 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)src_texture
, i
, &src_surface
);
4654 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)dst_texture
, i
, &dst_surface
);
4655 hr
= IWineD3DDevice_UpdateSurface(iface
, src_surface
, NULL
, dst_surface
, NULL
);
4656 IWineD3DSurface_Release(dst_surface
);
4657 IWineD3DSurface_Release(src_surface
);
4660 WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr
);
4667 case WINED3DRTYPE_CUBETEXTURE
:
4669 IWineD3DSurface
*src_surface
;
4670 IWineD3DSurface
*dst_surface
;
4671 WINED3DCUBEMAP_FACES face
;
4673 for (i
= 0; i
< level_count
; ++i
)
4675 /* Update each cube face. */
4676 for (face
= WINED3DCUBEMAP_FACE_POSITIVE_X
; face
<= WINED3DCUBEMAP_FACE_NEGATIVE_Z
; ++face
)
4678 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)src_texture
,
4679 face
, i
, &src_surface
);
4680 if (FAILED(hr
)) ERR("Failed to get src cube surface face %u, level %u, hr %#x.\n", face
, i
, hr
);
4681 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)dst_texture
,
4682 face
, i
, &dst_surface
);
4683 if (FAILED(hr
)) ERR("Failed to get dst cube surface face %u, level %u, hr %#x.\n", face
, i
, hr
);
4684 hr
= IWineD3DDevice_UpdateSurface(iface
, src_surface
, NULL
, dst_surface
, NULL
);
4685 IWineD3DSurface_Release(dst_surface
);
4686 IWineD3DSurface_Release(src_surface
);
4689 WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr
);
4697 case WINED3DRTYPE_VOLUMETEXTURE
:
4699 IWineD3DVolume
*src_volume
;
4700 IWineD3DVolume
*dst_volume
;
4702 for (i
= 0; i
< level_count
; ++i
)
4704 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)src_texture
, i
, &src_volume
);
4705 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)dst_texture
, i
, &dst_volume
);
4706 hr
= IWineD3DDeviceImpl_UpdateVolume(iface
, src_volume
, dst_volume
);
4707 IWineD3DVolume_Release(dst_volume
);
4708 IWineD3DVolume_Release(src_volume
);
4711 WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr
);
4719 FIXME("Unsupported texture type %#x.\n", type
);
4720 return WINED3DERR_INVALIDCALL
;
4726 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,UINT iSwapChain
, IWineD3DSurface
*pDestSurface
) {
4727 IWineD3DSwapChain
*swapChain
;
4729 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
4730 if(hr
== WINED3D_OK
) {
4731 hr
= IWineD3DSwapChain_GetFrontBufferData(swapChain
, pDestSurface
);
4732 IWineD3DSwapChain_Release(swapChain
);
4737 static HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
* pNumPasses
) {
4738 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4739 IWineD3DBaseTextureImpl
*texture
;
4742 TRACE("(%p) : %p\n", This
, pNumPasses
);
4744 for(i
= 0; i
< MAX_COMBINED_SAMPLERS
; i
++) {
4745 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MINFILTER
] == WINED3DTEXF_NONE
) {
4746 WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
4747 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
4749 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MAGFILTER
] == WINED3DTEXF_NONE
) {
4750 WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
4751 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
4754 texture
= (IWineD3DBaseTextureImpl
*) This
->stateBlock
->textures
[i
];
4755 if (!texture
|| texture
->resource
.format_desc
->Flags
& WINED3DFMT_FLAG_FILTERING
) continue;
4757 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MAGFILTER
] != WINED3DTEXF_POINT
) {
4758 WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i
);
4761 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MINFILTER
] != WINED3DTEXF_POINT
) {
4762 WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i
);
4765 if(This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_NONE
&&
4766 This
->stateBlock
->samplerState
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_POINT
/* sic! */) {
4767 WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i
);
4772 /* return a sensible default */
4775 TRACE("returning D3D_OK\n");
4779 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl
*device
)
4783 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
4785 IWineD3DBaseTextureImpl
*texture
= (IWineD3DBaseTextureImpl
*)device
->stateBlock
->textures
[i
];
4786 if (texture
&& (texture
->resource
.format_desc
->format
== WINED3DFMT_P8_UINT
4787 || texture
->resource
.format_desc
->format
== WINED3DFMT_P8_UINT_A8_UNORM
))
4789 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_SAMPLER(i
));
4794 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, CONST PALETTEENTRY
* pEntries
) {
4795 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4798 PALETTEENTRY
**palettes
;
4800 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
4802 if (PaletteNumber
>= MAX_PALETTES
) {
4803 ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
4804 return WINED3DERR_INVALIDCALL
;
4807 if (PaletteNumber
>= This
->NumberOfPalettes
) {
4808 NewSize
= This
->NumberOfPalettes
;
4811 } while(PaletteNumber
>= NewSize
);
4812 palettes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->palettes
, sizeof(PALETTEENTRY
*) * NewSize
);
4814 ERR("Out of memory!\n");
4815 return E_OUTOFMEMORY
;
4817 This
->palettes
= palettes
;
4818 This
->NumberOfPalettes
= NewSize
;
4821 if (!This
->palettes
[PaletteNumber
]) {
4822 This
->palettes
[PaletteNumber
] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
4823 if (!This
->palettes
[PaletteNumber
]) {
4824 ERR("Out of memory!\n");
4825 return E_OUTOFMEMORY
;
4829 for (j
= 0; j
< 256; ++j
) {
4830 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
4831 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
4832 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
4833 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
4835 if (PaletteNumber
== This
->currentPalette
) dirtify_p8_texture_samplers(This
);
4836 TRACE("(%p) : returning\n", This
);
4840 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, PALETTEENTRY
* pEntries
) {
4841 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4843 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
4844 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
4845 /* What happens in such situation isn't documented; Native seems to silently abort
4846 on such conditions. Return Invalid Call. */
4847 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
4848 return WINED3DERR_INVALIDCALL
;
4850 for (j
= 0; j
< 256; ++j
) {
4851 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
4852 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
4853 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
4854 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
4856 TRACE("(%p) : returning\n", This
);
4860 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
) {
4861 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4862 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
4863 /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
4864 (tested with reference rasterizer). Return Invalid Call. */
4865 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
4866 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
4867 return WINED3DERR_INVALIDCALL
;
4869 /*TODO: stateblocks */
4870 if (This
->currentPalette
!= PaletteNumber
) {
4871 This
->currentPalette
= PaletteNumber
;
4872 dirtify_p8_texture_samplers(This
);
4874 TRACE("(%p) : returning\n", This
);
4878 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
4879 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4880 if (PaletteNumber
== NULL
) {
4881 WARN("(%p) : returning Invalid Call\n", This
);
4882 return WINED3DERR_INVALIDCALL
;
4884 /*TODO: stateblocks */
4885 *PaletteNumber
= This
->currentPalette
;
4886 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
4890 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
4891 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4895 FIXME("(%p) : stub\n", This
);
4899 This
->softwareVertexProcessing
= bSoftware
;
4904 static BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
4905 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4909 FIXME("(%p) : stub\n", This
);
4912 return This
->softwareVertexProcessing
;
4915 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
,
4916 UINT swapchain_idx
, WINED3DRASTER_STATUS
*raster_status
)
4918 IWineD3DSwapChain
*swapchain
;
4921 TRACE("iface %p, swapchain_idx %u, raster_status %p.\n",
4922 iface
, swapchain_idx
, raster_status
);
4924 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
4927 WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx
, hr
);
4931 hr
= IWineD3DSwapChain_GetRasterStatus(swapchain
, raster_status
);
4932 IWineD3DSwapChain_Release(swapchain
);
4935 WARN("Failed to get raster status, hr %#x.\n", hr
);
4942 static HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
)
4945 if(nSegments
!= 0.0f
) {
4948 FIXME("iface %p, nSegments %.8e stub!\n", iface
, nSegments
);
4955 static float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
)
4960 FIXME("iface %p stub!\n", iface
);
4966 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pSourceSurface
, CONST RECT
* pSourceRect
, IWineD3DSurface
*pDestinationSurface
, CONST POINT
* pDestPoint
) {
4967 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
4968 /** TODO: remove casts to IWineD3DSurfaceImpl
4969 * NOTE: move code to surface to accomplish this
4970 ****************************************/
4971 IWineD3DSurfaceImpl
*pSrcSurface
= (IWineD3DSurfaceImpl
*)pSourceSurface
;
4972 IWineD3DSurfaceImpl
*dst_impl
= (IWineD3DSurfaceImpl
*)pDestinationSurface
;
4973 int srcWidth
, srcHeight
;
4974 unsigned int srcSurfaceWidth
, srcSurfaceHeight
, destSurfaceWidth
, destSurfaceHeight
;
4975 WINED3DFORMAT destFormat
, srcFormat
;
4977 int srcLeft
, destLeft
, destTop
;
4978 WINED3DPOOL srcPool
, destPool
;
4980 int rowoffset
= 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4981 const struct GlPixelFormatDesc
*src_format_desc
, *dst_format_desc
;
4985 CONVERT_TYPES convert
= NO_CONVERSION
;
4986 struct wined3d_context
*context
;
4988 WINED3DSURFACE_DESC winedesc
;
4990 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This
, pSourceSurface
, pSourceRect
, pDestinationSurface
, pDestPoint
);
4992 IWineD3DSurface_GetDesc(pSourceSurface
, &winedesc
);
4993 srcSurfaceWidth
= winedesc
.width
;
4994 srcSurfaceHeight
= winedesc
.height
;
4995 srcPool
= winedesc
.pool
;
4996 srcFormat
= winedesc
.format
;
4998 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
4999 destSurfaceWidth
= winedesc
.width
;
5000 destSurfaceHeight
= winedesc
.height
;
5001 destPool
= winedesc
.pool
;
5002 destFormat
= winedesc
.format
;
5003 destSize
= winedesc
.size
;
5005 if(srcPool
!= WINED3DPOOL_SYSTEMMEM
|| destPool
!= WINED3DPOOL_DEFAULT
){
5006 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface
, pDestinationSurface
);
5007 return WINED3DERR_INVALIDCALL
;
5010 /* This call loads the opengl surface directly, instead of copying the surface to the
5011 * destination's sysmem copy. If surface conversion is needed, use BltFast instead to
5012 * copy in sysmem and use regular surface loading.
5014 d3dfmt_get_conv(dst_impl
, FALSE
, TRUE
, &dummy
, &dummy
, &dummy
, &convert
, &bpp
, FALSE
);
5015 if(convert
!= NO_CONVERSION
) {
5016 return IWineD3DSurface_BltFast(pDestinationSurface
,
5017 pDestPoint
? pDestPoint
->x
: 0,
5018 pDestPoint
? pDestPoint
->y
: 0,
5019 pSourceSurface
, pSourceRect
, 0);
5022 if (destFormat
== WINED3DFMT_UNKNOWN
) {
5023 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This
);
5024 IWineD3DSurface_SetFormat(pDestinationSurface
, srcFormat
);
5026 /* Get the update surface description */
5027 IWineD3DSurface_GetDesc(pDestinationSurface
, &winedesc
);
5030 context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
5033 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
5034 checkGLcall("glActiveTextureARB");
5037 /* Make sure the surface is loaded and up to date */
5038 surface_internal_preload(pDestinationSurface
, SRGB_RGB
);
5039 IWineD3DSurface_BindTexture(pDestinationSurface
, FALSE
);
5041 src_format_desc
= ((IWineD3DSurfaceImpl
*)pSrcSurface
)->resource
.format_desc
;
5042 dst_format_desc
= dst_impl
->resource
.format_desc
;
5044 /* this needs to be done in lines if the sourceRect != the sourceWidth */
5045 srcWidth
= pSourceRect
? pSourceRect
->right
- pSourceRect
->left
: srcSurfaceWidth
;
5046 srcHeight
= pSourceRect
? pSourceRect
->bottom
- pSourceRect
->top
: srcSurfaceHeight
;
5047 srcLeft
= pSourceRect
? pSourceRect
->left
: 0;
5048 destLeft
= pDestPoint
? pDestPoint
->x
: 0;
5049 destTop
= pDestPoint
? pDestPoint
->y
: 0;
5052 /* This function doesn't support compressed textures
5053 the pitch is just bytesPerPixel * width */
5054 if(srcWidth
!= srcSurfaceWidth
|| srcLeft
){
5055 rowoffset
= srcSurfaceWidth
* src_format_desc
->byte_count
;
5056 offset
+= srcLeft
* src_format_desc
->byte_count
;
5057 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5059 /* TODO DXT formats */
5061 if(pSourceRect
!= NULL
&& pSourceRect
->top
!= 0){
5062 offset
+= pSourceRect
->top
* srcSurfaceWidth
* src_format_desc
->byte_count
;
5064 TRACE("(%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x\n",
5065 This
, dst_impl
->texture_level
, destLeft
, destTop
, srcWidth
, srcHeight
, dst_format_desc
->glFormat
,
5066 dst_format_desc
->glType
, IWineD3DSurface_GetData(pSourceSurface
), offset
);
5069 if (IWineD3DSurface_GetData(pSourceSurface
) == NULL
) {
5071 /* need to lock the surface to get the data */
5072 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5077 /* TODO: Cube and volume support */
5079 /* not a whole row so we have to do it a line at a time */
5082 /* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
5083 const unsigned char* data
=((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
5085 for (j
= destTop
; j
< (srcHeight
+ destTop
); ++j
)
5087 glTexSubImage2D(dst_impl
->texture_target
, dst_impl
->texture_level
, destLeft
, j
,
5088 srcWidth
, 1, dst_format_desc
->glFormat
, dst_format_desc
->glType
,data
);
5092 } else { /* Full width, so just write out the whole texture */
5093 const unsigned char* data
= ((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface
)) + offset
;
5095 if (dst_format_desc
->Flags
& WINED3DFMT_FLAG_COMPRESSED
)
5097 if (destSurfaceHeight
!= srcHeight
|| destSurfaceWidth
!= srcWidth
)
5099 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across. */
5100 FIXME("Updating part of a compressed texture is not supported.\n");
5102 if (destFormat
!= srcFormat
)
5104 FIXME("Updating mixed format compressed textures is not supported.\n");
5108 GL_EXTCALL(glCompressedTexImage2DARB(dst_impl
->texture_target
, dst_impl
->texture_level
,
5109 dst_format_desc
->glInternal
, srcWidth
, srcHeight
, 0, destSize
, data
));
5114 glTexSubImage2D(dst_impl
->texture_target
, dst_impl
->texture_level
, destLeft
, destTop
,
5115 srcWidth
, srcHeight
, dst_format_desc
->glFormat
, dst_format_desc
->glType
, data
);
5118 checkGLcall("glTexSubImage2D");
5121 context_release(context
);
5123 IWineD3DSurface_ModifyLocation(pDestinationSurface
, SFLAG_INTEXTURE
, TRUE
);
5124 sampler
= This
->rev_tex_unit_map
[0];
5125 if (sampler
!= WINED3D_UNMAPPED_STAGE
)
5127 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
5133 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DRECTPATCH_INFO
* pRectPatchInfo
) {
5134 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5135 struct WineD3DRectPatch
*patch
;
5136 GLenum old_primitive_type
;
5140 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
5142 if(!(Handle
|| pRectPatchInfo
)) {
5143 /* TODO: Write a test for the return value, thus the FIXME */
5144 FIXME("Both Handle and pRectPatchInfo are NULL\n");
5145 return WINED3DERR_INVALIDCALL
;
5149 i
= PATCHMAP_HASHFUNC(Handle
);
5151 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
5152 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
5153 if(patch
->Handle
== Handle
) {
5160 TRACE("Patch does not exist. Creating a new one\n");
5161 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5162 patch
->Handle
= Handle
;
5163 list_add_head(&This
->patches
[i
], &patch
->entry
);
5165 TRACE("Found existing patch %p\n", patch
);
5168 /* Since opengl does not load tesselated vertex attributes into numbered vertex
5169 * attributes we have to tesselate, read back, and draw. This needs a patch
5170 * management structure instance. Create one.
5172 * A possible improvement is to check if a vertex shader is used, and if not directly
5175 FIXME("Drawing an uncached patch. This is slow\n");
5176 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5179 if(pNumSegs
[0] != patch
->numSegs
[0] || pNumSegs
[1] != patch
->numSegs
[1] ||
5180 pNumSegs
[2] != patch
->numSegs
[2] || pNumSegs
[3] != patch
->numSegs
[3] ||
5181 (pRectPatchInfo
&& memcmp(pRectPatchInfo
, &patch
->RectPatchInfo
, sizeof(*pRectPatchInfo
)) != 0) ) {
5183 TRACE("Tesselation density or patch info changed, retesselating\n");
5185 if(pRectPatchInfo
) {
5186 patch
->RectPatchInfo
= *pRectPatchInfo
;
5188 patch
->numSegs
[0] = pNumSegs
[0];
5189 patch
->numSegs
[1] = pNumSegs
[1];
5190 patch
->numSegs
[2] = pNumSegs
[2];
5191 patch
->numSegs
[3] = pNumSegs
[3];
5193 hr
= tesselate_rectpatch(This
, patch
);
5195 WARN("Patch tesselation failed\n");
5197 /* Do not release the handle to store the params of the patch */
5199 HeapFree(GetProcessHeap(), 0, patch
);
5205 This
->currentPatch
= patch
;
5206 old_primitive_type
= This
->stateBlock
->gl_primitive_type
;
5207 This
->stateBlock
->gl_primitive_type
= GL_TRIANGLES
;
5208 IWineD3DDevice_DrawPrimitiveStrided(iface
, patch
->numSegs
[0] * patch
->numSegs
[1] * 2 * 3, &patch
->strided
);
5209 This
->stateBlock
->gl_primitive_type
= old_primitive_type
;
5210 This
->currentPatch
= NULL
;
5212 /* Destroy uncached patches */
5214 HeapFree(GetProcessHeap(), 0, patch
->mem
);
5215 HeapFree(GetProcessHeap(), 0, patch
);
5220 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
,
5221 UINT handle
, const float *segment_count
, const WINED3DTRIPATCH_INFO
*patch_info
)
5223 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p stub!\n",
5224 iface
, handle
, segment_count
, patch_info
);
5229 static HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
5230 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5232 struct WineD3DRectPatch
*patch
;
5234 TRACE("(%p) Handle(%d)\n", This
, Handle
);
5236 i
= PATCHMAP_HASHFUNC(Handle
);
5237 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
5238 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
5239 if(patch
->Handle
== Handle
) {
5240 TRACE("Deleting patch %p\n", patch
);
5241 list_remove(&patch
->entry
);
5242 HeapFree(GetProcessHeap(), 0, patch
->mem
);
5243 HeapFree(GetProcessHeap(), 0, patch
);
5248 /* TODO: Write a test for the return value */
5249 FIXME("Attempt to destroy nonexistent patch\n");
5250 return WINED3DERR_INVALIDCALL
;
5253 static IWineD3DSwapChain
*get_swapchain(IWineD3DSurface
*target
) {
5255 IWineD3DSwapChain
*swapchain
;
5257 hr
= IWineD3DSurface_GetContainer(target
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
5258 if (SUCCEEDED(hr
)) {
5259 IWineD3DSwapChain_Release((IUnknown
*)swapchain
);
5266 static void color_fill_fbo(IWineD3DDevice
*iface
, IWineD3DSurface
*surface
,
5267 const WINED3DRECT
*rect
, const float color
[4])
5269 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5270 struct wined3d_context
*context
;
5272 if (!surface_is_offscreen(surface
))
5274 TRACE("Surface %p is onscreen\n", surface
);
5276 context
= context_acquire(This
, surface
, CTXUSAGE_RESOURCELOAD
);
5278 context_bind_fbo(context
, GL_FRAMEBUFFER
, NULL
);
5279 context_set_draw_buffer(context
, surface_get_gl_buffer(surface
));
5283 TRACE("Surface %p is offscreen\n", surface
);
5285 context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
5287 context_bind_fbo(context
, GL_FRAMEBUFFER
, &context
->dst_fbo
);
5288 context_attach_surface_fbo(context
, GL_FRAMEBUFFER
, 0, surface
);
5289 context_attach_depth_stencil_fbo(context
, GL_FRAMEBUFFER
, NULL
, FALSE
);
5293 glEnable(GL_SCISSOR_TEST
);
5294 if(surface_is_offscreen(surface
)) {
5295 glScissor(rect
->x1
, rect
->y1
, rect
->x2
- rect
->x1
, rect
->y2
- rect
->y1
);
5297 glScissor(rect
->x1
, ((IWineD3DSurfaceImpl
*)surface
)->currentDesc
.Height
- rect
->y2
,
5298 rect
->x2
- rect
->x1
, rect
->y2
- rect
->y1
);
5300 checkGLcall("glScissor");
5301 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
5303 glDisable(GL_SCISSOR_TEST
);
5305 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE
));
5307 glDisable(GL_BLEND
);
5308 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE
));
5310 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5311 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE
));
5313 glClearColor(color
[0], color
[1], color
[2], color
[3]);
5314 glClear(GL_COLOR_BUFFER_BIT
);
5315 checkGLcall("glClear");
5318 context_release(context
);
5321 static inline DWORD
argb_to_fmt(DWORD color
, WINED3DFORMAT destfmt
) {
5322 unsigned int r
, g
, b
, a
;
5325 if (destfmt
== WINED3DFMT_B8G8R8A8_UNORM
5326 || destfmt
== WINED3DFMT_B8G8R8X8_UNORM
5327 || destfmt
== WINED3DFMT_B8G8R8_UNORM
)
5330 TRACE("Converting color %08x to format %s\n", color
, debug_d3dformat(destfmt
));
5332 a
= (color
& 0xff000000) >> 24;
5333 r
= (color
& 0x00ff0000) >> 16;
5334 g
= (color
& 0x0000ff00) >> 8;
5335 b
= (color
& 0x000000ff) >> 0;
5339 case WINED3DFMT_B5G6R5_UNORM
:
5340 if(r
== 0xff && g
== 0xff && b
== 0xff) return 0xffff;
5347 TRACE("Returning %08x\n", ret
);
5350 case WINED3DFMT_B5G5R5X1_UNORM
:
5351 case WINED3DFMT_B5G5R5A1_UNORM
:
5360 TRACE("Returning %08x\n", ret
);
5363 case WINED3DFMT_A8_UNORM
:
5364 TRACE("Returning %08x\n", a
);
5367 case WINED3DFMT_B4G4R4X4_UNORM
:
5368 case WINED3DFMT_B4G4R4A4_UNORM
:
5377 TRACE("Returning %08x\n", ret
);
5380 case WINED3DFMT_B2G3R3_UNORM
:
5387 TRACE("Returning %08x\n", ret
);
5390 case WINED3DFMT_R8G8B8X8_UNORM
:
5391 case WINED3DFMT_R8G8B8A8_UNORM
:
5396 TRACE("Returning %08x\n", ret
);
5399 case WINED3DFMT_B10G10R10A2_UNORM
:
5401 r
= (r
* 1024) / 256;
5402 g
= (g
* 1024) / 256;
5403 b
= (b
* 1024) / 256;
5408 TRACE("Returning %08x\n", ret
);
5411 case WINED3DFMT_R10G10B10A2_UNORM
:
5413 r
= (r
* 1024) / 256;
5414 g
= (g
* 1024) / 256;
5415 b
= (b
* 1024) / 256;
5420 TRACE("Returning %08x\n", ret
);
5424 FIXME("Add a COLORFILL conversion for format %s\n", debug_d3dformat(destfmt
));
5429 static HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
,
5430 IWineD3DSurface
*pSurface
, const WINED3DRECT
*pRect
, WINED3DCOLOR color
)
5432 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*) pSurface
;
5435 TRACE("iface %p, surface %p, rect %p, color 0x%08x.\n", iface
, pSurface
, pRect
, color
);
5437 if (surface
->resource
.pool
!= WINED3DPOOL_DEFAULT
&& surface
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
) {
5438 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5439 return WINED3DERR_INVALIDCALL
;
5442 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
) {
5443 const float c
[4] = {D3DCOLOR_R(color
), D3DCOLOR_G(color
), D3DCOLOR_B(color
), D3DCOLOR_A(color
)};
5444 color_fill_fbo(iface
, pSurface
, pRect
, c
);
5447 /* Just forward this to the DirectDraw blitting engine */
5448 memset(&BltFx
, 0, sizeof(BltFx
));
5449 BltFx
.dwSize
= sizeof(BltFx
);
5450 BltFx
.u5
.dwFillColor
= argb_to_fmt(color
, surface
->resource
.format_desc
->format
);
5451 return IWineD3DSurface_Blt(pSurface
, (const RECT
*)pRect
, NULL
, NULL
,
5452 WINEDDBLT_COLORFILL
, &BltFx
, WINED3DTEXF_POINT
);
5456 static void WINAPI
IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice
*iface
,
5457 IWineD3DRendertargetView
*rendertarget_view
, const float color
[4])
5459 IWineD3DResource
*resource
;
5460 IWineD3DSurface
*surface
;
5463 hr
= IWineD3DRendertargetView_GetResource(rendertarget_view
, &resource
);
5466 ERR("Failed to get resource, hr %#x\n", hr
);
5470 if (IWineD3DResource_GetType(resource
) != WINED3DRTYPE_SURFACE
)
5472 FIXME("Only supported on surface resources\n");
5473 IWineD3DResource_Release(resource
);
5477 surface
= (IWineD3DSurface
*)resource
;
5479 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
)
5481 color_fill_fbo(iface
, surface
, NULL
, color
);
5488 WARN("Converting to WINED3DCOLOR, this might give incorrect results\n");
5490 c
= ((DWORD
)(color
[2] * 255.0f
));
5491 c
|= ((DWORD
)(color
[1] * 255.0f
)) << 8;
5492 c
|= ((DWORD
)(color
[0] * 255.0f
)) << 16;
5493 c
|= ((DWORD
)(color
[3] * 255.0f
)) << 24;
5495 /* Just forward this to the DirectDraw blitting engine */
5496 memset(&BltFx
, 0, sizeof(BltFx
));
5497 BltFx
.dwSize
= sizeof(BltFx
);
5498 BltFx
.u5
.dwFillColor
= argb_to_fmt(c
, ((IWineD3DSurfaceImpl
*)surface
)->resource
.format_desc
->format
);
5499 hr
= IWineD3DSurface_Blt(surface
, NULL
, NULL
, NULL
, WINEDDBLT_COLORFILL
, &BltFx
, WINED3DTEXF_POINT
);
5502 ERR("Blt failed, hr %#x\n", hr
);
5506 IWineD3DResource_Release(resource
);
5509 /* rendertarget and depth stencil functions */
5510 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
* iface
,DWORD RenderTargetIndex
, IWineD3DSurface
**ppRenderTarget
) {
5511 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5513 if (RenderTargetIndex
>= This
->adapter
->gl_info
.limits
.buffers
)
5515 ERR("(%p) : Only %d render targets are supported.\n",
5516 This
, This
->adapter
->gl_info
.limits
.buffers
);
5517 return WINED3DERR_INVALIDCALL
;
5520 *ppRenderTarget
= This
->render_targets
[RenderTargetIndex
];
5521 TRACE("(%p) : RenderTarget %d Index returning %p\n", This
, RenderTargetIndex
, *ppRenderTarget
);
5522 /* Note inc ref on returned surface */
5523 if(*ppRenderTarget
!= NULL
)
5524 IWineD3DSurface_AddRef(*ppRenderTarget
);
5528 static HRESULT WINAPI
IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice
*iface
,
5529 IWineD3DSurface
*Front
, IWineD3DSurface
*Back
)
5531 IWineD3DSurfaceImpl
*FrontImpl
= (IWineD3DSurfaceImpl
*) Front
;
5532 IWineD3DSurfaceImpl
*BackImpl
= (IWineD3DSurfaceImpl
*) Back
;
5533 IWineD3DSwapChainImpl
*Swapchain
;
5536 TRACE("iface %p, front %p, back %p.\n", iface
, Front
, Back
);
5538 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &Swapchain
);
5539 if(hr
!= WINED3D_OK
) {
5540 ERR("Can't get the swapchain\n");
5544 /* Make sure to release the swapchain */
5545 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) Swapchain
);
5547 if(FrontImpl
&& !(FrontImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ) {
5548 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5549 return WINED3DERR_INVALIDCALL
;
5551 else if(BackImpl
&& !(BackImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
5552 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5553 return WINED3DERR_INVALIDCALL
;
5556 if(Swapchain
->frontBuffer
!= Front
) {
5557 TRACE("Changing the front buffer from %p to %p\n", Swapchain
->frontBuffer
, Front
);
5559 if(Swapchain
->frontBuffer
)
5561 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, NULL
);
5562 ((IWineD3DSurfaceImpl
*)Swapchain
->frontBuffer
)->Flags
&= ~SFLAG_SWAPCHAIN
;
5564 Swapchain
->frontBuffer
= Front
;
5566 if(Swapchain
->frontBuffer
) {
5567 IWineD3DSurface_SetContainer(Swapchain
->frontBuffer
, (IWineD3DBase
*) Swapchain
);
5568 ((IWineD3DSurfaceImpl
*)Swapchain
->frontBuffer
)->Flags
|= SFLAG_SWAPCHAIN
;
5572 if(Back
&& !Swapchain
->backBuffer
) {
5573 /* We need memory for the back buffer array - only one back buffer this way */
5574 Swapchain
->backBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*));
5575 if(!Swapchain
->backBuffer
) {
5576 ERR("Out of memory\n");
5577 return E_OUTOFMEMORY
;
5581 if(Swapchain
->backBuffer
[0] != Back
) {
5582 TRACE("Changing the back buffer from %p to %p\n", Swapchain
->backBuffer
, Back
);
5584 /* What to do about the context here in the case of multithreading? Not sure.
5585 * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
5587 WARN("No active context?\n");
5590 if(!Swapchain
->backBuffer
[0]) {
5591 /* GL was told to draw to the front buffer at creation,
5594 glDrawBuffer(GL_BACK
);
5595 checkGLcall("glDrawBuffer(GL_BACK)");
5596 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5597 Swapchain
->presentParms
.BackBufferCount
= 1;
5599 /* That makes problems - disable for now */
5600 /* glDrawBuffer(GL_FRONT); */
5601 checkGLcall("glDrawBuffer(GL_FRONT)");
5602 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5603 Swapchain
->presentParms
.BackBufferCount
= 0;
5607 if(Swapchain
->backBuffer
[0])
5609 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], NULL
);
5610 ((IWineD3DSurfaceImpl
*)Swapchain
->backBuffer
[0])->Flags
&= ~SFLAG_SWAPCHAIN
;
5612 Swapchain
->backBuffer
[0] = Back
;
5614 if(Swapchain
->backBuffer
[0]) {
5615 IWineD3DSurface_SetContainer(Swapchain
->backBuffer
[0], (IWineD3DBase
*) Swapchain
);
5616 ((IWineD3DSurfaceImpl
*)Swapchain
->backBuffer
[0])->Flags
|= SFLAG_SWAPCHAIN
;
5618 HeapFree(GetProcessHeap(), 0, Swapchain
->backBuffer
);
5619 Swapchain
->backBuffer
= NULL
;
5627 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
* iface
, IWineD3DSurface
**ppZStencilSurface
) {
5628 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5629 *ppZStencilSurface
= This
->stencilBufferTarget
;
5630 TRACE("(%p) : zStencilSurface returning %p\n", This
, *ppZStencilSurface
);
5632 if(*ppZStencilSurface
!= NULL
) {
5633 /* Note inc ref on returned surface */
5634 IWineD3DSurface_AddRef(*ppZStencilSurface
);
5637 return WINED3DERR_NOTFOUND
;
5641 void stretch_rect_fbo(IWineD3DDevice
*iface
, IWineD3DSurface
*src_surface
, WINED3DRECT
*src_rect
,
5642 IWineD3DSurface
*dst_surface
, WINED3DRECT
*dst_rect
, const WINED3DTEXTUREFILTERTYPE filter
, BOOL flip
)
5644 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5645 GLbitfield mask
= GL_COLOR_BUFFER_BIT
; /* TODO: Support blitting depth/stencil surfaces */
5646 IWineD3DSwapChain
*src_swapchain
, *dst_swapchain
;
5647 const struct wined3d_gl_info
*gl_info
;
5648 struct wined3d_context
*context
;
5650 POINT offset
= {0, 0};
5652 TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u\n",
5653 This
, src_surface
, src_rect
, dst_surface
, dst_rect
, debug_d3dtexturefiltertype(filter
), filter
, flip
);
5654 TRACE("src_rect [%u, %u]->[%u, %u]\n", src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
);
5655 TRACE("dst_rect [%u, %u]->[%u, %u]\n", dst_rect
->x1
, dst_rect
->y1
, dst_rect
->x2
, dst_rect
->y2
);
5658 case WINED3DTEXF_LINEAR
:
5659 gl_filter
= GL_LINEAR
;
5663 FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter
), filter
);
5664 case WINED3DTEXF_NONE
:
5665 case WINED3DTEXF_POINT
:
5666 gl_filter
= GL_NEAREST
;
5670 /* Attach src surface to src fbo */
5671 src_swapchain
= get_swapchain(src_surface
);
5672 dst_swapchain
= get_swapchain(dst_surface
);
5674 if (src_swapchain
) context
= context_acquire(This
, src_surface
, CTXUSAGE_RESOURCELOAD
);
5675 else if (dst_swapchain
) context
= context_acquire(This
, dst_surface
, CTXUSAGE_RESOURCELOAD
);
5676 else context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
5678 gl_info
= context
->gl_info
;
5680 if (!surface_is_offscreen(src_surface
))
5682 GLenum buffer
= surface_get_gl_buffer(src_surface
);
5684 TRACE("Source surface %p is onscreen\n", src_surface
);
5685 /* Make sure the drawable is up to date. In the offscreen case
5686 * attach_surface_fbo() implicitly takes care of this. */
5687 IWineD3DSurface_LoadLocation(src_surface
, SFLAG_INDRAWABLE
, NULL
);
5689 if(buffer
== GL_FRONT
) {
5692 ClientToScreen(((IWineD3DSwapChainImpl
*)src_swapchain
)->win_handle
, &offset
);
5693 GetClientRect(((IWineD3DSwapChainImpl
*)src_swapchain
)->win_handle
, &windowsize
);
5694 h
= windowsize
.bottom
- windowsize
.top
;
5695 src_rect
->x1
-= offset
.x
; src_rect
->x2
-=offset
.x
;
5696 src_rect
->y1
= offset
.y
+ h
- src_rect
->y1
;
5697 src_rect
->y2
= offset
.y
+ h
- src_rect
->y2
;
5699 src_rect
->y1
= ((IWineD3DSurfaceImpl
*)src_surface
)->currentDesc
.Height
- src_rect
->y1
;
5700 src_rect
->y2
= ((IWineD3DSurfaceImpl
*)src_surface
)->currentDesc
.Height
- src_rect
->y2
;
5704 context_bind_fbo(context
, GL_READ_FRAMEBUFFER
, NULL
);
5705 glReadBuffer(buffer
);
5706 checkGLcall("glReadBuffer()");
5708 TRACE("Source surface %p is offscreen\n", src_surface
);
5710 context_bind_fbo(context
, GL_READ_FRAMEBUFFER
, &context
->src_fbo
);
5711 context_attach_surface_fbo(context
, GL_READ_FRAMEBUFFER
, 0, src_surface
);
5712 glReadBuffer(GL_COLOR_ATTACHMENT0
);
5713 checkGLcall("glReadBuffer()");
5714 context_attach_depth_stencil_fbo(context
, GL_READ_FRAMEBUFFER
, NULL
, FALSE
);
5718 /* Attach dst surface to dst fbo */
5719 if (!surface_is_offscreen(dst_surface
))
5721 GLenum buffer
= surface_get_gl_buffer(dst_surface
);
5723 TRACE("Destination surface %p is onscreen\n", dst_surface
);
5724 /* Make sure the drawable is up to date. In the offscreen case
5725 * attach_surface_fbo() implicitly takes care of this. */
5726 IWineD3DSurface_LoadLocation(dst_surface
, SFLAG_INDRAWABLE
, NULL
);
5728 if(buffer
== GL_FRONT
) {
5731 ClientToScreen(((IWineD3DSwapChainImpl
*)dst_swapchain
)->win_handle
, &offset
);
5732 GetClientRect(((IWineD3DSwapChainImpl
*)dst_swapchain
)->win_handle
, &windowsize
);
5733 h
= windowsize
.bottom
- windowsize
.top
;
5734 dst_rect
->x1
-= offset
.x
; dst_rect
->x2
-=offset
.x
;
5735 dst_rect
->y1
= offset
.y
+ h
- dst_rect
->y1
;
5736 dst_rect
->y2
= offset
.y
+ h
- dst_rect
->y2
;
5738 /* Screen coords = window coords, surface height = window height */
5739 dst_rect
->y1
= ((IWineD3DSurfaceImpl
*)dst_surface
)->currentDesc
.Height
- dst_rect
->y1
;
5740 dst_rect
->y2
= ((IWineD3DSurfaceImpl
*)dst_surface
)->currentDesc
.Height
- dst_rect
->y2
;
5744 context_bind_fbo(context
, GL_DRAW_FRAMEBUFFER
, NULL
);
5745 context_set_draw_buffer(context
, buffer
);
5749 TRACE("Destination surface %p is offscreen\n", dst_surface
);
5752 context_bind_fbo(context
, GL_DRAW_FRAMEBUFFER
, &context
->dst_fbo
);
5753 context_attach_surface_fbo(context
, GL_DRAW_FRAMEBUFFER
, 0, dst_surface
);
5754 context_set_draw_buffer(context
, GL_COLOR_ATTACHMENT0
);
5755 context_attach_depth_stencil_fbo(context
, GL_DRAW_FRAMEBUFFER
, NULL
, FALSE
);
5757 glDisable(GL_SCISSOR_TEST
);
5758 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE
));
5761 gl_info
->fbo_ops
.glBlitFramebuffer(src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
,
5762 dst_rect
->x1
, dst_rect
->y2
, dst_rect
->x2
, dst_rect
->y1
, mask
, gl_filter
);
5763 checkGLcall("glBlitFramebuffer()");
5765 gl_info
->fbo_ops
.glBlitFramebuffer(src_rect
->x1
, src_rect
->y1
, src_rect
->x2
, src_rect
->y2
,
5766 dst_rect
->x1
, dst_rect
->y1
, dst_rect
->x2
, dst_rect
->y2
, mask
, gl_filter
);
5767 checkGLcall("glBlitFramebuffer()");
5771 context_release(context
);
5773 IWineD3DSurface_ModifyLocation(dst_surface
, SFLAG_INDRAWABLE
, TRUE
);
5776 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
, DWORD RenderTargetIndex
, IWineD3DSurface
*pRenderTarget
,
5777 BOOL set_viewport
) {
5778 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5780 TRACE("(%p) : Setting rendertarget %d to %p\n", This
, RenderTargetIndex
, pRenderTarget
);
5782 if (RenderTargetIndex
>= This
->adapter
->gl_info
.limits
.buffers
)
5784 WARN("(%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported)\n",
5785 This
, RenderTargetIndex
, This
->adapter
->gl_info
.limits
.buffers
);
5786 return WINED3DERR_INVALIDCALL
;
5789 /* MSDN says that null disables the render target
5790 but a device must always be associated with a render target
5791 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5793 if (RenderTargetIndex
== 0 && pRenderTarget
== NULL
) {
5794 FIXME("Trying to set render target 0 to NULL\n");
5795 return WINED3DERR_INVALIDCALL
;
5797 if (pRenderTarget
&& !(((IWineD3DSurfaceImpl
*)pRenderTarget
)->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
5798 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
);
5799 return WINED3DERR_INVALIDCALL
;
5802 /* If we are trying to set what we already have, don't bother */
5803 if (pRenderTarget
== This
->render_targets
[RenderTargetIndex
]) {
5804 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5807 if(pRenderTarget
) IWineD3DSurface_AddRef(pRenderTarget
);
5808 if(This
->render_targets
[RenderTargetIndex
]) IWineD3DSurface_Release(This
->render_targets
[RenderTargetIndex
]);
5809 This
->render_targets
[RenderTargetIndex
] = pRenderTarget
;
5811 /* Render target 0 is special */
5812 if(RenderTargetIndex
== 0 && set_viewport
) {
5813 /* Finally, reset the viewport and scissor rect as the MSDN states.
5814 * Tests show that stateblock recording is ignored, the change goes
5815 * directly into the primary stateblock.
5817 This
->stateBlock
->viewport
.Height
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->currentDesc
.Height
;
5818 This
->stateBlock
->viewport
.Width
= ((IWineD3DSurfaceImpl
*)This
->render_targets
[0])->currentDesc
.Width
;
5819 This
->stateBlock
->viewport
.X
= 0;
5820 This
->stateBlock
->viewport
.Y
= 0;
5821 This
->stateBlock
->viewport
.MaxZ
= 1.0f
;
5822 This
->stateBlock
->viewport
.MinZ
= 0.0f
;
5823 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
5825 This
->stateBlock
->scissorRect
.top
= 0;
5826 This
->stateBlock
->scissorRect
.left
= 0;
5827 This
->stateBlock
->scissorRect
.right
= This
->stateBlock
->viewport
.Width
;
5828 This
->stateBlock
->scissorRect
.bottom
= This
->stateBlock
->viewport
.Height
;
5829 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
5834 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*pNewZStencil
) {
5835 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5836 HRESULT hr
= WINED3D_OK
;
5837 IWineD3DSurface
*tmp
;
5839 TRACE("(%p) Swapping z-buffer. Old = %p, new = %p\n",This
, This
->stencilBufferTarget
, pNewZStencil
);
5841 if (pNewZStencil
== This
->stencilBufferTarget
) {
5842 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5844 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
5845 * depending on the renter target implementation being used.
5846 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5847 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5848 * stencil buffer and incur an extra memory overhead
5849 ******************************************************/
5851 if (This
->stencilBufferTarget
) {
5852 if (((IWineD3DSwapChainImpl
*)This
->swapchains
[0])->presentParms
.Flags
& WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
5853 || ((IWineD3DSurfaceImpl
*)This
->stencilBufferTarget
)->Flags
& SFLAG_DISCARD
) {
5854 surface_modify_ds_location(This
->stencilBufferTarget
, SFLAG_DS_DISCARDED
);
5856 struct wined3d_context
*context
= context_acquire(This
, This
->render_targets
[0], CTXUSAGE_RESOURCELOAD
);
5857 surface_load_ds_location(This
->stencilBufferTarget
, context
, SFLAG_DS_OFFSCREEN
);
5858 surface_modify_ds_location(This
->stencilBufferTarget
, SFLAG_DS_OFFSCREEN
);
5859 context_release(context
);
5863 tmp
= This
->stencilBufferTarget
;
5864 This
->stencilBufferTarget
= pNewZStencil
;
5865 /* should we be calling the parent or the wined3d surface? */
5866 if (NULL
!= This
->stencilBufferTarget
) IWineD3DSurface_AddRef(This
->stencilBufferTarget
);
5867 if (NULL
!= tmp
) IWineD3DSurface_Release(tmp
);
5870 if((!tmp
&& pNewZStencil
) || (!pNewZStencil
&& tmp
)) {
5871 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5872 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZENABLE
));
5873 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILENABLE
));
5874 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILWRITEMASK
));
5881 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
* iface
, UINT XHotSpot
,
5882 UINT YHotSpot
, IWineD3DSurface
*pCursorBitmap
) {
5883 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5884 /* TODO: the use of Impl is deprecated. */
5885 IWineD3DSurfaceImpl
* pSur
= (IWineD3DSurfaceImpl
*) pCursorBitmap
;
5886 WINED3DLOCKED_RECT lockedRect
;
5888 TRACE("(%p) : Spot Pos(%u,%u)\n", This
, XHotSpot
, YHotSpot
);
5890 /* some basic validation checks */
5891 if(This
->cursorTexture
) {
5892 struct wined3d_context
*context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
5894 glDeleteTextures(1, &This
->cursorTexture
);
5896 context_release(context
);
5897 This
->cursorTexture
= 0;
5900 if ( (pSur
->currentDesc
.Width
== 32) && (pSur
->currentDesc
.Height
== 32) )
5901 This
->haveHardwareCursor
= TRUE
;
5903 This
->haveHardwareCursor
= FALSE
;
5906 WINED3DLOCKED_RECT rect
;
5908 /* MSDN: Cursor must be A8R8G8B8 */
5909 if (pSur
->resource
.format_desc
->format
!= WINED3DFMT_B8G8R8A8_UNORM
)
5911 ERR("(%p) : surface(%p) has an invalid format\n", This
, pCursorBitmap
);
5912 return WINED3DERR_INVALIDCALL
;
5915 /* MSDN: Cursor must be smaller than the display mode */
5916 if(pSur
->currentDesc
.Width
> This
->ddraw_width
||
5917 pSur
->currentDesc
.Height
> This
->ddraw_height
) {
5918 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
);
5919 return WINED3DERR_INVALIDCALL
;
5922 if (!This
->haveHardwareCursor
) {
5923 /* TODO: MSDN: Cursor sizes must be a power of 2 */
5925 /* Do not store the surface's pointer because the application may
5926 * release it after setting the cursor image. Windows doesn't
5927 * addref the set surface, so we can't do this either without
5928 * creating circular refcount dependencies. Copy out the gl texture
5931 This
->cursorWidth
= pSur
->currentDesc
.Width
;
5932 This
->cursorHeight
= pSur
->currentDesc
.Height
;
5933 if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap
, &rect
, NULL
, WINED3DLOCK_READONLY
)))
5935 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
5936 const struct GlPixelFormatDesc
*glDesc
= getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM
, gl_info
);
5937 struct wined3d_context
*context
;
5938 char *mem
, *bits
= rect
.pBits
;
5939 GLint intfmt
= glDesc
->glInternal
;
5940 GLint format
= glDesc
->glFormat
;
5941 GLint type
= glDesc
->glType
;
5942 INT height
= This
->cursorHeight
;
5943 INT width
= This
->cursorWidth
;
5944 INT bpp
= glDesc
->byte_count
;
5948 /* Reformat the texture memory (pitch and width can be
5950 mem
= HeapAlloc(GetProcessHeap(), 0, width
* height
* bpp
);
5951 for(i
= 0; i
< height
; i
++)
5952 memcpy(&mem
[width
* bpp
* i
], &bits
[rect
.Pitch
* i
], width
* bpp
);
5953 IWineD3DSurface_UnlockRect(pCursorBitmap
);
5955 context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
5959 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
5961 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
5962 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
5965 /* Make sure that a proper texture unit is selected */
5966 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
5967 checkGLcall("glActiveTextureARB");
5968 sampler
= This
->rev_tex_unit_map
[0];
5969 if (sampler
!= WINED3D_UNMAPPED_STAGE
)
5971 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
5973 /* Create a new cursor texture */
5974 glGenTextures(1, &This
->cursorTexture
);
5975 checkGLcall("glGenTextures");
5976 glBindTexture(GL_TEXTURE_2D
, This
->cursorTexture
);
5977 checkGLcall("glBindTexture");
5978 /* Copy the bitmap memory into the cursor texture */
5979 glTexImage2D(GL_TEXTURE_2D
, 0, intfmt
, width
, height
, 0, format
, type
, mem
);
5980 HeapFree(GetProcessHeap(), 0, mem
);
5981 checkGLcall("glTexImage2D");
5983 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
5985 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
5986 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
5991 context_release(context
);
5995 FIXME("A cursor texture was not returned.\n");
5996 This
->cursorTexture
= 0;
6001 /* Draw a hardware cursor */
6002 ICONINFO cursorInfo
;
6004 /* Create and clear maskBits because it is not needed for
6005 * 32-bit cursors. 32x32 bits split into 32-bit chunks == 32
6007 DWORD
*maskBits
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6008 (pSur
->currentDesc
.Width
* pSur
->currentDesc
.Height
/ 8));
6009 IWineD3DSurface_LockRect(pCursorBitmap
, &lockedRect
, NULL
,
6010 WINED3DLOCK_NO_DIRTY_UPDATE
|
6011 WINED3DLOCK_READONLY
6013 TRACE("width: %i height: %i\n", pSur
->currentDesc
.Width
,
6014 pSur
->currentDesc
.Height
);
6016 cursorInfo
.fIcon
= FALSE
;
6017 cursorInfo
.xHotspot
= XHotSpot
;
6018 cursorInfo
.yHotspot
= YHotSpot
;
6019 cursorInfo
.hbmMask
= CreateBitmap(pSur
->currentDesc
.Width
, pSur
->currentDesc
.Height
,
6021 cursorInfo
.hbmColor
= CreateBitmap(pSur
->currentDesc
.Width
, pSur
->currentDesc
.Height
,
6022 1, 32, lockedRect
.pBits
);
6023 IWineD3DSurface_UnlockRect(pCursorBitmap
);
6024 /* Create our cursor and clean up. */
6025 cursor
= CreateIconIndirect(&cursorInfo
);
6027 if (cursorInfo
.hbmMask
) DeleteObject(cursorInfo
.hbmMask
);
6028 if (cursorInfo
.hbmColor
) DeleteObject(cursorInfo
.hbmColor
);
6029 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
6030 This
->hardwareCursor
= cursor
;
6031 HeapFree(GetProcessHeap(), 0, maskBits
);
6035 This
->xHotSpot
= XHotSpot
;
6036 This
->yHotSpot
= YHotSpot
;
6040 static void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
* iface
, int XScreenSpace
, int YScreenSpace
, DWORD Flags
) {
6041 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6042 TRACE("(%p) : SetPos to (%u,%u)\n", This
, XScreenSpace
, YScreenSpace
);
6044 This
->xScreenSpace
= XScreenSpace
;
6045 This
->yScreenSpace
= YScreenSpace
;
6051 static BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
6052 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6053 BOOL oldVisible
= This
->bCursorVisible
;
6056 TRACE("(%p) : visible(%d)\n", This
, bShow
);
6059 * When ShowCursor is first called it should make the cursor appear at the OS's last
6060 * known cursor position. Because of this, some applications just repetitively call
6061 * ShowCursor in order to update the cursor's position. This behavior is undocumented.
6064 This
->xScreenSpace
= pt
.x
;
6065 This
->yScreenSpace
= pt
.y
;
6067 if (This
->haveHardwareCursor
) {
6068 This
->bCursorVisible
= bShow
;
6070 SetCursor(This
->hardwareCursor
);
6076 if (This
->cursorTexture
)
6077 This
->bCursorVisible
= bShow
;
6083 static HRESULT WINAPI
evict_managed_resource(IWineD3DResource
*resource
, void *data
) {
6084 TRACE("checking resource %p for eviction\n", resource
);
6085 if(((IWineD3DResourceImpl
*) resource
)->resource
.pool
== WINED3DPOOL_MANAGED
) {
6086 TRACE("Evicting %p\n", resource
);
6087 IWineD3DResource_UnLoad(resource
);
6089 IWineD3DResource_Release(resource
);
6093 static HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
*iface
)
6095 TRACE("iface %p.\n", iface
);
6097 IWineD3DDevice_EnumResources(iface
, evict_managed_resource
, NULL
);
6101 static HRESULT
updateSurfaceDesc(IWineD3DSurfaceImpl
*surface
, const WINED3DPRESENT_PARAMETERS
* pPresentationParameters
)
6103 IWineD3DDeviceImpl
*device
= surface
->resource
.device
;
6104 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
6106 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6107 if(surface
->Flags
& SFLAG_DIBSECTION
) {
6108 /* Release the DC */
6109 SelectObject(surface
->hDC
, surface
->dib
.holdbitmap
);
6110 DeleteDC(surface
->hDC
);
6111 /* Release the DIB section */
6112 DeleteObject(surface
->dib
.DIBsection
);
6113 surface
->dib
.bitmap_data
= NULL
;
6114 surface
->resource
.allocatedMemory
= NULL
;
6115 surface
->Flags
&= ~SFLAG_DIBSECTION
;
6117 surface
->currentDesc
.Width
= pPresentationParameters
->BackBufferWidth
;
6118 surface
->currentDesc
.Height
= pPresentationParameters
->BackBufferHeight
;
6119 if (gl_info
->supported
[ARB_TEXTURE_NON_POWER_OF_TWO
] || gl_info
->supported
[ARB_TEXTURE_RECTANGLE
]
6120 || gl_info
->supported
[WINE_NORMALIZED_TEXRECT
])
6122 surface
->pow2Width
= pPresentationParameters
->BackBufferWidth
;
6123 surface
->pow2Height
= pPresentationParameters
->BackBufferHeight
;
6125 surface
->pow2Width
= surface
->pow2Height
= 1;
6126 while (surface
->pow2Width
< pPresentationParameters
->BackBufferWidth
) surface
->pow2Width
<<= 1;
6127 while (surface
->pow2Height
< pPresentationParameters
->BackBufferHeight
) surface
->pow2Height
<<= 1;
6129 surface
->glRect
.left
= 0;
6130 surface
->glRect
.top
= 0;
6131 surface
->glRect
.right
= surface
->pow2Width
;
6132 surface
->glRect
.bottom
= surface
->pow2Height
;
6134 if (surface
->texture_name
)
6136 struct wined3d_context
*context
= context_acquire(device
, NULL
, CTXUSAGE_RESOURCELOAD
);
6138 glDeleteTextures(1, &surface
->texture_name
);
6140 context_release(context
);
6141 surface
->texture_name
= 0;
6142 surface
->Flags
&= ~SFLAG_CLIENT
;
6144 if(surface
->pow2Width
!= pPresentationParameters
->BackBufferWidth
||
6145 surface
->pow2Height
!= pPresentationParameters
->BackBufferHeight
) {
6146 surface
->Flags
|= SFLAG_NONPOW2
;
6148 surface
->Flags
&= ~SFLAG_NONPOW2
;
6150 HeapFree(GetProcessHeap(), 0, surface
->resource
.heapMemory
);
6151 surface
->resource
.allocatedMemory
= NULL
;
6152 surface
->resource
.heapMemory
= NULL
;
6153 surface
->resource
.size
= IWineD3DSurface_GetPitch((IWineD3DSurface
*) surface
) * surface
->pow2Width
;
6155 /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
6157 if(!surface_init_sysmem((IWineD3DSurface
*) surface
))
6159 return E_OUTOFMEMORY
;
6164 static HRESULT WINAPI
reset_unload_resources(IWineD3DResource
*resource
, void *data
) {
6165 TRACE("Unloading resource %p\n", resource
);
6166 IWineD3DResource_UnLoad(resource
);
6167 IWineD3DResource_Release(resource
);
6171 static BOOL
is_display_mode_supported(IWineD3DDeviceImpl
*This
, const WINED3DPRESENT_PARAMETERS
*pp
)
6174 WINED3DDISPLAYMODE m
;
6177 /* All Windowed modes are supported, as is leaving the current mode */
6178 if(pp
->Windowed
) return TRUE
;
6179 if(!pp
->BackBufferWidth
) return TRUE
;
6180 if(!pp
->BackBufferHeight
) return TRUE
;
6182 count
= IWineD3D_GetAdapterModeCount(This
->wined3d
, This
->adapter
->ordinal
, WINED3DFMT_UNKNOWN
);
6183 for(i
= 0; i
< count
; i
++) {
6184 memset(&m
, 0, sizeof(m
));
6185 hr
= IWineD3D_EnumAdapterModes(This
->wined3d
, This
->adapter
->ordinal
, WINED3DFMT_UNKNOWN
, i
, &m
);
6187 ERR("EnumAdapterModes failed\n");
6189 if(m
.Width
== pp
->BackBufferWidth
&& m
.Height
== pp
->BackBufferHeight
) {
6190 /* Mode found, it is supported */
6194 /* Mode not found -> not supported */
6198 void delete_opengl_contexts(IWineD3DDevice
*iface
, IWineD3DSwapChain
*swapchain_iface
) {
6199 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6200 IWineD3DSwapChainImpl
*swapchain
= (IWineD3DSwapChainImpl
*) swapchain_iface
;
6201 const struct wined3d_gl_info
*gl_info
;
6202 struct wined3d_context
*context
;
6203 IWineD3DBaseShaderImpl
*shader
;
6205 context
= context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
6206 gl_info
= context
->gl_info
;
6208 IWineD3DDevice_EnumResources(iface
, reset_unload_resources
, NULL
);
6209 LIST_FOR_EACH_ENTRY(shader
, &This
->shaders
, IWineD3DBaseShaderImpl
, baseShader
.shader_list_entry
) {
6210 This
->shader_backend
->shader_destroy((IWineD3DBaseShader
*) shader
);
6214 if(This
->depth_blt_texture
) {
6215 glDeleteTextures(1, &This
->depth_blt_texture
);
6216 This
->depth_blt_texture
= 0;
6218 if (This
->depth_blt_rb
) {
6219 gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &This
->depth_blt_rb
);
6220 This
->depth_blt_rb
= 0;
6221 This
->depth_blt_rb_w
= 0;
6222 This
->depth_blt_rb_h
= 0;
6226 This
->blitter
->free_private(iface
);
6227 This
->frag_pipe
->free_private(iface
);
6228 This
->shader_backend
->shader_free_private(iface
);
6229 destroy_dummy_textures(This
, gl_info
);
6231 context_release(context
);
6233 while (This
->numContexts
)
6235 context_destroy(This
, This
->contexts
[0]);
6237 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6238 swapchain
->context
= NULL
;
6239 swapchain
->num_contexts
= 0;
6242 HRESULT
create_primary_opengl_context(IWineD3DDevice
*iface
, IWineD3DSwapChain
*swapchain_iface
) {
6243 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6244 IWineD3DSwapChainImpl
*swapchain
= (IWineD3DSwapChainImpl
*) swapchain_iface
;
6245 struct wined3d_context
*context
;
6247 IWineD3DSurfaceImpl
*target
;
6249 /* Recreate the primary swapchain's context */
6250 swapchain
->context
= HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain
->context
));
6251 if (!swapchain
->context
)
6253 ERR("Failed to allocate memory for swapchain context array.\n");
6254 return E_OUTOFMEMORY
;
6257 target
= (IWineD3DSurfaceImpl
*)(swapchain
->backBuffer
? swapchain
->backBuffer
[0] : swapchain
->frontBuffer
);
6258 context
= context_create(This
, target
, swapchain
->win_handle
, FALSE
, &swapchain
->presentParms
);
6261 WARN("Failed to create context.\n");
6262 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6266 swapchain
->context
[0] = context
;
6267 swapchain
->num_contexts
= 1;
6268 create_dummy_textures(This
);
6269 context_release(context
);
6271 hr
= This
->shader_backend
->shader_alloc_private(iface
);
6274 ERR("Failed to allocate shader private data, hr %#x.\n", hr
);
6278 hr
= This
->frag_pipe
->alloc_private(iface
);
6281 ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr
);
6282 This
->shader_backend
->shader_free_private(iface
);
6286 hr
= This
->blitter
->alloc_private(iface
);
6289 ERR("Failed to allocate blitter private data, hr %#x.\n", hr
);
6290 This
->frag_pipe
->free_private(iface
);
6291 This
->shader_backend
->shader_free_private(iface
);
6298 context_acquire(This
, NULL
, CTXUSAGE_RESOURCELOAD
);
6299 destroy_dummy_textures(This
, context
->gl_info
);
6300 context_release(context
);
6301 context_destroy(This
, context
);
6302 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6303 swapchain
->num_contexts
= 0;
6307 static HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
* iface
, WINED3DPRESENT_PARAMETERS
* pPresentationParameters
) {
6308 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6309 IWineD3DSwapChainImpl
*swapchain
;
6311 BOOL DisplayModeChanged
= FALSE
;
6312 WINED3DDISPLAYMODE mode
;
6313 TRACE("(%p)\n", This
);
6315 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &swapchain
);
6317 ERR("Failed to get the first implicit swapchain\n");
6321 if(!is_display_mode_supported(This
, pPresentationParameters
)) {
6322 WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6323 WARN("Requested mode: %d, %d\n", pPresentationParameters
->BackBufferWidth
,
6324 pPresentationParameters
->BackBufferHeight
);
6325 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
6326 return WINED3DERR_INVALIDCALL
;
6329 /* Is it necessary to recreate the gl context? Actually every setting can be changed
6330 * on an existing gl context, so there's no real need for recreation.
6332 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6334 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6336 TRACE("New params:\n");
6337 TRACE("BackBufferWidth = %d\n", pPresentationParameters
->BackBufferWidth
);
6338 TRACE("BackBufferHeight = %d\n", pPresentationParameters
->BackBufferHeight
);
6339 TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters
->BackBufferFormat
));
6340 TRACE("BackBufferCount = %d\n", pPresentationParameters
->BackBufferCount
);
6341 TRACE("MultiSampleType = %d\n", pPresentationParameters
->MultiSampleType
);
6342 TRACE("MultiSampleQuality = %d\n", pPresentationParameters
->MultiSampleQuality
);
6343 TRACE("SwapEffect = %d\n", pPresentationParameters
->SwapEffect
);
6344 TRACE("hDeviceWindow = %p\n", pPresentationParameters
->hDeviceWindow
);
6345 TRACE("Windowed = %s\n", pPresentationParameters
->Windowed
? "true" : "false");
6346 TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters
->EnableAutoDepthStencil
? "true" : "false");
6347 TRACE("Flags = %08x\n", pPresentationParameters
->Flags
);
6348 TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters
->FullScreen_RefreshRateInHz
);
6349 TRACE("PresentationInterval = %d\n", pPresentationParameters
->PresentationInterval
);
6351 /* No special treatment of these parameters. Just store them */
6352 swapchain
->presentParms
.SwapEffect
= pPresentationParameters
->SwapEffect
;
6353 swapchain
->presentParms
.Flags
= pPresentationParameters
->Flags
;
6354 swapchain
->presentParms
.PresentationInterval
= pPresentationParameters
->PresentationInterval
;
6355 swapchain
->presentParms
.FullScreen_RefreshRateInHz
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
6357 /* What to do about these? */
6358 if(pPresentationParameters
->BackBufferCount
!= 0 &&
6359 pPresentationParameters
->BackBufferCount
!= swapchain
->presentParms
.BackBufferCount
) {
6360 ERR("Cannot change the back buffer count yet\n");
6362 if(pPresentationParameters
->BackBufferFormat
!= WINED3DFMT_UNKNOWN
&&
6363 pPresentationParameters
->BackBufferFormat
!= swapchain
->presentParms
.BackBufferFormat
) {
6364 ERR("Cannot change the back buffer format yet\n");
6366 if(pPresentationParameters
->hDeviceWindow
!= NULL
&&
6367 pPresentationParameters
->hDeviceWindow
!= swapchain
->presentParms
.hDeviceWindow
) {
6368 ERR("Cannot change the device window yet\n");
6370 if (pPresentationParameters
->EnableAutoDepthStencil
&& !This
->auto_depth_stencil_buffer
) {
6373 TRACE("Creating the depth stencil buffer\n");
6375 hrc
= IWineD3DDeviceParent_CreateDepthStencilSurface(This
->device_parent
,
6377 pPresentationParameters
->BackBufferWidth
,
6378 pPresentationParameters
->BackBufferHeight
,
6379 pPresentationParameters
->AutoDepthStencilFormat
,
6380 pPresentationParameters
->MultiSampleType
,
6381 pPresentationParameters
->MultiSampleQuality
,
6383 &This
->auto_depth_stencil_buffer
);
6386 ERR("Failed to create the depth stencil buffer\n");
6387 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6388 return WINED3DERR_INVALIDCALL
;
6392 /* Reset the depth stencil */
6393 if (pPresentationParameters
->EnableAutoDepthStencil
)
6394 IWineD3DDevice_SetDepthStencilSurface(iface
, This
->auto_depth_stencil_buffer
);
6396 IWineD3DDevice_SetDepthStencilSurface(iface
, NULL
);
6398 TRACE("Resetting stateblock\n");
6399 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->updateStateBlock
);
6400 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)This
->stateBlock
);
6402 delete_opengl_contexts(iface
, (IWineD3DSwapChain
*) swapchain
);
6404 if(pPresentationParameters
->Windowed
) {
6405 mode
.Width
= swapchain
->orig_width
;
6406 mode
.Height
= swapchain
->orig_height
;
6407 mode
.RefreshRate
= 0;
6408 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
6410 mode
.Width
= pPresentationParameters
->BackBufferWidth
;
6411 mode
.Height
= pPresentationParameters
->BackBufferHeight
;
6412 mode
.RefreshRate
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
6413 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
6416 /* Should Width == 800 && Height == 0 set 800x600? */
6417 if(pPresentationParameters
->BackBufferWidth
!= 0 && pPresentationParameters
->BackBufferHeight
!= 0 &&
6418 (pPresentationParameters
->BackBufferWidth
!= swapchain
->presentParms
.BackBufferWidth
||
6419 pPresentationParameters
->BackBufferHeight
!= swapchain
->presentParms
.BackBufferHeight
))
6423 if(!pPresentationParameters
->Windowed
) {
6424 DisplayModeChanged
= TRUE
;
6426 swapchain
->presentParms
.BackBufferWidth
= pPresentationParameters
->BackBufferWidth
;
6427 swapchain
->presentParms
.BackBufferHeight
= pPresentationParameters
->BackBufferHeight
;
6429 hr
= updateSurfaceDesc((IWineD3DSurfaceImpl
*)swapchain
->frontBuffer
, pPresentationParameters
);
6432 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6436 for(i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; i
++) {
6437 hr
= updateSurfaceDesc((IWineD3DSurfaceImpl
*)swapchain
->backBuffer
[i
], pPresentationParameters
);
6440 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6444 if(This
->auto_depth_stencil_buffer
) {
6445 hr
= updateSurfaceDesc((IWineD3DSurfaceImpl
*)This
->auto_depth_stencil_buffer
, pPresentationParameters
);
6448 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6454 if((pPresentationParameters
->Windowed
&& !swapchain
->presentParms
.Windowed
) ||
6455 (swapchain
->presentParms
.Windowed
&& !pPresentationParameters
->Windowed
) ||
6456 DisplayModeChanged
) {
6458 IWineD3DDevice_SetDisplayMode(iface
, 0, &mode
);
6460 if(swapchain
->win_handle
&& !pPresentationParameters
->Windowed
) {
6461 if(swapchain
->presentParms
.Windowed
) {
6462 /* switch from windowed to fs */
6463 swapchain_setup_fullscreen_window(swapchain
, pPresentationParameters
->BackBufferWidth
,
6464 pPresentationParameters
->BackBufferHeight
);
6466 /* Fullscreen -> fullscreen mode change */
6467 MoveWindow(swapchain
->win_handle
, 0, 0,
6468 pPresentationParameters
->BackBufferWidth
, pPresentationParameters
->BackBufferHeight
,
6471 } else if(swapchain
->win_handle
&& !swapchain
->presentParms
.Windowed
) {
6472 /* Fullscreen -> windowed switch */
6473 swapchain_restore_fullscreen_window(swapchain
);
6475 swapchain
->presentParms
.Windowed
= pPresentationParameters
->Windowed
;
6476 } else if(!pPresentationParameters
->Windowed
) {
6477 DWORD style
= This
->style
, exStyle
= This
->exStyle
;
6478 /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6479 * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6480 * Reset to clear up their mess. Guild Wars also loses the device during that.
6484 swapchain_setup_fullscreen_window(swapchain
, pPresentationParameters
->BackBufferWidth
,
6485 pPresentationParameters
->BackBufferHeight
);
6486 This
->style
= style
;
6487 This
->exStyle
= exStyle
;
6490 /* Note: No parent needed for initial internal stateblock */
6491 hr
= IWineD3DDevice_CreateStateBlock(iface
, WINED3DSBT_INIT
, (IWineD3DStateBlock
**)&This
->stateBlock
, NULL
);
6492 if (FAILED(hr
)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr
);
6493 else TRACE("Created stateblock %p\n", This
->stateBlock
);
6494 This
->updateStateBlock
= This
->stateBlock
;
6495 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)This
->updateStateBlock
);
6497 hr
= IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock
*) This
->stateBlock
);
6499 ERR("Resetting the stateblock failed with error 0x%08x\n", hr
);
6502 if(wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
)
6505 GetClientRect(swapchain
->win_handle
, &client_rect
);
6507 if(!swapchain
->presentParms
.BackBufferCount
)
6509 TRACE("Single buffered rendering\n");
6510 swapchain
->render_to_fbo
= FALSE
;
6512 else if(swapchain
->presentParms
.BackBufferWidth
!= client_rect
.right
||
6513 swapchain
->presentParms
.BackBufferHeight
!= client_rect
.bottom
)
6515 TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
6516 swapchain
->presentParms
.BackBufferWidth
,
6517 swapchain
->presentParms
.BackBufferHeight
,
6518 client_rect
.right
, client_rect
.bottom
);
6519 swapchain
->render_to_fbo
= TRUE
;
6523 TRACE("Rendering directly to GL_BACK\n");
6524 swapchain
->render_to_fbo
= FALSE
;
6528 hr
= create_primary_opengl_context(iface
, (IWineD3DSwapChain
*) swapchain
);
6529 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6531 /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6537 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL enable_dialogs
)
6539 TRACE("iface %p, enable_dialogs %#x.\n", iface
, enable_dialogs
);
6541 if (!enable_dialogs
) FIXME("Dialogs cannot be disabled yet.\n");
6547 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, WINED3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
6548 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6549 TRACE("(%p) : pParameters %p\n", This
, pParameters
);
6551 *pParameters
= This
->createParms
;
6555 static void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
* iface
, UINT iSwapChain
, DWORD Flags
, CONST WINED3DGAMMARAMP
* pRamp
) {
6556 IWineD3DSwapChain
*swapchain
;
6558 TRACE("Relaying to swapchain\n");
6560 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
) {
6561 IWineD3DSwapChain_SetGammaRamp(swapchain
, Flags
, pRamp
);
6562 IWineD3DSwapChain_Release(swapchain
);
6566 static void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DGAMMARAMP
* pRamp
) {
6567 IWineD3DSwapChain
*swapchain
;
6569 TRACE("Relaying to swapchain\n");
6571 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
) {
6572 IWineD3DSwapChain_GetGammaRamp(swapchain
, pRamp
);
6573 IWineD3DSwapChain_Release(swapchain
);
6578 /** ********************************************************
6579 * Notification functions
6580 ** ********************************************************/
6581 /** This function must be called in the release of a resource when ref == 0,
6582 * the contents of resource must still be correct,
6583 * any handles to other resource held by the caller must be closed
6584 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6585 *****************************************************/
6586 void device_resource_add(IWineD3DDeviceImpl
*This
, IWineD3DResource
*resource
)
6588 TRACE("(%p) : Adding resource %p\n", This
, resource
);
6590 list_add_head(&This
->resources
, &((IWineD3DResourceImpl
*) resource
)->resource
.resource_list_entry
);
6593 static void device_resource_remove(IWineD3DDeviceImpl
*This
, IWineD3DResource
*resource
)
6595 TRACE("(%p) : Removing resource %p\n", This
, resource
);
6597 list_remove(&((IWineD3DResourceImpl
*) resource
)->resource
.resource_list_entry
);
6600 void device_resource_released(IWineD3DDeviceImpl
*This
, IWineD3DResource
*resource
)
6602 WINED3DRESOURCETYPE type
= IWineD3DResource_GetType(resource
);
6605 TRACE("(%p) : resource %p\n", This
, resource
);
6607 context_resource_released((IWineD3DDevice
*)This
, resource
, type
);
6610 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
6611 case WINED3DRTYPE_SURFACE
: {
6614 if (This
->d3d_initialized
)
6616 for (i
= 0; i
< This
->adapter
->gl_info
.limits
.buffers
; ++i
)
6618 if (This
->render_targets
[i
] == (IWineD3DSurface
*)resource
) {
6619 This
->render_targets
[i
] = NULL
;
6622 if (This
->stencilBufferTarget
== (IWineD3DSurface
*)resource
) {
6623 This
->stencilBufferTarget
= NULL
;
6629 case WINED3DRTYPE_TEXTURE
:
6630 case WINED3DRTYPE_CUBETEXTURE
:
6631 case WINED3DRTYPE_VOLUMETEXTURE
:
6632 for (counter
= 0; counter
< MAX_COMBINED_SAMPLERS
; counter
++) {
6633 if (This
->stateBlock
!= NULL
&& This
->stateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
6634 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
6635 This
->stateBlock
->textures
[counter
] = NULL
;
6637 if (This
->updateStateBlock
!= This
->stateBlock
){
6638 if (This
->updateStateBlock
->textures
[counter
] == (IWineD3DBaseTexture
*)resource
) {
6639 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter
, resource
);
6640 This
->updateStateBlock
->textures
[counter
] = NULL
;
6645 case WINED3DRTYPE_VOLUME
:
6646 /* TODO: nothing really? */
6648 case WINED3DRTYPE_BUFFER
:
6651 TRACE("Cleaning up stream pointers\n");
6653 for(streamNumber
= 0; streamNumber
< MAX_STREAMS
; streamNumber
++){
6654 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6655 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6657 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
6658 if ((IWineD3DResource
*)This
->updateStateBlock
->streamSource
[streamNumber
] == resource
) {
6659 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber
);
6660 This
->updateStateBlock
->streamSource
[streamNumber
] = 0;
6661 /* Set changed flag? */
6664 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) */
6665 if ((IWineD3DResource
*)This
->stateBlock
->streamSource
[streamNumber
] == resource
) {
6666 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber
);
6667 This
->stateBlock
->streamSource
[streamNumber
] = 0;
6672 if (This
->updateStateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
6673 if (This
->updateStateBlock
->pIndexData
== (IWineD3DBuffer
*)resource
) {
6674 This
->updateStateBlock
->pIndexData
= NULL
;
6677 if (This
->stateBlock
!= NULL
) { /* ==NULL when device is being destroyed */
6678 if (This
->stateBlock
->pIndexData
== (IWineD3DBuffer
*)resource
) {
6679 This
->stateBlock
->pIndexData
= NULL
;
6686 FIXME("(%p) unknown resource type %p %u\n", This
, resource
, IWineD3DResource_GetType(resource
));
6691 /* Remove the resource from the resourceStore */
6692 device_resource_remove(This
, resource
);
6694 TRACE("Resource released\n");
6698 static HRESULT WINAPI
IWineD3DDeviceImpl_EnumResources(IWineD3DDevice
*iface
, D3DCB_ENUMRESOURCES pCallback
, void *pData
) {
6699 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6700 IWineD3DResourceImpl
*resource
, *cursor
;
6702 TRACE("(%p)->(%p,%p)\n", This
, pCallback
, pData
);
6704 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &This
->resources
, IWineD3DResourceImpl
, resource
.resource_list_entry
) {
6705 TRACE("enumerating resource %p\n", resource
);
6706 IWineD3DResource_AddRef((IWineD3DResource
*) resource
);
6707 ret
= pCallback((IWineD3DResource
*) resource
, pData
);
6708 if(ret
== S_FALSE
) {
6709 TRACE("Canceling enumeration\n");
6716 /**********************************************************
6717 * IWineD3DDevice VTbl follows
6718 **********************************************************/
6720 static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
6722 /*** IUnknown methods ***/
6723 IWineD3DDeviceImpl_QueryInterface
,
6724 IWineD3DDeviceImpl_AddRef
,
6725 IWineD3DDeviceImpl_Release
,
6726 /*** IWineD3DDevice methods ***/
6727 IWineD3DDeviceImpl_GetParent
,
6728 /*** Creation methods**/
6729 IWineD3DDeviceImpl_CreateBuffer
,
6730 IWineD3DDeviceImpl_CreateVertexBuffer
,
6731 IWineD3DDeviceImpl_CreateIndexBuffer
,
6732 IWineD3DDeviceImpl_CreateStateBlock
,
6733 IWineD3DDeviceImpl_CreateSurface
,
6734 IWineD3DDeviceImpl_CreateRendertargetView
,
6735 IWineD3DDeviceImpl_CreateTexture
,
6736 IWineD3DDeviceImpl_CreateVolumeTexture
,
6737 IWineD3DDeviceImpl_CreateVolume
,
6738 IWineD3DDeviceImpl_CreateCubeTexture
,
6739 IWineD3DDeviceImpl_CreateQuery
,
6740 IWineD3DDeviceImpl_CreateSwapChain
,
6741 IWineD3DDeviceImpl_CreateVertexDeclaration
,
6742 IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF
,
6743 IWineD3DDeviceImpl_CreateVertexShader
,
6744 IWineD3DDeviceImpl_CreateGeometryShader
,
6745 IWineD3DDeviceImpl_CreatePixelShader
,
6746 IWineD3DDeviceImpl_CreatePalette
,
6747 /*** Odd functions **/
6748 IWineD3DDeviceImpl_Init3D
,
6749 IWineD3DDeviceImpl_InitGDI
,
6750 IWineD3DDeviceImpl_Uninit3D
,
6751 IWineD3DDeviceImpl_UninitGDI
,
6752 IWineD3DDeviceImpl_SetMultithreaded
,
6753 IWineD3DDeviceImpl_EvictManagedResources
,
6754 IWineD3DDeviceImpl_GetAvailableTextureMem
,
6755 IWineD3DDeviceImpl_GetBackBuffer
,
6756 IWineD3DDeviceImpl_GetCreationParameters
,
6757 IWineD3DDeviceImpl_GetDeviceCaps
,
6758 IWineD3DDeviceImpl_GetDirect3D
,
6759 IWineD3DDeviceImpl_GetDisplayMode
,
6760 IWineD3DDeviceImpl_SetDisplayMode
,
6761 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
6762 IWineD3DDeviceImpl_GetRasterStatus
,
6763 IWineD3DDeviceImpl_GetSwapChain
,
6764 IWineD3DDeviceImpl_Reset
,
6765 IWineD3DDeviceImpl_SetDialogBoxMode
,
6766 IWineD3DDeviceImpl_SetCursorProperties
,
6767 IWineD3DDeviceImpl_SetCursorPosition
,
6768 IWineD3DDeviceImpl_ShowCursor
,
6769 /*** Getters and setters **/
6770 IWineD3DDeviceImpl_SetClipPlane
,
6771 IWineD3DDeviceImpl_GetClipPlane
,
6772 IWineD3DDeviceImpl_SetClipStatus
,
6773 IWineD3DDeviceImpl_GetClipStatus
,
6774 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
6775 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
6776 IWineD3DDeviceImpl_SetDepthStencilSurface
,
6777 IWineD3DDeviceImpl_GetDepthStencilSurface
,
6778 IWineD3DDeviceImpl_SetGammaRamp
,
6779 IWineD3DDeviceImpl_GetGammaRamp
,
6780 IWineD3DDeviceImpl_SetIndexBuffer
,
6781 IWineD3DDeviceImpl_GetIndexBuffer
,
6782 IWineD3DDeviceImpl_SetBaseVertexIndex
,
6783 IWineD3DDeviceImpl_GetBaseVertexIndex
,
6784 IWineD3DDeviceImpl_SetLight
,
6785 IWineD3DDeviceImpl_GetLight
,
6786 IWineD3DDeviceImpl_SetLightEnable
,
6787 IWineD3DDeviceImpl_GetLightEnable
,
6788 IWineD3DDeviceImpl_SetMaterial
,
6789 IWineD3DDeviceImpl_GetMaterial
,
6790 IWineD3DDeviceImpl_SetNPatchMode
,
6791 IWineD3DDeviceImpl_GetNPatchMode
,
6792 IWineD3DDeviceImpl_SetPaletteEntries
,
6793 IWineD3DDeviceImpl_GetPaletteEntries
,
6794 IWineD3DDeviceImpl_SetPixelShader
,
6795 IWineD3DDeviceImpl_GetPixelShader
,
6796 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
6797 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
6798 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
6799 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
6800 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
6801 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
6802 IWineD3DDeviceImpl_SetRenderState
,
6803 IWineD3DDeviceImpl_GetRenderState
,
6804 IWineD3DDeviceImpl_SetRenderTarget
,
6805 IWineD3DDeviceImpl_GetRenderTarget
,
6806 IWineD3DDeviceImpl_SetFrontBackBuffers
,
6807 IWineD3DDeviceImpl_SetSamplerState
,
6808 IWineD3DDeviceImpl_GetSamplerState
,
6809 IWineD3DDeviceImpl_SetScissorRect
,
6810 IWineD3DDeviceImpl_GetScissorRect
,
6811 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
6812 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
6813 IWineD3DDeviceImpl_SetStreamSource
,
6814 IWineD3DDeviceImpl_GetStreamSource
,
6815 IWineD3DDeviceImpl_SetStreamSourceFreq
,
6816 IWineD3DDeviceImpl_GetStreamSourceFreq
,
6817 IWineD3DDeviceImpl_SetTexture
,
6818 IWineD3DDeviceImpl_GetTexture
,
6819 IWineD3DDeviceImpl_SetTextureStageState
,
6820 IWineD3DDeviceImpl_GetTextureStageState
,
6821 IWineD3DDeviceImpl_SetTransform
,
6822 IWineD3DDeviceImpl_GetTransform
,
6823 IWineD3DDeviceImpl_SetVertexDeclaration
,
6824 IWineD3DDeviceImpl_GetVertexDeclaration
,
6825 IWineD3DDeviceImpl_SetVertexShader
,
6826 IWineD3DDeviceImpl_GetVertexShader
,
6827 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
6828 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
6829 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
6830 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
6831 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
6832 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
6833 IWineD3DDeviceImpl_SetViewport
,
6834 IWineD3DDeviceImpl_GetViewport
,
6835 IWineD3DDeviceImpl_MultiplyTransform
,
6836 IWineD3DDeviceImpl_ValidateDevice
,
6837 IWineD3DDeviceImpl_ProcessVertices
,
6838 /*** State block ***/
6839 IWineD3DDeviceImpl_BeginStateBlock
,
6840 IWineD3DDeviceImpl_EndStateBlock
,
6841 /*** Scene management ***/
6842 IWineD3DDeviceImpl_BeginScene
,
6843 IWineD3DDeviceImpl_EndScene
,
6844 IWineD3DDeviceImpl_Present
,
6845 IWineD3DDeviceImpl_Clear
,
6846 IWineD3DDeviceImpl_ClearRendertargetView
,
6848 IWineD3DDeviceImpl_SetPrimitiveType
,
6849 IWineD3DDeviceImpl_GetPrimitiveType
,
6850 IWineD3DDeviceImpl_DrawPrimitive
,
6851 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
6852 IWineD3DDeviceImpl_DrawPrimitiveUP
,
6853 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
6854 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
6855 IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided
,
6856 IWineD3DDeviceImpl_DrawRectPatch
,
6857 IWineD3DDeviceImpl_DrawTriPatch
,
6858 IWineD3DDeviceImpl_DeletePatch
,
6859 IWineD3DDeviceImpl_ColorFill
,
6860 IWineD3DDeviceImpl_UpdateTexture
,
6861 IWineD3DDeviceImpl_UpdateSurface
,
6862 IWineD3DDeviceImpl_GetFrontBufferData
,
6863 /*** object tracking ***/
6864 IWineD3DDeviceImpl_EnumResources
6867 HRESULT
device_init(IWineD3DDeviceImpl
*device
, IWineD3DImpl
*wined3d
,
6868 UINT adapter_idx
, WINED3DDEVTYPE device_type
, HWND focus_window
, DWORD flags
,
6869 IUnknown
*parent
, IWineD3DDeviceParent
*device_parent
)
6871 struct wined3d_adapter
*adapter
= &wined3d
->adapters
[adapter_idx
];
6872 const struct fragment_pipeline
*fragment_pipeline
;
6873 struct shader_caps shader_caps
;
6874 struct fragment_caps ffp_caps
;
6875 WINED3DDISPLAYMODE mode
;
6879 device
->lpVtbl
= &IWineD3DDevice_Vtbl
;
6881 device
->wined3d
= (IWineD3D
*)wined3d
;
6882 IWineD3D_AddRef(device
->wined3d
);
6883 device
->adapter
= wined3d
->adapter_count
? adapter
: NULL
;
6884 device
->parent
= parent
;
6885 device
->device_parent
= device_parent
;
6886 list_init(&device
->resources
);
6887 list_init(&device
->shaders
);
6889 device
->surface_alignment
= wined3d
->dxVersion
== 7 ? DDRAW_PITCH_ALIGNMENT
: D3D8_PITCH_ALIGNMENT
;
6890 device
->posFixup
[0] = 1.0f
; /* This is needed to get the x coord unmodified through a MAD. */
6892 /* Get the initial screen setup for ddraw. */
6893 hr
= IWineD3D_GetAdapterDisplayMode((IWineD3D
*)wined3d
, adapter_idx
, &mode
);
6896 ERR("Failed to get the adapter's display mode, hr %#x.\n", hr
);
6897 IWineD3D_Release(device
->wined3d
);
6900 device
->ddraw_width
= mode
.Width
;
6901 device
->ddraw_height
= mode
.Height
;
6902 device
->ddraw_format
= mode
.Format
;
6904 /* Save the creation parameters. */
6905 device
->createParms
.AdapterOrdinal
= adapter_idx
;
6906 device
->createParms
.DeviceType
= device_type
;
6907 device
->createParms
.hFocusWindow
= focus_window
;
6908 device
->createParms
.BehaviorFlags
= flags
;
6910 device
->devType
= device_type
;
6911 for (i
= 0; i
< PATCHMAP_SIZE
; ++i
) list_init(&device
->patches
[i
]);
6913 select_shader_mode(&adapter
->gl_info
, &device
->ps_selected_mode
, &device
->vs_selected_mode
);
6914 device
->shader_backend
= select_shader_backend(adapter
, device_type
);
6916 memset(&shader_caps
, 0, sizeof(shader_caps
));
6917 device
->shader_backend
->shader_get_caps(device_type
, &adapter
->gl_info
, &shader_caps
);
6918 device
->d3d_vshader_constantF
= shader_caps
.MaxVertexShaderConst
;
6919 device
->d3d_pshader_constantF
= shader_caps
.MaxPixelShaderConst
;
6920 device
->vs_clipping
= shader_caps
.VSClipping
;
6922 memset(&ffp_caps
, 0, sizeof(ffp_caps
));
6923 fragment_pipeline
= select_fragment_implementation(adapter
, device_type
);
6924 device
->frag_pipe
= fragment_pipeline
;
6925 fragment_pipeline
->get_caps(device_type
, &adapter
->gl_info
, &ffp_caps
);
6926 device
->max_ffp_textures
= ffp_caps
.MaxSimultaneousTextures
;
6927 device
->max_ffp_texture_stages
= ffp_caps
.MaxTextureBlendStages
;
6929 hr
= compile_state_table(device
->StateTable
, device
->multistate_funcs
, &adapter
->gl_info
,
6930 ffp_vertexstate_template
, fragment_pipeline
, misc_state_template
);
6933 ERR("Failed to compile state table, hr %#x.\n", hr
);
6934 IWineD3D_Release(device
->wined3d
);
6938 device
->blitter
= select_blit_implementation(adapter
, device_type
);
6944 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl
*This
, DWORD state
) {
6945 DWORD rep
= This
->StateTable
[state
].representative
;
6946 struct wined3d_context
*context
;
6951 for(i
= 0; i
< This
->numContexts
; i
++) {
6952 context
= This
->contexts
[i
];
6953 if(isStateDirty(context
, rep
)) continue;
6955 context
->dirtyArray
[context
->numDirtyEntries
++] = rep
;
6956 idx
= rep
/ (sizeof(*context
->isStateDirty
) * CHAR_BIT
);
6957 shift
= rep
& ((sizeof(*context
->isStateDirty
) * CHAR_BIT
) - 1);
6958 context
->isStateDirty
[idx
] |= (1 << shift
);
6962 void get_drawable_size_pbuffer(struct wined3d_context
*context
, UINT
*width
, UINT
*height
)
6964 IWineD3DDeviceImpl
*device
= ((IWineD3DSurfaceImpl
*)context
->current_rt
)->resource
.device
;
6965 /* The drawable size of a pbuffer render target is the current pbuffer size. */
6966 *width
= device
->pbufferWidth
;
6967 *height
= device
->pbufferHeight
;
6970 void get_drawable_size_fbo(struct wined3d_context
*context
, UINT
*width
, UINT
*height
)
6972 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*)context
->current_rt
;
6973 /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
6974 *width
= surface
->pow2Width
;
6975 *height
= surface
->pow2Height
;
6978 void get_drawable_size_backbuffer(struct wined3d_context
*context
, UINT
*width
, UINT
*height
)
6980 IWineD3DSurfaceImpl
*surface
= (IWineD3DSurfaceImpl
*)context
->surface
;
6981 /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
6982 * current context's drawable, which is the size of the back buffer of the swapchain
6983 * the active context belongs to. The back buffer of the swapchain is stored as the
6984 * surface the context belongs to. */
6985 *width
= surface
->currentDesc
.Width
;
6986 *height
= surface
->currentDesc
.Height
;
6989 LRESULT
device_process_message(IWineD3DDeviceImpl
*device
, HWND window
,
6990 UINT message
, WPARAM wparam
, LPARAM lparam
, WNDPROC proc
)
6992 if (device
->filter_messages
)
6994 TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
6995 window
, message
, wparam
, lparam
);
6996 return DefWindowProcW(window
, message
, wparam
, lparam
);
6999 if (message
== WM_DESTROY
)
7001 TRACE("unregister window %p.\n", window
);
7002 wined3d_unregister_window(window
);
7004 if (device
->focus_window
== window
) device
->focus_window
= NULL
;
7005 else ERR("Window %p is not the focus window for device %p.\n", window
, device
);
7008 return CallWindowProcW(proc
, window
, message
, wparam
, lparam
);