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-2011 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 wined3d_buffer_preload(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 struct wined3d_texture
*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
->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
->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
->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
,
508 sizeof(*new_array
) * (device
->context_count
+ 1));
512 ERR("Failed to grow the context array.\n");
516 new_array
[device
->context_count
++] = context
;
517 device
->contexts
= new_array
;
521 void device_context_remove(IWineD3DDeviceImpl
*device
, struct wined3d_context
*context
)
523 struct wined3d_context
**new_array
;
527 TRACE("Removing context %p.\n", context
);
529 for (i
= 0; i
< device
->context_count
; ++i
)
531 if (device
->contexts
[i
] == context
)
540 ERR("Context %p doesn't exist in context array.\n", context
);
544 if (!--device
->context_count
)
546 HeapFree(GetProcessHeap(), 0, device
->contexts
);
547 device
->contexts
= NULL
;
551 memmove(&device
->contexts
[i
], &device
->contexts
[i
+ 1], (device
->context_count
- i
) * sizeof(*device
->contexts
));
552 new_array
= HeapReAlloc(GetProcessHeap(), 0, device
->contexts
, device
->context_count
* sizeof(*device
->contexts
));
555 ERR("Failed to shrink context array. Oh well.\n");
559 device
->contexts
= new_array
;
562 void device_get_draw_rect(IWineD3DDeviceImpl
*device
, RECT
*rect
)
564 struct wined3d_stateblock
*stateblock
= device
->stateBlock
;
565 WINED3DVIEWPORT
*vp
= &stateblock
->state
.viewport
;
567 SetRect(rect
, vp
->X
, vp
->Y
, vp
->X
+ vp
->Width
, vp
->Y
+ vp
->Height
);
569 if (stateblock
->state
.render_states
[WINED3DRS_SCISSORTESTENABLE
])
571 IntersectRect(rect
, rect
, &stateblock
->state
.scissor_rect
);
575 /* Do not call while under the GL lock. */
576 void device_switch_onscreen_ds(IWineD3DDeviceImpl
*device
,
577 struct wined3d_context
*context
, struct wined3d_surface
*depth_stencil
)
579 if (device
->onscreen_depth_stencil
)
581 surface_load_ds_location(device
->onscreen_depth_stencil
, context
, SFLAG_DS_OFFSCREEN
);
582 surface_modify_ds_location(device
->onscreen_depth_stencil
, SFLAG_DS_OFFSCREEN
,
583 device
->onscreen_depth_stencil
->ds_current_size
.cx
,
584 device
->onscreen_depth_stencil
->ds_current_size
.cy
);
585 wined3d_surface_decref(device
->onscreen_depth_stencil
);
587 device
->onscreen_depth_stencil
= depth_stencil
;
588 wined3d_surface_incref(device
->onscreen_depth_stencil
);
591 static BOOL
is_full_clear(struct wined3d_surface
*target
, const RECT
*draw_rect
, const RECT
*clear_rect
)
593 /* partial draw rect */
594 if (draw_rect
->left
|| draw_rect
->top
595 || draw_rect
->right
< target
->resource
.width
596 || draw_rect
->bottom
< target
->resource
.height
)
599 /* partial clear rect */
600 if (clear_rect
&& (clear_rect
->left
> 0 || clear_rect
->top
> 0
601 || clear_rect
->right
< target
->resource
.width
602 || clear_rect
->bottom
< target
->resource
.height
))
608 static void prepare_ds_clear(struct wined3d_surface
*ds
, struct wined3d_context
*context
,
609 DWORD location
, const RECT
*draw_rect
, UINT rect_count
, const RECT
*clear_rect
)
611 RECT current_rect
, r
;
613 if (ds
->flags
& location
)
614 SetRect(¤t_rect
, 0, 0,
615 ds
->ds_current_size
.cx
,
616 ds
->ds_current_size
.cy
);
618 SetRectEmpty(¤t_rect
);
620 IntersectRect(&r
, draw_rect
, ¤t_rect
);
621 if (EqualRect(&r
, draw_rect
))
623 /* current_rect ⊇ draw_rect, modify only. */
624 surface_modify_ds_location(ds
, location
, ds
->ds_current_size
.cx
, ds
->ds_current_size
.cy
);
628 if (EqualRect(&r
, ¤t_rect
))
630 /* draw_rect ⊇ current_rect, test if we're doing a full clear. */
634 /* Full clear, modify only. */
635 surface_modify_ds_location(ds
, location
, draw_rect
->right
, draw_rect
->bottom
);
639 IntersectRect(&r
, draw_rect
, clear_rect
);
640 if (EqualRect(&r
, draw_rect
))
642 /* clear_rect ⊇ draw_rect, modify only. */
643 surface_modify_ds_location(ds
, location
, draw_rect
->right
, draw_rect
->bottom
);
649 surface_load_ds_location(ds
, context
, location
);
650 surface_modify_ds_location(ds
, location
, ds
->ds_current_size
.cx
, ds
->ds_current_size
.cy
);
653 /* Do not call while under the GL lock. */
654 HRESULT
device_clear_render_targets(IWineD3DDeviceImpl
*device
, UINT rt_count
, struct wined3d_surface
**rts
,
655 struct wined3d_surface
*depth_stencil
, UINT rect_count
, const RECT
*rects
, const RECT
*draw_rect
,
656 DWORD flags
, const WINED3DCOLORVALUE
*color
, float depth
, DWORD stencil
)
658 const RECT
*clear_rect
= (rect_count
> 0 && rects
) ? (const RECT
*)rects
: NULL
;
659 struct wined3d_surface
*target
= rt_count
? rts
[0] : NULL
;
660 UINT drawable_width
, drawable_height
;
661 struct wined3d_context
*context
;
662 GLbitfield clear_mask
= 0;
663 BOOL render_offscreen
;
666 /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
667 * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
668 * for the cleared parts, and the untouched parts.
670 * If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
671 * anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
672 * the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
673 * checking all this if the dest surface is in the drawable anyway. */
674 if (flags
& WINED3DCLEAR_TARGET
&& !is_full_clear(target
, draw_rect
, clear_rect
))
676 for (i
= 0; i
< rt_count
; ++i
)
678 if (rts
[i
]) surface_load_location(rts
[i
], SFLAG_INDRAWABLE
, NULL
);
682 context
= context_acquire(device
, target
);
685 context_release(context
);
686 WARN("Invalid context, skipping clear.\n");
690 if (!context_apply_clear_state(context
, device
, rt_count
, rts
, depth_stencil
))
692 context_release(context
);
693 WARN("Failed to apply clear state, skipping clear.\n");
699 render_offscreen
= context
->render_offscreen
;
700 target
->get_drawable_size(context
, &drawable_width
, &drawable_height
);
704 render_offscreen
= TRUE
;
705 drawable_width
= depth_stencil
->pow2Width
;
706 drawable_height
= depth_stencil
->pow2Height
;
711 /* Only set the values up once, as they are not changing. */
712 if (flags
& WINED3DCLEAR_STENCIL
)
714 if (context
->gl_info
->supported
[EXT_STENCIL_TWO_SIDE
])
716 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
717 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE
));
720 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_STENCILWRITEMASK
));
721 glClearStencil(stencil
);
722 checkGLcall("glClearStencil");
723 clear_mask
= clear_mask
| GL_STENCIL_BUFFER_BIT
;
726 if (flags
& WINED3DCLEAR_ZBUFFER
)
728 DWORD location
= render_offscreen
? SFLAG_DS_OFFSCREEN
: SFLAG_DS_ONSCREEN
;
730 if (location
== SFLAG_DS_ONSCREEN
&& depth_stencil
!= device
->onscreen_depth_stencil
)
733 device_switch_onscreen_ds(device
, context
, depth_stencil
);
736 prepare_ds_clear(depth_stencil
, context
, location
, draw_rect
, rect_count
, clear_rect
);
737 surface_modify_location(depth_stencil
, SFLAG_INDRAWABLE
, TRUE
);
739 glDepthMask(GL_TRUE
);
740 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_ZWRITEENABLE
));
742 checkGLcall("glClearDepth");
743 clear_mask
= clear_mask
| GL_DEPTH_BUFFER_BIT
;
746 if (flags
& WINED3DCLEAR_TARGET
)
748 for (i
= 0; i
< rt_count
; ++i
)
750 if (rts
[i
]) surface_modify_location(rts
[i
], SFLAG_INDRAWABLE
, TRUE
);
753 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
754 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE
));
755 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1
));
756 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2
));
757 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3
));
758 glClearColor(color
->r
, color
->g
, color
->b
, color
->a
);
759 checkGLcall("glClearColor");
760 clear_mask
= clear_mask
| GL_COLOR_BUFFER_BIT
;
765 if (render_offscreen
)
767 glScissor(draw_rect
->left
, draw_rect
->top
,
768 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
772 glScissor(draw_rect
->left
, drawable_height
- draw_rect
->bottom
,
773 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
775 checkGLcall("glScissor");
777 checkGLcall("glClear");
783 /* Now process each rect in turn. */
784 for (i
= 0; i
< rect_count
; ++i
)
786 /* Note that GL uses lower left, width/height. */
787 IntersectRect(¤t_rect
, draw_rect
, &clear_rect
[i
]);
789 TRACE("clear_rect[%u] %s, current_rect %s.\n", i
,
790 wine_dbgstr_rect(&clear_rect
[i
]),
791 wine_dbgstr_rect(¤t_rect
));
793 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
794 * The rectangle is not cleared, no error is returned, but further rectanlges are
795 * still cleared if they are valid. */
796 if (current_rect
.left
> current_rect
.right
|| current_rect
.top
> current_rect
.bottom
)
798 TRACE("Rectangle with negative dimensions, ignoring.\n");
802 if (render_offscreen
)
804 glScissor(current_rect
.left
, current_rect
.top
,
805 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
809 glScissor(current_rect
.left
, drawable_height
- current_rect
.bottom
,
810 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
812 checkGLcall("glScissor");
815 checkGLcall("glClear");
821 if (wined3d_settings
.strict_draw_ordering
|| (flags
& WINED3DCLEAR_TARGET
822 && target
->container
.type
== WINED3D_CONTAINER_SWAPCHAIN
823 && target
->container
.u
.swapchain
->front_buffer
== target
))
824 wglFlush(); /* Flush to ensure ordering across contexts. */
826 context_release(context
);
832 /**********************************************************
833 * IUnknown parts follows
834 **********************************************************/
836 static HRESULT WINAPI
IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice
*iface
, REFIID riid
, void **object
)
838 TRACE("iface %p, riid %s, object %p.\n", iface
, debugstr_guid(riid
), object
);
840 if (IsEqualGUID(riid
, &IID_IWineD3DDevice
)
841 || IsEqualGUID(riid
, &IID_IUnknown
))
843 IUnknown_AddRef(iface
);
848 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
851 return E_NOINTERFACE
;
854 static ULONG WINAPI
IWineD3DDeviceImpl_AddRef(IWineD3DDevice
*iface
) {
855 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
856 ULONG refCount
= InterlockedIncrement(&This
->ref
);
858 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
862 static ULONG WINAPI
IWineD3DDeviceImpl_Release(IWineD3DDevice
*iface
) {
863 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
864 ULONG refCount
= InterlockedDecrement(&This
->ref
);
866 TRACE("(%p) : Releasing from %d\n", This
, refCount
+ 1);
871 for (i
= 0; i
< sizeof(This
->multistate_funcs
)/sizeof(This
->multistate_funcs
[0]); ++i
) {
872 HeapFree(GetProcessHeap(), 0, This
->multistate_funcs
[i
]);
873 This
->multistate_funcs
[i
] = NULL
;
876 /* TODO: Clean up all the surfaces and textures! */
877 /* NOTE: You must release the parent if the object was created via a callback
878 ** ***************************/
880 if (!list_empty(&This
->resources
))
882 struct wined3d_resource
*resource
;
883 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This
);
885 LIST_FOR_EACH_ENTRY(resource
, &This
->resources
, struct wined3d_resource
, resource_list_entry
)
887 FIXME("Leftover resource %p with type %s (%#x).\n",
888 resource
, debug_d3dresourcetype(resource
->resourceType
), resource
->resourceType
);
892 if(This
->contexts
) ERR("Context array not freed!\n");
893 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
894 This
->haveHardwareCursor
= FALSE
;
896 wined3d_decref(This
->wined3d
);
897 This
->wined3d
= NULL
;
898 HeapFree(GetProcessHeap(), 0, This
);
899 TRACE("Freed device %p\n", This
);
905 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateBuffer(IWineD3DDevice
*iface
, struct wined3d_buffer_desc
*desc
,
906 const void *data
, void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_buffer
**buffer
)
908 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
909 struct wined3d_buffer
*object
;
912 TRACE("iface %p, desc %p, data %p, parent %p, buffer %p\n", iface
, desc
, data
, parent
, buffer
);
914 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
917 ERR("Failed to allocate memory\n");
918 return E_OUTOFMEMORY
;
921 FIXME("Ignoring access flags (pool)\n");
923 hr
= buffer_init(object
, This
, desc
->byte_width
, desc
->usage
, WINED3DFMT_UNKNOWN
,
924 WINED3DPOOL_MANAGED
, GL_ARRAY_BUFFER_ARB
, data
, parent
, parent_ops
);
927 WARN("Failed to initialize buffer, hr %#x.\n", hr
);
928 HeapFree(GetProcessHeap(), 0, object
);
931 object
->desc
= *desc
;
933 TRACE("Created buffer %p.\n", object
);
940 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice
*iface
, UINT Size
, DWORD Usage
,
941 WINED3DPOOL Pool
, void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_buffer
**buffer
)
943 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
944 struct wined3d_buffer
*object
;
947 TRACE("iface %p, size %u, usage %#x, pool %#x, parent %p, parent_ops %p, buffer %p.\n",
948 iface
, Size
, Usage
, Pool
, parent
, parent_ops
, buffer
);
950 if (Pool
== WINED3DPOOL_SCRATCH
)
952 /* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
953 * anyway, SCRATCH vertex buffers aren't usable anywhere
955 WARN("Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL\n");
957 return WINED3DERR_INVALIDCALL
;
960 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
963 ERR("Out of memory\n");
965 return WINED3DERR_OUTOFVIDEOMEMORY
;
968 hr
= buffer_init(object
, This
, Size
, Usage
, WINED3DFMT_VERTEXDATA
,
969 Pool
, GL_ARRAY_BUFFER_ARB
, NULL
, parent
, parent_ops
);
972 WARN("Failed to initialize buffer, hr %#x.\n", hr
);
973 HeapFree(GetProcessHeap(), 0, object
);
977 TRACE("Created buffer %p.\n", object
);
983 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice
*iface
, UINT Length
, DWORD Usage
,
984 WINED3DPOOL Pool
, void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_buffer
**buffer
)
986 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
987 struct wined3d_buffer
*object
;
990 TRACE("iface %p, size %u, usage %#x, pool %#x, parent %p, parent_ops %p, buffer %p.\n",
991 iface
, Length
, Usage
, Pool
, parent
, parent_ops
, buffer
);
993 /* Allocate the storage for the device */
994 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
997 ERR("Out of memory\n");
999 return WINED3DERR_OUTOFVIDEOMEMORY
;
1002 hr
= buffer_init(object
, This
, Length
, Usage
| WINED3DUSAGE_STATICDECL
,
1003 WINED3DFMT_UNKNOWN
, Pool
, GL_ELEMENT_ARRAY_BUFFER_ARB
, NULL
,
1004 parent
, parent_ops
);
1007 WARN("Failed to initialize buffer, hr %#x\n", hr
);
1008 HeapFree(GetProcessHeap(), 0, object
);
1012 TRACE("Created buffer %p.\n", object
);
1019 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice
*iface
,
1020 WINED3DSTATEBLOCKTYPE type
, struct wined3d_stateblock
**stateblock
)
1022 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1023 struct wined3d_stateblock
*object
;
1026 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1029 ERR("Failed to allocate stateblock memory.\n");
1030 return E_OUTOFMEMORY
;
1033 hr
= stateblock_init(object
, This
, type
);
1036 WARN("Failed to initialize stateblock, hr %#x.\n", hr
);
1037 HeapFree(GetProcessHeap(), 0, object
);
1041 TRACE("Created stateblock %p.\n", object
);
1042 *stateblock
= object
;
1047 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice
*iface
, UINT Width
, UINT Height
,
1048 enum wined3d_format_id Format
, BOOL Lockable
, BOOL Discard
, UINT Level
, DWORD Usage
, WINED3DPOOL Pool
,
1049 WINED3DMULTISAMPLE_TYPE MultiSample
, DWORD MultisampleQuality
, WINED3DSURFTYPE Impl
,
1050 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_surface
**surface
)
1052 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1053 struct wined3d_surface
*object
;
1056 TRACE("iface %p, width %u, height %u, format %s (%#x), lockable %#x, discard %#x, level %u\n",
1057 iface
, Width
, Height
, debug_d3dformat(Format
), Format
, Lockable
, Discard
, Level
);
1058 TRACE("surface %p, usage %s (%#x), pool %s (%#x), multisample_type %#x, multisample_quality %u\n",
1059 surface
, debug_d3dusage(Usage
), Usage
, debug_d3dpool(Pool
), Pool
, MultiSample
, MultisampleQuality
);
1060 TRACE("surface_type %#x, parent %p, parent_ops %p.\n", Impl
, parent
, parent_ops
);
1062 if (Impl
== SURFACE_OPENGL
&& !This
->adapter
)
1064 ERR("OpenGL surfaces are not available without OpenGL.\n");
1065 return WINED3DERR_NOTAVAILABLE
;
1068 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1071 ERR("Failed to allocate surface memory.\n");
1072 return WINED3DERR_OUTOFVIDEOMEMORY
;
1075 hr
= surface_init(object
, Impl
, This
->surface_alignment
, Width
, Height
, Level
, Lockable
,
1076 Discard
, MultiSample
, MultisampleQuality
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1079 WARN("Failed to initialize surface, returning %#x.\n", hr
);
1080 HeapFree(GetProcessHeap(), 0, object
);
1084 TRACE("(%p) : Created surface %p\n", This
, object
);
1091 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateRendertargetView(IWineD3DDevice
*iface
,
1092 struct wined3d_resource
*resource
, void *parent
, struct wined3d_rendertarget_view
**rendertarget_view
)
1094 struct wined3d_rendertarget_view
*object
;
1096 TRACE("iface %p, resource %p, parent %p, rendertarget_view %p.\n",
1097 iface
, resource
, parent
, rendertarget_view
);
1099 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1102 ERR("Failed to allocate memory\n");
1103 return E_OUTOFMEMORY
;
1106 wined3d_rendertarget_view_init(object
, resource
, parent
);
1108 TRACE("Created render target view %p.\n", object
);
1109 *rendertarget_view
= object
;
1114 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice
*iface
,
1115 UINT Width
, UINT Height
, UINT Levels
, DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
,
1116 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_texture
**texture
)
1118 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1119 struct wined3d_texture
*object
;
1122 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This
, Width
, Height
, Levels
, Usage
);
1123 TRACE("Format %#x (%s), Pool %#x, texture %p, parent %p\n",
1124 Format
, debug_d3dformat(Format
), Pool
, texture
, parent
);
1126 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1129 ERR("Out of memory\n");
1131 return WINED3DERR_OUTOFVIDEOMEMORY
;
1134 hr
= texture_init(object
, Width
, Height
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1137 WARN("Failed to initialize texture, returning %#x\n", hr
);
1138 HeapFree(GetProcessHeap(), 0, object
);
1145 TRACE("(%p) : Created texture %p\n", This
, object
);
1150 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice
*iface
,
1151 UINT Width
, UINT Height
, UINT Depth
, UINT Levels
, DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
,
1152 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_texture
**texture
)
1154 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1155 struct wined3d_texture
*object
;
1158 TRACE("(%p) : W(%u) H(%u) D(%u), Lvl(%u) Usage(%#x), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1159 Depth
, Levels
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1161 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1164 ERR("Out of memory\n");
1166 return WINED3DERR_OUTOFVIDEOMEMORY
;
1169 hr
= volumetexture_init(object
, Width
, Height
, Depth
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1172 WARN("Failed to initialize volumetexture, returning %#x\n", hr
);
1173 HeapFree(GetProcessHeap(), 0, object
);
1178 TRACE("(%p) : Created volume texture %p.\n", This
, object
);
1184 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice
*iface
, UINT Width
, UINT Height
,
1185 UINT Depth
, DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
, void *parent
,
1186 const struct wined3d_parent_ops
*parent_ops
, struct wined3d_volume
**volume
)
1188 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1189 struct wined3d_volume
*object
;
1192 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This
, Width
, Height
,
1193 Depth
, Usage
, Format
, debug_d3dformat(Format
), debug_d3dpool(Pool
));
1195 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1198 ERR("Out of memory\n");
1200 return WINED3DERR_OUTOFVIDEOMEMORY
;
1203 hr
= volume_init(object
, This
, Width
, Height
, Depth
, Usage
, Format
, Pool
, parent
, parent_ops
);
1206 WARN("Failed to initialize volume, returning %#x.\n", hr
);
1207 HeapFree(GetProcessHeap(), 0, object
);
1211 TRACE("(%p) : Created volume %p.\n", This
, object
);
1217 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice
*iface
, UINT EdgeLength
, UINT Levels
,
1218 DWORD Usage
, enum wined3d_format_id Format
, WINED3DPOOL Pool
, void *parent
,
1219 const struct wined3d_parent_ops
*parent_ops
, struct wined3d_texture
**texture
)
1221 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1222 struct wined3d_texture
*object
;
1225 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1228 ERR("Out of memory\n");
1230 return WINED3DERR_OUTOFVIDEOMEMORY
;
1233 hr
= cubetexture_init(object
, EdgeLength
, Levels
, This
, Usage
, Format
, Pool
, parent
, parent_ops
);
1236 WARN("Failed to initialize cubetexture, returning %#x\n", hr
);
1237 HeapFree(GetProcessHeap(), 0, object
);
1242 TRACE("(%p) : Created Cube Texture %p\n", This
, object
);
1248 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice
*iface
,
1249 WINED3DQUERYTYPE type
, struct wined3d_query
**query
)
1251 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1252 struct wined3d_query
*object
;
1255 TRACE("iface %p, type %#x, query %p.\n", iface
, type
, query
);
1257 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1260 ERR("Failed to allocate query memory.\n");
1261 return E_OUTOFMEMORY
;
1264 hr
= query_init(object
, This
, type
);
1267 WARN("Failed to initialize query, hr %#x.\n", hr
);
1268 HeapFree(GetProcessHeap(), 0, object
);
1272 TRACE("Created query %p.\n", object
);
1278 /* Do not call while under the GL lock. */
1279 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice
*iface
,
1280 WINED3DPRESENT_PARAMETERS
*present_parameters
, WINED3DSURFTYPE surface_type
,
1281 void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1282 struct wined3d_swapchain
**swapchain
)
1284 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1285 struct wined3d_swapchain
*object
;
1288 TRACE("iface %p, present_parameters %p, swapchain %p, parent %p, surface_type %#x.\n",
1289 iface
, present_parameters
, swapchain
, parent
, surface_type
);
1291 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1294 ERR("Failed to allocate swapchain memory.\n");
1295 return E_OUTOFMEMORY
;
1298 hr
= swapchain_init(object
, surface_type
, This
, present_parameters
, parent
, parent_ops
);
1301 WARN("Failed to initialize swapchain, hr %#x.\n", hr
);
1302 HeapFree(GetProcessHeap(), 0, object
);
1306 TRACE("Created swapchain %p.\n", object
);
1307 *swapchain
= object
;
1312 static UINT WINAPI
IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice
*iface
)
1314 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1316 TRACE("iface %p.\n", iface
);
1318 return device
->swapchain_count
;
1321 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice
*iface
,
1322 UINT swapchain_idx
, struct wined3d_swapchain
**swapchain
)
1324 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1326 TRACE("iface %p, swapchain_idx %u, swapchain %p.\n",
1327 iface
, swapchain_idx
, swapchain
);
1329 if (swapchain_idx
>= device
->swapchain_count
)
1331 WARN("swapchain_idx %u >= swapchain_count %u.\n",
1332 swapchain_idx
, device
->swapchain_count
);
1335 return WINED3DERR_INVALIDCALL
;
1338 *swapchain
= device
->swapchains
[swapchain_idx
];
1339 wined3d_swapchain_incref(*swapchain
);
1340 TRACE("Returning %p.\n", *swapchain
);
1345 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice
*iface
,
1346 const WINED3DVERTEXELEMENT
*elements
, UINT element_count
, void *parent
,
1347 const struct wined3d_parent_ops
*parent_ops
, struct wined3d_vertex_declaration
**declaration
)
1349 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1350 struct wined3d_vertex_declaration
*object
;
1353 TRACE("iface %p, elements %p, element_count %u, parent %p, parent_ops %p, declaration %p.\n",
1354 iface
, elements
, element_count
, parent
, parent_ops
, declaration
);
1356 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1359 ERR("Failed to allocate vertex declaration memory.\n");
1360 return E_OUTOFMEMORY
;
1363 hr
= vertexdeclaration_init(object
, This
, elements
, element_count
, parent
, parent_ops
);
1366 WARN("Failed to initialize vertex declaration, hr %#x.\n", hr
);
1367 HeapFree(GetProcessHeap(), 0, object
);
1371 TRACE("Created vertex declaration %p.\n", object
);
1372 *declaration
= object
;
1377 struct wined3d_fvf_convert_state
1379 const struct wined3d_gl_info
*gl_info
;
1380 WINED3DVERTEXELEMENT
*elements
;
1385 static void append_decl_element(struct wined3d_fvf_convert_state
*state
,
1386 enum wined3d_format_id format_id
, WINED3DDECLUSAGE usage
, UINT usage_idx
)
1388 WINED3DVERTEXELEMENT
*elements
= state
->elements
;
1389 const struct wined3d_format
*format
;
1390 UINT offset
= state
->offset
;
1391 UINT idx
= state
->idx
;
1393 elements
[idx
].format
= format_id
;
1394 elements
[idx
].input_slot
= 0;
1395 elements
[idx
].offset
= offset
;
1396 elements
[idx
].output_slot
= 0;
1397 elements
[idx
].method
= WINED3DDECLMETHOD_DEFAULT
;
1398 elements
[idx
].usage
= usage
;
1399 elements
[idx
].usage_idx
= usage_idx
;
1401 format
= wined3d_get_format(state
->gl_info
, format_id
);
1402 state
->offset
+= format
->component_count
* format
->component_size
;
1406 static unsigned int ConvertFvfToDeclaration(IWineD3DDeviceImpl
*This
, /* For the GL info, which has the type table */
1407 DWORD fvf
, WINED3DVERTEXELEMENT
**ppVertexElements
)
1409 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1410 BOOL has_pos
= !!(fvf
& WINED3DFVF_POSITION_MASK
);
1411 BOOL has_blend
= (fvf
& WINED3DFVF_XYZB5
) > WINED3DFVF_XYZRHW
;
1412 BOOL has_blend_idx
= has_blend
&&
1413 (((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB5
) ||
1414 (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
) ||
1415 (fvf
& WINED3DFVF_LASTBETA_UBYTE4
));
1416 BOOL has_normal
= !!(fvf
& WINED3DFVF_NORMAL
);
1417 BOOL has_psize
= !!(fvf
& WINED3DFVF_PSIZE
);
1418 BOOL has_diffuse
= !!(fvf
& WINED3DFVF_DIFFUSE
);
1419 BOOL has_specular
= !!(fvf
& WINED3DFVF_SPECULAR
);
1421 DWORD num_textures
= (fvf
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
1422 DWORD texcoords
= (fvf
& 0xFFFF0000) >> 16;
1423 struct wined3d_fvf_convert_state state
;
1426 DWORD num_blends
= 1 + (((fvf
& WINED3DFVF_XYZB5
) - WINED3DFVF_XYZB1
) >> 1);
1427 if (has_blend_idx
) num_blends
--;
1429 /* Compute declaration size */
1430 size
= has_pos
+ (has_blend
&& num_blends
> 0) + has_blend_idx
+ has_normal
+
1431 has_psize
+ has_diffuse
+ has_specular
+ num_textures
;
1433 state
.gl_info
= gl_info
;
1434 state
.elements
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(*state
.elements
));
1435 if (!state
.elements
) return ~0U;
1441 if (!has_blend
&& (fvf
& WINED3DFVF_XYZRHW
))
1442 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_POSITIONT
, 0);
1443 else if ((fvf
& WINED3DFVF_XYZW
) == WINED3DFVF_XYZW
)
1444 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_POSITION
, 0);
1446 append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_POSITION
, 0);
1449 if (has_blend
&& (num_blends
> 0))
1451 if ((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
&& (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
))
1452 append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1458 append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1461 append_decl_element(&state
, WINED3DFMT_R32G32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1464 append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1467 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_BLENDWEIGHT
, 0);
1470 ERR("Unexpected amount of blend values: %u\n", num_blends
);
1477 if ((fvf
& WINED3DFVF_LASTBETA_UBYTE4
)
1478 || ((fvf
& WINED3DFVF_XYZB5
) == WINED3DFVF_XYZB2
&& (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)))
1479 append_decl_element(&state
, WINED3DFMT_R8G8B8A8_UINT
, WINED3DDECLUSAGE_BLENDINDICES
, 0);
1480 else if (fvf
& WINED3DFVF_LASTBETA_D3DCOLOR
)
1481 append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_BLENDINDICES
, 0);
1483 append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_BLENDINDICES
, 0);
1486 if (has_normal
) append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_NORMAL
, 0);
1487 if (has_psize
) append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_PSIZE
, 0);
1488 if (has_diffuse
) append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_COLOR
, 0);
1489 if (has_specular
) append_decl_element(&state
, WINED3DFMT_B8G8R8A8_UNORM
, WINED3DDECLUSAGE_COLOR
, 1);
1491 for (idx
= 0; idx
< num_textures
; ++idx
)
1493 switch ((texcoords
>> (idx
* 2)) & 0x03)
1495 case WINED3DFVF_TEXTUREFORMAT1
:
1496 append_decl_element(&state
, WINED3DFMT_R32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1498 case WINED3DFVF_TEXTUREFORMAT2
:
1499 append_decl_element(&state
, WINED3DFMT_R32G32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1501 case WINED3DFVF_TEXTUREFORMAT3
:
1502 append_decl_element(&state
, WINED3DFMT_R32G32B32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1504 case WINED3DFVF_TEXTUREFORMAT4
:
1505 append_decl_element(&state
, WINED3DFMT_R32G32B32A32_FLOAT
, WINED3DDECLUSAGE_TEXCOORD
, idx
);
1510 *ppVertexElements
= state
.elements
;
1514 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF(IWineD3DDevice
*iface
,
1515 DWORD fvf
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1516 struct wined3d_vertex_declaration
**declaration
)
1518 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1519 WINED3DVERTEXELEMENT
*elements
;
1523 TRACE("iface %p, fvf %#x, parent %p, parent_ops %p, declaration %p.\n",
1524 iface
, fvf
, parent
, parent_ops
, declaration
);
1526 size
= ConvertFvfToDeclaration(This
, fvf
, &elements
);
1527 if (size
== ~0U) return E_OUTOFMEMORY
;
1529 hr
= IWineD3DDeviceImpl_CreateVertexDeclaration(iface
, elements
, size
, parent
, parent_ops
, declaration
);
1530 HeapFree(GetProcessHeap(), 0, elements
);
1534 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice
*iface
,
1535 const DWORD
*pFunction
, const struct wined3d_shader_signature
*output_signature
,
1536 void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1537 struct wined3d_shader
**shader
)
1539 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1540 struct wined3d_shader
*object
;
1543 if (This
->vs_selected_mode
== SHADER_NONE
)
1544 return WINED3DERR_INVALIDCALL
;
1546 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1549 ERR("Failed to allocate shader memory.\n");
1550 return E_OUTOFMEMORY
;
1553 hr
= vertexshader_init(object
, This
, pFunction
, output_signature
, parent
, parent_ops
);
1556 WARN("Failed to initialize vertex shader, hr %#x.\n", hr
);
1557 HeapFree(GetProcessHeap(), 0, object
);
1561 TRACE("Created vertex shader %p.\n", object
);
1567 static HRESULT WINAPI
IWineD3DDeviceImpl_CreateGeometryShader(IWineD3DDevice
*iface
,
1568 const DWORD
*byte_code
, const struct wined3d_shader_signature
*output_signature
,
1569 void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1570 struct wined3d_shader
**shader
)
1572 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1573 struct wined3d_shader
*object
;
1576 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1579 ERR("Failed to allocate shader memory.\n");
1580 return E_OUTOFMEMORY
;
1583 hr
= geometryshader_init(object
, This
, byte_code
, output_signature
, parent
, parent_ops
);
1586 WARN("Failed to initialize geometry shader, hr %#x.\n", hr
);
1587 HeapFree(GetProcessHeap(), 0, object
);
1591 TRACE("Created geometry shader %p.\n", object
);
1597 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice
*iface
,
1598 const DWORD
*pFunction
, const struct wined3d_shader_signature
*output_signature
,
1599 void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1600 struct wined3d_shader
**shader
)
1602 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
1603 struct wined3d_shader
*object
;
1606 if (This
->ps_selected_mode
== SHADER_NONE
)
1607 return WINED3DERR_INVALIDCALL
;
1609 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1612 ERR("Failed to allocate shader memory.\n");
1613 return E_OUTOFMEMORY
;
1616 hr
= pixelshader_init(object
, This
, pFunction
, output_signature
, parent
, parent_ops
);
1619 WARN("Failed to initialize pixel shader, hr %#x.\n", hr
);
1620 HeapFree(GetProcessHeap(), 0, object
);
1624 TRACE("Created pixel shader %p.\n", object
);
1630 static HRESULT WINAPI
IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice
*iface
, DWORD flags
,
1631 const PALETTEENTRY
*entries
, void *parent
, struct wined3d_palette
**palette
)
1633 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1634 struct wined3d_palette
*object
;
1637 TRACE("iface %p, flags %#x, entries %p, palette %p, parent %p.\n",
1638 iface
, flags
, entries
, palette
, parent
);
1640 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
1643 ERR("Failed to allocate palette memory.\n");
1644 return E_OUTOFMEMORY
;
1647 hr
= wined3d_palette_init(object
, This
, flags
, entries
, parent
);
1650 WARN("Failed to initialize palette, hr %#x.\n", hr
);
1651 HeapFree(GetProcessHeap(), 0, object
);
1655 TRACE("Created palette %p.\n", object
);
1661 static void IWineD3DDeviceImpl_LoadLogo(IWineD3DDeviceImpl
*This
, const char *filename
) {
1665 HDC dcb
= NULL
, dcs
= NULL
;
1666 WINEDDCOLORKEY colorkey
;
1668 hbm
= LoadImageA(NULL
, filename
, IMAGE_BITMAP
, 0, 0, LR_LOADFROMFILE
| LR_CREATEDIBSECTION
);
1671 GetObjectA(hbm
, sizeof(BITMAP
), &bm
);
1672 dcb
= CreateCompatibleDC(NULL
);
1674 SelectObject(dcb
, hbm
);
1678 /* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
1679 * couldn't be loaded
1681 memset(&bm
, 0, sizeof(bm
));
1686 hr
= IWineD3DDevice_CreateSurface((IWineD3DDevice
*)This
, bm
.bmWidth
, bm
.bmHeight
, WINED3DFMT_B5G6R5_UNORM
, TRUE
,
1687 FALSE
, 0, 0, WINED3DPOOL_DEFAULT
, WINED3DMULTISAMPLE_NONE
, 0, SURFACE_OPENGL
, NULL
,
1688 &wined3d_null_parent_ops
, &This
->logo_surface
);
1691 ERR("Wine logo requested, but failed to create surface, hr %#x.\n", hr
);
1697 if (FAILED(hr
= wined3d_surface_getdc(This
->logo_surface
, &dcs
)))
1699 BitBlt(dcs
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, dcb
, 0, 0, SRCCOPY
);
1700 wined3d_surface_releasedc(This
->logo_surface
, dcs
);
1702 colorkey
.dwColorSpaceLowValue
= 0;
1703 colorkey
.dwColorSpaceHighValue
= 0;
1704 wined3d_surface_set_color_key(This
->logo_surface
, WINEDDCKEY_SRCBLT
, &colorkey
);
1708 const WINED3DCOLORVALUE c
= {1.0f
, 1.0f
, 1.0f
, 1.0f
};
1709 /* Fill the surface with a white color to show that wined3d is there */
1710 IWineD3DDevice_ColorFill((IWineD3DDevice
*)This
, This
->logo_surface
, NULL
, &c
);
1714 if (dcb
) DeleteDC(dcb
);
1715 if (hbm
) DeleteObject(hbm
);
1718 /* Context activation is done by the caller. */
1719 static void create_dummy_textures(IWineD3DDeviceImpl
*This
)
1721 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1723 /* Under DirectX you can have texture stage operations even if no texture is
1724 bound, whereas opengl will only do texture operations when a valid texture is
1725 bound. We emulate this by creating dummy textures and binding them to each
1726 texture stage, but disable all stages by default. Hence if a stage is enabled
1727 then the default texture will kick in until replaced by a SetTexture call */
1730 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
1732 /* The dummy texture does not have client storage backing */
1733 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
1734 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
1737 for (i
= 0; i
< gl_info
->limits
.textures
; ++i
)
1739 GLubyte white
= 255;
1741 /* Make appropriate texture active */
1742 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ i
));
1743 checkGLcall("glActiveTextureARB");
1745 /* Generate an opengl texture name */
1746 glGenTextures(1, &This
->dummyTextureName
[i
]);
1747 checkGLcall("glGenTextures");
1748 TRACE("Dummy Texture %d given name %d\n", i
, This
->dummyTextureName
[i
]);
1750 /* Generate a dummy 2d texture (not using 1d because they cause many
1751 * DRI drivers fall back to sw) */
1752 glBindTexture(GL_TEXTURE_2D
, This
->dummyTextureName
[i
]);
1753 checkGLcall("glBindTexture");
1755 glTexImage2D(GL_TEXTURE_2D
, 0, GL_LUMINANCE
, 1, 1, 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, &white
);
1756 checkGLcall("glTexImage2D");
1759 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
1761 /* Reenable because if supported it is enabled by default */
1762 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
1763 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
1769 /* Context activation is done by the caller. */
1770 static void destroy_dummy_textures(IWineD3DDeviceImpl
*device
, const struct wined3d_gl_info
*gl_info
)
1773 glDeleteTextures(gl_info
->limits
.textures
, device
->dummyTextureName
);
1774 checkGLcall("glDeleteTextures(gl_info->limits.textures, device->dummyTextureName)");
1777 memset(device
->dummyTextureName
, 0, gl_info
->limits
.textures
* sizeof(*device
->dummyTextureName
));
1780 static LONG
fullscreen_style(LONG style
)
1782 /* Make sure the window is managed, otherwise we won't get keyboard input. */
1783 style
|= WS_POPUP
| WS_SYSMENU
;
1784 style
&= ~(WS_CAPTION
| WS_THICKFRAME
);
1789 static LONG
fullscreen_exstyle(LONG exstyle
)
1791 /* Filter out window decorations. */
1792 exstyle
&= ~(WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
);
1797 static void WINAPI
IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice
*iface
, HWND window
, UINT w
, UINT h
)
1799 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1800 BOOL filter_messages
;
1801 LONG style
, exstyle
;
1803 TRACE("Setting up window %p for fullscreen mode.\n", window
);
1805 if (device
->style
|| device
->exStyle
)
1807 ERR("Changing the window style for window %p, but another style (%08x, %08x) is already stored.\n",
1808 window
, device
->style
, device
->exStyle
);
1811 device
->style
= GetWindowLongW(window
, GWL_STYLE
);
1812 device
->exStyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1814 style
= fullscreen_style(device
->style
);
1815 exstyle
= fullscreen_exstyle(device
->exStyle
);
1817 TRACE("Old style was %08x, %08x, setting to %08x, %08x.\n",
1818 device
->style
, device
->exStyle
, style
, exstyle
);
1820 filter_messages
= device
->filter_messages
;
1821 device
->filter_messages
= TRUE
;
1823 SetWindowLongW(window
, GWL_STYLE
, style
);
1824 SetWindowLongW(window
, GWL_EXSTYLE
, exstyle
);
1825 SetWindowPos(window
, HWND_TOP
, 0, 0, w
, h
, SWP_FRAMECHANGED
| SWP_SHOWWINDOW
| SWP_NOACTIVATE
);
1827 device
->filter_messages
= filter_messages
;
1830 static void WINAPI
IWineD3DDeviceImpl_RestoreFullscreenWindow(IWineD3DDevice
*iface
, HWND window
)
1832 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1833 BOOL filter_messages
;
1834 LONG style
, exstyle
;
1836 if (!device
->style
&& !device
->exStyle
) return;
1838 TRACE("Restoring window style of window %p to %08x, %08x.\n",
1839 window
, device
->style
, device
->exStyle
);
1841 style
= GetWindowLongW(window
, GWL_STYLE
);
1842 exstyle
= GetWindowLongW(window
, GWL_EXSTYLE
);
1844 filter_messages
= device
->filter_messages
;
1845 device
->filter_messages
= TRUE
;
1847 /* Only restore the style if the application didn't modify it during the
1848 * fullscreen phase. Some applications change it before calling Reset()
1849 * when switching between windowed and fullscreen modes (HL2), some
1850 * depend on the original style (Eve Online). */
1851 if (style
== fullscreen_style(device
->style
) && exstyle
== fullscreen_exstyle(device
->exStyle
))
1853 SetWindowLongW(window
, GWL_STYLE
, device
->style
);
1854 SetWindowLongW(window
, GWL_EXSTYLE
, device
->exStyle
);
1856 SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1858 device
->filter_messages
= filter_messages
;
1860 /* Delete the old values. */
1862 device
->exStyle
= 0;
1865 static HRESULT WINAPI
IWineD3DDeviceImpl_AcquireFocusWindow(IWineD3DDevice
*iface
, HWND window
)
1867 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1869 TRACE("iface %p, window %p.\n", iface
, window
);
1871 if (!wined3d_register_window(window
, device
))
1873 ERR("Failed to register window %p.\n", window
);
1877 device
->focus_window
= window
;
1878 SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
1883 static void WINAPI
IWineD3DDeviceImpl_ReleaseFocusWindow(IWineD3DDevice
*iface
)
1885 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
1887 TRACE("iface %p.\n", iface
);
1889 if (device
->focus_window
) wined3d_unregister_window(device
->focus_window
);
1890 device
->focus_window
= NULL
;
1893 static HRESULT WINAPI
IWineD3DDeviceImpl_Init3D(IWineD3DDevice
*iface
,
1894 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
1896 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
1897 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
1898 struct wined3d_swapchain
*swapchain
= NULL
;
1899 struct wined3d_context
*context
;
1904 TRACE("(%p)->(%p)\n", This
, pPresentationParameters
);
1906 if(This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
1907 if(!This
->adapter
->opengl
) return WINED3DERR_INVALIDCALL
;
1909 TRACE("(%p) : Creating stateblock\n", This
);
1910 hr
= IWineD3DDevice_CreateStateBlock(iface
, WINED3DSBT_INIT
, &This
->stateBlock
);
1913 WARN("Failed to create stateblock\n");
1916 TRACE("(%p) : Created stateblock (%p)\n", This
, This
->stateBlock
);
1917 This
->updateStateBlock
= This
->stateBlock
;
1918 wined3d_stateblock_incref(This
->updateStateBlock
);
1920 This
->render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1921 sizeof(*This
->render_targets
) * gl_info
->limits
.buffers
);
1923 This
->palette_count
= 1;
1924 This
->palettes
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(PALETTEENTRY
*));
1925 if (!This
->palettes
|| !This
->render_targets
)
1927 ERR("Out of memory!\n");
1931 This
->palettes
[0] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
1932 if(!This
->palettes
[0]) {
1933 ERR("Out of memory!\n");
1937 for (i
= 0; i
< 256; ++i
) {
1938 This
->palettes
[0][i
].peRed
= 0xFF;
1939 This
->palettes
[0][i
].peGreen
= 0xFF;
1940 This
->palettes
[0][i
].peBlue
= 0xFF;
1941 This
->palettes
[0][i
].peFlags
= 0xFF;
1943 This
->currentPalette
= 0;
1945 /* Initialize the texture unit mapping to a 1:1 mapping */
1946 for (state
= 0; state
< MAX_COMBINED_SAMPLERS
; ++state
)
1948 if (state
< gl_info
->limits
.fragment_samplers
)
1950 This
->texUnitMap
[state
] = state
;
1951 This
->rev_tex_unit_map
[state
] = state
;
1953 This
->texUnitMap
[state
] = WINED3D_UNMAPPED_STAGE
;
1954 This
->rev_tex_unit_map
[state
] = WINED3D_UNMAPPED_STAGE
;
1958 /* Setup the implicit swapchain. This also initializes a context. */
1959 TRACE("Creating implicit swapchain\n");
1960 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
1961 pPresentationParameters
, &swapchain
);
1964 WARN("Failed to create implicit swapchain\n");
1968 This
->swapchain_count
= 1;
1969 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->swapchain_count
* sizeof(*This
->swapchains
));
1970 if (!This
->swapchains
)
1972 ERR("Out of memory!\n");
1975 This
->swapchains
[0] = swapchain
;
1977 if (swapchain
->back_buffers
&& swapchain
->back_buffers
[0])
1979 TRACE("Setting rendertarget to %p.\n", swapchain
->back_buffers
);
1980 This
->render_targets
[0] = swapchain
->back_buffers
[0];
1984 TRACE("Setting rendertarget to %p.\n", swapchain
->front_buffer
);
1985 This
->render_targets
[0] = swapchain
->front_buffer
;
1987 wined3d_surface_incref(This
->render_targets
[0]);
1989 /* Depth Stencil support */
1990 This
->depth_stencil
= This
->auto_depth_stencil
;
1991 if (This
->depth_stencil
)
1992 wined3d_surface_incref(This
->depth_stencil
);
1994 hr
= This
->shader_backend
->shader_alloc_private(This
);
1996 TRACE("Shader private data couldn't be allocated\n");
1999 hr
= This
->frag_pipe
->alloc_private(This
);
2001 TRACE("Fragment pipeline private data couldn't be allocated\n");
2004 hr
= This
->blitter
->alloc_private(This
);
2006 TRACE("Blitter private data couldn't be allocated\n");
2010 /* Set up some starting GL setup */
2012 /* Setup all the devices defaults */
2013 stateblock_init_default_state(This
->stateBlock
);
2015 context
= context_acquire(This
, swapchain
->front_buffer
);
2017 create_dummy_textures(This
);
2021 /* Initialize the current view state */
2022 This
->view_ident
= 1;
2023 This
->contexts
[0]->last_was_rhw
= 0;
2024 glGetIntegerv(GL_MAX_LIGHTS
, &This
->maxConcurrentLights
);
2025 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
2027 switch(wined3d_settings
.offscreen_rendering_mode
) {
2029 This
->offscreenBuffer
= GL_COLOR_ATTACHMENT0
;
2032 case ORM_BACKBUFFER
:
2034 if (context_get_current()->aux_buffers
> 0)
2036 TRACE("Using auxilliary buffer for offscreen rendering\n");
2037 This
->offscreenBuffer
= GL_AUX0
;
2039 TRACE("Using back buffer for offscreen rendering\n");
2040 This
->offscreenBuffer
= GL_BACK
;
2045 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This
, This
);
2048 context_release(context
);
2050 /* Clear the screen */
2051 IWineD3DDevice_Clear((IWineD3DDevice
*) This
, 0, NULL
,
2052 WINED3DCLEAR_TARGET
| (pPresentationParameters
->EnableAutoDepthStencil
? WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
: 0),
2055 This
->d3d_initialized
= TRUE
;
2057 if(wined3d_settings
.logo
) {
2058 IWineD3DDeviceImpl_LoadLogo(This
, wined3d_settings
.logo
);
2060 This
->highest_dirty_ps_const
= 0;
2061 This
->highest_dirty_vs_const
= 0;
2065 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2066 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2067 This
->swapchain_count
= 0;
2070 HeapFree(GetProcessHeap(), 0, This
->palettes
[0]);
2071 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2073 This
->palette_count
= 0;
2075 wined3d_swapchain_decref(swapchain
);
2076 if (This
->stateBlock
)
2078 wined3d_stateblock_decref(This
->stateBlock
);
2079 This
->stateBlock
= NULL
;
2081 if (This
->blit_priv
) {
2082 This
->blitter
->free_private(This
);
2084 if (This
->fragment_priv
) {
2085 This
->frag_pipe
->free_private(This
);
2087 if (This
->shader_priv
) {
2088 This
->shader_backend
->shader_free_private(This
);
2093 static HRESULT WINAPI
IWineD3DDeviceImpl_InitGDI(IWineD3DDevice
*iface
,
2094 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
2096 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2097 struct wined3d_swapchain
*swapchain
= NULL
;
2100 /* Setup the implicit swapchain */
2101 TRACE("Creating implicit swapchain\n");
2102 hr
= IWineD3DDeviceParent_CreateSwapChain(This
->device_parent
,
2103 pPresentationParameters
, &swapchain
);
2106 WARN("Failed to create implicit swapchain\n");
2110 This
->swapchain_count
= 1;
2111 This
->swapchains
= HeapAlloc(GetProcessHeap(), 0, This
->swapchain_count
* sizeof(*This
->swapchains
));
2112 if (!This
->swapchains
)
2114 ERR("Out of memory!\n");
2117 This
->swapchains
[0] = swapchain
;
2121 wined3d_swapchain_decref(swapchain
);
2125 static HRESULT WINAPI
device_unload_resource(struct wined3d_resource
*resource
, void *data
)
2127 TRACE("Unloading resource %p.\n", resource
);
2129 resource
->resource_ops
->resource_unload(resource
);
2134 static HRESULT WINAPI
IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice
*iface
)
2136 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2137 const struct wined3d_gl_info
*gl_info
;
2138 struct wined3d_context
*context
;
2139 struct wined3d_surface
*surface
;
2141 TRACE("(%p)\n", This
);
2143 if(!This
->d3d_initialized
) return WINED3DERR_INVALIDCALL
;
2145 /* Force making the context current again, to verify it is still valid
2146 * (workaround for broken drivers) */
2147 context_set_current(NULL
);
2148 /* I don't think that the interface guarantees that the device is destroyed from the same thread
2149 * it was created. Thus make sure a context is active for the glDelete* calls
2151 context
= context_acquire(This
, NULL
);
2152 gl_info
= context
->gl_info
;
2154 if (This
->logo_surface
)
2155 wined3d_surface_decref(This
->logo_surface
);
2157 /* Unload resources */
2158 IWineD3DDevice_EnumResources(iface
, device_unload_resource
, NULL
);
2160 TRACE("Deleting high order patches\n");
2161 for(i
= 0; i
< PATCHMAP_SIZE
; i
++) {
2162 struct list
*e1
, *e2
;
2163 struct WineD3DRectPatch
*patch
;
2164 LIST_FOR_EACH_SAFE(e1
, e2
, &This
->patches
[i
]) {
2165 patch
= LIST_ENTRY(e1
, struct WineD3DRectPatch
, entry
);
2166 IWineD3DDevice_DeletePatch(iface
, patch
->Handle
);
2170 /* Delete the mouse cursor texture */
2171 if(This
->cursorTexture
) {
2173 glDeleteTextures(1, &This
->cursorTexture
);
2175 This
->cursorTexture
= 0;
2178 /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
2179 * private data, it might contain opengl pointers
2181 if(This
->depth_blt_texture
) {
2183 glDeleteTextures(1, &This
->depth_blt_texture
);
2185 This
->depth_blt_texture
= 0;
2187 if (This
->depth_blt_rb
) {
2189 gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &This
->depth_blt_rb
);
2191 This
->depth_blt_rb
= 0;
2192 This
->depth_blt_rb_w
= 0;
2193 This
->depth_blt_rb_h
= 0;
2196 /* Release the update stateblock */
2197 if (wined3d_stateblock_decref(This
->updateStateBlock
))
2199 if (This
->updateStateBlock
!= This
->stateBlock
)
2200 FIXME("Something's still holding the update stateblock.\n");
2202 This
->updateStateBlock
= NULL
;
2205 struct wined3d_stateblock
*stateblock
= This
->stateBlock
;
2206 This
->stateBlock
= NULL
;
2208 /* Release the stateblock */
2209 if (wined3d_stateblock_decref(stateblock
))
2210 FIXME("Something's still holding the stateblock.\n");
2213 /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
2214 This
->blitter
->free_private(This
);
2215 This
->frag_pipe
->free_private(This
);
2216 This
->shader_backend
->shader_free_private(This
);
2218 /* Release the buffers (with sanity checks)*/
2219 if (This
->onscreen_depth_stencil
)
2221 surface
= This
->onscreen_depth_stencil
;
2222 This
->onscreen_depth_stencil
= NULL
;
2223 wined3d_surface_decref(surface
);
2226 if (This
->depth_stencil
)
2228 surface
= This
->depth_stencil
;
2230 TRACE("Releasing depth/stencil buffer %p.\n", surface
);
2232 This
->depth_stencil
= NULL
;
2233 if (wined3d_surface_decref(surface
)
2234 && surface
!= This
->auto_depth_stencil
)
2236 ERR("Something is still holding a reference to depth/stencil buffer %p.\n", surface
);
2240 if (This
->auto_depth_stencil
)
2242 surface
= This
->auto_depth_stencil
;
2243 This
->auto_depth_stencil
= NULL
;
2244 if (wined3d_surface_decref(surface
))
2246 FIXME("(%p) Something's still holding the auto depth stencil buffer\n", This
);
2250 for (i
= 1; i
< gl_info
->limits
.buffers
; ++i
)
2252 IWineD3DDevice_SetRenderTarget(iface
, i
, NULL
, FALSE
);
2255 surface
= This
->render_targets
[0];
2256 TRACE("Setting rendertarget 0 to NULL\n");
2257 This
->render_targets
[0] = NULL
;
2258 TRACE("Releasing the render target at %p\n", surface
);
2259 wined3d_surface_decref(surface
);
2261 context_release(context
);
2263 for (i
= 0; i
< This
->swapchain_count
; ++i
)
2265 TRACE("Releasing the implicit swapchain %u.\n", i
);
2266 if (wined3d_swapchain_decref(This
->swapchains
[i
]))
2267 FIXME("Something's still holding the implicit swapchain.\n");
2270 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2271 This
->swapchains
= NULL
;
2272 This
->swapchain_count
= 0;
2274 for (i
= 0; i
< This
->palette_count
; ++i
)
2275 HeapFree(GetProcessHeap(), 0, This
->palettes
[i
]);
2276 HeapFree(GetProcessHeap(), 0, This
->palettes
);
2277 This
->palettes
= NULL
;
2278 This
->palette_count
= 0;
2280 HeapFree(GetProcessHeap(), 0, This
->render_targets
);
2281 This
->render_targets
= NULL
;
2283 This
->d3d_initialized
= FALSE
;
2288 static HRESULT WINAPI
IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice
*iface
)
2290 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2293 for (i
= 0; i
< This
->swapchain_count
; ++i
)
2295 TRACE("Releasing the implicit swapchain %u.\n", i
);
2296 if (wined3d_swapchain_decref(This
->swapchains
[i
]))
2297 FIXME("Something's still holding the implicit swapchain.\n");
2300 HeapFree(GetProcessHeap(), 0, This
->swapchains
);
2301 This
->swapchains
= NULL
;
2302 This
->swapchain_count
= 0;
2306 /* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
2307 * from SetCooperativeLevel if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
2308 * CreateDevice if D3DCREATE_MULTITHREADED is passed.
2310 * There is no way to deactivate thread safety once it is enabled.
2312 static void WINAPI
IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice
*iface
) {
2313 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
2315 /*For now just store the flag(needed in case of ddraw) */
2316 This
->createParms
.BehaviorFlags
|= WINED3DCREATE_MULTITHREADED
;
2319 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice
*iface
, UINT iSwapChain
,
2320 const WINED3DDISPLAYMODE
* pMode
) {
2322 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2323 const struct wined3d_format
*format
= wined3d_get_format(&This
->adapter
->gl_info
, pMode
->Format
);
2327 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This
, iSwapChain
, pMode
, pMode
->Width
, pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
2329 /* Resize the screen even without a window:
2330 * The app could have unset it with SetCooperativeLevel, but not called
2331 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
2332 * but we don't have any hwnd
2335 memset(&devmode
, 0, sizeof(devmode
));
2336 devmode
.dmSize
= sizeof(devmode
);
2337 devmode
.dmFields
= DM_BITSPERPEL
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
2338 devmode
.dmBitsPerPel
= format
->byte_count
* CHAR_BIT
;
2339 devmode
.dmPelsWidth
= pMode
->Width
;
2340 devmode
.dmPelsHeight
= pMode
->Height
;
2342 devmode
.dmDisplayFrequency
= pMode
->RefreshRate
;
2343 if (pMode
->RefreshRate
)
2344 devmode
.dmFields
|= DM_DISPLAYFREQUENCY
;
2346 /* Only change the mode if necessary */
2347 if (This
->ddraw_width
== pMode
->Width
&& This
->ddraw_height
== pMode
->Height
2348 && This
->ddraw_format
== pMode
->Format
&& !pMode
->RefreshRate
)
2351 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
);
2352 if (ret
!= DISP_CHANGE_SUCCESSFUL
)
2354 if (devmode
.dmDisplayFrequency
)
2356 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
2357 devmode
.dmFields
&= ~DM_DISPLAYFREQUENCY
;
2358 devmode
.dmDisplayFrequency
= 0;
2359 ret
= ChangeDisplaySettingsExW(NULL
, &devmode
, NULL
, CDS_FULLSCREEN
, NULL
) != DISP_CHANGE_SUCCESSFUL
;
2361 if(ret
!= DISP_CHANGE_SUCCESSFUL
) {
2362 return WINED3DERR_NOTAVAILABLE
;
2366 /* Store the new values */
2367 This
->ddraw_width
= pMode
->Width
;
2368 This
->ddraw_height
= pMode
->Height
;
2369 This
->ddraw_format
= pMode
->Format
;
2371 /* And finally clip mouse to our screen */
2372 SetRect(&clip_rc
, 0, 0, pMode
->Width
, pMode
->Height
);
2373 ClipCursor(&clip_rc
);
2378 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice
*iface
, struct wined3d
**wined3d
)
2380 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
2382 TRACE("iface %p, wined3d %p.\n", iface
, wined3d
);
2384 *wined3d
= device
->wined3d
;
2385 wined3d_incref(*wined3d
);
2387 TRACE("Returning %p.\n", *wined3d
);
2392 static UINT WINAPI
IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice
*iface
) {
2393 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2395 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This
,
2396 (This
->adapter
->TextureRam
/(1024*1024)),
2397 ((This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
) / (1024*1024)));
2398 /* return simulated texture memory left */
2399 return (This
->adapter
->TextureRam
- This
->adapter
->UsedTextureRam
);
2402 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice
*iface
, UINT StreamNumber
,
2403 struct wined3d_buffer
*buffer
, UINT OffsetInBytes
, UINT Stride
)
2405 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2406 struct wined3d_stream_state
*stream
;
2407 struct wined3d_buffer
*prev_buffer
;
2409 TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
2410 iface
, StreamNumber
, buffer
, OffsetInBytes
, Stride
);
2412 if (StreamNumber
>= MAX_STREAMS
) {
2413 WARN("Stream out of range %d\n", StreamNumber
);
2414 return WINED3DERR_INVALIDCALL
;
2415 } else if(OffsetInBytes
& 0x3) {
2416 WARN("OffsetInBytes is not 4 byte aligned: %d\n", OffsetInBytes
);
2417 return WINED3DERR_INVALIDCALL
;
2420 stream
= &This
->updateStateBlock
->state
.streams
[StreamNumber
];
2421 prev_buffer
= stream
->buffer
;
2423 This
->updateStateBlock
->changed
.streamSource
|= 1 << StreamNumber
;
2425 if (prev_buffer
== buffer
2426 && stream
->stride
== Stride
2427 && stream
->offset
== OffsetInBytes
)
2429 TRACE("Application is setting the old values over, nothing to do\n");
2433 stream
->buffer
= buffer
;
2436 stream
->stride
= Stride
;
2437 stream
->offset
= OffsetInBytes
;
2440 /* Handle recording of state blocks */
2441 if (This
->isRecordingState
) {
2442 TRACE("Recording... not performing anything\n");
2444 wined3d_buffer_incref(buffer
);
2446 wined3d_buffer_decref(prev_buffer
);
2452 InterlockedIncrement(&buffer
->bind_count
);
2453 wined3d_buffer_incref(buffer
);
2457 InterlockedDecrement(&prev_buffer
->bind_count
);
2458 wined3d_buffer_decref(prev_buffer
);
2461 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2466 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice
*iface
,
2467 UINT StreamNumber
, struct wined3d_buffer
**buffer
, UINT
*pOffset
, UINT
*pStride
)
2469 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2470 struct wined3d_stream_state
*stream
;
2472 TRACE("iface %p, stream_idx %u, buffer %p, offset %p, stride %p.\n",
2473 iface
, StreamNumber
, buffer
, pOffset
, pStride
);
2475 if (StreamNumber
>= MAX_STREAMS
)
2477 WARN("Stream out of range %d\n", StreamNumber
);
2478 return WINED3DERR_INVALIDCALL
;
2481 stream
= &This
->stateBlock
->state
.streams
[StreamNumber
];
2482 *buffer
= stream
->buffer
;
2483 *pStride
= stream
->stride
;
2484 if (pOffset
) *pOffset
= stream
->offset
;
2487 wined3d_buffer_incref(*buffer
);
2492 static HRESULT WINAPI
IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT Divider
) {
2493 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2494 struct wined3d_stream_state
*stream
;
2495 UINT old_flags
, oldFreq
;
2497 TRACE("iface %p, stream_idx %u, divider %#x.\n", iface
, StreamNumber
, Divider
);
2499 /* Verify input at least in d3d9 this is invalid. */
2500 if ((Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && (Divider
& WINED3DSTREAMSOURCE_INDEXEDDATA
))
2502 WARN("INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL\n");
2503 return WINED3DERR_INVALIDCALL
;
2505 if ((Divider
& WINED3DSTREAMSOURCE_INSTANCEDATA
) && !StreamNumber
)
2507 WARN("INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL\n");
2508 return WINED3DERR_INVALIDCALL
;
2512 WARN("Divider is 0, returning D3DERR_INVALIDCALL\n");
2513 return WINED3DERR_INVALIDCALL
;
2516 stream
= &This
->updateStateBlock
->state
.streams
[StreamNumber
];
2517 old_flags
= stream
->flags
;
2518 oldFreq
= stream
->frequency
;
2520 stream
->flags
= Divider
& (WINED3DSTREAMSOURCE_INSTANCEDATA
| WINED3DSTREAMSOURCE_INDEXEDDATA
);
2521 stream
->frequency
= Divider
& 0x7FFFFF;
2523 This
->updateStateBlock
->changed
.streamFreq
|= 1 << StreamNumber
;
2525 if (stream
->frequency
!= oldFreq
|| stream
->flags
!= old_flags
)
2526 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
2531 static HRESULT WINAPI
IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice
*iface
, UINT StreamNumber
, UINT
* Divider
) {
2532 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2533 struct wined3d_stream_state
*stream
;
2535 TRACE("iface %p, stream_idx %u, divider %p.\n", iface
, StreamNumber
, Divider
);
2537 stream
= &This
->updateStateBlock
->state
.streams
[StreamNumber
];
2538 *Divider
= stream
->flags
| stream
->frequency
;
2540 TRACE("Returning %#x.\n", *Divider
);
2546 * Get / Set & Multiply Transform
2548 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE d3dts
, CONST WINED3DMATRIX
* lpmatrix
) {
2549 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2551 /* Most of this routine, comments included copied from ddraw tree initially: */
2552 TRACE("(%p) : Transform State=%s\n", This
, debug_d3dtstype(d3dts
));
2554 /* Handle recording of state blocks */
2555 if (This
->isRecordingState
) {
2556 TRACE("Recording... not performing anything\n");
2557 This
->updateStateBlock
->changed
.transform
[d3dts
>> 5] |= 1 << (d3dts
& 0x1f);
2558 This
->updateStateBlock
->state
.transforms
[d3dts
] = *lpmatrix
;
2563 * If the new matrix is the same as the current one,
2564 * we cut off any further processing. this seems to be a reasonable
2565 * optimization because as was noticed, some apps (warcraft3 for example)
2566 * tend towards setting the same matrix repeatedly for some reason.
2568 * From here on we assume that the new matrix is different, wherever it matters.
2570 if (!memcmp(&This
->stateBlock
->state
.transforms
[d3dts
].u
.m
[0][0], lpmatrix
, sizeof(*lpmatrix
)))
2572 TRACE("The app is setting the same matrix over again\n");
2577 conv_mat(lpmatrix
, &This
->stateBlock
->state
.transforms
[d3dts
].u
.m
[0][0]);
2581 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2582 where ViewMat = Camera space, WorldMat = world space.
2584 In OpenGL, camera and world space is combined into GL_MODELVIEW
2585 matrix. The Projection matrix stay projection matrix.
2588 /* Capture the times we can just ignore the change for now */
2589 if (d3dts
== WINED3DTS_VIEW
) { /* handle the VIEW matrix */
2590 This
->view_ident
= !memcmp(lpmatrix
, identity
, 16 * sizeof(float));
2591 /* Handled by the state manager */
2594 if (d3dts
< WINED3DTS_WORLDMATRIX(This
->adapter
->gl_info
.limits
.blends
))
2595 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TRANSFORM(d3dts
));
2601 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTransform(IWineD3DDevice
*iface
,
2602 WINED3DTRANSFORMSTATETYPE state
, WINED3DMATRIX
*matrix
)
2604 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
2606 TRACE("iface %p, state %s, matrix %p.\n", iface
, debug_d3dtstype(state
), matrix
);
2608 *matrix
= device
->stateBlock
->state
.transforms
[state
];
2613 static HRESULT WINAPI
IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice
*iface
, WINED3DTRANSFORMSTATETYPE State
, CONST WINED3DMATRIX
* pMatrix
) {
2614 const WINED3DMATRIX
*mat
= NULL
;
2617 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2618 * below means it will be recorded in a state block change, but it
2619 * works regardless where it is recorded.
2620 * If this is found to be wrong, change to StateBlock.
2622 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2623 TRACE("(%p) : For state %s\n", This
, debug_d3dtstype(State
));
2625 if (State
<= HIGHEST_TRANSFORMSTATE
)
2627 mat
= &This
->updateStateBlock
->state
.transforms
[State
];
2631 FIXME("Unhandled transform state!!\n");
2634 multiply_matrix(&temp
, mat
, pMatrix
);
2636 /* Apply change via set transform - will reapply to eg. lights this way */
2637 return IWineD3DDeviceImpl_SetTransform(iface
, State
, &temp
);
2643 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2644 you can reference any indexes you want as long as that number max are enabled at any
2645 one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2646 However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2647 but when recording, just build a chain pretty much of commands to be replayed. */
2649 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLight(IWineD3DDevice
*iface
, DWORD Index
, CONST WINED3DLIGHT
* pLight
) {
2651 struct wined3d_light_info
*object
= NULL
;
2652 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2655 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2656 TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This
, Index
, pLight
, Hi
);
2658 /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2662 WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2663 return WINED3DERR_INVALIDCALL
;
2666 switch(pLight
->Type
) {
2667 case WINED3DLIGHT_POINT
:
2668 case WINED3DLIGHT_SPOT
:
2669 case WINED3DLIGHT_PARALLELPOINT
:
2670 case WINED3DLIGHT_GLSPOT
:
2671 /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2674 if (pLight
->Attenuation0
< 0.0f
|| pLight
->Attenuation1
< 0.0f
|| pLight
->Attenuation2
< 0.0f
)
2676 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2677 return WINED3DERR_INVALIDCALL
;
2681 case WINED3DLIGHT_DIRECTIONAL
:
2682 /* Ignores attenuation */
2686 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2687 return WINED3DERR_INVALIDCALL
;
2690 LIST_FOR_EACH(e
, &This
->updateStateBlock
->state
.light_map
[Hi
])
2692 object
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2693 if(object
->OriginalIndex
== Index
) break;
2698 TRACE("Adding new light\n");
2699 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2701 ERR("Out of memory error when allocating a light\n");
2702 return E_OUTOFMEMORY
;
2704 list_add_head(&This
->updateStateBlock
->state
.light_map
[Hi
], &object
->entry
);
2705 object
->glIndex
= -1;
2706 object
->OriginalIndex
= Index
;
2709 /* Initialize the object */
2710 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
,
2711 pLight
->Diffuse
.r
, pLight
->Diffuse
.g
, pLight
->Diffuse
.b
, pLight
->Diffuse
.a
,
2712 pLight
->Specular
.r
, pLight
->Specular
.g
, pLight
->Specular
.b
, pLight
->Specular
.a
,
2713 pLight
->Ambient
.r
, pLight
->Ambient
.g
, pLight
->Ambient
.b
, pLight
->Ambient
.a
);
2714 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight
->Position
.x
, pLight
->Position
.y
, pLight
->Position
.z
,
2715 pLight
->Direction
.x
, pLight
->Direction
.y
, pLight
->Direction
.z
);
2716 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight
->Range
, pLight
->Falloff
, pLight
->Theta
, pLight
->Phi
);
2718 /* Save away the information */
2719 object
->OriginalParms
= *pLight
;
2721 switch (pLight
->Type
) {
2722 case WINED3DLIGHT_POINT
:
2724 object
->lightPosn
[0] = pLight
->Position
.x
;
2725 object
->lightPosn
[1] = pLight
->Position
.y
;
2726 object
->lightPosn
[2] = pLight
->Position
.z
;
2727 object
->lightPosn
[3] = 1.0f
;
2728 object
->cutoff
= 180.0f
;
2732 case WINED3DLIGHT_DIRECTIONAL
:
2734 object
->lightPosn
[0] = -pLight
->Direction
.x
;
2735 object
->lightPosn
[1] = -pLight
->Direction
.y
;
2736 object
->lightPosn
[2] = -pLight
->Direction
.z
;
2737 object
->lightPosn
[3] = 0.0f
;
2738 object
->exponent
= 0.0f
;
2739 object
->cutoff
= 180.0f
;
2742 case WINED3DLIGHT_SPOT
:
2744 object
->lightPosn
[0] = pLight
->Position
.x
;
2745 object
->lightPosn
[1] = pLight
->Position
.y
;
2746 object
->lightPosn
[2] = pLight
->Position
.z
;
2747 object
->lightPosn
[3] = 1.0f
;
2750 object
->lightDirn
[0] = pLight
->Direction
.x
;
2751 object
->lightDirn
[1] = pLight
->Direction
.y
;
2752 object
->lightDirn
[2] = pLight
->Direction
.z
;
2753 object
->lightDirn
[3] = 1.0f
;
2756 * opengl-ish and d3d-ish spot lights use too different models for the
2757 * light "intensity" as a function of the angle towards the main light direction,
2758 * so we only can approximate very roughly.
2759 * however spot lights are rather rarely used in games (if ever used at all).
2760 * furthermore if still used, probably nobody pays attention to such details.
2762 if (!pLight
->Falloff
)
2764 /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
2765 * falloff resp. exponent parameter as an exponent, so the spot light lighting
2766 * will always be 1.0 for both of them, and we don't have to care for the
2767 * rest of the rather complex calculation
2769 object
->exponent
= 0.0f
;
2771 rho
= pLight
->Theta
+ (pLight
->Phi
- pLight
->Theta
)/(2*pLight
->Falloff
);
2772 if (rho
< 0.0001f
) rho
= 0.0001f
;
2773 object
->exponent
= -0.3f
/logf(cosf(rho
/2));
2775 if (object
->exponent
> 128.0f
)
2777 object
->exponent
= 128.0f
;
2779 object
->cutoff
= (float) (pLight
->Phi
*90/M_PI
);
2785 FIXME("Unrecognized light type %d\n", pLight
->Type
);
2788 /* Update the live definitions if the light is currently assigned a glIndex */
2789 if (object
->glIndex
!= -1 && !This
->isRecordingState
) {
2790 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(object
->glIndex
));
2795 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLight(IWineD3DDevice
*iface
, DWORD Index
, WINED3DLIGHT
*pLight
)
2797 struct wined3d_light_info
*lightInfo
= NULL
;
2798 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2799 DWORD Hi
= LIGHTMAP_HASHFUNC(Index
);
2801 TRACE("(%p) : Idx(%d), pLight(%p)\n", This
, Index
, pLight
);
2803 LIST_FOR_EACH(e
, &This
->stateBlock
->state
.light_map
[Hi
])
2805 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2806 if(lightInfo
->OriginalIndex
== Index
) break;
2812 TRACE("Light information requested but light not defined\n");
2813 return WINED3DERR_INVALIDCALL
;
2816 *pLight
= lightInfo
->OriginalParms
;
2821 * Get / Set Light Enable
2822 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2824 static HRESULT WINAPI
IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice
*iface
, DWORD Index
, BOOL Enable
)
2826 struct wined3d_light_info
*lightInfo
= NULL
;
2827 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2828 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2830 TRACE("(%p) : Idx(%d), enable? %d\n", This
, Index
, Enable
);
2832 LIST_FOR_EACH(e
, &This
->updateStateBlock
->state
.light_map
[Hi
])
2834 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2835 if(lightInfo
->OriginalIndex
== Index
) break;
2838 TRACE("Found light: %p\n", lightInfo
);
2840 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2843 TRACE("Light enabled requested but light not defined, so defining one!\n");
2844 IWineD3DDeviceImpl_SetLight(iface
, Index
, &WINED3D_default_light
);
2846 /* Search for it again! Should be fairly quick as near head of list */
2847 LIST_FOR_EACH(e
, &This
->updateStateBlock
->state
.light_map
[Hi
])
2849 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2850 if(lightInfo
->OriginalIndex
== Index
) break;
2855 FIXME("Adding default lights has failed dismally\n");
2856 return WINED3DERR_INVALIDCALL
;
2861 if(lightInfo
->glIndex
!= -1) {
2862 if(!This
->isRecordingState
) {
2863 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(lightInfo
->glIndex
));
2866 This
->updateStateBlock
->state
.lights
[lightInfo
->glIndex
] = NULL
;
2867 lightInfo
->glIndex
= -1;
2869 TRACE("Light already disabled, nothing to do\n");
2871 lightInfo
->enabled
= FALSE
;
2873 lightInfo
->enabled
= TRUE
;
2874 if (lightInfo
->glIndex
!= -1) {
2876 TRACE("Nothing to do as light was enabled\n");
2879 /* Find a free gl light */
2880 for (i
= 0; i
< This
->maxConcurrentLights
; ++i
)
2882 if (!This
->updateStateBlock
->state
.lights
[i
])
2884 This
->updateStateBlock
->state
.lights
[i
] = lightInfo
;
2885 lightInfo
->glIndex
= i
;
2889 if(lightInfo
->glIndex
== -1) {
2890 /* Our tests show that Windows returns D3D_OK in this situation, even with
2891 * D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
2892 * is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
2893 * as well for those lights.
2895 * TODO: Test how this affects rendering
2897 WARN("Too many concurrently active lights\n");
2901 /* i == lightInfo->glIndex */
2902 if(!This
->isRecordingState
) {
2903 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_ACTIVELIGHT(i
));
2911 static HRESULT WINAPI
IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice
*iface
, DWORD Index
,BOOL
* pEnable
)
2913 struct wined3d_light_info
*lightInfo
= NULL
;
2914 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2916 UINT Hi
= LIGHTMAP_HASHFUNC(Index
);
2917 TRACE("(%p) : for idx(%d)\n", This
, Index
);
2919 LIST_FOR_EACH(e
, &This
->stateBlock
->state
.light_map
[Hi
])
2921 lightInfo
= LIST_ENTRY(e
, struct wined3d_light_info
, entry
);
2922 if(lightInfo
->OriginalIndex
== Index
) break;
2928 TRACE("Light enabled state requested but light not defined\n");
2929 return WINED3DERR_INVALIDCALL
;
2931 /* true is 128 according to SetLightEnable */
2932 *pEnable
= lightInfo
->enabled
? 128 : 0;
2937 * Get / Set Clip Planes
2939 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, CONST
float *pPlane
) {
2940 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2941 TRACE("(%p) : for idx %d, %p\n", This
, Index
, pPlane
);
2943 /* Validate Index */
2944 if (Index
>= This
->adapter
->gl_info
.limits
.clipplanes
)
2946 TRACE("Application has requested clipplane this device doesn't support\n");
2947 return WINED3DERR_INVALIDCALL
;
2950 This
->updateStateBlock
->changed
.clipplane
|= 1 << Index
;
2952 if (This
->updateStateBlock
->state
.clip_planes
[Index
][0] == pPlane
[0]
2953 && This
->updateStateBlock
->state
.clip_planes
[Index
][1] == pPlane
[1]
2954 && This
->updateStateBlock
->state
.clip_planes
[Index
][2] == pPlane
[2]
2955 && This
->updateStateBlock
->state
.clip_planes
[Index
][3] == pPlane
[3])
2957 TRACE("Application is setting old values over, nothing to do\n");
2961 This
->updateStateBlock
->state
.clip_planes
[Index
][0] = pPlane
[0];
2962 This
->updateStateBlock
->state
.clip_planes
[Index
][1] = pPlane
[1];
2963 This
->updateStateBlock
->state
.clip_planes
[Index
][2] = pPlane
[2];
2964 This
->updateStateBlock
->state
.clip_planes
[Index
][3] = pPlane
[3];
2966 /* Handle recording of state blocks */
2967 if (This
->isRecordingState
) {
2968 TRACE("Recording... not performing anything\n");
2972 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_CLIPPLANE(Index
));
2977 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice
*iface
, DWORD Index
, float *pPlane
) {
2978 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
2979 TRACE("(%p) : for idx %d\n", This
, Index
);
2981 /* Validate Index */
2982 if (Index
>= This
->adapter
->gl_info
.limits
.clipplanes
)
2984 TRACE("Application has requested clipplane this device doesn't support\n");
2985 return WINED3DERR_INVALIDCALL
;
2988 pPlane
[0] = (float)This
->stateBlock
->state
.clip_planes
[Index
][0];
2989 pPlane
[1] = (float)This
->stateBlock
->state
.clip_planes
[Index
][1];
2990 pPlane
[2] = (float)This
->stateBlock
->state
.clip_planes
[Index
][2];
2991 pPlane
[3] = (float)This
->stateBlock
->state
.clip_planes
[Index
][3];
2996 * Get / Set Clip Plane Status
2997 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2999 static HRESULT WINAPI
IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice
*iface
, CONST WINED3DCLIPSTATUS
* pClipStatus
) {
3000 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3001 FIXME("(%p) : stub\n", This
);
3004 return WINED3DERR_INVALIDCALL
;
3006 This
->updateStateBlock
->state
.clip_status
.ClipUnion
= pClipStatus
->ClipUnion
;
3007 This
->updateStateBlock
->state
.clip_status
.ClipIntersection
= pClipStatus
->ClipIntersection
;
3011 static HRESULT WINAPI
IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice
*iface
, WINED3DCLIPSTATUS
* pClipStatus
) {
3012 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3013 FIXME("(%p) : stub\n", This
);
3016 return WINED3DERR_INVALIDCALL
;
3018 pClipStatus
->ClipUnion
= This
->updateStateBlock
->state
.clip_status
.ClipUnion
;
3019 pClipStatus
->ClipIntersection
= This
->updateStateBlock
->state
.clip_status
.ClipIntersection
;
3024 * Get / Set Material
3026 static HRESULT WINAPI
IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice
*iface
, CONST WINED3DMATERIAL
* pMaterial
) {
3027 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3029 This
->updateStateBlock
->changed
.material
= TRUE
;
3030 This
->updateStateBlock
->state
.material
= *pMaterial
;
3032 /* Handle recording of state blocks */
3033 if (This
->isRecordingState
) {
3034 TRACE("Recording... not performing anything\n");
3038 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_MATERIAL
);
3042 static HRESULT WINAPI
IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice
*iface
, WINED3DMATERIAL
* pMaterial
) {
3043 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3044 *pMaterial
= This
->updateStateBlock
->state
.material
;
3045 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This
, pMaterial
->Diffuse
.r
, pMaterial
->Diffuse
.g
,
3046 pMaterial
->Diffuse
.b
, pMaterial
->Diffuse
.a
);
3047 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This
, pMaterial
->Ambient
.r
, pMaterial
->Ambient
.g
,
3048 pMaterial
->Ambient
.b
, pMaterial
->Ambient
.a
);
3049 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This
, pMaterial
->Specular
.r
, pMaterial
->Specular
.g
,
3050 pMaterial
->Specular
.b
, pMaterial
->Specular
.a
);
3051 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This
, pMaterial
->Emissive
.r
, pMaterial
->Emissive
.g
,
3052 pMaterial
->Emissive
.b
, pMaterial
->Emissive
.a
);
3053 TRACE("(%p) : Power (%f)\n", This
, pMaterial
->Power
);
3061 static HRESULT WINAPI
IWineD3DDeviceImpl_SetIndexBuffer(IWineD3DDevice
*iface
,
3062 struct wined3d_buffer
*buffer
, enum wined3d_format_id fmt
)
3064 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3065 struct wined3d_buffer
*prev_buffer
;
3067 TRACE("iface %p, buffer %p, format %s.\n",
3068 iface
, buffer
, debug_d3dformat(fmt
));
3070 prev_buffer
= This
->updateStateBlock
->state
.index_buffer
;
3072 This
->updateStateBlock
->changed
.indices
= TRUE
;
3073 This
->updateStateBlock
->state
.index_buffer
= buffer
;
3074 This
->updateStateBlock
->state
.index_format
= fmt
;
3076 /* Handle recording of state blocks */
3077 if (This
->isRecordingState
) {
3078 TRACE("Recording... not performing anything\n");
3080 wined3d_buffer_incref(buffer
);
3082 wined3d_buffer_decref(prev_buffer
);
3086 if (prev_buffer
!= buffer
)
3088 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
3091 InterlockedIncrement(&buffer
->bind_count
);
3092 wined3d_buffer_incref(buffer
);
3096 InterlockedDecrement(&prev_buffer
->bind_count
);
3097 wined3d_buffer_decref(prev_buffer
);
3104 static HRESULT WINAPI
IWineD3DDeviceImpl_GetIndexBuffer(IWineD3DDevice
*iface
, struct wined3d_buffer
**buffer
)
3106 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3108 TRACE("iface %p, buffer %p.\n", iface
, buffer
);
3110 *buffer
= This
->stateBlock
->state
.index_buffer
;
3113 wined3d_buffer_incref(*buffer
);
3115 TRACE("Returning %p.\n", *buffer
);
3120 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
3121 static HRESULT WINAPI
IWineD3DDeviceImpl_SetBaseVertexIndex(IWineD3DDevice
*iface
, INT BaseIndex
) {
3122 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3123 TRACE("(%p)->(%d)\n", This
, BaseIndex
);
3125 if (This
->updateStateBlock
->state
.base_vertex_index
== BaseIndex
)
3127 TRACE("Application is setting the old value over, nothing to do\n");
3131 This
->updateStateBlock
->state
.base_vertex_index
= BaseIndex
;
3133 if (This
->isRecordingState
) {
3134 TRACE("Recording... not performing anything\n");
3137 /* The base vertex index affects the stream sources */
3138 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
3142 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBaseVertexIndex(IWineD3DDevice
*iface
, INT
* base_index
) {
3143 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3144 TRACE("(%p) : base_index %p\n", This
, base_index
);
3146 *base_index
= This
->stateBlock
->state
.base_vertex_index
;
3148 TRACE("Returning %u\n", *base_index
);
3154 * Get / Set Viewports
3156 static HRESULT WINAPI
IWineD3DDeviceImpl_SetViewport(IWineD3DDevice
*iface
, CONST WINED3DVIEWPORT
* pViewport
) {
3157 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3159 TRACE("(%p)\n", This
);
3160 This
->updateStateBlock
->changed
.viewport
= TRUE
;
3161 This
->updateStateBlock
->state
.viewport
= *pViewport
;
3163 /* Handle recording of state blocks */
3164 if (This
->isRecordingState
) {
3165 TRACE("Recording... not performing anything\n");
3169 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This
,
3170 pViewport
->X
, pViewport
->Y
, pViewport
->Width
, pViewport
->Height
, pViewport
->MinZ
, pViewport
->MaxZ
);
3172 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VIEWPORT
);
3177 static HRESULT WINAPI
IWineD3DDeviceImpl_GetViewport(IWineD3DDevice
*iface
, WINED3DVIEWPORT
* pViewport
) {
3178 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3179 TRACE("(%p)\n", This
);
3180 *pViewport
= This
->stateBlock
->state
.viewport
;
3184 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice
*iface
,
3185 WINED3DRENDERSTATETYPE State
, DWORD Value
)
3187 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3188 DWORD oldValue
= This
->stateBlock
->state
.render_states
[State
];
3190 TRACE("iface %p, state %s (%#x), value %#x.\n", iface
, debug_d3drenderstate(State
), State
, Value
);
3192 This
->updateStateBlock
->changed
.renderState
[State
>> 5] |= 1 << (State
& 0x1f);
3193 This
->updateStateBlock
->state
.render_states
[State
] = Value
;
3195 /* Handle recording of state blocks */
3196 if (This
->isRecordingState
) {
3197 TRACE("Recording... not performing anything\n");
3201 /* Compared here and not before the assignment to allow proper stateblock recording */
3202 if(Value
== oldValue
) {
3203 TRACE("Application is setting the old value over, nothing to do\n");
3205 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(State
));
3211 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice
*iface
,
3212 WINED3DRENDERSTATETYPE State
, DWORD
*pValue
)
3214 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3216 TRACE("iface %p, state %s (%#x), value %p.\n", iface
, debug_d3drenderstate(State
), State
, pValue
);
3218 *pValue
= This
->stateBlock
->state
.render_states
[State
];
3223 * Get / Set Sampler States
3224 * TODO: Verify against dx9 definitions
3227 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD Value
) {
3228 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3231 TRACE("(%p) : Sampler %#x, Type %s (%#x), Value %#x\n",
3232 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
, Value
);
3234 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3235 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3238 if (Sampler
>= sizeof(This
->stateBlock
->state
.sampler_states
) / sizeof(*This
->stateBlock
->state
.sampler_states
))
3240 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3241 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3244 oldValue
= This
->stateBlock
->state
.sampler_states
[Sampler
][Type
];
3245 This
->updateStateBlock
->state
.sampler_states
[Sampler
][Type
] = Value
;
3246 This
->updateStateBlock
->changed
.samplerState
[Sampler
] |= 1 << Type
;
3248 /* Handle recording of state blocks */
3249 if (This
->isRecordingState
) {
3250 TRACE("Recording... not performing anything\n");
3254 if(oldValue
== Value
) {
3255 TRACE("Application is setting the old value over, nothing to do\n");
3259 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(Sampler
));
3264 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice
*iface
, DWORD Sampler
, WINED3DSAMPLERSTATETYPE Type
, DWORD
* Value
) {
3265 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3267 TRACE("(%p) : Sampler %#x, Type %s (%#x)\n",
3268 This
, Sampler
, debug_d3dsamplerstate(Type
), Type
);
3270 if (Sampler
>= WINED3DVERTEXTEXTURESAMPLER0
&& Sampler
<= WINED3DVERTEXTEXTURESAMPLER3
) {
3271 Sampler
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
3274 if (Sampler
>= sizeof(This
->stateBlock
->state
.sampler_states
) / sizeof(*This
->stateBlock
->state
.sampler_states
))
3276 ERR("Current Sampler overflows sampleState0 array (sampler %d)\n", Sampler
);
3277 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
3279 *Value
= This
->stateBlock
->state
.sampler_states
[Sampler
][Type
];
3280 TRACE("(%p) : Returning %#x\n", This
, *Value
);
3285 static HRESULT WINAPI
IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice
*iface
, CONST RECT
* pRect
) {
3286 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3288 This
->updateStateBlock
->changed
.scissorRect
= TRUE
;
3289 if (EqualRect(&This
->updateStateBlock
->state
.scissor_rect
, pRect
))
3291 TRACE("App is setting the old scissor rectangle over, nothing to do.\n");
3294 CopyRect(&This
->updateStateBlock
->state
.scissor_rect
, pRect
);
3296 if(This
->isRecordingState
) {
3297 TRACE("Recording... not performing anything\n");
3301 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SCISSORRECT
);
3306 static HRESULT WINAPI
IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice
*iface
, RECT
* pRect
) {
3307 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3309 *pRect
= This
->updateStateBlock
->state
.scissor_rect
;
3310 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3314 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice
*iface
,
3315 struct wined3d_vertex_declaration
*pDecl
)
3317 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
3318 struct wined3d_vertex_declaration
*oldDecl
= This
->updateStateBlock
->state
.vertex_declaration
;
3320 TRACE("iface %p, declaration %p.\n", iface
, pDecl
);
3323 wined3d_vertex_declaration_incref(pDecl
);
3325 wined3d_vertex_declaration_decref(oldDecl
);
3327 This
->updateStateBlock
->state
.vertex_declaration
= pDecl
;
3328 This
->updateStateBlock
->changed
.vertexDecl
= TRUE
;
3330 if (This
->isRecordingState
) {
3331 TRACE("Recording... not performing anything\n");
3333 } else if(pDecl
== oldDecl
) {
3334 /* Checked after the assignment to allow proper stateblock recording */
3335 TRACE("Application is setting the old declaration over, nothing to do\n");
3339 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
3343 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice
*iface
,
3344 struct wined3d_vertex_declaration
**ppDecl
)
3346 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3348 TRACE("iface %p, declaration %p.\n", iface
, ppDecl
);
3350 *ppDecl
= This
->stateBlock
->state
.vertex_declaration
;
3352 wined3d_vertex_declaration_incref(*ppDecl
);
3357 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice
*iface
, struct wined3d_shader
*shader
)
3359 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
3360 struct wined3d_shader
*prev
= device
->updateStateBlock
->state
.vertex_shader
;
3362 device
->updateStateBlock
->state
.vertex_shader
= shader
;
3363 device
->updateStateBlock
->changed
.vertexShader
= TRUE
;
3365 if (device
->isRecordingState
)
3368 wined3d_shader_incref(shader
);
3370 wined3d_shader_decref(prev
);
3371 TRACE("Recording... not performing anything.\n");
3374 else if(prev
== shader
)
3376 /* Checked here to allow proper stateblock recording */
3377 TRACE("App is setting the old shader over, nothing to do.\n");
3381 TRACE("(%p) : setting shader(%p)\n", device
, shader
);
3383 wined3d_shader_incref(shader
);
3385 wined3d_shader_decref(prev
);
3387 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_VSHADER
);
3392 static struct wined3d_shader
* WINAPI
IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice
*iface
)
3394 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
3395 struct wined3d_shader
*shader
;
3397 TRACE("iface %p.\n", iface
);
3399 shader
= device
->stateBlock
->state
.vertex_shader
;
3401 wined3d_shader_incref(shader
);
3403 TRACE("Returning %p.\n", shader
);
3407 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantB(
3408 IWineD3DDevice
*iface
,
3410 CONST BOOL
*srcData
,
3413 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3414 unsigned int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3416 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3417 iface
, srcData
, start
, count
);
3419 if (!srcData
|| start
>= MAX_CONST_B
) return WINED3DERR_INVALIDCALL
;
3421 memcpy(&This
->updateStateBlock
->state
.vs_consts_b
[start
], srcData
, cnt
* sizeof(BOOL
));
3422 for (i
= 0; i
< cnt
; i
++)
3423 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3425 for (i
= start
; i
< cnt
+ start
; ++i
) {
3426 This
->updateStateBlock
->changed
.vertexShaderConstantsB
|= (1 << i
);
3429 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3434 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantB(
3435 IWineD3DDevice
*iface
,
3440 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3441 int cnt
= min(count
, MAX_CONST_B
- start
);
3443 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3444 iface
, dstData
, start
, count
);
3446 if (!dstData
|| cnt
< 0)
3447 return WINED3DERR_INVALIDCALL
;
3449 memcpy(dstData
, &This
->stateBlock
->state
.vs_consts_b
[start
], cnt
* sizeof(BOOL
));
3453 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantI(
3454 IWineD3DDevice
*iface
,
3459 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3460 unsigned int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3462 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3463 iface
, srcData
, start
, count
);
3465 if (!srcData
|| start
>= MAX_CONST_I
) return WINED3DERR_INVALIDCALL
;
3467 memcpy(&This
->updateStateBlock
->state
.vs_consts_i
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3468 for (i
= 0; i
< cnt
; i
++)
3469 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3470 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3472 for (i
= start
; i
< cnt
+ start
; ++i
) {
3473 This
->updateStateBlock
->changed
.vertexShaderConstantsI
|= (1 << i
);
3476 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3481 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantI(
3482 IWineD3DDevice
*iface
,
3487 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3488 int cnt
= min(count
, MAX_CONST_I
- start
);
3490 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3491 iface
, dstData
, start
, count
);
3493 if (!dstData
|| ((signed int)MAX_CONST_I
- (signed int)start
) <= 0)
3494 return WINED3DERR_INVALIDCALL
;
3496 memcpy(dstData
, &This
->stateBlock
->state
.vs_consts_i
[start
* 4], cnt
* sizeof(int) * 4);
3500 static HRESULT WINAPI
IWineD3DDeviceImpl_SetVertexShaderConstantF(
3501 IWineD3DDevice
*iface
,
3503 CONST
float *srcData
,
3506 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3509 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3510 iface
, srcData
, start
, count
);
3512 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3513 if (!srcData
|| start
+ count
> This
->d3d_vshader_constantF
|| start
> This
->d3d_vshader_constantF
)
3514 return WINED3DERR_INVALIDCALL
;
3516 memcpy(&This
->updateStateBlock
->state
.vs_consts_f
[start
* 4], srcData
, count
* sizeof(float) * 4);
3518 for (i
= 0; i
< count
; i
++)
3519 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3520 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3523 if (!This
->isRecordingState
)
3525 This
->shader_backend
->shader_update_float_vertex_constants(This
, start
, count
);
3526 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VERTEXSHADERCONSTANT
);
3529 memset(This
->updateStateBlock
->changed
.vertexShaderConstantsF
+ start
, 1,
3530 sizeof(*This
->updateStateBlock
->changed
.vertexShaderConstantsF
) * count
);
3535 static HRESULT WINAPI
IWineD3DDeviceImpl_GetVertexShaderConstantF(
3536 IWineD3DDevice
*iface
,
3541 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3542 int cnt
= min(count
, This
->d3d_vshader_constantF
- start
);
3544 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3545 iface
, dstData
, start
, count
);
3547 if (!dstData
|| cnt
< 0)
3548 return WINED3DERR_INVALIDCALL
;
3550 memcpy(dstData
, &This
->stateBlock
->state
.vs_consts_f
[start
* 4], cnt
* sizeof(float) * 4);
3554 static inline void markTextureStagesDirty(IWineD3DDeviceImpl
*This
, DWORD stage
) {
3556 for(i
= 0; i
<= WINED3D_HIGHEST_TEXTURE_STATE
; ++i
)
3558 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, i
));
3562 static void device_map_stage(IWineD3DDeviceImpl
*This
, DWORD stage
, DWORD unit
)
3564 DWORD i
= This
->rev_tex_unit_map
[unit
];
3565 DWORD j
= This
->texUnitMap
[stage
];
3567 This
->texUnitMap
[stage
] = unit
;
3568 if (i
!= WINED3D_UNMAPPED_STAGE
&& i
!= stage
)
3570 This
->texUnitMap
[i
] = WINED3D_UNMAPPED_STAGE
;
3573 This
->rev_tex_unit_map
[unit
] = stage
;
3574 if (j
!= WINED3D_UNMAPPED_STAGE
&& j
!= unit
)
3576 This
->rev_tex_unit_map
[j
] = WINED3D_UNMAPPED_STAGE
;
3580 static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl
*This
) {
3583 This
->fixed_function_usage_map
= 0;
3584 for (i
= 0; i
< MAX_TEXTURES
; ++i
)
3586 const struct wined3d_state
*state
= &This
->stateBlock
->state
;
3587 WINED3DTEXTUREOP color_op
= state
->texture_states
[i
][WINED3DTSS_COLOROP
];
3588 WINED3DTEXTUREOP alpha_op
= state
->texture_states
[i
][WINED3DTSS_ALPHAOP
];
3589 DWORD color_arg1
= state
->texture_states
[i
][WINED3DTSS_COLORARG1
] & WINED3DTA_SELECTMASK
;
3590 DWORD color_arg2
= state
->texture_states
[i
][WINED3DTSS_COLORARG2
] & WINED3DTA_SELECTMASK
;
3591 DWORD color_arg3
= state
->texture_states
[i
][WINED3DTSS_COLORARG0
] & WINED3DTA_SELECTMASK
;
3592 DWORD alpha_arg1
= state
->texture_states
[i
][WINED3DTSS_ALPHAARG1
] & WINED3DTA_SELECTMASK
;
3593 DWORD alpha_arg2
= state
->texture_states
[i
][WINED3DTSS_ALPHAARG2
] & WINED3DTA_SELECTMASK
;
3594 DWORD alpha_arg3
= state
->texture_states
[i
][WINED3DTSS_ALPHAARG0
] & WINED3DTA_SELECTMASK
;
3596 if (color_op
== WINED3DTOP_DISABLE
) {
3597 /* Not used, and disable higher stages */
3601 if (((color_arg1
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG2
)
3602 || ((color_arg2
== WINED3DTA_TEXTURE
) && color_op
!= WINED3DTOP_SELECTARG1
)
3603 || ((color_arg3
== WINED3DTA_TEXTURE
) && (color_op
== WINED3DTOP_MULTIPLYADD
|| color_op
== WINED3DTOP_LERP
))
3604 || ((alpha_arg1
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG2
)
3605 || ((alpha_arg2
== WINED3DTA_TEXTURE
) && alpha_op
!= WINED3DTOP_SELECTARG1
)
3606 || ((alpha_arg3
== WINED3DTA_TEXTURE
) && (alpha_op
== WINED3DTOP_MULTIPLYADD
|| alpha_op
== WINED3DTOP_LERP
))) {
3607 This
->fixed_function_usage_map
|= (1 << i
);
3610 if ((color_op
== WINED3DTOP_BUMPENVMAP
|| color_op
== WINED3DTOP_BUMPENVMAPLUMINANCE
) && i
< MAX_TEXTURES
- 1) {
3611 This
->fixed_function_usage_map
|= (1 << (i
+ 1));
3616 static void device_map_fixed_function_samplers(IWineD3DDeviceImpl
*This
, const struct wined3d_gl_info
*gl_info
)
3618 unsigned int i
, tex
;
3621 device_update_fixed_function_usage_map(This
);
3622 ffu_map
= This
->fixed_function_usage_map
;
3624 if (This
->max_ffp_textures
== gl_info
->limits
.texture_stages
3625 || This
->stateBlock
->state
.lowest_disabled_stage
<= This
->max_ffp_textures
)
3627 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
3629 if (!(ffu_map
& 1)) continue;
3631 if (This
->texUnitMap
[i
] != i
) {
3632 device_map_stage(This
, i
, i
);
3633 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3634 markTextureStagesDirty(This
, i
);
3640 /* Now work out the mapping */
3642 for (i
= 0; ffu_map
; ffu_map
>>= 1, ++i
)
3644 if (!(ffu_map
& 1)) continue;
3646 if (This
->texUnitMap
[i
] != tex
) {
3647 device_map_stage(This
, i
, tex
);
3648 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3649 markTextureStagesDirty(This
, i
);
3656 static void device_map_psamplers(IWineD3DDeviceImpl
*This
, const struct wined3d_gl_info
*gl_info
)
3658 const WINED3DSAMPLER_TEXTURE_TYPE
*sampler_type
=
3659 This
->stateBlock
->state
.pixel_shader
->reg_maps
.sampler_type
;
3662 for (i
= 0; i
< MAX_FRAGMENT_SAMPLERS
; ++i
) {
3663 if (sampler_type
[i
] && This
->texUnitMap
[i
] != i
)
3665 device_map_stage(This
, i
, i
);
3666 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(i
));
3667 if (i
< gl_info
->limits
.texture_stages
)
3669 markTextureStagesDirty(This
, i
);
3675 static BOOL
device_unit_free_for_vs(IWineD3DDeviceImpl
*This
, const WINED3DSAMPLER_TEXTURE_TYPE
*pshader_sampler_tokens
,
3676 const WINED3DSAMPLER_TEXTURE_TYPE
*vshader_sampler_tokens
, DWORD unit
)
3678 DWORD current_mapping
= This
->rev_tex_unit_map
[unit
];
3680 /* Not currently used */
3681 if (current_mapping
== WINED3D_UNMAPPED_STAGE
) return TRUE
;
3683 if (current_mapping
< MAX_FRAGMENT_SAMPLERS
) {
3684 /* Used by a fragment sampler */
3686 if (!pshader_sampler_tokens
) {
3687 /* No pixel shader, check fixed function */
3688 return current_mapping
>= MAX_TEXTURES
|| !(This
->fixed_function_usage_map
& (1 << current_mapping
));
3691 /* Pixel shader, check the shader's sampler map */
3692 return !pshader_sampler_tokens
[current_mapping
];
3695 /* Used by a vertex sampler */
3696 return !vshader_sampler_tokens
[current_mapping
- MAX_FRAGMENT_SAMPLERS
];
3699 static void device_map_vsamplers(IWineD3DDeviceImpl
*This
, BOOL ps
, const struct wined3d_gl_info
*gl_info
)
3701 const WINED3DSAMPLER_TEXTURE_TYPE
*vshader_sampler_type
=
3702 This
->stateBlock
->state
.vertex_shader
->reg_maps
.sampler_type
;
3703 const WINED3DSAMPLER_TEXTURE_TYPE
*pshader_sampler_type
= NULL
;
3704 int start
= min(MAX_COMBINED_SAMPLERS
, gl_info
->limits
.combined_samplers
) - 1;
3709 /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
3710 * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
3711 pshader_sampler_type
= This
->stateBlock
->state
.pixel_shader
->reg_maps
.sampler_type
;
3714 for (i
= 0; i
< MAX_VERTEX_SAMPLERS
; ++i
) {
3715 DWORD vsampler_idx
= i
+ MAX_FRAGMENT_SAMPLERS
;
3716 if (vshader_sampler_type
[i
])
3718 if (This
->texUnitMap
[vsampler_idx
] != WINED3D_UNMAPPED_STAGE
)
3720 /* Already mapped somewhere */
3724 while (start
>= 0) {
3725 if (device_unit_free_for_vs(This
, pshader_sampler_type
, vshader_sampler_type
, start
))
3727 device_map_stage(This
, vsampler_idx
, start
);
3728 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(vsampler_idx
));
3740 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl
*This
)
3742 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
3743 const struct wined3d_state
*state
= &This
->stateBlock
->state
;
3744 BOOL vs
= use_vs(state
);
3745 BOOL ps
= use_ps(state
);
3748 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3749 * that would be really messy and require shader recompilation
3750 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3751 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3753 if (ps
) device_map_psamplers(This
, gl_info
);
3754 else device_map_fixed_function_samplers(This
, gl_info
);
3756 if (vs
) device_map_vsamplers(This
, ps
, gl_info
);
3759 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice
*iface
, struct wined3d_shader
*shader
)
3761 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
3762 struct wined3d_shader
*prev
= device
->updateStateBlock
->state
.pixel_shader
;
3764 device
->updateStateBlock
->state
.pixel_shader
= shader
;
3765 device
->updateStateBlock
->changed
.pixelShader
= TRUE
;
3767 /* Handle recording of state blocks */
3768 if (device
->isRecordingState
)
3769 TRACE("Recording... not performing anything\n");
3771 if (device
->isRecordingState
)
3773 TRACE("Recording... not performing anything.\n");
3775 wined3d_shader_incref(shader
);
3777 wined3d_shader_decref(prev
);
3783 TRACE("App is setting the old pixel shader over, nothing to do.\n");
3788 wined3d_shader_incref(shader
);
3790 wined3d_shader_decref(prev
);
3792 TRACE("Setting shader %p.\n", shader
);
3793 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_PIXELSHADER
);
3798 static struct wined3d_shader
* WINAPI
IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice
*iface
)
3800 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
3801 struct wined3d_shader
*shader
;
3803 TRACE("iface %p.\n", iface
);
3805 shader
= device
->stateBlock
->state
.pixel_shader
;
3807 wined3d_shader_incref(shader
);
3809 TRACE("Returning %p.\n", shader
);
3813 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantB(
3814 IWineD3DDevice
*iface
,
3816 CONST BOOL
*srcData
,
3819 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3820 unsigned int i
, cnt
= min(count
, MAX_CONST_B
- start
);
3822 TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3823 iface
, srcData
, start
, count
);
3825 if (!srcData
|| start
>= MAX_CONST_B
) return WINED3DERR_INVALIDCALL
;
3827 memcpy(&This
->updateStateBlock
->state
.ps_consts_b
[start
], srcData
, cnt
* sizeof(BOOL
));
3828 for (i
= 0; i
< cnt
; i
++)
3829 TRACE("Set BOOL constant %u to %s\n", start
+ i
, srcData
[i
]? "true":"false");
3831 for (i
= start
; i
< cnt
+ start
; ++i
) {
3832 This
->updateStateBlock
->changed
.pixelShaderConstantsB
|= (1 << i
);
3835 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3840 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantB(
3841 IWineD3DDevice
*iface
,
3846 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3847 int cnt
= min(count
, MAX_CONST_B
- start
);
3849 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3850 iface
, dstData
, start
, count
);
3852 if (!dstData
|| cnt
< 0)
3853 return WINED3DERR_INVALIDCALL
;
3855 memcpy(dstData
, &This
->stateBlock
->state
.ps_consts_b
[start
], cnt
* sizeof(BOOL
));
3859 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantI(
3860 IWineD3DDevice
*iface
,
3865 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3866 unsigned int i
, cnt
= min(count
, MAX_CONST_I
- start
);
3868 TRACE("(iface %p, srcData %p, start %u, count %u)\n",
3869 iface
, srcData
, start
, count
);
3871 if (!srcData
|| start
>= MAX_CONST_I
) return WINED3DERR_INVALIDCALL
;
3873 memcpy(&This
->updateStateBlock
->state
.ps_consts_i
[start
* 4], srcData
, cnt
* sizeof(int) * 4);
3874 for (i
= 0; i
< cnt
; i
++)
3875 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start
+ i
,
3876 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3878 for (i
= start
; i
< cnt
+ start
; ++i
) {
3879 This
->updateStateBlock
->changed
.pixelShaderConstantsI
|= (1 << i
);
3882 if (!This
->isRecordingState
) IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3887 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantI(
3888 IWineD3DDevice
*iface
,
3893 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3894 int cnt
= min(count
, MAX_CONST_I
- start
);
3896 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3897 iface
, dstData
, start
, count
);
3899 if (!dstData
|| cnt
< 0)
3900 return WINED3DERR_INVALIDCALL
;
3902 memcpy(dstData
, &This
->stateBlock
->state
.ps_consts_i
[start
* 4], cnt
* sizeof(int) * 4);
3906 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPixelShaderConstantF(
3907 IWineD3DDevice
*iface
,
3909 CONST
float *srcData
,
3912 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3915 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3916 iface
, srcData
, start
, count
);
3918 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3919 if (!srcData
|| start
+ count
> This
->d3d_pshader_constantF
|| start
> This
->d3d_pshader_constantF
)
3920 return WINED3DERR_INVALIDCALL
;
3922 memcpy(&This
->updateStateBlock
->state
.ps_consts_f
[start
* 4], srcData
, count
* sizeof(float) * 4);
3924 for (i
= 0; i
< count
; i
++)
3925 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start
+ i
,
3926 srcData
[i
*4], srcData
[i
*4+1], srcData
[i
*4+2], srcData
[i
*4+3]);
3929 if (!This
->isRecordingState
)
3931 This
->shader_backend
->shader_update_float_pixel_constants(This
, start
, count
);
3932 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADERCONSTANT
);
3935 memset(This
->updateStateBlock
->changed
.pixelShaderConstantsF
+ start
, 1,
3936 sizeof(*This
->updateStateBlock
->changed
.pixelShaderConstantsF
) * count
);
3941 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPixelShaderConstantF(
3942 IWineD3DDevice
*iface
,
3947 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
3948 int cnt
= min(count
, This
->d3d_pshader_constantF
- start
);
3950 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3951 iface
, dstData
, start
, count
);
3953 if (!dstData
|| cnt
< 0)
3954 return WINED3DERR_INVALIDCALL
;
3956 memcpy(dstData
, &This
->stateBlock
->state
.ps_consts_f
[start
* 4], cnt
* sizeof(float) * 4);
3960 /* Context activation is done by the caller. */
3961 /* Do not call while under the GL lock. */
3962 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3963 static HRESULT
process_vertices_strided(IWineD3DDeviceImpl
*This
, DWORD dwDestIndex
, DWORD dwCount
,
3964 const struct wined3d_stream_info
*stream_info
, struct wined3d_buffer
*dest
, DWORD flags
,
3967 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
3968 char *dest_ptr
, *dest_conv
= NULL
, *dest_conv_addr
= NULL
;
3971 WINED3DMATRIX mat
, proj_mat
, view_mat
, world_mat
;
3975 if (stream_info
->use_map
& (1 << WINED3D_FFP_NORMAL
))
3977 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3980 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_POSITION
)))
3982 ERR("Source has no position mask\n");
3983 return WINED3DERR_INVALIDCALL
;
3986 if (!dest
->resource
.allocatedMemory
)
3987 buffer_get_sysmem(dest
, gl_info
);
3989 /* Get a pointer into the destination vbo(create one if none exists) and
3990 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3992 if (!dest
->buffer_object
&& gl_info
->supported
[ARB_VERTEX_BUFFER_OBJECT
])
3994 dest
->flags
|= WINED3D_BUFFER_CREATEBO
;
3995 wined3d_buffer_preload(dest
);
3998 if (dest
->buffer_object
)
4000 unsigned char extrabytes
= 0;
4001 /* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
4002 * gets written into the 4 bytes after the Z position. In the case of a dest buffer that only has D3DFVF_XYZ data,
4003 * this may write 4 extra bytes beyond the area that should be written
4005 if(DestFVF
== WINED3DFVF_XYZ
) extrabytes
= 4;
4006 dest_conv_addr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwCount
* get_flexible_vertex_size(DestFVF
) + extrabytes
);
4007 if(!dest_conv_addr
) {
4008 ERR("Out of memory\n");
4009 /* Continue without storing converted vertices */
4011 dest_conv
= dest_conv_addr
;
4014 if (This
->stateBlock
->state
.render_states
[WINED3DRS_CLIPPING
])
4016 static BOOL warned
= FALSE
;
4018 * The clipping code is not quite correct. Some things need
4019 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
4020 * so disable clipping for now.
4021 * (The graphics in Half-Life are broken, and my processvertices
4022 * test crashes with IDirect3DDevice3)
4028 FIXME("Clipping is broken and disabled for now\n");
4030 } else doClip
= FALSE
;
4031 dest_ptr
= ((char *)buffer_get_sysmem(dest
, gl_info
)) + dwDestIndex
* get_flexible_vertex_size(DestFVF
);
4033 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4036 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4037 WINED3DTS_PROJECTION
,
4039 IWineD3DDevice_GetTransform( (IWineD3DDevice
*) This
,
4040 WINED3DTS_WORLDMATRIX(0),
4043 TRACE("View mat:\n");
4044 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
);
4045 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
);
4046 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
);
4047 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
);
4049 TRACE("Proj mat:\n");
4050 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
);
4051 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
);
4052 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
);
4053 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
);
4055 TRACE("World mat:\n");
4056 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
);
4057 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
);
4058 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
);
4059 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
);
4061 /* Get the viewport */
4062 IWineD3DDevice_GetViewport( (IWineD3DDevice
*) This
, &vp
);
4063 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
4064 vp
.X
, vp
.Y
, vp
.Width
, vp
.Height
, vp
.MinZ
, vp
.MaxZ
);
4066 multiply_matrix(&mat
,&view_mat
,&world_mat
);
4067 multiply_matrix(&mat
,&proj_mat
,&mat
);
4069 numTextures
= (DestFVF
& WINED3DFVF_TEXCOUNT_MASK
) >> WINED3DFVF_TEXCOUNT_SHIFT
;
4071 for (i
= 0; i
< dwCount
; i
+= 1) {
4072 unsigned int tex_index
;
4074 if ( ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZ
) ||
4075 ((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) ) {
4076 /* The position first */
4077 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_POSITION
];
4078 const float *p
= (const float *)(element
->data
+ i
* element
->stride
);
4080 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p
[0], p
[1], p
[2]);
4082 /* Multiplication with world, view and projection matrix */
4083 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
);
4084 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
);
4085 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
);
4086 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
);
4088 TRACE("x=%f y=%f z=%f rhw=%f\n", x
, y
, z
, rhw
);
4090 /* WARNING: The following things are taken from d3d7 and were not yet checked
4091 * against d3d8 or d3d9!
4094 /* Clipping conditions: From msdn
4096 * A vertex is clipped if it does not match the following requirements
4100 * 0 < rhw ( Not in d3d7, but tested in d3d7)
4102 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
4103 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
4108 ( (-rhw
-eps
< x
) && (-rhw
-eps
< y
) && ( -eps
< z
) &&
4109 (x
<= rhw
+ eps
) && (y
<= rhw
+ eps
) && (z
<= rhw
+ eps
) &&
4112 /* "Normal" viewport transformation (not clipped)
4113 * 1) The values are divided by rhw
4114 * 2) The y axis is negative, so multiply it with -1
4115 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
4116 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
4117 * 4) Multiply x with Width/2 and add Width/2
4118 * 5) The same for the height
4119 * 6) Add the viewpoint X and Y to the 2D coordinates and
4120 * The minimum Z value to z
4121 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
4123 * Well, basically it's simply a linear transformation into viewport
4135 z
*= vp
.MaxZ
- vp
.MinZ
;
4137 x
+= vp
.Width
/ 2 + vp
.X
;
4138 y
+= vp
.Height
/ 2 + vp
.Y
;
4143 /* That vertex got clipped
4144 * Contrary to OpenGL it is not dropped completely, it just
4145 * undergoes a different calculation.
4147 TRACE("Vertex got clipped\n");
4154 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
4155 * outside of the main vertex buffer memory. That needs some more
4160 TRACE("Writing (%f %f %f) %f\n", x
, y
, z
, rhw
);
4163 ( (float *) dest_ptr
)[0] = x
;
4164 ( (float *) dest_ptr
)[1] = y
;
4165 ( (float *) dest_ptr
)[2] = z
;
4166 ( (float *) dest_ptr
)[3] = rhw
; /* SIC, see ddraw test! */
4168 dest_ptr
+= 3 * sizeof(float);
4170 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4171 dest_ptr
+= sizeof(float);
4176 ( (float *) dest_conv
)[0] = x
* w
;
4177 ( (float *) dest_conv
)[1] = y
* w
;
4178 ( (float *) dest_conv
)[2] = z
* w
;
4179 ( (float *) dest_conv
)[3] = w
;
4181 dest_conv
+= 3 * sizeof(float);
4183 if((DestFVF
& WINED3DFVF_POSITION_MASK
) == WINED3DFVF_XYZRHW
) {
4184 dest_conv
+= sizeof(float);
4188 if (DestFVF
& WINED3DFVF_PSIZE
) {
4189 dest_ptr
+= sizeof(DWORD
);
4190 if(dest_conv
) dest_conv
+= sizeof(DWORD
);
4192 if (DestFVF
& WINED3DFVF_NORMAL
) {
4193 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_NORMAL
];
4194 const float *normal
= (const float *)(element
->data
+ i
* element
->stride
);
4195 /* AFAIK this should go into the lighting information */
4196 FIXME("Didn't expect the destination to have a normal\n");
4197 copy_and_next(dest_ptr
, normal
, 3 * sizeof(float));
4199 copy_and_next(dest_conv
, normal
, 3 * sizeof(float));
4203 if (DestFVF
& WINED3DFVF_DIFFUSE
) {
4204 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_DIFFUSE
];
4205 const DWORD
*color_d
= (const DWORD
*)(element
->data
+ i
* element
->stride
);
4206 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_DIFFUSE
)))
4208 static BOOL warned
= FALSE
;
4211 ERR("No diffuse color in source, but destination has one\n");
4215 *( (DWORD
*) dest_ptr
) = 0xffffffff;
4216 dest_ptr
+= sizeof(DWORD
);
4219 *( (DWORD
*) dest_conv
) = 0xffffffff;
4220 dest_conv
+= sizeof(DWORD
);
4224 copy_and_next(dest_ptr
, color_d
, sizeof(DWORD
));
4226 *( (DWORD
*) dest_conv
) = (*color_d
& 0xff00ff00) ; /* Alpha + green */
4227 *( (DWORD
*) dest_conv
) |= (*color_d
& 0x00ff0000) >> 16; /* Red */
4228 *( (DWORD
*) dest_conv
) |= (*color_d
& 0xff0000ff) << 16; /* Blue */
4229 dest_conv
+= sizeof(DWORD
);
4234 if (DestFVF
& WINED3DFVF_SPECULAR
)
4236 /* What's the color value in the feedback buffer? */
4237 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_SPECULAR
];
4238 const DWORD
*color_s
= (const DWORD
*)(element
->data
+ i
* element
->stride
);
4239 if (!(stream_info
->use_map
& (1 << WINED3D_FFP_SPECULAR
)))
4241 static BOOL warned
= FALSE
;
4244 ERR("No specular color in source, but destination has one\n");
4248 *( (DWORD
*) dest_ptr
) = 0xFF000000;
4249 dest_ptr
+= sizeof(DWORD
);
4252 *( (DWORD
*) dest_conv
) = 0xFF000000;
4253 dest_conv
+= sizeof(DWORD
);
4257 copy_and_next(dest_ptr
, color_s
, sizeof(DWORD
));
4259 *( (DWORD
*) dest_conv
) = (*color_s
& 0xff00ff00) ; /* Alpha + green */
4260 *( (DWORD
*) dest_conv
) |= (*color_s
& 0x00ff0000) >> 16; /* Red */
4261 *( (DWORD
*) dest_conv
) |= (*color_s
& 0xff0000ff) << 16; /* Blue */
4262 dest_conv
+= sizeof(DWORD
);
4267 for (tex_index
= 0; tex_index
< numTextures
; tex_index
++) {
4268 const struct wined3d_stream_info_element
*element
= &stream_info
->elements
[WINED3D_FFP_TEXCOORD0
+ tex_index
];
4269 const float *tex_coord
= (const float *)(element
->data
+ i
* element
->stride
);
4270 if (!(stream_info
->use_map
& (1 << (WINED3D_FFP_TEXCOORD0
+ tex_index
))))
4272 ERR("No source texture, but destination requests one\n");
4273 dest_ptr
+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4274 if(dest_conv
) dest_conv
+= GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float);
4277 copy_and_next(dest_ptr
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4279 copy_and_next(dest_conv
, tex_coord
, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF
, tex_index
) * sizeof(float));
4289 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dest
->buffer_object
));
4290 checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
4291 GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB
, dwDestIndex
* get_flexible_vertex_size(DestFVF
),
4292 dwCount
* get_flexible_vertex_size(DestFVF
),
4294 checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
4298 HeapFree(GetProcessHeap(), 0, dest_conv_addr
);
4303 #undef copy_and_next
4305 /* Do not call while under the GL lock. */
4306 static HRESULT WINAPI
IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice
*iface
,
4307 UINT SrcStartIndex
, UINT DestIndex
, UINT VertexCount
, struct wined3d_buffer
*dst_buffer
,
4308 struct wined3d_vertex_declaration
*pVertexDecl
, DWORD flags
, DWORD DestFVF
)
4310 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4311 struct wined3d_stream_info stream_info
;
4312 const struct wined3d_gl_info
*gl_info
;
4313 struct wined3d_context
*context
;
4314 BOOL vbo
= FALSE
, streamWasUP
= This
->stateBlock
->state
.user_stream
;
4317 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This
, SrcStartIndex
, DestIndex
, VertexCount
, dst_buffer
, pVertexDecl
, flags
);
4320 ERR("Output vertex declaration not implemented yet\n");
4323 /* Need any context to write to the vbo. */
4324 context
= context_acquire(This
, NULL
);
4325 gl_info
= context
->gl_info
;
4327 /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
4328 * control the streamIsUP flag, thus restore it afterwards.
4330 This
->stateBlock
->state
.user_stream
= FALSE
;
4331 device_stream_info_from_declaration(This
, FALSE
, &stream_info
, &vbo
);
4332 This
->stateBlock
->state
.user_stream
= streamWasUP
;
4334 if(vbo
|| SrcStartIndex
) {
4336 /* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
4337 * unlikely to ever be used for drawing. Release vbos in those buffers and fix up the stream_info structure
4339 * Also get the start index in, but only loop over all elements if there's something to add at all.
4341 for (i
= 0; i
< (sizeof(stream_info
.elements
) / sizeof(*stream_info
.elements
)); ++i
)
4343 struct wined3d_stream_info_element
*e
;
4345 if (!(stream_info
.use_map
& (1 << i
))) continue;
4347 e
= &stream_info
.elements
[i
];
4348 if (e
->buffer_object
)
4350 struct wined3d_buffer
*vb
= This
->stateBlock
->state
.streams
[e
->stream_idx
].buffer
;
4351 e
->buffer_object
= 0;
4352 e
->data
= (BYTE
*)((ULONG_PTR
)e
->data
+ (ULONG_PTR
)buffer_get_sysmem(vb
, gl_info
));
4354 GL_EXTCALL(glDeleteBuffersARB(1, &vb
->buffer_object
));
4355 vb
->buffer_object
= 0;
4358 if (e
->data
) e
->data
+= e
->stride
* SrcStartIndex
;
4362 hr
= process_vertices_strided(This
, DestIndex
, VertexCount
,
4363 &stream_info
, dst_buffer
, flags
, DestFVF
);
4365 context_release(context
);
4371 * Get / Set Texture Stage States
4372 * TODO: Verify against dx9 definitions
4374 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD Value
)
4376 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4377 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
4380 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This
, Stage
, debug_d3dtexturestate(Type
), Type
, Value
);
4382 if (Type
> WINED3D_HIGHEST_TEXTURE_STATE
)
4384 WARN("Invalid Type %d passed.\n", Type
);
4388 if (Stage
>= gl_info
->limits
.texture_stages
)
4390 WARN("Attempting to set stage %u which is higher than the max stage %u, ignoring.\n",
4391 Stage
, gl_info
->limits
.texture_stages
- 1);
4395 oldValue
= This
->updateStateBlock
->state
.texture_states
[Stage
][Type
];
4396 This
->updateStateBlock
->changed
.textureState
[Stage
] |= 1 << Type
;
4397 This
->updateStateBlock
->state
.texture_states
[Stage
][Type
] = Value
;
4399 if (This
->isRecordingState
) {
4400 TRACE("Recording... not performing anything\n");
4404 /* Checked after the assignments to allow proper stateblock recording */
4405 if(oldValue
== Value
) {
4406 TRACE("App is setting the old value over, nothing to do\n");
4410 if (Stage
> This
->stateBlock
->state
.lowest_disabled_stage
4411 && This
->StateTable
[STATE_TEXTURESTAGE(0, Type
)].representative
4412 == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP
))
4414 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4415 * Changes in other states are important on disabled stages too
4420 if(Type
== WINED3DTSS_COLOROP
) {
4423 if(Value
== WINED3DTOP_DISABLE
&& oldValue
!= WINED3DTOP_DISABLE
) {
4424 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4425 * they have to be disabled
4427 * The current stage is dirtified below.
4429 for (i
= Stage
+ 1; i
< This
->stateBlock
->state
.lowest_disabled_stage
; ++i
)
4431 TRACE("Additionally dirtifying stage %u\n", i
);
4432 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4434 This
->stateBlock
->state
.lowest_disabled_stage
= Stage
;
4435 TRACE("New lowest disabled: %u\n", Stage
);
4436 } else if(Value
!= WINED3DTOP_DISABLE
&& oldValue
== WINED3DTOP_DISABLE
) {
4437 /* Previously disabled stage enabled. Stages above it may need enabling
4438 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4439 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4441 * Again stage Stage doesn't need to be dirtified here, it is handled below.
4444 for (i
= Stage
+ 1; i
< This
->adapter
->gl_info
.limits
.texture_stages
; ++i
)
4446 if (This
->updateStateBlock
->state
.texture_states
[i
][WINED3DTSS_COLOROP
] == WINED3DTOP_DISABLE
)
4448 TRACE("Additionally dirtifying stage %u due to enable\n", i
);
4449 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(i
, WINED3DTSS_COLOROP
));
4451 This
->stateBlock
->state
.lowest_disabled_stage
= i
;
4452 TRACE("New lowest disabled: %u\n", i
);
4456 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(Stage
, Type
));
4461 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice
*iface
, DWORD Stage
, WINED3DTEXTURESTAGESTATETYPE Type
, DWORD
*pValue
)
4463 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4465 TRACE("iface %p, stage %u, state %s, value %p.\n",
4466 iface
, Stage
, debug_d3dtexturestate(Type
), pValue
);
4468 if (Type
> WINED3D_HIGHEST_TEXTURE_STATE
)
4470 WARN("Invalid Type %d passed.\n", Type
);
4474 *pValue
= This
->updateStateBlock
->state
.texture_states
[Stage
][Type
];
4475 TRACE("Returning %#x.\n", *pValue
);
4480 static HRESULT WINAPI
IWineD3DDeviceImpl_SetTexture(IWineD3DDevice
*iface
,
4481 DWORD stage
, struct wined3d_texture
*texture
)
4483 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4484 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
4485 struct wined3d_texture
*prev
;
4487 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4489 if (stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& stage
<= WINED3DVERTEXTEXTURESAMPLER3
)
4490 stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4492 /* Windows accepts overflowing this array... we do not. */
4493 if (stage
>= sizeof(This
->stateBlock
->state
.textures
) / sizeof(*This
->stateBlock
->state
.textures
))
4495 WARN("Ignoring invalid stage %u.\n", stage
);
4499 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
4500 if (texture
&& texture
->resource
.pool
== WINED3DPOOL_SCRATCH
)
4502 WARN("Rejecting attempt to set scratch texture.\n");
4503 return WINED3DERR_INVALIDCALL
;
4506 This
->updateStateBlock
->changed
.textures
|= 1 << stage
;
4508 prev
= This
->updateStateBlock
->state
.textures
[stage
];
4509 TRACE("Previous texture %p.\n", prev
);
4511 if (texture
== prev
)
4513 TRACE("App is setting the same texture again, nothing to do.\n");
4517 TRACE("Setting new texture to %p.\n", texture
);
4518 This
->updateStateBlock
->state
.textures
[stage
] = texture
;
4520 if (This
->isRecordingState
)
4522 TRACE("Recording... not performing anything\n");
4524 if (texture
) wined3d_texture_incref(texture
);
4525 if (prev
) wined3d_texture_decref(prev
);
4532 LONG bind_count
= InterlockedIncrement(&texture
->bind_count
);
4534 wined3d_texture_incref(texture
);
4536 if (!prev
|| texture
->target
!= prev
->target
)
4537 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_PIXELSHADER
);
4539 if (!prev
&& stage
< gl_info
->limits
.texture_stages
)
4541 /* The source arguments for color and alpha ops have different
4542 * meanings when a NULL texture is bound, so the COLOROP and
4543 * ALPHAOP have to be dirtified. */
4544 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_COLOROP
));
4545 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_ALPHAOP
));
4548 if (bind_count
== 1)
4549 texture
->sampler
= stage
;
4554 LONG bind_count
= InterlockedDecrement(&prev
->bind_count
);
4556 wined3d_texture_decref(prev
);
4558 if (!texture
&& stage
< gl_info
->limits
.texture_stages
)
4560 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_COLOROP
));
4561 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_TEXTURESTAGE(stage
, WINED3DTSS_ALPHAOP
));
4564 if (bind_count
&& prev
->sampler
== stage
)
4568 /* Search for other stages the texture is bound to. Shouldn't
4569 * happen if applications bind textures to a single stage only. */
4570 TRACE("Searching for other stages the texture is bound to.\n");
4571 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
4573 if (This
->updateStateBlock
->state
.textures
[i
] == prev
)
4575 TRACE("Texture is also bound to stage %u.\n", i
);
4583 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(stage
));
4588 static HRESULT WINAPI
IWineD3DDeviceImpl_GetTexture(IWineD3DDevice
*iface
,
4589 DWORD stage
, struct wined3d_texture
**texture
)
4591 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4593 TRACE("iface %p, stage %u, texture %p.\n", iface
, stage
, texture
);
4595 if (stage
>= WINED3DVERTEXTEXTURESAMPLER0
&& stage
<= WINED3DVERTEXTEXTURESAMPLER3
)
4596 stage
-= (WINED3DVERTEXTEXTURESAMPLER0
- MAX_FRAGMENT_SAMPLERS
);
4598 if (stage
>= sizeof(This
->stateBlock
->state
.textures
) / sizeof(*This
->stateBlock
->state
.textures
))
4600 WARN("Current stage overflows textures array (stage %u).\n", stage
);
4601 return WINED3D_OK
; /* Windows accepts overflowing this array ... we do not. */
4604 *texture
= This
->stateBlock
->state
.textures
[stage
];
4606 wined3d_texture_incref(*texture
);
4608 TRACE("Returning %p.\n", *texture
);
4616 static HRESULT WINAPI
IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice
*iface
, UINT swapchain_idx
,
4617 UINT backbuffer_idx
, WINED3DBACKBUFFER_TYPE backbuffer_type
, struct wined3d_surface
**backbuffer
)
4619 struct wined3d_swapchain
*swapchain
;
4622 TRACE("iface %p, swapchain_idx %u, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
4623 iface
, swapchain_idx
, backbuffer_idx
, backbuffer_type
, backbuffer
);
4625 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
4628 WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx
, hr
);
4632 hr
= wined3d_swapchain_get_back_buffer(swapchain
, backbuffer_idx
, backbuffer_type
, backbuffer
);
4633 wined3d_swapchain_decref(swapchain
);
4636 WARN("Failed to get backbuffer %u, hr %#x.\n", backbuffer_idx
, hr
);
4643 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice
*iface
, WINED3DCAPS
*caps
)
4645 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
4647 TRACE("iface %p, caps %p.\n", iface
, caps
);
4649 return wined3d_get_device_caps(device
->wined3d
, device
->adapter
->ordinal
, device
->devType
, caps
);
4652 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice
*iface
,
4653 UINT swapchain_idx
, WINED3DDISPLAYMODE
*mode
)
4655 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
4656 struct wined3d_swapchain
*swapchain
;
4659 TRACE("iface %p, swapchain_idx %u, mode %p.\n", iface
, swapchain_idx
, mode
);
4663 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
4666 hr
= wined3d_swapchain_get_display_mode(swapchain
, mode
);
4667 wined3d_swapchain_decref(swapchain
);
4672 /* Don't read the real display mode, but return the stored mode
4673 * instead. X11 can't change the color depth, and some apps are
4674 * pretty angry if they SetDisplayMode from 24 to 16 bpp and find out
4675 * that GetDisplayMode still returns 24 bpp.
4677 * Also don't relay to the swapchain because with ddraw it's possible
4678 * that there isn't a swapchain at all. */
4679 mode
->Width
= device
->ddraw_width
;
4680 mode
->Height
= device
->ddraw_height
;
4681 mode
->Format
= device
->ddraw_format
;
4682 mode
->RefreshRate
= 0;
4690 * Stateblock related functions
4693 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice
*iface
)
4695 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4696 struct wined3d_stateblock
*stateblock
;
4699 TRACE("(%p)\n", This
);
4701 if (This
->isRecordingState
) return WINED3DERR_INVALIDCALL
;
4703 hr
= IWineD3DDeviceImpl_CreateStateBlock(iface
, WINED3DSBT_RECORDED
, &stateblock
);
4704 if (FAILED(hr
)) return hr
;
4706 wined3d_stateblock_decref(This
->updateStateBlock
);
4707 This
->updateStateBlock
= stateblock
;
4708 This
->isRecordingState
= TRUE
;
4710 TRACE("(%p) recording stateblock %p\n", This
, stateblock
);
4715 static HRESULT WINAPI
IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice
*iface
,
4716 struct wined3d_stateblock
**stateblock
)
4718 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4719 struct wined3d_stateblock
*object
= This
->updateStateBlock
;
4721 TRACE("iface %p, stateblock %p.\n", iface
, stateblock
);
4723 if (!This
->isRecordingState
) {
4724 WARN("(%p) not recording! returning error\n", This
);
4726 return WINED3DERR_INVALIDCALL
;
4729 stateblock_init_contained_states(object
);
4731 *stateblock
= object
;
4732 This
->isRecordingState
= FALSE
;
4733 This
->updateStateBlock
= This
->stateBlock
;
4734 wined3d_stateblock_incref(This
->updateStateBlock
);
4736 TRACE("Returning stateblock %p.\n", *stateblock
);
4742 * Scene related functions
4744 static HRESULT WINAPI
IWineD3DDeviceImpl_BeginScene(IWineD3DDevice
*iface
) {
4745 /* At the moment we have no need for any functionality at the beginning
4747 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4748 TRACE("(%p)\n", This
);
4751 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4752 return WINED3DERR_INVALIDCALL
;
4754 This
->inScene
= TRUE
;
4758 static HRESULT WINAPI
IWineD3DDeviceImpl_EndScene(IWineD3DDevice
*iface
)
4760 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4761 struct wined3d_context
*context
;
4763 TRACE("(%p)\n", This
);
4765 if(!This
->inScene
) {
4766 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4767 return WINED3DERR_INVALIDCALL
;
4770 context
= context_acquire(This
, NULL
);
4771 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4773 /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
4775 context_release(context
);
4777 This
->inScene
= FALSE
;
4781 static HRESULT WINAPI
IWineD3DDeviceImpl_Present(IWineD3DDevice
*iface
, const RECT
*src_rect
,
4782 const RECT
*dst_rect
, HWND dst_window_override
, const RGNDATA
*dirty_region
)
4784 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
4787 TRACE("iface %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p.\n",
4788 iface
, wine_dbgstr_rect(src_rect
), wine_dbgstr_rect(dst_rect
),
4789 dst_window_override
, dirty_region
);
4791 for (i
= 0; i
< device
->swapchain_count
; ++i
)
4793 wined3d_swapchain_present(device
->swapchains
[i
], src_rect
,
4794 dst_rect
, dst_window_override
, dirty_region
, 0);
4800 /* Do not call while under the GL lock. */
4801 static HRESULT WINAPI
IWineD3DDeviceImpl_Clear(IWineD3DDevice
*iface
, DWORD rect_count
,
4802 const RECT
*rects
, DWORD flags
, WINED3DCOLOR color
, float depth
, DWORD stencil
)
4804 const WINED3DCOLORVALUE c
= {D3DCOLOR_R(color
), D3DCOLOR_G(color
), D3DCOLOR_B(color
), D3DCOLOR_A(color
)};
4805 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
4808 TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, depth %.8e, stencil %u.\n",
4809 iface
, rect_count
, rects
, flags
, color
, depth
, stencil
);
4811 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
4813 struct wined3d_surface
*ds
= device
->depth_stencil
;
4816 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4817 /* TODO: What about depth stencil buffers without stencil bits? */
4818 return WINED3DERR_INVALIDCALL
;
4820 else if (flags
& WINED3DCLEAR_TARGET
)
4822 if(ds
->resource
.width
< device
->render_targets
[0]->resource
.width
||
4823 ds
->resource
.height
< device
->render_targets
[0]->resource
.height
)
4825 WARN("Silently ignoring depth and target clear with mismatching sizes\n");
4831 device_get_draw_rect(device
, &draw_rect
);
4833 return device_clear_render_targets(device
, device
->adapter
->gl_info
.limits
.buffers
,
4834 device
->render_targets
, device
->depth_stencil
, rect_count
, rects
,
4835 &draw_rect
, flags
, &c
, depth
, stencil
);
4842 static void WINAPI
IWineD3DDeviceImpl_SetPrimitiveType(IWineD3DDevice
*iface
,
4843 WINED3DPRIMITIVETYPE primitive_type
)
4845 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4847 TRACE("iface %p, primitive_type %s\n", iface
, debug_d3dprimitivetype(primitive_type
));
4849 This
->updateStateBlock
->changed
.primitive_type
= TRUE
;
4850 This
->updateStateBlock
->state
.gl_primitive_type
= gl_primitive_type_from_d3d(primitive_type
);
4853 static void WINAPI
IWineD3DDeviceImpl_GetPrimitiveType(IWineD3DDevice
*iface
,
4854 WINED3DPRIMITIVETYPE
*primitive_type
)
4856 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4858 TRACE("iface %p, primitive_type %p\n", iface
, primitive_type
);
4860 *primitive_type
= d3d_primitive_type_from_gl(This
->stateBlock
->state
.gl_primitive_type
);
4862 TRACE("Returning %s\n", debug_d3dprimitivetype(*primitive_type
));
4865 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice
*iface
, UINT StartVertex
, UINT vertex_count
)
4867 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4869 TRACE("(%p) : start %u, count %u\n", This
, StartVertex
, vertex_count
);
4871 if (!This
->stateBlock
->state
.vertex_declaration
)
4873 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4874 return WINED3DERR_INVALIDCALL
;
4877 /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4878 if (This
->stateBlock
->state
.user_stream
)
4880 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4881 This
->stateBlock
->state
.user_stream
= FALSE
;
4884 if (This
->stateBlock
->state
.load_base_vertex_index
)
4886 This
->stateBlock
->state
.load_base_vertex_index
= 0;
4887 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4889 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4890 drawPrimitive(This
, vertex_count
, StartVertex
/* start_idx */, 0 /* indxSize */, NULL
/* indxData */);
4894 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice
*iface
, UINT startIndex
, UINT index_count
)
4896 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4897 struct wined3d_buffer
*index_buffer
;
4901 index_buffer
= This
->stateBlock
->state
.index_buffer
;
4904 /* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
4905 * without an index buffer set. (The first time at least...)
4906 * D3D8 simply dies, but I doubt it can do much harm to return
4907 * D3DERR_INVALIDCALL there as well. */
4908 WARN("(%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL\n", This
);
4909 return WINED3DERR_INVALIDCALL
;
4912 if (!This
->stateBlock
->state
.vertex_declaration
)
4914 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4915 return WINED3DERR_INVALIDCALL
;
4918 if (This
->stateBlock
->state
.user_stream
)
4920 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
4921 This
->stateBlock
->state
.user_stream
= FALSE
;
4923 vbo
= index_buffer
->buffer_object
;
4925 TRACE("(%p) : startIndex %u, index count %u.\n", This
, startIndex
, index_count
);
4927 if (This
->stateBlock
->state
.index_format
== WINED3DFMT_R16_UINT
)
4932 if (This
->stateBlock
->state
.load_base_vertex_index
!= This
->stateBlock
->state
.base_vertex_index
)
4934 This
->stateBlock
->state
.load_base_vertex_index
= This
->stateBlock
->state
.base_vertex_index
;
4935 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4938 drawPrimitive(This
, index_count
, startIndex
, idxStride
,
4939 vbo
? NULL
: index_buffer
->resource
.allocatedMemory
);
4944 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice
*iface
, UINT vertex_count
,
4945 const void *pVertexStreamZeroData
, UINT VertexStreamZeroStride
)
4947 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4948 struct wined3d_stream_state
*stream
;
4949 struct wined3d_buffer
*vb
;
4951 TRACE("(%p) : vertex count %u, pVtxData %p, stride %u\n",
4952 This
, vertex_count
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4954 if (!This
->stateBlock
->state
.vertex_declaration
)
4956 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
4957 return WINED3DERR_INVALIDCALL
;
4960 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4961 stream
= &This
->stateBlock
->state
.streams
[0];
4962 vb
= stream
->buffer
;
4963 stream
->buffer
= (struct wined3d_buffer
*)pVertexStreamZeroData
;
4965 wined3d_buffer_decref(vb
);
4967 stream
->stride
= VertexStreamZeroStride
;
4968 This
->stateBlock
->state
.user_stream
= TRUE
;
4969 This
->stateBlock
->state
.load_base_vertex_index
= 0;
4971 /* TODO: Only mark dirty if drawing from a different UP address */
4972 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_STREAMSRC
);
4974 drawPrimitive(This
, vertex_count
, 0 /* start_idx */, 0 /* indxSize*/, NULL
/* indxData */);
4976 /* MSDN specifies stream zero settings must be set to NULL */
4977 stream
->buffer
= NULL
;
4980 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4981 * the new stream sources or use UP drawing again
4986 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice
*iface
,
4987 UINT index_count
, const void *pIndexData
, enum wined3d_format_id IndexDataFormat
,
4988 const void *pVertexStreamZeroData
, UINT VertexStreamZeroStride
)
4991 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
4992 struct wined3d_stream_state
*stream
;
4993 struct wined3d_buffer
*vb
, *ib
;
4995 TRACE("(%p) : index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u.\n",
4996 This
, index_count
, pIndexData
, IndexDataFormat
, pVertexStreamZeroData
, VertexStreamZeroStride
);
4998 if (!This
->stateBlock
->state
.vertex_declaration
)
5000 WARN("(%p) : Called without a valid vertex declaration set\n", This
);
5001 return WINED3DERR_INVALIDCALL
;
5004 if (IndexDataFormat
== WINED3DFMT_R16_UINT
) {
5010 stream
= &This
->stateBlock
->state
.streams
[0];
5011 vb
= stream
->buffer
;
5012 stream
->buffer
= (struct wined3d_buffer
*)pVertexStreamZeroData
;
5014 wined3d_buffer_decref(vb
);
5016 stream
->stride
= VertexStreamZeroStride
;
5017 This
->stateBlock
->state
.user_stream
= TRUE
;
5019 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
5020 This
->stateBlock
->state
.base_vertex_index
= 0;
5021 This
->stateBlock
->state
.load_base_vertex_index
= 0;
5022 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
5023 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5024 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5026 drawPrimitive(This
, index_count
, 0 /* start_idx */, idxStride
, pIndexData
);
5028 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
5029 stream
->buffer
= NULL
;
5031 ib
= This
->stateBlock
->state
.index_buffer
;
5034 wined3d_buffer_decref(ib
);
5035 This
->stateBlock
->state
.index_buffer
= NULL
;
5037 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
5038 * SetStreamSource to specify a vertex buffer
5044 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawPrimitiveStrided(IWineD3DDevice
*iface
,
5045 UINT vertex_count
, const WineDirect3DVertexStridedData
*DrawPrimStrideData
)
5047 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5049 /* Mark the state dirty until we have nicer tracking
5050 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5053 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5054 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5055 This
->stateBlock
->state
.base_vertex_index
= 0;
5056 This
->up_strided
= DrawPrimStrideData
;
5057 drawPrimitive(This
, vertex_count
, 0, 0, NULL
);
5058 This
->up_strided
= NULL
;
5062 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided(IWineD3DDevice
*iface
,
5063 UINT vertex_count
, const WineDirect3DVertexStridedData
*DrawPrimStrideData
,
5064 UINT NumVertices
, const void *pIndexData
, enum wined3d_format_id IndexDataFormat
)
5066 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
5067 DWORD idxSize
= (IndexDataFormat
== WINED3DFMT_R32_UINT
? 4 : 2);
5069 /* Mark the state dirty until we have nicer tracking
5070 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
5073 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_VDECL
);
5074 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_INDEXBUFFER
);
5075 This
->stateBlock
->state
.user_stream
= TRUE
;
5076 This
->stateBlock
->state
.base_vertex_index
= 0;
5077 This
->up_strided
= DrawPrimStrideData
;
5078 drawPrimitive(This
, vertex_count
, 0 /* start_idx */, idxSize
, pIndexData
);
5079 This
->up_strided
= NULL
;
5083 /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */
5084 static HRESULT
IWineD3DDeviceImpl_UpdateVolume(IWineD3DDevice
*iface
,
5085 struct wined3d_volume
*src_volume
, struct wined3d_volume
*dst_volume
)
5087 WINED3DLOCKED_BOX src
;
5088 WINED3DLOCKED_BOX dst
;
5091 TRACE("iface %p, src_volume %p, dst_volume %p.\n",
5092 iface
, src_volume
, dst_volume
);
5094 /* TODO: Implement direct loading into the gl volume instead of using
5095 * memcpy and dirtification to improve loading performance. */
5096 hr
= wined3d_volume_map(src_volume
, &src
, NULL
, WINED3DLOCK_READONLY
);
5097 if (FAILED(hr
)) return hr
;
5098 hr
= wined3d_volume_map(dst_volume
, &dst
, NULL
, WINED3DLOCK_DISCARD
);
5101 wined3d_volume_unmap(src_volume
);
5105 memcpy(dst
.pBits
, src
.pBits
, dst_volume
->resource
.size
);
5107 hr
= wined3d_volume_unmap(dst_volume
);
5109 wined3d_volume_unmap(src_volume
);
5111 hr
= wined3d_volume_unmap(src_volume
);
5116 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateTexture(IWineD3DDevice
*iface
,
5117 struct wined3d_texture
*src_texture
, struct wined3d_texture
*dst_texture
)
5119 unsigned int level_count
, i
;
5120 WINED3DRESOURCETYPE type
;
5123 TRACE("iface %p, src_texture %p, dst_texture %p.\n", iface
, src_texture
, dst_texture
);
5125 /* Verify that the source and destination textures are non-NULL. */
5126 if (!src_texture
|| !dst_texture
)
5128 WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n");
5129 return WINED3DERR_INVALIDCALL
;
5132 if (src_texture
== dst_texture
)
5134 WARN("Source and destination are the same object, returning WINED3DERR_INVALIDCALL.\n");
5135 return WINED3DERR_INVALIDCALL
;
5138 /* Verify that the source and destination textures are the same type. */
5139 type
= wined3d_texture_get_type(src_texture
);
5140 if (wined3d_texture_get_type(dst_texture
) != type
)
5142 WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n");
5143 return WINED3DERR_INVALIDCALL
;
5146 /* Check that both textures have the identical numbers of levels. */
5147 level_count
= wined3d_texture_get_level_count(src_texture
);
5148 if (wined3d_texture_get_level_count(dst_texture
) != level_count
)
5150 WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
5151 return WINED3DERR_INVALIDCALL
;
5154 /* Make sure that the destination texture is loaded. */
5155 dst_texture
->texture_ops
->texture_preload(dst_texture
, SRGB_RGB
);
5157 /* Update every surface level of the texture. */
5160 case WINED3DRTYPE_TEXTURE
:
5162 struct wined3d_surface
*src_surface
;
5163 struct wined3d_surface
*dst_surface
;
5165 for (i
= 0; i
< level_count
; ++i
)
5167 src_surface
= surface_from_resource(wined3d_texture_get_sub_resource(src_texture
, i
));
5168 dst_surface
= surface_from_resource(wined3d_texture_get_sub_resource(dst_texture
, i
));
5169 hr
= IWineD3DDevice_UpdateSurface(iface
, src_surface
, NULL
, dst_surface
, NULL
);
5172 WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr
);
5179 case WINED3DRTYPE_CUBETEXTURE
:
5181 struct wined3d_surface
*src_surface
;
5182 struct wined3d_surface
*dst_surface
;
5184 for (i
= 0; i
< level_count
* 6; ++i
)
5186 src_surface
= surface_from_resource(wined3d_texture_get_sub_resource(src_texture
, i
));
5187 dst_surface
= surface_from_resource(wined3d_texture_get_sub_resource(dst_texture
, i
));
5188 hr
= IWineD3DDevice_UpdateSurface(iface
, src_surface
, NULL
, dst_surface
, NULL
);
5191 WARN("IWineD3DDevice_UpdateSurface failed, hr %#x.\n", hr
);
5198 case WINED3DRTYPE_VOLUMETEXTURE
:
5200 for (i
= 0; i
< level_count
; ++i
)
5202 hr
= IWineD3DDeviceImpl_UpdateVolume(iface
,
5203 volume_from_resource(wined3d_texture_get_sub_resource(src_texture
, i
)),
5204 volume_from_resource(wined3d_texture_get_sub_resource(dst_texture
, i
)));
5207 WARN("IWineD3DDeviceImpl_UpdateVolume failed, hr %#x.\n", hr
);
5215 FIXME("Unsupported texture type %#x.\n", type
);
5216 return WINED3DERR_INVALIDCALL
;
5222 static HRESULT WINAPI
IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice
*iface
,
5223 UINT swapchain_idx
, struct wined3d_surface
*dst_surface
)
5225 struct wined3d_swapchain
*swapchain
;
5228 TRACE("iface %p, swapchain_idx %u, dst_surface %p.\n", iface
, swapchain_idx
, dst_surface
);
5230 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
5231 if (FAILED(hr
)) return hr
;
5233 hr
= wined3d_swapchain_get_front_buffer_data(swapchain
, dst_surface
);
5234 wined3d_swapchain_decref(swapchain
);
5239 static HRESULT WINAPI
IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice
*iface
, DWORD
*pNumPasses
)
5241 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5242 const struct wined3d_state
*state
= &This
->stateBlock
->state
;
5243 struct wined3d_texture
*texture
;
5246 TRACE("(%p) : %p\n", This
, pNumPasses
);
5248 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
5250 if (state
->sampler_states
[i
][WINED3DSAMP_MINFILTER
] == WINED3DTEXF_NONE
)
5252 WARN("Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
5253 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
5255 if (state
->sampler_states
[i
][WINED3DSAMP_MAGFILTER
] == WINED3DTEXF_NONE
)
5257 WARN("Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER\n", i
);
5258 return WINED3DERR_UNSUPPORTEDTEXTUREFILTER
;
5261 texture
= state
->textures
[i
];
5262 if (!texture
|| texture
->resource
.format
->flags
& WINED3DFMT_FLAG_FILTERING
) continue;
5264 if (state
->sampler_states
[i
][WINED3DSAMP_MAGFILTER
] != WINED3DTEXF_POINT
)
5266 WARN("Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL\n", i
);
5269 if (state
->sampler_states
[i
][WINED3DSAMP_MINFILTER
] != WINED3DTEXF_POINT
)
5271 WARN("Non-filterable texture and min filter enabled on samper %u, returning E_FAIL\n", i
);
5274 if (state
->sampler_states
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_NONE
5275 && state
->sampler_states
[i
][WINED3DSAMP_MIPFILTER
] != WINED3DTEXF_POINT
)
5277 WARN("Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL\n", i
);
5282 if (state
->render_states
[WINED3DRS_ZENABLE
] || state
->render_states
[WINED3DRS_ZWRITEENABLE
] ||
5283 state
->render_states
[WINED3DRS_STENCILENABLE
])
5285 struct wined3d_surface
*ds
= This
->depth_stencil
;
5286 struct wined3d_surface
*target
= This
->render_targets
[0];
5289 && (ds
->resource
.width
< target
->resource
.width
|| ds
->resource
.height
< target
->resource
.height
))
5291 WARN("Depth stencil is smaller than the color buffer, returning D3DERR_CONFLICTINGRENDERSTATE\n");
5292 return WINED3DERR_CONFLICTINGRENDERSTATE
;
5296 /* return a sensible default */
5299 TRACE("returning D3D_OK\n");
5303 static void dirtify_p8_texture_samplers(IWineD3DDeviceImpl
*device
)
5307 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
5309 struct wined3d_texture
*texture
= device
->stateBlock
->state
.textures
[i
];
5310 if (texture
&& (texture
->resource
.format
->id
== WINED3DFMT_P8_UINT
5311 || texture
->resource
.format
->id
== WINED3DFMT_P8_UINT_A8_UNORM
))
5313 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_SAMPLER(i
));
5318 static HRESULT WINAPI
IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice
*iface
,
5319 UINT PaletteNumber
, const PALETTEENTRY
*pEntries
)
5321 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5324 PALETTEENTRY
**palettes
;
5326 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5328 if (PaletteNumber
>= MAX_PALETTES
) {
5329 ERR("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This
, PaletteNumber
, MAX_PALETTES
);
5330 return WINED3DERR_INVALIDCALL
;
5333 if (PaletteNumber
>= This
->palette_count
)
5335 NewSize
= This
->palette_count
;
5338 } while(PaletteNumber
>= NewSize
);
5339 palettes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->palettes
, sizeof(PALETTEENTRY
*) * NewSize
);
5341 ERR("Out of memory!\n");
5342 return E_OUTOFMEMORY
;
5344 This
->palettes
= palettes
;
5345 This
->palette_count
= NewSize
;
5348 if (!This
->palettes
[PaletteNumber
]) {
5349 This
->palettes
[PaletteNumber
] = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY
) * 256);
5350 if (!This
->palettes
[PaletteNumber
]) {
5351 ERR("Out of memory!\n");
5352 return E_OUTOFMEMORY
;
5356 for (j
= 0; j
< 256; ++j
) {
5357 This
->palettes
[PaletteNumber
][j
].peRed
= pEntries
[j
].peRed
;
5358 This
->palettes
[PaletteNumber
][j
].peGreen
= pEntries
[j
].peGreen
;
5359 This
->palettes
[PaletteNumber
][j
].peBlue
= pEntries
[j
].peBlue
;
5360 This
->palettes
[PaletteNumber
][j
].peFlags
= pEntries
[j
].peFlags
;
5362 if (PaletteNumber
== This
->currentPalette
) dirtify_p8_texture_samplers(This
);
5363 TRACE("(%p) : returning\n", This
);
5367 static HRESULT WINAPI
IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice
*iface
,
5368 UINT PaletteNumber
, PALETTEENTRY
*pEntries
)
5370 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5372 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5374 if (PaletteNumber
>= This
->palette_count
|| !This
->palettes
[PaletteNumber
])
5376 /* What happens in such situation isn't documented; Native seems to silently abort
5377 on such conditions. Return Invalid Call. */
5378 ERR("(%p) : (%u) Nonexistent palette. Palette count %u.\n", This
, PaletteNumber
, This
->palette_count
);
5379 return WINED3DERR_INVALIDCALL
;
5381 for (j
= 0; j
< 256; ++j
) {
5382 pEntries
[j
].peRed
= This
->palettes
[PaletteNumber
][j
].peRed
;
5383 pEntries
[j
].peGreen
= This
->palettes
[PaletteNumber
][j
].peGreen
;
5384 pEntries
[j
].peBlue
= This
->palettes
[PaletteNumber
][j
].peBlue
;
5385 pEntries
[j
].peFlags
= This
->palettes
[PaletteNumber
][j
].peFlags
;
5387 TRACE("(%p) : returning\n", This
);
5391 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT PaletteNumber
)
5393 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5394 TRACE("(%p) : PaletteNumber %u\n", This
, PaletteNumber
);
5395 /* Native appears to silently abort on attempt to make an uninitialized palette current and render.
5396 (tested with reference rasterizer). Return Invalid Call. */
5397 if (PaletteNumber
>= This
->palette_count
|| !This
->palettes
[PaletteNumber
])
5399 ERR("(%p) : (%u) Nonexistent palette. Palette count %u.\n", This
, PaletteNumber
, This
->palette_count
);
5400 return WINED3DERR_INVALIDCALL
;
5402 /*TODO: stateblocks */
5403 if (This
->currentPalette
!= PaletteNumber
) {
5404 This
->currentPalette
= PaletteNumber
;
5405 dirtify_p8_texture_samplers(This
);
5407 TRACE("(%p) : returning\n", This
);
5411 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice
*iface
, UINT
* PaletteNumber
) {
5412 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5416 WARN("(%p) : returning Invalid Call\n", This
);
5417 return WINED3DERR_INVALIDCALL
;
5419 /*TODO: stateblocks */
5420 *PaletteNumber
= This
->currentPalette
;
5421 TRACE("(%p) : returning %u\n", This
, *PaletteNumber
);
5425 static HRESULT WINAPI
IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice
*iface
, BOOL bSoftware
) {
5426 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5430 FIXME("(%p) : stub\n", This
);
5434 This
->softwareVertexProcessing
= bSoftware
;
5439 static BOOL WINAPI
IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice
*iface
) {
5440 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5444 FIXME("(%p) : stub\n", This
);
5447 return This
->softwareVertexProcessing
;
5450 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice
*iface
,
5451 UINT swapchain_idx
, WINED3DRASTER_STATUS
*raster_status
)
5453 struct wined3d_swapchain
*swapchain
;
5456 TRACE("iface %p, swapchain_idx %u, raster_status %p.\n",
5457 iface
, swapchain_idx
, raster_status
);
5459 hr
= IWineD3DDeviceImpl_GetSwapChain(iface
, swapchain_idx
, &swapchain
);
5462 WARN("Failed to get swapchain %u, hr %#x.\n", swapchain_idx
, hr
);
5466 hr
= wined3d_swapchain_get_raster_status(swapchain
, raster_status
);
5467 wined3d_swapchain_decref(swapchain
);
5470 WARN("Failed to get raster status, hr %#x.\n", hr
);
5477 static HRESULT WINAPI
IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice
*iface
, float nSegments
)
5480 if(nSegments
!= 0.0f
) {
5483 FIXME("iface %p, nSegments %.8e stub!\n", iface
, nSegments
);
5490 static float WINAPI
IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice
*iface
)
5495 FIXME("iface %p stub!\n", iface
);
5501 static HRESULT WINAPI
IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
*iface
,
5502 struct wined3d_surface
*src_surface
, const RECT
*src_rect
,
5503 struct wined3d_surface
*dst_surface
, const POINT
*dst_point
)
5505 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5506 const struct wined3d_format
*src_format
;
5507 const struct wined3d_format
*dst_format
;
5508 const struct wined3d_gl_info
*gl_info
;
5509 struct wined3d_context
*context
;
5510 const unsigned char *data
;
5511 UINT update_w
, update_h
;
5512 CONVERT_TYPES convert
;
5516 struct wined3d_format format
;
5518 TRACE("iface %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n",
5519 iface
, src_surface
, wine_dbgstr_rect(src_rect
),
5520 dst_surface
, wine_dbgstr_point(dst_point
));
5522 if (src_surface
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
|| dst_surface
->resource
.pool
!= WINED3DPOOL_DEFAULT
)
5524 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n",
5525 src_surface
, dst_surface
);
5526 return WINED3DERR_INVALIDCALL
;
5529 src_format
= src_surface
->resource
.format
;
5530 dst_format
= dst_surface
->resource
.format
;
5532 if (src_format
->id
!= dst_format
->id
)
5534 WARN("Source and destination surfaces should have the same format.\n");
5535 return WINED3DERR_INVALIDCALL
;
5538 dst_x
= dst_point
? dst_point
->x
: 0;
5539 dst_y
= dst_point
? dst_point
->y
: 0;
5541 /* This call loads the OpenGL surface directly, instead of copying the
5542 * surface to the destination's sysmem copy. If surface conversion is
5543 * needed, use BltFast instead to copy in sysmem and use regular surface
5545 d3dfmt_get_conv(dst_surface
, FALSE
, TRUE
, &format
, &convert
);
5546 if (convert
!= NO_CONVERSION
|| format
.convert
)
5547 return wined3d_surface_bltfast(dst_surface
, dst_x
, dst_y
, src_surface
, src_rect
, 0);
5549 context
= context_acquire(This
, NULL
);
5550 gl_info
= context
->gl_info
;
5553 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
5554 checkGLcall("glActiveTextureARB");
5557 /* Make sure the surface is loaded and up to date */
5558 surface_internal_preload(dst_surface
, SRGB_RGB
);
5559 surface_bind(dst_surface
, gl_info
, FALSE
);
5561 src_w
= src_surface
->resource
.width
;
5562 src_h
= src_surface
->resource
.height
;
5563 update_w
= src_rect
? src_rect
->right
- src_rect
->left
: src_w
;
5564 update_h
= src_rect
? src_rect
->bottom
- src_rect
->top
: src_h
;
5566 data
= src_surface
->resource
.allocatedMemory
;
5567 if (!data
) ERR("Source surface has no allocated memory, but should be a sysmem surface.\n");
5571 if (dst_format
->flags
& WINED3DFMT_FLAG_COMPRESSED
)
5573 UINT row_length
= wined3d_format_calculate_size(src_format
, 1, update_w
, 1);
5574 UINT row_count
= (update_h
+ src_format
->block_height
- 1) / src_format
->block_height
;
5575 UINT src_pitch
= wined3d_format_calculate_size(src_format
, 1, src_w
, 1);
5579 data
+= (src_rect
->top
/ src_format
->block_height
) * src_pitch
;
5580 data
+= (src_rect
->left
/ src_format
->block_width
) * src_format
->block_byte_count
;
5583 TRACE("glCompressedTexSubImage2DARB, target %#x, level %d, x %d, y %d, w %d, h %d, "
5584 "format %#x, image_size %#x, data %p.\n", dst_surface
->texture_target
, dst_surface
->texture_level
,
5585 dst_x
, dst_y
, update_w
, update_h
, dst_format
->glFormat
, row_count
* row_length
, data
);
5587 if (row_length
== src_pitch
)
5589 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_surface
->texture_target
, dst_surface
->texture_level
,
5590 dst_x
, dst_y
, update_w
, update_h
, dst_format
->glInternal
, row_count
* row_length
, data
));
5596 /* glCompressedTexSubImage2DARB() ignores pixel store state, so we
5597 * can't use the unpack row length like below. */
5598 for (row
= 0, y
= dst_y
; row
< row_count
; ++row
)
5600 GL_EXTCALL(glCompressedTexSubImage2DARB(dst_surface
->texture_target
, dst_surface
->texture_level
,
5601 dst_x
, y
, update_w
, src_format
->block_height
, dst_format
->glInternal
, row_length
, data
));
5602 y
+= src_format
->block_height
;
5606 checkGLcall("glCompressedTexSubImage2DARB");
5612 data
+= src_rect
->top
* src_w
* src_format
->byte_count
;
5613 data
+= src_rect
->left
* src_format
->byte_count
;
5616 TRACE("glTexSubImage2D, target %#x, level %d, x %d, y %d, w %d, h %d, format %#x, type %#x, data %p.\n",
5617 dst_surface
->texture_target
, dst_surface
->texture_level
, dst_x
, dst_y
,
5618 update_w
, update_h
, dst_format
->glFormat
, dst_format
->glType
, data
);
5620 glPixelStorei(GL_UNPACK_ROW_LENGTH
, src_w
);
5621 glTexSubImage2D(dst_surface
->texture_target
, dst_surface
->texture_level
, dst_x
, dst_y
,
5622 update_w
, update_h
, dst_format
->glFormat
, dst_format
->glType
, data
);
5623 glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
5624 checkGLcall("glTexSubImage2D");
5628 context_release(context
);
5630 surface_modify_location(dst_surface
, SFLAG_INTEXTURE
, TRUE
);
5631 sampler
= This
->rev_tex_unit_map
[0];
5632 if (sampler
!= WINED3D_UNMAPPED_STAGE
)
5634 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
5640 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice
*iface
, UINT Handle
, CONST
float* pNumSegs
, CONST WINED3DRECTPATCH_INFO
* pRectPatchInfo
) {
5641 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5642 struct WineD3DRectPatch
*patch
;
5643 GLenum old_primitive_type
;
5647 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This
, Handle
, pNumSegs
, pRectPatchInfo
);
5649 if(!(Handle
|| pRectPatchInfo
)) {
5650 /* TODO: Write a test for the return value, thus the FIXME */
5651 FIXME("Both Handle and pRectPatchInfo are NULL\n");
5652 return WINED3DERR_INVALIDCALL
;
5656 i
= PATCHMAP_HASHFUNC(Handle
);
5658 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
5659 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
5660 if(patch
->Handle
== Handle
) {
5667 TRACE("Patch does not exist. Creating a new one\n");
5668 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5669 patch
->Handle
= Handle
;
5670 list_add_head(&This
->patches
[i
], &patch
->entry
);
5672 TRACE("Found existing patch %p\n", patch
);
5675 /* Since opengl does not load tesselated vertex attributes into numbered vertex
5676 * attributes we have to tesselate, read back, and draw. This needs a patch
5677 * management structure instance. Create one.
5679 * A possible improvement is to check if a vertex shader is used, and if not directly
5682 FIXME("Drawing an uncached patch. This is slow\n");
5683 patch
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*patch
));
5686 if (pNumSegs
[0] != patch
->numSegs
[0] || pNumSegs
[1] != patch
->numSegs
[1]
5687 || pNumSegs
[2] != patch
->numSegs
[2] || pNumSegs
[3] != patch
->numSegs
[3]
5688 || (pRectPatchInfo
&& memcmp(pRectPatchInfo
, &patch
->RectPatchInfo
, sizeof(*pRectPatchInfo
))))
5691 TRACE("Tesselation density or patch info changed, retesselating\n");
5693 if(pRectPatchInfo
) {
5694 patch
->RectPatchInfo
= *pRectPatchInfo
;
5696 patch
->numSegs
[0] = pNumSegs
[0];
5697 patch
->numSegs
[1] = pNumSegs
[1];
5698 patch
->numSegs
[2] = pNumSegs
[2];
5699 patch
->numSegs
[3] = pNumSegs
[3];
5701 hr
= tesselate_rectpatch(This
, patch
);
5703 WARN("Patch tesselation failed\n");
5705 /* Do not release the handle to store the params of the patch */
5707 HeapFree(GetProcessHeap(), 0, patch
);
5713 This
->currentPatch
= patch
;
5714 old_primitive_type
= This
->stateBlock
->state
.gl_primitive_type
;
5715 This
->stateBlock
->state
.gl_primitive_type
= GL_TRIANGLES
;
5716 IWineD3DDevice_DrawPrimitiveStrided(iface
, patch
->numSegs
[0] * patch
->numSegs
[1] * 2 * 3, &patch
->strided
);
5717 This
->stateBlock
->state
.gl_primitive_type
= old_primitive_type
;
5718 This
->currentPatch
= NULL
;
5720 /* Destroy uncached patches */
5722 HeapFree(GetProcessHeap(), 0, patch
->mem
);
5723 HeapFree(GetProcessHeap(), 0, patch
);
5728 static HRESULT WINAPI
IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice
*iface
,
5729 UINT handle
, const float *segment_count
, const WINED3DTRIPATCH_INFO
*patch_info
)
5731 FIXME("iface %p, handle %#x, segment_count %p, patch_info %p stub!\n",
5732 iface
, handle
, segment_count
, patch_info
);
5737 static HRESULT WINAPI
IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice
*iface
, UINT Handle
) {
5738 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5740 struct WineD3DRectPatch
*patch
;
5742 TRACE("(%p) Handle(%d)\n", This
, Handle
);
5744 i
= PATCHMAP_HASHFUNC(Handle
);
5745 LIST_FOR_EACH(e
, &This
->patches
[i
]) {
5746 patch
= LIST_ENTRY(e
, struct WineD3DRectPatch
, entry
);
5747 if(patch
->Handle
== Handle
) {
5748 TRACE("Deleting patch %p\n", patch
);
5749 list_remove(&patch
->entry
);
5750 HeapFree(GetProcessHeap(), 0, patch
->mem
);
5751 HeapFree(GetProcessHeap(), 0, patch
);
5756 /* TODO: Write a test for the return value */
5757 FIXME("Attempt to destroy nonexistent patch\n");
5758 return WINED3DERR_INVALIDCALL
;
5761 /* Do not call while under the GL lock. */
5762 static HRESULT WINAPI
IWineD3DDeviceImpl_ColorFill(IWineD3DDevice
*iface
,
5763 struct wined3d_surface
*surface
, const RECT
*rect
, const WINED3DCOLORVALUE
*color
)
5765 TRACE("iface %p, surface %p, rect %s, color {%.8e, %.8e, %.8e, %.8e}.\n",
5766 iface
, surface
, wine_dbgstr_rect(rect
),
5767 color
->r
, color
->g
, color
->b
, color
->a
);
5769 if (surface
->resource
.pool
!= WINED3DPOOL_DEFAULT
&& surface
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
)
5771 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5772 return WINED3DERR_INVALIDCALL
;
5775 return surface_color_fill(surface
, rect
, color
);
5778 /* Do not call while under the GL lock. */
5779 static void WINAPI
IWineD3DDeviceImpl_ClearRendertargetView(IWineD3DDevice
*iface
,
5780 struct wined3d_rendertarget_view
*rendertarget_view
, const WINED3DCOLORVALUE
*color
)
5782 struct wined3d_resource
*resource
;
5785 resource
= rendertarget_view
->resource
;
5786 if (resource
->resourceType
!= WINED3DRTYPE_SURFACE
)
5788 FIXME("Only supported on surface resources\n");
5792 hr
= surface_color_fill(surface_from_resource(resource
), NULL
, color
);
5793 if (FAILED(hr
)) ERR("Color fill failed, hr %#x.\n", hr
);
5796 /* rendertarget and depth stencil functions */
5797 static HRESULT WINAPI
IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice
*iface
,
5798 DWORD render_target_idx
, struct wined3d_surface
**render_target
)
5800 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
5802 TRACE("iface %p, render_target_idx %u, render_target %p.\n",
5803 iface
, render_target_idx
, render_target
);
5805 if (render_target_idx
>= device
->adapter
->gl_info
.limits
.buffers
)
5807 WARN("Only %u render targets are supported.\n", device
->adapter
->gl_info
.limits
.buffers
);
5808 return WINED3DERR_INVALIDCALL
;
5811 *render_target
= device
->render_targets
[render_target_idx
];
5813 wined3d_surface_incref(*render_target
);
5815 TRACE("Returning render target %p.\n", *render_target
);
5820 static HRESULT WINAPI
IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
*iface
,
5821 struct wined3d_surface
**depth_stencil
)
5823 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
5825 TRACE("iface %p, depth_stencil %p.\n", iface
, depth_stencil
);
5827 *depth_stencil
= device
->depth_stencil
;
5828 TRACE("Returning depth/stencil surface %p.\n", *depth_stencil
);
5829 if (!*depth_stencil
) return WINED3DERR_NOTFOUND
;
5830 wined3d_surface_incref(*depth_stencil
);
5835 static HRESULT WINAPI
IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice
*iface
,
5836 DWORD render_target_idx
, struct wined3d_surface
*render_target
, BOOL set_viewport
)
5838 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*)iface
;
5839 struct wined3d_surface
*prev
;
5841 TRACE("iface %p, render_target_idx %u, render_target %p, set_viewport %#x.\n",
5842 iface
, render_target_idx
, render_target
, set_viewport
);
5844 if (render_target_idx
>= device
->adapter
->gl_info
.limits
.buffers
)
5846 WARN("Only %u render targets are supported.\n", device
->adapter
->gl_info
.limits
.buffers
);
5847 return WINED3DERR_INVALIDCALL
;
5850 prev
= device
->render_targets
[render_target_idx
];
5851 if (render_target
== prev
)
5853 TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5857 /* Render target 0 can't be set to NULL. */
5858 if (!render_target
&& !render_target_idx
)
5860 WARN("Trying to set render target 0 to NULL.\n");
5861 return WINED3DERR_INVALIDCALL
;
5864 if (render_target
&& !(render_target
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
))
5866 FIXME("Surface %p doesn't have render target usage.\n", render_target
);
5867 return WINED3DERR_INVALIDCALL
;
5871 wined3d_surface_incref(render_target
);
5872 device
->render_targets
[render_target_idx
] = render_target
;
5873 /* Release after the assignment, to prevent device_resource_released()
5874 * from seeing the surface as still in use. */
5876 wined3d_surface_decref(prev
);
5878 /* Render target 0 is special. */
5879 if (!render_target_idx
&& set_viewport
)
5881 /* Set the viewport and scissor rectangles, if requested. Tests show
5882 * that stateblock recording is ignored, the change goes directly
5883 * into the primary stateblock. */
5884 device
->stateBlock
->state
.viewport
.Height
= device
->render_targets
[0]->resource
.height
;
5885 device
->stateBlock
->state
.viewport
.Width
= device
->render_targets
[0]->resource
.width
;
5886 device
->stateBlock
->state
.viewport
.X
= 0;
5887 device
->stateBlock
->state
.viewport
.Y
= 0;
5888 device
->stateBlock
->state
.viewport
.MaxZ
= 1.0f
;
5889 device
->stateBlock
->state
.viewport
.MinZ
= 0.0f
;
5890 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_VIEWPORT
);
5892 device
->stateBlock
->state
.scissor_rect
.top
= 0;
5893 device
->stateBlock
->state
.scissor_rect
.left
= 0;
5894 device
->stateBlock
->state
.scissor_rect
.right
= device
->stateBlock
->state
.viewport
.Width
;
5895 device
->stateBlock
->state
.scissor_rect
.bottom
= device
->stateBlock
->state
.viewport
.Height
;
5896 IWineD3DDeviceImpl_MarkStateDirty(device
, STATE_SCISSORRECT
);
5902 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice
*iface
,
5903 struct wined3d_surface
*depth_stencil
)
5905 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5906 struct wined3d_surface
*tmp
;
5908 TRACE("device %p, depth_stencil %p, old depth_stencil %p.\n", This
, depth_stencil
, This
->depth_stencil
);
5910 if (This
->depth_stencil
== depth_stencil
)
5912 TRACE("Trying to do a NOP SetRenderTarget operation.\n");
5916 if (This
->depth_stencil
)
5918 if (This
->swapchains
[0]->presentParms
.Flags
& WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
5919 || This
->depth_stencil
->flags
& SFLAG_DISCARD
)
5921 surface_modify_ds_location(This
->depth_stencil
, SFLAG_DS_DISCARDED
,
5922 This
->depth_stencil
->resource
.width
,
5923 This
->depth_stencil
->resource
.height
);
5924 if (This
->depth_stencil
== This
->onscreen_depth_stencil
)
5926 wined3d_surface_decref(This
->onscreen_depth_stencil
);
5927 This
->onscreen_depth_stencil
= NULL
;
5932 tmp
= This
->depth_stencil
;
5933 This
->depth_stencil
= depth_stencil
;
5934 if (This
->depth_stencil
)
5935 wined3d_surface_incref(This
->depth_stencil
);
5937 wined3d_surface_decref(tmp
);
5939 if ((!tmp
&& depth_stencil
) || (!depth_stencil
&& tmp
))
5941 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5942 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_ZENABLE
));
5943 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILENABLE
));
5944 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_STENCILWRITEMASK
));
5945 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_DEPTHBIAS
));
5947 else if (tmp
&& tmp
->resource
.format
->depth_size
!= This
->depth_stencil
->resource
.format
->depth_size
)
5949 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_RENDER(WINED3DRS_DEPTHBIAS
));
5955 static HRESULT WINAPI
IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice
*iface
,
5956 UINT XHotSpot
, UINT YHotSpot
, struct wined3d_surface
*cursor_image
)
5958 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
5959 WINED3DLOCKED_RECT lockedRect
;
5961 TRACE("iface %p, hotspot_x %u, hotspot_y %u, cursor_image %p.\n",
5962 iface
, XHotSpot
, YHotSpot
, cursor_image
);
5964 /* some basic validation checks */
5965 if (This
->cursorTexture
)
5967 struct wined3d_context
*context
= context_acquire(This
, NULL
);
5969 glDeleteTextures(1, &This
->cursorTexture
);
5971 context_release(context
);
5972 This
->cursorTexture
= 0;
5975 if (cursor_image
->resource
.width
== 32 && cursor_image
->resource
.height
== 32)
5976 This
->haveHardwareCursor
= TRUE
;
5978 This
->haveHardwareCursor
= FALSE
;
5982 WINED3DLOCKED_RECT rect
;
5984 /* MSDN: Cursor must be A8R8G8B8 */
5985 if (cursor_image
->resource
.format
->id
!= WINED3DFMT_B8G8R8A8_UNORM
)
5987 WARN("surface %p has an invalid format.\n", cursor_image
);
5988 return WINED3DERR_INVALIDCALL
;
5991 /* MSDN: Cursor must be smaller than the display mode */
5992 if (cursor_image
->resource
.width
> This
->ddraw_width
5993 || cursor_image
->resource
.height
> This
->ddraw_height
)
5995 WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n",
5996 cursor_image
, cursor_image
->resource
.width
, cursor_image
->resource
.height
,
5997 This
->ddraw_width
, This
->ddraw_height
);
5998 return WINED3DERR_INVALIDCALL
;
6001 if (!This
->haveHardwareCursor
) {
6002 /* TODO: MSDN: Cursor sizes must be a power of 2 */
6004 /* Do not store the surface's pointer because the application may
6005 * release it after setting the cursor image. Windows doesn't
6006 * addref the set surface, so we can't do this either without
6007 * creating circular refcount dependencies. Copy out the gl texture
6009 This
->cursorWidth
= cursor_image
->resource
.width
;
6010 This
->cursorHeight
= cursor_image
->resource
.height
;
6011 if (SUCCEEDED(wined3d_surface_map(cursor_image
, &rect
, NULL
, WINED3DLOCK_READONLY
)))
6013 const struct wined3d_gl_info
*gl_info
= &This
->adapter
->gl_info
;
6014 const struct wined3d_format
*format
= wined3d_get_format(gl_info
, WINED3DFMT_B8G8R8A8_UNORM
);
6015 struct wined3d_context
*context
;
6016 char *mem
, *bits
= rect
.pBits
;
6017 GLint intfmt
= format
->glInternal
;
6018 GLint gl_format
= format
->glFormat
;
6019 GLint type
= format
->glType
;
6020 INT height
= This
->cursorHeight
;
6021 INT width
= This
->cursorWidth
;
6022 INT bpp
= format
->byte_count
;
6026 /* Reformat the texture memory (pitch and width can be
6028 mem
= HeapAlloc(GetProcessHeap(), 0, width
* height
* bpp
);
6029 for(i
= 0; i
< height
; i
++)
6030 memcpy(&mem
[width
* bpp
* i
], &bits
[rect
.Pitch
* i
], width
* bpp
);
6031 wined3d_surface_unmap(cursor_image
);
6033 context
= context_acquire(This
, NULL
);
6037 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
6039 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_FALSE
);
6040 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
6043 /* Make sure that a proper texture unit is selected */
6044 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
6045 checkGLcall("glActiveTextureARB");
6046 sampler
= This
->rev_tex_unit_map
[0];
6047 if (sampler
!= WINED3D_UNMAPPED_STAGE
)
6049 IWineD3DDeviceImpl_MarkStateDirty(This
, STATE_SAMPLER(sampler
));
6051 /* Create a new cursor texture */
6052 glGenTextures(1, &This
->cursorTexture
);
6053 checkGLcall("glGenTextures");
6054 glBindTexture(GL_TEXTURE_2D
, This
->cursorTexture
);
6055 checkGLcall("glBindTexture");
6056 /* Copy the bitmap memory into the cursor texture */
6057 glTexImage2D(GL_TEXTURE_2D
, 0, intfmt
, width
, height
, 0, gl_format
, type
, mem
);
6058 checkGLcall("glTexImage2D");
6059 HeapFree(GetProcessHeap(), 0, mem
);
6061 if (gl_info
->supported
[APPLE_CLIENT_STORAGE
])
6063 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE
, GL_TRUE
);
6064 checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
6069 context_release(context
);
6073 FIXME("A cursor texture was not returned.\n");
6074 This
->cursorTexture
= 0;
6079 /* Draw a hardware cursor */
6080 ICONINFO cursorInfo
;
6082 /* Create and clear maskBits because it is not needed for
6083 * 32-bit cursors. 32x32 bits split into 32-bit chunks == 32
6085 DWORD
*maskBits
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6086 (cursor_image
->resource
.width
* cursor_image
->resource
.height
/ 8));
6087 wined3d_surface_map(cursor_image
, &lockedRect
, NULL
,
6088 WINED3DLOCK_NO_DIRTY_UPDATE
| WINED3DLOCK_READONLY
);
6089 TRACE("width: %u height: %u.\n", cursor_image
->resource
.width
, cursor_image
->resource
.height
);
6091 cursorInfo
.fIcon
= FALSE
;
6092 cursorInfo
.xHotspot
= XHotSpot
;
6093 cursorInfo
.yHotspot
= YHotSpot
;
6094 cursorInfo
.hbmMask
= CreateBitmap(cursor_image
->resource
.width
, cursor_image
->resource
.height
,
6096 cursorInfo
.hbmColor
= CreateBitmap(cursor_image
->resource
.width
, cursor_image
->resource
.height
,
6097 1, 32, lockedRect
.pBits
);
6098 wined3d_surface_unmap(cursor_image
);
6099 /* Create our cursor and clean up. */
6100 cursor
= CreateIconIndirect(&cursorInfo
);
6102 if (cursorInfo
.hbmMask
) DeleteObject(cursorInfo
.hbmMask
);
6103 if (cursorInfo
.hbmColor
) DeleteObject(cursorInfo
.hbmColor
);
6104 if (This
->hardwareCursor
) DestroyCursor(This
->hardwareCursor
);
6105 This
->hardwareCursor
= cursor
;
6106 HeapFree(GetProcessHeap(), 0, maskBits
);
6110 This
->xHotSpot
= XHotSpot
;
6111 This
->yHotSpot
= YHotSpot
;
6115 static void WINAPI
IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice
*iface
,
6116 int XScreenSpace
, int YScreenSpace
, DWORD flags
)
6118 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6120 TRACE("iface %p, x %d, y %d, flags %#x.\n",
6121 iface
, XScreenSpace
, YScreenSpace
, flags
);
6123 This
->xScreenSpace
= XScreenSpace
;
6124 This
->yScreenSpace
= YScreenSpace
;
6127 static BOOL WINAPI
IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice
* iface
, BOOL bShow
) {
6128 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6129 BOOL oldVisible
= This
->bCursorVisible
;
6132 TRACE("(%p) : visible(%d)\n", This
, bShow
);
6135 * When ShowCursor is first called it should make the cursor appear at the OS's last
6136 * known cursor position. Because of this, some applications just repetitively call
6137 * ShowCursor in order to update the cursor's position. This behavior is undocumented.
6140 This
->xScreenSpace
= pt
.x
;
6141 This
->yScreenSpace
= pt
.y
;
6143 if (This
->haveHardwareCursor
) {
6144 This
->bCursorVisible
= bShow
;
6146 SetCursor(This
->hardwareCursor
);
6152 if (This
->cursorTexture
)
6153 This
->bCursorVisible
= bShow
;
6159 static HRESULT WINAPI
evict_managed_resource(struct wined3d_resource
*resource
, void *data
)
6161 TRACE("checking resource %p for eviction\n", resource
);
6163 if (resource
->pool
== WINED3DPOOL_MANAGED
)
6165 TRACE("Evicting %p.\n", resource
);
6166 resource
->resource_ops
->resource_unload(resource
);
6172 static HRESULT WINAPI
IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice
*iface
)
6174 TRACE("iface %p.\n", iface
);
6176 IWineD3DDevice_EnumResources(iface
, evict_managed_resource
, NULL
);
6177 /* Invalidate stream sources, the buffer(s) may have been evicted. */
6178 IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl
*)iface
, STATE_STREAMSRC
);
6183 static HRESULT
updateSurfaceDesc(struct wined3d_surface
*surface
,
6184 const WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
6186 IWineD3DDeviceImpl
*device
= surface
->resource
.device
;
6187 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
6189 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6190 if (surface
->flags
& SFLAG_DIBSECTION
)
6192 /* Release the DC */
6193 SelectObject(surface
->hDC
, surface
->dib
.holdbitmap
);
6194 DeleteDC(surface
->hDC
);
6195 /* Release the DIB section */
6196 DeleteObject(surface
->dib
.DIBsection
);
6197 surface
->dib
.bitmap_data
= NULL
;
6198 surface
->resource
.allocatedMemory
= NULL
;
6199 surface
->flags
&= ~SFLAG_DIBSECTION
;
6201 surface
->resource
.width
= pPresentationParameters
->BackBufferWidth
;
6202 surface
->resource
.height
= pPresentationParameters
->BackBufferHeight
;
6203 if (gl_info
->supported
[ARB_TEXTURE_NON_POWER_OF_TWO
] || gl_info
->supported
[ARB_TEXTURE_RECTANGLE
]
6204 || gl_info
->supported
[WINED3D_GL_NORMALIZED_TEXRECT
])
6206 surface
->pow2Width
= pPresentationParameters
->BackBufferWidth
;
6207 surface
->pow2Height
= pPresentationParameters
->BackBufferHeight
;
6209 surface
->pow2Width
= surface
->pow2Height
= 1;
6210 while (surface
->pow2Width
< pPresentationParameters
->BackBufferWidth
) surface
->pow2Width
<<= 1;
6211 while (surface
->pow2Height
< pPresentationParameters
->BackBufferHeight
) surface
->pow2Height
<<= 1;
6214 if (surface
->texture_name
)
6216 struct wined3d_context
*context
= context_acquire(device
, NULL
);
6218 glDeleteTextures(1, &surface
->texture_name
);
6220 context_release(context
);
6221 surface
->texture_name
= 0;
6222 surface
->flags
&= ~SFLAG_CLIENT
;
6224 if (surface
->pow2Width
!= pPresentationParameters
->BackBufferWidth
6225 || surface
->pow2Height
!= pPresentationParameters
->BackBufferHeight
)
6227 surface
->flags
|= SFLAG_NONPOW2
;
6231 surface
->flags
&= ~SFLAG_NONPOW2
;
6233 HeapFree(GetProcessHeap(), 0, surface
->resource
.heapMemory
);
6234 surface
->resource
.allocatedMemory
= NULL
;
6235 surface
->resource
.heapMemory
= NULL
;
6236 surface
->resource
.size
= wined3d_surface_get_pitch(surface
) * surface
->pow2Width
;
6238 /* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
6240 if (!surface_init_sysmem(surface
))
6242 return E_OUTOFMEMORY
;
6247 static BOOL
is_display_mode_supported(IWineD3DDeviceImpl
*This
, const WINED3DPRESENT_PARAMETERS
*pp
)
6250 WINED3DDISPLAYMODE m
;
6253 /* All Windowed modes are supported, as is leaving the current mode */
6254 if(pp
->Windowed
) return TRUE
;
6255 if(!pp
->BackBufferWidth
) return TRUE
;
6256 if(!pp
->BackBufferHeight
) return TRUE
;
6258 count
= wined3d_get_adapter_mode_count(This
->wined3d
, This
->adapter
->ordinal
, WINED3DFMT_UNKNOWN
);
6259 for (i
= 0; i
< count
; ++i
)
6261 memset(&m
, 0, sizeof(m
));
6262 hr
= wined3d_enum_adapter_modes(This
->wined3d
, This
->adapter
->ordinal
, WINED3DFMT_UNKNOWN
, i
, &m
);
6264 ERR("Failed to enumerate adapter mode.\n");
6265 if (m
.Width
== pp
->BackBufferWidth
&& m
.Height
== pp
->BackBufferHeight
)
6266 /* Mode found, it is supported. */
6269 /* Mode not found -> not supported */
6273 /* Do not call while under the GL lock. */
6274 static void delete_opengl_contexts(IWineD3DDeviceImpl
*device
, struct wined3d_swapchain
*swapchain
)
6276 const struct wined3d_gl_info
*gl_info
;
6277 struct wined3d_context
*context
;
6278 struct wined3d_shader
*shader
;
6280 context
= context_acquire(device
, NULL
);
6281 gl_info
= context
->gl_info
;
6283 IWineD3DDevice_EnumResources((IWineD3DDevice
*)device
, device_unload_resource
, NULL
);
6284 LIST_FOR_EACH_ENTRY(shader
, &device
->shaders
, struct wined3d_shader
, shader_list_entry
)
6286 device
->shader_backend
->shader_destroy(shader
);
6290 if (device
->depth_blt_texture
)
6292 glDeleteTextures(1, &device
->depth_blt_texture
);
6293 device
->depth_blt_texture
= 0;
6295 if (device
->depth_blt_rb
)
6297 gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &device
->depth_blt_rb
);
6298 device
->depth_blt_rb
= 0;
6299 device
->depth_blt_rb_w
= 0;
6300 device
->depth_blt_rb_h
= 0;
6304 device
->blitter
->free_private(device
);
6305 device
->frag_pipe
->free_private(device
);
6306 device
->shader_backend
->shader_free_private(device
);
6307 destroy_dummy_textures(device
, gl_info
);
6309 context_release(context
);
6311 while (device
->context_count
)
6313 context_destroy(device
, device
->contexts
[0]);
6315 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6316 swapchain
->context
= NULL
;
6317 swapchain
->num_contexts
= 0;
6320 /* Do not call while under the GL lock. */
6321 static HRESULT
create_primary_opengl_context(IWineD3DDeviceImpl
*device
, struct wined3d_swapchain
*swapchain
)
6323 struct wined3d_context
*context
;
6324 struct wined3d_surface
*target
;
6327 /* Recreate the primary swapchain's context */
6328 swapchain
->context
= HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain
->context
));
6329 if (!swapchain
->context
)
6331 ERR("Failed to allocate memory for swapchain context array.\n");
6332 return E_OUTOFMEMORY
;
6335 target
= swapchain
->back_buffers
? swapchain
->back_buffers
[0] : swapchain
->front_buffer
;
6336 if (!(context
= context_create(swapchain
, target
, swapchain
->ds_format
)))
6338 WARN("Failed to create context.\n");
6339 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6343 swapchain
->context
[0] = context
;
6344 swapchain
->num_contexts
= 1;
6345 create_dummy_textures(device
);
6346 context_release(context
);
6348 hr
= device
->shader_backend
->shader_alloc_private(device
);
6351 ERR("Failed to allocate shader private data, hr %#x.\n", hr
);
6355 hr
= device
->frag_pipe
->alloc_private(device
);
6358 ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr
);
6359 device
->shader_backend
->shader_free_private(device
);
6363 hr
= device
->blitter
->alloc_private(device
);
6366 ERR("Failed to allocate blitter private data, hr %#x.\n", hr
);
6367 device
->frag_pipe
->free_private(device
);
6368 device
->shader_backend
->shader_free_private(device
);
6375 context_acquire(device
, NULL
);
6376 destroy_dummy_textures(device
, context
->gl_info
);
6377 context_release(context
);
6378 context_destroy(device
, context
);
6379 HeapFree(GetProcessHeap(), 0, swapchain
->context
);
6380 swapchain
->num_contexts
= 0;
6384 /* Do not call while under the GL lock. */
6385 static HRESULT WINAPI
IWineD3DDeviceImpl_Reset(IWineD3DDevice
*iface
,
6386 WINED3DPRESENT_PARAMETERS
*pPresentationParameters
)
6388 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6389 struct wined3d_swapchain
*swapchain
;
6391 BOOL DisplayModeChanged
= FALSE
;
6392 WINED3DDISPLAYMODE mode
;
6393 TRACE("(%p)\n", This
);
6395 hr
= IWineD3DDevice_GetSwapChain(iface
, 0, &swapchain
);
6398 ERR("Failed to get the first implicit swapchain\n");
6402 if(!is_display_mode_supported(This
, pPresentationParameters
)) {
6403 WARN("Rejecting Reset() call because the requested display mode is not supported\n");
6404 WARN("Requested mode: %d, %d\n", pPresentationParameters
->BackBufferWidth
,
6405 pPresentationParameters
->BackBufferHeight
);
6406 wined3d_swapchain_decref(swapchain
);
6407 return WINED3DERR_INVALIDCALL
;
6410 /* Is it necessary to recreate the gl context? Actually every setting can be changed
6411 * on an existing gl context, so there's no real need for recreation.
6413 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6415 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6417 TRACE("New params:\n");
6418 TRACE("BackBufferWidth = %d\n", pPresentationParameters
->BackBufferWidth
);
6419 TRACE("BackBufferHeight = %d\n", pPresentationParameters
->BackBufferHeight
);
6420 TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters
->BackBufferFormat
));
6421 TRACE("BackBufferCount = %d\n", pPresentationParameters
->BackBufferCount
);
6422 TRACE("MultiSampleType = %d\n", pPresentationParameters
->MultiSampleType
);
6423 TRACE("MultiSampleQuality = %d\n", pPresentationParameters
->MultiSampleQuality
);
6424 TRACE("SwapEffect = %d\n", pPresentationParameters
->SwapEffect
);
6425 TRACE("hDeviceWindow = %p\n", pPresentationParameters
->hDeviceWindow
);
6426 TRACE("Windowed = %s\n", pPresentationParameters
->Windowed
? "true" : "false");
6427 TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters
->EnableAutoDepthStencil
? "true" : "false");
6428 TRACE("Flags = %08x\n", pPresentationParameters
->Flags
);
6429 TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters
->FullScreen_RefreshRateInHz
);
6430 TRACE("PresentationInterval = %d\n", pPresentationParameters
->PresentationInterval
);
6432 /* No special treatment of these parameters. Just store them */
6433 swapchain
->presentParms
.SwapEffect
= pPresentationParameters
->SwapEffect
;
6434 swapchain
->presentParms
.Flags
= pPresentationParameters
->Flags
;
6435 swapchain
->presentParms
.PresentationInterval
= pPresentationParameters
->PresentationInterval
;
6436 swapchain
->presentParms
.FullScreen_RefreshRateInHz
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
6438 /* What to do about these? */
6439 if (pPresentationParameters
->BackBufferCount
6440 && pPresentationParameters
->BackBufferCount
!= swapchain
->presentParms
.BackBufferCount
)
6441 ERR("Cannot change the back buffer count yet\n");
6443 if(pPresentationParameters
->BackBufferFormat
!= WINED3DFMT_UNKNOWN
&&
6444 pPresentationParameters
->BackBufferFormat
!= swapchain
->presentParms
.BackBufferFormat
) {
6445 ERR("Cannot change the back buffer format yet\n");
6448 if (pPresentationParameters
->hDeviceWindow
6449 && pPresentationParameters
->hDeviceWindow
!= swapchain
->presentParms
.hDeviceWindow
)
6450 ERR("Cannot change the device window yet\n");
6452 if (pPresentationParameters
->EnableAutoDepthStencil
&& !This
->auto_depth_stencil
)
6456 TRACE("Creating the depth stencil buffer\n");
6458 hrc
= IWineD3DDeviceParent_CreateDepthStencilSurface(This
->device_parent
,
6459 pPresentationParameters
->BackBufferWidth
,
6460 pPresentationParameters
->BackBufferHeight
,
6461 pPresentationParameters
->AutoDepthStencilFormat
,
6462 pPresentationParameters
->MultiSampleType
,
6463 pPresentationParameters
->MultiSampleQuality
,
6465 &This
->auto_depth_stencil
);
6468 ERR("Failed to create the depth stencil buffer.\n");
6469 wined3d_swapchain_decref(swapchain
);
6470 return WINED3DERR_INVALIDCALL
;
6474 if (This
->onscreen_depth_stencil
)
6476 wined3d_surface_decref(This
->onscreen_depth_stencil
);
6477 This
->onscreen_depth_stencil
= NULL
;
6480 /* Reset the depth stencil */
6481 if (pPresentationParameters
->EnableAutoDepthStencil
)
6482 IWineD3DDevice_SetDepthStencilSurface(iface
, This
->auto_depth_stencil
);
6484 IWineD3DDevice_SetDepthStencilSurface(iface
, NULL
);
6486 TRACE("Resetting stateblock\n");
6487 wined3d_stateblock_decref(This
->updateStateBlock
);
6488 wined3d_stateblock_decref(This
->stateBlock
);
6490 delete_opengl_contexts(This
, swapchain
);
6492 if(pPresentationParameters
->Windowed
) {
6493 mode
.Width
= swapchain
->orig_width
;
6494 mode
.Height
= swapchain
->orig_height
;
6495 mode
.RefreshRate
= 0;
6496 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
6498 mode
.Width
= pPresentationParameters
->BackBufferWidth
;
6499 mode
.Height
= pPresentationParameters
->BackBufferHeight
;
6500 mode
.RefreshRate
= pPresentationParameters
->FullScreen_RefreshRateInHz
;
6501 mode
.Format
= swapchain
->presentParms
.BackBufferFormat
;
6504 /* Should Width == 800 && Height == 0 set 800x600? */
6505 if (pPresentationParameters
->BackBufferWidth
&& pPresentationParameters
->BackBufferHeight
6506 && (pPresentationParameters
->BackBufferWidth
!= swapchain
->presentParms
.BackBufferWidth
6507 || pPresentationParameters
->BackBufferHeight
!= swapchain
->presentParms
.BackBufferHeight
))
6511 if(!pPresentationParameters
->Windowed
) {
6512 DisplayModeChanged
= TRUE
;
6514 swapchain
->presentParms
.BackBufferWidth
= pPresentationParameters
->BackBufferWidth
;
6515 swapchain
->presentParms
.BackBufferHeight
= pPresentationParameters
->BackBufferHeight
;
6517 hr
= updateSurfaceDesc(swapchain
->front_buffer
, pPresentationParameters
);
6520 wined3d_swapchain_decref(swapchain
);
6524 for (i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; ++i
)
6526 hr
= updateSurfaceDesc(swapchain
->back_buffers
[i
], pPresentationParameters
);
6529 wined3d_swapchain_decref(swapchain
);
6533 if (This
->auto_depth_stencil
)
6535 hr
= updateSurfaceDesc(This
->auto_depth_stencil
, pPresentationParameters
);
6538 wined3d_swapchain_decref(swapchain
);
6544 if (!pPresentationParameters
->Windowed
!= !swapchain
->presentParms
.Windowed
6545 || DisplayModeChanged
)
6547 IWineD3DDevice_SetDisplayMode(iface
, 0, &mode
);
6549 if (!pPresentationParameters
->Windowed
)
6551 if (swapchain
->presentParms
.Windowed
)
6553 HWND focus_window
= This
->createParms
.hFocusWindow
;
6554 if (!focus_window
) focus_window
= pPresentationParameters
->hDeviceWindow
;
6555 if (FAILED(hr
= IWineD3DDevice_AcquireFocusWindow(iface
, focus_window
)))
6557 ERR("Failed to acquire focus window, hr %#x.\n", hr
);
6558 wined3d_swapchain_decref(swapchain
);
6562 /* switch from windowed to fs */
6563 IWineD3DDevice_SetupFullscreenWindow(iface
, swapchain
->device_window
,
6564 pPresentationParameters
->BackBufferWidth
,
6565 pPresentationParameters
->BackBufferHeight
);
6569 /* Fullscreen -> fullscreen mode change */
6570 MoveWindow(swapchain
->device_window
, 0, 0,
6571 pPresentationParameters
->BackBufferWidth
, pPresentationParameters
->BackBufferHeight
,
6575 else if (!swapchain
->presentParms
.Windowed
)
6577 /* Fullscreen -> windowed switch */
6578 IWineD3DDevice_RestoreFullscreenWindow(iface
, swapchain
->device_window
);
6579 IWineD3DDevice_ReleaseFocusWindow(iface
);
6581 swapchain
->presentParms
.Windowed
= pPresentationParameters
->Windowed
;
6583 else if (!pPresentationParameters
->Windowed
)
6585 DWORD style
= This
->style
, exStyle
= This
->exStyle
;
6586 /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
6587 * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call
6588 * Reset to clear up their mess. Guild Wars also loses the device during that.
6592 IWineD3DDevice_SetupFullscreenWindow(iface
, swapchain
->device_window
,
6593 pPresentationParameters
->BackBufferWidth
,
6594 pPresentationParameters
->BackBufferHeight
);
6595 This
->style
= style
;
6596 This
->exStyle
= exStyle
;
6599 /* Note: No parent needed for initial internal stateblock */
6600 hr
= IWineD3DDevice_CreateStateBlock(iface
, WINED3DSBT_INIT
, &This
->stateBlock
);
6601 if (FAILED(hr
)) ERR("Resetting the stateblock failed with error 0x%08x\n", hr
);
6602 else TRACE("Created stateblock %p\n", This
->stateBlock
);
6603 This
->updateStateBlock
= This
->stateBlock
;
6604 wined3d_stateblock_incref(This
->updateStateBlock
);
6606 stateblock_init_default_state(This
->stateBlock
);
6608 if(wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
)
6611 GetClientRect(swapchain
->win_handle
, &client_rect
);
6613 if(!swapchain
->presentParms
.BackBufferCount
)
6615 TRACE("Single buffered rendering\n");
6616 swapchain
->render_to_fbo
= FALSE
;
6618 else if(swapchain
->presentParms
.BackBufferWidth
!= client_rect
.right
||
6619 swapchain
->presentParms
.BackBufferHeight
!= client_rect
.bottom
)
6621 TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
6622 swapchain
->presentParms
.BackBufferWidth
,
6623 swapchain
->presentParms
.BackBufferHeight
,
6624 client_rect
.right
, client_rect
.bottom
);
6625 swapchain
->render_to_fbo
= TRUE
;
6629 TRACE("Rendering directly to GL_BACK\n");
6630 swapchain
->render_to_fbo
= FALSE
;
6634 hr
= create_primary_opengl_context(This
, swapchain
);
6635 wined3d_swapchain_decref(swapchain
);
6637 /* All done. There is no need to reload resources or shaders, this will happen automatically on the
6643 static HRESULT WINAPI
IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice
*iface
, BOOL enable_dialogs
)
6645 TRACE("iface %p, enable_dialogs %#x.\n", iface
, enable_dialogs
);
6647 if (!enable_dialogs
) FIXME("Dialogs cannot be disabled yet.\n");
6653 static HRESULT WINAPI
IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice
*iface
, WINED3DDEVICE_CREATION_PARAMETERS
*pParameters
) {
6654 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6655 TRACE("(%p) : pParameters %p\n", This
, pParameters
);
6657 *pParameters
= This
->createParms
;
6661 static void WINAPI
IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice
*iface
,
6662 UINT iSwapChain
, DWORD flags
, const WINED3DGAMMARAMP
*pRamp
)
6664 struct wined3d_swapchain
*swapchain
;
6666 TRACE("Relaying to swapchain\n");
6668 if (SUCCEEDED(IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)))
6670 wined3d_swapchain_set_gamma_ramp(swapchain
, flags
, pRamp
);
6671 wined3d_swapchain_decref(swapchain
);
6675 static void WINAPI
IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice
*iface
, UINT iSwapChain
, WINED3DGAMMARAMP
* pRamp
)
6677 struct wined3d_swapchain
*swapchain
;
6679 TRACE("Relaying to swapchain\n");
6681 if (SUCCEEDED(IWineD3DDeviceImpl_GetSwapChain(iface
, iSwapChain
, &swapchain
)))
6683 wined3d_swapchain_get_gamma_ramp(swapchain
, pRamp
);
6684 wined3d_swapchain_decref(swapchain
);
6688 void device_resource_add(struct IWineD3DDeviceImpl
*device
, struct wined3d_resource
*resource
)
6690 TRACE("device %p, resource %p.\n", device
, resource
);
6692 list_add_head(&device
->resources
, &resource
->resource_list_entry
);
6695 static void device_resource_remove(struct IWineD3DDeviceImpl
*device
, struct wined3d_resource
*resource
)
6697 TRACE("device %p, resource %p.\n", device
, resource
);
6699 list_remove(&resource
->resource_list_entry
);
6702 void device_resource_released(struct IWineD3DDeviceImpl
*device
, struct wined3d_resource
*resource
)
6704 WINED3DRESOURCETYPE type
= resource
->resourceType
;
6707 TRACE("device %p, resource %p, type %s.\n", device
, resource
, debug_d3dresourcetype(type
));
6709 context_resource_released(device
, resource
, type
);
6713 case WINED3DRTYPE_SURFACE
:
6715 struct wined3d_surface
*surface
= surface_from_resource(resource
);
6717 if (!device
->d3d_initialized
) break;
6719 for (i
= 0; i
< device
->adapter
->gl_info
.limits
.buffers
; ++i
)
6721 if (device
->render_targets
[i
] == surface
)
6723 ERR("Surface %p is still in use as render target %u.\n", surface
, i
);
6724 device
->render_targets
[i
] = NULL
;
6728 if (device
->depth_stencil
== surface
)
6730 ERR("Surface %p is still in use as depth/stencil buffer.\n", surface
);
6731 device
->depth_stencil
= NULL
;
6736 case WINED3DRTYPE_TEXTURE
:
6737 case WINED3DRTYPE_CUBETEXTURE
:
6738 case WINED3DRTYPE_VOLUMETEXTURE
:
6739 for (i
= 0; i
< MAX_COMBINED_SAMPLERS
; ++i
)
6741 struct wined3d_texture
*texture
= wined3d_texture_from_resource(resource
);
6743 if (device
->stateBlock
&& device
->stateBlock
->state
.textures
[i
] == texture
)
6745 ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6746 texture
, device
->stateBlock
, i
);
6747 device
->stateBlock
->state
.textures
[i
] = NULL
;
6750 if (device
->updateStateBlock
!= device
->stateBlock
6751 && device
->updateStateBlock
->state
.textures
[i
] == texture
)
6753 ERR("Texture %p is still in use by stateblock %p, stage %u.\n",
6754 texture
, device
->updateStateBlock
, i
);
6755 device
->updateStateBlock
->state
.textures
[i
] = NULL
;
6760 case WINED3DRTYPE_BUFFER
:
6762 struct wined3d_buffer
*buffer
= buffer_from_resource(resource
);
6764 for (i
= 0; i
< MAX_STREAMS
; ++i
)
6766 if (device
->stateBlock
&& device
->stateBlock
->state
.streams
[i
].buffer
== buffer
)
6768 ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6769 buffer
, device
->stateBlock
, i
);
6770 device
->stateBlock
->state
.streams
[i
].buffer
= NULL
;
6773 if (device
->updateStateBlock
!= device
->stateBlock
6774 && device
->updateStateBlock
->state
.streams
[i
].buffer
== buffer
)
6776 ERR("Buffer %p is still in use by stateblock %p, stream %u.\n",
6777 buffer
, device
->updateStateBlock
, i
);
6778 device
->updateStateBlock
->state
.streams
[i
].buffer
= NULL
;
6783 if (device
->stateBlock
&& device
->stateBlock
->state
.index_buffer
== buffer
)
6785 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6786 buffer
, device
->stateBlock
);
6787 device
->stateBlock
->state
.index_buffer
= NULL
;
6790 if (device
->updateStateBlock
!= device
->stateBlock
6791 && device
->updateStateBlock
->state
.index_buffer
== buffer
)
6793 ERR("Buffer %p is still in use by stateblock %p as index buffer.\n",
6794 buffer
, device
->updateStateBlock
);
6795 device
->updateStateBlock
->state
.index_buffer
= NULL
;
6804 /* Remove the resource from the resourceStore */
6805 device_resource_remove(device
, resource
);
6807 TRACE("Resource released.\n");
6810 static HRESULT WINAPI
IWineD3DDeviceImpl_EnumResources(IWineD3DDevice
*iface
,
6811 D3DCB_ENUMRESOURCES callback
, void *data
)
6813 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*) iface
;
6814 struct wined3d_resource
*resource
, *cursor
;
6816 TRACE("iface %p, callback %p, data %p.\n", iface
, callback
, data
);
6818 LIST_FOR_EACH_ENTRY_SAFE(resource
, cursor
, &This
->resources
, struct wined3d_resource
, resource_list_entry
)
6820 TRACE("enumerating resource %p.\n", resource
);
6821 if (callback(resource
, data
) == S_FALSE
)
6823 TRACE("Canceling enumeration.\n");
6831 static HRESULT WINAPI
IWineD3DDeviceImpl_GetSurfaceFromDC(IWineD3DDevice
*iface
,
6832 HDC dc
, struct wined3d_surface
**surface
)
6834 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
6835 struct wined3d_resource
*resource
;
6837 LIST_FOR_EACH_ENTRY(resource
, &This
->resources
, struct wined3d_resource
, resource_list_entry
)
6839 if (resource
->resourceType
== WINED3DRTYPE_SURFACE
)
6841 struct wined3d_surface
*s
= surface_from_resource(resource
);
6845 TRACE("Found surface %p for dc %p.\n", s
, dc
);
6852 return WINED3DERR_INVALIDCALL
;
6855 /**********************************************************
6856 * IWineD3DDevice VTbl follows
6857 **********************************************************/
6859 static const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl
=
6861 /*** IUnknown methods ***/
6862 IWineD3DDeviceImpl_QueryInterface
,
6863 IWineD3DDeviceImpl_AddRef
,
6864 IWineD3DDeviceImpl_Release
,
6865 /*** IWineD3DDevice methods ***/
6866 /*** Creation methods**/
6867 IWineD3DDeviceImpl_CreateBuffer
,
6868 IWineD3DDeviceImpl_CreateVertexBuffer
,
6869 IWineD3DDeviceImpl_CreateIndexBuffer
,
6870 IWineD3DDeviceImpl_CreateStateBlock
,
6871 IWineD3DDeviceImpl_CreateSurface
,
6872 IWineD3DDeviceImpl_CreateRendertargetView
,
6873 IWineD3DDeviceImpl_CreateTexture
,
6874 IWineD3DDeviceImpl_CreateVolumeTexture
,
6875 IWineD3DDeviceImpl_CreateVolume
,
6876 IWineD3DDeviceImpl_CreateCubeTexture
,
6877 IWineD3DDeviceImpl_CreateQuery
,
6878 IWineD3DDeviceImpl_CreateSwapChain
,
6879 IWineD3DDeviceImpl_CreateVertexDeclaration
,
6880 IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF
,
6881 IWineD3DDeviceImpl_CreateVertexShader
,
6882 IWineD3DDeviceImpl_CreateGeometryShader
,
6883 IWineD3DDeviceImpl_CreatePixelShader
,
6884 IWineD3DDeviceImpl_CreatePalette
,
6885 /*** Odd functions **/
6886 IWineD3DDeviceImpl_Init3D
,
6887 IWineD3DDeviceImpl_InitGDI
,
6888 IWineD3DDeviceImpl_Uninit3D
,
6889 IWineD3DDeviceImpl_UninitGDI
,
6890 IWineD3DDeviceImpl_SetMultithreaded
,
6891 IWineD3DDeviceImpl_EvictManagedResources
,
6892 IWineD3DDeviceImpl_GetAvailableTextureMem
,
6893 IWineD3DDeviceImpl_GetBackBuffer
,
6894 IWineD3DDeviceImpl_GetCreationParameters
,
6895 IWineD3DDeviceImpl_GetDeviceCaps
,
6896 IWineD3DDeviceImpl_GetDirect3D
,
6897 IWineD3DDeviceImpl_GetDisplayMode
,
6898 IWineD3DDeviceImpl_SetDisplayMode
,
6899 IWineD3DDeviceImpl_GetNumberOfSwapChains
,
6900 IWineD3DDeviceImpl_GetRasterStatus
,
6901 IWineD3DDeviceImpl_GetSwapChain
,
6902 IWineD3DDeviceImpl_Reset
,
6903 IWineD3DDeviceImpl_SetDialogBoxMode
,
6904 IWineD3DDeviceImpl_SetCursorProperties
,
6905 IWineD3DDeviceImpl_SetCursorPosition
,
6906 IWineD3DDeviceImpl_ShowCursor
,
6907 /*** Getters and setters **/
6908 IWineD3DDeviceImpl_SetClipPlane
,
6909 IWineD3DDeviceImpl_GetClipPlane
,
6910 IWineD3DDeviceImpl_SetClipStatus
,
6911 IWineD3DDeviceImpl_GetClipStatus
,
6912 IWineD3DDeviceImpl_SetCurrentTexturePalette
,
6913 IWineD3DDeviceImpl_GetCurrentTexturePalette
,
6914 IWineD3DDeviceImpl_SetDepthStencilSurface
,
6915 IWineD3DDeviceImpl_GetDepthStencilSurface
,
6916 IWineD3DDeviceImpl_SetGammaRamp
,
6917 IWineD3DDeviceImpl_GetGammaRamp
,
6918 IWineD3DDeviceImpl_SetIndexBuffer
,
6919 IWineD3DDeviceImpl_GetIndexBuffer
,
6920 IWineD3DDeviceImpl_SetBaseVertexIndex
,
6921 IWineD3DDeviceImpl_GetBaseVertexIndex
,
6922 IWineD3DDeviceImpl_SetLight
,
6923 IWineD3DDeviceImpl_GetLight
,
6924 IWineD3DDeviceImpl_SetLightEnable
,
6925 IWineD3DDeviceImpl_GetLightEnable
,
6926 IWineD3DDeviceImpl_SetMaterial
,
6927 IWineD3DDeviceImpl_GetMaterial
,
6928 IWineD3DDeviceImpl_SetNPatchMode
,
6929 IWineD3DDeviceImpl_GetNPatchMode
,
6930 IWineD3DDeviceImpl_SetPaletteEntries
,
6931 IWineD3DDeviceImpl_GetPaletteEntries
,
6932 IWineD3DDeviceImpl_SetPixelShader
,
6933 IWineD3DDeviceImpl_GetPixelShader
,
6934 IWineD3DDeviceImpl_SetPixelShaderConstantB
,
6935 IWineD3DDeviceImpl_GetPixelShaderConstantB
,
6936 IWineD3DDeviceImpl_SetPixelShaderConstantI
,
6937 IWineD3DDeviceImpl_GetPixelShaderConstantI
,
6938 IWineD3DDeviceImpl_SetPixelShaderConstantF
,
6939 IWineD3DDeviceImpl_GetPixelShaderConstantF
,
6940 IWineD3DDeviceImpl_SetRenderState
,
6941 IWineD3DDeviceImpl_GetRenderState
,
6942 IWineD3DDeviceImpl_SetRenderTarget
,
6943 IWineD3DDeviceImpl_GetRenderTarget
,
6944 IWineD3DDeviceImpl_SetSamplerState
,
6945 IWineD3DDeviceImpl_GetSamplerState
,
6946 IWineD3DDeviceImpl_SetScissorRect
,
6947 IWineD3DDeviceImpl_GetScissorRect
,
6948 IWineD3DDeviceImpl_SetSoftwareVertexProcessing
,
6949 IWineD3DDeviceImpl_GetSoftwareVertexProcessing
,
6950 IWineD3DDeviceImpl_SetStreamSource
,
6951 IWineD3DDeviceImpl_GetStreamSource
,
6952 IWineD3DDeviceImpl_SetStreamSourceFreq
,
6953 IWineD3DDeviceImpl_GetStreamSourceFreq
,
6954 IWineD3DDeviceImpl_SetTexture
,
6955 IWineD3DDeviceImpl_GetTexture
,
6956 IWineD3DDeviceImpl_SetTextureStageState
,
6957 IWineD3DDeviceImpl_GetTextureStageState
,
6958 IWineD3DDeviceImpl_SetTransform
,
6959 IWineD3DDeviceImpl_GetTransform
,
6960 IWineD3DDeviceImpl_SetVertexDeclaration
,
6961 IWineD3DDeviceImpl_GetVertexDeclaration
,
6962 IWineD3DDeviceImpl_SetVertexShader
,
6963 IWineD3DDeviceImpl_GetVertexShader
,
6964 IWineD3DDeviceImpl_SetVertexShaderConstantB
,
6965 IWineD3DDeviceImpl_GetVertexShaderConstantB
,
6966 IWineD3DDeviceImpl_SetVertexShaderConstantI
,
6967 IWineD3DDeviceImpl_GetVertexShaderConstantI
,
6968 IWineD3DDeviceImpl_SetVertexShaderConstantF
,
6969 IWineD3DDeviceImpl_GetVertexShaderConstantF
,
6970 IWineD3DDeviceImpl_SetViewport
,
6971 IWineD3DDeviceImpl_GetViewport
,
6972 IWineD3DDeviceImpl_MultiplyTransform
,
6973 IWineD3DDeviceImpl_ValidateDevice
,
6974 IWineD3DDeviceImpl_ProcessVertices
,
6975 /*** State block ***/
6976 IWineD3DDeviceImpl_BeginStateBlock
,
6977 IWineD3DDeviceImpl_EndStateBlock
,
6978 /*** Scene management ***/
6979 IWineD3DDeviceImpl_BeginScene
,
6980 IWineD3DDeviceImpl_EndScene
,
6981 IWineD3DDeviceImpl_Present
,
6982 IWineD3DDeviceImpl_Clear
,
6983 IWineD3DDeviceImpl_ClearRendertargetView
,
6985 IWineD3DDeviceImpl_SetPrimitiveType
,
6986 IWineD3DDeviceImpl_GetPrimitiveType
,
6987 IWineD3DDeviceImpl_DrawPrimitive
,
6988 IWineD3DDeviceImpl_DrawIndexedPrimitive
,
6989 IWineD3DDeviceImpl_DrawPrimitiveUP
,
6990 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP
,
6991 IWineD3DDeviceImpl_DrawPrimitiveStrided
,
6992 IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided
,
6993 IWineD3DDeviceImpl_DrawRectPatch
,
6994 IWineD3DDeviceImpl_DrawTriPatch
,
6995 IWineD3DDeviceImpl_DeletePatch
,
6996 IWineD3DDeviceImpl_ColorFill
,
6997 IWineD3DDeviceImpl_UpdateTexture
,
6998 IWineD3DDeviceImpl_UpdateSurface
,
6999 IWineD3DDeviceImpl_GetFrontBufferData
,
7000 /*** object tracking ***/
7001 IWineD3DDeviceImpl_EnumResources
,
7002 IWineD3DDeviceImpl_GetSurfaceFromDC
,
7003 IWineD3DDeviceImpl_AcquireFocusWindow
,
7004 IWineD3DDeviceImpl_ReleaseFocusWindow
,
7005 IWineD3DDeviceImpl_SetupFullscreenWindow
,
7006 IWineD3DDeviceImpl_RestoreFullscreenWindow
,
7009 HRESULT
device_init(IWineD3DDeviceImpl
*device
, struct wined3d
*wined3d
,
7010 UINT adapter_idx
, WINED3DDEVTYPE device_type
, HWND focus_window
, DWORD flags
,
7011 IWineD3DDeviceParent
*device_parent
)
7013 struct wined3d_adapter
*adapter
= &wined3d
->adapters
[adapter_idx
];
7014 const struct fragment_pipeline
*fragment_pipeline
;
7015 struct shader_caps shader_caps
;
7016 struct fragment_caps ffp_caps
;
7017 WINED3DDISPLAYMODE mode
;
7021 device
->lpVtbl
= &IWineD3DDevice_Vtbl
;
7023 device
->wined3d
= wined3d
;
7024 wined3d_incref(device
->wined3d
);
7025 device
->adapter
= wined3d
->adapter_count
? adapter
: NULL
;
7026 device
->device_parent
= device_parent
;
7027 list_init(&device
->resources
);
7028 list_init(&device
->shaders
);
7030 device
->surface_alignment
= wined3d
->dxVersion
== 7 ? DDRAW_PITCH_ALIGNMENT
: D3D8_PITCH_ALIGNMENT
;
7032 /* Get the initial screen setup for ddraw. */
7033 hr
= wined3d_get_adapter_display_mode(wined3d
, adapter_idx
, &mode
);
7036 ERR("Failed to get the adapter's display mode, hr %#x.\n", hr
);
7037 wined3d_decref(device
->wined3d
);
7040 device
->ddraw_width
= mode
.Width
;
7041 device
->ddraw_height
= mode
.Height
;
7042 device
->ddraw_format
= mode
.Format
;
7044 /* Save the creation parameters. */
7045 device
->createParms
.AdapterOrdinal
= adapter_idx
;
7046 device
->createParms
.DeviceType
= device_type
;
7047 device
->createParms
.hFocusWindow
= focus_window
;
7048 device
->createParms
.BehaviorFlags
= flags
;
7050 device
->devType
= device_type
;
7051 for (i
= 0; i
< PATCHMAP_SIZE
; ++i
) list_init(&device
->patches
[i
]);
7053 select_shader_mode(&adapter
->gl_info
, &device
->ps_selected_mode
, &device
->vs_selected_mode
);
7054 device
->shader_backend
= adapter
->shader_backend
;
7056 if (device
->shader_backend
)
7058 device
->shader_backend
->shader_get_caps(&adapter
->gl_info
, &shader_caps
);
7059 device
->d3d_vshader_constantF
= shader_caps
.MaxVertexShaderConst
;
7060 device
->d3d_pshader_constantF
= shader_caps
.MaxPixelShaderConst
;
7061 device
->vs_clipping
= shader_caps
.VSClipping
;
7063 fragment_pipeline
= adapter
->fragment_pipe
;
7064 device
->frag_pipe
= fragment_pipeline
;
7065 if (fragment_pipeline
)
7067 fragment_pipeline
->get_caps(&adapter
->gl_info
, &ffp_caps
);
7068 device
->max_ffp_textures
= ffp_caps
.MaxSimultaneousTextures
;
7070 hr
= compile_state_table(device
->StateTable
, device
->multistate_funcs
, &adapter
->gl_info
,
7071 ffp_vertexstate_template
, fragment_pipeline
, misc_state_template
);
7074 ERR("Failed to compile state table, hr %#x.\n", hr
);
7075 wined3d_decref(device
->wined3d
);
7079 device
->blitter
= adapter
->blitter
;
7085 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl
*This
, DWORD state
) {
7086 DWORD rep
= This
->StateTable
[state
].representative
;
7087 struct wined3d_context
*context
;
7092 for (i
= 0; i
< This
->context_count
; ++i
)
7094 context
= This
->contexts
[i
];
7095 if(isStateDirty(context
, rep
)) continue;
7097 context
->dirtyArray
[context
->numDirtyEntries
++] = rep
;
7098 idx
= rep
/ (sizeof(*context
->isStateDirty
) * CHAR_BIT
);
7099 shift
= rep
& ((sizeof(*context
->isStateDirty
) * CHAR_BIT
) - 1);
7100 context
->isStateDirty
[idx
] |= (1 << shift
);
7104 void get_drawable_size_fbo(struct wined3d_context
*context
, UINT
*width
, UINT
*height
)
7106 /* The drawable size of a fbo target is the opengl texture size, which is the power of two size. */
7107 *width
= context
->current_rt
->pow2Width
;
7108 *height
= context
->current_rt
->pow2Height
;
7111 void get_drawable_size_backbuffer(struct wined3d_context
*context
, UINT
*width
, UINT
*height
)
7113 struct wined3d_swapchain
*swapchain
= context
->swapchain
;
7114 /* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
7115 * current context's drawable, which is the size of the back buffer of the swapchain
7116 * the active context belongs to. */
7117 *width
= swapchain
->presentParms
.BackBufferWidth
;
7118 *height
= swapchain
->presentParms
.BackBufferHeight
;
7121 LRESULT
device_process_message(IWineD3DDeviceImpl
*device
, HWND window
, BOOL unicode
,
7122 UINT message
, WPARAM wparam
, LPARAM lparam
, WNDPROC proc
)
7124 if (device
->filter_messages
)
7126 TRACE("Filtering message: window %p, message %#x, wparam %#lx, lparam %#lx.\n",
7127 window
, message
, wparam
, lparam
);
7129 return DefWindowProcW(window
, message
, wparam
, lparam
);
7131 return DefWindowProcA(window
, message
, wparam
, lparam
);
7134 if (message
== WM_DESTROY
)
7136 TRACE("unregister window %p.\n", window
);
7137 wined3d_unregister_window(window
);
7139 if (device
->focus_window
== window
) device
->focus_window
= NULL
;
7140 else ERR("Window %p is not the focus window for device %p.\n", window
, device
);
7144 return CallWindowProcW(proc
, window
, message
, wparam
, lparam
);
7146 return CallWindowProcA(proc
, window
, message
, wparam
, lparam
);