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-2010 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
);
38 /* Define the default light parameters as specified by MSDN */
39 const WINED3DLIGHT WINED3D_default_light
= {
41 WINED3DLIGHT_DIRECTIONAL
, /* Type */
42 { 1.0f
, 1.0f
, 1.0f
, 0.0f
}, /* Diffuse r,g,b,a */
43 { 0.0f
, 0.0f
, 0.0f
, 0.0f
}, /* Specular r,g,b,a */
44 { 0.0f
, 0.0f
, 0.0f
, 0.0f
}, /* Ambient r,g,b,a, */
45 { 0.0f
, 0.0f
, 0.0f
}, /* Position x,y,z */
46 { 0.0f
, 0.0f
, 1.0f
}, /* Direction x,y,z */
49 0.0f
, 0.0f
, 0.0f
, /* Attenuation 0,1,2 */
54 /**********************************************************
55 * Global variable / Constants follow
56 **********************************************************/
57 const float identity
[] =
59 1.0f
, 0.0f
, 0.0f
, 0.0f
,
60 0.0f
, 1.0f
, 0.0f
, 0.0f
,
61 0.0f
, 0.0f
, 1.0f
, 0.0f
,
62 0.0f
, 0.0f
, 0.0f
, 1.0f
,
63 }; /* When needed for comparisons */
65 /* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
66 * actually have the same values in GL and D3D. */
67 static GLenum
gl_primitive_type_from_d3d(WINED3DPRIMITIVETYPE primitive_type
)
69 switch(primitive_type
)
71 case WINED3DPT_POINTLIST
:
74 case WINED3DPT_LINELIST
:
77 case WINED3DPT_LINESTRIP
:
80 case WINED3DPT_TRIANGLELIST
:
83 case WINED3DPT_TRIANGLESTRIP
:
84 return GL_TRIANGLE_STRIP
;
86 case WINED3DPT_TRIANGLEFAN
:
87 return GL_TRIANGLE_FAN
;
89 case WINED3DPT_LINELIST_ADJ
:
90 return GL_LINES_ADJACENCY_ARB
;
92 case WINED3DPT_LINESTRIP_ADJ
:
93 return GL_LINE_STRIP_ADJACENCY_ARB
;
95 case WINED3DPT_TRIANGLELIST_ADJ
:
96 return GL_TRIANGLES_ADJACENCY_ARB
;
98 case WINED3DPT_TRIANGLESTRIP_ADJ
:
99 return GL_TRIANGLE_STRIP_ADJACENCY_ARB
;
102 FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type
));
107 static WINED3DPRIMITIVETYPE
d3d_primitive_type_from_gl(GLenum primitive_type
)
109 switch(primitive_type
)
112 return WINED3DPT_POINTLIST
;
115 return WINED3DPT_LINELIST
;
118 return WINED3DPT_LINESTRIP
;
121 return WINED3DPT_TRIANGLELIST
;
123 case GL_TRIANGLE_STRIP
:
124 return WINED3DPT_TRIANGLESTRIP
;
126 case GL_TRIANGLE_FAN
:
127 return WINED3DPT_TRIANGLEFAN
;
129 case GL_LINES_ADJACENCY_ARB
:
130 return WINED3DPT_LINELIST_ADJ
;
132 case GL_LINE_STRIP_ADJACENCY_ARB
:
133 return WINED3DPT_LINESTRIP_ADJ
;
135 case GL_TRIANGLES_ADJACENCY_ARB
:
136 return WINED3DPT_TRIANGLELIST_ADJ
;
138 case GL_TRIANGLE_STRIP_ADJACENCY_ARB
:
139 return WINED3DPT_TRIANGLESTRIP_ADJ
;
142 FIXME("Unhandled primitive type %s\n", debug_d3dprimitivetype(primitive_type
));
143 return WINED3DPT_UNDEFINED
;
147 static BOOL
fixed_get_input(BYTE usage
, BYTE usage_idx
, unsigned int *regnum
)
149 if ((usage
== WINED3DDECLUSAGE_POSITION
|| usage
== WINED3DDECLUSAGE_POSITIONT
) && !usage_idx
)
150 *regnum
= WINED3D_FFP_POSITION
;
151 else if (usage
== WINED3DDECLUSAGE_BLENDWEIGHT
&& !usage_idx
)
152 *regnum
= WINED3D_FFP_BLENDWEIGHT
;
153 else if (usage
== WINED3DDECLUSAGE_BLENDINDICES
&& !usage_idx
)
154 *regnum
= WINED3D_FFP_BLENDINDICES
;
155 else if (usage
== WINED3DDECLUSAGE_NORMAL
&& !usage_idx
)
156 *regnum
= WINED3D_FFP_NORMAL
;
157 else if (usage
== WINED3DDECLUSAGE_PSIZE
&& !usage_idx
)
158 *regnum
= WINED3D_FFP_PSIZE
;
159 else if (usage
== WINED3DDECLUSAGE_COLOR
&& !usage_idx
)
160 *regnum
= WINED3D_FFP_DIFFUSE
;
161 else if (usage
== WINED3DDECLUSAGE_COLOR
&& usage_idx
== 1)
162 *regnum
= WINED3D_FFP_SPECULAR
;
163 else if (usage
== WINED3DDECLUSAGE_TEXCOORD
&& usage_idx
< WINED3DDP_MAXTEXCOORD
)
164 *regnum
= WINED3D_FFP_TEXCOORD0
+ usage_idx
;
167 FIXME("Unsupported input stream [usage=%s, usage_idx=%u]\n", debug_d3ddeclusage(usage
), usage_idx
);
175 /* Context activation is done by the caller. */
176 void device_stream_info_from_declaration(IWineD3DDeviceImpl
*This
,
177 BOOL use_vshader
, struct wined3d_stream_info
*stream_info
, BOOL
*fixup
)
179 /* We need to deal with frequency data! */
180 struct wined3d_vertex_declaration
*declaration
= This
->stateBlock
->state
.vertex_declaration
;
183 stream_info
->use_map
= 0;
184 stream_info
->swizzle_map
= 0;
186 /* Check for transformed vertices, disable vertex shader if present. */
187 stream_info
->position_transformed
= declaration
->position_transformed
;
188 if (declaration
->position_transformed
) use_vshader
= FALSE
;
190 /* Translate the declaration into strided data. */
191 for (i
= 0; i
< declaration
->element_count
; ++i
)
193 const struct wined3d_vertex_declaration_element
*element
= &declaration
->elements
[i
];
194 struct wined3d_buffer
*buffer
= This
->stateBlock
->state
.streams
[element
->input_slot
].buffer
;
195 GLuint buffer_object
= 0;
196 const BYTE
*data
= NULL
;
201 TRACE("%p Element %p (%u of %u)\n", declaration
->elements
,
202 element
, i
+ 1, declaration
->element_count
);
204 if (!buffer
) continue;
206 stride
= This
->stateBlock
->state
.streams
[element
->input_slot
].stride
;
207 if (This
->stateBlock
->state
.user_stream
)
209 TRACE("Stream %u is UP, %p\n", element
->input_slot
, buffer
);
211 data
= (BYTE
*)buffer
;
215 TRACE("Stream %u isn't UP, %p\n", element
->input_slot
, buffer
);
216 data
= buffer_get_memory(buffer
, &This
->adapter
->gl_info
, &buffer_object
);
218 /* Can't use vbo's if the base vertex index is negative. OpenGL doesn't accept negative offsets
219 * (or rather offsets bigger than the vbo, because the pointer is unsigned), so use system memory
220 * sources. In most sane cases the pointer - offset will still be > 0, otherwise it will wrap
221 * around to some big value. Hope that with the indices, the driver wraps it back internally. If
222 * not, drawStridedSlow is needed, including a vertex buffer path. */
223 if (This
->stateBlock
->state
.load_base_vertex_index
< 0)
225 WARN("load_base_vertex_index is < 0 (%d), not using VBOs.\n",
226 This
->stateBlock
->state
.load_base_vertex_index
);
228 data
= buffer_get_sysmem(buffer
, &This
->adapter
->gl_info
);
229 if ((UINT_PTR
)data
< -This
->stateBlock
->state
.load_base_vertex_index
* stride
)
231 FIXME("System memory vertex data load offset is negative!\n");
237 if (buffer_object
) *fixup
= TRUE
;
238 else if (*fixup
&& !use_vshader
239 && (element
->usage
== WINED3DDECLUSAGE_COLOR
240 || element
->usage
== WINED3DDECLUSAGE_POSITIONT
))
242 static BOOL warned
= FALSE
;
245 /* This may be bad with the fixed function pipeline. */
246 FIXME("Missing vbo streams with unfixed colors or transformed position, expect problems\n");
252 data
+= element
->offset
;
254 TRACE("offset %u input_slot %u usage_idx %d\n", element
->offset
, element
->input_slot
, element
->usage_idx
);
258 if (element
->output_slot
== ~0U)
260 /* TODO: Assuming vertexdeclarations are usually used with the
261 * same or a similar shader, it might be worth it to store the
262 * last used output slot and try that one first. */
263 stride_used
= vshader_get_input(This
->stateBlock
->state
.vertex_shader
,
264 element
->usage
, element
->usage_idx
, &idx
);
268 idx
= element
->output_slot
;
274 if (!element
->ffp_valid
)
276 WARN("Skipping unsupported fixed function element of format %s and usage %s\n",
277 debug_d3dformat(element
->format
->id
), debug_d3ddeclusage(element
->usage
));
282 stride_used
= fixed_get_input(element
->usage
, element
->usage_idx
, &idx
);
288 TRACE("Load %s array %u [usage %s, usage_idx %u, "
289 "input_slot %u, offset %u, stride %u, format %s, buffer_object %u]\n",
290 use_vshader
? "shader": "fixed function", idx
,
291 debug_d3ddeclusage(element
->usage
), element
->usage_idx
, element
->input_slot
,
292 element
->offset
, stride
, debug_d3dformat(element
->format
->id
), buffer_object
);
294 stream_info
->elements
[idx
].format
= element
->format
;
295 stream_info
->elements
[idx
].stride
= stride
;
296 stream_info
->elements
[idx
].data
= data
;
297 stream_info
->elements
[idx
].stream_idx
= element
->input_slot
;
298 stream_info
->elements
[idx
].buffer_object
= buffer_object
;
300 if (!This
->adapter
->gl_info
.supported
[ARB_VERTEX_ARRAY_BGRA
]
301 && element
->format
->id
== WINED3DFMT_B8G8R8A8_UNORM
)
303 stream_info
->swizzle_map
|= 1 << idx
;
305 stream_info
->use_map
|= 1 << idx
;
309 This
->num_buffer_queries
= 0;
310 if (!This
->stateBlock
->state
.user_stream
)
312 WORD map
= stream_info
->use_map
;
314 /* PreLoad all the vertex buffers. */
315 for (i
= 0; map
; map
>>= 1, ++i
)
317 struct wined3d_stream_info_element
*element
;
318 struct wined3d_buffer
*buffer
;
320 if (!(map
& 1)) continue;
322 element
= &stream_info
->elements
[i
];
323 buffer
= This
->stateBlock
->state
.streams
[element
->stream_idx
].buffer
;
324 IWineD3DBuffer_PreLoad((IWineD3DBuffer
*)buffer
);
326 /* If PreLoad dropped the buffer object, update the stream info. */
327 if (buffer
->buffer_object
!= element
->buffer_object
)
329 element
->buffer_object
= 0;
330 element
->data
= buffer_get_sysmem(buffer
, &This
->adapter
->gl_info
) + (ptrdiff_t)element
->data
;
334 This
->buffer_queries
[This
->num_buffer_queries
++] = buffer
->query
;
339 static void stream_info_element_from_strided(const struct wined3d_gl_info
*gl_info
,
340 const struct WineDirect3DStridedData
*strided
, struct wined3d_stream_info_element
*e
)
342 e
->format
= wined3d_get_format(gl_info
, strided
->format
);
343 e
->stride
= strided
->dwStride
;
344 e
->data
= strided
->lpData
;
346 e
->buffer_object
= 0;
349 static void device_stream_info_from_strided(const struct wined3d_gl_info
*gl_info
,
350 const struct WineDirect3DVertexStridedData
*strided
, struct wined3d_stream_info
*stream_info
)
354 memset(stream_info
, 0, sizeof(*stream_info
));
356 if (strided
->position
.lpData
)
357 stream_info_element_from_strided(gl_info
, &strided
->position
, &stream_info
->elements
[WINED3D_FFP_POSITION
]);
358 if (strided
->normal
.lpData
)
359 stream_info_element_from_strided(gl_info
, &strided
->normal
, &stream_info
->elements
[WINED3D_FFP_NORMAL
]);
360 if (strided
->diffuse
.lpData
)
361 stream_info_element_from_strided(gl_info
, &strided
->diffuse
, &stream_info
->elements
[WINED3D_FFP_DIFFUSE
]);
362 if (strided
->specular
.lpData
)
363 stream_info_element_from_strided(gl_info
, &strided
->specular
, &stream_info
->elements
[WINED3D_FFP_SPECULAR
]);
365 for (i
= 0; i
< WINED3DDP_MAXTEXCOORD
; ++i
)
367 if (strided
->texCoords
[i
].lpData
)
368 stream_info_element_from_strided(gl_info
, &strided
->texCoords
[i
],
369 &stream_info
->elements
[WINED3D_FFP_TEXCOORD0
+ i
]);
372 stream_info
->position_transformed
= strided
->position_transformed
;
374 for (i
= 0; i
< sizeof(stream_info
->elements
) / sizeof(*stream_info
->elements
); ++i
)
376 if (!stream_info
->elements
[i
].format
) continue;
378 if (!gl_info
->supported
[ARB_VERTEX_ARRAY_BGRA
]
379 && stream_info
->elements
[i
].format
->id
== WINED3DFMT_B8G8R8A8_UNORM
)
381 stream_info
->swizzle_map
|= 1 << i
;
383 stream_info
->use_map
|= 1 << i
;
387 static void device_trace_strided_stream_info(const struct wined3d_stream_info
*stream_info
)
389 TRACE("Strided Data:\n");
390 TRACE_STRIDED(stream_info
, WINED3D_FFP_POSITION
);
391 TRACE_STRIDED(stream_info
, WINED3D_FFP_BLENDWEIGHT
);
392 TRACE_STRIDED(stream_info
, WINED3D_FFP_BLENDINDICES
);
393 TRACE_STRIDED(stream_info
, WINED3D_FFP_NORMAL
);
394 TRACE_STRIDED(stream_info
, WINED3D_FFP_PSIZE
);
395 TRACE_STRIDED(stream_info
, WINED3D_FFP_DIFFUSE
);
396 TRACE_STRIDED(stream_info
, WINED3D_FFP_SPECULAR
);
397 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD0
);
398 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD1
);
399 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD2
);
400 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD3
);
401 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD4
);
402 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD5
);
403 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD6
);
404 TRACE_STRIDED(stream_info
, WINED3D_FFP_TEXCOORD7
);
407 /* Context activation is done by the caller. */
408 void device_update_stream_info(IWineD3DDeviceImpl
*device
, const struct wined3d_gl_info
*gl_info
)
410 struct wined3d_stream_info
*stream_info
= &device
->strided_streams
;
411 const struct wined3d_state
*state
= &device
->stateBlock
->state
;
414 if (device
->up_strided
)
416 /* Note: this is a ddraw fixed-function code path. */
417 TRACE("=============================== Strided Input ================================\n");
418 device_stream_info_from_strided(gl_info
, device
->up_strided
, stream_info
);
419 if (TRACE_ON(d3d
)) device_trace_strided_stream_info(stream_info
);
423 TRACE("============================= Vertex Declaration =============================\n");
424 device_stream_info_from_declaration(device
, !!state
->vertex_shader
, stream_info
, &fixup
);
427 if (state
->vertex_shader
&& !stream_info
->position_transformed
)
429 if (state
->vertex_declaration
->half_float_conv_needed
&& !fixup
)
431 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion.\n");
432 device
->useDrawStridedSlow
= TRUE
;
436 device
->useDrawStridedSlow
= FALSE
;
441 WORD slow_mask
= (1 << WINED3D_FFP_PSIZE
);
442 slow_mask
|= -!gl_info
->supported
[ARB_VERTEX_ARRAY_BGRA
]
443 & ((1 << WINED3D_FFP_DIFFUSE
) | (1 << WINED3D_FFP_SPECULAR
));
445 if ((stream_info
->position_transformed
|| (stream_info
->use_map
& slow_mask
)) && !fixup
)
447 device
->useDrawStridedSlow
= TRUE
;
451 device
->useDrawStridedSlow
= FALSE
;
456 static void device_preload_texture(const struct wined3d_state
*state
, unsigned int idx
)
458 IWineD3DBaseTextureImpl
*texture
;
459 enum WINED3DSRGB srgb
;
461 if (!(texture
= state
->textures
[idx
])) return;
462 srgb
= state
->sampler_states
[idx
][WINED3DSAMP_SRGBTEXTURE
] ? SRGB_SRGB
: SRGB_RGB
;
463 texture
->baseTexture
.texture_ops
->texture_preload(texture
, srgb
);
466 void device_preload_textures(IWineD3DDeviceImpl
*device
)
468 const struct wined3d_state
*state
= &device
->stateBlock
->state
;
473 for (i
= 0; i
< MAX_VERTEX_SAMPLERS
; ++i
)
475 if (state
->vertex_shader
->baseShader
.reg_maps
.sampler_type
[i
])
476 device_preload_texture(state
, MAX_FRAGMENT_SAMPLERS
+ i
);
482 for (i
= 0; i
< MAX_FRAGMENT_SAMPLERS
; ++i
)
484 if (state
->pixel_shader
->baseShader
.reg_maps
.sampler_type
[i
])
485 device_preload_texture(state
, i
);
490 WORD ffu_map
= device
->fixed_function_usage_map
;
492 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
495 device_preload_texture(state
, i
);
500 BOOL
device_context_add(IWineD3DDeviceImpl
*device
, struct wined3d_context
*context
)
502 struct wined3d_context
**new_array
;
504 TRACE("Adding context %p.\n", context
);
506 if (!device
->contexts
) new_array
= HeapAlloc(GetProcessHeap(), 0, sizeof(*new_array
));
507 else new_array
= HeapReAlloc(GetProcessHeap(), 0, device
->contexts
, sizeof(*new_array
) * (device
->numContexts
+ 1));
511 ERR("Failed to grow the context array.\n");
515 new_array
[device
->numContexts
++] = context
;
516 device
->contexts
= new_array
;
520 void device_context_remove(IWineD3DDeviceImpl
*device
, struct wined3d_context
*context
)
522 struct wined3d_context
**new_array
;
526 TRACE("Removing context %p.\n", context
);
528 for (i
= 0; i
< device
->numContexts
; ++i
)
530 if (device
->contexts
[i
] == context
)
539 ERR("Context %p doesn't exist in context array.\n", context
);
543 if (!--device
->numContexts
)
545 HeapFree(GetProcessHeap(), 0, device
->contexts
);
546 device
->contexts
= NULL
;
550 memmove(&device
->contexts
[i
], &device
->contexts
[i
+ 1], (device
->numContexts
- i
) * sizeof(*device
->contexts
));
551 new_array
= HeapReAlloc(GetProcessHeap(), 0, device
->contexts
, device
->numContexts
* sizeof(*device
->contexts
));
554 ERR("Failed to shrink context array. Oh well.\n");
558 device
->contexts
= new_array
;
561 void device_get_draw_rect(IWineD3DDeviceImpl
*device
, RECT
*rect
)
563 struct wined3d_stateblock
*stateblock
= device
->stateBlock
;
564 WINED3DVIEWPORT
*vp
= &stateblock
->state
.viewport
;
566 SetRect(rect
, vp
->X
, vp
->Y
, vp
->X
+ vp
->Width
, vp
->Y
+ vp
->Height
);
568 if (stateblock
->state
.render_states
[WINED3DRS_SCISSORTESTENABLE
])
570 IntersectRect(rect
, rect
, &stateblock
->state
.scissor_rect
);
574 /* Do not call while under the GL lock. */
575 void device_switch_onscreen_ds(IWineD3DDeviceImpl
*device
,
576 struct wined3d_context
*context
, IWineD3DSurfaceImpl
*depth_stencil
)
578 if (device
->onscreen_depth_stencil
)
580 surface_load_ds_location(device
->onscreen_depth_stencil
, context
, SFLAG_DS_OFFSCREEN
);
581 surface_modify_ds_location(device
->onscreen_depth_stencil
, SFLAG_DS_OFFSCREEN
,
582 device
->onscreen_depth_stencil
->ds_current_size
.cx
,
583 device
->onscreen_depth_stencil
->ds_current_size
.cy
);
584 IWineD3DSurface_Release((IWineD3DSurface
*)device
->onscreen_depth_stencil
);
586 device
->onscreen_depth_stencil
= depth_stencil
;
587 IWineD3DSurface_AddRef((IWineD3DSurface
*)device
->onscreen_depth_stencil
);
590 static BOOL
is_full_clear(IWineD3DSurfaceImpl
*target
, const RECT
*draw_rect
, const RECT
*clear_rect
)
592 /* partial draw rect */
593 if (draw_rect
->left
|| draw_rect
->top
594 || draw_rect
->right
< target
->currentDesc
.Width
595 || draw_rect
->bottom
< target
->currentDesc
.Height
)
598 /* partial clear rect */
599 if (clear_rect
&& (clear_rect
->left
> 0 || clear_rect
->top
> 0
600 || clear_rect
->right
< target
->currentDesc
.Width
601 || clear_rect
->bottom
< target
->currentDesc
.Height
))
607 static void prepare_ds_clear(IWineD3DSurfaceImpl
*ds
, struct wined3d_context
*context
,
608 DWORD location
, const RECT
*draw_rect
, UINT rect_count
, const RECT
*clear_rect
)
610 RECT current_rect
, r
;
612 if (ds
->flags
& location
)
613 SetRect(¤t_rect
, 0, 0,
614 ds
->ds_current_size
.cx
,
615 ds
->ds_current_size
.cy
);
617 SetRectEmpty(¤t_rect
);
619 IntersectRect(&r
, draw_rect
, ¤t_rect
);
620 if (EqualRect(&r
, draw_rect
))
622 /* current_rect ⊇ draw_rect, modify only. */
623 surface_modify_ds_location(ds
, location
, ds
->ds_current_size
.cx
, ds
->ds_current_size
.cy
);
627 if (EqualRect(&r
, ¤t_rect
))
629 /* draw_rect ⊇ current_rect, test if we're doing a full clear. */
633 /* Full clear, modify only. */
634 surface_modify_ds_location(ds
, location
, draw_rect
->right
, draw_rect
->bottom
);
638 IntersectRect(&r
, draw_rect
, clear_rect
);
639 if (EqualRect(&r
, draw_rect
))
641 /* clear_rect ⊇ draw_rect, modify only. */
642 surface_modify_ds_location(ds
, location
, draw_rect
->right
, draw_rect
->bottom
);
648 surface_load_ds_location(ds
, context
, location
);
649 surface_modify_ds_location(ds
, location
, ds
->ds_current_size
.cx
, ds
->ds_current_size
.cy
);
652 /* Do not call while under the GL lock. */
653 HRESULT
device_clear_render_targets(IWineD3DDeviceImpl
*device
, UINT rt_count
, IWineD3DSurfaceImpl
**rts
,
654 UINT rect_count
, const RECT
*rects
, const RECT
*draw_rect
, DWORD flags
,
655 const WINED3DCOLORVALUE
*color
, float depth
, DWORD stencil
)
657 const RECT
*clear_rect
= (rect_count
> 0 && rects
) ? (const RECT
*)rects
: NULL
;
658 IWineD3DSurfaceImpl
*depth_stencil
= device
->depth_stencil
;
659 IWineD3DSurfaceImpl
*target
= rts
[0];
660 UINT drawable_width
, drawable_height
;
661 struct wined3d_context
*context
;
662 GLbitfield clear_mask
= 0;
665 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
666 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
667 * for the cleared parts, and the untouched parts.
669 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
670 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
671 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
672 * checking all this if the dest surface is in the drawable anyway. */
673 if (flags
& WINED3DCLEAR_TARGET
&& !is_full_clear(target
, draw_rect
, clear_rect
))
675 for (i
= 0; i
< rt_count
; ++i
)
677 if (rts
[i
]) surface_load_location(rts
[i
], SFLAG_INDRAWABLE
, NULL
);
681 context
= context_acquire(device
, target
);
684 context_release(context
);
685 WARN("Invalid context, skipping clear.\n");
689 if (!context_apply_clear_state(context
, device
, rt_count
, rts
, depth_stencil
))
691 context_release(context
);
692 WARN("Failed to apply clear state, skipping clear.\n");
696 target
->get_drawable_size(context
, &drawable_width
, &drawable_height
);
700 /* Only set the values up once, as they are not changing. */
701 if (flags
& WINED3DCLEAR_STENCIL
)
703 if (context
->gl_info
->supported
[EXT_STENCIL_TWO_SIDE
])
705 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
706 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE
));
709 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_STENCILWRITEMASK
));
710 glClearStencil(stencil
);
711 checkGLcall("glClearStencil");
712 clear_mask
= clear_mask
| GL_STENCIL_BUFFER_BIT
;
715 if (flags
& WINED3DCLEAR_ZBUFFER
)
717 DWORD location
= context
->render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
719 if (location
== SFLAG_DS_ONSCREEN
&& depth_stencil
!= device
->onscreen_depth_stencil
)
722 device_switch_onscreen_ds(device
, context
, depth_stencil
);
725 prepare_ds_clear(depth_stencil
, context
, location
, draw_rect
, rect_count
, clear_rect
);
726 surface_modify_location(depth_stencil
, SFLAG_INDRAWABLE
, TRUE
);
728 glDepthMask(GL_TRUE
);
729 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_ZWRITEENABLE
));
731 checkGLcall("glClearDepth");
732 clear_mask
= clear_mask
| GL_DEPTH_BUFFER_BIT
;
735 if (flags
& WINED3DCLEAR_TARGET
)
737 for (i
= 0; i
< rt_count
; ++i
)
739 if (rts
[i
]) surface_modify_location(rts
[i
], SFLAG_INDRAWABLE
, TRUE
);
742 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
743 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE
));
744 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1
));
745 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2
));
746 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3
));
747 glClearColor(color
->r
, color
->g
, color
->b
, color
->a
);
748 checkGLcall("glClearColor");
749 clear_mask
= clear_mask
| GL_COLOR_BUFFER_BIT
;
754 if (context
->render_offscreen
)
756 glScissor(draw_rect
->left
, draw_rect
->top
,
757 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
761 glScissor(draw_rect
->left
, drawable_height
- draw_rect
->bottom
,
762 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
764 checkGLcall("glScissor");
766 checkGLcall("glClear");
772 /* Now process each rect in turn. */
773 for (i
= 0; i
< rect_count
; ++i
)
775 /* Note that GL uses lower left, width/height. */
776 IntersectRect(¤t_rect
, draw_rect
, &clear_rect
[i
]);
778 TRACE("clear_rect[%u] %s, current_rect %s.\n", i
,
779 wine_dbgstr_rect(&clear_rect
[i
]),
780 wine_dbgstr_rect(¤t_rect
));
782 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
783 * The rectangle is not cleared, no error is returned, but further rectanlges are
784 * still cleared if they are valid. */
785 if (current_rect
.left
> current_rect
.right
|| current_rect
.top
> current_rect
.bottom
)
787 TRACE("Rectangle with negative dimensions, ignoring.\n");
791 if (context
->render_offscreen
)
793 glScissor(current_rect
.left
, current_rect
.top
,
794 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
798 glScissor(current_rect
.left
, drawable_height
- current_rect
.bottom
,
799 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
801 checkGLcall("glScissor");
804 checkGLcall("glClear");
810 if (wined3d_settings
.strict_draw_ordering
|| (target
->container
.type
== WINED3D_CONTAINER_SWAPCHAIN
811 && target
->container
.u
.swapchain
->front_buffer
== target
))
812 wglFlush(); /* Flush to ensure ordering across contexts. */
814 context_release(context
);
820 /**********************************************************
821 * IUnknown parts follows
822 **********************************************************/
824 static HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
, REFIID riid
, void **object
)
826 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
828 if (IsEqualGUID(riid
, &IID_IWineD3DDevice
)
829 || IsEqualGUID(riid
, &IID_IUnknown
))
831 IUnknown_AddRef(iface
);
836 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
839 return E_NOINTERFACE
;
842 static ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
843 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
844 ULONG refCount
= InterlockedIncrement(&This
->ref
);
846 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
850 static ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
851 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
852 ULONG refCount
= InterlockedDecrement(&This
->ref
);
854 TRACE("(%p) : Releasing from %d\n", This
, refCount
+ 1);
859 for (i
= 0; i
< sizeof(This
->multistate_funcs
)/sizeof(This
->multistate_funcs
[0]); ++i
) {
860 HeapFree(GetProcessHeap(), 0, This
->multistate_funcs
[i
]);
861 This
->multistate_funcs
[i
] = NULL
;
864 /* TODO: Clean up all the surfaces and textures! */
865 /* NOTE: You must release the parent if the object was created via a callback
866 ** ***************************/
868 if (!list_empty(&This
->resources
))
870 struct wined3d_resource
*resource
;
871 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This
);
873 LIST_FOR_EACH_ENTRY(resource
, &This
->resources
, struct wined3d_resource
, resource_list_entry
)
875 FIXME("Leftover resource %p with type %s (%#x).\n",
876 resource
, debug_d3dresourcetype(resource
->resourceType
), resource
->resourceType
);
880 if(This
->contexts
) ERR("Context array not freed!\n");
881 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
882 This
->haveHardwareCursor
= FALSE
;
884 wined3d_decref(This
->wined3d
);
885 This
->wined3d
= NULL
;
886 HeapFree(GetProcessHeap(), 0, This
);
887 TRACE("Freed device %p\n", This
);
893 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice
*iface
, struct wined3d_buffer_desc
*desc
,
894 const void *data
, void *parent
, const struct wined3d_parent_ops
*parent_ops
, IWineD3DBuffer
**buffer
)
896 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
897 struct wined3d_buffer
*object
;
900 TRACE("iface %p, desc %p, data %p, parent %p, buffer %p\n", iface
, desc
, data
, parent
, buffer
);
902 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
905 ERR("Failed to allocate memory\n");
906 return E_OUTOFMEMORY
;
909 FIXME("Ignoring access flags (pool)\n");
911 hr
= buffer_init(object
, This
, desc
->byte_width
, desc
->usage
, WINED3DFMT_UNKNOWN
,
912 WINED3DPOOL_MANAGED
, GL_ARRAY_BUFFER_ARB
, data
, parent
, parent_ops
);
915 WARN("Failed to initialize buffer, hr %#x.\n", hr
);
916 HeapFree(GetProcessHeap(), 0, object
);
919 object
->desc
= *desc
;
921 TRACE("Created buffer %p.\n", object
);
923 *buffer
= (IWineD3DBuffer
*)object
;
928 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
,
929 UINT Size
, DWORD Usage
, WINED3DPOOL Pool
, void *parent
,
930 const struct wined3d_parent_ops
*parent_ops
, IWineD3DBuffer
**ppVertexBuffer
)
932 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
933 struct wined3d_buffer
*object
;
936 TRACE("iface %p, size %u, usage %#x, pool %#x, buffer %p, parent %p, parent_ops %p.\n",
937 iface
, Size
, Usage
, Pool
, ppVertexBuffer
, parent
, parent_ops
);
939 if (Pool
== WINED3DPOOL_SCRATCH
)
941 /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
942 * anyway, SCRATCH vertex buffers aren't usable anywhere
944 WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n");
945 *ppVertexBuffer
= NULL
;
946 return WINED3DERR_INVALIDCALL
;
949 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
952 ERR("Out of memory\n");
953 *ppVertexBuffer
= NULL
;
954 return WINED3DERR_OUTOFVIDEOMEMORY
;
957 hr
= buffer_init(object
, This
, Size
, Usage
, WINED3DFMT_VERTEXDATA
,
958 Pool
, GL_ARRAY_BUFFER_ARB
, NULL
, parent
, parent_ops
);
961 WARN("Failed to initialize buffer, hr %#x.\n", hr
);
962 HeapFree(GetProcessHeap(), 0, object
);
966 TRACE("Created buffer %p.\n", object
);
967 *ppVertexBuffer
= (IWineD3DBuffer
*)object
;
972 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
,
973 UINT Length
, DWORD Usage
, WINED3DPOOL Pool
, void *parent
,
974 const struct wined3d_parent_ops
*parent_ops
, IWineD3DBuffer
**ppIndexBuffer
)
976 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
977 struct wined3d_buffer
*object
;
980 TRACE("(%p) Creating index buffer\n", This
);
982 /* Allocate the storage for the device */
983 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
986 ERR("Out of memory\n");
987 *ppIndexBuffer
= NULL
;
988 return WINED3DERR_OUTOFVIDEOMEMORY
;
991 hr
= buffer_init(object
, This
, Length
, Usage
| WINED3DUSAGE_STATICDECL
,
992 WINED3DFMT_UNKNOWN
, Pool
, GL_ELEMENT_ARRAY_BUFFER_ARB
, NULL
,
996 WARN("Failed to initialize buffer, hr %#x\n", hr
);
997 HeapFree(GetProcessHeap(), 0, object
);
1001 TRACE("Created buffer %p.\n", object
);
1003 *ppIndexBuffer
= (IWineD3DBuffer
*) object
;
1008 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
*iface
,
1009 WINED3DSTATEBLOCKTYPE type
, struct wined3d_stateblock
**stateblock
)
1011 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1012 struct wined3d_stateblock
*object
;
1015 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1018 ERR("Failed to allocate stateblock memory.\n");
1019 return E_OUTOFMEMORY
;
1022 hr
= stateblock_init(object
, This
, type
);
1025 WARN("Failed to initialize stateblock, hr %#x.\n", hr
);
1026 HeapFree(GetProcessHeap(), 0, object
);
1030 TRACE("Created stateblock %p.\n", object
);
1031 *stateblock
= object
;
1036 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice
*iface
, UINT Width
, UINT Height
,
1037 enum wined3d_format_id Format
, BOOL Lockable
, BOOL Discard
, UINT Level
, DWORD Usage
, WINED3DPOOL Pool
,
1038 WINED3DMULTISAMPLE_TYPE MultiSample
, DWORD MultisampleQuality
, WINED3DSURFTYPE Impl
,
1039 void *parent
, const struct wined3d_parent_ops
*parent_ops
, IWineD3DSurface
**surface
)
1041 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1042 IWineD3DSurfaceImpl
*object
;
1045 TRACE("iface %p, width %u, height %u, format %s (%#x), lockable %#x, discard %#x, level %u\n",
1046 iface
, Width
, Height
, debug_d3dformat(Format
), Format
, Lockable
, Discard
, Level
);
1047 TRACE("surface %p, usage %s (%#x), pool %s (%#x), multisample_type %#x, multisample_quality %u\n",
1048 surface
, debug_d3dusage(Usage
), Usage
, debug_d3dpool(Pool
), Pool
, MultiSample
, MultisampleQuality
);
1049 TRACE("surface_type %#x, parent %p, parent_ops %p.\n", Impl
, parent
, parent_ops
);
1051 if (Impl
== SURFACE_OPENGL
&& !This
->adapter
)
1053 ERR("OpenGL surfaces are not available without OpenGL.\n");
1054 return WINED3DERR_NOTAVAILABLE
;
1057 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1060 ERR("Failed to allocate surface memory.\n");
1061 return WINED3DERR_OUTOFVIDEOMEMORY
;
1064 hr
= surface_init(object
, Impl
, This
->surface_alignment
, Width
, Height
, Level
, Lockable
,
1065 Discard
, MultiSample
, MultisampleQuality
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1068 WARN("Failed to initialize surface, returning %#x.\n", hr
);
1069 HeapFree(GetProcessHeap(), 0, object
);
1073 TRACE("(%p) : Created surface %p\n", This
, object
);
1075 *surface
= (IWineD3DSurface
*)object
;
1080 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice
*iface
,
1081 struct wined3d_resource
*resource
, void *parent
, IWineD3DRendertargetView
**rendertarget_view
)
1083 struct wined3d_rendertarget_view
*object
;
1085 TRACE("iface %p, resource %p, parent %p, rendertarget_view %p.\n",
1086 iface
, resource
, parent
, rendertarget_view
);
1088 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1091 ERR("Failed to allocate memory\n");
1092 return E_OUTOFMEMORY
;
1095 wined3d_rendertarget_view_init(object
, resource
, parent
);
1097 TRACE("Created render target view %p.\n", object
);
1098 *rendertarget_view
= (IWineD3DRendertargetView
*)object
;
1103 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
,
1104 UINT Width
, UINT Height
, UINT Levels
, DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
,
1105 void *parent
, const struct wined3d_parent_ops
*parent_ops
, IWineD3DTexture
**ppTexture
)
1107 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1108 IWineD3DTextureImpl
*object
;
1111 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This
, Width
, Height
, Levels
, Usage
);
1112 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, parent %p\n",
1113 Format
, debug_d3dformat(Format
), Pool
, ppTexture
, parent
);
1115 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1118 ERR("Out of memory\n");
1120 return WINED3DERR_OUTOFVIDEOMEMORY
;
1123 hr
= texture_init(object
, Width
, Height
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1126 WARN("Failed to initialize texture, returning %#x\n", hr
);
1127 HeapFree(GetProcessHeap(), 0, object
);
1132 *ppTexture
= (IWineD3DTexture
*)object
;
1134 TRACE("(%p) : Created texture %p\n", This
, object
);
1139 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
1140 UINT Width
, UINT Height
, UINT Depth
, UINT Levels
, DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
,
1141 void *parent
, const struct wined3d_parent_ops
*parent_ops
, IWineD3DVolumeTexture
**ppVolumeTexture
)
1143 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1144 IWineD3DVolumeTextureImpl
*object
;
1147 TRACE("(%p) : W(%u) H(%u) D(%u), Lvl(%u) Usage(%#x), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1148 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1150 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1153 ERR("Out of memory\n");
1154 *ppVolumeTexture
= NULL
;
1155 return WINED3DERR_OUTOFVIDEOMEMORY
;
1158 hr
= volumetexture_init(object
, Width
, Height
, Depth
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1161 WARN("Failed to initialize volumetexture, returning %#x\n", hr
);
1162 HeapFree(GetProcessHeap(), 0, object
);
1163 *ppVolumeTexture
= NULL
;
1167 TRACE("(%p) : Created volume texture %p.\n", This
, object
);
1168 *ppVolumeTexture
= (IWineD3DVolumeTexture
*)object
;
1173 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
, UINT Width
, UINT Height
,
1174 UINT Depth
, DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
, void *parent
,
1175 const struct wined3d_parent_ops
*parent_ops
, IWineD3DVolume
**ppVolume
)
1177 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1178 IWineD3DVolumeImpl
*object
;
1181 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1182 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1184 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1187 ERR("Out of memory\n");
1189 return WINED3DERR_OUTOFVIDEOMEMORY
;
1192 hr
= volume_init(object
, This
, Width
, Height
, Depth
, Usage
, Format
, Pool
, parent
, parent_ops
);
1195 WARN("Failed to initialize volume, returning %#x.\n", hr
);
1196 HeapFree(GetProcessHeap(), 0, object
);
1200 TRACE("(%p) : Created volume %p.\n", This
, object
);
1201 *ppVolume
= (IWineD3DVolume
*)object
;
1206 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
, UINT EdgeLength
, UINT Levels
,
1207 DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
, void *parent
,
1208 const struct wined3d_parent_ops
*parent_ops
, IWineD3DCubeTexture
**ppCubeTexture
)
1210 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1211 IWineD3DCubeTextureImpl
*object
; /** NOTE: impl ref allowed since this is a create function **/
1214 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1217 ERR("Out of memory\n");
1218 *ppCubeTexture
= NULL
;
1219 return WINED3DERR_OUTOFVIDEOMEMORY
;
1222 hr
= cubetexture_init(object
, EdgeLength
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1225 WARN("Failed to initialize cubetexture, returning %#x\n", hr
);
1226 HeapFree(GetProcessHeap(), 0, object
);
1227 *ppCubeTexture
= NULL
;
1231 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
1232 *ppCubeTexture
= (IWineD3DCubeTexture
*)object
;
1237 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
,
1238 WINED3DQUERYTYPE type
, struct wined3d_query
**query
)
1240 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1241 struct wined3d_query
*object
;
1244 TRACE("iface %p, type %#x, query %p.\n", iface
, type
, query
);
1246 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1249 ERR("Failed to allocate query memory.\n");
1250 return E_OUTOFMEMORY
;
1253 hr
= query_init(object
, This
, type
);
1256 WARN("Failed to initialize query, hr %#x.\n", hr
);
1257 HeapFree(GetProcessHeap(), 0, object
);
1261 TRACE("Created query %p.\n", object
);
1267 /* Do not call while under the GL lock. */
1268 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice
*iface
,
1269 WINED3DPRESENT_PARAMETERS
*present_parameters
, WINED3DSURFTYPE surface_type
,
1270 void *parent
, IWineD3DSwapChain
**swapchain
)
1272 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1273 IWineD3DSwapChainImpl
*object
;
1276 TRACE("iface %p, present_parameters %p, swapchain %p, parent %p, surface_type %#x.\n",
1277 iface
, present_parameters
, swapchain
, parent
, surface_type
);
1279 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1282 ERR("Failed to allocate swapchain memory.\n");
1283 return E_OUTOFMEMORY
;
1286 hr
= swapchain_init(object
, surface_type
, This
, present_parameters
, parent
);
1289 WARN("Failed to initialize swapchain, hr %#x.\n", hr
);
1290 HeapFree(GetProcessHeap(), 0, object
);
1294 TRACE("Created swapchain %p.\n", object
);
1295 *swapchain
= (IWineD3DSwapChain
*)object
;
1300 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1301 static UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
) {
1302 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1303 TRACE("(%p)\n", This
);
1305 return This
->NumberOfSwapChains
;
1308 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
, UINT iSwapChain
, IWineD3DSwapChain
**pSwapChain
) {
1309 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1310 TRACE("(%p) : swapchain %d\n", This
, iSwapChain
);
1312 if (iSwapChain
< This
->NumberOfSwapChains
)
1314 *pSwapChain
= (IWineD3DSwapChain
*)This
->swapchains
[iSwapChain
];
1315 IWineD3DSwapChain_AddRef(*pSwapChain
);
1316 TRACE("(%p) returning %p\n", This
, *pSwapChain
);
1319 TRACE("Swapchain out of range\n");
1321 return WINED3DERR_INVALIDCALL
;
1325 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
*iface
,
1326 const WINED3DVERTEXELEMENT
*elements
, UINT element_count
, void *parent
,
1327 const struct wined3d_parent_ops
*parent_ops
, struct wined3d_vertex_declaration
**declaration
)
1329 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1330 struct wined3d_vertex_declaration
*object
;
1333 TRACE("iface %p, elements %p, element_count %u, parent %p, parent_ops %p, declaration %p.\n",
1334 iface
, elements
, element_count
, parent
, parent_ops
, declaration
);
1336 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1339 ERR("Failed to allocate vertex declaration memory.\n");
1340 return E_OUTOFMEMORY
;
1343 hr
= vertexdeclaration_init(object
, This
, elements
, element_count
, parent
, parent_ops
);
1346 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr
);
1347 HeapFree(GetProcessHeap(), 0, object
);
1351 TRACE("Created vertex declaration %p.\n", object
);
1352 *declaration
= object
;
1357 struct wined3d_fvf_convert_state
1359 const struct wined3d_gl_info
*gl_info
;
1360 WINED3DVERTEXELEMENT
*elements
;
1365 static void append_decl_element(struct wined3d_fvf_convert_state
*state
,
1366 enum wined3d_format_id format_id
, WINED3DDECLUSAGE usage
, UINT usage_idx
)
1368 WINED3DVERTEXELEMENT
*elements
= state
->elements
;
1369 const struct wined3d_format
*format
;
1370 UINT offset
= state
->offset
;
1371 UINT idx
= state
->idx
;
1373 elements
[idx
].format
= format_id
;
1374 elements
[idx
].input_slot
= 0;
1375 elements
[idx
].offset
= offset
;
1376 elements
[idx
].output_slot
= 0;
1377 elements
[idx
].method
= WINED3DDECLMETHOD_DEFAULT
;
1378 elements
[idx
].usage
= usage
;
1379 elements
[idx
].usage_idx
= usage_idx
;
1381 format
= wined3d_get_format(state
->gl_info
, format_id
);
1382 state
->offset
+= format
->component_count
* format
->component_size
;
1386 static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl
*This
, /* For the GL info, which has the type table */
1387 DWORD fvf
, WINED3DVERTEXELEMENT
**ppVertexElements
)
1389 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1390 BOOL has_pos
= !!(fvf
& WINED3DFVF_POSITION_MASK
);
1391 BOOL has_blend
= (fvf
& WINED3DFVF_XYZB5
) > WINED3DFVF_XYZRHW
;
1392 BOOL has_blend_idx
= has_blend
&&
1393 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB5
) ||
1394 (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
) ||
1395 (fvf
& WINED3DFVF_LASTBETA_UBYTE4
));
1396 BOOL has_normal
= !!(fvf
& WINED3DFVF_NORMAL
);
1397 BOOL has_psize
= !!(fvf
& WINED3DFVF_PSIZE
);
1398 BOOL has_diffuse
= !!(fvf
& WINED3DFVF_DIFFUSE
);
1399 BOOL has_specular
= !!(fvf
& WINED3DFVF_SPECULAR
);
1401 DWORD num_textures
= (fvf
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
1402 DWORD texcoords
= (fvf
& 0xFFFF0000) >> 16;
1403 struct wined3d_fvf_convert_state state
;
1406 DWORD num_blends
= 1 + (((fvf
& WINED3DFVF_XYZB5
) - WINED3DFVF_XYZB1
) >> 1);
1407 if (has_blend_idx
) num_blends
--;
1409 /* Compute declaration size */
1410 size
= has_pos
+ (has_blend
&& num_blends
> 0) + has_blend_idx
+ has_normal
+
1411 has_psize
+ has_diffuse
+ has_specular
+ num_textures
;
1413 state
.gl_info
= gl_info
;
1414 state
.elements
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(*state
.elements
));
1415 if (!state
.elements
) return ~0U;
1421 if (!has_blend
&& (fvf
& WINED3DFVF_XYZRHW
))
1422 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_POSITIONT
, 0);
1423 else if ((fvf
& WINED3DFVF_XYZW
) == WINED3DFVF_XYZW
)
1424 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_POSITION
, 0);
1426 append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_POSITION
, 0);
1429 if (has_blend
&& (num_blends
> 0))
1431 if ((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
&& (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
))
1432 append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1438 append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1441 append_decl_element(&state
, WINED3DFMT_R32G32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1444 append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1447 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1450 ERR("Unexpected amount of blend values: %u\n", num_blends
);
1457 if ((fvf
& WINED3DFVF_LASTBETA_UBYTE4
)
1458 || ((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
&& (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)))
1459 append_decl_element(&state
, WINED3DFMT_R8G8B8A8_UINT
, WINED3DDECLUSAGE_BLENDINDICES
, 0);
1460 else if (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)
1461 append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_BLENDINDICES
, 0);
1463 append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_BLENDINDICES
, 0);
1466 if (has_normal
) append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_NORMAL
, 0);
1467 if (has_psize
) append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_PSIZE
, 0);
1468 if (has_diffuse
) append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_COLOR
, 0);
1469 if (has_specular
) append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_COLOR
, 1);
1471 for (idx
= 0; idx
< num_textures
; ++idx
)
1473 switch ((texcoords
>> (idx
* 2)) & 0x03)
1475 case WINED3DFVF_TEXTUREFORMAT1
:
1476 append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1478 case WINED3DFVF_TEXTUREFORMAT2
:
1479 append_decl_element(&state
, WINED3DFMT_R32G32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1481 case WINED3DFVF_TEXTUREFORMAT3
:
1482 append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1484 case WINED3DFVF_TEXTUREFORMAT4
:
1485 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1490 *ppVertexElements
= state
.elements
;
1494 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice
*iface
,
1495 DWORD fvf
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1496 struct wined3d_vertex_declaration
**declaration
)
1498 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1499 WINED3DVERTEXELEMENT
*elements
;
1503 TRACE("iface %p, fvf %#x, parent %p, parent_ops %p, declaration %p.\n",
1504 iface
, fvf
, parent
, parent_ops
, declaration
);
1506 size
= ConvertFvfToDeclaration(This
, fvf
, &elements
);
1507 if (size
== ~0U) return E_OUTOFMEMORY
;
1509 hr
= IWineD3DDeviceImpl_CreateVertexDeclaration(iface
, elements
, size
, parent
, parent_ops
, declaration
);
1510 HeapFree(GetProcessHeap(), 0, elements
);
1514 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
*iface
,
1515 const DWORD
*pFunction
, const struct wined3d_shader_signature
*output_signature
,
1516 void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1517 IWineD3DVertexShader
**ppVertexShader
)
1519 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1520 IWineD3DVertexShaderImpl
*object
;
1523 if (This
->vs_selected_mode
== SHADER_NONE
)
1524 return WINED3DERR_INVALIDCALL
;
1526 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1529 ERR("Failed to allocate shader memory.\n");
1530 return E_OUTOFMEMORY
;
1533 hr
= vertexshader_init(object
, This
, pFunction
, output_signature
, parent
, parent_ops
);
1536 WARN("Failed to initialize vertex shader, hr %#x.\n", hr
);
1537 HeapFree(GetProcessHeap(), 0, object
);
1541 TRACE("Created vertex shader %p.\n", object
);
1542 *ppVertexShader
= (IWineD3DVertexShader
*)object
;
1547 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateGeometryShader(IWineD3DDevice
*iface
,
1548 const DWORD
*byte_code
, const struct wined3d_shader_signature
*output_signature
,
1549 void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1550 IWineD3DGeometryShader
**shader
)
1552 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1553 struct wined3d_geometryshader
*object
;
1556 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1559 ERR("Failed to allocate shader memory.\n");
1560 return E_OUTOFMEMORY
;
1563 hr
= geometryshader_init(object
, This
, byte_code
, output_signature
, parent
, parent_ops
);
1566 WARN("Failed to initialize geometry shader, hr %#x.\n", hr
);
1567 HeapFree(GetProcessHeap(), 0, object
);
1571 TRACE("Created geometry shader %p.\n", object
);
1572 *shader
= (IWineD3DGeometryShader
*)object
;
1577 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
*iface
,
1578 const DWORD
*pFunction
, const struct wined3d_shader_signature
*output_signature
,
1579 void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1580 IWineD3DPixelShader
**ppPixelShader
)
1582 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1583 IWineD3DPixelShaderImpl
*object
;
1586 if (This
->ps_selected_mode
== SHADER_NONE
)
1587 return WINED3DERR_INVALIDCALL
;
1589 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1592 ERR("Failed to allocate shader memory.\n");
1593 return E_OUTOFMEMORY
;
1596 hr
= pixelshader_init(object
, This
, pFunction
, output_signature
, parent
, parent_ops
);
1599 WARN("Failed to initialize pixel shader, hr %#x.\n", hr
);
1600 HeapFree(GetProcessHeap(), 0, object
);
1604 TRACE("Created pixel shader %p.\n", object
);
1605 *ppPixelShader
= (IWineD3DPixelShader
*)object
;
1610 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice
*iface
, DWORD flags
,
1611 const PALETTEENTRY
*entries
, void *parent
, struct wined3d_palette
**palette
)
1613 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1614 struct wined3d_palette
*object
;
1617 TRACE("iface %p, flags %#x, entries %p, palette %p, parent %p.\n",
1618 iface
, flags
, entries
, palette
, parent
);
1620 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1623 ERR("Failed to allocate palette memory.\n");
1624 return E_OUTOFMEMORY
;
1627 hr
= wined3d_palette_init(object
, This
, flags
, entries
, parent
);
1630 WARN("Failed to initialize palette, hr %#x.\n", hr
);
1631 HeapFree(GetProcessHeap(), 0, object
);
1635 TRACE("Created palette %p.\n", object
);
1641 static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl
*This
, const char *filename
) {
1645 HDC dcb
= NULL
, dcs
= NULL
;
1646 WINEDDCOLORKEY colorkey
;
1648 hbm
= LoadImageA(NULL
, filename
, IMAGE_BITMAP
, 0, 0, LR_LOADFROMFILE
| LR_CREATEDIBSECTION
);
1651 GetObjectA(hbm
, sizeof(BITMAP
), &bm
);
1652 dcb
= CreateCompatibleDC(NULL
);
1654 SelectObject(dcb
, hbm
);
1658 /* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
1659 * couldn't be loaded
1661 memset(&bm
, 0, sizeof(bm
));
1666 hr
= IWineD3DDevice_CreateSurface((IWineD3DDevice
*)This
, bm
.bmWidth
, bm
.bmHeight
, WINED3DFMT_B5G6R5_UNORM
, TRUE
,
1667 FALSE
, 0, 0, WINED3DPOOL_DEFAULT
, WINED3DMULTISAMPLE_NONE
, 0, SURFACE_OPENGL
, NULL
,
1668 &wined3d_null_parent_ops
, &This
->logo_surface
);
1671 ERR("Wine logo requested, but failed to create surface, hr %#x.\n", hr
);
1676 hr
= IWineD3DSurface_GetDC(This
->logo_surface
, &dcs
);
1677 if(FAILED(hr
)) goto out
;
1678 BitBlt(dcs
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, dcb
, 0, 0, SRCCOPY
);
1679 IWineD3DSurface_ReleaseDC(This
->logo_surface
, dcs
);
1681 colorkey
.dwColorSpaceLowValue
= 0;
1682 colorkey
.dwColorSpaceHighValue
= 0;
1683 IWineD3DSurface_SetColorKey(This
->logo_surface
, WINEDDCKEY_SRCBLT
, &colorkey
);
1687 const WINED3DCOLORVALUE c
= {1.0f
, 1.0f
, 1.0f
, 1.0f
};
1688 /* Fill the surface with a white color to show that wined3d is there */
1689 IWineD3DDevice_ColorFill((IWineD3DDevice
*)This
, This
->logo_surface
, NULL
, &c
);
1693 if (dcb
) DeleteDC(dcb
);
1694 if (hbm
) DeleteObject(hbm
);
1697 /* Context activation is done by the caller. */
1698 static void create_dummy_textures(IWineD3DDeviceImpl
*This
)
1700 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1702 /* Under DirectX you can have texture stage operations even if no texture is
1703 bound, whereas opengl will only do texture operations when a valid texture is
1704 bound. We emulate this by creating dummy textures and binding them to each
1705 texture stage, but disable all stages by default. Hence if a stage is enabled
1706 then the default texture will kick in until replaced by a SetTexture call */
1709 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
1711 /* The dummy texture does not have client storage backing */
1712 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
1713 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
1716 for (i
= 0; i
< gl_info
->limits
.textures
; ++i
)
1718 GLubyte white
= 255;
1720 /* Make appropriate texture active */
1721 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
1722 checkGLcall("glActiveTextureARB");
1724 /* Generate an opengl texture name */
1725 glGenTextures(1, &This
->dummyTextureName
[i
]);
1726 checkGLcall("glGenTextures");
1727 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
1729 /* Generate a dummy 2d texture (not using 1d because they cause many
1730 * DRI drivers fall back to sw) */
1731 glBindTexture(GL_TEXTURE_2D
, This
->dummyTextureName
[i
]);
1732 checkGLcall("glBindTexture");
1734 glTexImage2D(GL_TEXTURE_2D
, 0, GL_LUMINANCE
, 1, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
1735 checkGLcall("glTexImage2D");
1738 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
1740 /* Reenable because if supported it is enabled by default */
1741 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
1742 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
1748 /* Context activation is done by the caller. */
1749 static void destroy_dummy_textures(IWineD3DDeviceImpl
*device
, const struct wined3d_gl_info
*gl_info
)
1752 glDeleteTextures(gl_info
->limits
.textures
, device
->dummyTextureName
);
1753 checkGLcall("glDeleteTextures(gl_info->limits.textures, device->dummyTextureName)");
1756 memset(device
->dummyTextureName
, 0, gl_info
->limits
.textures
* sizeof(*device
->dummyTextureName
));
1759 static LONG
fullscreen_style(LONG style
)
1761 /* Make sure the window is managed, otherwise we won't get keyboard input. */
1762 style
|= WS_POPUP
| WS_SYSMENU
;
1763 style
&= ~(WS_CAPTION
| WS_THICKFRAME
);
1768 static LONG
fullscreen_exstyle(LONG exstyle
)
1770 /* Filter out window decorations. */
1771 exstyle
&= ~(WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
);
1776 static void WINAPI
IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice
*iface
, HWND window
, UINT w
, UINT h
)
1778 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1779 BOOL filter_messages
;
1780 LONG style
, exstyle
;
1782 TRACE("Setting up window %p for fullscreen mode.\n", window
);
1784 if (device
->style
|| device
->exStyle
)
1786 ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n",
1787 window
, device
->style
, device
->exStyle
);
1790 device
->style
= GetWindowLongW(window
, GWL_STYLE
);
1791 device
->exStyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1793 style
= fullscreen_style(device
->style
);
1794 exstyle
= fullscreen_exstyle(device
->exStyle
);
1796 TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n",
1797 device
->style
, device
->exStyle
, style
, exstyle
);
1799 filter_messages
= device
->filter_messages
;
1800 device
->filter_messages
= TRUE
;
1802 SetWindowLongW(window
, GWL_STYLE
, style
);
1803 SetWindowLongW(window
, GWL_EXSTYLE
, exstyle
);
1804 SetWindowPos(window
, HWND_TOP
, 0, 0, w
, h
, SWP_FRAMECHANGED
| SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
1806 device
->filter_messages
= filter_messages
;
1809 static void WINAPI
IWineD3DDeviceImpl_RestoreFullscreenWindow(IWineD3DDevice
*iface
, HWND window
)
1811 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1812 BOOL filter_messages
;
1813 LONG style
, exstyle
;
1815 if (!device
->style
&& !device
->exStyle
) return;
1817 TRACE("Restoring window style of window %p to %08x, %08x.\n",
1818 window
, device
->style
, device
->exStyle
);
1820 style
= GetWindowLongW(window
, GWL_STYLE
);
1821 exstyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1823 filter_messages
= device
->filter_messages
;
1824 device
->filter_messages
= TRUE
;
1826 /* Only restore the style if the application didn't modify it during the
1827 * fullscreen phase. Some applications change it before calling Reset()
1828 * when switching between windowed and fullscreen modes (HL2), some
1829 * depend on the original style (Eve Online). */
1830 if (style
== fullscreen_style(device
->style
) && exstyle
== fullscreen_exstyle(device
->exStyle
))
1832 SetWindowLongW(window
, GWL_STYLE
, device
->style
);
1833 SetWindowLongW(window
, GWL_EXSTYLE
, device
->exStyle
);
1835 SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1837 device
->filter_messages
= filter_messages
;
1839 /* Delete the old values. */
1841 device
->exStyle
= 0;
1844 static HRESULT WINAPI
IWineD3DDeviceImpl_AcquireFocusWindow(IWineD3DDevice
*iface
, HWND window
)
1846 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1848 TRACE("iface %p, window %p.\n", iface
, window
);
1850 if (!wined3d_register_window(window
, device
))
1852 ERR("Failed to register window %p.\n", window
);
1856 device
->focus_window
= window
;
1857 SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1862 static void WINAPI
IWineD3DDeviceImpl_ReleaseFocusWindow(IWineD3DDevice
*iface
)
1864 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1866 TRACE("iface %p.\n", iface
);
1868 if (device
->focus_window
) wined3d_unregister_window(device
->focus_window
);
1869 device
->focus_window
= NULL
;
1872 static HRESULT WINAPI
IWineD3DDeviceImpl_Init3D(IWineD3DDevice
*iface
,
1873 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
1875 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1876 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1877 IWineD3DSwapChainImpl
*swapchain
= NULL
;
1878 struct wined3d_context
*context
;
1883 TRACE("(%p)->(%p)\n", This
, pPresentationParameters
);
1885 if(This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
1886 if(!This
->adapter
->opengl
) return WINED3DERR_INVALIDCALL
;
1888 TRACE("(%p) : Creating stateblock\n", This
);
1889 hr
= IWineD3DDevice_CreateStateBlock(iface
, WINED3DSBT_INIT
, &This
->stateBlock
);
1892 WARN("Failed to create stateblock\n");
1895 TRACE("(%p) : Created stateblock (%p)\n", This
, This
->stateBlock
);
1896 This
->updateStateBlock
= This
->stateBlock
;
1897 wined3d_stateblock_incref(This
->updateStateBlock
);
1899 This
->render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1900 sizeof(*This
->render_targets
) * gl_info
->limits
.buffers
);
1902 This
->NumberOfPalettes
= 1;
1903 This
->palettes
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PALETTEENTRY
*));
1904 if (!This
->palettes
|| !This
->render_targets
)
1906 ERR("Out of memory!\n");
1910 This
->palettes
[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
1911 if(!This
->palettes
[0]) {
1912 ERR("Out of memory!\n");
1916 for (i
= 0; i
< 256; ++i
) {
1917 This
->palettes
[0][i
].peRed
= 0xFF;
1918 This
->palettes
[0][i
].peGreen
= 0xFF;
1919 This
->palettes
[0][i
].peBlue
= 0xFF;
1920 This
->palettes
[0][i
].peFlags
= 0xFF;
1922 This
->currentPalette
= 0;
1924 /* Initialize the texture unit mapping to a 1:1 mapping */
1925 for (state
= 0; state
< MAX_COMBINED_SAMPLERS
; ++state
)
1927 if (state
< gl_info
->limits
.fragment_samplers
)
1929 This
->texUnitMap
[state
] = state
;
1930 This
->rev_tex_unit_map
[state
] = state
;
1932 This
->texUnitMap
[state
] = WINED3D_UNMAPPED_STAGE
;
1933 This
->rev_tex_unit_map
[state
] = WINED3D_UNMAPPED_STAGE
;
1937 /* Setup the implicit swapchain. This also initializes a context. */
1938 TRACE("Creating implicit swapchain\n");
1939 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
1940 pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
);
1943 WARN("Failed to create implicit swapchain\n");
1947 This
->NumberOfSwapChains
= 1;
1948 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(*This
->swapchains
));
1949 if (!This
->swapchains
)
1951 ERR("Out of memory!\n");
1954 This
->swapchains
[0] = swapchain
;
1956 if (swapchain
->back_buffers
&& swapchain
->back_buffers
[0])
1958 TRACE("Setting rendertarget to %p.\n", swapchain
->back_buffers
);
1959 This
->render_targets
[0] = swapchain
->back_buffers
[0];
1963 TRACE("Setting rendertarget to %p.\n", swapchain
->front_buffer
);
1964 This
->render_targets
[0] = swapchain
->front_buffer
;
1966 IWineD3DSurface_AddRef((IWineD3DSurface
*)This
->render_targets
[0]);
1968 /* Depth Stencil support */
1969 This
->depth_stencil
= This
->auto_depth_stencil
;
1970 if (This
->depth_stencil
)
1971 IWineD3DSurface_AddRef((IWineD3DSurface
*)This
->depth_stencil
);
1973 hr
= This
->shader_backend
->shader_alloc_private(This
);
1975 TRACE("Shader private data couldn't be allocated\n");
1978 hr
= This
->frag_pipe
->alloc_private(This
);
1980 TRACE("Fragment pipeline private data couldn't be allocated\n");
1983 hr
= This
->blitter
->alloc_private(This
);
1985 TRACE("Blitter private data couldn't be allocated\n");
1989 /* Set up some starting GL setup */
1991 /* Setup all the devices defaults */
1992 stateblock_init_default_state(This
->stateBlock
);
1994 context
= context_acquire(This
, swapchain
->front_buffer
);
1996 create_dummy_textures(This
);
2000 /* Initialize the current view state */
2001 This
->view_ident
= 1;
2002 This
->contexts
[0]->last_was_rhw
= 0;
2003 glGetIntegerv(GL_MAX_LIGHTS
, &This
->maxConcurrentLights
);
2004 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
2006 switch(wined3d_settings
.offscreen_rendering_mode
) {
2008 This
->offscreenBuffer
= GL_COLOR_ATTACHMENT0
;
2011 case ORM_BACKBUFFER
:
2013 if (context_get_current()->aux_buffers
> 0)
2015 TRACE("Using auxilliary buffer for offscreen rendering\n");
2016 This
->offscreenBuffer
= GL_AUX0
;
2018 TRACE("Using back buffer for offscreen rendering\n");
2019 This
->offscreenBuffer
= GL_BACK
;
2024 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This
, This
);
2027 context_release(context
);
2029 /* Clear the screen */
2030 IWineD3DDevice_Clear((IWineD3DDevice
*) This
, 0, NULL
,
2031 WINED3DCLEAR_TARGET
| pPresentationParameters
->EnableAutoDepthStencil
? WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
: 0,
2034 This
->d3d_initialized
= TRUE
;
2036 if(wined3d_settings
.logo
) {
2037 IWineD3DDeviceImpl_LoadLogo(This
, wined3d_settings
.logo
);
2039 This
->highest_dirty_ps_const
= 0;
2040 This
->highest_dirty_vs_const
= 0;
2044 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2045 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2046 This
->NumberOfSwapChains
= 0;
2047 if(This
->palettes
) {
2048 HeapFree(GetProcessHeap(), 0, This
->palettes
[0]);
2049 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2051 This
->NumberOfPalettes
= 0;
2053 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) swapchain
);
2055 if (This
->stateBlock
)
2057 wined3d_stateblock_decref(This
->stateBlock
);
2058 This
->stateBlock
= NULL
;
2060 if (This
->blit_priv
) {
2061 This
->blitter
->free_private(This
);
2063 if (This
->fragment_priv
) {
2064 This
->frag_pipe
->free_private(This
);
2066 if (This
->shader_priv
) {
2067 This
->shader_backend
->shader_free_private(This
);
2072 static HRESULT WINAPI
IWineD3DDeviceImpl_InitGDI(IWineD3DDevice
*iface
,
2073 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
2075 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2076 IWineD3DSwapChainImpl
*swapchain
= NULL
;
2079 /* Setup the implicit swapchain */
2080 TRACE("Creating implicit swapchain\n");
2081 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
2082 pPresentationParameters
, (IWineD3DSwapChain
**)&swapchain
);
2085 WARN("Failed to create implicit swapchain\n");
2089 This
->NumberOfSwapChains
= 1;
2090 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->NumberOfSwapChains
* sizeof(*This
->swapchains
));
2091 if (!This
->swapchains
)
2093 ERR("Out of memory!\n");
2096 This
->swapchains
[0] = swapchain
;
2100 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
2104 static HRESULT WINAPI
device_unload_resource(struct wined3d_resource
*resource
, void *data
)
2106 TRACE("Unloading resource %p.\n", resource
);
2108 resource
->resource_ops
->resource_unload(resource
);
2113 static HRESULT WINAPI
IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice
*iface
,
2114 D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain
)
2116 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2117 const struct wined3d_gl_info
*gl_info
;
2118 struct IWineD3DSurfaceImpl
*surface
;
2119 struct wined3d_context
*context
;
2122 TRACE("(%p)\n", This
);
2124 if(!This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2126 /* I don't think that the interface guarantees that the device is destroyed from the same thread
2127 * it was created. Thus make sure a context is active for the glDelete* calls
2129 context
= context_acquire(This
, NULL
);
2130 gl_info
= context
->gl_info
;
2132 if(This
->logo_surface
) IWineD3DSurface_Release(This
->logo_surface
);
2134 /* Unload resources */
2135 IWineD3DDevice_EnumResources(iface
, device_unload_resource
, NULL
);
2137 TRACE("Deleting high order patches\n");
2138 for(i
= 0; i
< PATCHMAP_SIZE
; i
++) {
2139 struct list
*e1
, *e2
;
2140 struct WineD3DRectPatch
*patch
;
2141 LIST_FOR_EACH_SAFE(e1
, e2
, &This
->patches
[i
]) {
2142 patch
= LIST_ENTRY(e1
, struct WineD3DRectPatch
, entry
);
2143 IWineD3DDevice_DeletePatch(iface
, patch
->Handle
);
2147 /* Delete the mouse cursor texture */
2148 if(This
->cursorTexture
) {
2150 glDeleteTextures(1, &This
->cursorTexture
);
2152 This
->cursorTexture
= 0;
2155 for (sampler
= 0; sampler
< MAX_FRAGMENT_SAMPLERS
; ++sampler
) {
2156 IWineD3DDevice_SetTexture(iface
, sampler
, NULL
);
2158 for (sampler
= 0; sampler
< MAX_VERTEX_SAMPLERS
; ++sampler
) {
2159 IWineD3DDevice_SetTexture(iface
, WINED3DVERTEXTEXTURESAMPLER0
+ sampler
, NULL
);
2162 /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
2163 * private data, it might contain opengl pointers
2165 if(This
->depth_blt_texture
) {
2167 glDeleteTextures(1, &This
->depth_blt_texture
);
2169 This
->depth_blt_texture
= 0;
2171 if (This
->depth_blt_rb
) {
2173 gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &This
->depth_blt_rb
);
2175 This
->depth_blt_rb
= 0;
2176 This
->depth_blt_rb_w
= 0;
2177 This
->depth_blt_rb_h
= 0;
2180 /* Release the update stateblock */
2181 if (wined3d_stateblock_decref(This
->updateStateBlock
))
2183 if (This
->updateStateBlock
!= This
->stateBlock
)
2184 FIXME("Something's still holding the update stateblock.\n");
2186 This
->updateStateBlock
= NULL
;
2189 struct wined3d_stateblock
*stateblock
= This
->stateBlock
;
2190 This
->stateBlock
= NULL
;
2192 /* Release the stateblock */
2193 if (wined3d_stateblock_decref(stateblock
))
2194 FIXME("Something's still holding the stateblock.\n");
2197 /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
2198 This
->blitter
->free_private(This
);
2199 This
->frag_pipe
->free_private(This
);
2200 This
->shader_backend
->shader_free_private(This
);
2202 /* Release the buffers (with sanity checks)*/
2203 if (This
->onscreen_depth_stencil
)
2205 surface
= This
->onscreen_depth_stencil
;
2206 This
->onscreen_depth_stencil
= NULL
;
2207 IWineD3DSurface_Release((IWineD3DSurface
*)surface
);
2210 if (This
->depth_stencil
)
2212 surface
= This
->depth_stencil
;
2214 TRACE("Releasing depth/stencil buffer %p.\n", surface
);
2216 This
->depth_stencil
= NULL
;
2217 if (IWineD3DSurface_Release((IWineD3DSurface
*)surface
)
2218 && surface
!= This
->auto_depth_stencil
)
2220 ERR("Something is still holding a reference to depth/stencil buffer %p.\n", surface
);
2224 if (This
->auto_depth_stencil
)
2226 surface
= This
->auto_depth_stencil
;
2227 This
->auto_depth_stencil
= NULL
;
2228 if (IWineD3DSurface_Release((IWineD3DSurface
*)surface
))
2230 FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This
);
2234 for (i
= 1; i
< gl_info
->limits
.buffers
; ++i
)
2236 IWineD3DDevice_SetRenderTarget(iface
, i
, NULL
, FALSE
);
2239 surface
= This
->render_targets
[0];
2240 TRACE("Setting rendertarget 0 to NULL\n");
2241 This
->render_targets
[0] = NULL
;
2242 TRACE("Releasing the render target at %p\n", surface
);
2243 IWineD3DSurface_Release((IWineD3DSurface
*)surface
);
2245 context_release(context
);
2247 for (i
= 0; i
< This
->NumberOfSwapChains
; ++i
)
2249 TRACE("Releasing the implicit swapchain %u.\n", i
);
2250 if (D3DCB_DestroySwapChain((IWineD3DSwapChain
*)This
->swapchains
[i
]) > 0)
2252 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
2256 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2257 This
->swapchains
= NULL
;
2258 This
->NumberOfSwapChains
= 0;
2260 for (i
= 0; i
< This
->NumberOfPalettes
; i
++) HeapFree(GetProcessHeap(), 0, This
->palettes
[i
]);
2261 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2262 This
->palettes
= NULL
;
2263 This
->NumberOfPalettes
= 0;
2265 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2266 This
->render_targets
= NULL
;
2268 This
->d3d_initialized
= FALSE
;
2273 static HRESULT WINAPI
IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice
*iface
, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain
) {
2274 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2277 for (i
= 0; i
< This
->NumberOfSwapChains
; ++i
)
2279 TRACE("Releasing the implicit swapchain %u.\n", i
);
2280 if (D3DCB_DestroySwapChain((IWineD3DSwapChain
*)This
->swapchains
[i
]) > 0)
2282 FIXME("(%p) Something's still holding the implicit swapchain\n", This
);
2286 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2287 This
->swapchains
= NULL
;
2288 This
->NumberOfSwapChains
= 0;
2292 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
2293 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2294 * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2296 * There is no way to deactivate thread safety once it is enabled.
2298 static void WINAPI
IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice
*iface
) {
2299 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2301 /*For now just store the flag(needed in case of ddraw) */
2302 This
->createParms
.BehaviorFlags
|= WINED3DCREATE_MULTITHREADED
;
2305 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
,
2306 const WINED3DDISPLAYMODE
* pMode
) {
2308 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2309 const struct wined3d_format
*format
= wined3d_get_format(&This
->adapter
->gl_info
, pMode
->Format
);
2313 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This
, iSwapChain
, pMode
, pMode
->Width
, pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
2315 /* Resize the screen even without a window:
2316 * The app could have unset it with SetCooperativeLevel, but not called
2317 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2318 * but we don't have any hwnd
2321 memset(&devmode
, 0, sizeof(devmode
));
2322 devmode
.dmSize
= sizeof(devmode
);
2323 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
2324 devmode
.dmBitsPerPel
= format
->byte_count
* CHAR_BIT
;
2325 devmode
.dmPelsWidth
= pMode
->Width
;
2326 devmode
.dmPelsHeight
= pMode
->Height
;
2328 devmode
.dmDisplayFrequency
= pMode
->RefreshRate
;
2329 if (pMode
->RefreshRate
)
2330 devmode
.dmFields
|= DM_DISPLAYFREQUENCY
;
2332 /* Only change the mode if necessary */
2333 if (This
->ddraw_width
== pMode
->Width
&& This
->ddraw_height
== pMode
->Height
2334 && This
->ddraw_format
== pMode
->Format
&& !pMode
->RefreshRate
)
2337 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
2338 if (ret
!= DISP_CHANGE_SUCCESSFUL
)
2340 if (devmode
.dmDisplayFrequency
)
2342 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2343 devmode
.dmFields
&= ~DM_DISPLAYFREQUENCY
;
2344 devmode
.dmDisplayFrequency
= 0;
2345 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
) != DISP_CHANGE_SUCCESSFUL
;
2347 if(ret
!= DISP_CHANGE_SUCCESSFUL
) {
2348 return WINED3DERR_NOTAVAILABLE
;
2352 /* Store the new values */
2353 This
->ddraw_width
= pMode
->Width
;
2354 This
->ddraw_height
= pMode
->Height
;
2355 This
->ddraw_format
= pMode
->Format
;
2357 /* And finally clip mouse to our screen */
2358 SetRect(&clip_rc
, 0, 0, pMode
->Width
, pMode
->Height
);
2359 ClipCursor(&clip_rc
);
2364 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
*iface
, struct wined3d
**wined3d
)
2366 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
2368 TRACE("iface %p, wined3d %p.\n", iface
, wined3d
);
2370 *wined3d
= device
->wined3d
;
2371 wined3d_incref(*wined3d
);
2373 TRACE("Returning %p.\n", *wined3d
);
2378 static UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
2379 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2381 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This
,
2382 (This
->adapter
->TextureRam
/(1024*1024)),
2383 ((This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
) / (1024*1024)));
2384 /* return simulated texture memory left */
2385 return (This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
);
2389 * Get / Set Stream Source
2391 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,
2392 IWineD3DBuffer
*pStreamData
, UINT OffsetInBytes
, UINT Stride
)
2394 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2395 struct wined3d_stream_state
*stream
;
2396 IWineD3DBuffer
*oldSrc
;
2398 TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
2399 iface
, StreamNumber
, pStreamData
, OffsetInBytes
, Stride
);
2401 if (StreamNumber
>= MAX_STREAMS
) {
2402 WARN("Stream out of range %d\n", StreamNumber
);
2403 return WINED3DERR_INVALIDCALL
;
2404 } else if(OffsetInBytes
& 0x3) {
2405 WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes
);
2406 return WINED3DERR_INVALIDCALL
;
2409 stream
= &This
->updateStateBlock
->state
.streams
[StreamNumber
];
2410 oldSrc
= (IWineD3DBuffer
*)stream
->buffer
;
2412 This
->updateStateBlock
->changed
.streamSource
|= 1 << StreamNumber
;
2414 if (oldSrc
== pStreamData
2415 && stream
->stride
== Stride
2416 && stream
->offset
== OffsetInBytes
)
2418 TRACE("Application is setting the old values over, nothing to do\n");
2422 stream
->buffer
= (struct wined3d_buffer
*)pStreamData
;
2425 stream
->stride
= Stride
;
2426 stream
->offset
= OffsetInBytes
;
2429 /* Handle recording of state blocks */
2430 if (This
->isRecordingState
) {
2431 TRACE("Recording... not performing anything\n");
2432 if (pStreamData
) IWineD3DBuffer_AddRef(pStreamData
);
2433 if (oldSrc
) IWineD3DBuffer_Release(oldSrc
);
2439 InterlockedIncrement(&((struct wined3d_buffer
*)pStreamData
)->bind_count
);
2440 IWineD3DBuffer_AddRef(pStreamData
);
2444 InterlockedDecrement(&((struct wined3d_buffer
*)oldSrc
)->bind_count
);
2445 IWineD3DBuffer_Release(oldSrc
);
2448 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2453 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
,
2454 UINT StreamNumber
, IWineD3DBuffer
**pStream
, UINT
*pOffset
, UINT
*pStride
)
2456 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2457 struct wined3d_stream_state
*stream
;
2459 TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
2460 iface
, StreamNumber
, pStream
, pOffset
, pStride
);
2462 if (StreamNumber
>= MAX_STREAMS
)
2464 WARN("Stream out of range %d\n", StreamNumber
);
2465 return WINED3DERR_INVALIDCALL
;
2468 stream
= &This
->stateBlock
->state
.streams
[StreamNumber
];
2469 *pStream
= (IWineD3DBuffer
*)stream
->buffer
;
2470 *pStride
= stream
->stride
;
2471 if (pOffset
) *pOffset
= stream
->offset
;
2473 if (*pStream
) IWineD3DBuffer_AddRef(*pStream
);
2478 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
2479 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2480 struct wined3d_stream_state
*stream
;
2481 UINT old_flags
, oldFreq
;
2483 TRACE("iface %p, stream_idx %u, divider %#x.\n", iface
, StreamNumber
, Divider
);
2485 /* Verify input at least in d3d9 this is invalid. */
2486 if ((Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && (Divider
& WINED3DSTREAMSOURCE_INDEXEDDATA
))
2488 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
2489 return WINED3DERR_INVALIDCALL
;
2491 if ((Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && !StreamNumber
)
2493 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
2494 return WINED3DERR_INVALIDCALL
;
2498 WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
2499 return WINED3DERR_INVALIDCALL
;
2502 stream
= &This
->updateStateBlock
->state
.streams
[StreamNumber
];
2503 old_flags
= stream
->flags
;
2504 oldFreq
= stream
->frequency
;
2506 stream
->flags
= Divider
& (WINED3DSTREAMSOURCE_INSTANCEDATA
| WINED3DSTREAMSOURCE_INDEXEDDATA
);
2507 stream
->frequency
= Divider
& 0x7FFFFF;
2509 This
->updateStateBlock
->changed
.streamFreq
|= 1 << StreamNumber
;
2511 if (stream
->frequency
!= oldFreq
|| stream
->flags
!= old_flags
)
2512 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2517 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
2518 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2519 struct wined3d_stream_state
*stream
;
2521 TRACE("iface %p, stream_idx %u, divider %p.\n", iface
, StreamNumber
, Divider
);
2523 stream
= &This
->updateStateBlock
->state
.streams
[StreamNumber
];
2524 *Divider
= stream
->flags
| stream
->frequency
;
2526 TRACE("Returning %#x.\n", *Divider
);
2532 * Get / Set & Multiply Transform
2534 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE d3dts
, CONST WINED3DMATRIX
* lpmatrix
) {
2535 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2537 /* Most of this routine, comments included copied from ddraw tree initially: */
2538 TRACE("(%p) : Transform State=%s\n", This
, debug_d3dtstype(d3dts
));
2540 /* Handle recording of state blocks */
2541 if (This
->isRecordingState
) {
2542 TRACE("Recording... not performing anything\n");
2543 This
->updateStateBlock
->changed
.transform
[d3dts
>> 5] |= 1 << (d3dts
& 0x1f);
2544 This
->updateStateBlock
->state
.transforms
[d3dts
] = *lpmatrix
;
2549 * If the new matrix is the same as the current one,
2550 * we cut off any further processing. this seems to be a reasonable
2551 * optimization because as was noticed, some apps (warcraft3 for example)
2552 * tend towards setting the same matrix repeatedly for some reason.
2554 * From here on we assume that the new matrix is different, wherever it matters.
2556 if (!memcmp(&This
->stateBlock
->state
.transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(*lpmatrix
)))
2558 TRACE("The app is setting the same matrix over again\n");
2563 conv_mat(lpmatrix
, &This
->stateBlock
->state
.transforms
[d3dts
].u
.m
[0][0]);
2567 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2568 where ViewMat = Camera space, WorldMat = world space.
2570 In OpenGL, camera and world space is combined into GL_MODELVIEW
2571 matrix. The Projection matrix stay projection matrix.
2574 /* Capture the times we can just ignore the change for now */
2575 if (d3dts
== WINED3DTS_VIEW
) { /* handle the VIEW matrix */
2576 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
2577 /* Handled by the state manager */
2580 if (d3dts
< WINED3DTS_WORLDMATRIX(This
->adapter
->gl_info
.limits
.blends
))
2581 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TRANSFORM(d3dts
));
2587 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
,
2588 WINED3DTRANSFORMSTATETYPE state
, WINED3DMATRIX
*matrix
)
2590 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
2592 TRACE("iface %p, state %s, matrix %p.\n", iface
, debug_d3dtstype(state
), matrix
);
2594 *matrix
= device
->stateBlock
->state
.transforms
[state
];
2599 static HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, CONST WINED3DMATRIX
* pMatrix
) {
2600 const WINED3DMATRIX
*mat
= NULL
;
2603 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2604 * below means it will be recorded in a state block change, but it
2605 * works regardless where it is recorded.
2606 * If this is found to be wrong, change to StateBlock.
2608 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2609 TRACE("(%p) : For state %s\n", This
, debug_d3dtstype(State
));
2611 if (State
<= HIGHEST_TRANSFORMSTATE
)
2613 mat
= &This
->updateStateBlock
->state
.transforms
[State
];
2617 FIXME("Unhandled transform state!!\n");
2620 multiply_matrix(&temp
, mat
, pMatrix
);
2622 /* Apply change via set transform - will reapply to eg. lights this way */
2623 return IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
2629 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2630 you can reference any indexes you want as long as that number max are enabled at any
2631 one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2632 However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2633 but when recording, just build a chain pretty much of commands to be replayed. */
2635 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
2637 struct wined3d_light_info
*object
= NULL
;
2638 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2641 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2642 TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This
, Index
, pLight
, Hi
);
2644 /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2648 WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2649 return WINED3DERR_INVALIDCALL
;
2652 switch(pLight
->Type
) {
2653 case WINED3DLIGHT_POINT
:
2654 case WINED3DLIGHT_SPOT
:
2655 case WINED3DLIGHT_PARALLELPOINT
:
2656 case WINED3DLIGHT_GLSPOT
:
2657 /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2660 if (pLight
->Attenuation0
< 0.0f
|| pLight
->Attenuation1
< 0.0f
|| pLight
->Attenuation2
< 0.0f
)
2662 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2663 return WINED3DERR_INVALIDCALL
;
2667 case WINED3DLIGHT_DIRECTIONAL
:
2668 /* Ignores attenuation */
2672 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2673 return WINED3DERR_INVALIDCALL
;
2676 LIST_FOR_EACH(e
, &This
->updateStateBlock
->state
.light_map
[Hi
])
2678 object
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2679 if(object
->OriginalIndex
== Index
) break;
2684 TRACE("Adding new light\n");
2685 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2687 ERR("Out of memory error when allocating a light\n");
2688 return E_OUTOFMEMORY
;
2690 list_add_head(&This
->updateStateBlock
->state
.light_map
[Hi
], &object
->entry
);
2691 object
->glIndex
= -1;
2692 object
->OriginalIndex
= Index
;
2695 /* Initialize the object */
2696 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
,
2697 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
2698 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
2699 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
2700 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
2701 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
2702 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
2704 /* Save away the information */
2705 object
->OriginalParms
= *pLight
;
2707 switch (pLight
->Type
) {
2708 case WINED3DLIGHT_POINT
:
2710 object
->lightPosn
[0] = pLight
->Position
.x
;
2711 object
->lightPosn
[1] = pLight
->Position
.y
;
2712 object
->lightPosn
[2] = pLight
->Position
.z
;
2713 object
->lightPosn
[3] = 1.0f
;
2714 object
->cutoff
= 180.0f
;
2718 case WINED3DLIGHT_DIRECTIONAL
:
2720 object
->lightPosn
[0] = -pLight
->Direction
.x
;
2721 object
->lightPosn
[1] = -pLight
->Direction
.y
;
2722 object
->lightPosn
[2] = -pLight
->Direction
.z
;
2723 object
->lightPosn
[3] = 0.0f
;
2724 object
->exponent
= 0.0f
;
2725 object
->cutoff
= 180.0f
;
2728 case WINED3DLIGHT_SPOT
:
2730 object
->lightPosn
[0] = pLight
->Position
.x
;
2731 object
->lightPosn
[1] = pLight
->Position
.y
;
2732 object
->lightPosn
[2] = pLight
->Position
.z
;
2733 object
->lightPosn
[3] = 1.0f
;
2736 object
->lightDirn
[0] = pLight
->Direction
.x
;
2737 object
->lightDirn
[1] = pLight
->Direction
.y
;
2738 object
->lightDirn
[2] = pLight
->Direction
.z
;
2739 object
->lightDirn
[3] = 1.0f
;
2742 * opengl-ish and d3d-ish spot lights use too different models for the
2743 * light "intensity" as a function of the angle towards the main light direction,
2744 * so we only can approximate very roughly.
2745 * however spot lights are rather rarely used in games (if ever used at all).
2746 * furthermore if still used, probably nobody pays attention to such details.
2748 if (!pLight
->Falloff
)
2750 /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2751 * falloff resp. exponent parameter as an exponent, so the spot light lighting
2752 * will always be 1.0 for both of them, and we don't have to care for the
2753 * rest of the rather complex calculation
2755 object
->exponent
= 0.0f
;
2757 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
2758 if (rho
< 0.0001f
) rho
= 0.0001f
;
2759 object
->exponent
= -0.3f
/logf(cosf(rho
/2));
2761 if (object
->exponent
> 128.0f
)
2763 object
->exponent
= 128.0f
;
2765 object
->cutoff
= (float) (pLight
->Phi
*90/M_PI
);
2771 FIXME("Unrecognized light type %d\n", pLight
->Type
);
2774 /* Update the live definitions if the light is currently assigned a glIndex */
2775 if (object
->glIndex
!= -1 && !This
->isRecordingState
) {
2776 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(object
->glIndex
));
2781 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
*pLight
)
2783 struct wined3d_light_info
*lightInfo
= NULL
;
2784 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2785 DWORD Hi
= LIGHTMAP_HASHFUNC(Index
);
2787 TRACE("(%p) : Idx(%d), pLight(%p)\n", This
, Index
, pLight
);
2789 LIST_FOR_EACH(e
, &This
->stateBlock
->state
.light_map
[Hi
])
2791 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2792 if(lightInfo
->OriginalIndex
== Index
) break;
2798 TRACE("Light information requested but light not defined\n");
2799 return WINED3DERR_INVALIDCALL
;
2802 *pLight
= lightInfo
->OriginalParms
;
2807 * Get / Set Light Enable
2808 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2810 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
)
2812 struct wined3d_light_info
*lightInfo
= NULL
;
2813 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2814 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2816 TRACE("(%p) : Idx(%d), enable? %d\n", This
, Index
, Enable
);
2818 LIST_FOR_EACH(e
, &This
->updateStateBlock
->state
.light_map
[Hi
])
2820 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2821 if(lightInfo
->OriginalIndex
== Index
) break;
2824 TRACE("Found light: %p\n", lightInfo
);
2826 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2829 TRACE("Light enabled requested but light not defined, so defining one!\n");
2830 IWineD3DDeviceImpl_SetLight(iface
, Index
, &WINED3D_default_light
);
2832 /* Search for it again! Should be fairly quick as near head of list */
2833 LIST_FOR_EACH(e
, &This
->updateStateBlock
->state
.light_map
[Hi
])
2835 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2836 if(lightInfo
->OriginalIndex
== Index
) break;
2841 FIXME("Adding default lights has failed dismally\n");
2842 return WINED3DERR_INVALIDCALL
;
2847 if(lightInfo
->glIndex
!= -1) {
2848 if(!This
->isRecordingState
) {
2849 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(lightInfo
->glIndex
));
2852 This
->updateStateBlock
->state
.lights
[lightInfo
->glIndex
] = NULL
;
2853 lightInfo
->glIndex
= -1;
2855 TRACE("Light already disabled, nothing to do\n");
2857 lightInfo
->enabled
= FALSE
;
2859 lightInfo
->enabled
= TRUE
;
2860 if (lightInfo
->glIndex
!= -1) {
2862 TRACE("Nothing to do as light was enabled\n");
2865 /* Find a free gl light */
2866 for (i
= 0; i
< This
->maxConcurrentLights
; ++i
)
2868 if (!This
->updateStateBlock
->state
.lights
[i
])
2870 This
->updateStateBlock
->state
.lights
[i
] = lightInfo
;
2871 lightInfo
->glIndex
= i
;
2875 if(lightInfo
->glIndex
== -1) {
2876 /* Our tests show that Windows returns D3D_OK in this situation, even with
2877 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
2878 * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
2879 * as well for those lights.
2881 * TODO: Test how this affects rendering
2883 WARN("Too many concurrently active lights\n");
2887 /* i == lightInfo->glIndex */
2888 if(!This
->isRecordingState
) {
2889 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(i
));
2897 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
)
2899 struct wined3d_light_info
*lightInfo
= NULL
;
2900 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2902 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2903 TRACE("(%p) : for idx(%d)\n", This
, Index
);
2905 LIST_FOR_EACH(e
, &This
->stateBlock
->state
.light_map
[Hi
])
2907 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2908 if(lightInfo
->OriginalIndex
== Index
) break;
2914 TRACE("Light enabled state requested but light not defined\n");
2915 return WINED3DERR_INVALIDCALL
;
2917 /* true is 128 according to SetLightEnable */
2918 *pEnable
= lightInfo
->enabled
? 128 : 0;
2923 * Get / Set Clip Planes
2925 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
2926 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2927 TRACE("(%p) : for idx %d, %p\n", This
, Index
, pPlane
);
2929 /* Validate Index */
2930 if (Index
>= This
->adapter
->gl_info
.limits
.clipplanes
)
2932 TRACE("Application has requested clipplane this device doesn't support\n");
2933 return WINED3DERR_INVALIDCALL
;
2936 This
->updateStateBlock
->changed
.clipplane
|= 1 << Index
;
2938 if (This
->updateStateBlock
->state
.clip_planes
[Index
][0] == pPlane
[0]
2939 && This
->updateStateBlock
->state
.clip_planes
[Index
][1] == pPlane
[1]
2940 && This
->updateStateBlock
->state
.clip_planes
[Index
][2] == pPlane
[2]
2941 && This
->updateStateBlock
->state
.clip_planes
[Index
][3] == pPlane
[3])
2943 TRACE("Application is setting old values over, nothing to do\n");
2947 This
->updateStateBlock
->state
.clip_planes
[Index
][0] = pPlane
[0];
2948 This
->updateStateBlock
->state
.clip_planes
[Index
][1] = pPlane
[1];
2949 This
->updateStateBlock
->state
.clip_planes
[Index
][2] = pPlane
[2];
2950 This
->updateStateBlock
->state
.clip_planes
[Index
][3] = pPlane
[3];
2952 /* Handle recording of state blocks */
2953 if (This
->isRecordingState
) {
2954 TRACE("Recording... not performing anything\n");
2958 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_CLIPPLANE(Index
));
2963 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
2964 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2965 TRACE("(%p) : for idx %d\n", This
, Index
);
2967 /* Validate Index */
2968 if (Index
>= This
->adapter
->gl_info
.limits
.clipplanes
)
2970 TRACE("Application has requested clipplane this device doesn't support\n");
2971 return WINED3DERR_INVALIDCALL
;
2974 pPlane
[0] = (float)This
->stateBlock
->state
.clip_planes
[Index
][0];
2975 pPlane
[1] = (float)This
->stateBlock
->state
.clip_planes
[Index
][1];
2976 pPlane
[2] = (float)This
->stateBlock
->state
.clip_planes
[Index
][2];
2977 pPlane
[3] = (float)This
->stateBlock
->state
.clip_planes
[Index
][3];
2982 * Get / Set Clip Plane Status
2983 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2985 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
2986 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2987 FIXME("(%p) : stub\n", This
);
2990 return WINED3DERR_INVALIDCALL
;
2992 This
->updateStateBlock
->state
.clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
2993 This
->updateStateBlock
->state
.clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
2997 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
2998 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2999 FIXME("(%p) : stub\n", This
);
3002 return WINED3DERR_INVALIDCALL
;
3004 pClipStatus
->ClipUnion
= This
->updateStateBlock
->state
.clip_status
.ClipUnion
;
3005 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->state
.clip_status
.ClipIntersection
;
3010 * Get / Set Material
3012 static HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
3013 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3015 This
->updateStateBlock
->changed
.material
= TRUE
;
3016 This
->updateStateBlock
->state
.material
= *pMaterial
;
3018 /* Handle recording of state blocks */
3019 if (This
->isRecordingState
) {
3020 TRACE("Recording... not performing anything\n");
3024 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_MATERIAL
);
3028 static HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
3029 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3030 *pMaterial
= This
->updateStateBlock
->state
.material
;
3031 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
3032 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
3033 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
3034 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
3035 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
3036 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
3037 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
3038 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
3039 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
3047 static HRESULT WINAPI
IWineD3DDeviceImpl_SetIndexBuffer(IWineD3DDevice
*iface
,
3048 IWineD3DBuffer
*pIndexData
, enum wined3d_format_id fmt
)
3050 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3051 IWineD3DBuffer
*oldIdxs
;
3053 TRACE("(%p) : Setting to %p\n", This
, pIndexData
);
3054 oldIdxs
= (IWineD3DBuffer
*)This
->updateStateBlock
->state
.index_buffer
;
3056 This
->updateStateBlock
->changed
.indices
= TRUE
;
3057 This
->updateStateBlock
->state
.index_buffer
= (struct wined3d_buffer
*)pIndexData
;
3058 This
->updateStateBlock
->state
.index_format
= fmt
;
3060 /* Handle recording of state blocks */
3061 if (This
->isRecordingState
) {
3062 TRACE("Recording... not performing anything\n");
3063 if(pIndexData
) IWineD3DBuffer_AddRef(pIndexData
);
3064 if(oldIdxs
) IWineD3DBuffer_Release(oldIdxs
);
3068 if(oldIdxs
!= pIndexData
) {
3069 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
3071 InterlockedIncrement(&((struct wined3d_buffer
*)pIndexData
)->bind_count
);
3072 IWineD3DBuffer_AddRef(pIndexData
);
3075 InterlockedDecrement(&((struct wined3d_buffer
*)oldIdxs
)->bind_count
);
3076 IWineD3DBuffer_Release(oldIdxs
);
3083 static HRESULT WINAPI
IWineD3DDeviceImpl_GetIndexBuffer(IWineD3DDevice
*iface
, IWineD3DBuffer
**ppIndexData
)
3085 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3087 *ppIndexData
= (IWineD3DBuffer
*)This
->stateBlock
->state
.index_buffer
;
3089 /* up ref count on ppindexdata */
3091 IWineD3DBuffer_AddRef(*ppIndexData
);
3092 TRACE("(%p) index data set to %p\n", This
, ppIndexData
);
3094 TRACE("(%p) No index data set\n", This
);
3096 TRACE("Returning %p\n", *ppIndexData
);
3101 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
3102 static HRESULT WINAPI
IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice
*iface
, INT BaseIndex
) {
3103 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3104 TRACE("(%p)->(%d)\n", This
, BaseIndex
);
3106 if (This
->updateStateBlock
->state
.base_vertex_index
== BaseIndex
)
3108 TRACE("Application is setting the old value over, nothing to do\n");
3112 This
->updateStateBlock
->state
.base_vertex_index
= BaseIndex
;
3114 if (This
->isRecordingState
) {
3115 TRACE("Recording... not performing anything\n");
3118 /* The base vertex index affects the stream sources */
3119 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
3123 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice
*iface
, INT
* base_index
) {
3124 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3125 TRACE("(%p) : base_index %p\n", This
, base_index
);
3127 *base_index
= This
->stateBlock
->state
.base_vertex_index
;
3129 TRACE("Returning %u\n", *base_index
);
3135 * Get / Set Viewports
3137 static HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
3138 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3140 TRACE("(%p)\n", This
);
3141 This
->updateStateBlock
->changed
.viewport
= TRUE
;
3142 This
->updateStateBlock
->state
.viewport
= *pViewport
;
3144 /* Handle recording of state blocks */
3145 if (This
->isRecordingState
) {
3146 TRACE("Recording... not performing anything\n");
3150 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This
,
3151 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
3153 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
3158 static HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
3159 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3160 TRACE("(%p)\n", This
);
3161 *pViewport
= This
->stateBlock
->state
.viewport
;
3165 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
,
3166 WINED3DRENDERSTATETYPE State
, DWORD Value
)
3168 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3169 DWORD oldValue
= This
->stateBlock
->state
.render_states
[State
];
3171 TRACE("iface %p, state %s (%#x), value %#x.\n", iface
, debug_d3drenderstate(State
), State
, Value
);
3173 This
->updateStateBlock
->changed
.renderState
[State
>> 5] |= 1 << (State
& 0x1f);
3174 This
->updateStateBlock
->state
.render_states
[State
] = Value
;
3176 /* Handle recording of state blocks */
3177 if (This
->isRecordingState
) {
3178 TRACE("Recording... not performing anything\n");
3182 /* Compared here and not before the assignment to allow proper stateblock recording */
3183 if(Value
== oldValue
) {
3184 TRACE("Application is setting the old value over, nothing to do\n");
3186 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(State
));
3192 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
,
3193 WINED3DRENDERSTATETYPE State
, DWORD
*pValue
)
3195 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3197 TRACE("iface %p, state %s (%#x), value %p.\n", iface
, debug_d3drenderstate(State
), State
, pValue
);
3199 *pValue
= This
->stateBlock
->state
.render_states
[State
];
3204 * Get / Set Sampler States
3205 * TODO: Verify against dx9 definitions
3208 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
3209 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3212 TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3213 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
, Value
);
3215 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3216 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3219 if (Sampler
>= sizeof(This
->stateBlock
->state
.sampler_states
) / sizeof(*This
->stateBlock
->state
.sampler_states
))
3221 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3222 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3225 oldValue
= This
->stateBlock
->state
.sampler_states
[Sampler
][Type
];
3226 This
->updateStateBlock
->state
.sampler_states
[Sampler
][Type
] = Value
;
3227 This
->updateStateBlock
->changed
.samplerState
[Sampler
] |= 1 << Type
;
3229 /* Handle recording of state blocks */
3230 if (This
->isRecordingState
) {
3231 TRACE("Recording... not performing anything\n");
3235 if(oldValue
== Value
) {
3236 TRACE("Application is setting the old value over, nothing to do\n");
3240 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(Sampler
));
3245 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
3246 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3248 TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3249 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
);
3251 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3252 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3255 if (Sampler
>= sizeof(This
->stateBlock
->state
.sampler_states
) / sizeof(*This
->stateBlock
->state
.sampler_states
))
3257 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3258 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3260 *Value
= This
->stateBlock
->state
.sampler_states
[Sampler
][Type
];
3261 TRACE("(%p) : Returning %#x\n", This
, *Value
);
3266 static HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
3267 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3269 This
->updateStateBlock
->changed
.scissorRect
= TRUE
;
3270 if (EqualRect(&This
->updateStateBlock
->state
.scissor_rect
, pRect
))
3272 TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
3275 CopyRect(&This
->updateStateBlock
->state
.scissor_rect
, pRect
);
3277 if(This
->isRecordingState
) {
3278 TRACE("Recording... not performing anything\n");
3282 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
3287 static HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
3288 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3290 *pRect
= This
->updateStateBlock
->state
.scissor_rect
;
3291 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3295 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
*iface
,
3296 struct wined3d_vertex_declaration
*pDecl
)
3298 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
3299 struct wined3d_vertex_declaration
*oldDecl
= This
->updateStateBlock
->state
.vertex_declaration
;
3301 TRACE("iface %p, declaration %p.\n", iface
, pDecl
);
3304 wined3d_vertex_declaration_incref(pDecl
);
3306 wined3d_vertex_declaration_decref(oldDecl
);
3308 This
->updateStateBlock
->state
.vertex_declaration
= pDecl
;
3309 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
3311 if (This
->isRecordingState
) {
3312 TRACE("Recording... not performing anything\n");
3314 } else if(pDecl
== oldDecl
) {
3315 /* Checked after the assignment to allow proper stateblock recording */
3316 TRACE("Application is setting the old declaration over, nothing to do\n");
3320 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
3324 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
*iface
,
3325 struct wined3d_vertex_declaration
**ppDecl
)
3327 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3329 TRACE("iface %p, declaration %p.\n", iface
, ppDecl
);
3331 *ppDecl
= This
->stateBlock
->state
.vertex_declaration
;
3333 wined3d_vertex_declaration_incref(*ppDecl
);
3338 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, IWineD3DVertexShader
*pShader
)
3340 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3341 IWineD3DVertexShader
*oldShader
= (IWineD3DVertexShader
*)This
->updateStateBlock
->state
.vertex_shader
;
3343 This
->updateStateBlock
->state
.vertex_shader
= (IWineD3DVertexShaderImpl
*)pShader
;
3344 This
->updateStateBlock
->changed
.vertexShader
= TRUE
;
3346 if (This
->isRecordingState
) {
3347 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
3348 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
3349 TRACE("Recording... not performing anything\n");
3351 } else if(oldShader
== pShader
) {
3352 /* Checked here to allow proper stateblock recording */
3353 TRACE("App is setting the old shader over, nothing to do\n");
3357 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
3358 if(pShader
) IWineD3DVertexShader_AddRef(pShader
);
3359 if(oldShader
) IWineD3DVertexShader_Release(oldShader
);
3361 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VSHADER
);
3366 static IWineD3DVertexShader
* WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
)
3368 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
3369 IWineD3DVertexShader
*shader
;
3371 TRACE("iface %p.\n", iface
);
3373 shader
= (IWineD3DVertexShader
*)device
->stateBlock
->state
.vertex_shader
;
3374 if (shader
) IWineD3DVertexShader_AddRef(shader
);
3376 TRACE("Returning %p.\n", shader
);
3380 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(
3381 IWineD3DDevice
*iface
,
3383 CONST BOOL
*srcData
,
3386 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3387 unsigned int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3389 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3390 iface
, srcData
, start
, count
);
3392 if (!srcData
|| start
>= MAX_CONST_B
) return WINED3DERR_INVALIDCALL
;
3394 memcpy(&This
->updateStateBlock
->state
.vs_consts_b
[start
], srcData
, cnt
* sizeof(BOOL
));
3395 for (i
= 0; i
< cnt
; i
++)
3396 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3398 for (i
= start
; i
< cnt
+ start
; ++i
) {
3399 This
->updateStateBlock
->changed
.vertexShaderConstantsB
|= (1 << i
);
3402 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3407 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(
3408 IWineD3DDevice
*iface
,
3413 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3414 int cnt
= min(count
, MAX_CONST_B
- start
);
3416 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3417 iface
, dstData
, start
, count
);
3419 if (!dstData
|| cnt
< 0)
3420 return WINED3DERR_INVALIDCALL
;
3422 memcpy(dstData
, &This
->stateBlock
->state
.vs_consts_b
[start
], cnt
* sizeof(BOOL
));
3426 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(
3427 IWineD3DDevice
*iface
,
3432 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3433 unsigned int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3435 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3436 iface
, srcData
, start
, count
);
3438 if (!srcData
|| start
>= MAX_CONST_I
) return WINED3DERR_INVALIDCALL
;
3440 memcpy(&This
->updateStateBlock
->state
.vs_consts_i
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3441 for (i
= 0; i
< cnt
; i
++)
3442 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3443 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3445 for (i
= start
; i
< cnt
+ start
; ++i
) {
3446 This
->updateStateBlock
->changed
.vertexShaderConstantsI
|= (1 << i
);
3449 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3454 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(
3455 IWineD3DDevice
*iface
,
3460 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3461 int cnt
= min(count
, MAX_CONST_I
- start
);
3463 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3464 iface
, dstData
, start
, count
);
3466 if (!dstData
|| ((signed int)MAX_CONST_I
- (signed int)start
) <= 0)
3467 return WINED3DERR_INVALIDCALL
;
3469 memcpy(dstData
, &This
->stateBlock
->state
.vs_consts_i
[start
* 4], cnt
* sizeof(int) * 4);
3473 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(
3474 IWineD3DDevice
*iface
,
3476 CONST
float *srcData
,
3479 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3482 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3483 iface
, srcData
, start
, count
);
3485 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3486 if (!srcData
|| start
+ count
> This
->d3d_vshader_constantF
|| start
> This
->d3d_vshader_constantF
)
3487 return WINED3DERR_INVALIDCALL
;
3489 memcpy(&This
->updateStateBlock
->state
.vs_consts_f
[start
* 4], srcData
, count
* sizeof(float) * 4);
3491 for (i
= 0; i
< count
; i
++)
3492 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3493 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3496 if (!This
->isRecordingState
)
3498 This
->shader_backend
->shader_update_float_vertex_constants(This
, start
, count
);
3499 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3502 memset(This
->updateStateBlock
->changed
.vertexShaderConstantsF
+ start
, 1,
3503 sizeof(*This
->updateStateBlock
->changed
.vertexShaderConstantsF
) * count
);
3508 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(
3509 IWineD3DDevice
*iface
,
3514 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3515 int cnt
= min(count
, This
->d3d_vshader_constantF
- start
);
3517 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3518 iface
, dstData
, start
, count
);
3520 if (!dstData
|| cnt
< 0)
3521 return WINED3DERR_INVALIDCALL
;
3523 memcpy(dstData
, &This
->stateBlock
->state
.vs_consts_f
[start
* 4], cnt
* sizeof(float) * 4);
3527 static inline void markTextureStagesDirty(IWineD3DDeviceImpl
*This
, DWORD stage
) {
3529 for(i
= 0; i
<= WINED3D_HIGHEST_TEXTURE_STATE
; ++i
)
3531 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, i
));
3535 static void device_map_stage(IWineD3DDeviceImpl
*This
, DWORD stage
, DWORD unit
)
3537 DWORD i
= This
->rev_tex_unit_map
[unit
];
3538 DWORD j
= This
->texUnitMap
[stage
];
3540 This
->texUnitMap
[stage
] = unit
;
3541 if (i
!= WINED3D_UNMAPPED_STAGE
&& i
!= stage
)
3543 This
->texUnitMap
[i
] = WINED3D_UNMAPPED_STAGE
;
3546 This
->rev_tex_unit_map
[unit
] = stage
;
3547 if (j
!= WINED3D_UNMAPPED_STAGE
&& j
!= unit
)
3549 This
->rev_tex_unit_map
[j
] = WINED3D_UNMAPPED_STAGE
;
3553 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl
*This
) {
3556 This
->fixed_function_usage_map
= 0;
3557 for (i
= 0; i
< MAX_TEXTURES
; ++i
)
3559 const struct wined3d_state
*state
= &This
->stateBlock
->state
;
3560 WINED3DTEXTUREOP color_op
= state
->texture_states
[i
][WINED3DTSS_COLOROP
];
3561 WINED3DTEXTUREOP alpha_op
= state
->texture_states
[i
][WINED3DTSS_ALPHAOP
];
3562 DWORD color_arg1
= state
->texture_states
[i
][WINED3DTSS_COLORARG1
] & WINED3DTA_SELECTMASK
;
3563 DWORD color_arg2
= state
->texture_states
[i
][WINED3DTSS_COLORARG2
] & WINED3DTA_SELECTMASK
;
3564 DWORD color_arg3
= state
->texture_states
[i
][WINED3DTSS_COLORARG0
] & WINED3DTA_SELECTMASK
;
3565 DWORD alpha_arg1
= state
->texture_states
[i
][WINED3DTSS_ALPHAARG1
] & WINED3DTA_SELECTMASK
;
3566 DWORD alpha_arg2
= state
->texture_states
[i
][WINED3DTSS_ALPHAARG2
] & WINED3DTA_SELECTMASK
;
3567 DWORD alpha_arg3
= state
->texture_states
[i
][WINED3DTSS_ALPHAARG0
] & WINED3DTA_SELECTMASK
;
3569 if (color_op
== WINED3DTOP_DISABLE
) {
3570 /* Not used, and disable higher stages */
3574 if (((color_arg1
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG2
)
3575 || ((color_arg2
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG1
)
3576 || ((color_arg3
== WINED3DTA_TEXTURE
) && (color_op
== WINED3DTOP_MULTIPLYADD
|| color_op
== WINED3DTOP_LERP
))
3577 || ((alpha_arg1
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG2
)
3578 || ((alpha_arg2
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG1
)
3579 || ((alpha_arg3
== WINED3DTA_TEXTURE
) && (alpha_op
== WINED3DTOP_MULTIPLYADD
|| alpha_op
== WINED3DTOP_LERP
))) {
3580 This
->fixed_function_usage_map
|= (1 << i
);
3583 if ((color_op
== WINED3DTOP_BUMPENVMAP
|| color_op
== WINED3DTOP_BUMPENVMAPLUMINANCE
) && i
< MAX_TEXTURES
- 1) {
3584 This
->fixed_function_usage_map
|= (1 << (i
+ 1));
3589 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl
*This
, const struct wined3d_gl_info
*gl_info
)
3591 unsigned int i
, tex
;
3594 device_update_fixed_function_usage_map(This
);
3595 ffu_map
= This
->fixed_function_usage_map
;
3597 if (This
->max_ffp_textures
== gl_info
->limits
.texture_stages
3598 || This
->stateBlock
->state
.lowest_disabled_stage
<= This
->max_ffp_textures
)
3600 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
3602 if (!(ffu_map
& 1)) continue;
3604 if (This
->texUnitMap
[i
] != i
) {
3605 device_map_stage(This
, i
, i
);
3606 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3607 markTextureStagesDirty(This
, i
);
3613 /* Now work out the mapping */
3615 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
3617 if (!(ffu_map
& 1)) continue;
3619 if (This
->texUnitMap
[i
] != tex
) {
3620 device_map_stage(This
, i
, tex
);
3621 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3622 markTextureStagesDirty(This
, i
);
3629 static void device_map_psamplers(IWineD3DDeviceImpl
*This
, const struct wined3d_gl_info
*gl_info
)
3631 const WINED3DSAMPLER_TEXTURE_TYPE
*sampler_type
=
3632 This
->stateBlock
->state
.pixel_shader
->baseShader
.reg_maps
.sampler_type
;
3635 for (i
= 0; i
< MAX_FRAGMENT_SAMPLERS
; ++i
) {
3636 if (sampler_type
[i
] && This
->texUnitMap
[i
] != i
)
3638 device_map_stage(This
, i
, i
);
3639 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3640 if (i
< gl_info
->limits
.texture_stages
)
3642 markTextureStagesDirty(This
, i
);
3648 static BOOL
device_unit_free_for_vs(IWineD3DDeviceImpl
*This
, const WINED3DSAMPLER_TEXTURE_TYPE
*pshader_sampler_tokens
,
3649 const WINED3DSAMPLER_TEXTURE_TYPE
*vshader_sampler_tokens
, DWORD unit
)
3651 DWORD current_mapping
= This
->rev_tex_unit_map
[unit
];
3653 /* Not currently used */
3654 if (current_mapping
== WINED3D_UNMAPPED_STAGE
) return TRUE
;
3656 if (current_mapping
< MAX_FRAGMENT_SAMPLERS
) {
3657 /* Used by a fragment sampler */
3659 if (!pshader_sampler_tokens
) {
3660 /* No pixel shader, check fixed function */
3661 return current_mapping
>= MAX_TEXTURES
|| !(This
->fixed_function_usage_map
& (1 << current_mapping
));
3664 /* Pixel shader, check the shader's sampler map */
3665 return !pshader_sampler_tokens
[current_mapping
];
3668 /* Used by a vertex sampler */
3669 return !vshader_sampler_tokens
[current_mapping
- MAX_FRAGMENT_SAMPLERS
];
3672 static void device_map_vsamplers(IWineD3DDeviceImpl
*This
, BOOL ps
, const struct wined3d_gl_info
*gl_info
)
3674 const WINED3DSAMPLER_TEXTURE_TYPE
*vshader_sampler_type
=
3675 This
->stateBlock
->state
.vertex_shader
->baseShader
.reg_maps
.sampler_type
;
3676 const WINED3DSAMPLER_TEXTURE_TYPE
*pshader_sampler_type
= NULL
;
3677 int start
= min(MAX_COMBINED_SAMPLERS
, gl_info
->limits
.combined_samplers
) - 1;
3682 IWineD3DPixelShaderImpl
*pshader
= This
->stateBlock
->state
.pixel_shader
;
3684 /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3685 * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3686 pshader_sampler_type
= pshader
->baseShader
.reg_maps
.sampler_type
;
3689 for (i
= 0; i
< MAX_VERTEX_SAMPLERS
; ++i
) {
3690 DWORD vsampler_idx
= i
+ MAX_FRAGMENT_SAMPLERS
;
3691 if (vshader_sampler_type
[i
])
3693 if (This
->texUnitMap
[vsampler_idx
] != WINED3D_UNMAPPED_STAGE
)
3695 /* Already mapped somewhere */
3699 while (start
>= 0) {
3700 if (device_unit_free_for_vs(This
, pshader_sampler_type
, vshader_sampler_type
, start
))
3702 device_map_stage(This
, vsampler_idx
, start
);
3703 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(vsampler_idx
));
3715 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl
*This
)
3717 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
3718 const struct wined3d_state
*state
= &This
->stateBlock
->state
;
3719 BOOL vs
= use_vs(state
);
3720 BOOL ps
= use_ps(state
);
3723 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3724 * that would be really messy and require shader recompilation
3725 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3726 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3728 if (ps
) device_map_psamplers(This
, gl_info
);
3729 else device_map_fixed_function_samplers(This
, gl_info
);
3731 if (vs
) device_map_vsamplers(This
, ps
, gl_info
);
3734 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, IWineD3DPixelShader
*pShader
)
3736 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3737 IWineD3DPixelShader
*oldShader
= (IWineD3DPixelShader
*)This
->updateStateBlock
->state
.pixel_shader
;
3738 This
->updateStateBlock
->state
.pixel_shader
= (IWineD3DPixelShaderImpl
*)pShader
;
3739 This
->updateStateBlock
->changed
.pixelShader
= TRUE
;
3741 /* Handle recording of state blocks */
3742 if (This
->isRecordingState
) {
3743 TRACE("Recording... not performing anything\n");
3746 if (This
->isRecordingState
) {
3747 TRACE("Recording... not performing anything\n");
3748 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3749 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3753 if(pShader
== oldShader
) {
3754 TRACE("App is setting the old pixel shader over, nothing to do\n");
3758 if(pShader
) IWineD3DPixelShader_AddRef(pShader
);
3759 if(oldShader
) IWineD3DPixelShader_Release(oldShader
);
3761 TRACE("(%p) : setting pShader(%p)\n", This
, pShader
);
3762 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
3767 static IWineD3DPixelShader
* WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
)
3769 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
3770 IWineD3DPixelShader
*shader
;
3772 TRACE("iface %p.\n", iface
);
3774 shader
= (IWineD3DPixelShader
*)device
->stateBlock
->state
.pixel_shader
;
3775 if (shader
) IWineD3DPixelShader_AddRef(shader
);
3777 TRACE("Returning %p.\n", shader
);
3781 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(
3782 IWineD3DDevice
*iface
,
3784 CONST BOOL
*srcData
,
3787 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3788 unsigned int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3790 TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3791 iface
, srcData
, start
, count
);
3793 if (!srcData
|| start
>= MAX_CONST_B
) return WINED3DERR_INVALIDCALL
;
3795 memcpy(&This
->updateStateBlock
->state
.ps_consts_b
[start
], srcData
, cnt
* sizeof(BOOL
));
3796 for (i
= 0; i
< cnt
; i
++)
3797 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3799 for (i
= start
; i
< cnt
+ start
; ++i
) {
3800 This
->updateStateBlock
->changed
.pixelShaderConstantsB
|= (1 << i
);
3803 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3808 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(
3809 IWineD3DDevice
*iface
,
3814 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3815 int cnt
= min(count
, MAX_CONST_B
- start
);
3817 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3818 iface
, dstData
, start
, count
);
3820 if (!dstData
|| cnt
< 0)
3821 return WINED3DERR_INVALIDCALL
;
3823 memcpy(dstData
, &This
->stateBlock
->state
.ps_consts_b
[start
], cnt
* sizeof(BOOL
));
3827 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(
3828 IWineD3DDevice
*iface
,
3833 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3834 unsigned int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3836 TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3837 iface
, srcData
, start
, count
);
3839 if (!srcData
|| start
>= MAX_CONST_I
) return WINED3DERR_INVALIDCALL
;
3841 memcpy(&This
->updateStateBlock
->state
.ps_consts_i
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3842 for (i
= 0; i
< cnt
; i
++)
3843 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3844 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3846 for (i
= start
; i
< cnt
+ start
; ++i
) {
3847 This
->updateStateBlock
->changed
.pixelShaderConstantsI
|= (1 << i
);
3850 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3855 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(
3856 IWineD3DDevice
*iface
,
3861 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3862 int cnt
= min(count
, MAX_CONST_I
- start
);
3864 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3865 iface
, dstData
, start
, count
);
3867 if (!dstData
|| cnt
< 0)
3868 return WINED3DERR_INVALIDCALL
;
3870 memcpy(dstData
, &This
->stateBlock
->state
.ps_consts_i
[start
* 4], cnt
* sizeof(int) * 4);
3874 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(
3875 IWineD3DDevice
*iface
,
3877 CONST
float *srcData
,
3880 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3883 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3884 iface
, srcData
, start
, count
);
3886 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3887 if (!srcData
|| start
+ count
> This
->d3d_pshader_constantF
|| start
> This
->d3d_pshader_constantF
)
3888 return WINED3DERR_INVALIDCALL
;
3890 memcpy(&This
->updateStateBlock
->state
.ps_consts_f
[start
* 4], srcData
, count
* sizeof(float) * 4);
3892 for (i
= 0; i
< count
; i
++)
3893 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3894 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3897 if (!This
->isRecordingState
)
3899 This
->shader_backend
->shader_update_float_pixel_constants(This
, start
, count
);
3900 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3903 memset(This
->updateStateBlock
->changed
.pixelShaderConstantsF
+ start
, 1,
3904 sizeof(*This
->updateStateBlock
->changed
.pixelShaderConstantsF
) * count
);
3909 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(
3910 IWineD3DDevice
*iface
,
3915 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3916 int cnt
= min(count
, This
->d3d_pshader_constantF
- start
);
3918 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3919 iface
, dstData
, start
, count
);
3921 if (!dstData
|| cnt
< 0)
3922 return WINED3DERR_INVALIDCALL
;
3924 memcpy(dstData
, &This
->stateBlock
->state
.ps_consts_f
[start
* 4], cnt
* sizeof(float) * 4);
3928 /* Context activation is done by the caller. */
3929 /* Do not call while under the GL lock. */
3930 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3931 static HRESULT
process_vertices_strided(IWineD3DDeviceImpl
*This
, DWORD dwDestIndex
, DWORD dwCount
,
3932 const struct wined3d_stream_info
*stream_info
, struct wined3d_buffer
*dest
, DWORD flags
,
3935 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
3936 char *dest_ptr
, *dest_conv
= NULL
, *dest_conv_addr
= NULL
;
3939 WINED3DMATRIX mat
, proj_mat
, view_mat
, world_mat
;
3943 if (stream_info
->use_map
& (1 << WINED3D_FFP_NORMAL
))
3945 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3948 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_POSITION
)))
3950 ERR("Source has no position mask\n");
3951 return WINED3DERR_INVALIDCALL
;
3954 if (!dest
->resource
.allocatedMemory
)
3955 buffer_get_sysmem(dest
, gl_info
);
3957 /* Get a pointer into the destination vbo(create one if none exists) and
3958 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3960 if (!dest
->buffer_object
&& gl_info
->supported
[ARB_VERTEX_BUFFER_OBJECT
])
3962 dest
->flags
|= WINED3D_BUFFER_CREATEBO
;
3963 IWineD3DBuffer_PreLoad((IWineD3DBuffer
*)dest
);
3966 if (dest
->buffer_object
)
3968 unsigned char extrabytes
= 0;
3969 /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
3970 * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
3971 * this may write 4 extra bytes beyond the area that should be written
3973 if(DestFVF
== WINED3DFVF_XYZ
) extrabytes
= 4;
3974 dest_conv_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwCount
* get_flexible_vertex_size(DestFVF
) + extrabytes
);
3975 if(!dest_conv_addr
) {
3976 ERR("Out of memory\n");
3977 /* Continue without storing converted vertices */
3979 dest_conv
= dest_conv_addr
;
3982 if (This
->stateBlock
->state
.render_states
[WINED3DRS_CLIPPING
])
3984 static BOOL warned
= FALSE
;
3986 * The clipping code is not quite correct. Some things need
3987 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3988 * so disable clipping for now.
3989 * (The graphics in Half-Life are broken, and my processvertices
3990 * test crashes with IDirect3DDevice3)
3996 FIXME("Clipping is broken and disabled for now\n");
3998 } else doClip
= FALSE
;
3999 dest_ptr
= ((char *)buffer_get_sysmem(dest
, gl_info
)) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
4001 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4004 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4005 WINED3DTS_PROJECTION
,
4007 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4008 WINED3DTS_WORLDMATRIX(0),
4011 TRACE("View mat:\n");
4012 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
);
4013 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
);
4014 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
);
4015 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
);
4017 TRACE("Proj mat:\n");
4018 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
);
4019 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
);
4020 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
);
4021 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
);
4023 TRACE("World mat:\n");
4024 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
);
4025 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
);
4026 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
);
4027 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
);
4029 /* Get the viewport */
4030 IWineD3DDevice_GetViewport( (IWineD3DDevice
*) This
, &vp
);
4031 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4032 vp
.X
, vp
.Y
, vp
.Width
, vp
.Height
, vp
.MinZ
, vp
.MaxZ
);
4034 multiply_matrix(&mat
,&view_mat
,&world_mat
);
4035 multiply_matrix(&mat
,&proj_mat
,&mat
);
4037 numTextures
= (DestFVF
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
4039 for (i
= 0; i
< dwCount
; i
+= 1) {
4040 unsigned int tex_index
;
4042 if ( ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZ
) ||
4043 ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) ) {
4044 /* The position first */
4045 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_POSITION
];
4046 const float *p
= (const float *)(element
->data
+ i
* element
->stride
);
4048 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
4050 /* Multiplication with world, view and projection matrix */
4051 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
);
4052 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
);
4053 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
);
4054 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
);
4056 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
4058 /* WARNING: The following things are taken from d3d7 and were not yet checked
4059 * against d3d8 or d3d9!
4062 /* Clipping conditions: From msdn
4064 * A vertex is clipped if it does not match the following requirements
4068 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4070 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4071 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4076 ( (-rhw
-eps
< x
) && (-rhw
-eps
< y
) && ( -eps
< z
) &&
4077 (x
<= rhw
+ eps
) && (y
<= rhw
+ eps
) && (z
<= rhw
+ eps
) &&
4080 /* "Normal" viewport transformation (not clipped)
4081 * 1) The values are divided by rhw
4082 * 2) The y axis is negative, so multiply it with -1
4083 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4084 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4085 * 4) Multiply x with Width/2 and add Width/2
4086 * 5) The same for the height
4087 * 6) Add the viewpoint X and Y to the 2D coordinates and
4088 * The minimum Z value to z
4089 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4091 * Well, basically it's simply a linear transformation into viewport
4103 z
*= vp
.MaxZ
- vp
.MinZ
;
4105 x
+= vp
.Width
/ 2 + vp
.X
;
4106 y
+= vp
.Height
/ 2 + vp
.Y
;
4111 /* That vertex got clipped
4112 * Contrary to OpenGL it is not dropped completely, it just
4113 * undergoes a different calculation.
4115 TRACE("Vertex got clipped\n");
4122 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4123 * outside of the main vertex buffer memory. That needs some more
4128 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
4131 ( (float *) dest_ptr
)[0] = x
;
4132 ( (float *) dest_ptr
)[1] = y
;
4133 ( (float *) dest_ptr
)[2] = z
;
4134 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
4136 dest_ptr
+= 3 * sizeof(float);
4138 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4139 dest_ptr
+= sizeof(float);
4144 ( (float *) dest_conv
)[0] = x
* w
;
4145 ( (float *) dest_conv
)[1] = y
* w
;
4146 ( (float *) dest_conv
)[2] = z
* w
;
4147 ( (float *) dest_conv
)[3] = w
;
4149 dest_conv
+= 3 * sizeof(float);
4151 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4152 dest_conv
+= sizeof(float);
4156 if (DestFVF
& WINED3DFVF_PSIZE
) {
4157 dest_ptr
+= sizeof(DWORD
);
4158 if(dest_conv
) dest_conv
+= sizeof(DWORD
);
4160 if (DestFVF
& WINED3DFVF_NORMAL
) {
4161 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_NORMAL
];
4162 const float *normal
= (const float *)(element
->data
+ i
* element
->stride
);
4163 /* AFAIK this should go into the lighting information */
4164 FIXME("Didn't expect the destination to have a normal\n");
4165 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
4167 copy_and_next(dest_conv
, normal
, 3 * sizeof(float));
4171 if (DestFVF
& WINED3DFVF_DIFFUSE
) {
4172 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_DIFFUSE
];
4173 const DWORD
*color_d
= (const DWORD
*)(element
->data
+ i
* element
->stride
);
4174 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_DIFFUSE
)))
4176 static BOOL warned
= FALSE
;
4179 ERR("No diffuse color in source, but destination has one\n");
4183 *( (DWORD
*) dest_ptr
) = 0xffffffff;
4184 dest_ptr
+= sizeof(DWORD
);
4187 *( (DWORD
*) dest_conv
) = 0xffffffff;
4188 dest_conv
+= sizeof(DWORD
);
4192 copy_and_next(dest_ptr
, color_d
, sizeof(DWORD
));
4194 *( (DWORD
*) dest_conv
) = (*color_d
& 0xff00ff00) ; /* Alpha + green */
4195 *( (DWORD
*) dest_conv
) |= (*color_d
& 0x00ff0000) >> 16; /* Red */
4196 *( (DWORD
*) dest_conv
) |= (*color_d
& 0xff0000ff) << 16; /* Blue */
4197 dest_conv
+= sizeof(DWORD
);
4202 if (DestFVF
& WINED3DFVF_SPECULAR
)
4204 /* What's the color value in the feedback buffer? */
4205 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_SPECULAR
];
4206 const DWORD
*color_s
= (const DWORD
*)(element
->data
+ i
* element
->stride
);
4207 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_SPECULAR
)))
4209 static BOOL warned
= FALSE
;
4212 ERR("No specular color in source, but destination has one\n");
4216 *( (DWORD
*) dest_ptr
) = 0xFF000000;
4217 dest_ptr
+= sizeof(DWORD
);
4220 *( (DWORD
*) dest_conv
) = 0xFF000000;
4221 dest_conv
+= sizeof(DWORD
);
4225 copy_and_next(dest_ptr
, color_s
, sizeof(DWORD
));
4227 *( (DWORD
*) dest_conv
) = (*color_s
& 0xff00ff00) ; /* Alpha + green */
4228 *( (DWORD
*) dest_conv
) |= (*color_s
& 0x00ff0000) >> 16; /* Red */
4229 *( (DWORD
*) dest_conv
) |= (*color_s
& 0xff0000ff) << 16; /* Blue */
4230 dest_conv
+= sizeof(DWORD
);
4235 for (tex_index
= 0; tex_index
< numTextures
; tex_index
++) {
4236 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_TEXCOORD0
+ tex_index
];
4237 const float *tex_coord
= (const float *)(element
->data
+ i
* element
->stride
);
4238 if (!(stream_info
->use_map
& (1 << (WINED3D_FFP_TEXCOORD0
+ tex_index
))))
4240 ERR("No source texture, but destination requests one\n");
4241 dest_ptr
+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4242 if(dest_conv
) dest_conv
+= GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4245 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4247 copy_and_next(dest_conv
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4257 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->buffer_object
));
4258 checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4259 GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB
, dwDestIndex
* get_flexible_vertex_size(DestFVF
),
4260 dwCount
* get_flexible_vertex_size(DestFVF
),
4262 checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4266 HeapFree(GetProcessHeap(), 0, dest_conv_addr
);
4271 #undef copy_and_next
4273 /* Do not call while under the GL lock. */
4274 static HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
, UINT SrcStartIndex
, UINT DestIndex
,
4275 UINT VertexCount
, IWineD3DBuffer
*pDestBuffer
, struct wined3d_vertex_declaration
*pVertexDecl
, DWORD flags
,
4278 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4279 struct wined3d_stream_info stream_info
;
4280 const struct wined3d_gl_info
*gl_info
;
4281 struct wined3d_context
*context
;
4282 BOOL vbo
= FALSE
, streamWasUP
= This
->stateBlock
->state
.user_stream
;
4285 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This
, SrcStartIndex
, DestIndex
, VertexCount
, pDestBuffer
, pVertexDecl
, flags
);
4288 ERR("Output vertex declaration not implemented yet\n");
4291 /* Need any context to write to the vbo. */
4292 context
= context_acquire(This
, NULL
);
4293 gl_info
= context
->gl_info
;
4295 /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4296 * control the streamIsUP flag, thus restore it afterwards.
4298 This
->stateBlock
->state
.user_stream
= FALSE
;
4299 device_stream_info_from_declaration(This
, FALSE
, &stream_info
, &vbo
);
4300 This
->stateBlock
->state
.user_stream
= streamWasUP
;
4302 if(vbo
|| SrcStartIndex
) {
4304 /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4305 * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
4307 * Also get the start index in, but only loop over all elements if there's something to add at all.
4309 for (i
= 0; i
< (sizeof(stream_info
.elements
) / sizeof(*stream_info
.elements
)); ++i
)
4311 struct wined3d_stream_info_element
*e
;
4313 if (!(stream_info
.use_map
& (1 << i
))) continue;
4315 e
= &stream_info
.elements
[i
];
4316 if (e
->buffer_object
)
4318 struct wined3d_buffer
*vb
= This
->stateBlock
->state
.streams
[e
->stream_idx
].buffer
;
4319 e
->buffer_object
= 0;
4320 e
->data
= (BYTE
*)((ULONG_PTR
)e
->data
+ (ULONG_PTR
)buffer_get_sysmem(vb
, gl_info
));
4322 GL_EXTCALL(glDeleteBuffersARB(1, &vb
->buffer_object
));
4323 vb
->buffer_object
= 0;
4326 if (e
->data
) e
->data
+= e
->stride
* SrcStartIndex
;
4330 hr
= process_vertices_strided(This
, DestIndex
, VertexCount
, &stream_info
,
4331 (struct wined3d_buffer
*)pDestBuffer
, flags
, DestFVF
);
4333 context_release(context
);
4339 * Get / Set Texture Stage States
4340 * TODO: Verify against dx9 definitions
4342 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
)
4344 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4345 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
4348 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
4350 if (Type
> WINED3D_HIGHEST_TEXTURE_STATE
)
4352 WARN("Invalid Type %d passed.\n", Type
);
4356 if (Stage
>= gl_info
->limits
.texture_stages
)
4358 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
4359 Stage
, gl_info
->limits
.texture_stages
- 1);
4363 oldValue
= This
->updateStateBlock
->state
.texture_states
[Stage
][Type
];
4364 This
->updateStateBlock
->changed
.textureState
[Stage
] |= 1 << Type
;
4365 This
->updateStateBlock
->state
.texture_states
[Stage
][Type
] = Value
;
4367 if (This
->isRecordingState
) {
4368 TRACE("Recording... not performing anything\n");
4372 /* Checked after the assignments to allow proper stateblock recording */
4373 if(oldValue
== Value
) {
4374 TRACE("App is setting the old value over, nothing to do\n");
4378 if (Stage
> This
->stateBlock
->state
.lowest_disabled_stage
4379 && This
->StateTable
[STATE_TEXTURESTAGE(0, Type
)].representative
4380 == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP
))
4382 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4383 * Changes in other states are important on disabled stages too
4388 if(Type
== WINED3DTSS_COLOROP
) {
4391 if(Value
== WINED3DTOP_DISABLE
&& oldValue
!= WINED3DTOP_DISABLE
) {
4392 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4393 * they have to be disabled
4395 * The current stage is dirtified below.
4397 for (i
= Stage
+ 1; i
< This
->stateBlock
->state
.lowest_disabled_stage
; ++i
)
4399 TRACE("Additionally dirtifying stage %u\n", i
);
4400 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4402 This
->stateBlock
->state
.lowest_disabled_stage
= Stage
;
4403 TRACE("New lowest disabled: %u\n", Stage
);
4404 } else if(Value
!= WINED3DTOP_DISABLE
&& oldValue
== WINED3DTOP_DISABLE
) {
4405 /* Previously disabled stage enabled. Stages above it may need enabling
4406 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4407 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4409 * Again stage Stage doesn't need to be dirtified here, it is handled below.
4412 for (i
= Stage
+ 1; i
< This
->adapter
->gl_info
.limits
.texture_stages
; ++i
)
4414 if (This
->updateStateBlock
->state
.texture_states
[i
][WINED3DTSS_COLOROP
] == WINED3DTOP_DISABLE
)
4416 TRACE("Additionally dirtifying stage %u due to enable\n", i
);
4417 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4419 This
->stateBlock
->state
.lowest_disabled_stage
= i
;
4420 TRACE("New lowest disabled: %u\n", i
);
4424 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, Type
));
4429 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
*pValue
)
4431 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4433 TRACE("iface %p, stage %u, state %s, value %p.\n",
4434 iface
, Stage
, debug_d3dtexturestate(Type
), pValue
);
4436 if (Type
> WINED3D_HIGHEST_TEXTURE_STATE
)
4438 WARN("Invalid Type %d passed.\n", Type
);
4442 *pValue
= This
->updateStateBlock
->state
.texture_states
[Stage
][Type
];
4443 TRACE("Returning %#x.\n", *pValue
);
4451 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
,
4452 DWORD stage
, IWineD3DBaseTexture
*texture
)
4454 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4455 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
4456 IWineD3DBaseTexture
*prev
;
4458 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4460 if (stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& stage
<= WINED3DVERTEXTEXTURESAMPLER3
)
4461 stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4463 /* Windows accepts overflowing this array... we do not. */
4464 if (stage
>= sizeof(This
->stateBlock
->state
.textures
) / sizeof(*This
->stateBlock
->state
.textures
))
4466 WARN("Ignoring invalid stage %u.\n", stage
);
4470 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4471 if (texture
&& ((IWineD3DTextureImpl
*)texture
)->resource
.pool
== WINED3DPOOL_SCRATCH
)
4473 WARN("Rejecting attempt to set scratch texture.\n");
4474 return WINED3DERR_INVALIDCALL
;
4477 This
->updateStateBlock
->changed
.textures
|= 1 << stage
;
4479 prev
= (IWineD3DBaseTexture
*)This
->updateStateBlock
->state
.textures
[stage
];
4480 TRACE("Previous texture %p.\n", prev
);
4482 if (texture
== prev
)
4484 TRACE("App is setting the same texture again, nothing to do.\n");
4488 TRACE("Setting new texture to %p.\n", texture
);
4489 This
->updateStateBlock
->state
.textures
[stage
] = (IWineD3DBaseTextureImpl
*)texture
;
4491 if (This
->isRecordingState
)
4493 TRACE("Recording... not performing anything\n");
4495 if (texture
) IWineD3DBaseTexture_AddRef(texture
);
4496 if (prev
) IWineD3DBaseTexture_Release(prev
);
4503 IWineD3DBaseTextureImpl
*t
= (IWineD3DBaseTextureImpl
*)texture
;
4504 LONG bind_count
= InterlockedIncrement(&t
->baseTexture
.bindCount
);
4505 GLenum dimensions
= t
->baseTexture
.target
;
4507 IWineD3DBaseTexture_AddRef(texture
);
4509 if (!prev
|| dimensions
!= ((IWineD3DBaseTextureImpl
*)prev
)->baseTexture
.target
)
4510 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
4512 if (!prev
&& stage
< gl_info
->limits
.texture_stages
)
4514 /* The source arguments for color and alpha ops have different
4515 * meanings when a NULL texture is bound, so the COLOROP and
4516 * ALPHAOP have to be dirtified. */
4517 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_COLOROP
));
4518 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_ALPHAOP
));
4521 if (bind_count
== 1) t
->baseTexture
.sampler
= stage
;
4526 IWineD3DBaseTextureImpl
*t
= (IWineD3DBaseTextureImpl
*)prev
;
4527 LONG bind_count
= InterlockedDecrement(&t
->baseTexture
.bindCount
);
4529 IWineD3DBaseTexture_Release(prev
);
4531 if (!texture
&& stage
< gl_info
->limits
.texture_stages
)
4533 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_COLOROP
));
4534 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_ALPHAOP
));
4537 if (bind_count
&& t
->baseTexture
.sampler
== stage
)
4541 /* Search for other stages the texture is bound to. Shouldn't
4542 * happen if applications bind textures to a single stage only. */
4543 TRACE("Searching for other stages the texture is bound to.\n");
4544 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
4546 if (This
->updateStateBlock
->state
.textures
[i
] == t
)
4548 TRACE("Texture is also bound to stage %u.\n", i
);
4549 t
->baseTexture
.sampler
= i
;
4556 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(stage
));
4561 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
, DWORD Stage
, IWineD3DBaseTexture
** ppTexture
) {
4562 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4564 TRACE("(%p) : Stage %#x, ppTexture %p\n", This
, Stage
, ppTexture
);
4566 if (Stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& Stage
<= WINED3DVERTEXTEXTURESAMPLER3
) {
4567 Stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4570 if (Stage
>= sizeof(This
->stateBlock
->state
.textures
) / sizeof(*This
->stateBlock
->state
.textures
))
4572 ERR("Current stage overflows textures array (stage %d)\n", Stage
);
4573 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
4576 *ppTexture
= (IWineD3DBaseTexture
*)This
->stateBlock
->state
.textures
[Stage
];
4578 IWineD3DBaseTexture_AddRef(*ppTexture
);
4580 TRACE("(%p) : Returning %p\n", This
, *ppTexture
);
4588 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT swapchain_idx
,
4589 UINT backbuffer_idx
, WINED3DBACKBUFFER_TYPE backbuffer_type
, IWineD3DSurface
**backbuffer
)
4591 IWineD3DSwapChain
*swapchain
;
4594 TRACE("iface %p, swapchain_idx %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
4595 iface
, swapchain_idx
, backbuffer_idx
, backbuffer_type
, backbuffer
);
4597 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
4600 WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx
, hr
);
4604 hr
= IWineD3DSwapChain_GetBackBuffer(swapchain
, backbuffer_idx
, backbuffer_type
, backbuffer
);
4605 IWineD3DSwapChain_Release(swapchain
);
4608 WARN("Failed to get backbuffer %u, hr %#x.\n", backbuffer_idx
, hr
);
4615 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
*caps
)
4617 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
4619 TRACE("iface %p, caps %p.\n", iface
, caps
);
4621 return wined3d_get_device_caps(device
->wined3d
, device
->adapter
->ordinal
, device
->devType
, caps
);
4624 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DDISPLAYMODE
* pMode
) {
4625 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4626 IWineD3DSwapChain
*swapChain
;
4629 if(iSwapChain
> 0) {
4630 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapChain
);
4631 if (hr
== WINED3D_OK
) {
4632 hr
= IWineD3DSwapChain_GetDisplayMode(swapChain
, pMode
);
4633 IWineD3DSwapChain_Release(swapChain
);
4635 FIXME("(%p) Error getting display mode\n", This
);
4638 /* Don't read the real display mode,
4639 but return the stored mode instead. X11 can't change the color
4640 depth, and some apps are pretty angry if they SetDisplayMode from
4641 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4643 Also don't relay to the swapchain because with ddraw it's possible
4644 that there isn't a swapchain at all */
4645 pMode
->Width
= This
->ddraw_width
;
4646 pMode
->Height
= This
->ddraw_height
;
4647 pMode
->Format
= This
->ddraw_format
;
4648 pMode
->RefreshRate
= 0;
4656 * Stateblock related functions
4659 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
)
4661 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4662 struct wined3d_stateblock
*stateblock
;
4665 TRACE("(%p)\n", This
);
4667 if (This
->isRecordingState
) return WINED3DERR_INVALIDCALL
;
4669 hr
= IWineD3DDeviceImpl_CreateStateBlock(iface
, WINED3DSBT_RECORDED
, &stateblock
);
4670 if (FAILED(hr
)) return hr
;
4672 wined3d_stateblock_decref(This
->updateStateBlock
);
4673 This
->updateStateBlock
= stateblock
;
4674 This
->isRecordingState
= TRUE
;
4676 TRACE("(%p) recording stateblock %p\n", This
, stateblock
);
4681 static HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
,
4682 struct wined3d_stateblock
**stateblock
)
4684 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4685 struct wined3d_stateblock
*object
= This
->updateStateBlock
;
4687 TRACE("iface %p, stateblock %p.\n", iface
, stateblock
);
4689 if (!This
->isRecordingState
) {
4690 WARN("(%p) not recording! returning error\n", This
);
4692 return WINED3DERR_INVALIDCALL
;
4695 stateblock_init_contained_states(object
);
4697 *stateblock
= object
;
4698 This
->isRecordingState
= FALSE
;
4699 This
->updateStateBlock
= This
->stateBlock
;
4700 wined3d_stateblock_incref(This
->updateStateBlock
);
4702 TRACE("Returning stateblock %p.\n", *stateblock
);
4708 * Scene related functions
4710 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
4711 /* At the moment we have no need for any functionality at the beginning
4713 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4714 TRACE("(%p)\n", This
);
4717 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4718 return WINED3DERR_INVALIDCALL
;
4720 This
->inScene
= TRUE
;
4724 static HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
)
4726 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4727 struct wined3d_context
*context
;
4729 TRACE("(%p)\n", This
);
4731 if(!This
->inScene
) {
4732 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4733 return WINED3DERR_INVALIDCALL
;
4736 context
= context_acquire(This
, NULL
);
4737 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4739 /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4741 context_release(context
);
4743 This
->inScene
= FALSE
;
4747 static HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
,
4748 const RECT
*pSourceRect
, const RECT
*pDestRect
,
4749 HWND hDestWindowOverride
, const RGNDATA
*pDirtyRegion
)
4751 IWineD3DSwapChain
*swapChain
= NULL
;
4753 int swapchains
= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface
);
4755 TRACE("iface %p.\n", iface
);
4757 for(i
= 0 ; i
< swapchains
; i
++) {
4759 IWineD3DDeviceImpl_GetSwapChain(iface
, i
, &swapChain
);
4760 TRACE("Presenting chain %d, %p.\n", i
, swapChain
);
4761 IWineD3DSwapChain_Present(swapChain
, pSourceRect
, pDestRect
, hDestWindowOverride
, pDirtyRegion
, 0);
4762 IWineD3DSwapChain_Release(swapChain
);
4768 /* Do not call while under the GL lock. */
4769 static HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD rect_count
,
4770 const RECT
*rects
, DWORD flags
, WINED3DCOLOR color
, float depth
, DWORD stencil
)
4772 const WINED3DCOLORVALUE c
= {D3DCOLOR_R(color
), D3DCOLOR_G(color
), D3DCOLOR_B(color
), D3DCOLOR_A(color
)};
4773 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
4776 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, depth %.8e, stencil %u.\n",
4777 iface
, rect_count
, rects
, flags
, color
, depth
, stencil
);
4779 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
) && !device
->depth_stencil
)
4781 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4782 /* TODO: What about depth stencil buffers without stencil bits? */
4783 return WINED3DERR_INVALIDCALL
;
4786 device_get_draw_rect(device
, &draw_rect
);
4788 return device_clear_render_targets(device
, device
->adapter
->gl_info
.limits
.buffers
,
4789 device
->render_targets
, rect_count
, rects
, &draw_rect
, flags
, &c
, depth
, stencil
);
4796 static void WINAPI
IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice
*iface
,
4797 WINED3DPRIMITIVETYPE primitive_type
)
4799 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4801 TRACE("iface %p, primitive_type %s\n", iface
, debug_d3dprimitivetype(primitive_type
));
4803 This
->updateStateBlock
->changed
.primitive_type
= TRUE
;
4804 This
->updateStateBlock
->state
.gl_primitive_type
= gl_primitive_type_from_d3d(primitive_type
);
4807 static void WINAPI
IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice
*iface
,
4808 WINED3DPRIMITIVETYPE
*primitive_type
)
4810 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4812 TRACE("iface %p, primitive_type %p\n", iface
, primitive_type
);
4814 *primitive_type
= d3d_primitive_type_from_gl(This
->stateBlock
->state
.gl_primitive_type
);
4816 TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type
));
4819 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, UINT StartVertex
, UINT vertex_count
)
4821 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4823 TRACE("(%p) : start %u, count %u\n", This
, StartVertex
, vertex_count
);
4825 if (!This
->stateBlock
->state
.vertex_declaration
)
4827 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4828 return WINED3DERR_INVALIDCALL
;
4831 /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4832 if (This
->stateBlock
->state
.user_stream
)
4834 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4835 This
->stateBlock
->state
.user_stream
= FALSE
;
4838 if (This
->stateBlock
->state
.load_base_vertex_index
)
4840 This
->stateBlock
->state
.load_base_vertex_index
= 0;
4841 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4843 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4844 drawPrimitive(This
, vertex_count
, StartVertex
/* start_idx */, 0 /* indxSize */, NULL
/* indxData */);
4848 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
, UINT startIndex
, UINT index_count
)
4850 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4851 struct wined3d_buffer
*index_buffer
;
4855 index_buffer
= This
->stateBlock
->state
.index_buffer
;
4858 /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4859 * without an index buffer set. (The first time at least...)
4860 * D3D8 simply dies, but I doubt it can do much harm to return
4861 * D3DERR_INVALIDCALL there as well. */
4862 WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This
);
4863 return WINED3DERR_INVALIDCALL
;
4866 if (!This
->stateBlock
->state
.vertex_declaration
)
4868 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4869 return WINED3DERR_INVALIDCALL
;
4872 if (This
->stateBlock
->state
.user_stream
)
4874 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4875 This
->stateBlock
->state
.user_stream
= FALSE
;
4877 vbo
= index_buffer
->buffer_object
;
4879 TRACE("(%p) : startIndex %u, index count %u.\n", This
, startIndex
, index_count
);
4881 if (This
->stateBlock
->state
.index_format
== WINED3DFMT_R16_UINT
)
4886 if (This
->stateBlock
->state
.load_base_vertex_index
!= This
->stateBlock
->state
.base_vertex_index
)
4888 This
->stateBlock
->state
.load_base_vertex_index
= This
->stateBlock
->state
.base_vertex_index
;
4889 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4892 drawPrimitive(This
, index_count
, startIndex
, idxStride
,
4893 vbo
? NULL
: index_buffer
->resource
.allocatedMemory
);
4898 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, UINT vertex_count
,
4899 const void *pVertexStreamZeroData
, UINT VertexStreamZeroStride
)
4901 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4902 struct wined3d_stream_state
*stream
;
4905 TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4906 This
, vertex_count
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4908 if (!This
->stateBlock
->state
.vertex_declaration
)
4910 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4911 return WINED3DERR_INVALIDCALL
;
4914 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4915 stream
= &This
->stateBlock
->state
.streams
[0];
4916 vb
= (IWineD3DBuffer
*)stream
->buffer
;
4917 stream
->buffer
= (struct wined3d_buffer
*)pVertexStreamZeroData
;
4918 if (vb
) IWineD3DBuffer_Release(vb
);
4920 stream
->stride
= VertexStreamZeroStride
;
4921 This
->stateBlock
->state
.user_stream
= TRUE
;
4922 This
->stateBlock
->state
.load_base_vertex_index
= 0;
4924 /* TODO: Only mark dirty if drawing from a different UP address */
4925 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4927 drawPrimitive(This
, vertex_count
, 0 /* start_idx */, 0 /* indxSize*/, NULL
/* indxData */);
4929 /* MSDN specifies stream zero settings must be set to NULL */
4930 stream
->buffer
= NULL
;
4933 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4934 * the new stream sources or use UP drawing again
4939 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
,
4940 UINT index_count
, const void *pIndexData
, enum wined3d_format_id IndexDataFormat
,
4941 const void *pVertexStreamZeroData
, UINT VertexStreamZeroStride
)
4944 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4945 struct wined3d_stream_state
*stream
;
4949 TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4950 This
, index_count
, pIndexData
, IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4952 if (!This
->stateBlock
->state
.vertex_declaration
)
4954 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4955 return WINED3DERR_INVALIDCALL
;
4958 if (IndexDataFormat
== WINED3DFMT_R16_UINT
) {
4964 stream
= &This
->stateBlock
->state
.streams
[0];
4965 vb
= (IWineD3DBuffer
*)stream
->buffer
;
4966 stream
->buffer
= (struct wined3d_buffer
*)pVertexStreamZeroData
;
4967 if (vb
) IWineD3DBuffer_Release(vb
);
4969 stream
->stride
= VertexStreamZeroStride
;
4970 This
->stateBlock
->state
.user_stream
= TRUE
;
4972 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4973 This
->stateBlock
->state
.base_vertex_index
= 0;
4974 This
->stateBlock
->state
.load_base_vertex_index
= 0;
4975 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4976 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
4977 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4979 drawPrimitive(This
, index_count
, 0 /* start_idx */, idxStride
, pIndexData
);
4981 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4982 stream
->buffer
= NULL
;
4984 ib
= (IWineD3DBuffer
*)This
->stateBlock
->state
.index_buffer
;
4987 IWineD3DBuffer_Release(ib
);
4988 This
->stateBlock
->state
.index_buffer
= NULL
;
4990 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4991 * SetStreamSource to specify a vertex buffer
4997 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice
*iface
,
4998 UINT vertex_count
, const WineDirect3DVertexStridedData
*DrawPrimStrideData
)
5000 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5002 /* Mark the state dirty until we have nicer tracking
5003 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5006 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5007 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5008 This
->stateBlock
->state
.base_vertex_index
= 0;
5009 This
->up_strided
= DrawPrimStrideData
;
5010 drawPrimitive(This
, vertex_count
, 0, 0, NULL
);
5011 This
->up_strided
= NULL
;
5015 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice
*iface
,
5016 UINT vertex_count
, const WineDirect3DVertexStridedData
*DrawPrimStrideData
,
5017 UINT NumVertices
, const void *pIndexData
, enum wined3d_format_id IndexDataFormat
)
5019 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5020 DWORD idxSize
= (IndexDataFormat
== WINED3DFMT_R32_UINT
? 4 : 2);
5022 /* Mark the state dirty until we have nicer tracking
5023 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5026 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5027 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5028 This
->stateBlock
->state
.user_stream
= TRUE
;
5029 This
->stateBlock
->state
.base_vertex_index
= 0;
5030 This
->up_strided
= DrawPrimStrideData
;
5031 drawPrimitive(This
, vertex_count
, 0 /* start_idx */, idxSize
, pIndexData
);
5032 This
->up_strided
= NULL
;
5036 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
5037 static HRESULT
IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice
*iface
,
5038 IWineD3DVolume
*pSourceVolume
, IWineD3DVolume
*pDestinationVolume
)
5040 WINED3DLOCKED_BOX src
;
5041 WINED3DLOCKED_BOX dst
;
5044 TRACE("iface %p, src_volume %p, dst_volume %p.\n",
5045 iface
, pSourceVolume
, pDestinationVolume
);
5047 /* TODO: Implement direct loading into the gl volume instead of using memcpy and
5048 * dirtification to improve loading performance.
5050 hr
= IWineD3DVolume_Map(pSourceVolume
, &src
, NULL
, WINED3DLOCK_READONLY
);
5051 if (FAILED(hr
)) return hr
;
5052 hr
= IWineD3DVolume_Map(pDestinationVolume
, &dst
, NULL
, WINED3DLOCK_DISCARD
);
5055 IWineD3DVolume_Unmap(pSourceVolume
);
5059 memcpy(dst
.pBits
, src
.pBits
, ((IWineD3DVolumeImpl
*) pDestinationVolume
)->resource
.size
);
5061 hr
= IWineD3DVolume_Unmap(pDestinationVolume
);
5063 IWineD3DVolume_Unmap(pSourceVolume
);
5065 hr
= IWineD3DVolume_Unmap(pSourceVolume
);
5070 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice
*iface
,
5071 IWineD3DBaseTexture
*src_texture
, IWineD3DBaseTexture
*dst_texture
)
5073 unsigned int level_count
, i
;
5074 WINED3DRESOURCETYPE type
;
5077 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface
, src_texture
, dst_texture
);
5079 /* Verify that the source and destination textures are non-NULL. */
5080 if (!src_texture
|| !dst_texture
)
5082 WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
5083 return WINED3DERR_INVALIDCALL
;
5086 if (src_texture
== dst_texture
)
5088 WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
5089 return WINED3DERR_INVALIDCALL
;
5092 /* Verify that the source and destination textures are the same type. */
5093 type
= IWineD3DBaseTexture_GetType(src_texture
);
5094 if (IWineD3DBaseTexture_GetType(dst_texture
) != type
)
5096 WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
5097 return WINED3DERR_INVALIDCALL
;
5100 /* Check that both textures have the identical numbers of levels. */
5101 level_count
= IWineD3DBaseTexture_GetLevelCount(src_texture
);
5102 if (IWineD3DBaseTexture_GetLevelCount(dst_texture
) != level_count
)
5104 WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
5105 return WINED3DERR_INVALIDCALL
;
5108 /* Make sure that the destination texture is loaded. */
5109 ((IWineD3DBaseTextureImpl
*)dst_texture
)->baseTexture
.texture_ops
->texture_preload(
5110 (IWineD3DBaseTextureImpl
*)dst_texture
, SRGB_RGB
);
5112 /* Update every surface level of the texture. */
5115 case WINED3DRTYPE_TEXTURE
:
5117 IWineD3DSurface
*src_surface
;
5118 IWineD3DSurface
*dst_surface
;
5120 for (i
= 0; i
< level_count
; ++i
)
5122 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)src_texture
, i
, &src_surface
);
5123 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture
*)dst_texture
, i
, &dst_surface
);
5124 hr
= IWineD3DDevice_UpdateSurface(iface
, src_surface
, NULL
, dst_surface
, NULL
);
5125 IWineD3DSurface_Release(dst_surface
);
5126 IWineD3DSurface_Release(src_surface
);
5129 WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr
);
5136 case WINED3DRTYPE_CUBETEXTURE
:
5138 IWineD3DSurface
*src_surface
;
5139 IWineD3DSurface
*dst_surface
;
5141 for (i
= 0; i
< level_count
* 6; ++i
)
5143 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)src_texture
, i
, &src_surface
);
5144 if (FAILED(hr
)) ERR("Failed to get src cube sub-resource %u, hr %#x.\n", i
, hr
);
5145 hr
= IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture
*)dst_texture
, i
, &dst_surface
);
5146 if (FAILED(hr
)) ERR("Failed to get dst cube sub-resource %u, hr %#x.\n", i
, hr
);
5147 hr
= IWineD3DDevice_UpdateSurface(iface
, src_surface
, NULL
, dst_surface
, NULL
);
5148 IWineD3DSurface_Release(dst_surface
);
5149 IWineD3DSurface_Release(src_surface
);
5152 WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr
);
5159 case WINED3DRTYPE_VOLUMETEXTURE
:
5161 IWineD3DVolume
*src_volume
;
5162 IWineD3DVolume
*dst_volume
;
5164 for (i
= 0; i
< level_count
; ++i
)
5166 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)src_texture
, i
, &src_volume
);
5167 IWineD3DVolumeTexture_GetVolumeLevel((IWineD3DVolumeTexture
*)dst_texture
, i
, &dst_volume
);
5168 hr
= IWineD3DDeviceImpl_UpdateVolume(iface
, src_volume
, dst_volume
);
5169 IWineD3DVolume_Release(dst_volume
);
5170 IWineD3DVolume_Release(src_volume
);
5173 WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr
);
5181 FIXME("Unsupported texture type %#x.\n", type
);
5182 return WINED3DERR_INVALIDCALL
;
5188 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,
5189 UINT swapchain_idx
, IWineD3DSurface
*dst_surface
)
5191 IWineD3DSwapChain
*swapchain
;
5194 TRACE("iface %p, swapchain_idx %u, dst_surface %p.\n", iface
, swapchain_idx
, dst_surface
);
5196 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
5197 if (FAILED(hr
)) return hr
;
5199 hr
= IWineD3DSwapChain_GetFrontBufferData(swapchain
, dst_surface
);
5200 IWineD3DSwapChain_Release(swapchain
);
5205 static HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
* pNumPasses
) {
5206 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5207 IWineD3DBaseTextureImpl
*texture
;
5210 TRACE("(%p) : %p\n", This
, pNumPasses
);
5212 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
5214 if (This
->stateBlock
->state
.sampler_states
[i
][WINED3DSAMP_MINFILTER
] == WINED3DTEXF_NONE
)
5216 WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
5217 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
5219 if (This
->stateBlock
->state
.sampler_states
[i
][WINED3DSAMP_MAGFILTER
] == WINED3DTEXF_NONE
)
5221 WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
5222 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
5225 texture
= This
->stateBlock
->state
.textures
[i
];
5226 if (!texture
|| texture
->resource
.format
->flags
& WINED3DFMT_FLAG_FILTERING
) continue;
5228 if (This
->stateBlock
->state
.sampler_states
[i
][WINED3DSAMP_MAGFILTER
] != WINED3DTEXF_POINT
)
5230 WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i
);
5233 if (This
->stateBlock
->state
.sampler_states
[i
][WINED3DSAMP_MINFILTER
] != WINED3DTEXF_POINT
)
5235 WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i
);
5238 if (This
->stateBlock
->state
.sampler_states
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_NONE
5239 && This
->stateBlock
->state
.sampler_states
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_POINT
)
5241 WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i
);
5246 /* return a sensible default */
5249 TRACE("returning D3D_OK\n");
5253 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl
*device
)
5257 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
5259 IWineD3DBaseTextureImpl
*texture
= device
->stateBlock
->state
.textures
[i
];
5260 if (texture
&& (texture
->resource
.format
->id
== WINED3DFMT_P8_UINT
5261 || texture
->resource
.format
->id
== WINED3DFMT_P8_UINT_A8_UNORM
))
5263 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_SAMPLER(i
));
5268 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, CONST PALETTEENTRY
* pEntries
) {
5269 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5272 PALETTEENTRY
**palettes
;
5274 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5276 if (PaletteNumber
>= MAX_PALETTES
) {
5277 ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
5278 return WINED3DERR_INVALIDCALL
;
5281 if (PaletteNumber
>= This
->NumberOfPalettes
) {
5282 NewSize
= This
->NumberOfPalettes
;
5285 } while(PaletteNumber
>= NewSize
);
5286 palettes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->palettes
, sizeof(PALETTEENTRY
*) * NewSize
);
5288 ERR("Out of memory!\n");
5289 return E_OUTOFMEMORY
;
5291 This
->palettes
= palettes
;
5292 This
->NumberOfPalettes
= NewSize
;
5295 if (!This
->palettes
[PaletteNumber
]) {
5296 This
->palettes
[PaletteNumber
] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
5297 if (!This
->palettes
[PaletteNumber
]) {
5298 ERR("Out of memory!\n");
5299 return E_OUTOFMEMORY
;
5303 for (j
= 0; j
< 256; ++j
) {
5304 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
5305 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
5306 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
5307 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
5309 if (PaletteNumber
== This
->currentPalette
) dirtify_p8_texture_samplers(This
);
5310 TRACE("(%p) : returning\n", This
);
5314 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
, UINT PaletteNumber
, PALETTEENTRY
* pEntries
) {
5315 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5317 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5318 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
5319 /* What happens in such situation isn't documented; Native seems to silently abort
5320 on such conditions. Return Invalid Call. */
5321 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
5322 return WINED3DERR_INVALIDCALL
;
5324 for (j
= 0; j
< 256; ++j
) {
5325 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
5326 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
5327 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
5328 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
5330 TRACE("(%p) : returning\n", This
);
5334 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
) {
5335 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5336 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5337 /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5338 (tested with reference rasterizer). Return Invalid Call. */
5339 if (PaletteNumber
>= This
->NumberOfPalettes
|| !This
->palettes
[PaletteNumber
]) {
5340 ERR("(%p) : (%u) Nonexistent palette. NumberOfPalettes %u\n", This
, PaletteNumber
, This
->NumberOfPalettes
);
5341 return WINED3DERR_INVALIDCALL
;
5343 /*TODO: stateblocks */
5344 if (This
->currentPalette
!= PaletteNumber
) {
5345 This
->currentPalette
= PaletteNumber
;
5346 dirtify_p8_texture_samplers(This
);
5348 TRACE("(%p) : returning\n", This
);
5352 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
5353 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5357 WARN("(%p) : returning Invalid Call\n", This
);
5358 return WINED3DERR_INVALIDCALL
;
5360 /*TODO: stateblocks */
5361 *PaletteNumber
= This
->currentPalette
;
5362 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
5366 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
5367 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5371 FIXME("(%p) : stub\n", This
);
5375 This
->softwareVertexProcessing
= bSoftware
;
5380 static BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
5381 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5385 FIXME("(%p) : stub\n", This
);
5388 return This
->softwareVertexProcessing
;
5391 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
,
5392 UINT swapchain_idx
, WINED3DRASTER_STATUS
*raster_status
)
5394 IWineD3DSwapChain
*swapchain
;
5397 TRACE("iface %p, swapchain_idx %u, raster_status %p.\n",
5398 iface
, swapchain_idx
, raster_status
);
5400 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
5403 WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx
, hr
);
5407 hr
= IWineD3DSwapChain_GetRasterStatus(swapchain
, raster_status
);
5408 IWineD3DSwapChain_Release(swapchain
);
5411 WARN("Failed to get raster status, hr %#x.\n", hr
);
5418 static HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
)
5421 if(nSegments
!= 0.0f
) {
5424 FIXME("iface %p, nSegments %.8e stub!\n", iface
, nSegments
);
5431 static float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
)
5436 FIXME("iface %p stub!\n", iface
);
5442 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
,
5443 IWineD3DSurface
*src_surface
, const RECT
*src_rect
,
5444 IWineD3DSurface
*dst_surface
, const POINT
*dst_point
)
5446 IWineD3DSurfaceImpl
*src_impl
= (IWineD3DSurfaceImpl
*)src_surface
;
5447 IWineD3DSurfaceImpl
*dst_impl
= (IWineD3DSurfaceImpl
*)dst_surface
;
5448 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5449 const struct wined3d_format
*src_format
;
5450 const struct wined3d_format
*dst_format
;
5451 const struct wined3d_gl_info
*gl_info
;
5452 struct wined3d_context
*context
;
5453 const unsigned char *data
;
5454 UINT update_w
, update_h
;
5455 CONVERT_TYPES convert
;
5459 struct wined3d_format format
;
5461 TRACE("iface %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
5462 iface
, src_surface
, wine_dbgstr_rect(src_rect
),
5463 dst_surface
, wine_dbgstr_point(dst_point
));
5465 if (src_impl
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
|| dst_impl
->resource
.pool
!= WINED3DPOOL_DEFAULT
)
5467 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n",
5468 src_surface
, dst_surface
);
5469 return WINED3DERR_INVALIDCALL
;
5472 src_format
= src_impl
->resource
.format
;
5473 dst_format
= dst_impl
->resource
.format
;
5475 if (src_format
->id
!= dst_format
->id
)
5477 WARN("Source and destination surfaces should have the same format.\n");
5478 return WINED3DERR_INVALIDCALL
;
5481 dst_x
= dst_point
? dst_point
->x
: 0;
5482 dst_y
= dst_point
? dst_point
->y
: 0;
5484 /* This call loads the OpenGL surface directly, instead of copying the
5485 * surface to the destination's sysmem copy. If surface conversion is
5486 * needed, use BltFast instead to copy in sysmem and use regular surface
5488 d3dfmt_get_conv(dst_impl
, FALSE
, TRUE
, &format
, &convert
);
5489 if (convert
!= NO_CONVERSION
|| format
.convert
)
5490 return IWineD3DSurface_BltFast(dst_surface
, dst_x
, dst_y
, src_surface
, src_rect
, 0);
5492 context
= context_acquire(This
, NULL
);
5493 gl_info
= context
->gl_info
;
5496 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
5497 checkGLcall("glActiveTextureARB");
5500 /* Make sure the surface is loaded and up to date */
5501 surface_internal_preload(dst_impl
, SRGB_RGB
);
5502 surface_bind(dst_impl
, FALSE
);
5504 src_w
= src_impl
->currentDesc
.Width
;
5505 src_h
= src_impl
->currentDesc
.Height
;
5506 update_w
= src_rect
? src_rect
->right
- src_rect
->left
: src_w
;
5507 update_h
= src_rect
? src_rect
->bottom
- src_rect
->top
: src_h
;
5509 data
= src_impl
->resource
.allocatedMemory
;
5510 if (!data
) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n");
5514 if (dst_format
->flags
& WINED3DFMT_FLAG_COMPRESSED
)
5516 UINT row_length
= wined3d_format_calculate_size(src_format
, 1, update_w
, 1);
5517 UINT row_count
= (update_h
+ src_format
->block_height
- 1) / src_format
->block_height
;
5518 UINT src_pitch
= wined3d_format_calculate_size(src_format
, 1, src_w
, 1);
5522 data
+= (src_rect
->top
/ src_format
->block_height
) * src_pitch
;
5523 data
+= (src_rect
->left
/ src_format
->block_width
) * src_format
->block_byte_count
;
5526 TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
5527 "format %#x, image_size %#x, data %p.\n", dst_impl
->texture_target
, dst_impl
->texture_level
,
5528 dst_x
, dst_y
, update_w
, update_h
, dst_format
->glFormat
, row_count
* row_length
, data
);
5530 if (row_length
== src_pitch
)
5532 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl
->texture_target
, dst_impl
->texture_level
,
5533 dst_x
, dst_y
, update_w
, update_h
, dst_format
->glInternal
, row_count
* row_length
, data
));
5539 /* glCompressedTexSubImage2DARB() ignores pixel store state, so we
5540 * can't use the unpack row length like below. */
5541 for (row
= 0, y
= dst_y
; row
< row_count
; ++row
)
5543 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_impl
->texture_target
, dst_impl
->texture_level
,
5544 dst_x
, y
, update_w
, src_format
->block_height
, dst_format
->glInternal
, row_length
, data
));
5545 y
+= src_format
->block_height
;
5549 checkGLcall("glCompressedTexSubImage2DARB");
5555 data
+= src_rect
->top
* src_w
* src_format
->byte_count
;
5556 data
+= src_rect
->left
* src_format
->byte_count
;
5559 TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n",
5560 dst_impl
->texture_target
, dst_impl
->texture_level
, dst_x
, dst_y
,
5561 update_w
, update_h
, dst_format
->glFormat
, dst_format
->glType
, data
);
5563 glPixelStorei(GL_UNPACK_ROW_LENGTH
, src_w
);
5564 glTexSubImage2D(dst_impl
->texture_target
, dst_impl
->texture_level
, dst_x
, dst_y
,
5565 update_w
, update_h
, dst_format
->glFormat
, dst_format
->glType
, data
);
5566 glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
5567 checkGLcall("glTexSubImage2D");
5571 context_release(context
);
5573 surface_modify_location(dst_impl
, SFLAG_INTEXTURE
, TRUE
);
5574 sampler
= This
->rev_tex_unit_map
[0];
5575 if (sampler
!= WINED3D_UNMAPPED_STAGE
)
5577 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
5583 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DRECTPATCH_INFO
* pRectPatchInfo
) {
5584 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5585 struct WineD3DRectPatch
*patch
;
5586 GLenum old_primitive_type
;
5590 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
5592 if(!(Handle
|| pRectPatchInfo
)) {
5593 /* TODO: Write a test for the return value, thus the FIXME */
5594 FIXME("Both Handle and pRectPatchInfo are NULL\n");
5595 return WINED3DERR_INVALIDCALL
;
5599 i
= PATCHMAP_HASHFUNC(Handle
);
5601 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
5602 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
5603 if(patch
->Handle
== Handle
) {
5610 TRACE("Patch does not exist. Creating a new one\n");
5611 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5612 patch
->Handle
= Handle
;
5613 list_add_head(&This
->patches
[i
], &patch
->entry
);
5615 TRACE("Found existing patch %p\n", patch
);
5618 /* Since opengl does not load tesselated vertex attributes into numbered vertex
5619 * attributes we have to tesselate, read back, and draw. This needs a patch
5620 * management structure instance. Create one.
5622 * A possible improvement is to check if a vertex shader is used, and if not directly
5625 FIXME("Drawing an uncached patch. This is slow\n");
5626 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5629 if (pNumSegs
[0] != patch
->numSegs
[0] || pNumSegs
[1] != patch
->numSegs
[1]
5630 || pNumSegs
[2] != patch
->numSegs
[2] || pNumSegs
[3] != patch
->numSegs
[3]
5631 || (pRectPatchInfo
&& memcmp(pRectPatchInfo
, &patch
->RectPatchInfo
, sizeof(*pRectPatchInfo
))))
5634 TRACE("Tesselation density or patch info changed, retesselating\n");
5636 if(pRectPatchInfo
) {
5637 patch
->RectPatchInfo
= *pRectPatchInfo
;
5639 patch
->numSegs
[0] = pNumSegs
[0];
5640 patch
->numSegs
[1] = pNumSegs
[1];
5641 patch
->numSegs
[2] = pNumSegs
[2];
5642 patch
->numSegs
[3] = pNumSegs
[3];
5644 hr
= tesselate_rectpatch(This
, patch
);
5646 WARN("Patch tesselation failed\n");
5648 /* Do not release the handle to store the params of the patch */
5650 HeapFree(GetProcessHeap(), 0, patch
);
5656 This
->currentPatch
= patch
;
5657 old_primitive_type
= This
->stateBlock
->state
.gl_primitive_type
;
5658 This
->stateBlock
->state
.gl_primitive_type
= GL_TRIANGLES
;
5659 IWineD3DDevice_DrawPrimitiveStrided(iface
, patch
->numSegs
[0] * patch
->numSegs
[1] * 2 * 3, &patch
->strided
);
5660 This
->stateBlock
->state
.gl_primitive_type
= old_primitive_type
;
5661 This
->currentPatch
= NULL
;
5663 /* Destroy uncached patches */
5665 HeapFree(GetProcessHeap(), 0, patch
->mem
);
5666 HeapFree(GetProcessHeap(), 0, patch
);
5671 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
,
5672 UINT handle
, const float *segment_count
, const WINED3DTRIPATCH_INFO
*patch_info
)
5674 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p stub!\n",
5675 iface
, handle
, segment_count
, patch_info
);
5680 static HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
5681 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5683 struct WineD3DRectPatch
*patch
;
5685 TRACE("(%p) Handle(%d)\n", This
, Handle
);
5687 i
= PATCHMAP_HASHFUNC(Handle
);
5688 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
5689 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
5690 if(patch
->Handle
== Handle
) {
5691 TRACE("Deleting patch %p\n", patch
);
5692 list_remove(&patch
->entry
);
5693 HeapFree(GetProcessHeap(), 0, patch
->mem
);
5694 HeapFree(GetProcessHeap(), 0, patch
);
5699 /* TODO: Write a test for the return value */
5700 FIXME("Attempt to destroy nonexistent patch\n");
5701 return WINED3DERR_INVALIDCALL
;
5704 /* Do not call while under the GL lock. */
5705 static HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
,
5706 IWineD3DSurface
*surface
, const RECT
*rect
, const WINED3DCOLORVALUE
*color
)
5708 IWineD3DSurfaceImpl
*s
= (IWineD3DSurfaceImpl
*)surface
;
5710 TRACE("iface %p, surface %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
5711 iface
, surface
, wine_dbgstr_rect(rect
),
5712 color
->r
, color
->g
, color
->b
, color
->a
);
5714 if (s
->resource
.pool
!= WINED3DPOOL_DEFAULT
&& s
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
)
5716 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5717 return WINED3DERR_INVALIDCALL
;
5720 return surface_color_fill(s
, rect
, color
);
5723 /* Do not call while under the GL lock. */
5724 static void WINAPI
IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice
*iface
,
5725 IWineD3DRendertargetView
*rendertarget_view
, const WINED3DCOLORVALUE
*color
)
5727 struct wined3d_resource
*resource
;
5730 hr
= IWineD3DRendertargetView_GetResource(rendertarget_view
, &resource
);
5733 ERR("Failed to get resource, hr %#x\n", hr
);
5737 if (resource
->resourceType
!= WINED3DRTYPE_SURFACE
)
5739 FIXME("Only supported on surface resources\n");
5743 hr
= surface_color_fill(surface_from_resource(resource
), NULL
, color
);
5744 if (FAILED(hr
)) ERR("Color fill failed, hr %#x.\n", hr
);
5747 /* rendertarget and depth stencil functions */
5748 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
*iface
,
5749 DWORD render_target_idx
, IWineD3DSurface
**render_target
)
5751 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
5753 TRACE("iface %p, render_target_idx %u, render_target %p.\n",
5754 iface
, render_target_idx
, render_target
);
5756 if (render_target_idx
>= device
->adapter
->gl_info
.limits
.buffers
)
5758 WARN("Only %u render targets are supported.\n", device
->adapter
->gl_info
.limits
.buffers
);
5759 return WINED3DERR_INVALIDCALL
;
5762 *render_target
= (IWineD3DSurface
*)device
->render_targets
[render_target_idx
];
5763 if (*render_target
) IWineD3DSurface_AddRef(*render_target
);
5765 TRACE("Returning render target %p.\n", *render_target
);
5770 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
**depth_stencil
)
5772 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
5774 TRACE("iface %p, depth_stencil %p.\n", iface
, depth_stencil
);
5776 *depth_stencil
= (IWineD3DSurface
*)device
->depth_stencil
;
5777 TRACE("Returning depth/stencil surface %p.\n", *depth_stencil
);
5778 if (!*depth_stencil
) return WINED3DERR_NOTFOUND
;
5779 IWineD3DSurface_AddRef(*depth_stencil
);
5784 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
,
5785 DWORD render_target_idx
, IWineD3DSurface
*render_target
, BOOL set_viewport
)
5787 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
5788 IWineD3DSurfaceImpl
*prev
;
5790 TRACE("iface %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
5791 iface
, render_target_idx
, render_target
, set_viewport
);
5793 if (render_target_idx
>= device
->adapter
->gl_info
.limits
.buffers
)
5795 WARN("Only %u render targets are supported.\n", device
->adapter
->gl_info
.limits
.buffers
);
5796 return WINED3DERR_INVALIDCALL
;
5799 prev
= device
->render_targets
[render_target_idx
];
5800 if (render_target
== (IWineD3DSurface
*)prev
)
5802 TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5806 /* Render target 0 can't be set to NULL. */
5807 if (!render_target
&& !render_target_idx
)
5809 WARN("Trying to set render target 0 to NULL.\n");
5810 return WINED3DERR_INVALIDCALL
;
5813 if (render_target
&& !(((IWineD3DSurfaceImpl
*)render_target
)->resource
.usage
& WINED3DUSAGE_RENDERTARGET
))
5815 FIXME("Surface %p doesn't have render target usage.\n", render_target
);
5816 return WINED3DERR_INVALIDCALL
;
5819 if (render_target
) IWineD3DSurface_AddRef(render_target
);
5820 device
->render_targets
[render_target_idx
] = (IWineD3DSurfaceImpl
*)render_target
;
5821 /* Release after the assignment, to prevent device_resource_released()
5822 * from seeing the surface as still in use. */
5823 if (prev
) IWineD3DSurface_Release((IWineD3DSurface
*)prev
);
5825 /* Render target 0 is special. */
5826 if (!render_target_idx
&& set_viewport
)
5828 /* Set the viewport and scissor rectangles, if requested. Tests show
5829 * that stateblock recording is ignored, the change goes directly
5830 * into the primary stateblock. */
5831 device
->stateBlock
->state
.viewport
.Height
= device
->render_targets
[0]->currentDesc
.Height
;
5832 device
->stateBlock
->state
.viewport
.Width
= device
->render_targets
[0]->currentDesc
.Width
;
5833 device
->stateBlock
->state
.viewport
.X
= 0;
5834 device
->stateBlock
->state
.viewport
.Y
= 0;
5835 device
->stateBlock
->state
.viewport
.MaxZ
= 1.0f
;
5836 device
->stateBlock
->state
.viewport
.MinZ
= 0.0f
;
5837 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_VIEWPORT
);
5839 device
->stateBlock
->state
.scissor_rect
.top
= 0;
5840 device
->stateBlock
->state
.scissor_rect
.left
= 0;
5841 device
->stateBlock
->state
.scissor_rect
.right
= device
->stateBlock
->state
.viewport
.Width
;
5842 device
->stateBlock
->state
.scissor_rect
.bottom
= device
->stateBlock
->state
.viewport
.Height
;
5843 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_SCISSORRECT
);
5849 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
, IWineD3DSurface
*depth_stencil
)
5851 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5852 IWineD3DSurfaceImpl
*tmp
;
5854 TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n", This
, depth_stencil
, This
->depth_stencil
);
5856 if (This
->depth_stencil
== (IWineD3DSurfaceImpl
*)depth_stencil
)
5858 TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5862 if (This
->depth_stencil
)
5864 if (This
->swapchains
[0]->presentParms
.Flags
& WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
5865 || This
->depth_stencil
->flags
& SFLAG_DISCARD
)
5867 surface_modify_ds_location(This
->depth_stencil
, SFLAG_DS_DISCARDED
,
5868 This
->depth_stencil
->currentDesc
.Width
,
5869 This
->depth_stencil
->currentDesc
.Height
);
5870 if (This
->depth_stencil
== This
->onscreen_depth_stencil
)
5872 IWineD3DSurface_Release((IWineD3DSurface
*)This
->onscreen_depth_stencil
);
5873 This
->onscreen_depth_stencil
= NULL
;
5878 tmp
= This
->depth_stencil
;
5879 This
->depth_stencil
= (IWineD3DSurfaceImpl
*)depth_stencil
;
5880 if (This
->depth_stencil
) IWineD3DSurface_AddRef((IWineD3DSurface
*)This
->depth_stencil
);
5881 if (tmp
) IWineD3DSurface_Release((IWineD3DSurface
*)tmp
);
5883 if ((!tmp
&& depth_stencil
) || (!depth_stencil
&& tmp
))
5885 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5886 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZENABLE
));
5887 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILENABLE
));
5888 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILWRITEMASK
));
5894 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
*iface
,
5895 UINT XHotSpot
, UINT YHotSpot
, IWineD3DSurface
*cursor_image
)
5897 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5898 IWineD3DSurfaceImpl
*s
= (IWineD3DSurfaceImpl
*)cursor_image
;
5899 WINED3DLOCKED_RECT lockedRect
;
5901 TRACE("iface %p, hotspot_x %u, hotspot_y %u, cursor_image %p.\n",
5902 iface
, XHotSpot
, YHotSpot
, cursor_image
);
5904 /* some basic validation checks */
5905 if (This
->cursorTexture
)
5907 struct wined3d_context
*context
= context_acquire(This
, NULL
);
5909 glDeleteTextures(1, &This
->cursorTexture
);
5911 context_release(context
);
5912 This
->cursorTexture
= 0;
5915 if ((s
->currentDesc
.Width
== 32) && (s
->currentDesc
.Height
== 32))
5916 This
->haveHardwareCursor
= TRUE
;
5918 This
->haveHardwareCursor
= FALSE
;
5922 WINED3DLOCKED_RECT rect
;
5924 /* MSDN: Cursor must be A8R8G8B8 */
5925 if (s
->resource
.format
->id
!= WINED3DFMT_B8G8R8A8_UNORM
)
5927 WARN("surface %p has an invalid format.\n", cursor_image
);
5928 return WINED3DERR_INVALIDCALL
;
5931 /* MSDN: Cursor must be smaller than the display mode */
5932 if (s
->currentDesc
.Width
> This
->ddraw_width
5933 || s
->currentDesc
.Height
> This
->ddraw_height
)
5935 WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
5936 s
, s
->currentDesc
.Width
, s
->currentDesc
.Height
, This
->ddraw_width
, This
->ddraw_height
);
5937 return WINED3DERR_INVALIDCALL
;
5940 if (!This
->haveHardwareCursor
) {
5941 /* TODO: MSDN: Cursor sizes must be a power of 2 */
5943 /* Do not store the surface's pointer because the application may
5944 * release it after setting the cursor image. Windows doesn't
5945 * addref the set surface, so we can't do this either without
5946 * creating circular refcount dependencies. Copy out the gl texture
5949 This
->cursorWidth
= s
->currentDesc
.Width
;
5950 This
->cursorHeight
= s
->currentDesc
.Height
;
5951 if (SUCCEEDED(IWineD3DSurface_Map(cursor_image
, &rect
, NULL
, WINED3DLOCK_READONLY
)))
5953 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
5954 const struct wined3d_format
*format
= wined3d_get_format(gl_info
, WINED3DFMT_B8G8R8A8_UNORM
);
5955 struct wined3d_context
*context
;
5956 char *mem
, *bits
= rect
.pBits
;
5957 GLint intfmt
= format
->glInternal
;
5958 GLint gl_format
= format
->glFormat
;
5959 GLint type
= format
->glType
;
5960 INT height
= This
->cursorHeight
;
5961 INT width
= This
->cursorWidth
;
5962 INT bpp
= format
->byte_count
;
5966 /* Reformat the texture memory (pitch and width can be
5968 mem
= HeapAlloc(GetProcessHeap(), 0, width
* height
* bpp
);
5969 for(i
= 0; i
< height
; i
++)
5970 memcpy(&mem
[width
* bpp
* i
], &bits
[rect
.Pitch
* i
], width
* bpp
);
5971 IWineD3DSurface_Unmap(cursor_image
);
5973 context
= context_acquire(This
, NULL
);
5977 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
5979 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
5980 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
5983 /* Make sure that a proper texture unit is selected */
5984 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
5985 checkGLcall("glActiveTextureARB");
5986 sampler
= This
->rev_tex_unit_map
[0];
5987 if (sampler
!= WINED3D_UNMAPPED_STAGE
)
5989 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
5991 /* Create a new cursor texture */
5992 glGenTextures(1, &This
->cursorTexture
);
5993 checkGLcall("glGenTextures");
5994 glBindTexture(GL_TEXTURE_2D
, This
->cursorTexture
);
5995 checkGLcall("glBindTexture");
5996 /* Copy the bitmap memory into the cursor texture */
5997 glTexImage2D(GL_TEXTURE_2D
, 0, intfmt
, width
, height
, 0, gl_format
, type
, mem
);
5998 checkGLcall("glTexImage2D");
5999 HeapFree(GetProcessHeap(), 0, mem
);
6001 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
6003 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
6004 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6009 context_release(context
);
6013 FIXME("A cursor texture was not returned.\n");
6014 This
->cursorTexture
= 0;
6019 /* Draw a hardware cursor */
6020 ICONINFO cursorInfo
;
6022 /* Create and clear maskBits because it is not needed for
6023 * 32-bit cursors. 32x32 bits split into 32-bit chunks == 32
6025 DWORD
*maskBits
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6026 (s
->currentDesc
.Width
* s
->currentDesc
.Height
/ 8));
6027 IWineD3DSurface_Map(cursor_image
, &lockedRect
, NULL
,
6028 WINED3DLOCK_NO_DIRTY_UPDATE
| WINED3DLOCK_READONLY
);
6029 TRACE("width: %u height: %u.\n", s
->currentDesc
.Width
, s
->currentDesc
.Height
);
6031 cursorInfo
.fIcon
= FALSE
;
6032 cursorInfo
.xHotspot
= XHotSpot
;
6033 cursorInfo
.yHotspot
= YHotSpot
;
6034 cursorInfo
.hbmMask
= CreateBitmap(s
->currentDesc
.Width
, s
->currentDesc
.Height
, 1, 1, maskBits
);
6035 cursorInfo
.hbmColor
= CreateBitmap(s
->currentDesc
.Width
, s
->currentDesc
.Height
, 1, 32, lockedRect
.pBits
);
6036 IWineD3DSurface_Unmap(cursor_image
);
6037 /* Create our cursor and clean up. */
6038 cursor
= CreateIconIndirect(&cursorInfo
);
6040 if (cursorInfo
.hbmMask
) DeleteObject(cursorInfo
.hbmMask
);
6041 if (cursorInfo
.hbmColor
) DeleteObject(cursorInfo
.hbmColor
);
6042 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
6043 This
->hardwareCursor
= cursor
;
6044 HeapFree(GetProcessHeap(), 0, maskBits
);
6048 This
->xHotSpot
= XHotSpot
;
6049 This
->yHotSpot
= YHotSpot
;
6053 static void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
*iface
,
6054 int XScreenSpace
, int YScreenSpace
, DWORD flags
)
6056 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6058 TRACE("iface %p, x %d, y %d, flags %#x.\n",
6059 iface
, XScreenSpace
, YScreenSpace
, flags
);
6061 This
->xScreenSpace
= XScreenSpace
;
6062 This
->yScreenSpace
= YScreenSpace
;
6065 static BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
6066 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6067 BOOL oldVisible
= This
->bCursorVisible
;
6070 TRACE("(%p) : visible(%d)\n", This
, bShow
);
6073 * When ShowCursor is first called it should make the cursor appear at the OS's last
6074 * known cursor position. Because of this, some applications just repetitively call
6075 * ShowCursor in order to update the cursor's position. This behavior is undocumented.
6078 This
->xScreenSpace
= pt
.x
;
6079 This
->yScreenSpace
= pt
.y
;
6081 if (This
->haveHardwareCursor
) {
6082 This
->bCursorVisible
= bShow
;
6084 SetCursor(This
->hardwareCursor
);
6090 if (This
->cursorTexture
)
6091 This
->bCursorVisible
= bShow
;
6097 static HRESULT WINAPI
evict_managed_resource(struct wined3d_resource
*resource
, void *data
)
6099 TRACE("checking resource %p for eviction\n", resource
);
6101 if (resource
->pool
== WINED3DPOOL_MANAGED
)
6103 TRACE("Evicting %p.\n", resource
);
6104 resource
->resource_ops
->resource_unload(resource
);
6110 static HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
*iface
)
6112 TRACE("iface %p.\n", iface
);
6114 IWineD3DDevice_EnumResources(iface
, evict_managed_resource
, NULL
);
6115 /* Invalidate stream sources, the buffer(s) may have been evicted. */
6116 IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl
*)iface
, STATE_STREAMSRC
);
6121 static HRESULT
updateSurfaceDesc(IWineD3DSurfaceImpl
*surface
, const WINED3DPRESENT_PARAMETERS
* pPresentationParameters
)
6123 IWineD3DDeviceImpl
*device
= surface
->resource
.device
;
6124 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
6126 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6127 if (surface
->flags
& SFLAG_DIBSECTION
)
6129 /* Release the DC */
6130 SelectObject(surface
->hDC
, surface
->dib
.holdbitmap
);
6131 DeleteDC(surface
->hDC
);
6132 /* Release the DIB section */
6133 DeleteObject(surface
->dib
.DIBsection
);
6134 surface
->dib
.bitmap_data
= NULL
;
6135 surface
->resource
.allocatedMemory
= NULL
;
6136 surface
->flags
&= ~SFLAG_DIBSECTION
;
6138 surface
->currentDesc
.Width
= pPresentationParameters
->BackBufferWidth
;
6139 surface
->currentDesc
.Height
= pPresentationParameters
->BackBufferHeight
;
6140 if (gl_info
->supported
[ARB_TEXTURE_NON_POWER_OF_TWO
] || gl_info
->supported
[ARB_TEXTURE_RECTANGLE
]
6141 || gl_info
->supported
[WINED3D_GL_NORMALIZED_TEXRECT
])
6143 surface
->pow2Width
= pPresentationParameters
->BackBufferWidth
;
6144 surface
->pow2Height
= pPresentationParameters
->BackBufferHeight
;
6146 surface
->pow2Width
= surface
->pow2Height
= 1;
6147 while (surface
->pow2Width
< pPresentationParameters
->BackBufferWidth
) surface
->pow2Width
<<= 1;
6148 while (surface
->pow2Height
< pPresentationParameters
->BackBufferHeight
) surface
->pow2Height
<<= 1;
6151 if (surface
->texture_name
)
6153 struct wined3d_context
*context
= context_acquire(device
, NULL
);
6155 glDeleteTextures(1, &surface
->texture_name
);
6157 context_release(context
);
6158 surface
->texture_name
= 0;
6159 surface
->flags
&= ~SFLAG_CLIENT
;
6161 if (surface
->pow2Width
!= pPresentationParameters
->BackBufferWidth
6162 || surface
->pow2Height
!= pPresentationParameters
->BackBufferHeight
)
6164 surface
->flags
|= SFLAG_NONPOW2
;
6168 surface
->flags
&= ~SFLAG_NONPOW2
;
6170 HeapFree(GetProcessHeap(), 0, surface
->resource
.heapMemory
);
6171 surface
->resource
.allocatedMemory
= NULL
;
6172 surface
->resource
.heapMemory
= NULL
;
6173 surface
->resource
.size
= IWineD3DSurface_GetPitch((IWineD3DSurface
*) surface
) * surface
->pow2Width
;
6175 /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
6177 if (!surface_init_sysmem(surface
))
6179 return E_OUTOFMEMORY
;
6184 static BOOL
is_display_mode_supported(IWineD3DDeviceImpl
*This
, const WINED3DPRESENT_PARAMETERS
*pp
)
6187 WINED3DDISPLAYMODE m
;
6190 /* All Windowed modes are supported, as is leaving the current mode */
6191 if(pp
->Windowed
) return TRUE
;
6192 if(!pp
->BackBufferWidth
) return TRUE
;
6193 if(!pp
->BackBufferHeight
) return TRUE
;
6195 count
= wined3d_get_adapter_mode_count(This
->wined3d
, This
->adapter
->ordinal
, WINED3DFMT_UNKNOWN
);
6196 for (i
= 0; i
< count
; ++i
)
6198 memset(&m
, 0, sizeof(m
));
6199 hr
= wined3d_enum_adapter_modes(This
->wined3d
, This
->adapter
->ordinal
, WINED3DFMT_UNKNOWN
, i
, &m
);
6201 ERR("Failed to enumerate adapter mode.\n");
6202 if (m
.Width
== pp
->BackBufferWidth
&& m
.Height
== pp
->BackBufferHeight
)
6203 /* Mode found, it is supported. */
6206 /* Mode not found -> not supported */
6210 /* Do not call while under the GL lock. */
6211 static void delete_opengl_contexts(IWineD3DDeviceImpl
*device
, IWineD3DSwapChainImpl
*swapchain
)
6213 const struct wined3d_gl_info
*gl_info
;
6214 struct wined3d_context
*context
;
6215 IWineD3DBaseShaderImpl
*shader
;
6217 context
= context_acquire(device
, NULL
);
6218 gl_info
= context
->gl_info
;
6220 IWineD3DDevice_EnumResources((IWineD3DDevice
*)device
, device_unload_resource
, NULL
);
6221 LIST_FOR_EACH_ENTRY(shader
, &device
->shaders
, IWineD3DBaseShaderImpl
, baseShader
.shader_list_entry
)
6223 device
->shader_backend
->shader_destroy(shader
);
6227 if (device
->depth_blt_texture
)
6229 glDeleteTextures(1, &device
->depth_blt_texture
);
6230 device
->depth_blt_texture
= 0;
6232 if (device
->depth_blt_rb
)
6234 gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &device
->depth_blt_rb
);
6235 device
->depth_blt_rb
= 0;
6236 device
->depth_blt_rb_w
= 0;
6237 device
->depth_blt_rb_h
= 0;
6241 device
->blitter
->free_private(device
);
6242 device
->frag_pipe
->free_private(device
);
6243 device
->shader_backend
->shader_free_private(device
);
6244 destroy_dummy_textures(device
, gl_info
);
6246 context_release(context
);
6248 while (device
->numContexts
)
6250 context_destroy(device
, device
->contexts
[0]);
6252 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6253 swapchain
->context
= NULL
;
6254 swapchain
->num_contexts
= 0;
6257 /* Do not call while under the GL lock. */
6258 static HRESULT
create_primary_opengl_context(IWineD3DDeviceImpl
*device
, IWineD3DSwapChainImpl
*swapchain
)
6260 struct wined3d_context
*context
;
6262 IWineD3DSurfaceImpl
*target
;
6264 /* Recreate the primary swapchain's context */
6265 swapchain
->context
= HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain
->context
));
6266 if (!swapchain
->context
)
6268 ERR("Failed to allocate memory for swapchain context array.\n");
6269 return E_OUTOFMEMORY
;
6272 target
= swapchain
->back_buffers
? swapchain
->back_buffers
[0] : swapchain
->front_buffer
;
6273 if (!(context
= context_create(swapchain
, target
, swapchain
->ds_format
)))
6275 WARN("Failed to create context.\n");
6276 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6280 swapchain
->context
[0] = context
;
6281 swapchain
->num_contexts
= 1;
6282 create_dummy_textures(device
);
6283 context_release(context
);
6285 hr
= device
->shader_backend
->shader_alloc_private(device
);
6288 ERR("Failed to allocate shader private data, hr %#x.\n", hr
);
6292 hr
= device
->frag_pipe
->alloc_private(device
);
6295 ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr
);
6296 device
->shader_backend
->shader_free_private(device
);
6300 hr
= device
->blitter
->alloc_private(device
);
6303 ERR("Failed to allocate blitter private data, hr %#x.\n", hr
);
6304 device
->frag_pipe
->free_private(device
);
6305 device
->shader_backend
->shader_free_private(device
);
6312 context_acquire(device
, NULL
);
6313 destroy_dummy_textures(device
, context
->gl_info
);
6314 context_release(context
);
6315 context_destroy(device
, context
);
6316 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6317 swapchain
->num_contexts
= 0;
6321 /* Do not call while under the GL lock. */
6322 static HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
*iface
,
6323 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
6325 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6326 IWineD3DSwapChainImpl
*swapchain
;
6328 BOOL DisplayModeChanged
= FALSE
;
6329 WINED3DDISPLAYMODE mode
;
6330 TRACE("(%p)\n", This
);
6332 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, (IWineD3DSwapChain
**) &swapchain
);
6334 ERR("Failed to get the first implicit swapchain\n");
6338 if(!is_display_mode_supported(This
, pPresentationParameters
)) {
6339 WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6340 WARN("Requested mode: %d, %d\n", pPresentationParameters
->BackBufferWidth
,
6341 pPresentationParameters
->BackBufferHeight
);
6342 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
6343 return WINED3DERR_INVALIDCALL
;
6346 /* Is it necessary to recreate the gl context? Actually every setting can be changed
6347 * on an existing gl context, so there's no real need for recreation.
6349 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6351 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6353 TRACE("New params:\n");
6354 TRACE("BackBufferWidth = %d\n", pPresentationParameters
->BackBufferWidth
);
6355 TRACE("BackBufferHeight = %d\n", pPresentationParameters
->BackBufferHeight
);
6356 TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters
->BackBufferFormat
));
6357 TRACE("BackBufferCount = %d\n", pPresentationParameters
->BackBufferCount
);
6358 TRACE("MultiSampleType = %d\n", pPresentationParameters
->MultiSampleType
);
6359 TRACE("MultiSampleQuality = %d\n", pPresentationParameters
->MultiSampleQuality
);
6360 TRACE("SwapEffect = %d\n", pPresentationParameters
->SwapEffect
);
6361 TRACE("hDeviceWindow = %p\n", pPresentationParameters
->hDeviceWindow
);
6362 TRACE("Windowed = %s\n", pPresentationParameters
->Windowed
? "true" : "false");
6363 TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters
->EnableAutoDepthStencil
? "true" : "false");
6364 TRACE("Flags = %08x\n", pPresentationParameters
->Flags
);
6365 TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters
->FullScreen_RefreshRateInHz
);
6366 TRACE("PresentationInterval = %d\n", pPresentationParameters
->PresentationInterval
);
6368 /* No special treatment of these parameters. Just store them */
6369 swapchain
->presentParms
.SwapEffect
= pPresentationParameters
->SwapEffect
;
6370 swapchain
->presentParms
.Flags
= pPresentationParameters
->Flags
;
6371 swapchain
->presentParms
.PresentationInterval
= pPresentationParameters
->PresentationInterval
;
6372 swapchain
->presentParms
.FullScreen_RefreshRateInHz
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
6374 /* What to do about these? */
6375 if (pPresentationParameters
->BackBufferCount
6376 && pPresentationParameters
->BackBufferCount
!= swapchain
->presentParms
.BackBufferCount
)
6377 ERR("Cannot change the back buffer count yet\n");
6379 if(pPresentationParameters
->BackBufferFormat
!= WINED3DFMT_UNKNOWN
&&
6380 pPresentationParameters
->BackBufferFormat
!= swapchain
->presentParms
.BackBufferFormat
) {
6381 ERR("Cannot change the back buffer format yet\n");
6384 if (pPresentationParameters
->hDeviceWindow
6385 && pPresentationParameters
->hDeviceWindow
!= swapchain
->presentParms
.hDeviceWindow
)
6386 ERR("Cannot change the device window yet\n");
6388 if (pPresentationParameters
->EnableAutoDepthStencil
&& !This
->auto_depth_stencil
)
6392 TRACE("Creating the depth stencil buffer\n");
6394 hrc
= IWineD3DDeviceParent_CreateDepthStencilSurface(This
->device_parent
,
6395 pPresentationParameters
->BackBufferWidth
,
6396 pPresentationParameters
->BackBufferHeight
,
6397 pPresentationParameters
->AutoDepthStencilFormat
,
6398 pPresentationParameters
->MultiSampleType
,
6399 pPresentationParameters
->MultiSampleQuality
,
6401 (IWineD3DSurface
**)&This
->auto_depth_stencil
);
6404 ERR("Failed to create the depth stencil buffer\n");
6405 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6406 return WINED3DERR_INVALIDCALL
;
6410 if (This
->onscreen_depth_stencil
)
6412 IWineD3DSurface_Release((IWineD3DSurface
*)This
->onscreen_depth_stencil
);
6413 This
->onscreen_depth_stencil
= NULL
;
6416 /* Reset the depth stencil */
6417 if (pPresentationParameters
->EnableAutoDepthStencil
)
6418 IWineD3DDevice_SetDepthStencilSurface(iface
, (IWineD3DSurface
*)This
->auto_depth_stencil
);
6420 IWineD3DDevice_SetDepthStencilSurface(iface
, NULL
);
6422 TRACE("Resetting stateblock\n");
6423 wined3d_stateblock_decref(This
->updateStateBlock
);
6424 wined3d_stateblock_decref(This
->stateBlock
);
6426 delete_opengl_contexts(This
, swapchain
);
6428 if(pPresentationParameters
->Windowed
) {
6429 mode
.Width
= swapchain
->orig_width
;
6430 mode
.Height
= swapchain
->orig_height
;
6431 mode
.RefreshRate
= 0;
6432 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
6434 mode
.Width
= pPresentationParameters
->BackBufferWidth
;
6435 mode
.Height
= pPresentationParameters
->BackBufferHeight
;
6436 mode
.RefreshRate
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
6437 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
6440 /* Should Width == 800 && Height == 0 set 800x600? */
6441 if (pPresentationParameters
->BackBufferWidth
&& pPresentationParameters
->BackBufferHeight
6442 && (pPresentationParameters
->BackBufferWidth
!= swapchain
->presentParms
.BackBufferWidth
6443 || pPresentationParameters
->BackBufferHeight
!= swapchain
->presentParms
.BackBufferHeight
))
6447 if(!pPresentationParameters
->Windowed
) {
6448 DisplayModeChanged
= TRUE
;
6450 swapchain
->presentParms
.BackBufferWidth
= pPresentationParameters
->BackBufferWidth
;
6451 swapchain
->presentParms
.BackBufferHeight
= pPresentationParameters
->BackBufferHeight
;
6453 hr
= updateSurfaceDesc(swapchain
->front_buffer
, pPresentationParameters
);
6456 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6460 for (i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; ++i
)
6462 hr
= updateSurfaceDesc(swapchain
->back_buffers
[i
], pPresentationParameters
);
6465 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6469 if (This
->auto_depth_stencil
)
6471 hr
= updateSurfaceDesc(This
->auto_depth_stencil
, pPresentationParameters
);
6474 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6480 if (!pPresentationParameters
->Windowed
!= !swapchain
->presentParms
.Windowed
6481 || DisplayModeChanged
)
6483 BOOL filter
= This
->filter_messages
;
6484 This
->filter_messages
= TRUE
;
6486 IWineD3DDevice_SetDisplayMode(iface
, 0, &mode
);
6488 if (!pPresentationParameters
->Windowed
)
6490 if (swapchain
->presentParms
.Windowed
)
6492 HWND focus_window
= This
->createParms
.hFocusWindow
;
6493 if (!focus_window
) focus_window
= pPresentationParameters
->hDeviceWindow
;
6494 if (FAILED(hr
= IWineD3DDevice_AcquireFocusWindow(iface
, focus_window
)))
6496 ERR("Failed to acquire focus window, hr %#x.\n", hr
);
6497 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
6501 /* switch from windowed to fs */
6502 IWineD3DDevice_SetupFullscreenWindow(iface
, swapchain
->device_window
,
6503 pPresentationParameters
->BackBufferWidth
,
6504 pPresentationParameters
->BackBufferHeight
);
6508 /* Fullscreen -> fullscreen mode change */
6509 MoveWindow(swapchain
->device_window
, 0, 0,
6510 pPresentationParameters
->BackBufferWidth
, pPresentationParameters
->BackBufferHeight
,
6514 else if (!swapchain
->presentParms
.Windowed
)
6516 /* Fullscreen -> windowed switch */
6517 IWineD3DDevice_RestoreFullscreenWindow(iface
, swapchain
->device_window
);
6518 IWineD3DDevice_ReleaseFocusWindow(iface
);
6520 swapchain
->presentParms
.Windowed
= pPresentationParameters
->Windowed
;
6522 This
->filter_messages
= filter
;
6524 else if (!pPresentationParameters
->Windowed
)
6526 DWORD style
= This
->style
, exStyle
= This
->exStyle
;
6527 /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6528 * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6529 * Reset to clear up their mess. Guild Wars also loses the device during that.
6533 IWineD3DDevice_SetupFullscreenWindow(iface
, swapchain
->device_window
,
6534 pPresentationParameters
->BackBufferWidth
,
6535 pPresentationParameters
->BackBufferHeight
);
6536 This
->style
= style
;
6537 This
->exStyle
= exStyle
;
6540 /* Note: No parent needed for initial internal stateblock */
6541 hr
= IWineD3DDevice_CreateStateBlock(iface
, WINED3DSBT_INIT
, &This
->stateBlock
);
6542 if (FAILED(hr
)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr
);
6543 else TRACE("Created stateblock %p\n", This
->stateBlock
);
6544 This
->updateStateBlock
= This
->stateBlock
;
6545 wined3d_stateblock_incref(This
->updateStateBlock
);
6547 stateblock_init_default_state(This
->stateBlock
);
6549 if(wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
)
6552 GetClientRect(swapchain
->win_handle
, &client_rect
);
6554 if(!swapchain
->presentParms
.BackBufferCount
)
6556 TRACE("Single buffered rendering\n");
6557 swapchain
->render_to_fbo
= FALSE
;
6559 else if(swapchain
->presentParms
.BackBufferWidth
!= client_rect
.right
||
6560 swapchain
->presentParms
.BackBufferHeight
!= client_rect
.bottom
)
6562 TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
6563 swapchain
->presentParms
.BackBufferWidth
,
6564 swapchain
->presentParms
.BackBufferHeight
,
6565 client_rect
.right
, client_rect
.bottom
);
6566 swapchain
->render_to_fbo
= TRUE
;
6570 TRACE("Rendering directly to GL_BACK\n");
6571 swapchain
->render_to_fbo
= FALSE
;
6575 hr
= create_primary_opengl_context(This
, swapchain
);
6576 IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
6578 /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6584 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL enable_dialogs
)
6586 TRACE("iface %p, enable_dialogs %#x.\n", iface
, enable_dialogs
);
6588 if (!enable_dialogs
) FIXME("Dialogs cannot be disabled yet.\n");
6594 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, WINED3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
6595 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6596 TRACE("(%p) : pParameters %p\n", This
, pParameters
);
6598 *pParameters
= This
->createParms
;
6602 static void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
*iface
,
6603 UINT iSwapChain
, DWORD flags
, const WINED3DGAMMARAMP
*pRamp
)
6605 IWineD3DSwapChain
*swapchain
;
6607 TRACE("Relaying to swapchain\n");
6609 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
)
6611 IWineD3DSwapChain_SetGammaRamp(swapchain
, flags
, pRamp
);
6612 IWineD3DSwapChain_Release(swapchain
);
6616 static void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DGAMMARAMP
* pRamp
) {
6617 IWineD3DSwapChain
*swapchain
;
6619 TRACE("Relaying to swapchain\n");
6621 if (IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
) == WINED3D_OK
) {
6622 IWineD3DSwapChain_GetGammaRamp(swapchain
, pRamp
);
6623 IWineD3DSwapChain_Release(swapchain
);
6627 void device_resource_add(struct IWineD3DDeviceImpl
*device
, struct wined3d_resource
*resource
)
6629 TRACE("device %p, resource %p.\n", device
, resource
);
6631 list_add_head(&device
->resources
, &resource
->resource_list_entry
);
6634 static void device_resource_remove(struct IWineD3DDeviceImpl
*device
, struct wined3d_resource
*resource
)
6636 TRACE("device %p, resource %p.\n", device
, resource
);
6638 list_remove(&resource
->resource_list_entry
);
6641 void device_resource_released(struct IWineD3DDeviceImpl
*device
, struct wined3d_resource
*resource
)
6643 WINED3DRESOURCETYPE type
= resource
->resourceType
;
6646 TRACE("device %p, resource %p, type %s.\n", device
, resource
, debug_d3dresourcetype(type
));
6648 context_resource_released(device
, resource
, type
);
6652 case WINED3DRTYPE_SURFACE
:
6654 IWineD3DSurfaceImpl
*surface
= surface_from_resource(resource
);
6656 if (!device
->d3d_initialized
) break;
6658 for (i
= 0; i
< device
->adapter
->gl_info
.limits
.buffers
; ++i
)
6660 if (device
->render_targets
[i
] == surface
)
6662 ERR("Surface %p is still in use as render target %u.\n", surface
, i
);
6663 device
->render_targets
[i
] = NULL
;
6667 if (device
->depth_stencil
== surface
)
6669 ERR("Surface %p is still in use as depth/stencil buffer.\n", surface
);
6670 device
->depth_stencil
= NULL
;
6675 case WINED3DRTYPE_TEXTURE
:
6676 case WINED3DRTYPE_CUBETEXTURE
:
6677 case WINED3DRTYPE_VOLUMETEXTURE
:
6678 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
6680 IWineD3DBaseTextureImpl
*texture
= basetexture_from_resource(resource
);
6682 if (device
->stateBlock
&& device
->stateBlock
->state
.textures
[i
] == texture
)
6684 ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6685 texture
, device
->stateBlock
, i
);
6686 device
->stateBlock
->state
.textures
[i
] = NULL
;
6689 if (device
->updateStateBlock
!= device
->stateBlock
6690 && device
->updateStateBlock
->state
.textures
[i
] == texture
)
6692 ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6693 texture
, device
->updateStateBlock
, i
);
6694 device
->updateStateBlock
->state
.textures
[i
] = NULL
;
6699 case WINED3DRTYPE_BUFFER
:
6701 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
6703 for (i
= 0; i
< MAX_STREAMS
; ++i
)
6705 if (device
->stateBlock
&& device
->stateBlock
->state
.streams
[i
].buffer
== buffer
)
6707 ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6708 buffer
, device
->stateBlock
, i
);
6709 device
->stateBlock
->state
.streams
[i
].buffer
= NULL
;
6712 if (device
->updateStateBlock
!= device
->stateBlock
6713 && device
->updateStateBlock
->state
.streams
[i
].buffer
== buffer
)
6715 ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6716 buffer
, device
->updateStateBlock
, i
);
6717 device
->updateStateBlock
->state
.streams
[i
].buffer
= NULL
;
6722 if (device
->stateBlock
&& device
->stateBlock
->state
.index_buffer
== buffer
)
6724 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6725 buffer
, device
->stateBlock
);
6726 device
->stateBlock
->state
.index_buffer
= NULL
;
6729 if (device
->updateStateBlock
!= device
->stateBlock
6730 && device
->updateStateBlock
->state
.index_buffer
== buffer
)
6732 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6733 buffer
, device
->updateStateBlock
);
6734 device
->updateStateBlock
->state
.index_buffer
= NULL
;
6743 /* Remove the resource from the resourceStore */
6744 device_resource_remove(device
, resource
);
6746 TRACE("Resource released.\n");
6749 static HRESULT WINAPI
IWineD3DDeviceImpl_EnumResources(IWineD3DDevice
*iface
,
6750 D3DCB_ENUMRESOURCES callback
, void *data
)
6752 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6753 struct wined3d_resource
*resource
, *cursor
;
6755 TRACE("iface %p, callback %p, data %p.\n", iface
, callback
, data
);
6757 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &This
->resources
, struct wined3d_resource
, resource_list_entry
)
6759 TRACE("enumerating resource %p.\n", resource
);
6760 if (callback(resource
, data
) == S_FALSE
)
6762 TRACE("Canceling enumeration.\n");
6770 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSurfaceFromDC(IWineD3DDevice
*iface
, HDC dc
, IWineD3DSurface
**surface
)
6772 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6773 struct wined3d_resource
*resource
;
6775 LIST_FOR_EACH_ENTRY(resource
, &This
->resources
, struct wined3d_resource
, resource_list_entry
)
6777 if (resource
->resourceType
== WINED3DRTYPE_SURFACE
)
6779 IWineD3DSurfaceImpl
*s
= surface_from_resource(resource
);
6783 TRACE("Found surface %p for dc %p.\n", s
, dc
);
6784 *surface
= (IWineD3DSurface
*)s
;
6790 return WINED3DERR_INVALIDCALL
;
6793 /**********************************************************
6794 * IWineD3DDevice VTbl follows
6795 **********************************************************/
6797 static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
6799 /*** IUnknown methods ***/
6800 IWineD3DDeviceImpl_QueryInterface
,
6801 IWineD3DDeviceImpl_AddRef
,
6802 IWineD3DDeviceImpl_Release
,
6803 /*** IWineD3DDevice methods ***/
6804 /*** Creation methods**/
6805 IWineD3DDeviceImpl_CreateBuffer
,
6806 IWineD3DDeviceImpl_CreateVertexBuffer
,
6807 IWineD3DDeviceImpl_CreateIndexBuffer
,
6808 IWineD3DDeviceImpl_CreateStateBlock
,
6809 IWineD3DDeviceImpl_CreateSurface
,
6810 IWineD3DDeviceImpl_CreateRendertargetView
,
6811 IWineD3DDeviceImpl_CreateTexture
,
6812 IWineD3DDeviceImpl_CreateVolumeTexture
,
6813 IWineD3DDeviceImpl_CreateVolume
,
6814 IWineD3DDeviceImpl_CreateCubeTexture
,
6815 IWineD3DDeviceImpl_CreateQuery
,
6816 IWineD3DDeviceImpl_CreateSwapChain
,
6817 IWineD3DDeviceImpl_CreateVertexDeclaration
,
6818 IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF
,
6819 IWineD3DDeviceImpl_CreateVertexShader
,
6820 IWineD3DDeviceImpl_CreateGeometryShader
,
6821 IWineD3DDeviceImpl_CreatePixelShader
,
6822 IWineD3DDeviceImpl_CreatePalette
,
6823 /*** Odd functions **/
6824 IWineD3DDeviceImpl_Init3D
,
6825 IWineD3DDeviceImpl_InitGDI
,
6826 IWineD3DDeviceImpl_Uninit3D
,
6827 IWineD3DDeviceImpl_UninitGDI
,
6828 IWineD3DDeviceImpl_SetMultithreaded
,
6829 IWineD3DDeviceImpl_EvictManagedResources
,
6830 IWineD3DDeviceImpl_GetAvailableTextureMem
,
6831 IWineD3DDeviceImpl_GetBackBuffer
,
6832 IWineD3DDeviceImpl_GetCreationParameters
,
6833 IWineD3DDeviceImpl_GetDeviceCaps
,
6834 IWineD3DDeviceImpl_GetDirect3D
,
6835 IWineD3DDeviceImpl_GetDisplayMode
,
6836 IWineD3DDeviceImpl_SetDisplayMode
,
6837 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
6838 IWineD3DDeviceImpl_GetRasterStatus
,
6839 IWineD3DDeviceImpl_GetSwapChain
,
6840 IWineD3DDeviceImpl_Reset
,
6841 IWineD3DDeviceImpl_SetDialogBoxMode
,
6842 IWineD3DDeviceImpl_SetCursorProperties
,
6843 IWineD3DDeviceImpl_SetCursorPosition
,
6844 IWineD3DDeviceImpl_ShowCursor
,
6845 /*** Getters and setters **/
6846 IWineD3DDeviceImpl_SetClipPlane
,
6847 IWineD3DDeviceImpl_GetClipPlane
,
6848 IWineD3DDeviceImpl_SetClipStatus
,
6849 IWineD3DDeviceImpl_GetClipStatus
,
6850 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
6851 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
6852 IWineD3DDeviceImpl_SetDepthStencilSurface
,
6853 IWineD3DDeviceImpl_GetDepthStencilSurface
,
6854 IWineD3DDeviceImpl_SetGammaRamp
,
6855 IWineD3DDeviceImpl_GetGammaRamp
,
6856 IWineD3DDeviceImpl_SetIndexBuffer
,
6857 IWineD3DDeviceImpl_GetIndexBuffer
,
6858 IWineD3DDeviceImpl_SetBaseVertexIndex
,
6859 IWineD3DDeviceImpl_GetBaseVertexIndex
,
6860 IWineD3DDeviceImpl_SetLight
,
6861 IWineD3DDeviceImpl_GetLight
,
6862 IWineD3DDeviceImpl_SetLightEnable
,
6863 IWineD3DDeviceImpl_GetLightEnable
,
6864 IWineD3DDeviceImpl_SetMaterial
,
6865 IWineD3DDeviceImpl_GetMaterial
,
6866 IWineD3DDeviceImpl_SetNPatchMode
,
6867 IWineD3DDeviceImpl_GetNPatchMode
,
6868 IWineD3DDeviceImpl_SetPaletteEntries
,
6869 IWineD3DDeviceImpl_GetPaletteEntries
,
6870 IWineD3DDeviceImpl_SetPixelShader
,
6871 IWineD3DDeviceImpl_GetPixelShader
,
6872 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
6873 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
6874 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
6875 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
6876 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
6877 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
6878 IWineD3DDeviceImpl_SetRenderState
,
6879 IWineD3DDeviceImpl_GetRenderState
,
6880 IWineD3DDeviceImpl_SetRenderTarget
,
6881 IWineD3DDeviceImpl_GetRenderTarget
,
6882 IWineD3DDeviceImpl_SetSamplerState
,
6883 IWineD3DDeviceImpl_GetSamplerState
,
6884 IWineD3DDeviceImpl_SetScissorRect
,
6885 IWineD3DDeviceImpl_GetScissorRect
,
6886 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
6887 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
6888 IWineD3DDeviceImpl_SetStreamSource
,
6889 IWineD3DDeviceImpl_GetStreamSource
,
6890 IWineD3DDeviceImpl_SetStreamSourceFreq
,
6891 IWineD3DDeviceImpl_GetStreamSourceFreq
,
6892 IWineD3DDeviceImpl_SetTexture
,
6893 IWineD3DDeviceImpl_GetTexture
,
6894 IWineD3DDeviceImpl_SetTextureStageState
,
6895 IWineD3DDeviceImpl_GetTextureStageState
,
6896 IWineD3DDeviceImpl_SetTransform
,
6897 IWineD3DDeviceImpl_GetTransform
,
6898 IWineD3DDeviceImpl_SetVertexDeclaration
,
6899 IWineD3DDeviceImpl_GetVertexDeclaration
,
6900 IWineD3DDeviceImpl_SetVertexShader
,
6901 IWineD3DDeviceImpl_GetVertexShader
,
6902 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
6903 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
6904 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
6905 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
6906 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
6907 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
6908 IWineD3DDeviceImpl_SetViewport
,
6909 IWineD3DDeviceImpl_GetViewport
,
6910 IWineD3DDeviceImpl_MultiplyTransform
,
6911 IWineD3DDeviceImpl_ValidateDevice
,
6912 IWineD3DDeviceImpl_ProcessVertices
,
6913 /*** State block ***/
6914 IWineD3DDeviceImpl_BeginStateBlock
,
6915 IWineD3DDeviceImpl_EndStateBlock
,
6916 /*** Scene management ***/
6917 IWineD3DDeviceImpl_BeginScene
,
6918 IWineD3DDeviceImpl_EndScene
,
6919 IWineD3DDeviceImpl_Present
,
6920 IWineD3DDeviceImpl_Clear
,
6921 IWineD3DDeviceImpl_ClearRendertargetView
,
6923 IWineD3DDeviceImpl_SetPrimitiveType
,
6924 IWineD3DDeviceImpl_GetPrimitiveType
,
6925 IWineD3DDeviceImpl_DrawPrimitive
,
6926 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
6927 IWineD3DDeviceImpl_DrawPrimitiveUP
,
6928 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
6929 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
6930 IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided
,
6931 IWineD3DDeviceImpl_DrawRectPatch
,
6932 IWineD3DDeviceImpl_DrawTriPatch
,
6933 IWineD3DDeviceImpl_DeletePatch
,
6934 IWineD3DDeviceImpl_ColorFill
,
6935 IWineD3DDeviceImpl_UpdateTexture
,
6936 IWineD3DDeviceImpl_UpdateSurface
,
6937 IWineD3DDeviceImpl_GetFrontBufferData
,
6938 /*** object tracking ***/
6939 IWineD3DDeviceImpl_EnumResources
,
6940 IWineD3DDeviceImpl_GetSurfaceFromDC
,
6941 IWineD3DDeviceImpl_AcquireFocusWindow
,
6942 IWineD3DDeviceImpl_ReleaseFocusWindow
,
6943 IWineD3DDeviceImpl_SetupFullscreenWindow
,
6944 IWineD3DDeviceImpl_RestoreFullscreenWindow
,
6947 HRESULT
device_init(IWineD3DDeviceImpl
*device
, struct wined3d
*wined3d
,
6948 UINT adapter_idx
, WINED3DDEVTYPE device_type
, HWND focus_window
, DWORD flags
,
6949 IWineD3DDeviceParent
*device_parent
)
6951 struct wined3d_adapter
*adapter
= &wined3d
->adapters
[adapter_idx
];
6952 const struct fragment_pipeline
*fragment_pipeline
;
6953 struct shader_caps shader_caps
;
6954 struct fragment_caps ffp_caps
;
6955 WINED3DDISPLAYMODE mode
;
6959 device
->lpVtbl
= &IWineD3DDevice_Vtbl
;
6961 device
->wined3d
= wined3d
;
6962 wined3d_incref(device
->wined3d
);
6963 device
->adapter
= wined3d
->adapter_count
? adapter
: NULL
;
6964 device
->device_parent
= device_parent
;
6965 list_init(&device
->resources
);
6966 list_init(&device
->shaders
);
6968 device
->surface_alignment
= wined3d
->dxVersion
== 7 ? DDRAW_PITCH_ALIGNMENT
: D3D8_PITCH_ALIGNMENT
;
6970 /* Get the initial screen setup for ddraw. */
6971 hr
= wined3d_get_adapter_display_mode(wined3d
, adapter_idx
, &mode
);
6974 ERR("Failed to get the adapter's display mode, hr %#x.\n", hr
);
6975 wined3d_decref(device
->wined3d
);
6978 device
->ddraw_width
= mode
.Width
;
6979 device
->ddraw_height
= mode
.Height
;
6980 device
->ddraw_format
= mode
.Format
;
6982 /* Save the creation parameters. */
6983 device
->createParms
.AdapterOrdinal
= adapter_idx
;
6984 device
->createParms
.DeviceType
= device_type
;
6985 device
->createParms
.hFocusWindow
= focus_window
;
6986 device
->createParms
.BehaviorFlags
= flags
;
6988 device
->devType
= device_type
;
6989 for (i
= 0; i
< PATCHMAP_SIZE
; ++i
) list_init(&device
->patches
[i
]);
6991 select_shader_mode(&adapter
->gl_info
, &device
->ps_selected_mode
, &device
->vs_selected_mode
);
6992 device
->shader_backend
= adapter
->shader_backend
;
6994 if (device
->shader_backend
)
6996 device
->shader_backend
->shader_get_caps(&adapter
->gl_info
, &shader_caps
);
6997 device
->d3d_vshader_constantF
= shader_caps
.MaxVertexShaderConst
;
6998 device
->d3d_pshader_constantF
= shader_caps
.MaxPixelShaderConst
;
6999 device
->vs_clipping
= shader_caps
.VSClipping
;
7001 fragment_pipeline
= adapter
->fragment_pipe
;
7002 device
->frag_pipe
= fragment_pipeline
;
7003 if (fragment_pipeline
)
7005 fragment_pipeline
->get_caps(&adapter
->gl_info
, &ffp_caps
);
7006 device
->max_ffp_textures
= ffp_caps
.MaxSimultaneousTextures
;
7008 hr
= compile_state_table(device
->StateTable
, device
->multistate_funcs
, &adapter
->gl_info
,
7009 ffp_vertexstate_template
, fragment_pipeline
, misc_state_template
);
7012 ERR("Failed to compile state table, hr %#x.\n", hr
);
7013 wined3d_decref(device
->wined3d
);
7017 device
->blitter
= adapter
->blitter
;
7023 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl
*This
, DWORD state
) {
7024 DWORD rep
= This
->StateTable
[state
].representative
;
7025 struct wined3d_context
*context
;
7030 for(i
= 0; i
< This
->numContexts
; i
++) {
7031 context
= This
->contexts
[i
];
7032 if(isStateDirty(context
, rep
)) continue;
7034 context
->dirtyArray
[context
->numDirtyEntries
++] = rep
;
7035 idx
= rep
/ (sizeof(*context
->isStateDirty
) * CHAR_BIT
);
7036 shift
= rep
& ((sizeof(*context
->isStateDirty
) * CHAR_BIT
) - 1);
7037 context
->isStateDirty
[idx
] |= (1 << shift
);
7041 void get_drawable_size_fbo(struct wined3d_context
*context
, UINT
*width
, UINT
*height
)
7043 /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
7044 *width
= context
->current_rt
->pow2Width
;
7045 *height
= context
->current_rt
->pow2Height
;
7048 void get_drawable_size_backbuffer(struct wined3d_context
*context
, UINT
*width
, UINT
*height
)
7050 IWineD3DSwapChainImpl
*swapchain
= context
->swapchain
;
7051 /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7052 * current context's drawable, which is the size of the back buffer of the swapchain
7053 * the active context belongs to. */
7054 *width
= swapchain
->presentParms
.BackBufferWidth
;
7055 *height
= swapchain
->presentParms
.BackBufferHeight
;
7058 LRESULT
device_process_message(IWineD3DDeviceImpl
*device
, HWND window
, BOOL unicode
,
7059 UINT message
, WPARAM wparam
, LPARAM lparam
, WNDPROC proc
)
7061 if (device
->filter_messages
)
7063 TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
7064 window
, message
, wparam
, lparam
);
7066 return DefWindowProcW(window
, message
, wparam
, lparam
);
7068 return DefWindowProcA(window
, message
, wparam
, lparam
);
7071 if (message
== WM_DESTROY
)
7073 TRACE("unregister window %p.\n", window
);
7074 wined3d_unregister_window(window
);
7076 if (device
->focus_window
== window
) device
->focus_window
= NULL
;
7077 else ERR("Window %p is not the focus window for device %p.\n", window
, device
);
7081 return CallWindowProcW(proc
, window
, message
, wparam
, lparam
);
7083 return CallWindowProcA(proc
, window
, message
, wparam
, lparam
);