2004-10-07 06:22:21 +02:00
/*
* IWineD3DDevice implementation
*
2006-04-18 23:15:56 +02:00
* Copyright 2002 Lionel Ulmer
2005-03-02 13:16:10 +01:00
* Copyright 2002 - 2005 Jason Edmeades
2004-10-07 06:22:21 +02:00
* Copyright 2003 - 2004 Raphael Junqueira
* Copyright 2004 Christian Costa
2005-03-02 13:16:10 +01:00
* Copyright 2005 Oliver Stieber
2008-10-18 19:21:20 +02:00
* Copyright 2006 - 2008 Stefan Dösinger for CodeWeavers
2008-08-21 18:34:55 +02:00
* Copyright 2006 - 2008 Henri Verbeet
2007-05-15 00:37:53 +02:00
* Copyright 2007 Andrew Riedi
2004-10-07 06:22:21 +02:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
2006-05-18 14:49:52 +02:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2004-10-07 06:22:21 +02:00
*/
# include "config.h"
2006-06-09 09:36:55 +02:00
# include <stdio.h>
2006-02-13 13:23:42 +01:00
# ifdef HAVE_FLOAT_H
# include <float.h>
# endif
2004-10-07 06:22:21 +02:00
# include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL ( d3d ) ;
2007-06-09 14:27:41 +02:00
# define GLINFO_LOCATION This->adapter->gl_info
2004-10-07 06:22:21 +02:00
2006-06-07 05:37:05 +02:00
/* Define the default light parameters as specified by MSDN */
const WINED3DLIGHT WINED3D_default_light = {
2006-10-11 03:55:47 +02:00
WINED3DLIGHT_DIRECTIONAL , /* Type */
{ 1.0 , 1.0 , 1.0 , 0.0 } , /* Diffuse r,g,b,a */
{ 0.0 , 0.0 , 0.0 , 0.0 } , /* Specular r,g,b,a */
{ 0.0 , 0.0 , 0.0 , 0.0 } , /* Ambient r,g,b,a, */
{ 0.0 , 0.0 , 0.0 } , /* Position x,y,z */
{ 0.0 , 0.0 , 1.0 } , /* Direction x,y,z */
0.0 , /* Range */
0.0 , /* Falloff */
0.0 , 0.0 , 0.0 , /* Attenuation 0,1,2 */
0.0 , /* Theta */
0.0 /* Phi */
2006-06-07 05:37:05 +02:00
} ;
2004-10-07 06:22:21 +02:00
/**********************************************************
2004-11-28 16:04:41 +01:00
* Global variable / Constants follow
2004-10-07 06:22:21 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-11-28 16:04:41 +01:00
const float identity [ 16 ] = { 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1 } ; /* When needed for comparisons */
2004-10-07 06:22:21 +02:00
2009-03-05 12:30:43 +01:00
/* Note that except for WINED3DPT_POINTLIST and WINED3DPT_LINELIST these
* actually have the same values in GL and D3D . */
static GLenum gl_primitive_type_from_d3d ( WINED3DPRIMITIVETYPE primitive_type )
{
switch ( primitive_type )
{
case WINED3DPT_POINTLIST :
return GL_POINTS ;
case WINED3DPT_LINELIST :
return GL_LINES ;
case WINED3DPT_LINESTRIP :
return GL_LINE_STRIP ;
case WINED3DPT_TRIANGLELIST :
return GL_TRIANGLES ;
case WINED3DPT_TRIANGLESTRIP :
return GL_TRIANGLE_STRIP ;
case WINED3DPT_TRIANGLEFAN :
return GL_TRIANGLE_FAN ;
case WINED3DPT_LINELIST_ADJ :
return GL_LINES_ADJACENCY_ARB ;
case WINED3DPT_LINESTRIP_ADJ :
return GL_LINE_STRIP_ADJACENCY_ARB ;
case WINED3DPT_TRIANGLELIST_ADJ :
return GL_TRIANGLES_ADJACENCY_ARB ;
case WINED3DPT_TRIANGLESTRIP_ADJ :
return GL_TRIANGLE_STRIP_ADJACENCY_ARB ;
default :
FIXME ( " Unhandled primitive type %s \n " , debug_d3dprimitivetype ( primitive_type ) ) ;
return GL_NONE ;
}
}
static WINED3DPRIMITIVETYPE d3d_primitive_type_from_gl ( GLenum primitive_type )
{
switch ( primitive_type )
{
case GL_POINTS :
return WINED3DPT_POINTLIST ;
case GL_LINES :
return WINED3DPT_LINELIST ;
case GL_LINE_STRIP :
return WINED3DPT_LINESTRIP ;
case GL_TRIANGLES :
return WINED3DPT_TRIANGLELIST ;
case GL_TRIANGLE_STRIP :
return WINED3DPT_TRIANGLESTRIP ;
case GL_TRIANGLE_FAN :
return WINED3DPT_TRIANGLEFAN ;
case GL_LINES_ADJACENCY_ARB :
return WINED3DPT_LINELIST_ADJ ;
case GL_LINE_STRIP_ADJACENCY_ARB :
return WINED3DPT_LINESTRIP_ADJ ;
case GL_TRIANGLES_ADJACENCY_ARB :
return WINED3DPT_TRIANGLELIST_ADJ ;
case GL_TRIANGLE_STRIP_ADJACENCY_ARB :
return WINED3DPT_TRIANGLESTRIP_ADJ ;
default :
FIXME ( " Unhandled primitive type %s \n " , debug_d3dprimitivetype ( primitive_type ) ) ;
return WINED3DPT_UNDEFINED ;
}
}
2009-03-27 10:25:55 +01:00
static BOOL fixed_get_input ( BYTE usage , BYTE usage_idx , unsigned int * regnum )
{
if ( ( usage = = WINED3DDECLUSAGE_POSITION | | usage = = WINED3DDECLUSAGE_POSITIONT ) & & usage_idx = = 0 )
* regnum = WINED3D_FFP_POSITION ;
else if ( usage = = WINED3DDECLUSAGE_BLENDWEIGHT & & usage_idx = = 0 )
* regnum = WINED3D_FFP_BLENDWEIGHT ;
else if ( usage = = WINED3DDECLUSAGE_BLENDINDICES & & usage_idx = = 0 )
* regnum = WINED3D_FFP_BLENDINDICES ;
else if ( usage = = WINED3DDECLUSAGE_NORMAL & & usage_idx = = 0 )
* regnum = WINED3D_FFP_NORMAL ;
else if ( usage = = WINED3DDECLUSAGE_PSIZE & & usage_idx = = 0 )
* regnum = WINED3D_FFP_PSIZE ;
else if ( usage = = WINED3DDECLUSAGE_COLOR & & usage_idx = = 0 )
* regnum = WINED3D_FFP_DIFFUSE ;
else if ( usage = = WINED3DDECLUSAGE_COLOR & & usage_idx = = 1 )
* regnum = WINED3D_FFP_SPECULAR ;
else if ( usage = = WINED3DDECLUSAGE_TEXCOORD & & usage_idx < WINED3DDP_MAXTEXCOORD )
* regnum = WINED3D_FFP_TEXCOORD0 + usage_idx ;
else
{
FIXME ( " Unsupported input stream [usage=%s, usage_idx=%u] \n " , debug_d3ddeclusage ( usage ) , usage_idx ) ;
* regnum = ~ 0U ;
return FALSE ;
}
return TRUE ;
}
2009-06-26 10:07:12 +02:00
/* Context activation is done by the caller. */
2009-03-27 10:25:55 +01:00
void device_stream_info_from_declaration ( IWineD3DDeviceImpl * This ,
BOOL use_vshader , struct wined3d_stream_info * stream_info , BOOL * fixup )
{
/* We need to deal with frequency data! */
IWineD3DVertexDeclarationImpl * declaration = ( IWineD3DVertexDeclarationImpl * ) This - > stateBlock - > vertexDecl ;
UINT stream_count = This - > stateBlock - > streamIsUP ? 0 : declaration - > num_streams ;
const DWORD * streams = declaration - > streams ;
unsigned int i ;
memset ( stream_info , 0 , sizeof ( * stream_info ) ) ;
/* Check for transformed vertices, disable vertex shader if present. */
stream_info - > position_transformed = declaration - > position_transformed ;
if ( declaration - > position_transformed ) use_vshader = FALSE ;
/* Translate the declaration into strided data. */
2009-03-27 10:25:56 +01:00
for ( i = 0 ; i < declaration - > element_count ; + + i )
2009-03-27 10:25:55 +01:00
{
2009-03-27 10:25:56 +01:00
const struct wined3d_vertex_declaration_element * element = & declaration - > elements [ i ] ;
2009-03-27 10:25:55 +01:00
GLuint buffer_object = 0 ;
const BYTE * data = NULL ;
BOOL stride_used ;
unsigned int idx ;
DWORD stride ;
2009-03-27 10:25:56 +01:00
TRACE ( " %p Element %p (%u of %u) \n " , declaration - > elements ,
element , i + 1 , declaration - > element_count ) ;
2009-03-27 10:25:55 +01:00
2009-03-27 10:25:56 +01:00
if ( ! This - > stateBlock - > streamSource [ element - > input_slot ] ) continue ;
2009-03-27 10:25:55 +01:00
2009-03-27 10:25:56 +01:00
stride = This - > stateBlock - > streamStride [ element - > input_slot ] ;
2009-03-27 10:25:55 +01:00
if ( This - > stateBlock - > streamIsUP )
{
2009-03-27 10:25:56 +01:00
TRACE ( " Stream %u is UP, %p \n " , element - > input_slot , This - > stateBlock - > streamSource [ element - > input_slot ] ) ;
2009-03-27 10:25:55 +01:00
buffer_object = 0 ;
2009-03-27 10:25:56 +01:00
data = ( BYTE * ) This - > stateBlock - > streamSource [ element - > input_slot ] ;
2009-03-27 10:25:55 +01:00
}
else
{
2009-03-27 10:25:56 +01:00
TRACE ( " Stream %u isn't UP, %p \n " , element - > input_slot , This - > stateBlock - > streamSource [ element - > input_slot ] ) ;
data = buffer_get_memory ( This - > stateBlock - > streamSource [ element - > input_slot ] , 0 , & buffer_object ) ;
2009-03-27 10:25:55 +01:00
/* Can't use vbo's if the base vertex index is negative. OpenGL doesn't accept negative offsets
* ( or rather offsets bigger than the vbo , because the pointer is unsigned ) , so use system memory
* sources . In most sane cases the pointer - offset will still be > 0 , otherwise it will wrap
* around to some big value . Hope that with the indices , the driver wraps it back internally . If
* not , drawStridedSlow is needed , including a vertex buffer path . */
if ( This - > stateBlock - > loadBaseVertexIndex < 0 )
{
WARN ( " loadBaseVertexIndex is < 0 (%d), not using vbos \n " , This - > stateBlock - > loadBaseVertexIndex ) ;
buffer_object = 0 ;
2009-04-19 20:42:08 +02:00
data = buffer_get_sysmem ( ( struct wined3d_buffer * ) This - > stateBlock - > streamSource [ element - > input_slot ] ) ;
2009-03-27 10:25:55 +01:00
if ( ( UINT_PTR ) data < - This - > stateBlock - > loadBaseVertexIndex * stride )
{
FIXME ( " System memory vertex data load offset is negative! \n " ) ;
}
}
if ( fixup )
{
if ( buffer_object ) * fixup = TRUE ;
else if ( * fixup & & ! use_vshader
2009-03-27 10:25:56 +01:00
& & ( element - > usage = = WINED3DDECLUSAGE_COLOR
| | element - > usage = = WINED3DDECLUSAGE_POSITIONT ) )
2009-03-27 10:25:55 +01:00
{
static BOOL warned = FALSE ;
if ( ! warned )
{
/* This may be bad with the fixed function pipeline. */
FIXME ( " Missing vbo streams with unfixed colors or transformed position, expect problems \n " ) ;
warned = TRUE ;
}
}
}
}
2009-03-27 10:25:56 +01:00
data + = element - > offset ;
2009-03-27 10:25:55 +01:00
2009-03-27 10:25:56 +01:00
TRACE ( " offset %u input_slot %u usage_idx %d \n " , element - > offset , element - > input_slot , element - > usage_idx ) ;
2009-03-27 10:25:55 +01:00
if ( use_vshader )
{
2009-03-30 11:24:54 +02:00
if ( element - > output_slot = = ~ 0U )
{
/* TODO: Assuming vertexdeclarations are usually used with the
* same or a similar shader , it might be worth it to store the
* last used output slot and try that one first . */
stride_used = vshader_get_input ( This - > stateBlock - > vertexShader ,
element - > usage , element - > usage_idx , & idx ) ;
}
else
{
idx = element - > output_slot ;
stride_used = TRUE ;
}
2009-03-27 10:25:55 +01:00
}
else
{
2009-03-27 10:25:56 +01:00
if ( ! element - > ffp_valid )
2009-03-27 10:25:55 +01:00
{
2009-03-27 10:25:56 +01:00
WARN ( " Skipping unsupported fixed function element of format %s and usage %s \n " ,
debug_d3dformat ( element - > format_desc - > format ) , debug_d3ddeclusage ( element - > usage ) ) ;
2009-03-27 10:25:55 +01:00
stride_used = FALSE ;
}
else
{
2009-03-27 10:25:56 +01:00
stride_used = fixed_get_input ( element - > usage , element - > usage_idx , & idx ) ;
2009-03-27 10:25:55 +01:00
}
}
if ( stride_used )
{
TRACE ( " Load %s array %u [usage %s, usage_idx %u, "
2009-03-27 10:25:56 +01:00
" input_slot %u, offset %u, stride %u, format %s, buffer_object %u] \n " ,
2009-03-27 10:25:55 +01:00
use_vshader ? " shader " : " fixed function " , idx ,
2009-03-27 10:25:56 +01:00
debug_d3ddeclusage ( element - > usage ) , element - > usage_idx , element - > input_slot ,
element - > offset , stride , debug_d3dformat ( element - > format_desc - > format ) , buffer_object ) ;
2009-03-30 11:24:54 +02:00
stream_info - > elements [ idx ] . format_desc = element - > format_desc ;
2009-03-27 10:25:55 +01:00
stream_info - > elements [ idx ] . stride = stride ;
stream_info - > elements [ idx ] . data = data ;
2009-03-27 10:25:56 +01:00
stream_info - > elements [ idx ] . stream_idx = element - > input_slot ;
2009-03-27 10:25:55 +01:00
stream_info - > elements [ idx ] . buffer_object = buffer_object ;
2009-03-27 10:25:56 +01:00
if ( ! GL_SUPPORT ( EXT_VERTEX_ARRAY_BGRA ) & & element - > format_desc - > format = = WINED3DFMT_A8R8G8B8 )
2009-03-27 10:25:55 +01:00
{
stream_info - > swizzle_map | = 1 < < idx ;
}
stream_info - > use_map | = 1 < < idx ;
}
}
/* Now call PreLoad on all the vertex buffers. In the very rare case
* that the buffers stopps converting PreLoad will dirtify the VDECL again .
* The vertex buffer can now use the strided structure in the device instead of finding its
* own again .
*
* NULL streams won ' t be recorded in the array , UP streams won ' t be either . A stream is only
* once in there . */
for ( i = 0 ; i < stream_count ; + + i )
{
IWineD3DBuffer * vb = This - > stateBlock - > streamSource [ streams [ i ] ] ;
if ( vb ) IWineD3DBuffer_PreLoad ( vb ) ;
}
}
static void stream_info_element_from_strided ( IWineD3DDeviceImpl * This ,
const struct WineDirect3DStridedData * strided , struct wined3d_stream_info_element * e )
{
2009-03-27 10:25:56 +01:00
const struct GlPixelFormatDesc * format_desc = getFormatDescEntry ( strided - > format , & This - > adapter - > gl_info ) ;
2009-03-30 11:24:54 +02:00
e - > format_desc = format_desc ;
2009-03-27 10:25:55 +01:00
e - > stride = strided - > dwStride ;
e - > data = strided - > lpData ;
e - > stream_idx = 0 ;
e - > buffer_object = 0 ;
}
void device_stream_info_from_strided ( IWineD3DDeviceImpl * This ,
const struct WineDirect3DVertexStridedData * strided , struct wined3d_stream_info * stream_info )
{
unsigned int i ;
memset ( stream_info , 0 , sizeof ( * stream_info ) ) ;
if ( strided - > position . lpData )
stream_info_element_from_strided ( This , & strided - > position , & stream_info - > elements [ WINED3D_FFP_POSITION ] ) ;
if ( strided - > normal . lpData )
stream_info_element_from_strided ( This , & strided - > normal , & stream_info - > elements [ WINED3D_FFP_NORMAL ] ) ;
if ( strided - > diffuse . lpData )
stream_info_element_from_strided ( This , & strided - > diffuse , & stream_info - > elements [ WINED3D_FFP_DIFFUSE ] ) ;
if ( strided - > specular . lpData )
stream_info_element_from_strided ( This , & strided - > specular , & stream_info - > elements [ WINED3D_FFP_SPECULAR ] ) ;
for ( i = 0 ; i < WINED3DDP_MAXTEXCOORD ; + + i )
{
if ( strided - > texCoords [ i ] . lpData )
stream_info_element_from_strided ( This , & strided - > texCoords [ i ] ,
& stream_info - > elements [ WINED3D_FFP_TEXCOORD0 + i ] ) ;
}
stream_info - > position_transformed = strided - > position_transformed ;
for ( i = 0 ; i < sizeof ( stream_info - > elements ) / sizeof ( * stream_info - > elements ) ; + + i )
{
2009-04-09 09:58:27 +02:00
if ( ! stream_info - > elements [ i ] . format_desc ) continue ;
2009-03-30 11:24:54 +02:00
if ( ! GL_SUPPORT ( EXT_VERTEX_ARRAY_BGRA ) & & stream_info - > elements [ i ] . format_desc - > format = = WINED3DFMT_A8R8G8B8 )
2009-03-27 10:25:55 +01:00
{
stream_info - > swizzle_map | = 1 < < i ;
}
stream_info - > use_map | = 1 < < i ;
}
}
2009-03-05 12:30:43 +01:00
2005-03-02 13:16:10 +01:00
/**********************************************************
* IUnknown parts follows
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface ( IWineD3DDevice * iface , REFIID riid , LPVOID * ppobj )
2005-03-02 13:16:10 +01:00
{
2005-03-02 14:44:58 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
2005-03-02 14:44:58 +01:00
TRACE ( " (%p)->(%s,%p) \n " , This , debugstr_guid ( riid ) , ppobj ) ;
2005-07-13 16:15:54 +02:00
if ( IsEqualGUID ( riid , & IID_IUnknown )
2006-02-06 11:32:41 +01:00
| | IsEqualGUID ( riid , & IID_IWineD3DBase )
2005-03-02 14:44:58 +01:00
| | IsEqualGUID ( riid , & IID_IWineD3DDevice ) ) {
IUnknown_AddRef ( iface ) ;
* ppobj = This ;
2006-04-25 23:59:12 +02:00
return S_OK ;
2005-03-02 14:44:58 +01:00
}
2006-04-25 23:59:12 +02:00
* ppobj = NULL ;
2005-03-02 13:16:10 +01:00
return E_NOINTERFACE ;
}
2006-06-10 13:15:32 +02:00
static ULONG WINAPI IWineD3DDeviceImpl_AddRef ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
ULONG refCount = InterlockedIncrement ( & This - > ref ) ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : AddRef increasing from %d \n " , This , refCount - 1 ) ;
2005-03-02 13:16:10 +01:00
return refCount ;
}
2006-06-10 13:15:32 +02:00
static ULONG WINAPI IWineD3DDeviceImpl_Release ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
ULONG refCount = InterlockedDecrement ( & This - > ref ) ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : Releasing from %d \n " , This , refCount + 1 ) ;
2005-03-02 13:16:10 +01:00
if ( ! refCount ) {
2009-01-07 02:20:08 +01:00
UINT i ;
for ( i = 0 ; i < sizeof ( This - > multistate_funcs ) / sizeof ( This - > multistate_funcs [ 0 ] ) ; + + i ) {
HeapFree ( GetProcessHeap ( ) , 0 , This - > multistate_funcs [ i ] ) ;
This - > multistate_funcs [ i ] = NULL ;
}
2005-03-02 13:16:10 +01:00
/* TODO: Clean up all the surfaces and textures! */
2006-04-18 22:38:30 +02:00
/* NOTE: You must release the parent if the object was created via a callback
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-23 12:07:46 +02:00
2007-11-16 20:28:45 +01:00
if ( ! list_empty ( & This - > resources ) ) {
2006-04-18 22:38:30 +02:00
FIXME ( " (%p) Device released with resources still bound, acceptable but unexpected \n " , This ) ;
2007-11-16 20:28:45 +01:00
dumpResources ( & This - > resources ) ;
2006-04-18 22:38:30 +02:00
}
2005-06-23 13:05:24 +02:00
2007-02-12 19:21:10 +01:00
if ( This - > contexts ) ERR ( " Context array not freed! \n " ) ;
2007-05-15 00:37:53 +02:00
if ( This - > hardwareCursor ) DestroyCursor ( This - > hardwareCursor ) ;
This - > haveHardwareCursor = FALSE ;
2005-09-23 12:07:46 +02:00
2005-03-02 13:16:10 +01:00
IWineD3D_Release ( This - > wineD3D ) ;
2005-09-23 12:07:46 +02:00
This - > wineD3D = NULL ;
2005-03-02 13:16:10 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , This ) ;
2005-11-10 13:14:56 +01:00
TRACE ( " Freed device %p \n " , This ) ;
2005-09-23 12:07:46 +02:00
This = NULL ;
2005-03-02 13:16:10 +01:00
}
return refCount ;
2004-12-13 14:35:38 +01:00
}
2004-10-07 06:22:21 +02:00
/**********************************************************
* IWineD3DDevice implementation follows
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetParent ( IWineD3DDevice * iface , IUnknown * * pParent ) {
2004-11-23 14:52:46 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
* pParent = This - > parent ;
IUnknown_AddRef ( This - > parent ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-23 14:52:46 +01:00
}
2009-02-23 09:16:02 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateBuffer ( IWineD3DDevice * iface ,
2009-03-31 09:38:14 +02:00
struct wined3d_buffer_desc * desc , const void * data , IUnknown * parent , IWineD3DBuffer * * buffer )
2009-02-23 09:16:02 +01:00
{
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-05-26 09:15:11 +02:00
const struct GlPixelFormatDesc * format_desc = getFormatDescEntry ( WINED3DFMT_UNKNOWN , & This - > adapter - > gl_info ) ;
2009-02-23 09:16:02 +01:00
struct wined3d_buffer * object ;
HRESULT hr ;
2009-03-31 09:38:14 +02:00
TRACE ( " iface %p, desc %p, data %p, parent %p, buffer %p \n " , iface , desc , data , parent , buffer ) ;
2009-02-23 09:16:02 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Failed to allocate memory \n " ) ;
return E_OUTOFMEMORY ;
}
object - > vtbl = & wined3d_buffer_vtbl ;
object - > desc = * desc ;
FIXME ( " Ignoring access flags (pool) \n " ) ;
2009-05-29 09:13:21 +02:00
hr = resource_init ( ( IWineD3DResource * ) object , WINED3DRTYPE_BUFFER , This , desc - > byte_width ,
2009-05-26 09:15:11 +02:00
desc - > usage , format_desc , WINED3DPOOL_MANAGED , parent ) ;
2009-02-23 09:16:02 +01:00
if ( FAILED ( hr ) )
{
WARN ( " Failed to initialize resource, returning %#x \n " , hr ) ;
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
return hr ;
}
2009-04-06 13:38:56 +02:00
object - > buffer_type_hint = GL_ARRAY_BUFFER_ARB ;
2009-02-23 09:16:02 +01:00
TRACE ( " Created resource %p \n " , object ) ;
TRACE ( " size %#x, usage=%#x, format %s, memory @ %p, iface @ %p \n " , object - > resource . size , object - > resource . usage ,
2009-03-13 10:44:18 +01:00
debug_d3dformat ( object - > resource . format_desc - > format ) , object - > resource . allocatedMemory , object ) ;
2009-02-23 09:16:02 +01:00
2009-03-31 09:38:14 +02:00
if ( data )
{
BYTE * ptr ;
hr = IWineD3DBuffer_Map ( ( IWineD3DBuffer * ) object , 0 , desc - > byte_width , & ptr , 0 ) ;
if ( FAILED ( hr ) )
{
ERR ( " Failed to map buffer, hr %#x \n " , hr ) ;
IWineD3DBuffer_Release ( ( IWineD3DBuffer * ) object ) ;
return hr ;
}
memcpy ( ptr , data , desc - > byte_width ) ;
hr = IWineD3DBuffer_Unmap ( ( IWineD3DBuffer * ) object ) ;
if ( FAILED ( hr ) )
{
ERR ( " Failed to unmap buffer, hr %#x \n " , hr ) ;
IWineD3DBuffer_Release ( ( IWineD3DBuffer * ) object ) ;
return hr ;
}
}
2009-02-23 09:16:02 +01:00
* buffer = ( IWineD3DBuffer * ) object ;
return WINED3D_OK ;
}
2009-03-06 14:56:23 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer ( IWineD3DDevice * iface , UINT Size , DWORD Usage ,
2009-04-23 09:24:27 +02:00
DWORD FVF , WINED3DPOOL Pool , IWineD3DBuffer * * ppVertexBuffer , IUnknown * parent )
2009-03-06 14:56:23 +01:00
{
2004-10-14 02:32:04 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-13 10:44:18 +01:00
/* Dummy format for now */
const struct GlPixelFormatDesc * format_desc = getFormatDescEntry ( WINED3DFMT_VERTEXDATA , & This - > adapter - > gl_info ) ;
2009-03-06 14:56:23 +01:00
struct wined3d_buffer * object ;
2006-06-21 15:05:38 +02:00
int dxVersion = ( ( IWineD3DImpl * ) This - > wineD3D ) - > dxVersion ;
2009-01-13 10:31:57 +01:00
HRESULT hr ;
2006-06-21 15:05:38 +02:00
BOOL conv ;
2007-02-13 20:24:39 +01:00
if ( Size = = 0 ) {
WARN ( " Size 0 requested, returning WINED3DERR_INVALIDCALL \n " ) ;
2007-10-22 13:30:14 +02:00
* ppVertexBuffer = NULL ;
return WINED3DERR_INVALIDCALL ;
} else if ( Pool = = WINED3DPOOL_SCRATCH ) {
/* The d3d9 testsuit shows that this is not allowed. It doesn't make much sense
2008-05-06 15:54:52 +02:00
* anyway , SCRATCH vertex buffers aren ' t usable anywhere
2007-10-22 13:30:14 +02:00
*/
WARN ( " Vertex buffer in D3DPOOL_SCRATCH requested, returning WINED3DERR_INVALIDCALL \n " ) ;
2007-02-13 20:24:39 +01:00
* ppVertexBuffer = NULL ;
return WINED3DERR_INVALIDCALL ;
}
2009-01-13 10:31:57 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppVertexBuffer = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
2009-03-06 14:56:23 +01:00
object - > vtbl = & wined3d_buffer_vtbl ;
2009-05-29 09:13:21 +02:00
hr = resource_init ( ( IWineD3DResource * ) object , WINED3DRTYPE_BUFFER , This , Size , Usage , format_desc , Pool , parent ) ;
2009-01-13 10:31:57 +01:00
if ( FAILED ( hr ) )
{
WARN ( " Failed to initialize resource, returning %#x \n " , hr ) ;
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppVertexBuffer = NULL ;
return hr ;
}
2009-04-06 13:38:56 +02:00
object - > buffer_type_hint = GL_ARRAY_BUFFER_ARB ;
2009-01-13 10:31:57 +01:00
TRACE ( " (%p) : Created resource %p \n " , This , object ) ;
2007-12-19 23:29:39 +01:00
TRACE ( " (%p) : Size=%d, Usage=0x%08x, FVF=%x, Pool=%d - Memory@%p, Iface@%p \n " , This , Size , Usage , FVF , Pool , object - > resource . allocatedMemory , object ) ;
2009-03-06 14:56:23 +01:00
* ppVertexBuffer = ( IWineD3DBuffer * ) object ;
2006-06-21 15:05:38 +02:00
/* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
* drawStridedFast ( half - life 2 ) .
*
* Basically converting the vertices in the buffer is quite expensive , and observations
* show that drawStridedSlow is faster than converting + uploading + drawStridedFast .
* Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers .
*
* Direct3D7 has another problem : Its vertexbuffer api doesn ' t offer a way to specify
2006-08-06 12:28:32 +02:00
* the range of vertices being locked , so each lock will require the whole buffer to be transformed .
2006-06-21 15:05:38 +02:00
* Moreover geometry data in dx7 is quite simple , so drawStridedSlow isn ' t a big hit . A plus
* is that the vertex buffers fvf can be trusted in dx7 . So only create non - converted vbos for
* dx7 apps .
* There is a IDirect3DVertexBuffer7 : : Optimize call after which the buffer can ' t be locked any
* more . In this call we can convert dx7 buffers too .
*/
2006-10-31 09:16:08 +01:00
conv = ( ( FVF & WINED3DFVF_POSITION_MASK ) = = WINED3DFVF_XYZRHW ) | | ( FVF & ( WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR ) ) ;
2007-12-19 23:29:39 +01:00
if ( ! GL_SUPPORT ( ARB_VERTEX_BUFFER_OBJECT ) ) {
TRACE ( " Not creating a vbo because GL_ARB_vertex_buffer is not supported \n " ) ;
} else if ( Pool = = WINED3DPOOL_SYSTEMMEM ) {
TRACE ( " Not creating a vbo because the vertex buffer is in system memory \n " ) ;
} else if ( Usage & WINED3DUSAGE_DYNAMIC ) {
TRACE ( " Not creating a vbo because the buffer has dynamic usage \n " ) ;
} else if ( dxVersion < = 7 & & conv ) {
TRACE ( " Not creating a vbo because dxVersion is 7 and the fvf needs conversion \n " ) ;
} else {
2009-03-06 14:56:23 +01:00
object - > flags | = WINED3D_BUFFER_CREATEBO ;
2006-06-21 15:05:38 +02:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-10-14 02:32:04 +02:00
}
2004-10-07 06:22:21 +02:00
2009-04-23 09:24:27 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer ( IWineD3DDevice * iface ,
UINT Length , DWORD Usage , WINED3DPOOL Pool , IWineD3DBuffer * * ppIndexBuffer , IUnknown * parent )
{
2004-11-24 19:13:41 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-04-09 10:50:31 +02:00
const struct GlPixelFormatDesc * format_desc = getFormatDescEntry ( WINED3DFMT_UNKNOWN , & This - > adapter - > gl_info ) ;
2009-04-06 13:38:56 +02:00
struct wined3d_buffer * object ;
2009-01-13 10:31:57 +01:00
HRESULT hr ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) Creating index buffer \n " , This ) ;
2007-02-19 15:25:32 +01:00
2004-11-24 19:13:41 +01:00
/* Allocate the storage for the device */
2009-01-13 10:31:57 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppIndexBuffer = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
2009-04-06 13:38:56 +02:00
object - > vtbl = & wined3d_buffer_vtbl ;
2009-05-29 09:13:21 +02:00
hr = resource_init ( ( IWineD3DResource * ) object , WINED3DRTYPE_BUFFER , This , Length , Usage , format_desc , Pool , parent ) ;
2009-01-13 10:31:57 +01:00
if ( FAILED ( hr ) )
{
WARN ( " Failed to initialize resource, returning %#x \n " , hr ) ;
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppIndexBuffer = NULL ;
return hr ;
}
2009-04-06 13:38:56 +02:00
object - > buffer_type_hint = GL_ELEMENT_ARRAY_BUFFER_ARB ;
2009-01-13 10:31:57 +01:00
TRACE ( " (%p) : Created resource %p \n " , This , object ) ;
2007-02-19 15:25:32 +01:00
if ( Pool ! = WINED3DPOOL_SYSTEMMEM & & ! ( Usage & WINED3DUSAGE_DYNAMIC ) & & GL_SUPPORT ( ARB_VERTEX_BUFFER_OBJECT ) ) {
2009-04-06 13:38:56 +02:00
object - > flags | = WINED3D_BUFFER_CREATEBO ;
2007-02-19 15:25:32 +01:00
}
2009-04-09 10:50:31 +02:00
TRACE ( " (%p) : Len=%d, Use=%x, Pool=%d - Memory@%p, Iface@%p \n " , This , Length , Usage ,
Pool , object , object - > resource . allocatedMemory ) ;
2009-04-06 16:46:12 +02:00
* ppIndexBuffer = ( IWineD3DBuffer * ) object ;
2004-11-24 19:13:41 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-24 19:13:41 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock ( IWineD3DDevice * iface , WINED3DSTATEBLOCKTYPE Type , IWineD3DStateBlock * * ppStateBlock , IUnknown * parent ) {
2005-07-13 16:15:54 +02:00
2004-10-21 22:59:12 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DStateBlockImpl * object ;
2009-03-25 10:12:27 +01:00
unsigned int i , j ;
2006-07-19 06:06:07 +02:00
HRESULT temp_result ;
2005-03-02 13:16:10 +01:00
2009-01-14 10:01:11 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppStateBlock = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DStateBlock_Vtbl ;
object - > wineD3DDevice = This ;
object - > parent = parent ;
object - > ref = 1 ;
object - > blockType = Type ;
* ppStateBlock = ( IWineD3DStateBlock * ) object ;
2004-10-21 22:59:12 +02:00
2007-02-14 17:46:54 +01:00
for ( i = 0 ; i < LIGHTMAP_SIZE ; i + + ) {
list_init ( & object - > lightMap [ i ] ) ;
}
2008-12-18 17:59:06 +01:00
temp_result = allocate_shader_constants ( object ) ;
if ( FAILED ( temp_result ) )
{
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
return temp_result ;
}
2004-10-21 22:59:12 +02:00
/* Special case - Used during initialization to produce a placeholder stateblock
so other functions called can update a state block */
2009-01-09 10:23:43 +01:00
if ( Type = = WINED3DSBT_INIT | | Type = = WINED3DSBT_RECORDED )
{
2004-10-23 00:27:51 +02:00
/* Don't bother increasing the reference count otherwise a device will never
2004-10-21 22:59:12 +02:00
be freed due to circular dependencies */
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-10-21 22:59:12 +02:00
}
2005-07-05 16:05:18 +02:00
/* Otherwise, might as well set the whole state block to the appropriate values */
2006-07-23 21:08:27 +02:00
if ( This - > stateBlock ! = NULL )
stateblock_copy ( ( IWineD3DStateBlock * ) object , ( IWineD3DStateBlock * ) This - > stateBlock ) ;
else
memset ( object - > streamFreq , 1 , sizeof ( object - > streamFreq ) ) ;
2005-07-05 16:05:18 +02:00
2005-07-11 12:59:41 +02:00
/* Reset the ref and type after kludging it */
2005-07-05 16:05:18 +02:00
object - > wineD3DDevice = This ;
object - > ref = 1 ;
object - > blockType = Type ;
TRACE ( " Updating changed flags appropriate for type %d \n " , Type ) ;
2005-07-26 20:49:30 +02:00
if ( Type = = WINED3DSBT_ALL ) {
2005-08-22 11:13:49 +02:00
2005-07-05 16:05:18 +02:00
TRACE ( " ALL => Pretend everything has changed \n " ) ;
2006-07-23 21:08:27 +02:00
stateblock_savedstates_set ( ( IWineD3DStateBlock * ) object , & object - > changed , TRUE ) ;
2007-02-14 17:46:54 +01:00
/* Lights are not part of the changed / set structure */
for ( j = 0 ; j < LIGHTMAP_SIZE ; j + + ) {
struct list * e ;
LIST_FOR_EACH ( e , & object - > lightMap [ j ] ) {
PLIGHTINFOEL * light = LIST_ENTRY ( e , PLIGHTINFOEL , entry ) ;
light - > changed = TRUE ;
light - > enabledChanged = TRUE ;
}
}
2007-07-31 15:04:56 +02:00
for ( j = 1 ; j < = WINEHIGHEST_RENDER_STATE ; j + + ) {
object - > contained_render_states [ j - 1 ] = j ;
}
2007-08-21 23:22:26 +02:00
object - > num_contained_render_states = WINEHIGHEST_RENDER_STATE ;
2007-07-31 15:44:13 +02:00
/* TODO: Filter unused transforms between TEXTURE8 and WORLD0? */
for ( j = 1 ; j < = HIGHEST_TRANSFORMSTATE ; j + + ) {
object - > contained_transform_states [ j - 1 ] = j ;
}
object - > num_contained_transform_states = HIGHEST_TRANSFORMSTATE ;
2007-08-03 20:26:29 +02:00
for ( j = 0 ; j < GL_LIMITS ( vshader_constantsF ) ; j + + ) {
object - > contained_vs_consts_f [ j ] = j ;
}
object - > num_contained_vs_consts_f = GL_LIMITS ( vshader_constantsF ) ;
2007-08-03 20:07:30 +02:00
for ( j = 0 ; j < MAX_CONST_I ; j + + ) {
object - > contained_vs_consts_i [ j ] = j ;
}
object - > num_contained_vs_consts_i = MAX_CONST_I ;
for ( j = 0 ; j < MAX_CONST_B ; j + + ) {
object - > contained_vs_consts_b [ j ] = j ;
}
object - > num_contained_vs_consts_b = MAX_CONST_B ;
2007-08-03 20:26:29 +02:00
for ( j = 0 ; j < GL_LIMITS ( pshader_constantsF ) ; j + + ) {
object - > contained_ps_consts_f [ j ] = j ;
}
object - > num_contained_ps_consts_f = GL_LIMITS ( pshader_constantsF ) ;
2007-08-03 20:12:54 +02:00
for ( j = 0 ; j < MAX_CONST_I ; j + + ) {
object - > contained_ps_consts_i [ j ] = j ;
}
object - > num_contained_ps_consts_i = MAX_CONST_I ;
for ( j = 0 ; j < MAX_CONST_B ; j + + ) {
object - > contained_ps_consts_b [ j ] = j ;
}
object - > num_contained_ps_consts_b = MAX_CONST_B ;
2007-08-09 17:45:29 +02:00
for ( i = 0 ; i < MAX_TEXTURES ; i + + ) {
2009-01-06 11:43:45 +01:00
for ( j = 0 ; j < = WINED3D_HIGHEST_TEXTURE_STATE ; + + j )
{
2007-08-09 17:45:29 +02:00
object - > contained_tss_states [ object - > num_contained_tss_states ] . stage = i ;
object - > contained_tss_states [ object - > num_contained_tss_states ] . state = j ;
object - > num_contained_tss_states + + ;
}
}
2007-08-03 20:23:52 +02:00
for ( i = 0 ; i < MAX_COMBINED_SAMPLERS ; i + + ) {
for ( j = 1 ; j < = WINED3D_HIGHEST_SAMPLER_STATE ; j + + ) {
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . stage = i ;
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . state = j ;
object - > num_contained_sampler_states + + ;
}
}
2007-07-31 15:04:56 +02:00
2007-08-19 20:40:44 +02:00
for ( i = 0 ; i < MAX_STREAMS ; i + + ) {
if ( object - > streamSource [ i ] ) {
2009-03-06 14:56:23 +01:00
IWineD3DBuffer_AddRef ( object - > streamSource [ i ] ) ;
2007-08-19 20:40:44 +02:00
}
}
2007-08-19 20:42:29 +02:00
if ( object - > pIndexData ) {
2009-04-06 16:46:12 +02:00
IWineD3DBuffer_AddRef ( object - > pIndexData ) ;
2007-08-19 20:42:29 +02:00
}
2007-08-20 18:56:10 +02:00
if ( object - > vertexShader ) {
IWineD3DVertexShader_AddRef ( object - > vertexShader ) ;
}
if ( object - > pixelShader ) {
IWineD3DPixelShader_AddRef ( object - > pixelShader ) ;
}
2007-08-19 20:40:44 +02:00
2005-07-26 20:49:30 +02:00
} else if ( Type = = WINED3DSBT_PIXELSTATE ) {
2005-07-05 16:05:18 +02:00
2005-08-22 11:13:49 +02:00
TRACE ( " PIXELSTATE => Pretend all pixel shates have changed \n " ) ;
2006-07-23 21:08:27 +02:00
stateblock_savedstates_set ( ( IWineD3DStateBlock * ) object , & object - > changed , FALSE ) ;
2005-09-28 12:13:00 +02:00
2005-07-05 16:05:18 +02:00
object - > changed . pixelShader = TRUE ;
2005-09-21 12:19:29 +02:00
2005-09-28 12:13:00 +02:00
/* Pixel Shader Constants */
2008-07-10 20:38:35 +02:00
for ( i = 0 ; i < GL_LIMITS ( pshader_constantsF ) ; + + i ) {
2007-08-03 20:26:29 +02:00
object - > contained_ps_consts_f [ i ] = i ;
2006-06-06 08:46:59 +02:00
object - > changed . pixelShaderConstantsF [ i ] = TRUE ;
2007-08-03 20:26:29 +02:00
}
2008-07-10 20:38:35 +02:00
object - > num_contained_ps_consts_f = GL_LIMITS ( pshader_constantsF ) ;
2007-08-03 20:12:54 +02:00
for ( i = 0 ; i < MAX_CONST_B ; + + i ) {
object - > contained_ps_consts_b [ i ] = i ;
2008-12-02 18:41:33 +01:00
object - > changed . pixelShaderConstantsB | = ( 1 < < i ) ;
2007-08-03 20:12:54 +02:00
}
object - > num_contained_ps_consts_b = MAX_CONST_B ;
for ( i = 0 ; i < MAX_CONST_I ; + + i ) {
object - > contained_ps_consts_i [ i ] = i ;
2008-12-02 18:41:33 +01:00
object - > changed . pixelShaderConstantsI | = ( 1 < < i ) ;
2007-08-03 20:12:54 +02:00
}
object - > num_contained_ps_consts_i = MAX_CONST_I ;
2007-07-31 15:04:56 +02:00
2005-07-05 16:05:18 +02:00
for ( i = 0 ; i < NUM_SAVEDPIXELSTATES_R ; i + + ) {
2009-01-05 10:10:16 +01:00
DWORD rs = SavedPixelStates_R [ i ] ;
object - > changed . renderState [ rs > > 5 ] | = 1 < < ( rs & 0x1f ) ;
object - > contained_render_states [ i ] = rs ;
2005-07-05 16:05:18 +02:00
}
2007-07-31 15:04:56 +02:00
object - > num_contained_render_states = NUM_SAVEDPIXELSTATES_R ;
2007-06-22 00:02:12 +02:00
for ( j = 0 ; j < MAX_TEXTURES ; j + + ) {
2005-09-21 12:19:29 +02:00
for ( i = 0 ; i < NUM_SAVEDPIXELSTATES_T ; i + + ) {
2009-01-06 11:43:45 +01:00
DWORD state = SavedPixelStates_T [ i ] ;
object - > changed . textureState [ j ] | = 1 < < state ;
2007-08-09 17:45:29 +02:00
object - > contained_tss_states [ object - > num_contained_tss_states ] . stage = j ;
2009-01-06 11:43:45 +01:00
object - > contained_tss_states [ object - > num_contained_tss_states ] . state = state ;
2007-08-09 17:45:29 +02:00
object - > num_contained_tss_states + + ;
2005-09-21 12:19:29 +02:00
}
}
2007-08-03 20:23:52 +02:00
for ( j = 0 ; j < MAX_COMBINED_SAMPLERS ; j + + ) {
2005-09-21 12:19:29 +02:00
for ( i = 0 ; i < NUM_SAVEDPIXELSTATES_S ; i + + ) {
2009-01-05 10:10:16 +01:00
DWORD state = SavedPixelStates_S [ i ] ;
object - > changed . samplerState [ j ] | = 1 < < state ;
2007-08-03 20:23:52 +02:00
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . stage = j ;
2009-01-05 10:10:16 +01:00
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . state = state ;
2007-08-03 20:23:52 +02:00
object - > num_contained_sampler_states + + ;
2005-09-21 12:19:29 +02:00
}
}
2007-08-20 18:56:10 +02:00
if ( object - > pixelShader ) {
IWineD3DPixelShader_AddRef ( object - > pixelShader ) ;
}
2005-07-05 16:05:18 +02:00
2007-08-19 20:40:44 +02:00
/* Pixel state blocks do not contain vertex buffers. Set them to NULL to avoid wrong refcounting
* on them . This makes releasing the buffer easier
*/
for ( i = 0 ; i < MAX_STREAMS ; i + + ) {
object - > streamSource [ i ] = NULL ;
}
2007-08-19 20:42:29 +02:00
object - > pIndexData = NULL ;
2007-08-20 18:56:10 +02:00
object - > vertexShader = NULL ;
2007-08-19 20:40:44 +02:00
2005-07-26 20:49:30 +02:00
} else if ( Type = = WINED3DSBT_VERTEXSTATE ) {
2005-07-05 16:05:18 +02:00
2005-08-22 11:13:49 +02:00
TRACE ( " VERTEXSTATE => Pretend all vertex shates have changed \n " ) ;
2006-07-23 21:08:27 +02:00
stateblock_savedstates_set ( ( IWineD3DStateBlock * ) object , & object - > changed , FALSE ) ;
2005-09-28 12:13:00 +02:00
2005-07-05 16:05:18 +02:00
object - > changed . vertexShader = TRUE ;
2005-09-28 12:13:00 +02:00
/* Vertex Shader Constants */
2007-08-03 20:26:29 +02:00
for ( i = 0 ; i < GL_LIMITS ( vshader_constantsF ) ; + + i ) {
2006-06-06 08:46:59 +02:00
object - > changed . vertexShaderConstantsF [ i ] = TRUE ;
2007-08-03 20:26:29 +02:00
object - > contained_vs_consts_f [ i ] = i ;
}
object - > num_contained_vs_consts_f = GL_LIMITS ( vshader_constantsF ) ;
2007-08-03 20:07:30 +02:00
for ( i = 0 ; i < MAX_CONST_B ; + + i ) {
object - > contained_vs_consts_b [ i ] = i ;
2008-12-02 18:41:33 +01:00
object - > changed . vertexShaderConstantsB | = ( 1 < < i ) ;
2007-08-03 20:07:30 +02:00
}
object - > num_contained_vs_consts_b = MAX_CONST_B ;
for ( i = 0 ; i < MAX_CONST_I ; + + i ) {
object - > contained_vs_consts_i [ i ] = i ;
2008-12-02 18:41:33 +01:00
object - > changed . vertexShaderConstantsI | = ( 1 < < i ) ;
2007-08-03 20:07:30 +02:00
}
object - > num_contained_vs_consts_i = MAX_CONST_I ;
2005-07-05 16:05:18 +02:00
for ( i = 0 ; i < NUM_SAVEDVERTEXSTATES_R ; i + + ) {
2009-01-05 10:10:16 +01:00
DWORD rs = SavedVertexStates_R [ i ] ;
object - > changed . renderState [ rs > > 5 ] | = 1 < < ( rs & 0x1f ) ;
object - > contained_render_states [ i ] = rs ;
2005-07-05 16:05:18 +02:00
}
2007-07-31 15:04:56 +02:00
object - > num_contained_render_states = NUM_SAVEDVERTEXSTATES_R ;
2007-06-22 00:02:12 +02:00
for ( j = 0 ; j < MAX_TEXTURES ; j + + ) {
2005-09-21 12:19:29 +02:00
for ( i = 0 ; i < NUM_SAVEDVERTEXSTATES_T ; i + + ) {
2009-01-06 11:43:45 +01:00
DWORD state = SavedVertexStates_T [ i ] ;
object - > changed . textureState [ j ] | = 1 < < state ;
2007-08-09 17:45:29 +02:00
object - > contained_tss_states [ object - > num_contained_tss_states ] . stage = j ;
2009-01-06 11:43:45 +01:00
object - > contained_tss_states [ object - > num_contained_tss_states ] . state = state ;
2007-08-09 17:45:29 +02:00
object - > num_contained_tss_states + + ;
2005-09-21 12:19:29 +02:00
}
}
2007-08-03 20:23:52 +02:00
for ( j = 0 ; j < MAX_COMBINED_SAMPLERS ; j + + ) {
2005-09-21 12:19:29 +02:00
for ( i = 0 ; i < NUM_SAVEDVERTEXSTATES_S ; i + + ) {
2009-01-05 10:10:16 +01:00
DWORD state = SavedVertexStates_S [ i ] ;
object - > changed . samplerState [ j ] | = 1 < < state ;
2007-08-03 20:23:52 +02:00
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . stage = j ;
2009-01-05 10:10:16 +01:00
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . state = state ;
2007-08-03 20:23:52 +02:00
object - > num_contained_sampler_states + + ;
2005-09-21 12:19:29 +02:00
}
}
2005-07-05 16:05:18 +02:00
2007-02-14 17:46:54 +01:00
for ( j = 0 ; j < LIGHTMAP_SIZE ; j + + ) {
struct list * e ;
LIST_FOR_EACH ( e , & object - > lightMap [ j ] ) {
PLIGHTINFOEL * light = LIST_ENTRY ( e , PLIGHTINFOEL , entry ) ;
light - > changed = TRUE ;
light - > enabledChanged = TRUE ;
2005-07-05 16:05:18 +02:00
}
}
2007-08-19 20:40:44 +02:00
for ( i = 0 ; i < MAX_STREAMS ; i + + ) {
if ( object - > streamSource [ i ] ) {
2009-03-06 14:56:23 +01:00
IWineD3DBuffer_AddRef ( object - > streamSource [ i ] ) ;
2007-08-19 20:40:44 +02:00
}
}
2007-08-20 18:56:10 +02:00
if ( object - > vertexShader ) {
IWineD3DVertexShader_AddRef ( object - > vertexShader ) ;
}
2007-08-19 20:42:29 +02:00
object - > pIndexData = NULL ;
2007-08-20 18:56:10 +02:00
object - > pixelShader = NULL ;
2005-07-05 16:05:18 +02:00
} else {
FIXME ( " Unrecognized state block type %d \n " , Type ) ;
}
TRACE ( " (%p) returning token (ptr to stateblock) of %p \n " , This , object ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-10-21 22:59:12 +02:00
}
2009-06-12 09:46:03 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface ( IWineD3DDevice * iface , UINT Width , UINT Height ,
WINED3DFORMAT Format , BOOL Lockable , BOOL Discard , UINT Level , IWineD3DSurface * * ppSurface ,
DWORD Usage , WINED3DPOOL Pool , WINED3DMULTISAMPLE_TYPE MultiSample , DWORD MultisampleQuality ,
WINED3DSURFTYPE Impl , IUnknown * parent )
2009-04-23 09:24:27 +02:00
{
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-06-15 09:06:49 +02:00
IWineD3DSurfaceImpl * object ;
2009-01-13 10:31:57 +01:00
HRESULT hr ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) Create surface \n " , This ) ;
2005-07-13 16:15:54 +02:00
2009-06-15 09:06:49 +02:00
if ( Impl = = SURFACE_OPENGL & & ! This - > adapter )
2009-06-11 10:24:30 +02:00
{
2009-06-15 09:06:49 +02:00
ERR ( " OpenGL surfaces are not available without OpenGL. \n " ) ;
return WINED3DERR_NOTAVAILABLE ;
2009-06-11 10:24:30 +02:00
}
2008-08-26 21:36:30 +02:00
2009-01-13 10:31:57 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
2009-06-15 09:06:49 +02:00
ERR ( " Failed to allocate surface memory. \n " ) ;
2009-01-13 10:31:57 +01:00
* ppSurface = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
2009-06-15 09:06:49 +02:00
hr = surface_init ( object , Impl , This - > surface_alignment , Width , Height , Level , Lockable ,
Discard , MultiSample , MultisampleQuality , This , Usage , Format , Pool , parent ) ;
2009-01-13 10:31:57 +01:00
if ( FAILED ( hr ) )
{
2009-06-15 09:06:49 +02:00
WARN ( " Failed to initialize surface, returning %#x. \n " , hr ) ;
2009-01-13 10:31:57 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppSurface = NULL ;
return hr ;
}
2009-06-15 09:06:49 +02:00
TRACE ( " (%p) : Created surface %p \n " , This , object ) ;
2009-01-13 10:31:57 +01:00
* ppSurface = ( IWineD3DSurface * ) object ;
2009-01-13 10:31:57 +01:00
return hr ;
2005-03-02 13:16:10 +01:00
}
2009-02-24 07:43:02 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateRendertargetView ( IWineD3DDevice * iface ,
IWineD3DResource * resource , IUnknown * parent , IWineD3DRendertargetView * * rendertarget_view )
{
struct wined3d_rendertarget_view * object ;
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Failed to allocate memory \n " ) ;
return E_OUTOFMEMORY ;
}
object - > vtbl = & wined3d_rendertarget_view_vtbl ;
object - > refcount = 1 ;
IWineD3DResource_AddRef ( resource ) ;
object - > resource = resource ;
object - > parent = parent ;
* rendertarget_view = ( IWineD3DRendertargetView * ) object ;
return WINED3D_OK ;
}
2009-01-16 10:14:24 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture ( IWineD3DDevice * iface ,
2009-04-23 09:24:27 +02:00
UINT Width , UINT Height , UINT Levels , DWORD Usage , WINED3DFORMAT Format ,
WINED3DPOOL Pool , IWineD3DTexture * * ppTexture , IUnknown * parent )
2009-01-16 10:14:24 +01:00
{
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
IWineD3DTextureImpl * object ;
2005-03-02 13:16:10 +01:00
HRESULT hr ;
2005-08-03 21:49:05 +02:00
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : Width %d, Height %d, Levels %d, Usage %#x \n " , This , Width , Height , Levels , Usage ) ;
2009-04-23 09:24:27 +02:00
TRACE ( " Format %#x (%s), Pool %#x, ppTexture %p, parent %p \n " ,
Format , debug_d3dformat ( Format ) , Pool , ppTexture , parent ) ;
2005-01-17 14:44:57 +01:00
2009-01-13 10:31:57 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppTexture = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DTexture_Vtbl ;
2009-06-03 10:47:25 +02:00
hr = texture_init ( object , Width , Height , Levels , This , Usage , Format , Pool , parent ) ;
2009-01-13 10:31:57 +01:00
if ( FAILED ( hr ) )
{
2009-06-03 10:47:25 +02:00
WARN ( " Failed to initialize texture, returning %#x \n " , hr ) ;
2009-01-13 10:31:57 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppTexture = NULL ;
return hr ;
}
* ppTexture = ( IWineD3DTexture * ) object ;
2009-06-03 10:47:25 +02:00
TRACE ( " (%p) : Created texture %p \n " , This , object ) ;
2005-07-13 16:15:54 +02:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-17 14:44:57 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture ( IWineD3DDevice * iface ,
2009-04-23 09:24:27 +02:00
UINT Width , UINT Height , UINT Depth , UINT Levels , DWORD Usage , WINED3DFORMAT Format ,
WINED3DPOOL Pool , IWineD3DVolumeTexture * * ppVolumeTexture , IUnknown * parent )
2009-01-16 10:14:24 +01:00
{
2005-01-17 14:44:57 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DVolumeTextureImpl * object ;
2009-01-13 10:31:57 +01:00
HRESULT hr ;
2007-10-26 13:44:16 +02:00
2009-06-03 10:47:26 +02:00
TRACE ( " (%p) : W(%u) H(%u) D(%u), Lvl(%u) Usage(%#x), Fmt(%u,%s), Pool(%s) \n " , This , Width , Height ,
Depth , Levels , Usage , Format , debug_d3dformat ( Format ) , debug_d3dpool ( Pool ) ) ;
2009-01-13 10:31:57 +01:00
2009-01-13 10:31:57 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppVolumeTexture = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DVolumeTexture_Vtbl ;
2009-06-03 10:47:26 +02:00
hr = volumetexture_init ( object , Width , Height , Depth , Levels , This , Usage , Format , Pool , parent ) ;
2009-01-13 10:31:57 +01:00
if ( FAILED ( hr ) )
{
2009-06-03 10:47:26 +02:00
WARN ( " Failed to initialize volumetexture, returning %#x \n " , hr ) ;
2009-01-13 10:31:57 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppVolumeTexture = NULL ;
return hr ;
}
2009-06-03 10:47:26 +02:00
TRACE ( " (%p) : Created volume texture %p. \n " , This , object ) ;
* ppVolumeTexture = ( IWineD3DVolumeTexture * ) object ;
2005-01-17 14:44:57 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-17 14:44:57 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume ( IWineD3DDevice * iface ,
2009-04-23 09:24:27 +02:00
UINT Width , UINT Height , UINT Depth , DWORD Usage , WINED3DFORMAT Format ,
WINED3DPOOL Pool , IWineD3DVolume * * ppVolume , IUnknown * parent )
{
2005-01-17 14:44:57 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-03-02 13:16:10 +01:00
IWineD3DVolumeImpl * object ; /** NOTE: impl ref allowed since this is a create function **/
2009-03-13 10:44:18 +01:00
const struct GlPixelFormatDesc * format_desc = getFormatDescEntry ( Format , & GLINFO_LOCATION ) ;
2009-01-13 10:31:57 +01:00
HRESULT hr ;
2005-01-17 14:44:57 +01:00
2007-10-26 13:44:16 +02:00
if ( ! GL_SUPPORT ( EXT_TEXTURE3D ) ) {
WARN ( " (%p) : Volume cannot be created - no volume texture support \n " , This ) ;
return WINED3DERR_INVALIDCALL ;
}
2009-01-13 10:31:57 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppVolume = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DVolume_Vtbl ;
2009-05-29 09:13:21 +02:00
hr = resource_init ( ( IWineD3DResource * ) object , WINED3DRTYPE_VOLUME , This ,
2009-03-13 10:44:18 +01:00
Width * Height * Depth * format_desc - > byte_count , Usage , format_desc , Pool , parent ) ;
2009-01-13 10:31:57 +01:00
if ( FAILED ( hr ) )
{
WARN ( " Failed to initialize resource, returning %#x \n " , hr ) ;
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppVolume = NULL ;
return hr ;
}
TRACE ( " (%p) : Created resource %p \n " , This , object ) ;
* ppVolume = ( IWineD3DVolume * ) object ;
2005-01-17 14:44:57 +01:00
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s) \n " , This , Width , Height ,
2005-01-17 14:44:57 +01:00
Depth , Usage , Format , debug_d3dformat ( Format ) , debug_d3dpool ( Pool ) ) ;
2005-03-02 13:16:10 +01:00
object - > currentDesc . Width = Width ;
object - > currentDesc . Height = Height ;
object - > currentDesc . Depth = Depth ;
/** Note: Volume textures cannot be dxtn, hence no need to check here **/
object - > lockable = TRUE ;
object - > locked = FALSE ;
2006-04-07 13:12:22 +02:00
memset ( & object - > lockedBox , 0 , sizeof ( WINED3DBOX ) ) ;
2005-08-03 21:49:05 +02:00
object - > dirty = TRUE ;
2009-01-14 10:01:10 +01:00
volume_add_dirty_box ( ( IWineD3DVolume * ) object , NULL ) ;
return WINED3D_OK ;
2005-01-17 14:44:57 +01:00
}
2009-01-16 10:14:24 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture ( IWineD3DDevice * iface ,
2009-04-23 09:24:27 +02:00
UINT EdgeLength , UINT Levels , DWORD Usage , WINED3DFORMAT Format ,
WINED3DPOOL Pool , IWineD3DCubeTexture * * ppCubeTexture , IUnknown * parent )
2009-01-16 10:14:24 +01:00
{
2005-08-03 21:49:05 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DCubeTextureImpl * object ; /** NOTE: impl ref allowed since this is a create function **/
HRESULT hr ;
2009-01-13 10:31:58 +01:00
2009-01-13 10:31:57 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppCubeTexture = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DCubeTexture_Vtbl ;
2009-06-03 10:47:26 +02:00
hr = cubetexture_init ( object , EdgeLength , Levels , This , Usage , Format , Pool , parent ) ;
2009-01-13 10:31:57 +01:00
if ( FAILED ( hr ) )
{
2009-06-03 10:47:26 +02:00
WARN ( " Failed to initialize cubetexture, returning %#x \n " , hr ) ;
2009-01-13 10:31:57 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppCubeTexture = NULL ;
return hr ;
}
2005-01-17 14:44:57 +01:00
TRACE ( " (%p) : Created Cube Texture %p \n " , This , object ) ;
2009-06-03 10:47:26 +02:00
* ppCubeTexture = ( IWineD3DCubeTexture * ) object ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-17 14:44:57 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery ( IWineD3DDevice * iface , WINED3DQUERYTYPE Type , IWineD3DQuery * * ppQuery , IUnknown * parent ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-03-03 14:57:15 +01:00
IWineD3DQueryImpl * object ; /*NOTE: impl ref allowed since this is a create function */
2007-02-15 13:51:24 +01:00
HRESULT hr = WINED3DERR_NOTAVAILABLE ;
2008-02-28 21:02:58 +01:00
const IWineD3DQueryVtbl * vtable ;
2005-03-03 14:57:15 +01:00
2007-02-15 13:51:24 +01:00
/* Just a check to see if we support this type of query */
switch ( Type ) {
case WINED3DQUERYTYPE_OCCLUSION :
TRACE ( " (%p) occlusion query \n " , This ) ;
if ( GL_SUPPORT ( ARB_OCCLUSION_QUERY ) )
hr = WINED3D_OK ;
else
WARN ( " Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY \n " ) ;
2008-02-28 21:03:41 +01:00
vtable = & IWineD3DOcclusionQuery_Vtbl ;
2007-02-15 13:51:24 +01:00
break ;
2007-02-16 19:14:46 +01:00
case WINED3DQUERYTYPE_EVENT :
2007-03-01 01:17:05 +01:00
if ( ! ( GL_SUPPORT ( NV_FENCE ) | | GL_SUPPORT ( APPLE_FENCE ) ) ) {
2007-03-01 00:34:33 +01:00
/* Half-Life 2 needs this query. It does not render the main menu correctly otherwise
* Pretend to support it , faking this query does not do much harm except potentially lowering performance
*/
FIXME ( " (%p) Event query: Unimplemented, but pretending to be supported \n " , This ) ;
}
2008-02-28 21:02:58 +01:00
vtable = & IWineD3DEventQuery_Vtbl ;
2007-02-16 19:14:46 +01:00
hr = WINED3D_OK ;
break ;
2007-02-15 13:51:24 +01:00
case WINED3DQUERYTYPE_VCACHE :
case WINED3DQUERYTYPE_RESOURCEMANAGER :
case WINED3DQUERYTYPE_VERTEXSTATS :
case WINED3DQUERYTYPE_TIMESTAMP :
case WINED3DQUERYTYPE_TIMESTAMPDISJOINT :
case WINED3DQUERYTYPE_TIMESTAMPFREQ :
case WINED3DQUERYTYPE_PIPELINETIMINGS :
case WINED3DQUERYTYPE_INTERFACETIMINGS :
case WINED3DQUERYTYPE_VERTEXTIMINGS :
case WINED3DQUERYTYPE_PIXELTIMINGS :
case WINED3DQUERYTYPE_BANDWIDTHTIMINGS :
case WINED3DQUERYTYPE_CACHEUTILIZATION :
default :
2008-02-28 21:02:58 +01:00
/* Use the base Query vtable until we have a special one for each query */
vtable = & IWineD3DQuery_Vtbl ;
2007-02-15 13:51:24 +01:00
FIXME ( " (%p) Unhandled query type %d \n " , This , Type ) ;
}
if ( NULL = = ppQuery | | hr ! = WINED3D_OK ) {
2005-03-02 13:16:10 +01:00
return hr ;
}
2009-01-14 10:01:11 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppQuery = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = vtable ;
object - > type = Type ;
object - > state = QUERY_CREATED ;
object - > wineD3DDevice = This ;
object - > parent = parent ;
object - > ref = 1 ;
* ppQuery = ( IWineD3DQuery * ) object ;
2005-09-21 11:43:13 +02:00
/* allocated the 'extended' data based on the type of query requested */
switch ( Type ) {
2006-10-11 03:53:30 +02:00
case WINED3DQUERYTYPE_OCCLUSION :
2007-10-12 09:32:43 +02:00
object - > extendedData = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( WineQueryOcclusionData ) ) ;
( ( WineQueryOcclusionData * ) ( object - > extendedData ) ) - > ctx = This - > activeContext ;
2006-07-25 00:51:33 +02:00
if ( GL_SUPPORT ( ARB_OCCLUSION_QUERY ) ) {
2005-09-21 11:43:13 +02:00
TRACE ( " (%p) Allocating data for an occlusion query \n " , This ) ;
2008-12-03 08:07:54 +01:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
ENTER_GL ( ) ;
2006-07-25 00:51:33 +02:00
GL_EXTCALL ( glGenQueriesARB ( 1 , & ( ( WineQueryOcclusionData * ) ( object - > extendedData ) ) - > queryId ) ) ;
2008-12-03 08:07:54 +01:00
LEAVE_GL ( ) ;
2005-09-21 11:43:13 +02:00
break ;
}
2007-03-01 00:34:33 +01:00
case WINED3DQUERYTYPE_EVENT :
2007-10-12 09:32:43 +02:00
object - > extendedData = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( WineQueryEventData ) ) ;
( ( WineQueryEventData * ) ( object - > extendedData ) ) - > ctx = This - > activeContext ;
2008-12-03 08:07:54 +01:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
ENTER_GL ( ) ;
2007-03-01 01:17:05 +01:00
if ( GL_SUPPORT ( APPLE_FENCE ) ) {
GL_EXTCALL ( glGenFencesAPPLE ( 1 , & ( ( WineQueryEventData * ) ( object - > extendedData ) ) - > fenceId ) ) ;
checkGLcall ( " glGenFencesAPPLE " ) ;
} else if ( GL_SUPPORT ( NV_FENCE ) ) {
2007-03-01 00:34:33 +01:00
GL_EXTCALL ( glGenFencesNV ( 1 , & ( ( WineQueryEventData * ) ( object - > extendedData ) ) - > fenceId ) ) ;
checkGLcall ( " glGenFencesNV " ) ;
}
2008-12-03 08:07:54 +01:00
LEAVE_GL ( ) ;
2007-03-01 00:34:33 +01:00
break ;
2006-10-11 03:53:30 +02:00
case WINED3DQUERYTYPE_VCACHE :
case WINED3DQUERYTYPE_RESOURCEMANAGER :
case WINED3DQUERYTYPE_VERTEXSTATS :
case WINED3DQUERYTYPE_TIMESTAMP :
case WINED3DQUERYTYPE_TIMESTAMPDISJOINT :
case WINED3DQUERYTYPE_TIMESTAMPFREQ :
case WINED3DQUERYTYPE_PIPELINETIMINGS :
case WINED3DQUERYTYPE_INTERFACETIMINGS :
case WINED3DQUERYTYPE_VERTEXTIMINGS :
case WINED3DQUERYTYPE_PIXELTIMINGS :
case WINED3DQUERYTYPE_BANDWIDTHTIMINGS :
case WINED3DQUERYTYPE_CACHEUTILIZATION :
2005-09-21 11:43:13 +02:00
default :
object - > extendedData = 0 ;
FIXME ( " (%p) Unhandled query type %d \n " , This , Type ) ;
}
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : Created Query %p \n " , This , object ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2007-01-18 23:41:36 +01:00
/*****************************************************************************
* IWineD3DDeviceImpl_SetupFullscreenWindow
*
* Helper function that modifies a HWND ' s Style and ExStyle for proper
* fullscreen use .
*
* Params :
* iface : Pointer to the IWineD3DDevice interface
* window : Window to setup
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-10 22:20:50 +01:00
static LONG fullscreen_style ( LONG orig_style ) {
LONG style = orig_style ;
style & = ~ WS_CAPTION ;
style & = ~ WS_THICKFRAME ;
/* Make sure the window is managed, otherwise we won't get keyboard input */
style | = WS_POPUP | WS_SYSMENU ;
return style ;
}
static LONG fullscreen_exStyle ( LONG orig_exStyle ) {
LONG exStyle = orig_exStyle ;
/* Filter out window decorations */
exStyle & = ~ WS_EX_WINDOWEDGE ;
exStyle & = ~ WS_EX_CLIENTEDGE ;
return exStyle ;
}
2008-11-24 17:23:10 +01:00
static void IWineD3DDeviceImpl_SetupFullscreenWindow ( IWineD3DDevice * iface , HWND window , UINT w , UINT h ) {
2007-01-18 23:41:36 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
LONG style , exStyle ;
/* Don't do anything if an original style is stored.
* That shouldn ' t happen
*/
TRACE ( " (%p): Setting up window %p for exclusive mode \n " , This , window ) ;
2007-02-14 17:59:08 +01:00
if ( This - > style | | This - > exStyle ) {
2007-01-18 23:41:36 +01:00
ERR ( " (%p): Want to change the window parameters of HWND %p, but "
" another style is stored for restoration afterwards \n " , This , window ) ;
}
/* Get the parameters and save them */
style = GetWindowLongW ( window , GWL_STYLE ) ;
exStyle = GetWindowLongW ( window , GWL_EXSTYLE ) ;
This - > style = style ;
This - > exStyle = exStyle ;
2008-03-10 22:20:50 +01:00
style = fullscreen_style ( style ) ;
exStyle = fullscreen_exStyle ( exStyle ) ;
2007-01-18 23:41:36 +01:00
TRACE ( " Old style was %08x,%08x, setting to %08x,%08x \n " ,
This - > style , This - > exStyle , style , exStyle ) ;
SetWindowLongW ( window , GWL_STYLE , style ) ;
SetWindowLongW ( window , GWL_EXSTYLE , exStyle ) ;
/* Inform the window about the update. */
SetWindowPos ( window , HWND_TOP , 0 , 0 ,
2008-08-21 22:51:18 +02:00
w , h , SWP_FRAMECHANGED | SWP_SHOWWINDOW ) ;
2007-01-18 23:41:36 +01:00
}
/*****************************************************************************
* IWineD3DDeviceImpl_RestoreWindow
*
* Helper function that restores a windows ' properties when taking it out
* of fullscreen mode
*
* Params :
* iface : Pointer to the IWineD3DDevice interface
* window : Window to setup
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-11-24 17:23:10 +01:00
static void IWineD3DDeviceImpl_RestoreWindow ( IWineD3DDevice * iface , HWND window ) {
2007-01-18 23:41:36 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-03-10 22:20:50 +01:00
LONG style , exStyle ;
2007-01-18 23:41:36 +01:00
/* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
* switch , do nothing
*/
if ( ! This - > style & & ! This - > exStyle ) return ;
TRACE ( " (%p): Restoring window settings of window %p to %08x, %08x \n " ,
This , window , This - > style , This - > exStyle ) ;
2008-03-10 22:20:50 +01:00
style = GetWindowLongW ( window , GWL_STYLE ) ;
exStyle = GetWindowLongW ( window , GWL_EXSTYLE ) ;
/* Only restore the style if the application didn't modify it during the fullscreen phase.
* Some applications change it before calling Reset ( ) when switching between windowed and
* fullscreen modes ( HL2 ) , some depend on the original style ( Eve Online )
*/
if ( style = = fullscreen_style ( This - > style ) & &
exStyle = = fullscreen_style ( This - > exStyle ) ) {
SetWindowLongW ( window , GWL_STYLE , This - > style ) ;
SetWindowLongW ( window , GWL_EXSTYLE , This - > exStyle ) ;
}
2007-01-18 23:41:36 +01:00
/* Delete the old values */
This - > style = 0 ;
This - > exStyle = 0 ;
/* Inform the window about the update */
SetWindowPos ( window , 0 /* InsertAfter, ignored */ ,
0 , 0 , 0 , 0 , /* Pos, Size, ignored */
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER ) ;
}
2005-03-02 13:16:10 +01:00
/* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
2009-01-16 10:14:24 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain ( IWineD3DDevice * iface ,
WINED3DPRESENT_PARAMETERS * pPresentationParameters , IWineD3DSwapChain * * ppSwapChain ,
IUnknown * parent , WINED3DSURFTYPE surface_type )
2008-10-28 09:27:20 +01:00
{
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-06-23 13:05:24 +02:00
HDC hDc ;
IWineD3DSwapChainImpl * object ; /** NOTE: impl ref allowed since this is a create function **/
2008-10-07 16:01:01 +02:00
HRESULT hr ;
2007-02-12 19:22:41 +01:00
IUnknown * bufferParent ;
2007-10-26 02:16:03 +02:00
BOOL displaymode_set = FALSE ;
2007-12-06 23:43:25 +01:00
WINED3DDISPLAYMODE Mode ;
2009-03-13 10:44:18 +01:00
const struct GlPixelFormatDesc * format_desc ;
2005-06-23 13:05:24 +02:00
2008-01-23 15:16:30 +01:00
TRACE ( " (%p) : Created Additional Swap Chain \n " , This ) ;
2005-06-23 13:05:24 +02:00
/** FIXME: Test under windows to find out what the life cycle of a swap chain is,
* does a device hold a reference to a swap chain giving them a lifetime of the device
2005-11-23 20:14:43 +01:00
* or does the swap chain notify the device of its destruction .
2005-06-23 13:05:24 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-05-24 11:34:30 +02:00
/* Check the params */
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX ) {
ERR ( " App requested %d back buffers, this is not supported for now \n " , pPresentationParameters - > BackBufferCount ) ;
2006-05-24 11:34:30 +02:00
return WINED3DERR_INVALIDCALL ;
2007-02-15 22:36:50 +01:00
} else if ( pPresentationParameters - > BackBufferCount > 1 ) {
2006-06-15 12:54:19 +02:00
FIXME ( " The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible \n " ) ;
2006-05-24 11:34:30 +02:00
}
2009-01-14 10:01:11 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppSwapChain = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
2008-08-05 21:23:00 +02:00
switch ( surface_type ) {
case SURFACE_GDI :
object - > lpVtbl = & IWineGDISwapChain_Vtbl ;
break ;
case SURFACE_OPENGL :
object - > lpVtbl = & IWineD3DSwapChain_Vtbl ;
break ;
case SURFACE_UNKNOWN :
FIXME ( " Caller tried to create a SURFACE_UNKNOWN swapchain \n " ) ;
2009-01-14 10:01:12 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
2008-08-05 21:23:00 +02:00
return WINED3DERR_INVALIDCALL ;
}
2009-01-14 10:01:11 +01:00
object - > wineD3DDevice = This ;
object - > parent = parent ;
object - > ref = 1 ;
* ppSwapChain = ( IWineD3DSwapChain * ) object ;
2005-06-23 13:05:24 +02:00
/*********************
* Lookup the window Handle and the relating X window handle
* * * * * * * * * * * * * * * * * * * */
/* Setup hwnd we are using, plus which display this equates to */
2007-02-15 22:36:50 +01:00
object - > win_handle = pPresentationParameters - > hDeviceWindow ;
2005-06-23 13:05:24 +02:00
if ( ! object - > win_handle ) {
object - > win_handle = This - > createParms . hFocusWindow ;
}
2008-08-04 21:16:49 +02:00
if ( ! pPresentationParameters - > Windowed & & object - > win_handle ) {
IWineD3DDeviceImpl_SetupFullscreenWindow ( iface , object - > win_handle ,
pPresentationParameters - > BackBufferWidth ,
pPresentationParameters - > BackBufferHeight ) ;
2008-08-05 21:24:10 +02:00
}
2005-06-23 13:05:24 +02:00
hDc = GetDC ( object - > win_handle ) ;
2007-08-08 03:09:38 +02:00
TRACE ( " Using hDc %p \n " , hDc ) ;
2005-06-23 13:05:24 +02:00
2007-08-08 03:09:38 +02:00
if ( NULL = = hDc ) {
WARN ( " Failed to get a HDc for Window %p \n " , object - > win_handle ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_NOTAVAILABLE ;
2005-06-23 13:05:24 +02:00
}
2006-12-08 16:13:15 +01:00
2007-12-06 23:43:25 +01:00
/* Get info on the current display setup */
IWineD3D_GetAdapterDisplayMode ( This - > wineD3D , This - > adapter - > num , & Mode ) ;
object - > orig_width = Mode . Width ;
object - > orig_height = Mode . Height ;
object - > orig_fmt = Mode . Format ;
2009-03-13 10:44:18 +01:00
format_desc = getFormatDescEntry ( Mode . Format , & GLINFO_LOCATION ) ;
2006-12-08 16:13:15 +01:00
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > Windowed & &
( ( pPresentationParameters - > BackBufferWidth = = 0 ) | |
2007-08-28 22:37:37 +02:00
( pPresentationParameters - > BackBufferHeight = = 0 ) | |
( pPresentationParameters - > BackBufferFormat = = WINED3DFMT_UNKNOWN ) ) ) {
2005-06-23 13:05:24 +02:00
2007-02-12 19:22:41 +01:00
RECT Rect ;
GetClientRect ( object - > win_handle , & Rect ) ;
2005-06-23 13:05:24 +02:00
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > BackBufferWidth = = 0 ) {
pPresentationParameters - > BackBufferWidth = Rect . right ;
TRACE ( " Updating width to %d \n " , pPresentationParameters - > BackBufferWidth ) ;
2007-02-12 19:22:41 +01:00
}
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > BackBufferHeight = = 0 ) {
pPresentationParameters - > BackBufferHeight = Rect . bottom ;
TRACE ( " Updating height to %d \n " , pPresentationParameters - > BackBufferHeight ) ;
2005-06-23 13:05:24 +02:00
}
2007-08-24 23:44:00 +02:00
if ( pPresentationParameters - > BackBufferFormat = = WINED3DFMT_UNKNOWN ) {
pPresentationParameters - > BackBufferFormat = object - > orig_fmt ;
TRACE ( " Updating format to %s \n " , debug_d3dformat ( object - > orig_fmt ) ) ;
}
2005-06-23 13:05:24 +02:00
}
2007-02-12 19:22:41 +01:00
/* Put the correct figures in the presentation parameters */
TRACE ( " Copying across presentation parameters \n " ) ;
2007-02-15 22:36:50 +01:00
object - > presentParms = * pPresentationParameters ;
2005-06-23 13:05:24 +02:00
2007-02-12 19:22:41 +01:00
TRACE ( " calling rendertarget CB \n " ) ;
2009-01-16 10:14:24 +01:00
hr = IWineD3DDeviceParent_CreateRenderTarget ( This - > device_parent , parent ,
object - > presentParms . BackBufferWidth , object - > presentParms . BackBufferHeight ,
object - > presentParms . BackBufferFormat , object - > presentParms . MultiSampleType ,
object - > presentParms . MultiSampleQuality , TRUE /* Lockable */ , & object - > frontBuffer ) ;
2008-10-07 16:01:01 +02:00
if ( SUCCEEDED ( hr ) ) {
2007-02-12 19:22:41 +01:00
IWineD3DSurface_SetContainer ( object - > frontBuffer , ( IWineD3DBase * ) object ) ;
2009-03-25 10:12:27 +01:00
( ( IWineD3DSurfaceImpl * ) object - > frontBuffer ) - > Flags | = SFLAG_SWAPCHAIN ;
2008-08-05 21:23:00 +02:00
if ( surface_type = = SURFACE_OPENGL ) {
IWineD3DSurface_ModifyLocation ( object - > frontBuffer , SFLAG_INDRAWABLE , TRUE ) ;
}
2007-02-12 19:22:41 +01:00
} else {
ERR ( " Failed to create the front buffer \n " ) ;
goto error ;
2005-06-23 13:05:24 +02:00
}
/*********************
* Windowed / Fullscreen
* * * * * * * * * * * * * * * * * * */
/**
2005-07-11 12:59:41 +02:00
* TODO : MSDN says that we are only allowed one fullscreen swapchain per device ,
2005-11-23 20:14:43 +01:00
* so we should really check to see if there is a fullscreen swapchain already
2005-07-11 12:59:41 +02:00
* I think Windows and X have different ideas about fullscreen , does a single head count as full screen ?
2005-06-23 13:05:24 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-02-15 22:36:50 +01:00
if ( ! pPresentationParameters - > Windowed ) {
2007-12-11 16:40:07 +01:00
WINED3DDISPLAYMODE mode ;
2005-06-23 13:05:24 +02:00
/* Change the display settings */
2007-12-11 16:40:07 +01:00
mode . Width = pPresentationParameters - > BackBufferWidth ;
mode . Height = pPresentationParameters - > BackBufferHeight ;
mode . Format = pPresentationParameters - > BackBufferFormat ;
mode . RefreshRate = pPresentationParameters - > FullScreen_RefreshRateInHz ;
2006-12-29 20:25:25 +01:00
2007-12-11 16:40:07 +01:00
IWineD3DDevice_SetDisplayMode ( iface , 0 , & mode ) ;
displaymode_set = TRUE ;
2005-06-23 13:05:24 +02:00
}
2007-10-26 02:16:03 +02:00
/**
* Create an opengl context for the display visual
* NOTE : the visual is chosen as the window is created and the glcontext cannot
* use different properties after that point in time . FIXME : How to handle when requested format
* doesn ' t match actual visual ? Cannot choose one here - code removed as it ONLY works if the one
* it chooses is identical to the one already being used !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
object - > context = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( object - > context ) ) ;
2008-10-15 13:35:31 +02:00
if ( ! object - > context ) {
ERR ( " Failed to create the context array \n " ) ;
hr = E_OUTOFMEMORY ;
goto error ;
}
2007-10-26 02:16:03 +02:00
object - > num_contexts = 1 ;
2008-08-05 21:23:00 +02:00
if ( surface_type = = SURFACE_OPENGL ) {
object - > context [ 0 ] = CreateContext ( This , ( IWineD3DSurfaceImpl * ) object - > frontBuffer , object - > win_handle , FALSE /* pbuffer */ , pPresentationParameters ) ;
if ( ! object - > context [ 0 ] ) {
ERR ( " Failed to create a new context \n " ) ;
hr = WINED3DERR_NOTAVAILABLE ;
goto error ;
} else {
TRACE ( " Context created (HWND=%p, glContext=%p) \n " ,
object - > win_handle , object - > context [ 0 ] - > glCtx ) ;
}
2007-10-26 02:16:03 +02:00
}
2005-06-23 13:05:24 +02:00
/*********************
* Create the back , front and stencil buffers
* * * * * * * * * * * * * * * * * * */
2006-05-13 23:33:00 +02:00
if ( object - > presentParms . BackBufferCount > 0 ) {
2008-11-20 23:13:48 +01:00
UINT i ;
2006-06-15 12:54:19 +02:00
object - > backBuffer = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( IWineD3DSurface * ) * object - > presentParms . BackBufferCount ) ;
if ( ! object - > backBuffer ) {
ERR ( " Out of memory \n " ) ;
2007-02-12 19:22:41 +01:00
hr = E_OUTOFMEMORY ;
goto error ;
2006-06-15 12:54:19 +02:00
}
for ( i = 0 ; i < object - > presentParms . BackBufferCount ; i + + ) {
TRACE ( " calling rendertarget CB \n " ) ;
2009-01-16 10:14:24 +01:00
hr = IWineD3DDeviceParent_CreateRenderTarget ( This - > device_parent , parent ,
object - > presentParms . BackBufferWidth , object - > presentParms . BackBufferHeight ,
object - > presentParms . BackBufferFormat , object - > presentParms . MultiSampleType ,
object - > presentParms . MultiSampleQuality , TRUE /* Lockable */ , & object - > backBuffer [ i ] ) ;
2008-10-07 16:01:01 +02:00
if ( SUCCEEDED ( hr ) ) {
2006-06-15 12:54:19 +02:00
IWineD3DSurface_SetContainer ( object - > backBuffer [ i ] , ( IWineD3DBase * ) object ) ;
2009-03-25 10:12:27 +01:00
( ( IWineD3DSurfaceImpl * ) object - > backBuffer [ i ] ) - > Flags | = SFLAG_SWAPCHAIN ;
2006-06-15 12:54:19 +02:00
} else {
2007-02-12 19:22:41 +01:00
ERR ( " Cannot create new back buffer \n " ) ;
goto error ;
2006-06-15 12:54:19 +02:00
}
2008-08-05 21:23:00 +02:00
if ( surface_type = = SURFACE_OPENGL ) {
ENTER_GL ( ) ;
glDrawBuffer ( GL_BACK ) ;
checkGLcall ( " glDrawBuffer(GL_BACK) " ) ;
LEAVE_GL ( ) ;
}
2006-06-15 12:54:19 +02:00
}
2006-05-13 23:33:00 +02:00
} else {
object - > backBuffer = NULL ;
/* Single buffering - draw to front buffer */
2008-08-05 21:23:00 +02:00
if ( surface_type = = SURFACE_OPENGL ) {
ENTER_GL ( ) ;
glDrawBuffer ( GL_FRONT ) ;
checkGLcall ( " glDrawBuffer(GL_FRONT) " ) ;
LEAVE_GL ( ) ;
}
2006-05-13 23:33:00 +02:00
}
2005-06-23 13:05:24 +02:00
/* Under directX swapchains share the depth stencil, so only create one depth-stencil */
2008-10-07 16:01:01 +02:00
if ( pPresentationParameters - > EnableAutoDepthStencil & & surface_type = = SURFACE_OPENGL ) {
2005-06-23 13:05:24 +02:00
TRACE ( " Creating depth stencil buffer \n " ) ;
2007-11-10 00:19:19 +01:00
if ( This - > auto_depth_stencil_buffer = = NULL ) {
2009-01-16 10:14:24 +01:00
hr = IWineD3DDeviceParent_CreateDepthStencilSurface ( This - > device_parent , parent ,
object - > presentParms . BackBufferWidth , object - > presentParms . BackBufferHeight ,
object - > presentParms . AutoDepthStencilFormat , object - > presentParms . MultiSampleType ,
object - > presentParms . MultiSampleQuality , FALSE /* FIXME: Discard */ ,
& This - > auto_depth_stencil_buffer ) ;
2008-10-07 16:01:01 +02:00
if ( SUCCEEDED ( hr ) ) {
2007-11-10 00:19:19 +01:00
IWineD3DSurface_SetContainer ( This - > auto_depth_stencil_buffer , 0 ) ;
2008-10-07 16:01:01 +02:00
} else {
ERR ( " Failed to create the auto depth stencil \n " ) ;
goto error ;
}
2005-06-23 13:05:24 +02:00
}
}
2008-07-01 18:17:38 +02:00
IWineD3DSwapChain_GetGammaRamp ( ( IWineD3DSwapChain * ) object , & object - > orig_gamma ) ;
2007-02-12 19:22:41 +01:00
TRACE ( " Created swapchain %p \n " , object ) ;
2008-09-22 14:52:36 +02:00
TRACE ( " FrontBuf @ %p, BackBuf @ %p, DepthStencil %d \n " , object - > frontBuffer , object - > backBuffer ? object - > backBuffer [ 0 ] : NULL , pPresentationParameters - > EnableAutoDepthStencil ) ;
2007-02-12 19:22:41 +01:00
return WINED3D_OK ;
2005-06-23 13:05:24 +02:00
2007-02-12 19:22:41 +01:00
error :
2007-10-26 02:16:03 +02:00
if ( displaymode_set ) {
DEVMODEW devmode ;
RECT clip_rc ;
SetRect ( & clip_rc , 0 , 0 , object - > orig_width , object - > orig_height ) ;
ClipCursor ( NULL ) ;
/* Change the display settings */
memset ( & devmode , 0 , sizeof ( devmode ) ) ;
devmode . dmSize = sizeof ( devmode ) ;
devmode . dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT ;
2009-03-13 10:44:18 +01:00
devmode . dmBitsPerPel = format_desc - > byte_count * 8 ;
2007-10-26 02:16:03 +02:00
devmode . dmPelsWidth = object - > orig_width ;
devmode . dmPelsHeight = object - > orig_height ;
ChangeDisplaySettingsExW ( This - > adapter - > DeviceName , & devmode , NULL , CDS_FULLSCREEN , NULL ) ;
}
2007-02-12 19:22:41 +01:00
if ( object - > backBuffer ) {
2008-11-20 23:13:48 +01:00
UINT i ;
2007-02-12 19:22:41 +01:00
for ( i = 0 ; i < object - > presentParms . BackBufferCount ; i + + ) {
if ( object - > backBuffer [ i ] ) {
IWineD3DSurface_GetParent ( object - > backBuffer [ i ] , & bufferParent ) ;
IUnknown_Release ( bufferParent ) ; /* once for the get parent */
if ( IUnknown_Release ( bufferParent ) > 0 ) {
FIXME ( " (%p) Something's still holding the back buffer \n " , This ) ;
2006-06-15 12:54:19 +02:00
}
2005-06-23 13:05:24 +02:00
}
}
2007-02-12 19:22:41 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , object - > backBuffer ) ;
object - > backBuffer = NULL ;
}
2008-10-15 13:35:31 +02:00
if ( object - > context & & object - > context [ 0 ] )
2007-03-04 17:31:06 +01:00
DestroyContext ( This , object - > context [ 0 ] ) ;
2007-02-12 19:22:41 +01:00
if ( object - > frontBuffer ) {
IWineD3DSurface_GetParent ( object - > frontBuffer , & bufferParent ) ;
IUnknown_Release ( bufferParent ) ; /* once for the get parent */
if ( IUnknown_Release ( bufferParent ) > 0 ) {
FIXME ( " (%p) Something's still holding the front buffer \n " , This ) ;
2005-06-23 13:05:24 +02:00
}
}
2007-03-07 22:16:48 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
2005-06-23 13:05:24 +02:00
return hr ;
2005-03-02 13:16:10 +01:00
}
2005-07-11 12:59:41 +02:00
/** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
2006-06-10 13:15:32 +02:00
static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-05-24 11:34:30 +02:00
TRACE ( " (%p) \n " , This ) ;
2005-06-23 13:05:24 +02:00
2006-05-24 11:34:30 +02:00
return This - > NumberOfSwapChains ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain ( IWineD3DDevice * iface , UINT iSwapChain , IWineD3DSwapChain * * pSwapChain ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-11-10 13:14:56 +01:00
TRACE ( " (%p) : swapchain %d \n " , This , iSwapChain ) ;
2005-06-23 13:05:24 +02:00
2006-05-24 11:34:30 +02:00
if ( iSwapChain < This - > NumberOfSwapChains ) {
* pSwapChain = This - > swapchains [ iSwapChain ] ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_AddRef ( * pSwapChain ) ;
2006-05-24 11:34:30 +02:00
TRACE ( " (%p) returning %p \n " , This , * pSwapChain ) ;
return WINED3D_OK ;
} else {
TRACE ( " Swapchain out of range \n " ) ;
* pSwapChain = NULL ;
return WINED3DERR_INVALIDCALL ;
2005-07-27 17:33:17 +02:00
}
2005-03-02 13:16:10 +01:00
}
/*****
* Vertex Declaration
* * * * */
2007-02-13 23:12:36 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration ( IWineD3DDevice * iface , IWineD3DVertexDeclaration * * ppVertexDeclaration ,
2008-01-07 17:17:04 +01:00
IUnknown * parent , const WINED3DVERTEXELEMENT * elements , UINT element_count ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DVertexDeclarationImpl * object = NULL ;
2006-04-07 12:51:12 +02:00
HRESULT hr = WINED3D_OK ;
2007-02-13 23:12:36 +01:00
TRACE ( " (%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p \n " ,
This , ( ( IWineD3DImpl * ) This - > wineD3D ) - > dxVersion , elements , element_count , ppVertexDeclaration ) ;
2009-01-14 10:01:11 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppVertexDeclaration = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DVertexDeclaration_Vtbl ;
object - > wineD3DDevice = This ;
object - > parent = parent ;
object - > ref = 1 ;
* ppVertexDeclaration = ( IWineD3DVertexDeclaration * ) object ;
2005-03-02 13:16:10 +01:00
2009-03-27 10:25:55 +01:00
hr = vertexdeclaration_init ( object , elements , element_count ) ;
2007-12-20 20:48:03 +01:00
if ( FAILED ( hr ) ) {
2008-09-18 14:57:54 +02:00
IWineD3DVertexDeclaration_Release ( ( IWineD3DVertexDeclaration * ) object ) ;
2007-12-20 20:48:03 +01:00
* ppVertexDeclaration = NULL ;
}
2005-03-02 13:16:10 +01:00
return hr ;
}
2008-01-07 17:17:04 +01:00
static unsigned int ConvertFvfToDeclaration ( IWineD3DDeviceImpl * This , /* For the GL info, which has the type table */
DWORD fvf , WINED3DVERTEXELEMENT * * ppVertexElements ) {
2007-04-25 17:04:46 +02:00
unsigned int idx , idx2 ;
unsigned int offset ;
BOOL has_pos = ( fvf & WINED3DFVF_POSITION_MASK ) ! = 0 ;
BOOL has_blend = ( fvf & WINED3DFVF_XYZB5 ) > WINED3DFVF_XYZRHW ;
BOOL has_blend_idx = has_blend & &
( ( ( fvf & WINED3DFVF_XYZB5 ) = = WINED3DFVF_XYZB5 ) | |
( fvf & WINED3DFVF_LASTBETA_D3DCOLOR ) | |
( fvf & WINED3DFVF_LASTBETA_UBYTE4 ) ) ;
BOOL has_normal = ( fvf & WINED3DFVF_NORMAL ) ! = 0 ;
BOOL has_psize = ( fvf & WINED3DFVF_PSIZE ) ! = 0 ;
BOOL has_diffuse = ( fvf & WINED3DFVF_DIFFUSE ) ! = 0 ;
BOOL has_specular = ( fvf & WINED3DFVF_SPECULAR ) ! = 0 ;
DWORD num_textures = ( fvf & WINED3DFVF_TEXCOUNT_MASK ) > > WINED3DFVF_TEXCOUNT_SHIFT ;
2008-08-20 17:51:45 +02:00
DWORD texcoords = ( fvf & 0xFFFF0000 ) > > 16 ;
2007-04-25 17:04:46 +02:00
WINED3DVERTEXELEMENT * elements = NULL ;
unsigned int size ;
DWORD num_blends = 1 + ( ( ( fvf & WINED3DFVF_XYZB5 ) - WINED3DFVF_XYZB1 ) > > 1 ) ;
if ( has_blend_idx ) num_blends - - ;
/* Compute declaration size */
size = has_pos + ( has_blend & & num_blends > 0 ) + has_blend_idx + has_normal +
2009-03-27 10:25:56 +01:00
has_psize + has_diffuse + has_specular + num_textures ;
2007-04-25 17:04:46 +02:00
/* convert the declaration */
elements = HeapAlloc ( GetProcessHeap ( ) , 0 , size * sizeof ( WINED3DVERTEXELEMENT ) ) ;
2009-03-27 10:25:56 +01:00
if ( ! elements ) return ~ 0U ;
2007-04-25 17:04:46 +02:00
idx = 0 ;
if ( has_pos ) {
if ( ! has_blend & & ( fvf & WINED3DFVF_XYZRHW ) ) {
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32G32B32A32_FLOAT ;
elements [ idx ] . usage = WINED3DDECLUSAGE_POSITIONT ;
2007-04-25 17:04:46 +02:00
}
2008-12-29 16:31:22 +01:00
else if ( ( fvf & WINED3DFVF_XYZW ) = = WINED3DFVF_XYZW ) {
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32G32B32A32_FLOAT ;
elements [ idx ] . usage = WINED3DDECLUSAGE_POSITION ;
2008-12-29 16:31:22 +01:00
}
2007-04-25 17:04:46 +02:00
else {
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32G32B32_FLOAT ;
elements [ idx ] . usage = WINED3DDECLUSAGE_POSITION ;
2007-04-25 17:04:46 +02:00
}
2009-03-27 10:25:56 +01:00
elements [ idx ] . usage_idx = 0 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
if ( has_blend & & ( num_blends > 0 ) ) {
if ( ( ( fvf & WINED3DFVF_XYZB5 ) = = WINED3DFVF_XYZB2 ) & & ( fvf & WINED3DFVF_LASTBETA_D3DCOLOR ) )
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_A8R8G8B8 ;
2008-11-03 00:38:14 +01:00
else {
switch ( num_blends ) {
2009-03-27 10:25:56 +01:00
case 1 : elements [ idx ] . format = WINED3DFMT_R32_FLOAT ; break ;
case 2 : elements [ idx ] . format = WINED3DFMT_R32G32_FLOAT ; break ;
case 3 : elements [ idx ] . format = WINED3DFMT_R32G32B32_FLOAT ; break ;
case 4 : elements [ idx ] . format = WINED3DFMT_R32G32B32A32_FLOAT ; break ;
2008-11-03 00:38:14 +01:00
default :
ERR ( " Unexpected amount of blend values: %u \n " , num_blends ) ;
}
}
2009-03-27 10:25:56 +01:00
elements [ idx ] . usage = WINED3DDECLUSAGE_BLENDWEIGHT ;
elements [ idx ] . usage_idx = 0 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
if ( has_blend_idx ) {
if ( fvf & WINED3DFVF_LASTBETA_UBYTE4 | |
( ( ( fvf & WINED3DFVF_XYZB5 ) = = WINED3DFVF_XYZB2 ) & & ( fvf & WINED3DFVF_LASTBETA_D3DCOLOR ) ) )
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R8G8B8A8_UINT ;
2007-04-25 17:04:46 +02:00
else if ( fvf & WINED3DFVF_LASTBETA_D3DCOLOR )
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_A8R8G8B8 ;
2007-04-25 17:04:46 +02:00
else
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32_FLOAT ;
elements [ idx ] . usage = WINED3DDECLUSAGE_BLENDINDICES ;
elements [ idx ] . usage_idx = 0 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
if ( has_normal ) {
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32G32B32_FLOAT ;
elements [ idx ] . usage = WINED3DDECLUSAGE_NORMAL ;
elements [ idx ] . usage_idx = 0 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
if ( has_psize ) {
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32_FLOAT ;
elements [ idx ] . usage = WINED3DDECLUSAGE_PSIZE ;
elements [ idx ] . usage_idx = 0 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
if ( has_diffuse ) {
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_A8R8G8B8 ;
elements [ idx ] . usage = WINED3DDECLUSAGE_COLOR ;
elements [ idx ] . usage_idx = 0 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
if ( has_specular ) {
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_A8R8G8B8 ;
elements [ idx ] . usage = WINED3DDECLUSAGE_COLOR ;
elements [ idx ] . usage_idx = 1 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
for ( idx2 = 0 ; idx2 < num_textures ; idx2 + + ) {
unsigned int numcoords = ( texcoords > > ( idx2 * 2 ) ) & 0x03 ;
switch ( numcoords ) {
case WINED3DFVF_TEXTUREFORMAT1 :
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32_FLOAT ;
2007-04-25 17:04:46 +02:00
break ;
case WINED3DFVF_TEXTUREFORMAT2 :
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32G32_FLOAT ;
2007-04-25 17:04:46 +02:00
break ;
case WINED3DFVF_TEXTUREFORMAT3 :
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32G32B32_FLOAT ;
2007-04-25 17:04:46 +02:00
break ;
case WINED3DFVF_TEXTUREFORMAT4 :
2009-03-27 10:25:56 +01:00
elements [ idx ] . format = WINED3DFMT_R32G32B32A32_FLOAT ;
2007-04-25 17:04:46 +02:00
break ;
}
2009-03-27 10:25:56 +01:00
elements [ idx ] . usage = WINED3DDECLUSAGE_TEXCOORD ;
elements [ idx ] . usage_idx = idx2 ;
2007-04-25 17:04:46 +02:00
idx + + ;
}
/* Now compute offsets, and initialize the rest of the fields */
2009-03-27 10:25:56 +01:00
for ( idx = 0 , offset = 0 ; idx < size ; + + idx )
{
2009-03-27 10:25:56 +01:00
const struct GlPixelFormatDesc * format_desc = getFormatDescEntry ( elements [ idx ] . format , & This - > adapter - > gl_info ) ;
elements [ idx ] . input_slot = 0 ;
elements [ idx ] . method = WINED3DDECLMETHOD_DEFAULT ;
elements [ idx ] . offset = offset ;
offset + = format_desc - > component_count * format_desc - > component_size ;
2007-04-25 17:04:46 +02:00
}
* ppVertexElements = elements ;
return size ;
}
2007-04-22 11:52:11 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF ( IWineD3DDevice * iface , IWineD3DVertexDeclaration * * ppVertexDeclaration , IUnknown * Parent , DWORD Fvf ) {
2007-04-25 17:04:46 +02:00
WINED3DVERTEXELEMENT * elements = NULL ;
2007-12-19 02:51:53 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-01-07 17:17:04 +01:00
unsigned int size ;
2007-04-25 17:04:46 +02:00
DWORD hr ;
2007-12-19 02:51:53 +01:00
size = ConvertFvfToDeclaration ( This , Fvf , & elements ) ;
2009-03-27 10:25:56 +01:00
if ( size = = ~ 0U ) return WINED3DERR_OUTOFVIDEOMEMORY ;
2007-04-25 17:04:46 +02:00
hr = IWineD3DDevice_CreateVertexDeclaration ( iface , ppVertexDeclaration , Parent , elements , size ) ;
HeapFree ( GetProcessHeap ( ) , 0 , elements ) ;
if ( hr ! = S_OK ) return hr ;
return WINED3D_OK ;
2007-04-22 11:52:11 +02:00
}
2009-05-26 09:15:12 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader ( IWineD3DDevice * iface ,
2009-05-28 08:44:21 +02:00
const DWORD * pFunction , const struct wined3d_shader_signature * output_signature ,
2009-05-26 09:15:12 +02:00
IWineD3DVertexShader * * ppVertexShader , IUnknown * parent )
{
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DVertexShaderImpl * object ; /* NOTE: impl usage is ok, this is a create */
2006-04-07 12:51:12 +02:00
HRESULT hr = WINED3D_OK ;
2008-12-15 16:35:13 +01:00
if ( ! pFunction ) return WINED3DERR_INVALIDCALL ;
2009-01-12 10:17:50 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppVertexShader = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DVertexShader_Vtbl ;
object - > parent = parent ;
2009-05-05 09:38:03 +02:00
shader_init ( & object - > baseShader , iface ) ;
2009-01-12 10:17:50 +01:00
list_add_head ( & This - > shaders , & object - > baseShader . shader_list_entry ) ;
2009-01-12 10:17:50 +01:00
* ppVertexShader = ( IWineD3DVertexShader * ) object ;
2005-03-02 13:16:10 +01:00
2009-01-12 10:17:50 +01:00
TRACE ( " (%p) : Created vertex shader %p \n " , This , * ppVertexShader ) ;
2006-03-16 22:42:00 +01:00
2009-05-26 09:15:12 +02:00
hr = IWineD3DVertexShader_SetFunction ( * ppVertexShader , pFunction , output_signature ) ;
2009-01-12 10:17:50 +01:00
if ( FAILED ( hr ) )
{
WARN ( " (%p) : Failed to set function, returning %#x \n " , iface , hr ) ;
2005-12-09 11:23:52 +01:00
IWineD3DVertexShader_Release ( * ppVertexShader ) ;
2009-01-12 10:17:50 +01:00
* ppVertexShader = NULL ;
return hr ;
2005-12-09 11:23:52 +01:00
}
2009-01-12 10:17:50 +01:00
return hr ;
2005-03-02 13:16:10 +01:00
}
2009-05-08 17:44:25 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader ( IWineD3DDevice * iface ,
const DWORD * pFunction , const struct wined3d_shader_signature * output_signature ,
IWineD3DPixelShader * * ppPixelShader , IUnknown * parent )
{
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-25 21:24:21 +02:00
IWineD3DPixelShaderImpl * object ; /* NOTE: impl allowed, this is a create */
2006-04-07 12:51:12 +02:00
HRESULT hr = WINED3D_OK ;
2005-08-25 21:24:21 +02:00
2008-12-15 16:35:13 +01:00
if ( ! pFunction ) return WINED3DERR_INVALIDCALL ;
2009-01-12 10:17:50 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object )
{
ERR ( " Out of memory \n " ) ;
* ppPixelShader = NULL ;
return WINED3DERR_OUTOFVIDEOMEMORY ;
}
object - > lpVtbl = & IWineD3DPixelShader_Vtbl ;
object - > parent = parent ;
2009-05-05 09:38:03 +02:00
shader_init ( & object - > baseShader , iface ) ;
2009-01-12 10:17:50 +01:00
list_add_head ( & This - > shaders , & object - > baseShader . shader_list_entry ) ;
2009-01-12 10:17:50 +01:00
* ppPixelShader = ( IWineD3DPixelShader * ) object ;
2009-01-12 10:17:50 +01:00
TRACE ( " (%p) : Created pixel shader %p \n " , This , * ppPixelShader ) ;
2009-05-08 17:44:25 +02:00
hr = IWineD3DPixelShader_SetFunction ( * ppPixelShader , pFunction , output_signature ) ;
2009-01-12 10:17:50 +01:00
if ( FAILED ( hr ) )
{
WARN ( " (%p) : Failed to set function, returning %#x \n " , iface , hr ) ;
IWineD3DPixelShader_Release ( * ppPixelShader ) ;
* ppPixelShader = NULL ;
return hr ;
2005-11-21 17:27:55 +01:00
}
2005-08-25 21:24:21 +02:00
2005-11-21 17:27:55 +01:00
return hr ;
2005-03-02 13:16:10 +01:00
}
2008-11-26 16:14:39 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette ( IWineD3DDevice * iface , DWORD Flags ,
const PALETTEENTRY * PalEnt , IWineD3DPalette * * Palette , IUnknown * Parent )
{
2006-04-17 17:04:59 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DPaletteImpl * object ;
2006-04-21 00:00:30 +02:00
HRESULT hr ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p)->(%x, %p, %p, %p) \n " , This , Flags , PalEnt , Palette , Parent ) ;
2006-04-17 17:04:59 +02:00
/* Create the new object */
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3DPaletteImpl ) ) ;
if ( ! object ) {
ERR ( " Out of memory when allocating memory for a IWineD3DPalette implementation \n " ) ;
2006-04-21 00:00:30 +02:00
return E_OUTOFMEMORY ;
2006-04-17 17:04:59 +02:00
}
object - > lpVtbl = & IWineD3DPalette_Vtbl ;
object - > ref = 1 ;
2006-04-21 00:00:30 +02:00
object - > Flags = Flags ;
object - > parent = Parent ;
object - > wineD3DDevice = This ;
object - > palNumEntries = IWineD3DPaletteImpl_Size ( Flags ) ;
object - > hpal = CreatePalette ( ( const LOGPALETTE * ) & ( object - > palVersion ) ) ;
if ( ! object - > hpal ) {
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
return E_OUTOFMEMORY ;
}
hr = IWineD3DPalette_SetEntries ( ( IWineD3DPalette * ) object , 0 , 0 , IWineD3DPaletteImpl_Size ( Flags ) , PalEnt ) ;
if ( FAILED ( hr ) ) {
IWineD3DPalette_Release ( ( IWineD3DPalette * ) object ) ;
return hr ;
}
2006-04-17 17:04:59 +02:00
* Palette = ( IWineD3DPalette * ) object ;
2006-04-21 00:00:30 +02:00
return WINED3D_OK ;
2006-04-17 17:04:59 +02:00
}
2007-09-01 21:22:32 +02:00
static void IWineD3DDeviceImpl_LoadLogo ( IWineD3DDeviceImpl * This , const char * filename ) {
HBITMAP hbm ;
BITMAP bm ;
HRESULT hr ;
HDC dcb = NULL , dcs = NULL ;
WINEDDCOLORKEY colorkey ;
2009-02-03 09:36:07 +01:00
hbm = LoadImageA ( NULL , filename , IMAGE_BITMAP , 0 , 0 , LR_LOADFROMFILE | LR_CREATEDIBSECTION ) ;
2007-09-01 21:22:32 +02:00
if ( hbm )
{
GetObjectA ( hbm , sizeof ( BITMAP ) , & bm ) ;
dcb = CreateCompatibleDC ( NULL ) ;
if ( ! dcb ) goto out ;
SelectObject ( dcb , hbm ) ;
}
else
{
/* Create a 32x32 white surface to indicate that wined3d is used, but the specified image
* couldn ' t be loaded
*/
memset ( & bm , 0 , sizeof ( bm ) ) ;
bm . bmWidth = 32 ;
bm . bmHeight = 32 ;
}
2009-06-12 09:46:03 +02:00
hr = IWineD3DDevice_CreateSurface ( ( IWineD3DDevice * ) This , bm . bmWidth , bm . bmHeight , WINED3DFMT_R5G6B5 , TRUE ,
FALSE , 0 , & This - > logo_surface , 0 , WINED3DPOOL_DEFAULT , WINED3DMULTISAMPLE_NONE , 0 , SURFACE_OPENGL , NULL ) ;
2007-09-01 21:22:32 +02:00
if ( FAILED ( hr ) ) {
ERR ( " Wine logo requested, but failed to create surface \n " ) ;
goto out ;
}
if ( dcb ) {
hr = IWineD3DSurface_GetDC ( This - > logo_surface , & dcs ) ;
if ( FAILED ( hr ) ) goto out ;
BitBlt ( dcs , 0 , 0 , bm . bmWidth , bm . bmHeight , dcb , 0 , 0 , SRCCOPY ) ;
IWineD3DSurface_ReleaseDC ( This - > logo_surface , dcs ) ;
colorkey . dwColorSpaceLowValue = 0 ;
colorkey . dwColorSpaceHighValue = 0 ;
IWineD3DSurface_SetColorKey ( This - > logo_surface , WINEDDCKEY_SRCBLT , & colorkey ) ;
} else {
/* Fill the surface with a white color to show that wined3d is there */
IWineD3DDevice_ColorFill ( ( IWineD3DDevice * ) This , This - > logo_surface , NULL , 0xffffffff ) ;
}
out :
if ( dcb ) {
DeleteDC ( dcb ) ;
}
if ( hbm ) {
DeleteObject ( hbm ) ;
}
return ;
}
2009-06-26 10:07:12 +02:00
/* Context activation is done by the caller. */
2008-02-15 15:54:37 +01:00
static void create_dummy_textures ( IWineD3DDeviceImpl * This ) {
unsigned int i ;
/* Under DirectX you can have texture stage operations even if no texture is
bound , whereas opengl will only do texture operations when a valid texture is
bound . We emulate this by creating dummy textures and binding them to each
texture stage , but disable all stages by default . Hence if a stage is enabled
then the default texture will kick in until replaced by a SetTexture call */
ENTER_GL ( ) ;
if ( GL_SUPPORT ( APPLE_CLIENT_STORAGE ) ) {
/* The dummy texture does not have client storage backing */
glPixelStorei ( GL_UNPACK_CLIENT_STORAGE_APPLE , GL_FALSE ) ;
checkGLcall ( " glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE) " ) ;
}
for ( i = 0 ; i < GL_LIMITS ( textures ) ; i + + ) {
GLubyte white = 255 ;
/* Make appropriate texture active */
2008-12-16 13:18:49 +01:00
GL_EXTCALL ( glActiveTextureARB ( GL_TEXTURE0_ARB + i ) ) ;
checkGLcall ( " glActiveTextureARB " ) ;
2008-02-15 15:54:37 +01:00
/* Generate an opengl texture name */
glGenTextures ( 1 , & This - > dummyTextureName [ i ] ) ;
checkGLcall ( " glGenTextures " ) ;
TRACE ( " Dummy Texture %d given name %d \n " , i , This - > dummyTextureName [ i ] ) ;
/* Generate a dummy 2d texture (not using 1d because they cause many
* DRI drivers fall back to sw ) */
glBindTexture ( GL_TEXTURE_2D , This - > dummyTextureName [ i ] ) ;
checkGLcall ( " glBindTexture " ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_LUMINANCE , 1 , 1 , 0 , GL_LUMINANCE , GL_UNSIGNED_BYTE , & white ) ;
checkGLcall ( " glTexImage2D " ) ;
}
if ( GL_SUPPORT ( APPLE_CLIENT_STORAGE ) ) {
/* Reenable because if supported it is enabled by default */
glPixelStorei ( GL_UNPACK_CLIENT_STORAGE_APPLE , GL_TRUE ) ;
checkGLcall ( " glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE) " ) ;
}
LEAVE_GL ( ) ;
}
2009-01-16 10:14:24 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_Init3D ( IWineD3DDevice * iface ,
WINED3DPRESENT_PARAMETERS * pPresentationParameters )
{
2006-04-18 22:38:30 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-01-22 09:27:00 +01:00
IWineD3DSwapChainImpl * swapchain = NULL ;
2007-06-12 17:49:58 +02:00
HRESULT hr ;
2006-12-15 19:16:36 +01:00
DWORD state ;
2008-03-26 23:23:04 +01:00
unsigned int i ;
2006-04-18 22:38:30 +02:00
2009-01-16 10:14:24 +01:00
TRACE ( " (%p)->(%p) \n " , This , pPresentationParameters ) ;
2006-04-18 22:38:30 +02:00
if ( This - > d3d_initialized ) return WINED3DERR_INVALIDCALL ;
2008-03-28 23:04:52 +01:00
if ( ! This - > adapter - > opengl ) return WINED3DERR_INVALIDCALL ;
2006-04-18 22:38:30 +02:00
/* TODO: Test if OpenGL is compiled in and loaded */
2007-07-22 23:09:11 +02:00
TRACE ( " (%p) : Creating stateblock \n " , This ) ;
/* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
hr = IWineD3DDevice_CreateStateBlock ( iface ,
WINED3DSBT_INIT ,
( IWineD3DStateBlock * * ) & This - > stateBlock ,
NULL ) ;
if ( WINED3D_OK ! = hr ) { /* Note: No parent needed for initial internal stateblock */
WARN ( " Failed to create stateblock \n " ) ;
2007-10-09 22:04:18 +02:00
goto err_out ;
2007-07-22 23:09:11 +02:00
}
TRACE ( " (%p) : Created stateblock (%p) \n " , This , This - > stateBlock ) ;
This - > updateStateBlock = This - > stateBlock ;
IWineD3DStateBlock_AddRef ( ( IWineD3DStateBlock * ) This - > updateStateBlock ) ;
2007-07-16 19:49:34 +02:00
This - > render_targets = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3DSurface * ) * GL_LIMITS ( buffers ) ) ;
This - > draw_buffers = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( GLenum ) * GL_LIMITS ( buffers ) ) ;
2008-03-26 23:23:04 +01:00
This - > NumberOfPalettes = 1 ;
This - > palettes = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( PALETTEENTRY * ) ) ;
2008-08-21 18:34:55 +02:00
if ( ! This - > palettes | | ! This - > render_targets | | ! This - > draw_buffers ) {
2008-03-26 23:23:04 +01:00
ERR ( " Out of memory! \n " ) ;
goto err_out ;
}
This - > palettes [ 0 ] = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( PALETTEENTRY ) * 256 ) ;
if ( ! This - > palettes [ 0 ] ) {
ERR ( " Out of memory! \n " ) ;
goto err_out ;
}
for ( i = 0 ; i < 256 ; + + i ) {
This - > palettes [ 0 ] [ i ] . peRed = 0xFF ;
This - > palettes [ 0 ] [ i ] . peGreen = 0xFF ;
This - > palettes [ 0 ] [ i ] . peBlue = 0xFF ;
This - > palettes [ 0 ] [ i ] . peFlags = 0xFF ;
}
This - > currentPalette = 0 ;
2006-12-19 23:33:34 +01:00
/* Initialize the texture unit mapping to a 1:1 mapping */
2007-06-25 22:45:40 +02:00
for ( state = 0 ; state < MAX_COMBINED_SAMPLERS ; + + state ) {
2007-06-25 22:45:21 +02:00
if ( state < GL_LIMITS ( fragment_samplers ) ) {
2007-06-22 20:43:19 +02:00
This - > texUnitMap [ state ] = state ;
This - > rev_tex_unit_map [ state ] = state ;
} else {
This - > texUnitMap [ state ] = - 1 ;
This - > rev_tex_unit_map [ state ] = - 1 ;
}
2006-12-19 23:33:34 +01:00
}
2009-06-26 10:07:12 +02:00
/* Setup the implicit swapchain. This also initializes a context. */
2006-04-18 22:38:30 +02:00
TRACE ( " Creating implicit swapchain \n " ) ;
2009-01-16 10:14:24 +01:00
hr = IWineD3DDeviceParent_CreateSwapChain ( This - > device_parent ,
pPresentationParameters , ( IWineD3DSwapChain * * ) & swapchain ) ;
if ( FAILED ( hr ) )
{
2006-04-18 22:38:30 +02:00
WARN ( " Failed to create implicit swapchain \n " ) ;
2007-10-09 22:04:18 +02:00
goto err_out ;
2006-04-18 22:38:30 +02:00
}
2006-05-24 11:34:30 +02:00
This - > NumberOfSwapChains = 1 ;
This - > swapchains = HeapAlloc ( GetProcessHeap ( ) , 0 , This - > NumberOfSwapChains * sizeof ( IWineD3DSwapChain * ) ) ;
if ( ! This - > swapchains ) {
ERR ( " Out of memory! \n " ) ;
2007-10-09 22:04:18 +02:00
goto err_out ;
2006-05-24 11:34:30 +02:00
}
This - > swapchains [ 0 ] = ( IWineD3DSwapChain * ) swapchain ;
2006-06-15 12:54:19 +02:00
if ( swapchain - > backBuffer & & swapchain - > backBuffer [ 0 ] ) {
2006-04-18 22:38:30 +02:00
TRACE ( " Setting rendertarget to %p \n " , swapchain - > backBuffer ) ;
2006-12-19 19:25:22 +01:00
This - > render_targets [ 0 ] = swapchain - > backBuffer [ 0 ] ;
2007-02-12 19:21:10 +01:00
This - > lastActiveRenderTarget = swapchain - > backBuffer [ 0 ] ;
2006-04-18 22:38:30 +02:00
}
else {
TRACE ( " Setting rendertarget to %p \n " , swapchain - > frontBuffer ) ;
2006-12-19 19:25:22 +01:00
This - > render_targets [ 0 ] = swapchain - > frontBuffer ;
2007-02-12 19:21:10 +01:00
This - > lastActiveRenderTarget = swapchain - > frontBuffer ;
2006-04-18 22:38:30 +02:00
}
2006-12-19 19:25:22 +01:00
IWineD3DSurface_AddRef ( This - > render_targets [ 0 ] ) ;
2007-03-04 17:31:06 +01:00
This - > activeContext = swapchain - > context [ 0 ] ;
2007-06-02 22:20:17 +02:00
This - > lastThread = GetCurrentThreadId ( ) ;
2007-02-12 19:21:10 +01:00
2006-04-18 22:38:30 +02:00
/* Depth Stencil support */
2007-11-10 00:19:19 +01:00
This - > stencilBufferTarget = This - > auto_depth_stencil_buffer ;
2006-04-18 22:38:30 +02:00
if ( NULL ! = This - > stencilBufferTarget ) {
IWineD3DSurface_AddRef ( This - > stencilBufferTarget ) ;
}
2008-03-18 19:49:05 +01:00
hr = This - > shader_backend - > shader_alloc_private ( iface ) ;
if ( FAILED ( hr ) ) {
TRACE ( " Shader private data couldn't be allocated \n " ) ;
goto err_out ;
}
2008-07-11 16:41:28 +02:00
hr = This - > frag_pipe - > alloc_private ( iface ) ;
if ( FAILED ( hr ) ) {
TRACE ( " Fragment pipeline private data couldn't be allocated \n " ) ;
goto err_out ;
}
2008-08-01 20:21:10 +02:00
hr = This - > blitter - > alloc_private ( iface ) ;
if ( FAILED ( hr ) ) {
TRACE ( " Blitter private data couldn't be allocated \n " ) ;
goto err_out ;
}
2008-03-18 19:49:05 +01:00
2006-04-18 22:38:30 +02:00
/* Set up some starting GL setup */
/* Setup all the devices defaults */
IWineD3DStateBlock_InitStartupStateBlock ( ( IWineD3DStateBlock * ) This - > stateBlock ) ;
2008-02-15 15:54:37 +01:00
create_dummy_textures ( This ) ;
2008-04-06 23:06:22 +02:00
ENTER_GL ( ) ;
2006-04-18 22:38:30 +02:00
/* Initialize the current view state */
This - > view_ident = 1 ;
2007-02-12 19:35:45 +01:00
This - > contexts [ 0 ] - > last_was_rhw = 0 ;
2006-04-18 22:38:30 +02:00
glGetIntegerv ( GL_MAX_LIGHTS , & This - > maxConcurrentLights ) ;
2007-02-12 19:22:41 +01:00
checkGLcall ( " glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights) " ) ;
2007-02-27 21:32:15 +01:00
switch ( wined3d_settings . offscreen_rendering_mode ) {
case ORM_FBO :
case ORM_PBUFFER :
This - > offscreenBuffer = GL_BACK ;
break ;
case ORM_BACKBUFFER :
{
2008-04-08 14:20:27 +02:00
if ( This - > activeContext - > aux_buffers > 0 ) {
2007-02-27 21:32:15 +01:00
TRACE ( " Using auxilliary buffer for offscreen rendering \n " ) ;
This - > offscreenBuffer = GL_AUX0 ;
} else {
TRACE ( " Using back buffer for offscreen rendering \n " ) ;
This - > offscreenBuffer = GL_BACK ;
}
}
}
2006-04-18 22:38:30 +02:00
TRACE ( " (%p) All defaults now set up, leaving Init3D with %p \n " , This , This ) ;
2007-02-12 19:22:41 +01:00
LEAVE_GL ( ) ;
2006-04-18 22:38:30 +02:00
/* Clear the screen */
2007-03-06 13:35:56 +01:00
IWineD3DDevice_Clear ( ( IWineD3DDevice * ) This , 0 , NULL ,
WINED3DCLEAR_TARGET | pPresentationParameters - > EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0 ,
0x00 , 1.0 , 0 ) ;
2006-04-18 22:38:30 +02:00
This - > d3d_initialized = TRUE ;
2007-09-01 21:22:32 +02:00
if ( wined3d_settings . logo ) {
IWineD3DDeviceImpl_LoadLogo ( This , wined3d_settings . logo ) ;
}
2008-03-04 02:30:23 +01:00
This - > highest_dirty_ps_const = 0 ;
This - > highest_dirty_vs_const = 0 ;
2006-04-18 22:38:30 +02:00
return WINED3D_OK ;
2007-10-09 22:04:18 +02:00
2008-01-22 09:27:00 +01:00
err_out :
2007-10-09 22:04:18 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , This - > render_targets ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > draw_buffers ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > swapchains ) ;
This - > NumberOfSwapChains = 0 ;
2008-03-26 23:23:04 +01:00
if ( This - > palettes ) {
HeapFree ( GetProcessHeap ( ) , 0 , This - > palettes [ 0 ] ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > palettes ) ;
}
This - > NumberOfPalettes = 0 ;
2007-10-09 22:04:18 +02:00
if ( swapchain ) {
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
}
if ( This - > stateBlock ) {
IWineD3DStateBlock_Release ( ( IWineD3DStateBlock * ) This - > stateBlock ) ;
This - > stateBlock = NULL ;
}
2008-08-20 22:45:02 +02:00
if ( This - > blit_priv ) {
This - > blitter - > free_private ( iface ) ;
}
if ( This - > fragment_priv ) {
This - > frag_pipe - > free_private ( iface ) ;
}
if ( This - > shader_priv ) {
This - > shader_backend - > shader_free_private ( iface ) ;
}
2007-10-09 22:04:18 +02:00
return hr ;
2006-04-12 21:08:57 +02:00
}
2009-01-16 10:14:24 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI ( IWineD3DDevice * iface ,
WINED3DPRESENT_PARAMETERS * pPresentationParameters )
{
2008-08-05 21:23:00 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSwapChainImpl * swapchain = NULL ;
HRESULT hr ;
/* Setup the implicit swapchain */
TRACE ( " Creating implicit swapchain \n " ) ;
2009-01-16 10:14:24 +01:00
hr = IWineD3DDeviceParent_CreateSwapChain ( This - > device_parent ,
pPresentationParameters , ( IWineD3DSwapChain * * ) & swapchain ) ;
if ( FAILED ( hr ) )
{
2008-08-05 21:23:00 +02:00
WARN ( " Failed to create implicit swapchain \n " ) ;
goto err_out ;
}
This - > NumberOfSwapChains = 1 ;
This - > swapchains = HeapAlloc ( GetProcessHeap ( ) , 0 , This - > NumberOfSwapChains * sizeof ( IWineD3DSwapChain * ) ) ;
if ( ! This - > swapchains ) {
ERR ( " Out of memory! \n " ) ;
goto err_out ;
}
This - > swapchains [ 0 ] = ( IWineD3DSwapChain * ) swapchain ;
return WINED3D_OK ;
err_out :
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
return hr ;
}
2009-03-23 13:54:34 +01:00
static HRESULT WINAPI device_unload_resource ( IWineD3DResource * resource , void * ctx )
{
IWineD3DResource_UnLoad ( resource ) ;
IWineD3DResource_Release ( resource ) ;
return WINED3D_OK ;
}
2006-12-18 00:17:24 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D ( IWineD3DDevice * iface , D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface , D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain ) {
2006-04-18 22:38:30 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-06-27 23:40:42 +02:00
int sampler ;
2007-08-06 16:38:00 +02:00
UINT i ;
2006-04-18 22:38:30 +02:00
TRACE ( " (%p) \n " , This ) ;
if ( ! This - > d3d_initialized ) return WINED3DERR_INVALIDCALL ;
2008-01-09 20:37:05 +01:00
/* I don't think that the interface guarantees that the device is destroyed from the same thread
2007-03-17 23:00:39 +01:00
* it was created . Thus make sure a context is active for the glDelete * calls
*/
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-09-01 21:22:32 +02:00
if ( This - > logo_surface ) IWineD3DSurface_Release ( This - > logo_surface ) ;
2009-03-23 13:54:34 +01:00
/* Unload resources */
IWineD3DDevice_EnumResources ( iface , device_unload_resource , NULL ) ;
2007-07-04 17:57:45 +02:00
TRACE ( " Deleting high order patches \n " ) ;
for ( i = 0 ; i < PATCHMAP_SIZE ; i + + ) {
struct list * e1 , * e2 ;
struct WineD3DRectPatch * patch ;
LIST_FOR_EACH_SAFE ( e1 , e2 , & This - > patches [ i ] ) {
patch = LIST_ENTRY ( e1 , struct WineD3DRectPatch , entry ) ;
IWineD3DDevice_DeletePatch ( iface , patch - > Handle ) ;
}
}
2007-10-11 23:11:37 +02:00
/* Delete the palette conversion shader if it is around */
if ( This - > paletteConversionShader ) {
2008-04-06 23:05:55 +02:00
ENTER_GL ( ) ;
2007-10-11 23:11:37 +02:00
GL_EXTCALL ( glDeleteProgramsARB ( 1 , & This - > paletteConversionShader ) ) ;
2008-04-06 23:05:55 +02:00
LEAVE_GL ( ) ;
2007-11-08 22:51:01 +01:00
This - > paletteConversionShader = 0 ;
2007-10-11 23:11:37 +02:00
}
2007-02-12 19:21:10 +01:00
/* Delete the pbuffer context if there is any */
if ( This - > pbufferContext ) DestroyContext ( This , This - > pbufferContext ) ;
2006-07-27 17:39:03 +02:00
/* Delete the mouse cursor texture */
if ( This - > cursorTexture ) {
ENTER_GL ( ) ;
glDeleteTextures ( 1 , & This - > cursorTexture ) ;
LEAVE_GL ( ) ;
This - > cursorTexture = 0 ;
}
2007-06-25 22:45:40 +02:00
for ( sampler = 0 ; sampler < MAX_FRAGMENT_SAMPLERS ; + + sampler ) {
2006-06-27 23:40:42 +02:00
IWineD3DDevice_SetTexture ( iface , sampler , NULL ) ;
2006-04-18 22:38:30 +02:00
}
2007-06-25 22:45:40 +02:00
for ( sampler = 0 ; sampler < MAX_VERTEX_SAMPLERS ; + + sampler ) {
IWineD3DDevice_SetTexture ( iface , WINED3DVERTEXTEXTURESAMPLER0 + sampler , NULL ) ;
}
2006-04-18 22:38:30 +02:00
2008-03-18 19:49:05 +01:00
/* Destroy the depth blt resources, they will be invalid after the reset. Also free shader
* private data , it might contain opengl pointers
*/
2008-06-27 00:52:13 +02:00
if ( This - > depth_blt_texture ) {
2009-05-13 18:22:55 +02:00
ENTER_GL ( ) ;
2008-06-27 00:52:13 +02:00
glDeleteTextures ( 1 , & This - > depth_blt_texture ) ;
2009-05-13 18:22:55 +02:00
LEAVE_GL ( ) ;
2008-06-27 00:52:13 +02:00
This - > depth_blt_texture = 0 ;
}
2008-07-02 23:00:11 +02:00
if ( This - > depth_blt_rb ) {
2009-05-13 18:22:55 +02:00
ENTER_GL ( ) ;
2008-07-02 23:00:11 +02:00
GL_EXTCALL ( glDeleteRenderbuffersEXT ( 1 , & This - > depth_blt_rb ) ) ;
2009-05-13 18:22:55 +02:00
LEAVE_GL ( ) ;
2008-07-02 23:00:11 +02:00
This - > depth_blt_rb = 0 ;
This - > depth_blt_rb_w = 0 ;
This - > depth_blt_rb_h = 0 ;
}
2008-03-18 19:49:05 +01:00
2007-08-14 14:44:41 +02:00
/* Release the update stateblock */
if ( IWineD3DStateBlock_Release ( ( IWineD3DStateBlock * ) This - > updateStateBlock ) > 0 ) {
if ( This - > updateStateBlock ! = This - > stateBlock )
FIXME ( " (%p) Something's still holding the Update stateblock \n " , This ) ;
}
This - > updateStateBlock = NULL ;
{ /* because were not doing proper internal refcounts releasing the primary state block
causes recursion with the extra checks in ResourceReleased , to avoid this we have
to set this - > stateBlock = NULL ; first */
IWineD3DStateBlock * stateBlock = ( IWineD3DStateBlock * ) This - > stateBlock ;
This - > stateBlock = NULL ;
/* Release the stateblock */
if ( IWineD3DStateBlock_Release ( stateBlock ) > 0 ) {
FIXME ( " (%p) Something's still holding the Update stateblock \n " , This ) ;
}
}
2008-07-10 23:26:10 +02:00
/* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
2008-08-01 20:21:10 +02:00
This - > blitter - > free_private ( iface ) ;
2008-07-11 16:41:28 +02:00
This - > frag_pipe - > free_private ( iface ) ;
2008-07-28 18:41:02 +02:00
This - > shader_backend - > shader_free_private ( iface ) ;
2008-07-10 23:26:10 +02:00
2006-05-24 11:34:30 +02:00
/* Release the buffers (with sanity checks)*/
2006-04-18 22:38:30 +02:00
TRACE ( " Releasing the depth stencil buffer at %p \n " , This - > stencilBufferTarget ) ;
if ( This - > stencilBufferTarget ! = NULL & & ( IWineD3DSurface_Release ( This - > stencilBufferTarget ) > 0 ) ) {
2007-11-10 00:19:19 +01:00
if ( This - > auto_depth_stencil_buffer ! = This - > stencilBufferTarget )
FIXME ( " (%p) Something's still holding the stencilBufferTarget \n " , This ) ;
2006-04-18 22:38:30 +02:00
}
This - > stencilBufferTarget = NULL ;
2006-12-19 19:25:22 +01:00
TRACE ( " Releasing the render target at %p \n " , This - > render_targets [ 0 ] ) ;
if ( IWineD3DSurface_Release ( This - > render_targets [ 0 ] ) > 0 ) {
2008-01-09 20:37:05 +01:00
/* This check is a bit silly, it should be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
2006-04-18 22:38:30 +02:00
}
TRACE ( " Setting rendertarget to NULL \n " ) ;
2006-12-19 19:25:22 +01:00
This - > render_targets [ 0 ] = NULL ;
2006-04-18 22:38:30 +02:00
2007-11-10 00:19:19 +01:00
if ( This - > auto_depth_stencil_buffer ) {
if ( D3DCB_DestroyDepthStencilSurface ( This - > auto_depth_stencil_buffer ) > 0 ) {
FIXME ( " (%p) Something's still holding the auto depth stencil buffer \n " , This ) ;
2006-07-21 05:06:32 +02:00
}
2007-11-10 00:19:19 +01:00
This - > auto_depth_stencil_buffer = NULL ;
2006-04-18 22:38:30 +02:00
}
2006-05-24 11:34:30 +02:00
for ( i = 0 ; i < This - > NumberOfSwapChains ; i + + ) {
TRACE ( " Releasing the implicit swapchain %d \n " , i ) ;
2006-12-18 00:17:24 +01:00
if ( D3DCB_DestroySwapChain ( This - > swapchains [ i ] ) > 0 ) {
2006-04-18 22:38:30 +02:00
FIXME ( " (%p) Something's still holding the implicit swapchain \n " , This ) ;
}
}
2006-05-24 11:34:30 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , This - > swapchains ) ;
2006-04-18 22:38:30 +02:00
This - > swapchains = NULL ;
2006-05-24 11:34:30 +02:00
This - > NumberOfSwapChains = 0 ;
2006-04-18 22:38:30 +02:00
2008-03-26 23:23:04 +01:00
for ( i = 0 ; i < This - > NumberOfPalettes ; i + + ) HeapFree ( GetProcessHeap ( ) , 0 , This - > palettes [ i ] ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > palettes ) ;
This - > palettes = NULL ;
This - > NumberOfPalettes = 0 ;
2007-07-16 19:49:34 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , This - > render_targets ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > draw_buffers ) ;
This - > render_targets = NULL ;
This - > draw_buffers = NULL ;
2006-04-18 22:38:30 +02:00
This - > d3d_initialized = FALSE ;
return WINED3D_OK ;
2006-04-12 21:08:57 +02:00
}
2008-08-05 21:23:00 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_UninitGDI ( IWineD3DDevice * iface , D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
unsigned int i ;
for ( i = 0 ; i < This - > NumberOfSwapChains ; i + + ) {
TRACE ( " Releasing the implicit swapchain %d \n " , i ) ;
if ( D3DCB_DestroySwapChain ( This - > swapchains [ i ] ) > 0 ) {
FIXME ( " (%p) Something's still holding the implicit swapchain \n " , This ) ;
}
}
HeapFree ( GetProcessHeap ( ) , 0 , This - > swapchains ) ;
This - > swapchains = NULL ;
This - > NumberOfSwapChains = 0 ;
return WINED3D_OK ;
}
2007-10-19 05:40:40 +02:00
/* Enables thread safety in the wined3d device and its resources. Called by DirectDraw
* from SetCooperativeLevel if DDSCL_MULTITHREADED is specified , and by d3d8 / 9 from
2007-03-04 17:03:03 +01:00
* CreateDevice if D3DCREATE_MULTITHREADED is passed .
*
2007-10-19 05:40:40 +02:00
* There is no way to deactivate thread safety once it is enabled .
2007-03-04 17:03:03 +01:00
*/
static void WINAPI IWineD3DDeviceImpl_SetMultithreaded ( IWineD3DDevice * iface ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
/*For now just store the flag(needed in case of ddraw) */
This - > createParms . BehaviorFlags | = WINED3DCREATE_MULTITHREADED ;
return ;
}
2008-11-25 11:57:39 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode ( IWineD3DDevice * iface , UINT iSwapChain ,
const WINED3DDISPLAYMODE * pMode ) {
2006-05-18 22:42:22 +02:00
DEVMODEW devmode ;
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
LONG ret ;
2009-03-13 10:44:18 +01:00
const struct GlPixelFormatDesc * format_desc = getFormatDescEntry ( pMode - > Format , & GLINFO_LOCATION ) ;
2006-12-14 23:51:23 +01:00
RECT clip_rc ;
2006-05-18 22:42:22 +02:00
TRACE ( " (%p)->(%d,%p) Mode=%dx%dx@%d, %s \n " , This , iSwapChain , pMode , pMode - > Width , pMode - > Height , pMode - > RefreshRate , debug_d3dformat ( pMode - > Format ) ) ;
/* Resize the screen even without a window:
* The app could have unset it with SetCooperativeLevel , but not called
* RestoreDisplayMode first . Then the release will call RestoreDisplayMode ,
* but we don ' t have any hwnd
*/
2007-08-05 20:23:42 +02:00
memset ( & devmode , 0 , sizeof ( devmode ) ) ;
devmode . dmSize = sizeof ( devmode ) ;
2006-05-18 22:42:22 +02:00
devmode . dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT ;
2009-03-13 10:44:18 +01:00
devmode . dmBitsPerPel = format_desc - > byte_count * 8 ;
2006-05-18 22:42:22 +02:00
devmode . dmPelsWidth = pMode - > Width ;
devmode . dmPelsHeight = pMode - > Height ;
devmode . dmDisplayFrequency = pMode - > RefreshRate ;
if ( pMode - > RefreshRate ! = 0 ) {
devmode . dmFields | = DM_DISPLAYFREQUENCY ;
}
/* Only change the mode if necessary */
if ( ( This - > ddraw_width = = pMode - > Width ) & &
( This - > ddraw_height = = pMode - > Height ) & &
( This - > ddraw_format = = pMode - > Format ) & &
( pMode - > RefreshRate = = 0 ) ) {
2007-02-14 23:30:40 +01:00
return WINED3D_OK ;
2006-05-18 22:42:22 +02:00
}
ret = ChangeDisplaySettingsExW ( NULL , & devmode , NULL , CDS_FULLSCREEN , NULL ) ;
if ( ret ! = DISP_CHANGE_SUCCESSFUL ) {
if ( devmode . dmDisplayFrequency ! = 0 ) {
WARN ( " ChangeDisplaySettingsExW failed, trying without the refresh rate \n " ) ;
devmode . dmFields & = ~ DM_DISPLAYFREQUENCY ;
devmode . dmDisplayFrequency = 0 ;
ret = ChangeDisplaySettingsExW ( NULL , & devmode , NULL , CDS_FULLSCREEN , NULL ) ! = DISP_CHANGE_SUCCESSFUL ;
}
if ( ret ! = DISP_CHANGE_SUCCESSFUL ) {
2007-04-14 22:44:55 +02:00
return WINED3DERR_NOTAVAILABLE ;
2006-05-18 22:42:22 +02:00
}
}
/* Store the new values */
This - > ddraw_width = pMode - > Width ;
This - > ddraw_height = pMode - > Height ;
This - > ddraw_format = pMode - > Format ;
2006-12-14 23:51:23 +01:00
/* And finally clip mouse to our screen */
SetRect ( & clip_rc , 0 , 0 , pMode - > Width , pMode - > Height ) ;
ClipCursor ( & clip_rc ) ;
2006-05-18 22:42:22 +02:00
return WINED3D_OK ;
2006-04-17 17:51:21 +02:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D ( IWineD3DDevice * iface , IWineD3D * * ppD3D ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
* ppD3D = This - > wineD3D ;
TRACE ( " (%p) : wineD3D returning %p \n " , This , * ppD3D ) ;
2006-11-30 13:32:58 +01:00
IWineD3D_AddRef ( * ppD3D ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-07-13 16:15:54 +02:00
2006-06-10 13:15:32 +02:00
static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-09-23 00:46:21 +02:00
2006-08-08 00:03:06 +02:00
TRACE ( " (%p) : simulating %dMB, returning %dMB left \n " , This ,
2007-09-23 00:46:21 +02:00
( This - > adapter - > TextureRam / ( 1024 * 1024 ) ) ,
( ( This - > adapter - > TextureRam - This - > adapter - > UsedTextureRam ) / ( 1024 * 1024 ) ) ) ;
2006-08-08 00:03:06 +02:00
/* return simulated texture memory left */
2007-09-23 00:46:21 +02:00
return ( This - > adapter - > TextureRam - This - > adapter - > UsedTextureRam ) ;
2005-03-02 13:16:10 +01:00
}
2004-11-23 14:52:46 +01:00
/*****
* Get / Set Stream Source
* * * * */
2009-03-06 14:56:23 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource ( IWineD3DDevice * iface , UINT StreamNumber ,
IWineD3DBuffer * pStreamData , UINT OffsetInBytes , UINT Stride )
{
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DBuffer * oldSrc ;
2004-11-23 14:52:46 +01:00
2005-09-02 13:17:17 +02:00
if ( StreamNumber > = MAX_STREAMS ) {
WARN ( " Stream out of range %d \n " , StreamNumber ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2007-12-20 22:14:53 +01:00
} else if ( OffsetInBytes & 0x3 ) {
WARN ( " OffsetInBytes is not 4 byte aligned: %d \n " , OffsetInBytes ) ;
return WINED3DERR_INVALIDCALL ;
2005-09-02 13:17:17 +02:00
}
2007-08-19 20:37:50 +02:00
oldSrc = This - > updateStateBlock - > streamSource [ StreamNumber ] ;
2007-04-09 01:55:16 +02:00
TRACE ( " (%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u \n " , This , StreamNumber , oldSrc , pStreamData , OffsetInBytes , Stride ) ;
2004-11-23 14:52:46 +01:00
2008-12-31 16:57:11 +01:00
This - > updateStateBlock - > changed . streamSource | = 1 < < StreamNumber ;
2007-01-04 00:08:20 +01:00
if ( oldSrc = = pStreamData & &
This - > updateStateBlock - > streamStride [ StreamNumber ] = = Stride & &
2007-02-14 17:49:53 +01:00
This - > updateStateBlock - > streamOffset [ StreamNumber ] = = OffsetInBytes ) {
2007-01-04 00:08:20 +01:00
TRACE ( " Application is setting the old values over, nothing to do \n " ) ;
return WINED3D_OK ;
}
2005-07-05 16:05:18 +02:00
This - > updateStateBlock - > streamSource [ StreamNumber ] = pStreamData ;
2006-12-24 10:00:05 +01:00
if ( pStreamData ) {
This - > updateStateBlock - > streamStride [ StreamNumber ] = Stride ;
This - > updateStateBlock - > streamOffset [ StreamNumber ] = OffsetInBytes ;
}
2004-11-23 14:52:46 +01:00
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2009-03-06 14:56:23 +01:00
if ( pStreamData ) IWineD3DBuffer_AddRef ( pStreamData ) ;
if ( oldSrc ) IWineD3DBuffer_Release ( oldSrc ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-23 14:52:46 +01:00
}
2005-07-26 20:49:30 +02:00
if ( pStreamData ! = NULL ) {
2009-03-06 14:56:23 +01:00
InterlockedIncrement ( & ( ( struct wined3d_buffer * ) pStreamData ) - > bind_count ) ;
IWineD3DBuffer_AddRef ( pStreamData ) ;
2005-07-26 20:49:30 +02:00
}
if ( oldSrc ! = NULL ) {
2009-03-06 14:56:23 +01:00
InterlockedDecrement ( & ( ( struct wined3d_buffer * ) oldSrc ) - > bind_count ) ;
IWineD3DBuffer_Release ( oldSrc ) ;
2005-07-26 20:49:30 +02:00
}
2004-11-23 14:52:46 +01:00
2007-01-02 00:35:07 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_STREAMSRC ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-23 14:52:46 +01:00
}
2009-03-06 14:56:23 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource ( IWineD3DDevice * iface ,
UINT StreamNumber , IWineD3DBuffer * * pStream , UINT * pOffset , UINT * pStride )
{
2004-11-23 14:52:46 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-09-02 13:17:17 +02:00
2007-04-09 01:55:16 +02:00
TRACE ( " (%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u \n " , This , StreamNumber ,
This - > stateBlock - > streamSource [ StreamNumber ] ,
This - > stateBlock - > streamOffset [ StreamNumber ] ,
This - > stateBlock - > streamStride [ StreamNumber ] ) ;
2004-11-23 14:52:46 +01:00
2005-09-02 13:17:17 +02:00
if ( StreamNumber > = MAX_STREAMS ) {
WARN ( " Stream out of range %d \n " , StreamNumber ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-09-02 13:17:17 +02:00
}
2005-07-05 16:05:18 +02:00
* pStream = This - > stateBlock - > streamSource [ StreamNumber ] ;
* pStride = This - > stateBlock - > streamStride [ StreamNumber ] ;
2006-07-31 15:36:11 +02:00
if ( pOffset ) {
* pOffset = This - > stateBlock - > streamOffset [ StreamNumber ] ;
}
2005-09-02 13:17:17 +02:00
2006-12-24 10:00:05 +01:00
if ( * pStream ! = NULL ) {
2009-03-06 14:56:23 +01:00
IWineD3DBuffer_AddRef ( * pStream ) ; /* We have created a new reference to the VB */
2005-09-02 13:17:17 +02:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-23 14:52:46 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq ( IWineD3DDevice * iface , UINT StreamNumber , UINT Divider ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-02-14 17:56:29 +01:00
UINT oldFlags = This - > updateStateBlock - > streamFlags [ StreamNumber ] ;
UINT oldFreq = This - > updateStateBlock - > streamFreq [ StreamNumber ] ;
2005-07-13 16:15:54 +02:00
2008-04-06 18:50:02 +02:00
/* Verify input at least in d3d9 this is invalid*/
if ( ( Divider & WINED3DSTREAMSOURCE_INSTANCEDATA ) & & ( Divider & WINED3DSTREAMSOURCE_INDEXEDDATA ) ) {
WARN ( " INSTANCEDATA and INDEXEDDATA were set, returning D3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
if ( ( Divider & WINED3DSTREAMSOURCE_INSTANCEDATA ) & & StreamNumber = = 0 ) {
WARN ( " INSTANCEDATA used on stream 0, returning D3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
if ( Divider = = 0 ) {
WARN ( " Divider is 0, returning D3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
2005-09-02 13:17:17 +02:00
TRACE ( " (%p) StreamNumber(%d), Divider(%d) \n " , This , StreamNumber , Divider ) ;
2006-10-31 09:19:13 +01:00
This - > updateStateBlock - > streamFlags [ StreamNumber ] = Divider & ( WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA ) ;
2005-09-02 13:17:17 +02:00
2008-12-31 16:57:11 +01:00
This - > updateStateBlock - > changed . streamFreq | = 1 < < StreamNumber ;
2005-09-02 13:17:17 +02:00
This - > updateStateBlock - > streamFreq [ StreamNumber ] = Divider & 0x7FFFFF ;
2007-02-14 17:56:29 +01:00
if ( This - > updateStateBlock - > streamFreq [ StreamNumber ] ! = oldFreq | |
This - > updateStateBlock - > streamFlags [ StreamNumber ] ! = oldFlags ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_STREAMSRC ) ;
2005-09-02 13:17:17 +02:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-07-13 16:15:54 +02:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq ( IWineD3DDevice * iface , UINT StreamNumber , UINT * Divider ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
2005-09-02 13:17:17 +02:00
TRACE ( " (%p) StreamNumber(%d), Divider(%p) \n " , This , StreamNumber , Divider ) ;
* Divider = This - > updateStateBlock - > streamFreq [ StreamNumber ] | This - > updateStateBlock - > streamFlags [ StreamNumber ] ;
TRACE ( " (%p) : returning %d \n " , This , * Divider ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2004-11-28 16:04:41 +01:00
/*****
2005-07-11 12:59:41 +02:00
* Get / Set & Multiply Transform
2004-11-28 16:04:41 +01:00
* * * * */
2006-10-12 08:21:39 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform ( IWineD3DDevice * iface , WINED3DTRANSFORMSTATETYPE d3dts , CONST WINED3DMATRIX * lpmatrix ) {
2004-11-28 16:04:41 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
/* Most of this routine, comments included copied from ddraw tree initially: */
2006-07-24 04:54:30 +02:00
TRACE ( " (%p) : Transform State=%s \n " , This , debug_d3dtstype ( d3dts ) ) ;
2004-11-28 16:04:41 +01:00
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2009-01-05 10:10:16 +01:00
This - > updateStateBlock - > changed . transform [ d3dts > > 5 ] | = 1 < < ( d3dts & 0x1f ) ;
2008-03-20 23:25:13 +01:00
This - > updateStateBlock - > transforms [ d3dts ] = * lpmatrix ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-28 16:04:41 +01:00
}
/*
* If the new matrix is the same as the current one ,
* we cut off any further processing . this seems to be a reasonable
* optimization because as was noticed , some apps ( warcraft3 for example )
* tend towards setting the same matrix repeatedly for some reason .
*
* From here on we assume that the new matrix is different , wherever it matters .
*/
2006-10-12 08:21:39 +02:00
if ( ! memcmp ( & This - > stateBlock - > transforms [ d3dts ] . u . m [ 0 ] [ 0 ] , lpmatrix , sizeof ( WINED3DMATRIX ) ) ) {
2004-11-28 16:04:41 +01:00
TRACE ( " The app is setting the same matrix over again \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-28 16:04:41 +01:00
} else {
conv_mat ( lpmatrix , & This - > stateBlock - > transforms [ d3dts ] . u . m [ 0 ] [ 0 ] ) ;
}
/*
ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
where ViewMat = Camera space , WorldMat = world space .
In OpenGL , camera and world space is combined into GL_MODELVIEW
2005-07-13 16:15:54 +02:00
matrix . The Projection matrix stay projection matrix .
2004-11-28 16:04:41 +01:00
*/
/* Capture the times we can just ignore the change for now */
2008-01-09 20:37:05 +01:00
if ( d3dts = = WINED3DTS_VIEW ) { /* handle the VIEW matrix */
2005-07-13 16:15:54 +02:00
This - > view_ident = ! memcmp ( lpmatrix , identity , 16 * sizeof ( float ) ) ;
2007-01-02 00:48:58 +01:00
/* Handled by the state manager */
2004-11-28 16:04:41 +01:00
}
2007-01-02 00:48:58 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TRANSFORM ( d3dts ) ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-28 16:04:41 +01:00
}
2006-10-12 08:21:39 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform ( IWineD3DDevice * iface , WINED3DTRANSFORMSTATETYPE State , WINED3DMATRIX * pMatrix ) {
2004-11-28 16:04:41 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-07-24 04:54:30 +02:00
TRACE ( " (%p) : for Transform State %s \n " , This , debug_d3dtstype ( State ) ) ;
2008-03-20 23:25:13 +01:00
* pMatrix = This - > stateBlock - > transforms [ State ] ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-28 16:04:41 +01:00
}
2006-10-12 08:21:39 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform ( IWineD3DDevice * iface , WINED3DTRANSFORMSTATETYPE State , CONST WINED3DMATRIX * pMatrix ) {
2008-11-26 16:14:39 +01:00
const WINED3DMATRIX * mat = NULL ;
2006-10-12 08:21:39 +02:00
WINED3DMATRIX temp ;
2004-11-29 18:53:42 +01:00
2004-12-20 20:27:06 +01:00
/* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
* below means it will be recorded in a state block change , but it
2005-07-13 16:15:54 +02:00
* works regardless where it is recorded .
2004-12-20 20:27:06 +01:00
* If this is found to be wrong , change to StateBlock .
*/
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-07-24 04:54:30 +02:00
TRACE ( " (%p) : For state %s \n " , This , debug_d3dtstype ( State ) ) ;
2004-11-29 18:53:42 +01:00
2008-12-31 16:57:10 +01:00
if ( State < = HIGHEST_TRANSFORMSTATE )
2004-11-29 18:53:42 +01:00
{
mat = & This - > updateStateBlock - > transforms [ State ] ;
} else {
FIXME ( " Unhandled transform state!! \n " ) ;
}
2008-01-23 22:39:56 +01:00
multiply_matrix ( & temp , mat , pMatrix ) ;
2004-11-29 18:53:42 +01:00
/* Apply change via set transform - will reapply to eg. lights this way */
2005-08-22 11:13:49 +02:00
return IWineD3DDeviceImpl_SetTransform ( iface , State , & temp ) ;
2004-11-29 18:53:42 +01:00
}
/*****
* Get / Set Light
* * * * */
/* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2004-12-20 20:27:06 +01:00
you can reference any indexes you want as long as that number max are enabled at any
2007-02-19 15:24:26 +01:00
one point in time ! Therefore since the indexes can be anything , we need a hashmap of them .
However , this causes stateblock problems . When capturing the state block , I duplicate the hashmap ,
2004-11-29 18:53:42 +01:00
but when recording , just build a chain pretty much of commands to be replayed . */
2005-07-13 16:15:54 +02:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetLight ( IWineD3DDevice * iface , DWORD Index , CONST WINED3DLIGHT * pLight ) {
2004-11-29 18:53:42 +01:00
float rho ;
2007-02-14 17:46:54 +01:00
PLIGHTINFOEL * object = NULL ;
UINT Hi = LIGHTMAP_HASHFUNC ( Index ) ;
struct list * e ;
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-02-14 17:46:54 +01:00
TRACE ( " (%p) : Idx(%d), pLight(%p). Hash index is %d \n " , This , Index , pLight , Hi ) ;
2004-11-29 18:53:42 +01:00
2007-02-20 22:43:13 +01:00
/* Check the parameter range. Need for speed most wanted sets junk lights which confuse
* the gl driver .
*/
if ( ! pLight ) {
WARN ( " Light pointer = NULL, returning WINED3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
switch ( pLight - > Type ) {
case WINED3DLIGHT_POINT :
case WINED3DLIGHT_SPOT :
case WINED3DLIGHT_PARALLELPOINT :
case WINED3DLIGHT_GLSPOT :
/* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
* most wanted
*/
if ( pLight - > Attenuation0 < 0.0 | | pLight - > Attenuation1 < 0.0 | | pLight - > Attenuation2 < 0.0 ) {
WARN ( " Attenuation is negative, returning WINED3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
break ;
case WINED3DLIGHT_DIRECTIONAL :
/* Ignores attenuation */
break ;
default :
WARN ( " Light type out of range, returning WINED3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
2007-02-14 17:46:54 +01:00
LIST_FOR_EACH ( e , & This - > updateStateBlock - > lightMap [ Hi ] ) {
object = LIST_ENTRY ( e , PLIGHTINFOEL , entry ) ;
if ( object - > OriginalIndex = = Index ) break ;
object = NULL ;
2004-11-29 18:53:42 +01:00
}
2007-02-14 17:46:54 +01:00
if ( ! object ) {
TRACE ( " Adding new light \n " ) ;
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * object ) ) ;
if ( ! object ) {
ERR ( " Out of memory error when allocating a light \n " ) ;
return E_OUTOFMEMORY ;
2004-11-29 18:53:42 +01:00
}
2007-02-14 17:46:54 +01:00
list_add_head ( & This - > updateStateBlock - > lightMap [ Hi ] , & object - > entry ) ;
2004-11-29 18:53:42 +01:00
object - > glIndex = - 1 ;
2007-02-14 17:46:54 +01:00
object - > OriginalIndex = Index ;
object - > changed = TRUE ;
2004-11-29 18:53:42 +01:00
}
2005-11-23 20:14:43 +01:00
/* Initialize the object */
2006-10-01 05:20:10 +02:00
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 ,
2004-11-29 18:53:42 +01:00
pLight - > Diffuse . r , pLight - > Diffuse . g , pLight - > Diffuse . b , pLight - > Diffuse . a ,
pLight - > Specular . r , pLight - > Specular . g , pLight - > Specular . b , pLight - > Specular . a ,
pLight - > Ambient . r , pLight - > Ambient . g , pLight - > Ambient . b , pLight - > Ambient . a ) ;
TRACE ( " ... Pos(%f,%f,%f), Dirn(%f,%f,%f) \n " , pLight - > Position . x , pLight - > Position . y , pLight - > Position . z ,
pLight - > Direction . x , pLight - > Direction . y , pLight - > Direction . z ) ;
TRACE ( " ... Range(%f), Falloff(%f), Theta(%f), Phi(%f) \n " , pLight - > Range , pLight - > Falloff , pLight - > Theta , pLight - > Phi ) ;
/* Save away the information */
2008-03-20 23:25:13 +01:00
object - > OriginalParms = * pLight ;
2004-11-29 18:53:42 +01:00
switch ( pLight - > Type ) {
2006-10-11 03:55:47 +02:00
case WINED3DLIGHT_POINT :
2004-11-29 18:53:42 +01:00
/* Position */
object - > lightPosn [ 0 ] = pLight - > Position . x ;
object - > lightPosn [ 1 ] = pLight - > Position . y ;
object - > lightPosn [ 2 ] = pLight - > Position . z ;
object - > lightPosn [ 3 ] = 1.0f ;
object - > cutoff = 180.0f ;
/* FIXME: Range */
break ;
2006-10-11 03:55:47 +02:00
case WINED3DLIGHT_DIRECTIONAL :
2004-11-29 18:53:42 +01:00
/* Direction */
object - > lightPosn [ 0 ] = - pLight - > Direction . x ;
object - > lightPosn [ 1 ] = - pLight - > Direction . y ;
object - > lightPosn [ 2 ] = - pLight - > Direction . z ;
object - > lightPosn [ 3 ] = 0.0 ;
object - > exponent = 0.0f ;
object - > cutoff = 180.0f ;
break ;
2006-10-11 03:55:47 +02:00
case WINED3DLIGHT_SPOT :
2004-11-29 18:53:42 +01:00
/* Position */
object - > lightPosn [ 0 ] = pLight - > Position . x ;
object - > lightPosn [ 1 ] = pLight - > Position . y ;
object - > lightPosn [ 2 ] = pLight - > Position . z ;
object - > lightPosn [ 3 ] = 1.0 ;
/* Direction */
object - > lightDirn [ 0 ] = pLight - > Direction . x ;
object - > lightDirn [ 1 ] = pLight - > Direction . y ;
object - > lightDirn [ 2 ] = pLight - > Direction . z ;
object - > lightDirn [ 3 ] = 1.0 ;
/*
* opengl - ish and d3d - ish spot lights use too different models for the
* light " intensity " as a function of the angle towards the main light direction ,
* so we only can approximate very roughly .
* however spot lights are rather rarely used in games ( if ever used at all ) .
* furthermore if still used , probably nobody pays attention to such details .
*/
if ( pLight - > Falloff = = 0 ) {
2007-08-20 22:10:36 +02:00
/* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
* falloff resp . exponent parameter as an exponent , so the spot light lighting
* will always be 1.0 for both of them , and we don ' t have to care for the
* rest of the rather complex calculation
*/
object - > exponent = 0 ;
2004-11-29 18:53:42 +01:00
} else {
rho = pLight - > Theta + ( pLight - > Phi - pLight - > Theta ) / ( 2 * pLight - > Falloff ) ;
2007-08-20 22:10:36 +02:00
if ( rho < 0.0001 ) rho = 0.0001f ;
object - > exponent = - 0.3 / log ( cos ( rho / 2 ) ) ;
2004-11-29 18:53:42 +01:00
}
2009-01-09 10:23:43 +01:00
if ( object - > exponent > 128.0 ) {
object - > exponent = 128.0 ;
}
2004-11-29 18:53:42 +01:00
object - > cutoff = pLight - > Phi * 90 / M_PI ;
/* FIXME: Range */
break ;
default :
FIXME ( " Unrecognized light type %d \n " , pLight - > Type ) ;
}
/* Update the live definitions if the light is currently assigned a glIndex */
2007-02-14 17:46:54 +01:00
if ( object - > glIndex ! = - 1 & & ! This - > isRecordingState ) {
2007-02-14 17:48:52 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_ACTIVELIGHT ( object - > glIndex ) ) ;
2004-11-29 18:53:42 +01:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetLight ( IWineD3DDevice * iface , DWORD Index , WINED3DLIGHT * pLight ) {
2004-11-29 18:53:42 +01:00
PLIGHTINFOEL * lightInfo = NULL ;
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-02-14 17:46:54 +01:00
DWORD Hi = LIGHTMAP_HASHFUNC ( Index ) ;
struct list * e ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : Idx(%d), pLight(%p) \n " , This , Index , pLight ) ;
2005-07-13 16:15:54 +02:00
2007-02-14 17:46:54 +01:00
LIST_FOR_EACH ( e , & This - > stateBlock - > lightMap [ Hi ] ) {
lightInfo = LIST_ENTRY ( e , PLIGHTINFOEL , entry ) ;
if ( lightInfo - > OriginalIndex = = Index ) break ;
lightInfo = NULL ;
}
2004-11-29 18:53:42 +01:00
if ( lightInfo = = NULL ) {
TRACE ( " Light information requested but light not defined \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2004-11-29 18:53:42 +01:00
}
2008-03-20 23:25:13 +01:00
* pLight = lightInfo - > OriginalParms ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
/*****
2005-07-13 16:15:54 +02:00
* Get / Set Light Enable
2004-11-29 18:53:42 +01:00
* ( Note for consistency , renamed d3dx function by adding the ' set ' prefix )
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable ( IWineD3DDevice * iface , DWORD Index , BOOL Enable ) {
2004-11-29 18:53:42 +01:00
PLIGHTINFOEL * lightInfo = NULL ;
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-02-14 17:46:54 +01:00
UINT Hi = LIGHTMAP_HASHFUNC ( Index ) ;
struct list * e ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : Idx(%d), enable? %d \n " , This , Index , Enable ) ;
2004-11-29 18:53:42 +01:00
2007-02-14 17:46:54 +01:00
LIST_FOR_EACH ( e , & This - > updateStateBlock - > lightMap [ Hi ] ) {
lightInfo = LIST_ENTRY ( e , PLIGHTINFOEL , entry ) ;
if ( lightInfo - > OriginalIndex = = Index ) break ;
lightInfo = NULL ;
2004-11-29 18:53:42 +01:00
}
2007-02-14 17:46:54 +01:00
TRACE ( " Found light: %p \n " , lightInfo ) ;
2004-11-29 18:53:42 +01:00
/* Special case - enabling an undefined light creates one with a strict set of parms! */
if ( lightInfo = = NULL ) {
2006-06-07 05:37:05 +02:00
2005-07-13 16:15:54 +02:00
TRACE ( " Light enabled requested but light not defined, so defining one! \n " ) ;
2006-06-07 05:37:05 +02:00
IWineD3DDeviceImpl_SetLight ( iface , Index , & WINED3D_default_light ) ;
2004-11-29 18:53:42 +01:00
/* Search for it again! Should be fairly quick as near head of list */
2007-02-14 17:46:54 +01:00
LIST_FOR_EACH ( e , & This - > updateStateBlock - > lightMap [ Hi ] ) {
lightInfo = LIST_ENTRY ( e , PLIGHTINFOEL , entry ) ;
if ( lightInfo - > OriginalIndex = = Index ) break ;
lightInfo = NULL ;
}
2004-11-29 18:53:42 +01:00
if ( lightInfo = = NULL ) {
FIXME ( " Adding default lights has failed dismally \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2004-11-29 18:53:42 +01:00
}
}
2007-02-14 17:46:54 +01:00
lightInfo - > enabledChanged = TRUE ;
if ( ! Enable ) {
if ( lightInfo - > glIndex ! = - 1 ) {
if ( ! This - > isRecordingState ) {
2007-02-14 17:48:52 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_ACTIVELIGHT ( lightInfo - > glIndex ) ) ;
2007-02-14 17:46:54 +01:00
}
2004-11-29 18:53:42 +01:00
2008-10-03 08:55:41 +02:00
This - > updateStateBlock - > activeLights [ lightInfo - > glIndex ] = NULL ;
2007-02-14 17:46:54 +01:00
lightInfo - > glIndex = - 1 ;
2004-11-29 18:53:42 +01:00
} else {
2007-02-14 17:46:54 +01:00
TRACE ( " Light already disabled, nothing to do \n " ) ;
2004-11-29 18:53:42 +01:00
}
2007-11-29 13:22:47 +01:00
lightInfo - > enabled = FALSE ;
2004-11-29 18:53:42 +01:00
} else {
2007-11-29 13:22:47 +01:00
lightInfo - > enabled = TRUE ;
2007-02-14 17:46:54 +01:00
if ( lightInfo - > glIndex ! = - 1 ) {
2004-11-29 18:53:42 +01:00
/* nop */
TRACE ( " Nothing to do as light was enabled \n " ) ;
} else {
2007-02-14 17:46:54 +01:00
int i ;
/* Find a free gl light */
for ( i = 0 ; i < This - > maxConcurrentLights ; i + + ) {
2008-10-03 08:55:41 +02:00
if ( This - > updateStateBlock - > activeLights [ i ] = = NULL ) {
This - > updateStateBlock - > activeLights [ i ] = lightInfo ;
2007-02-14 17:46:54 +01:00
lightInfo - > glIndex = i ;
break ;
2004-11-29 18:53:42 +01:00
}
}
2007-02-14 17:46:54 +01:00
if ( lightInfo - > glIndex = = - 1 ) {
2007-11-29 13:22:47 +01:00
/* Our tests show that Windows returns D3D_OK in this situation, even with
* D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices . This
* is consistent among ddraw , d3d8 and d3d9 . GetLightEnable returns TRUE
* as well for those lights .
*
* TODO : Test how this affects rendering
*/
2008-12-29 16:31:22 +01:00
WARN ( " Too many concurrently active lights \n " ) ;
2007-11-29 13:22:47 +01:00
return WINED3D_OK ;
2007-02-14 17:46:54 +01:00
}
2004-11-29 18:53:42 +01:00
2007-02-14 17:46:54 +01:00
/* i == lightInfo->glIndex */
if ( ! This - > isRecordingState ) {
2007-02-14 17:48:52 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_ACTIVELIGHT ( i ) ) ;
2004-11-29 18:53:42 +01:00
}
}
}
2007-02-14 17:46:54 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable ( IWineD3DDevice * iface , DWORD Index , BOOL * pEnable ) {
2004-11-29 18:53:42 +01:00
PLIGHTINFOEL * lightInfo = NULL ;
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-02-14 17:46:54 +01:00
struct list * e ;
UINT Hi = LIGHTMAP_HASHFUNC ( Index ) ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : for idx(%d) \n " , This , Index ) ;
2005-07-13 16:15:54 +02:00
2007-02-14 17:46:54 +01:00
LIST_FOR_EACH ( e , & This - > stateBlock - > lightMap [ Hi ] ) {
lightInfo = LIST_ENTRY ( e , PLIGHTINFOEL , entry ) ;
if ( lightInfo - > OriginalIndex = = Index ) break ;
lightInfo = NULL ;
}
2004-11-29 18:53:42 +01:00
if ( lightInfo = = NULL ) {
TRACE ( " Light enabled state requested but light not defined \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2004-11-29 18:53:42 +01:00
}
2007-02-14 17:46:54 +01:00
/* true is 128 according to SetLightEnable */
2007-11-29 13:22:47 +01:00
* pEnable = lightInfo - > enabled ? 128 : 0 ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
/*****
* Get / Set Clip Planes
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane ( IWineD3DDevice * iface , DWORD Index , CONST float * pPlane ) {
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : for idx %d, %p \n " , This , Index , pPlane ) ;
2004-11-29 18:53:42 +01:00
/* Validate Index */
if ( Index > = GL_LIMITS ( clipplanes ) ) {
TRACE ( " Application has requested clipplane this device doesn't support \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2004-11-29 18:53:42 +01:00
}
2008-12-31 16:57:11 +01:00
This - > updateStateBlock - > changed . clipplane | = 1 < < Index ;
2007-02-28 14:36:36 +01:00
if ( This - > updateStateBlock - > clipplane [ Index ] [ 0 ] = = pPlane [ 0 ] & &
This - > updateStateBlock - > clipplane [ Index ] [ 1 ] = = pPlane [ 1 ] & &
This - > updateStateBlock - > clipplane [ Index ] [ 2 ] = = pPlane [ 2 ] & &
This - > updateStateBlock - > clipplane [ Index ] [ 3 ] = = pPlane [ 3 ] ) {
TRACE ( " Application is setting old values over, nothing to do \n " ) ;
return WINED3D_OK ;
}
2004-11-29 18:53:42 +01:00
This - > updateStateBlock - > clipplane [ Index ] [ 0 ] = pPlane [ 0 ] ;
This - > updateStateBlock - > clipplane [ Index ] [ 1 ] = pPlane [ 1 ] ;
This - > updateStateBlock - > clipplane [ Index ] [ 2 ] = pPlane [ 2 ] ;
This - > updateStateBlock - > clipplane [ Index ] [ 3 ] = pPlane [ 3 ] ;
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2007-02-28 14:36:36 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_CLIPPLANE ( Index ) ) ;
2004-11-29 18:53:42 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane ( IWineD3DDevice * iface , DWORD Index , float * pPlane ) {
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : for idx %d \n " , This , Index ) ;
2004-11-29 18:53:42 +01:00
/* Validate Index */
if ( Index > = GL_LIMITS ( clipplanes ) ) {
TRACE ( " Application has requested clipplane this device doesn't support \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2004-11-29 18:53:42 +01:00
}
pPlane [ 0 ] = This - > stateBlock - > clipplane [ Index ] [ 0 ] ;
pPlane [ 1 ] = This - > stateBlock - > clipplane [ Index ] [ 1 ] ;
pPlane [ 2 ] = This - > stateBlock - > clipplane [ Index ] [ 2 ] ;
pPlane [ 3 ] = This - > stateBlock - > clipplane [ Index ] [ 3 ] ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
/*****
* Get / Set Clip Plane Status
* WARNING : This code relies on the fact that D3DCLIPSTATUS8 = = D3DCLIPSTATUS9
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus ( IWineD3DDevice * iface , CONST WINED3DCLIPSTATUS * pClipStatus ) {
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
FIXME ( " (%p) : stub \n " , This ) ;
if ( NULL = = pClipStatus ) {
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2004-11-29 18:53:42 +01:00
}
This - > updateStateBlock - > clip_status . ClipUnion = pClipStatus - > ClipUnion ;
This - > updateStateBlock - > clip_status . ClipIntersection = pClipStatus - > ClipIntersection ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus ( IWineD3DDevice * iface , WINED3DCLIPSTATUS * pClipStatus ) {
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
FIXME ( " (%p) : stub \n " , This ) ;
2004-11-29 18:53:42 +01:00
if ( NULL = = pClipStatus ) {
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2004-11-29 18:53:42 +01:00
}
pClipStatus - > ClipUnion = This - > updateStateBlock - > clip_status . ClipUnion ;
pClipStatus - > ClipIntersection = This - > updateStateBlock - > clip_status . ClipIntersection ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
/*****
* Get / Set Material
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial ( IWineD3DDevice * iface , CONST WINED3DMATERIAL * pMaterial ) {
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
This - > updateStateBlock - > changed . material = TRUE ;
2008-03-20 23:25:13 +01:00
This - > updateStateBlock - > material = * pMaterial ;
2004-11-29 18:53:42 +01:00
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2007-06-15 21:33:54 +02:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_MATERIAL ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial ( IWineD3DDevice * iface , WINED3DMATERIAL * pMaterial ) {
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-03-20 23:25:13 +01:00
* pMaterial = This - > updateStateBlock - > material ;
2005-08-22 11:13:49 +02:00
TRACE ( " (%p) : Diffuse (%f,%f,%f,%f) \n " , This , pMaterial - > Diffuse . r , pMaterial - > Diffuse . g ,
pMaterial - > Diffuse . b , pMaterial - > Diffuse . a ) ;
TRACE ( " (%p) : Ambient (%f,%f,%f,%f) \n " , This , pMaterial - > Ambient . r , pMaterial - > Ambient . g ,
pMaterial - > Ambient . b , pMaterial - > Ambient . a ) ;
TRACE ( " (%p) : Specular (%f,%f,%f,%f) \n " , This , pMaterial - > Specular . r , pMaterial - > Specular . g ,
pMaterial - > Specular . b , pMaterial - > Specular . a ) ;
TRACE ( " (%p) : Emissive (%f,%f,%f,%f) \n " , This , pMaterial - > Emissive . r , pMaterial - > Emissive . g ,
pMaterial - > Emissive . b , pMaterial - > Emissive . a ) ;
2004-11-29 18:53:42 +01:00
TRACE ( " (%p) : Power (%f) \n " , This , pMaterial - > Power ) ;
2005-08-22 11:13:49 +02:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-29 18:53:42 +01:00
}
2004-12-09 12:42:34 +01:00
/*****
* Get / Set Indices
* * * * */
2009-04-09 10:50:31 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices ( IWineD3DDevice * iface , IWineD3DBuffer * pIndexData , WINED3DFORMAT fmt ) {
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-04-06 16:46:12 +02:00
IWineD3DBuffer * oldIdxs ;
2004-12-09 12:42:34 +01:00
2007-06-05 18:52:21 +02:00
TRACE ( " (%p) : Setting to %p \n " , This , pIndexData ) ;
2004-12-09 12:42:34 +01:00
oldIdxs = This - > updateStateBlock - > pIndexData ;
This - > updateStateBlock - > changed . indices = TRUE ;
This - > updateStateBlock - > pIndexData = pIndexData ;
2009-04-09 10:50:31 +02:00
This - > updateStateBlock - > IndexFmt = fmt ;
2004-12-09 12:42:34 +01:00
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2009-04-06 16:46:12 +02:00
if ( pIndexData ) IWineD3DBuffer_AddRef ( pIndexData ) ;
if ( oldIdxs ) IWineD3DBuffer_Release ( oldIdxs ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2007-02-19 15:25:32 +01:00
if ( oldIdxs ! = pIndexData ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_INDEXBUFFER ) ;
2009-04-06 13:38:56 +02:00
if ( pIndexData ) {
InterlockedIncrement ( & ( ( struct wined3d_buffer * ) pIndexData ) - > bind_count ) ;
2009-04-06 16:46:12 +02:00
IWineD3DBuffer_AddRef ( pIndexData ) ;
2009-04-06 13:38:56 +02:00
}
if ( oldIdxs ) {
InterlockedDecrement ( & ( ( struct wined3d_buffer * ) oldIdxs ) - > bind_count ) ;
2009-04-06 16:46:12 +02:00
IWineD3DBuffer_Release ( oldIdxs ) ;
2009-04-06 13:38:56 +02:00
}
2007-02-19 15:25:32 +01:00
}
2009-04-06 13:38:56 +02:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2009-04-06 16:46:12 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices ( IWineD3DDevice * iface , IWineD3DBuffer * * ppIndexData ) {
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
* ppIndexData = This - > stateBlock - > pIndexData ;
2005-07-13 16:15:54 +02:00
2006-11-30 13:33:18 +01:00
/* up ref count on ppindexdata */
2005-08-22 11:13:49 +02:00
if ( * ppIndexData ) {
2009-04-06 16:46:12 +02:00
IWineD3DBuffer_AddRef ( * ppIndexData ) ;
2007-06-06 18:40:09 +02:00
TRACE ( " (%p) index data set to %p \n " , This , ppIndexData ) ;
2005-08-22 11:13:49 +02:00
} else {
TRACE ( " (%p) No index data set \n " , This ) ;
}
2007-06-06 18:40:09 +02:00
TRACE ( " Returning %p \n " , * ppIndexData ) ;
2004-12-09 12:42:34 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2007-01-02 21:07:39 +01:00
/* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2007-08-25 00:09:33 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetBaseVertexIndex ( IWineD3DDevice * iface , INT BaseIndex ) {
2007-01-02 21:07:39 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p)->(%d) \n " , This , BaseIndex ) ;
if ( This - > updateStateBlock - > baseVertexIndex = = BaseIndex ) {
TRACE ( " Application is setting the old value over, nothing to do \n " ) ;
return WINED3D_OK ;
}
This - > updateStateBlock - > baseVertexIndex = BaseIndex ;
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
return WINED3D_OK ;
}
2007-06-05 18:52:21 +02:00
/* The base vertex index affects the stream sources */
2007-01-02 21:07:39 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_STREAMSRC ) ;
return WINED3D_OK ;
}
2007-08-25 00:09:33 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetBaseVertexIndex ( IWineD3DDevice * iface , INT * base_index ) {
2007-06-06 18:40:02 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p) : base_index %p \n " , This , base_index ) ;
* base_index = This - > stateBlock - > baseVertexIndex ;
TRACE ( " Returning %u \n " , * base_index ) ;
return WINED3D_OK ;
}
2004-12-09 12:42:34 +01:00
/*****
* Get / Set Viewports
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport ( IWineD3DDevice * iface , CONST WINED3DVIEWPORT * pViewport ) {
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p) \n " , This ) ;
This - > updateStateBlock - > changed . viewport = TRUE ;
2008-03-20 23:25:13 +01:00
This - > updateStateBlock - > viewport = * pViewport ;
2004-12-09 12:42:34 +01:00
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f \n " , This ,
2004-12-09 12:42:34 +01:00
pViewport - > X , pViewport - > Y , pViewport - > Width , pViewport - > Height , pViewport - > MinZ , pViewport - > MaxZ ) ;
2007-01-02 21:40:59 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VIEWPORT ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport ( IWineD3DDevice * iface , WINED3DVIEWPORT * pViewport ) {
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p) \n " , This ) ;
2008-03-20 23:25:13 +01:00
* pViewport = This - > stateBlock - > viewport ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2004-12-13 14:35:38 +01:00
/*****
* Get / Set Render States
* TODO : Verify against dx9 definitions
* * * * */
2006-10-12 08:19:57 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState ( IWineD3DDevice * iface , WINED3DRENDERSTATETYPE State , DWORD Value ) {
2004-12-13 14:35:38 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-12-15 19:16:36 +01:00
DWORD oldValue = This - > stateBlock - > renderState [ State ] ;
2005-07-13 16:15:54 +02:00
2006-10-01 05:20:10 +02:00
TRACE ( " (%p)->state = %s(%d), value = %d \n " , This , debug_d3drenderstate ( State ) , State , Value ) ;
2006-12-15 19:16:36 +01:00
2009-01-05 10:10:16 +01:00
This - > updateStateBlock - > changed . renderState [ State > > 5 ] | = 1 < < ( State & 0x1f ) ;
2004-12-13 14:35:38 +01:00
This - > updateStateBlock - > renderState [ State ] = Value ;
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-13 14:35:38 +01:00
}
2006-12-15 19:16:36 +01:00
/* Compared here and not before the assignment to allow proper stateblock recording */
if ( Value = = oldValue ) {
TRACE ( " Application is setting the old value over, nothing to do \n " ) ;
} else {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( State ) ) ;
}
2004-12-13 14:35:38 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-13 14:35:38 +01:00
}
2006-10-12 08:19:57 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState ( IWineD3DDevice * iface , WINED3DRENDERSTATETYPE State , DWORD * pValue ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) for State %d = %d \n " , This , State , This - > stateBlock - > renderState [ State ] ) ;
2005-03-02 13:16:10 +01:00
* pValue = This - > stateBlock - > renderState [ State ] ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-08-01 12:58:31 +02:00
/*****
2005-08-03 13:00:28 +02:00
* Get / Set Sampler States
2005-08-01 12:58:31 +02:00
* TODO : Verify against dx9 definitions
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState ( IWineD3DDevice * iface , DWORD Sampler , WINED3DSAMPLERSTATETYPE Type , DWORD Value ) {
2005-08-01 12:58:31 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-06-25 22:45:57 +02:00
DWORD oldValue ;
TRACE ( " (%p) : Sampler %#x, Type %s (%#x), Value %#x \n " ,
This , Sampler , debug_d3dsamplerstate ( Type ) , Type , Value ) ;
if ( Sampler > = WINED3DVERTEXTEXTURESAMPLER0 & & Sampler < = WINED3DVERTEXTEXTURESAMPLER3 ) {
Sampler - = ( WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS ) ;
}
2006-12-19 23:17:17 +01:00
2008-01-15 08:06:37 +01:00
if ( Sampler > = sizeof ( This - > stateBlock - > samplerState ) / sizeof ( This - > stateBlock - > samplerState [ 0 ] ) ) {
2008-01-24 14:03:10 +01:00
ERR ( " Current Sampler overflows sampleState0 array (sampler %d) \n " , Sampler ) ;
2008-01-15 08:06:37 +01:00
return WINED3D_OK ; /* Windows accepts overflowing this array ... we do not. */
}
2005-08-01 12:58:31 +02:00
/**
* SetSampler is designed to allow for more than the standard up to 8 textures
* and Geforce has stopped supporting more than 6 standard textures in openGL .
* So I have to use ARB for Gforce . ( maybe if the sampler > 4 then use ARB ? )
*
* http : //developer.nvidia.com/object/General_FAQ.html#t6
*
* There are two new settings for GForce
* the sampler one :
* GL_MAX_TEXTURE_IMAGE_UNITS_ARB
* and the texture one :
* GL_MAX_TEXTURE_COORDS_ARB .
* Ok GForce say it ' s ok to use glTexParameter / glGetTexParameter ( . . . ) .
* * * * * * * * * * * * * * * * * */
2006-06-09 23:47:16 +02:00
2007-06-25 22:45:57 +02:00
oldValue = This - > stateBlock - > samplerState [ Sampler ] [ Type ] ;
2005-08-01 12:58:31 +02:00
This - > updateStateBlock - > samplerState [ Sampler ] [ Type ] = Value ;
2009-01-05 10:10:16 +01:00
This - > updateStateBlock - > changed . samplerState [ Sampler ] | = 1 < < Type ;
2005-08-01 12:58:31 +02:00
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-08-01 12:58:31 +02:00
}
2006-12-19 23:17:17 +01:00
if ( oldValue = = Value ) {
TRACE ( " Application is setting the old value over, nothing to do \n " ) ;
return WINED3D_OK ;
}
2006-12-19 23:26:39 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( Sampler ) ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState ( IWineD3DDevice * iface , DWORD Sampler , WINED3DSAMPLERSTATETYPE Type , DWORD * Value ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-06-25 22:45:57 +02:00
TRACE ( " (%p) : Sampler %#x, Type %s (%#x) \n " ,
This , Sampler , debug_d3dsamplerstate ( Type ) , Type ) ;
if ( Sampler > = WINED3DVERTEXTEXTURESAMPLER0 & & Sampler < = WINED3DVERTEXTEXTURESAMPLER3 ) {
Sampler - = ( WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS ) ;
}
2008-01-15 08:06:37 +01:00
if ( Sampler > = sizeof ( This - > stateBlock - > samplerState ) / sizeof ( This - > stateBlock - > samplerState [ 0 ] ) ) {
2008-01-24 14:03:10 +01:00
ERR ( " Current Sampler overflows sampleState0 array (sampler %d) \n " , Sampler ) ;
2008-01-15 08:06:37 +01:00
return WINED3D_OK ; /* Windows accepts overflowing this array ... we do not. */
}
2006-10-29 01:55:55 +02:00
* Value = This - > stateBlock - > samplerState [ Sampler ] [ Type ] ;
2007-06-25 22:45:57 +02:00
TRACE ( " (%p) : Returning %#x \n " , This , * Value ) ;
2005-03-02 13:16:10 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect ( IWineD3DDevice * iface , CONST RECT * pRect ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
2007-01-10 11:28:42 +01:00
This - > updateStateBlock - > changed . scissorRect = TRUE ;
2007-02-20 22:47:38 +01:00
if ( EqualRect ( & This - > updateStateBlock - > scissorRect , pRect ) ) {
2007-02-19 15:25:16 +01:00
TRACE ( " App is setting the old scissor rectangle over, nothing to do \n " ) ;
return WINED3D_OK ;
}
2007-02-20 22:47:38 +01:00
CopyRect ( & This - > updateStateBlock - > scissorRect , pRect ) ;
2007-01-10 11:28:42 +01:00
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
return WINED3D_OK ;
}
2007-02-19 15:25:16 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SCISSORRECT ) ;
2005-08-01 12:58:31 +02:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect ( IWineD3DDevice * iface , RECT * pRect ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-02-13 20:55:43 +01:00
* pRect = This - > updateStateBlock - > scissorRect ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p)Returning a Scissor Rect of %d:%d-%d:%d \n " , This , pRect - > left , pRect - > top , pRect - > right , pRect - > bottom ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration ( IWineD3DDevice * iface , IWineD3DVertexDeclaration * pDecl ) {
2005-07-07 22:45:39 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-02-06 11:31:57 +01:00
IWineD3DVertexDeclaration * oldDecl = This - > updateStateBlock - > vertexDecl ;
2005-07-07 22:45:39 +02:00
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : pDecl=%p \n " , This , pDecl ) ;
2005-12-16 12:38:24 +01:00
This - > updateStateBlock - > vertexDecl = pDecl ;
This - > updateStateBlock - > changed . vertexDecl = TRUE ;
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2007-01-04 00:07:00 +01:00
return WINED3D_OK ;
} else if ( pDecl = = oldDecl ) {
/* Checked after the assignment to allow proper stateblock recording */
TRACE ( " Application is setting the old declaration over, nothing to do \n " ) ;
return WINED3D_OK ;
2005-12-16 12:38:24 +01:00
}
2007-01-02 00:35:07 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VDECL ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration ( IWineD3DDevice * iface , IWineD3DVertexDeclaration * * ppDecl ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p) : ppDecl=%p \n " , This , ppDecl ) ;
2005-07-13 16:15:54 +02:00
2005-12-14 10:50:27 +01:00
* ppDecl = This - > stateBlock - > vertexDecl ;
2005-03-02 13:16:10 +01:00
if ( NULL ! = * ppDecl ) IWineD3DVertexDeclaration_AddRef ( * ppDecl ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader ( IWineD3DDevice * iface , IWineD3DVertexShader * pShader ) {
2005-12-15 10:25:47 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DVertexShader * oldShader = This - > updateStateBlock - > vertexShader ;
2005-07-13 16:15:54 +02:00
2005-12-15 10:25:47 +01:00
This - > updateStateBlock - > vertexShader = pShader ;
2005-03-02 13:16:10 +01:00
This - > updateStateBlock - > changed . vertexShader = TRUE ;
2005-07-13 16:15:54 +02:00
2005-08-17 13:34:03 +02:00
if ( This - > isRecordingState ) {
2007-08-20 18:56:10 +02:00
if ( pShader ) IWineD3DVertexShader_AddRef ( pShader ) ;
if ( oldShader ) IWineD3DVertexShader_Release ( oldShader ) ;
2005-08-17 13:34:03 +02:00
TRACE ( " Recording... not performing anything \n " ) ;
2007-01-04 00:07:45 +01:00
return WINED3D_OK ;
} else if ( oldShader = = pShader ) {
/* Checked here to allow proper stateblock recording */
TRACE ( " App is setting the old shader over, nothing to do \n " ) ;
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-12-13 11:11:01 +01:00
TRACE ( " (%p) : setting pShader(%p) \n " , This , pShader ) ;
2007-08-20 18:56:10 +02:00
if ( pShader ) IWineD3DVertexShader_AddRef ( pShader ) ;
if ( oldShader ) IWineD3DVertexShader_Release ( oldShader ) ;
2007-01-02 00:35:07 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VSHADER ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader ( IWineD3DDevice * iface , IWineD3DVertexShader * * ppShader ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-22 11:13:49 +02:00
if ( NULL = = ppShader ) {
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-08-22 11:13:49 +02:00
}
* ppShader = This - > stateBlock - > vertexShader ;
if ( NULL ! = * ppShader )
2005-03-02 13:16:10 +01:00
IWineD3DVertexShader_AddRef ( * ppShader ) ;
2005-08-22 11:13:49 +02:00
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : returning %p \n " , This , * ppShader ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
CONST BOOL * srcData ,
UINT count ) {
2005-03-02 13:16:10 +01:00
2006-06-06 08:46:59 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-25 10:12:27 +01:00
unsigned int i , cnt = min ( count , MAX_CONST_B - start ) ;
2005-09-21 12:19:29 +02:00
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, srcData %p, start %d, count %d) \n " ,
iface , srcData , start , count ) ;
2005-09-21 12:19:29 +02:00
2009-03-25 10:12:27 +01:00
if ( ! srcData | | start > = MAX_CONST_B ) return WINED3DERR_INVALIDCALL ;
2005-09-21 12:19:29 +02:00
2006-06-06 23:17:35 +02:00
memcpy ( & This - > updateStateBlock - > vertexShaderConstantB [ start ] , srcData , cnt * sizeof ( BOOL ) ) ;
2006-07-03 03:26:03 +02:00
for ( i = 0 ; i < cnt ; i + + )
2006-07-21 15:19:04 +02:00
TRACE ( " Set BOOL constant %u to %s \n " , start + i , srcData [ i ] ? " true " : " false " ) ;
2005-09-21 12:19:29 +02:00
2005-12-20 11:46:52 +01:00
for ( i = start ; i < cnt + start ; + + i ) {
2008-12-02 18:41:33 +01:00
This - > updateStateBlock - > changed . vertexShaderConstantsB | = ( 1 < < i ) ;
2005-08-17 12:27:01 +02:00
}
2005-09-21 12:19:29 +02:00
2008-12-17 17:07:25 +01:00
if ( ! This - > isRecordingState ) IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VERTEXSHADERCONSTANT ) ;
2007-01-06 18:17:27 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
BOOL * dstData ,
UINT count ) {
2005-09-21 12:19:29 +02:00
2006-06-06 08:46:59 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-07-19 06:06:07 +02:00
int cnt = min ( count , MAX_CONST_B - start ) ;
2005-09-21 12:19:29 +02:00
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, dstData %p, start %d, count %d) \n " ,
iface , dstData , start , count ) ;
2005-09-21 12:19:29 +02:00
2006-06-06 08:46:59 +02:00
if ( dstData = = NULL | | cnt < 0 )
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-09-21 12:19:29 +02:00
2006-07-21 05:02:29 +02:00
memcpy ( dstData , & This - > stateBlock - > vertexShaderConstantB [ start ] , cnt * sizeof ( BOOL ) ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
CONST int * srcData ,
UINT count ) {
2005-09-21 12:19:29 +02:00
2005-12-20 11:46:52 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-25 10:12:27 +01:00
unsigned int i , cnt = min ( count , MAX_CONST_I - start ) ;
2005-03-02 13:16:10 +01:00
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, srcData %p, start %d, count %d) \n " ,
iface , srcData , start , count ) ;
2009-03-25 10:12:27 +01:00
if ( ! srcData | | start > = MAX_CONST_I ) return WINED3DERR_INVALIDCALL ;
2006-06-06 08:46:59 +02:00
2006-06-06 23:17:35 +02:00
memcpy ( & This - > updateStateBlock - > vertexShaderConstantI [ start * 4 ] , srcData , cnt * sizeof ( int ) * 4 ) ;
2006-07-03 03:26:03 +02:00
for ( i = 0 ; i < cnt ; i + + )
2006-07-21 15:19:04 +02:00
TRACE ( " Set INT constant %u to { %d, %d, %d, %d } \n " , start + i ,
2006-07-03 03:26:03 +02:00
srcData [ i * 4 ] , srcData [ i * 4 + 1 ] , srcData [ i * 4 + 2 ] , srcData [ i * 4 + 3 ] ) ;
2006-06-06 08:46:59 +02:00
for ( i = start ; i < cnt + start ; + + i ) {
2008-12-02 18:41:33 +01:00
This - > updateStateBlock - > changed . vertexShaderConstantsI | = ( 1 < < i ) ;
2006-06-06 08:46:59 +02:00
}
2008-12-17 17:07:25 +01:00
if ( ! This - > isRecordingState ) IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VERTEXSHADERCONSTANT ) ;
2007-01-06 18:17:27 +01:00
2006-06-06 08:46:59 +02:00
return WINED3D_OK ;
2005-12-20 11:46:52 +01:00
}
2005-09-21 12:19:29 +02:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
int * dstData ,
UINT count ) {
2005-12-20 11:46:52 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-07-19 06:06:07 +02:00
int cnt = min ( count , MAX_CONST_I - start ) ;
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, dstData %p, start %d, count %d) \n " ,
iface , dstData , start , count ) ;
2006-08-09 18:02:28 +02:00
if ( dstData = = NULL | | ( ( signed int ) MAX_CONST_I - ( signed int ) start ) < = ( signed int ) 0 )
2006-06-06 08:46:59 +02:00
return WINED3DERR_INVALIDCALL ;
2006-07-21 05:02:29 +02:00
memcpy ( dstData , & This - > stateBlock - > vertexShaderConstantI [ start * 4 ] , cnt * sizeof ( int ) * 4 ) ;
2006-06-06 08:46:59 +02:00
return WINED3D_OK ;
2005-12-20 11:46:52 +01:00
}
2005-09-21 12:19:29 +02:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
CONST float * srcData ,
UINT count ) {
2005-09-21 12:19:29 +02:00
2005-12-20 11:46:52 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-11-20 23:13:48 +01:00
UINT i ;
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, srcData %p, start %d, count %d) \n " ,
iface , srcData , start , count ) ;
2005-09-21 12:19:29 +02:00
2007-02-20 22:43:53 +01:00
/* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
2009-03-22 12:24:28 +01:00
if ( srcData = = NULL | | start + count > This - > d3d_vshader_constantF | | start > This - > d3d_vshader_constantF )
2006-06-06 08:46:59 +02:00
return WINED3DERR_INVALIDCALL ;
2007-02-20 22:43:53 +01:00
memcpy ( & This - > updateStateBlock - > vertexShaderConstantF [ start * 4 ] , srcData , count * sizeof ( float ) * 4 ) ;
if ( TRACE_ON ( d3d ) ) {
for ( i = 0 ; i < count ; i + + )
TRACE ( " Set FLOAT constant %u to { %f, %f, %f, %f } \n " , start + i ,
srcData [ i * 4 ] , srcData [ i * 4 + 1 ] , srcData [ i * 4 + 2 ] , srcData [ i * 4 + 3 ] ) ;
}
2006-06-06 08:46:59 +02:00
2008-12-17 17:07:25 +01:00
if ( ! This - > isRecordingState )
{
2008-12-17 17:07:25 +01:00
This - > shader_backend - > shader_update_float_vertex_constants ( iface , start , count ) ;
2008-12-17 17:07:25 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VERTEXSHADERCONSTANT ) ;
}
2008-03-04 02:30:23 +01:00
2008-12-17 17:07:24 +01:00
memset ( This - > updateStateBlock - > changed . vertexShaderConstantsF + start , 1 ,
sizeof ( * This - > updateStateBlock - > changed . vertexShaderConstantsF ) * count ) ;
2008-03-04 02:30:23 +01:00
return WINED3D_OK ;
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
float * dstData ,
UINT count ) {
2005-12-20 11:46:52 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-22 12:24:28 +01:00
int cnt = min ( count , This - > d3d_vshader_constantF - start ) ;
2005-09-21 12:19:29 +02:00
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, dstData %p, start %d, count %d) \n " ,
iface , dstData , start , count ) ;
2005-03-02 13:16:10 +01:00
2006-06-06 08:46:59 +02:00
if ( dstData = = NULL | | cnt < 0 )
return WINED3DERR_INVALIDCALL ;
2006-07-21 05:02:29 +02:00
memcpy ( dstData , & This - > stateBlock - > vertexShaderConstantF [ start * 4 ] , cnt * sizeof ( float ) * 4 ) ;
2006-06-06 08:46:59 +02:00
return WINED3D_OK ;
2005-11-29 17:05:54 +01:00
}
2006-12-19 23:33:34 +01:00
static inline void markTextureStagesDirty ( IWineD3DDeviceImpl * This , DWORD stage ) {
DWORD i ;
2009-01-06 11:43:45 +01:00
for ( i = 0 ; i < = WINED3D_HIGHEST_TEXTURE_STATE ; + + i )
{
2006-12-19 23:33:34 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( stage , i ) ) ;
}
}
2007-06-22 20:43:19 +02:00
static void device_map_stage ( IWineD3DDeviceImpl * This , int stage , int unit ) {
int i = This - > rev_tex_unit_map [ unit ] ;
int j = This - > texUnitMap [ stage ] ;
This - > texUnitMap [ stage ] = unit ;
if ( i ! = - 1 & & i ! = stage ) {
This - > texUnitMap [ i ] = - 1 ;
}
This - > rev_tex_unit_map [ unit ] = stage ;
if ( j ! = - 1 & & j ! = unit ) {
This - > rev_tex_unit_map [ j ] = - 1 ;
}
}
2007-06-22 20:43:24 +02:00
static void device_update_fixed_function_usage_map ( IWineD3DDeviceImpl * This ) {
int i ;
2008-12-30 14:56:49 +01:00
This - > fixed_function_usage_map = 0 ;
2007-06-22 20:43:24 +02:00
for ( i = 0 ; i < MAX_TEXTURES ; + + i ) {
2007-06-27 23:47:24 +02:00
WINED3DTEXTUREOP color_op = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_COLOROP ] ;
WINED3DTEXTUREOP alpha_op = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_ALPHAOP ] ;
DWORD color_arg1 = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_COLORARG1 ] & WINED3DTA_SELECTMASK ;
DWORD color_arg2 = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_COLORARG2 ] & WINED3DTA_SELECTMASK ;
DWORD color_arg3 = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_COLORARG0 ] & WINED3DTA_SELECTMASK ;
DWORD alpha_arg1 = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_ALPHAARG1 ] & WINED3DTA_SELECTMASK ;
DWORD alpha_arg2 = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_ALPHAARG2 ] & WINED3DTA_SELECTMASK ;
DWORD alpha_arg3 = This - > stateBlock - > textureState [ i ] [ WINED3DTSS_ALPHAARG0 ] & WINED3DTA_SELECTMASK ;
if ( color_op = = WINED3DTOP_DISABLE ) {
/* Not used, and disable higher stages */
break ;
}
if ( ( ( color_arg1 = = WINED3DTA_TEXTURE ) & & color_op ! = WINED3DTOP_SELECTARG2 )
| | ( ( color_arg2 = = WINED3DTA_TEXTURE ) & & color_op ! = WINED3DTOP_SELECTARG1 )
| | ( ( color_arg3 = = WINED3DTA_TEXTURE ) & & ( color_op = = WINED3DTOP_MULTIPLYADD | | color_op = = WINED3DTOP_LERP ) )
| | ( ( alpha_arg1 = = WINED3DTA_TEXTURE ) & & alpha_op ! = WINED3DTOP_SELECTARG2 )
| | ( ( alpha_arg2 = = WINED3DTA_TEXTURE ) & & alpha_op ! = WINED3DTOP_SELECTARG1 )
| | ( ( alpha_arg3 = = WINED3DTA_TEXTURE ) & & ( alpha_op = = WINED3DTOP_MULTIPLYADD | | alpha_op = = WINED3DTOP_LERP ) ) ) {
2008-12-30 14:56:49 +01:00
This - > fixed_function_usage_map | = ( 1 < < i ) ;
2007-06-27 23:47:24 +02:00
}
if ( ( color_op = = WINED3DTOP_BUMPENVMAP | | color_op = = WINED3DTOP_BUMPENVMAPLUMINANCE ) & & i < MAX_TEXTURES - 1 ) {
2008-12-30 14:56:49 +01:00
This - > fixed_function_usage_map | = ( 1 < < ( i + 1 ) ) ;
2007-06-27 23:47:24 +02:00
}
2007-06-22 20:43:24 +02:00
}
}
2007-06-22 20:43:29 +02:00
static void device_map_fixed_function_samplers ( IWineD3DDeviceImpl * This ) {
2009-03-25 10:12:27 +01:00
unsigned int i , tex ;
2008-12-31 16:57:10 +01:00
WORD ffu_map ;
2007-06-22 20:43:29 +02:00
device_update_fixed_function_usage_map ( This ) ;
2008-12-31 16:57:10 +01:00
ffu_map = This - > fixed_function_usage_map ;
2007-06-22 20:43:29 +02:00
2008-08-21 20:23:38 +02:00
if ( This - > max_ffp_textures = = This - > max_ffp_texture_stages | |
2008-12-31 16:57:10 +01:00
This - > stateBlock - > lowest_disabled_stage < = This - > max_ffp_textures ) {
for ( i = 0 ; ffu_map ; ffu_map > > = 1 , + + i )
{
if ( ! ( ffu_map & 1 ) ) continue ;
2007-06-28 23:32:38 +02:00
2007-06-22 20:43:38 +02:00
if ( This - > texUnitMap [ i ] ! = i ) {
device_map_stage ( This , i , i ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( i ) ) ;
2007-06-28 23:32:38 +02:00
markTextureStagesDirty ( This , i ) ;
2007-06-22 20:43:38 +02:00
}
}
return ;
}
2007-06-22 20:43:29 +02:00
/* Now work out the mapping */
tex = 0 ;
2008-12-31 16:57:10 +01:00
for ( i = 0 ; ffu_map ; ffu_map > > = 1 , + + i )
{
if ( ! ( ffu_map & 1 ) ) continue ;
2007-06-22 20:43:29 +02:00
if ( This - > texUnitMap [ i ] ! = tex ) {
device_map_stage ( This , i , tex ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( i ) ) ;
markTextureStagesDirty ( This , i ) ;
}
+ + tex ;
}
}
2007-06-22 20:43:42 +02:00
static void device_map_psamplers ( IWineD3DDeviceImpl * This ) {
2009-04-29 09:55:06 +02:00
const WINED3DSAMPLER_TEXTURE_TYPE * sampler_type =
( ( IWineD3DPixelShaderImpl * ) This - > stateBlock - > pixelShader ) - > baseShader . reg_maps . sampler_type ;
2009-03-25 10:12:27 +01:00
unsigned int i ;
2007-06-22 20:43:42 +02:00
2007-06-25 22:45:40 +02:00
for ( i = 0 ; i < MAX_FRAGMENT_SAMPLERS ; + + i ) {
2009-04-29 09:55:06 +02:00
if ( sampler_type [ i ] & & This - > texUnitMap [ i ] ! = i )
{
2007-06-22 20:43:42 +02:00
device_map_stage ( This , i , i ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( i ) ) ;
if ( i < MAX_TEXTURES ) {
markTextureStagesDirty ( This , i ) ;
}
}
}
}
2008-11-26 16:14:39 +01:00
static BOOL device_unit_free_for_vs ( IWineD3DDeviceImpl * This , const DWORD * pshader_sampler_tokens ,
const DWORD * vshader_sampler_tokens , int unit )
{
2007-06-27 23:47:06 +02:00
int current_mapping = This - > rev_tex_unit_map [ unit ] ;
if ( current_mapping = = - 1 ) {
/* Not currently used */
return TRUE ;
}
if ( current_mapping < MAX_FRAGMENT_SAMPLERS ) {
/* Used by a fragment sampler */
if ( ! pshader_sampler_tokens ) {
/* No pixel shader, check fixed function */
2008-12-30 14:56:49 +01:00
return current_mapping > = MAX_TEXTURES | | ! ( This - > fixed_function_usage_map & ( 1 < < current_mapping ) ) ;
2007-06-27 23:47:06 +02:00
}
/* Pixel shader, check the shader's sampler map */
return ! pshader_sampler_tokens [ current_mapping ] ;
}
/* Used by a vertex sampler */
return ! vshader_sampler_tokens [ current_mapping ] ;
}
static void device_map_vsamplers ( IWineD3DDeviceImpl * This , BOOL ps ) {
2009-04-29 09:55:06 +02:00
const WINED3DSAMPLER_TEXTURE_TYPE * vshader_sampler_type =
( ( IWineD3DVertexShaderImpl * ) This - > stateBlock - > vertexShader ) - > baseShader . reg_maps . sampler_type ;
const WINED3DSAMPLER_TEXTURE_TYPE * pshader_sampler_type = NULL ;
2007-06-27 23:47:06 +02:00
int start = GL_LIMITS ( combined_samplers ) - 1 ;
int i ;
if ( ps ) {
IWineD3DPixelShaderImpl * pshader = ( IWineD3DPixelShaderImpl * ) This - > stateBlock - > pixelShader ;
2008-12-12 09:33:51 +01:00
/* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
* Otherwise we ' d need to call shader_update_samplers ( ) here for 1. x pixelshaders . */
2009-04-29 09:55:06 +02:00
pshader_sampler_type = pshader - > baseShader . reg_maps . sampler_type ;
2007-06-27 23:47:06 +02:00
}
for ( i = 0 ; i < MAX_VERTEX_SAMPLERS ; + + i ) {
int vsampler_idx = i + MAX_FRAGMENT_SAMPLERS ;
2009-04-29 09:55:06 +02:00
if ( vshader_sampler_type [ i ] )
{
2009-03-09 14:31:28 +01:00
if ( This - > texUnitMap [ vsampler_idx ] ! = WINED3D_UNMAPPED_STAGE )
{
2007-06-27 23:47:06 +02:00
/* Already mapped somewhere */
continue ;
}
while ( start > = 0 ) {
2009-04-29 09:55:06 +02:00
if ( device_unit_free_for_vs ( This , pshader_sampler_type , vshader_sampler_type , start ) )
{
2007-06-27 23:47:06 +02:00
device_map_stage ( This , vsampler_idx , start ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( vsampler_idx ) ) ;
- - start ;
break ;
}
- - start ;
}
}
}
}
2007-06-12 23:08:22 +02:00
void IWineD3DDeviceImpl_FindTexUnitMap ( IWineD3DDeviceImpl * This ) {
2008-12-30 14:56:49 +01:00
BOOL vs = use_vs ( This - > stateBlock ) ;
BOOL ps = use_ps ( This - > stateBlock ) ;
2007-07-01 23:40:57 +02:00
/*
2006-12-19 23:33:34 +01:00
* Rules are :
* - > Pixel shaders need a 1 : 1 map . In theory the shader input could be mapped too , but
* that would be really messy and require shader recompilation
* - > When the mapping of a stage is changed , sampler and ALL texture stage states have
* to be reset . Because of that try to work with a 1 : 1 mapping as much as possible
*/
2007-06-22 20:43:42 +02:00
if ( ps ) {
device_map_psamplers ( This ) ;
2006-12-19 23:33:34 +01:00
} else {
2007-06-22 20:43:29 +02:00
device_map_fixed_function_samplers ( This ) ;
2006-12-19 23:33:34 +01:00
}
2007-06-27 23:47:06 +02:00
if ( vs ) {
device_map_vsamplers ( This , ps ) ;
}
2006-12-19 23:33:34 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader ( IWineD3DDevice * iface , IWineD3DPixelShader * pShader ) {
2005-08-25 21:24:21 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-12-15 10:25:47 +01:00
IWineD3DPixelShader * oldShader = This - > updateStateBlock - > pixelShader ;
2005-08-25 21:24:21 +02:00
This - > updateStateBlock - > pixelShader = pShader ;
This - > updateStateBlock - > changed . pixelShader = TRUE ;
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
2005-11-21 17:27:55 +01:00
TRACE ( " Recording... not performing anything \n " ) ;
2005-08-25 21:24:21 +02:00
}
2005-12-13 11:11:01 +01:00
2006-12-19 23:22:19 +01:00
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2007-08-20 18:56:10 +02:00
if ( pShader ) IWineD3DPixelShader_AddRef ( pShader ) ;
if ( oldShader ) IWineD3DPixelShader_Release ( oldShader ) ;
2006-12-19 23:22:19 +01:00
return WINED3D_OK ;
2005-12-15 10:25:47 +01:00
}
2006-12-19 23:22:48 +01:00
if ( pShader = = oldShader ) {
TRACE ( " App is setting the old pixel shader over, nothing to do \n " ) ;
return WINED3D_OK ;
}
2007-08-20 18:56:10 +02:00
if ( pShader ) IWineD3DPixelShader_AddRef ( pShader ) ;
if ( oldShader ) IWineD3DPixelShader_Release ( oldShader ) ;
2005-12-13 11:11:01 +01:00
TRACE ( " (%p) : setting pShader(%p) \n " , This , pShader ) ;
2006-12-19 23:22:19 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADER ) ;
2006-12-19 23:33:34 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader ( IWineD3DDevice * iface , IWineD3DPixelShader * * ppShader ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-25 21:24:21 +02:00
2005-11-21 17:27:55 +01:00
if ( NULL = = ppShader ) {
2005-08-25 21:24:21 +02:00
WARN ( " (%p) : PShader is NULL, returning INVALIDCALL \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-08-25 21:24:21 +02:00
}
2006-01-20 16:13:12 +01:00
* ppShader = This - > stateBlock - > pixelShader ;
2006-04-14 02:48:59 +02:00
if ( NULL ! = * ppShader ) {
2005-08-25 21:24:21 +02:00
IWineD3DPixelShader_AddRef ( * ppShader ) ;
}
TRACE ( " (%p) : returning %p \n " , This , * ppShader ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
CONST BOOL * srcData ,
UINT count ) {
2005-08-25 21:24:21 +02:00
2006-06-06 08:46:59 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-25 10:12:27 +01:00
unsigned int i , cnt = min ( count , MAX_CONST_B - start ) ;
2005-08-25 21:24:21 +02:00
2009-03-25 10:12:27 +01:00
TRACE ( " (iface %p, srcData %p, start %u, count %u) \n " ,
2006-06-06 08:46:59 +02:00
iface , srcData , start , count ) ;
2005-03-02 13:16:10 +01:00
2009-03-25 10:12:27 +01:00
if ( ! srcData | | start > = MAX_CONST_B ) return WINED3DERR_INVALIDCALL ;
2005-09-28 12:13:00 +02:00
2006-06-06 23:17:35 +02:00
memcpy ( & This - > updateStateBlock - > pixelShaderConstantB [ start ] , srcData , cnt * sizeof ( BOOL ) ) ;
2006-07-03 03:26:03 +02:00
for ( i = 0 ; i < cnt ; i + + )
2006-07-19 06:06:07 +02:00
TRACE ( " Set BOOL constant %u to %s \n " , start + i , srcData [ i ] ? " true " : " false " ) ;
2005-09-28 12:13:00 +02:00
2005-12-20 11:46:52 +01:00
for ( i = start ; i < cnt + start ; + + i ) {
2008-12-02 18:41:33 +01:00
This - > updateStateBlock - > changed . pixelShaderConstantsB | = ( 1 < < i ) ;
2005-08-25 21:24:21 +02:00
}
2005-09-28 12:13:00 +02:00
2008-12-17 17:07:25 +01:00
if ( ! This - > isRecordingState ) IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADERCONSTANT ) ;
2007-01-06 18:17:27 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
BOOL * dstData ,
UINT count ) {
2005-09-28 12:13:00 +02:00
2006-06-06 08:46:59 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-07-19 06:06:07 +02:00
int cnt = min ( count , MAX_CONST_B - start ) ;
2005-12-20 11:46:52 +01:00
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, dstData %p, start %d, count %d) \n " ,
iface , dstData , start , count ) ;
2005-11-21 17:27:55 +01:00
2006-06-06 08:46:59 +02:00
if ( dstData = = NULL | | cnt < 0 )
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-09-28 12:13:00 +02:00
2006-07-21 05:02:29 +02:00
memcpy ( dstData , & This - > stateBlock - > pixelShaderConstantB [ start ] , cnt * sizeof ( BOOL ) ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
CONST int * srcData ,
UINT count ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-25 10:12:27 +01:00
unsigned int i , cnt = min ( count , MAX_CONST_I - start ) ;
2005-09-28 12:13:00 +02:00
2009-03-25 10:12:27 +01:00
TRACE ( " (iface %p, srcData %p, start %u, count %u) \n " ,
2006-06-06 08:46:59 +02:00
iface , srcData , start , count ) ;
2005-09-28 12:13:00 +02:00
2009-03-25 10:12:27 +01:00
if ( ! srcData | | start > = MAX_CONST_I ) return WINED3DERR_INVALIDCALL ;
2006-06-06 08:46:59 +02:00
2006-06-06 23:17:35 +02:00
memcpy ( & This - > updateStateBlock - > pixelShaderConstantI [ start * 4 ] , srcData , cnt * sizeof ( int ) * 4 ) ;
2006-07-03 03:26:03 +02:00
for ( i = 0 ; i < cnt ; i + + )
2006-07-19 06:06:07 +02:00
TRACE ( " Set INT constant %u to { %d, %d, %d, %d } \n " , start + i ,
2006-07-03 03:26:03 +02:00
srcData [ i * 4 ] , srcData [ i * 4 + 1 ] , srcData [ i * 4 + 2 ] , srcData [ i * 4 + 3 ] ) ;
2006-06-06 08:46:59 +02:00
for ( i = start ; i < cnt + start ; + + i ) {
2008-12-02 18:41:33 +01:00
This - > updateStateBlock - > changed . pixelShaderConstantsI | = ( 1 < < i ) ;
2006-06-06 08:46:59 +02:00
}
2005-09-28 12:13:00 +02:00
2008-12-17 17:07:25 +01:00
if ( ! This - > isRecordingState ) IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADERCONSTANT ) ;
2007-01-06 18:17:27 +01:00
2006-06-06 08:46:59 +02:00
return WINED3D_OK ;
2005-12-20 11:46:52 +01:00
}
2005-09-28 12:13:00 +02:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
int * dstData ,
UINT count ) {
2005-12-20 11:46:52 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-07-19 06:06:07 +02:00
int cnt = min ( count , MAX_CONST_I - start ) ;
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, dstData %p, start %d, count %d) \n " ,
iface , dstData , start , count ) ;
if ( dstData = = NULL | | cnt < 0 )
return WINED3DERR_INVALIDCALL ;
2006-07-21 05:02:29 +02:00
memcpy ( dstData , & This - > stateBlock - > pixelShaderConstantI [ start * 4 ] , cnt * sizeof ( int ) * 4 ) ;
2006-06-06 08:46:59 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
CONST float * srcData ,
UINT count ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-11-20 23:13:48 +01:00
UINT i ;
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, srcData %p, start %d, count %d) \n " ,
iface , srcData , start , count ) ;
2007-02-20 22:43:53 +01:00
/* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
2009-03-22 12:24:28 +01:00
if ( srcData = = NULL | | start + count > This - > d3d_pshader_constantF | | start > This - > d3d_pshader_constantF )
2006-06-06 08:46:59 +02:00
return WINED3DERR_INVALIDCALL ;
2007-02-20 22:43:53 +01:00
memcpy ( & This - > updateStateBlock - > pixelShaderConstantF [ start * 4 ] , srcData , count * sizeof ( float ) * 4 ) ;
if ( TRACE_ON ( d3d ) ) {
for ( i = 0 ; i < count ; i + + )
TRACE ( " Set FLOAT constant %u to { %f, %f, %f, %f } \n " , start + i ,
srcData [ i * 4 ] , srcData [ i * 4 + 1 ] , srcData [ i * 4 + 2 ] , srcData [ i * 4 + 3 ] ) ;
}
2006-06-06 08:46:59 +02:00
2008-12-17 17:07:25 +01:00
if ( ! This - > isRecordingState )
{
2008-12-17 17:07:25 +01:00
This - > shader_backend - > shader_update_float_pixel_constants ( iface , start , count ) ;
2008-12-17 17:07:25 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADERCONSTANT ) ;
}
2008-03-04 02:30:23 +01:00
2008-12-17 17:07:24 +01:00
memset ( This - > updateStateBlock - > changed . pixelShaderConstantsF + start , 1 ,
sizeof ( * This - > updateStateBlock - > changed . pixelShaderConstantsF ) * count ) ;
2008-03-04 02:30:23 +01:00
return WINED3D_OK ;
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF (
2006-06-06 08:46:59 +02:00
IWineD3DDevice * iface ,
UINT start ,
float * dstData ,
UINT count ) {
2004-12-13 14:35:38 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-22 12:24:28 +01:00
int cnt = min ( count , This - > d3d_pshader_constantF - start ) ;
2005-09-28 12:13:00 +02:00
2006-06-06 08:46:59 +02:00
TRACE ( " (iface %p, dstData %p, start %d, count %d) \n " ,
iface , dstData , start , count ) ;
2004-12-13 14:35:38 +01:00
2006-06-06 08:46:59 +02:00
if ( dstData = = NULL | | cnt < 0 )
return WINED3DERR_INVALIDCALL ;
2006-07-21 05:02:29 +02:00
memcpy ( dstData , & This - > stateBlock - > pixelShaderConstantF [ start * 4 ] , cnt * sizeof ( float ) * 4 ) ;
2006-06-06 08:46:59 +02:00
return WINED3D_OK ;
2005-11-29 17:05:54 +01:00
}
2009-06-26 10:07:12 +02:00
/* Context activation is done by the caller. */
2006-05-12 22:21:31 +02:00
# define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
2008-11-26 16:14:39 +01:00
static HRESULT process_vertices_strided ( IWineD3DDeviceImpl * This , DWORD dwDestIndex , DWORD dwCount ,
2009-04-06 14:16:59 +02:00
const struct wined3d_stream_info * stream_info , struct wined3d_buffer * dest , DWORD dwFlags ,
DWORD DestFVF )
2008-11-26 16:14:39 +01:00
{
2007-02-20 23:00:02 +01:00
char * dest_ptr , * dest_conv = NULL , * dest_conv_addr = NULL ;
2006-05-12 22:21:31 +02:00
unsigned int i ;
2006-10-11 03:57:25 +02:00
WINED3DVIEWPORT vp ;
2006-10-12 08:21:39 +02:00
WINED3DMATRIX mat , proj_mat , view_mat , world_mat ;
2006-05-12 22:21:31 +02:00
BOOL doClip ;
2008-11-20 23:13:48 +01:00
DWORD numTextures ;
2006-05-12 22:21:31 +02:00
2009-03-27 10:25:55 +01:00
if ( stream_info - > elements [ WINED3D_FFP_NORMAL ] . data )
{
2006-05-12 22:21:31 +02:00
WARN ( " lighting state not saved yet... Some strange stuff may happen ! \n " ) ;
}
2009-03-27 10:25:55 +01:00
if ( ! stream_info - > elements [ WINED3D_FFP_POSITION ] . data )
{
2006-05-12 22:21:31 +02:00
ERR ( " Source has no position mask \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
2006-06-21 15:05:38 +02:00
/* We might access VBOs from this code, so hold the lock */
ENTER_GL ( ) ;
2006-05-12 22:21:31 +02:00
if ( dest - > resource . allocatedMemory = = NULL ) {
2009-04-19 20:42:08 +02:00
buffer_get_sysmem ( dest ) ;
2006-06-21 15:05:38 +02:00
}
/* Get a pointer into the destination vbo(create one if none exists) and
* write correct opengl data into it . It ' s cheap and allows us to run drawStridedFast
*/
2009-03-06 14:56:23 +01:00
if ( ! dest - > buffer_object & & GL_SUPPORT ( ARB_VERTEX_BUFFER_OBJECT ) )
{
dest - > flags | = WINED3D_BUFFER_CREATEBO ;
IWineD3DBuffer_PreLoad ( ( IWineD3DBuffer * ) dest ) ;
2006-06-21 15:05:38 +02:00
}
2009-03-06 14:56:23 +01:00
if ( dest - > buffer_object )
{
2007-05-06 18:39:29 +02:00
unsigned char extrabytes = 0 ;
/* If the destination vertex buffer has D3DFVF_XYZ position(non-rhw), native d3d writes RHW position, where the RHW
* gets written into the 4 bytes after the Z position . In the case of a dest buffer that only has D3DFVF_XYZ data ,
* this may write 4 extra bytes beyond the area that should be written
*/
if ( DestFVF = = WINED3DFVF_XYZ ) extrabytes = 4 ;
dest_conv_addr = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , dwCount * get_flexible_vertex_size ( DestFVF ) + extrabytes ) ;
2007-02-20 23:00:02 +01:00
if ( ! dest_conv_addr ) {
ERR ( " Out of memory \n " ) ;
2006-06-21 15:05:38 +02:00
/* Continue without storing converted vertices */
}
2007-02-20 23:00:02 +01:00
dest_conv = dest_conv_addr ;
2006-05-12 22:21:31 +02:00
}
/* Should I clip?
2006-10-12 08:19:57 +02:00
* a ) WINED3DRS_CLIPPING is enabled
2006-05-12 22:21:31 +02:00
* b ) WINED3DVOP_CLIP is passed
*/
2006-05-24 10:46:06 +02:00
if ( This - > stateBlock - > renderState [ WINED3DRS_CLIPPING ] ) {
2006-05-12 22:21:31 +02:00
static BOOL warned = FALSE ;
/*
* The clipping code is not quite correct . Some things need
* to be checked against IDirect3DDevice3 ( ! ) , d3d8 and d3d9 ,
* so disable clipping for now .
* ( The graphics in Half - Life are broken , and my processvertices
* test crashes with IDirect3DDevice3 )
doClip = TRUE ;
*/
doClip = FALSE ;
if ( ! warned ) {
warned = TRUE ;
FIXME ( " Clipping is broken and disabled for now \n " ) ;
}
} else doClip = FALSE ;
2009-04-09 18:40:57 +02:00
dest_ptr = ( ( char * ) buffer_get_sysmem ( dest ) ) + dwDestIndex * get_flexible_vertex_size ( DestFVF ) ;
2006-05-12 22:21:31 +02:00
IWineD3DDevice_GetTransform ( ( IWineD3DDevice * ) This ,
2006-07-24 04:54:30 +02:00
WINED3DTS_VIEW ,
2006-05-12 22:21:31 +02:00
& view_mat ) ;
IWineD3DDevice_GetTransform ( ( IWineD3DDevice * ) This ,
2006-07-24 04:54:30 +02:00
WINED3DTS_PROJECTION ,
2006-05-12 22:21:31 +02:00
& proj_mat ) ;
IWineD3DDevice_GetTransform ( ( IWineD3DDevice * ) This ,
2006-07-24 04:54:30 +02:00
WINED3DTS_WORLDMATRIX ( 0 ) ,
2006-05-12 22:21:31 +02:00
& world_mat ) ;
2006-06-15 17:41:17 +02:00
TRACE ( " View mat: \n " ) ;
2007-01-09 00:39:30 +01:00
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 ) ;
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 ) ;
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 ) ;
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 ) ;
2006-05-12 22:21:31 +02:00
2006-06-15 17:41:17 +02:00
TRACE ( " Proj mat: \n " ) ;
2007-01-09 00:39:30 +01:00
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 ) ;
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 ) ;
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 ) ;
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 ) ;
2006-05-12 22:21:31 +02:00
2006-06-15 17:41:17 +02:00
TRACE ( " World mat: \n " ) ;
2007-01-09 00:39:30 +01:00
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 ) ;
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 ) ;
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 ) ;
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 ) ;
2006-05-12 22:21:31 +02:00
/* Get the viewport */
IWineD3DDevice_GetViewport ( ( IWineD3DDevice * ) This , & vp ) ;
2006-10-01 05:20:10 +02:00
TRACE ( " Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f \n " ,
2006-05-12 22:21:31 +02:00
vp . X , vp . Y , vp . Width , vp . Height , vp . MinZ , vp . MaxZ ) ;
multiply_matrix ( & mat , & view_mat , & world_mat ) ;
multiply_matrix ( & mat , & proj_mat , & mat ) ;
2006-10-31 09:16:08 +01:00
numTextures = ( DestFVF & WINED3DFVF_TEXCOUNT_MASK ) > > WINED3DFVF_TEXCOUNT_SHIFT ;
2006-05-12 22:21:31 +02:00
for ( i = 0 ; i < dwCount ; i + = 1 ) {
unsigned int tex_index ;
2006-10-31 09:16:08 +01:00
if ( ( ( DestFVF & WINED3DFVF_POSITION_MASK ) = = WINED3DFVF_XYZ ) | |
( ( DestFVF & WINED3DFVF_POSITION_MASK ) = = WINED3DFVF_XYZRHW ) ) {
2006-05-12 22:21:31 +02:00
/* The position first */
2009-03-27 10:25:55 +01:00
const struct wined3d_stream_info_element * element = & stream_info - > elements [ WINED3D_FFP_POSITION ] ;
const float * p = ( const float * ) ( element - > data + i * element - > stride ) ;
2006-05-12 22:21:31 +02:00
float x , y , z , rhw ;
TRACE ( " In: ( %06.2f %06.2f %06.2f ) \n " , p [ 0 ] , p [ 1 ] , p [ 2 ] ) ;
/* Multiplication with world, view and projection matrix */
x = ( p [ 0 ] * mat . u . s . _11 ) + ( p [ 1 ] * mat . u . s . _21 ) + ( p [ 2 ] * mat . u . s . _31 ) + ( 1.0 * mat . u . s . _41 ) ;
y = ( p [ 0 ] * mat . u . s . _12 ) + ( p [ 1 ] * mat . u . s . _22 ) + ( p [ 2 ] * mat . u . s . _32 ) + ( 1.0 * mat . u . s . _42 ) ;
z = ( p [ 0 ] * mat . u . s . _13 ) + ( p [ 1 ] * mat . u . s . _23 ) + ( p [ 2 ] * mat . u . s . _33 ) + ( 1.0 * mat . u . s . _43 ) ;
rhw = ( p [ 0 ] * mat . u . s . _14 ) + ( p [ 1 ] * mat . u . s . _24 ) + ( p [ 2 ] * mat . u . s . _34 ) + ( 1.0 * mat . u . s . _44 ) ;
TRACE ( " x=%f y=%f z=%f rhw=%f \n " , x , y , z , rhw ) ;
/* WARNING: The following things are taken from d3d7 and were not yet checked
* against d3d8 or d3d9 !
*/
2008-03-01 05:34:39 +01:00
/* Clipping conditions: From msdn
2006-05-12 22:21:31 +02:00
*
* A vertex is clipped if it does not match the following requirements
* - rhw < x < = rhw
* - rhw < y < = rhw
* 0 < z < = rhw
* 0 < rhw ( Not in d3d7 , but tested in d3d7 )
*
* If clipping is on is determined by the D3DVOP_CLIP flag in D3D7 , and
* by the D3DRS_CLIPPING in D3D9 ( according to the msdn , not checked )
*
*/
2006-09-26 20:31:58 +02:00
if ( ! doClip | |
2006-05-12 22:21:31 +02:00
( ( - rhw - eps < x ) & & ( - rhw - eps < y ) & & ( - eps < z ) & &
( x < = rhw + eps ) & & ( y < = rhw + eps ) & & ( z < = rhw + eps ) & &
( rhw > eps ) ) ) {
/* "Normal" viewport transformation (not clipped)
2006-06-15 17:38:04 +02:00
* 1 ) The values are divided by rhw
2006-05-12 22:21:31 +02:00
* 2 ) The y axis is negative , so multiply it with - 1
* 3 ) Screen coordinates go from - ( Width / 2 ) to + ( Width / 2 ) and
* - ( Height / 2 ) to + ( Height / 2 ) . The z range is MinZ to MaxZ
* 4 ) Multiply x with Width / 2 and add Width / 2
* 5 ) The same for the height
* 6 ) Add the viewpoint X and Y to the 2 D coordinates and
* The minimum Z value to z
* 7 ) rhw = 1 / rhw Reciprocal of Homogeneous W . . . .
*
* Well , basically it ' s simply a linear transformation into viewport
* coordinates
*/
x / = rhw ;
y / = rhw ;
z / = rhw ;
y * = - 1 ;
x * = vp . Width / 2 ;
y * = vp . Height / 2 ;
z * = vp . MaxZ - vp . MinZ ;
x + = vp . Width / 2 + vp . X ;
y + = vp . Height / 2 + vp . Y ;
z + = vp . MinZ ;
rhw = 1 / rhw ;
} else {
/* That vertex got clipped
* Contrary to OpenGL it is not dropped completely , it just
* undergoes a different calculation .
*/
TRACE ( " Vertex got clipped \n " ) ;
x + = rhw ;
y + = rhw ;
x / = 2 ;
y / = 2 ;
2006-06-23 18:18:02 +02:00
/* Msdn mentions that Direct3D9 keeps a list of clipped vertices
2006-05-12 22:21:31 +02:00
* outside of the main vertex buffer memory . That needs some more
* investigation . . .
*/
}
TRACE ( " Writing (%f %f %f) %f \n " , x , y , z , rhw ) ;
( ( float * ) dest_ptr ) [ 0 ] = x ;
( ( float * ) dest_ptr ) [ 1 ] = y ;
( ( float * ) dest_ptr ) [ 2 ] = z ;
( ( float * ) dest_ptr ) [ 3 ] = rhw ; /* SIC, see ddraw test! */
dest_ptr + = 3 * sizeof ( float ) ;
2006-10-31 09:16:08 +01:00
if ( ( DestFVF & WINED3DFVF_POSITION_MASK ) = = WINED3DFVF_XYZRHW ) {
2006-05-12 22:21:31 +02:00
dest_ptr + = sizeof ( float ) ;
}
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
float w = 1 / rhw ;
( ( float * ) dest_conv ) [ 0 ] = x * w ;
( ( float * ) dest_conv ) [ 1 ] = y * w ;
( ( float * ) dest_conv ) [ 2 ] = z * w ;
( ( float * ) dest_conv ) [ 3 ] = w ;
dest_conv + = 3 * sizeof ( float ) ;
2006-10-31 09:16:08 +01:00
if ( ( DestFVF & WINED3DFVF_POSITION_MASK ) = = WINED3DFVF_XYZRHW ) {
2006-06-21 15:05:38 +02:00
dest_conv + = sizeof ( float ) ;
}
}
2006-05-12 22:21:31 +02:00
}
2006-10-31 09:16:08 +01:00
if ( DestFVF & WINED3DFVF_PSIZE ) {
2006-05-12 22:21:31 +02:00
dest_ptr + = sizeof ( DWORD ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) dest_conv + = sizeof ( DWORD ) ;
2006-05-12 22:21:31 +02:00
}
2006-10-31 09:16:08 +01:00
if ( DestFVF & WINED3DFVF_NORMAL ) {
2009-03-27 10:25:55 +01:00
const struct wined3d_stream_info_element * element = & stream_info - > elements [ WINED3D_FFP_NORMAL ] ;
const float * normal = ( const float * ) ( element - > data + i * element - > stride ) ;
2006-05-12 22:21:31 +02:00
/* AFAIK this should go into the lighting information */
FIXME ( " Didn't expect the destination to have a normal \n " ) ;
copy_and_next ( dest_ptr , normal , 3 * sizeof ( float ) ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
copy_and_next ( dest_conv , normal , 3 * sizeof ( float ) ) ;
}
2006-05-12 22:21:31 +02:00
}
2006-10-31 09:16:08 +01:00
if ( DestFVF & WINED3DFVF_DIFFUSE ) {
2009-03-27 10:25:55 +01:00
const struct wined3d_stream_info_element * element = & stream_info - > elements [ WINED3D_FFP_DIFFUSE ] ;
const DWORD * color_d = ( const DWORD * ) ( element - > data + i * element - > stride ) ;
2006-05-12 22:21:31 +02:00
if ( ! color_d ) {
static BOOL warned = FALSE ;
2006-09-26 20:31:58 +02:00
if ( ! warned ) {
2006-05-12 22:21:31 +02:00
ERR ( " No diffuse color in source, but destination has one \n " ) ;
warned = TRUE ;
}
* ( ( DWORD * ) dest_ptr ) = 0xffffffff ;
dest_ptr + = sizeof ( DWORD ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
* ( ( DWORD * ) dest_conv ) = 0xffffffff ;
dest_conv + = sizeof ( DWORD ) ;
}
2006-05-12 22:21:31 +02:00
}
2006-06-21 15:05:38 +02:00
else {
2006-05-12 22:21:31 +02:00
copy_and_next ( dest_ptr , color_d , sizeof ( DWORD ) ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
* ( ( DWORD * ) dest_conv ) = ( * color_d & 0xff00ff00 ) ; /* Alpha + green */
* ( ( DWORD * ) dest_conv ) | = ( * color_d & 0x00ff0000 ) > > 16 ; /* Red */
* ( ( DWORD * ) dest_conv ) | = ( * color_d & 0xff0000ff ) < < 16 ; /* Blue */
dest_conv + = sizeof ( DWORD ) ;
}
}
2006-05-12 22:21:31 +02:00
}
2006-10-31 09:16:08 +01:00
if ( DestFVF & WINED3DFVF_SPECULAR ) {
2006-05-12 22:21:31 +02:00
/* What's the color value in the feedback buffer? */
2009-03-27 10:25:55 +01:00
const struct wined3d_stream_info_element * element = & stream_info - > elements [ WINED3D_FFP_SPECULAR ] ;
const DWORD * color_s = ( const DWORD * ) ( element - > data + i * element - > stride ) ;
2006-05-12 22:21:31 +02:00
if ( ! color_s ) {
static BOOL warned = FALSE ;
2006-09-26 20:31:58 +02:00
if ( ! warned ) {
2006-05-12 22:21:31 +02:00
ERR ( " No specular color in source, but destination has one \n " ) ;
warned = TRUE ;
}
* ( ( DWORD * ) dest_ptr ) = 0xFF000000 ;
dest_ptr + = sizeof ( DWORD ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
* ( ( DWORD * ) dest_conv ) = 0xFF000000 ;
dest_conv + = sizeof ( DWORD ) ;
}
2006-05-12 22:21:31 +02:00
}
else {
copy_and_next ( dest_ptr , color_s , sizeof ( DWORD ) ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
* ( ( DWORD * ) dest_conv ) = ( * color_s & 0xff00ff00 ) ; /* Alpha + green */
* ( ( DWORD * ) dest_conv ) | = ( * color_s & 0x00ff0000 ) > > 16 ; /* Red */
* ( ( DWORD * ) dest_conv ) | = ( * color_s & 0xff0000ff ) < < 16 ; /* Blue */
dest_conv + = sizeof ( DWORD ) ;
}
2006-05-12 22:21:31 +02:00
}
}
for ( tex_index = 0 ; tex_index < numTextures ; tex_index + + ) {
2009-03-27 10:25:55 +01:00
const struct wined3d_stream_info_element * element = & stream_info - > elements [ WINED3D_FFP_TEXCOORD0 + tex_index ] ;
const float * tex_coord = ( const float * ) ( element - > data + i * element - > stride ) ;
2006-05-12 22:21:31 +02:00
if ( ! tex_coord ) {
ERR ( " No source texture, but destination requests one \n " ) ;
dest_ptr + = GET_TEXCOORD_SIZE_FROM_FVF ( DestFVF , tex_index ) * sizeof ( float ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) dest_conv + = GET_TEXCOORD_SIZE_FROM_FVF ( DestFVF , tex_index ) * sizeof ( float ) ;
2006-05-12 22:21:31 +02:00
}
else {
copy_and_next ( dest_ptr , tex_coord , GET_TEXCOORD_SIZE_FROM_FVF ( DestFVF , tex_index ) * sizeof ( float ) ) ;
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
copy_and_next ( dest_conv , tex_coord , GET_TEXCOORD_SIZE_FROM_FVF ( DestFVF , tex_index ) * sizeof ( float ) ) ;
}
2006-05-12 22:21:31 +02:00
}
}
}
2006-06-21 15:05:38 +02:00
if ( dest_conv ) {
2009-03-06 14:56:23 +01:00
GL_EXTCALL ( glBindBufferARB ( GL_ARRAY_BUFFER_ARB , dest - > buffer_object ) ) ;
2007-02-20 23:00:02 +01:00
checkGLcall ( " glBindBufferARB(GL_ARRAY_BUFFER_ARB) " ) ;
GL_EXTCALL ( glBufferSubDataARB ( GL_ARRAY_BUFFER_ARB , dwDestIndex * get_flexible_vertex_size ( DestFVF ) ,
dwCount * get_flexible_vertex_size ( DestFVF ) ,
dest_conv_addr ) ) ;
checkGLcall ( " glBufferSubDataARB(GL_ARRAY_BUFFER_ARB) " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , dest_conv_addr ) ;
2006-06-21 15:05:38 +02:00
}
LEAVE_GL ( ) ;
2006-05-12 22:21:31 +02:00
return WINED3D_OK ;
}
# undef copy_and_next
2009-03-06 14:56:23 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices ( IWineD3DDevice * iface , UINT SrcStartIndex , UINT DestIndex ,
2009-04-06 14:16:59 +02:00
UINT VertexCount , IWineD3DBuffer * pDestBuffer , IWineD3DVertexDeclaration * pVertexDecl , DWORD Flags ,
DWORD DestFVF )
2009-03-06 14:56:23 +01:00
{
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-27 10:25:55 +01:00
struct wined3d_stream_info stream_info ;
2007-04-29 17:36:35 +02:00
BOOL vbo = FALSE , streamWasUP = This - > stateBlock - > streamIsUP ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p)->(%d,%d,%d,%p,%p,%d \n " , This , SrcStartIndex , DestIndex , VertexCount , pDestBuffer , pVertexDecl , Flags ) ;
2006-05-12 22:21:31 +02:00
2007-04-22 18:06:07 +02:00
if ( pVertexDecl ) {
ERR ( " Output vertex declaration not implemented yet \n " ) ;
2006-09-04 16:16:45 +02:00
}
2007-03-17 23:00:39 +01:00
2008-01-02 19:51:51 +01:00
/* Need any context to write to the vbo. */
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-03-17 23:00:39 +01:00
2007-04-29 17:36:35 +02:00
/* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP
* control the streamIsUP flag , thus restore it afterwards .
*/
This - > stateBlock - > streamIsUP = FALSE ;
2009-03-27 10:25:55 +01:00
device_stream_info_from_declaration ( This , FALSE , & stream_info , & vbo ) ;
2007-04-29 17:36:35 +02:00
This - > stateBlock - > streamIsUP = streamWasUP ;
2006-06-21 15:05:38 +02:00
2007-04-22 18:06:07 +02:00
if ( vbo | | SrcStartIndex ) {
unsigned int i ;
2008-01-09 20:37:05 +01:00
/* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcessVertices are
2009-03-27 10:25:55 +01:00
* unlikely to ever be used for drawing . Release vbos in those buffers and fix up the stream_info structure
2007-04-22 18:06:07 +02:00
*
* Also get the start index in , but only loop over all elements if there ' s something to add at all .
*/
2009-03-27 10:25:55 +01:00
for ( i = 0 ; i < ( sizeof ( stream_info . elements ) / sizeof ( * stream_info . elements ) ) ; + + i )
2009-03-26 10:43:40 +01:00
{
2009-03-27 10:25:55 +01:00
struct wined3d_stream_info_element * e = & stream_info . elements [ i ] ;
if ( e - > buffer_object )
2009-03-26 10:43:40 +01:00
{
2009-03-27 10:25:55 +01:00
struct wined3d_buffer * vb = ( struct wined3d_buffer * ) This - > stateBlock - > streamSource [ e - > stream_idx ] ;
e - > buffer_object = 0 ;
2009-04-09 18:40:57 +02:00
e - > data = ( BYTE * ) ( ( unsigned long ) e - > data + ( unsigned long ) buffer_get_sysmem ( vb ) ) ;
2009-03-26 10:43:40 +01:00
ENTER_GL ( ) ;
GL_EXTCALL ( glDeleteBuffersARB ( 1 , & vb - > buffer_object ) ) ;
vb - > buffer_object = 0 ;
LEAVE_GL ( ) ;
}
2009-03-27 10:25:55 +01:00
if ( e - > data ) e - > data + = e - > stride * SrcStartIndex ;
2006-06-21 15:05:38 +02:00
}
}
2009-03-27 10:25:55 +01:00
return process_vertices_strided ( This , DestIndex , VertexCount , & stream_info ,
2009-04-06 14:16:59 +02:00
( struct wined3d_buffer * ) pDestBuffer , Flags , DestFVF ) ;
2005-03-02 13:16:10 +01:00
}
2004-12-13 14:35:38 +01:00
2005-08-22 11:13:49 +02:00
/*****
* Get / Set Texture Stage States
* TODO : Verify against dx9 definitions
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState ( IWineD3DDevice * iface , DWORD Stage , WINED3DTEXTURESTAGESTATETYPE Type , DWORD Value ) {
2005-08-01 12:58:31 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-12-19 23:12:26 +01:00
DWORD oldValue = This - > updateStateBlock - > textureState [ Stage ] [ Type ] ;
2005-08-01 12:58:31 +02:00
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : Stage=%d, Type=%s(%d), Value=%d \n " , This , Stage , debug_d3dtexturestate ( Type ) , Type , Value ) ;
2005-08-01 12:58:31 +02:00
2007-04-16 21:44:27 +02:00
if ( Stage > = MAX_TEXTURES ) {
WARN ( " Attempting to set stage %u which is higher than the max stage %u, ignoring \n " , Stage , MAX_TEXTURES - 1 ) ;
return WINED3D_OK ;
}
2009-01-06 11:43:45 +01:00
This - > updateStateBlock - > changed . textureState [ Stage ] | = 1 < < Type ;
2005-08-01 12:58:31 +02:00
This - > updateStateBlock - > textureState [ Stage ] [ Type ] = Value ;
2006-12-19 23:00:58 +01:00
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
return WINED3D_OK ;
}
2006-12-19 23:12:26 +01:00
/* Checked after the assignments to allow proper stateblock recording */
if ( oldValue = = Value ) {
TRACE ( " App is setting the old value over, nothing to do \n " ) ;
return WINED3D_OK ;
}
2006-12-19 23:00:58 +01:00
if ( Stage > This - > stateBlock - > lowest_disabled_stage & &
2008-07-02 01:23:44 +02:00
This - > StateTable [ STATE_TEXTURESTAGE ( 0 , Type ) ] . representative = = STATE_TEXTURESTAGE ( 0 , WINED3DTSS_COLOROP ) ) {
2006-12-19 23:00:58 +01:00
/* Colorop change above lowest disabled stage? That won't change anything in the gl setup
* Changes in other states are important on disabled stages too
*/
return WINED3D_OK ;
}
if ( Type = = WINED3DTSS_COLOROP ) {
2009-03-25 10:12:27 +01:00
unsigned int i ;
2006-12-19 23:00:58 +01:00
2006-12-19 23:12:26 +01:00
if ( Value = = WINED3DTOP_DISABLE & & oldValue ! = WINED3DTOP_DISABLE ) {
2006-12-19 23:00:58 +01:00
/* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
* they have to be disabled
*
* The current stage is dirtified below .
*/
for ( i = Stage + 1 ; i < This - > stateBlock - > lowest_disabled_stage ; i + + ) {
2009-03-25 10:12:27 +01:00
TRACE ( " Additionally dirtifying stage %u \n " , i ) ;
2006-12-19 23:00:58 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( i , WINED3DTSS_COLOROP ) ) ;
}
This - > stateBlock - > lowest_disabled_stage = Stage ;
2009-03-25 10:12:27 +01:00
TRACE ( " New lowest disabled: %u \n " , Stage ) ;
2006-12-19 23:12:26 +01:00
} else if ( Value ! = WINED3DTOP_DISABLE & & oldValue = = WINED3DTOP_DISABLE ) {
2006-12-19 23:00:58 +01:00
/* Previously disabled stage enabled. Stages above it may need enabling
* stage must be lowest_disabled_stage here , if it ' s bigger success is returned above ,
* and stages below the lowest disabled stage can ' t be enabled ( because they are enabled already ) .
*
* Again stage Stage doesn ' t need to be dirtified here , it is handled below .
*/
for ( i = Stage + 1 ; i < GL_LIMITS ( texture_stages ) ; i + + ) {
if ( This - > updateStateBlock - > textureState [ i ] [ WINED3DTSS_COLOROP ] = = WINED3DTOP_DISABLE ) {
break ;
}
2009-03-25 10:12:27 +01:00
TRACE ( " Additionally dirtifying stage %u due to enable \n " , i ) ;
2006-12-19 23:00:58 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( i , WINED3DTSS_COLOROP ) ) ;
}
This - > stateBlock - > lowest_disabled_stage = i ;
2009-03-25 10:12:27 +01:00
TRACE ( " New lowest disabled: %u \n " , i ) ;
2006-12-19 23:00:58 +01:00
}
}
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( Stage , Type ) ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-13 14:35:38 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState ( IWineD3DDevice * iface , DWORD Stage , WINED3DTEXTURESTAGESTATETYPE Type , DWORD * pValue ) {
2004-12-13 14:35:38 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : requesting Stage %d, Type %d getting %d \n " , This , Stage , Type , This - > updateStateBlock - > textureState [ Stage ] [ Type ] ) ;
2004-12-13 14:35:38 +01:00
* pValue = This - > updateStateBlock - > textureState [ Stage ] [ Type ] ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-13 14:35:38 +01:00
}
2005-01-18 12:42:29 +01:00
/*****
2005-07-13 16:15:54 +02:00
* Get / Set Texture
2005-01-18 12:42:29 +01:00
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture ( IWineD3DDevice * iface , DWORD Stage , IWineD3DBaseTexture * pTexture ) {
2005-01-18 12:42:29 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-06-25 22:46:01 +02:00
IWineD3DBaseTexture * oldTexture ;
2005-01-18 12:42:29 +01:00
2007-06-25 22:46:01 +02:00
TRACE ( " (%p) : Stage %#x, Texture %p \n " , This , Stage , pTexture ) ;
2005-01-18 12:42:29 +01:00
2007-06-25 22:46:01 +02:00
if ( Stage > = WINED3DVERTEXTEXTURESAMPLER0 & & Stage < = WINED3DVERTEXTEXTURESAMPLER3 ) {
Stage - = ( WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS ) ;
2005-08-01 11:20:55 +02:00
}
2007-06-25 22:46:01 +02:00
2008-01-15 08:06:37 +01:00
if ( Stage > = sizeof ( This - > stateBlock - > textures ) / sizeof ( This - > stateBlock - > textures [ 0 ] ) ) {
2008-01-24 14:03:10 +01:00
ERR ( " Current stage overflows textures array (stage %d) \n " , Stage ) ;
2008-01-15 08:06:37 +01:00
return WINED3D_OK ; /* Windows accepts overflowing this array ... we do not. */
}
2007-06-25 22:46:01 +02:00
oldTexture = This - > updateStateBlock - > textures [ Stage ] ;
2005-08-01 11:20:55 +02:00
2008-12-12 09:33:51 +01:00
/* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH */
if ( pTexture & & ( ( IWineD3DTextureImpl * ) pTexture ) - > resource . pool = = WINED3DPOOL_SCRATCH )
{
WARN ( " (%p) Attempt to set scratch texture rejected \n " , pTexture ) ;
return WINED3DERR_INVALIDCALL ;
2006-02-06 20:57:42 +01:00
}
2006-06-27 23:40:42 +02:00
TRACE ( " GL_LIMITS %d \n " , GL_LIMITS ( sampler_stages ) ) ;
2005-08-01 11:20:55 +02:00
TRACE ( " (%p) : oldtexture(%p) \n " , This , oldTexture ) ;
2009-01-02 16:19:12 +01:00
This - > updateStateBlock - > changed . textures | = 1 < < Stage ;
2005-08-01 11:20:55 +02:00
TRACE ( " (%p) : setting new texture to %p \n " , This , pTexture ) ;
This - > updateStateBlock - > textures [ Stage ] = pTexture ;
2005-01-18 12:42:29 +01:00
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-18 12:42:29 +01:00
}
2006-12-19 23:17:17 +01:00
if ( oldTexture = = pTexture ) {
TRACE ( " App is setting the same texture again, nothing to do \n " ) ;
return WINED3D_OK ;
}
2005-03-14 11:12:52 +01:00
/** NOTE: MSDN says that setTexture increases the reference count,
2007-10-23 15:30:30 +02:00
* and that the application must set the texture back to null ( or have a leaky application ) ,
2005-11-23 20:14:43 +01:00
* This means we should pass the refcount up to the parent
2005-03-14 11:12:52 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-26 20:49:30 +02:00
if ( NULL ! = This - > updateStateBlock - > textures [ Stage ] ) {
2006-12-19 23:26:39 +01:00
IWineD3DBaseTextureImpl * new = ( IWineD3DBaseTextureImpl * ) This - > updateStateBlock - > textures [ Stage ] ;
ULONG bindCount = InterlockedIncrement ( & new - > baseTexture . bindCount ) ;
2009-01-12 10:17:50 +01:00
UINT dimensions = IWineD3DBaseTexture_GetTextureDimensions ( pTexture ) ;
2006-12-19 23:26:39 +01:00
2005-12-15 10:25:47 +01:00
IWineD3DBaseTexture_AddRef ( This - > updateStateBlock - > textures [ Stage ] ) ;
2009-01-12 10:17:50 +01:00
if ( ! oldTexture | | dimensions ! = IWineD3DBaseTexture_GetTextureDimensions ( oldTexture ) )
{
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADER ) ;
}
2006-12-25 12:43:02 +01:00
if ( oldTexture = = NULL & & Stage < MAX_TEXTURES ) {
2006-12-19 23:00:58 +01:00
/* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
2006-12-19 23:03:37 +01:00
* so the COLOROP and ALPHAOP have to be dirtified .
2006-12-19 23:00:58 +01:00
*/
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( Stage , WINED3DTSS_COLOROP ) ) ;
2006-12-19 23:03:37 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( Stage , WINED3DTSS_ALPHAOP ) ) ;
2006-12-19 23:00:58 +01:00
}
2006-12-19 23:26:39 +01:00
if ( bindCount = = 1 ) {
new - > baseTexture . sampler = Stage ;
}
/* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
2005-07-26 20:49:30 +02:00
}
2005-03-14 11:12:52 +01:00
2005-07-26 20:49:30 +02:00
if ( NULL ! = oldTexture ) {
2006-12-19 23:26:39 +01:00
IWineD3DBaseTextureImpl * old = ( IWineD3DBaseTextureImpl * ) oldTexture ;
LONG bindCount = InterlockedDecrement ( & old - > baseTexture . bindCount ) ;
2005-12-15 10:25:47 +01:00
IWineD3DBaseTexture_Release ( oldTexture ) ;
2006-12-25 12:43:02 +01:00
if ( pTexture = = NULL & & Stage < MAX_TEXTURES ) {
2006-12-19 23:00:58 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( Stage , WINED3DTSS_COLOROP ) ) ;
2006-12-19 23:03:37 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( Stage , WINED3DTSS_ALPHAOP ) ) ;
2006-12-19 23:00:58 +01:00
}
2005-07-13 16:15:54 +02:00
2006-12-19 23:26:39 +01:00
if ( bindCount & & old - > baseTexture . sampler = = Stage ) {
int i ;
/* Have to do a search for the other sampler(s) where the texture is bound to
* Shouldn ' t happen as long as apps bind a texture only to one stage
*/
TRACE ( " Searcing for other sampler / stage id where the texture is bound to \n " ) ;
2007-06-25 22:46:01 +02:00
for ( i = 0 ; i < MAX_COMBINED_SAMPLERS ; i + + ) {
2006-12-19 23:26:39 +01:00
if ( This - > updateStateBlock - > textures [ i ] = = oldTexture ) {
old - > baseTexture . sampler = i ;
break ;
}
}
}
2006-05-24 17:15:24 +02:00
}
2006-12-19 23:26:39 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( Stage ) ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-18 12:42:29 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture ( IWineD3DDevice * iface , DWORD Stage , IWineD3DBaseTexture * * ppTexture ) {
2005-01-18 12:42:29 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-06-25 22:46:01 +02:00
TRACE ( " (%p) : Stage %#x, ppTexture %p \n " , This , Stage , ppTexture ) ;
if ( Stage > = WINED3DVERTEXTEXTURESAMPLER0 & & Stage < = WINED3DVERTEXTEXTURESAMPLER3 ) {
Stage - = ( WINED3DVERTEXTEXTURESAMPLER0 - MAX_FRAGMENT_SAMPLERS ) ;
}
2005-08-22 11:13:49 +02:00
2008-01-15 08:06:37 +01:00
if ( Stage > = sizeof ( This - > stateBlock - > textures ) / sizeof ( This - > stateBlock - > textures [ 0 ] ) ) {
2008-01-24 14:03:10 +01:00
ERR ( " Current stage overflows textures array (stage %d) \n " , Stage ) ;
2008-01-15 08:06:37 +01:00
return WINED3D_OK ; /* Windows accepts overflowing this array ... we do not. */
}
2006-10-29 01:55:55 +02:00
* ppTexture = This - > stateBlock - > textures [ Stage ] ;
2006-11-30 13:33:29 +01:00
if ( * ppTexture )
IWineD3DBaseTexture_AddRef ( * ppTexture ) ;
2006-10-29 01:54:25 +02:00
2007-06-25 22:46:01 +02:00
TRACE ( " (%p) : Returning %p \n " , This , * ppTexture ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-18 12:42:29 +01:00
}
/*****
* Get Back Buffer
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer ( IWineD3DDevice * iface , UINT iSwapChain , UINT BackBuffer , WINED3DBACKBUFFER_TYPE Type ,
2005-08-22 11:13:49 +02:00
IWineD3DSurface * * ppBackBuffer ) {
2005-01-18 12:42:29 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-06-23 13:05:24 +02:00
IWineD3DSwapChain * swapChain ;
HRESULT hr ;
2005-01-18 12:42:29 +01:00
TRACE ( " (%p) : BackBuf %d Type %d SwapChain %d returning %p \n " , This , BackBuffer , Type , iSwapChain , * ppBackBuffer ) ;
2005-06-23 13:05:24 +02:00
hr = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapChain ) ;
2006-04-07 12:51:12 +02:00
if ( hr = = WINED3D_OK ) {
2005-06-23 13:05:24 +02:00
hr = IWineD3DSwapChain_GetBackBuffer ( swapChain , BackBuffer , Type , ppBackBuffer ) ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_Release ( swapChain ) ;
2005-08-22 11:13:49 +02:00
} else {
2005-06-23 13:05:24 +02:00
* ppBackBuffer = NULL ;
2005-01-18 12:42:29 +01:00
}
2005-06-23 13:05:24 +02:00
return hr ;
2005-01-18 12:42:29 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps ( IWineD3DDevice * iface , WINED3DCAPS * pCaps ) {
2005-01-18 12:42:29 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
WARN ( " (%p) : stub, calling idirect3d for now \n " , This ) ;
2005-06-17 11:59:03 +02:00
return IWineD3D_GetDeviceCaps ( This - > wineD3D , This - > adapterNo , This - > devType , pCaps ) ;
2005-01-18 12:42:29 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode ( IWineD3DDevice * iface , UINT iSwapChain , WINED3DDISPLAYMODE * pMode ) {
2005-01-18 12:42:29 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-06-23 13:05:24 +02:00
IWineD3DSwapChain * swapChain ;
HRESULT hr ;
2005-01-18 12:42:29 +01:00
2006-05-18 22:42:22 +02:00
if ( iSwapChain > 0 ) {
2008-01-23 22:39:56 +01:00
hr = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapChain ) ;
2006-05-18 22:42:22 +02:00
if ( hr = = WINED3D_OK ) {
hr = IWineD3DSwapChain_GetDisplayMode ( swapChain , pMode ) ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_Release ( swapChain ) ;
2006-05-18 22:42:22 +02:00
} else {
FIXME ( " (%p) Error getting display mode \n " , This ) ;
}
2005-08-22 11:13:49 +02:00
} else {
2006-05-18 22:42:22 +02:00
/* Don't read the real display mode,
but return the stored mode instead . X11 can ' t change the color
depth , and some apps are pretty angry if they SetDisplayMode from
24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
Also don ' t relay to the swapchain because with ddraw it ' s possible
that there isn ' t a swapchain at all */
pMode - > Width = This - > ddraw_width ;
pMode - > Height = This - > ddraw_height ;
pMode - > Format = This - > ddraw_format ;
pMode - > RefreshRate = 0 ;
hr = WINED3D_OK ;
2005-06-23 13:05:24 +02:00
}
2006-05-18 22:42:22 +02:00
2005-06-23 13:05:24 +02:00
return hr ;
2005-01-18 12:42:29 +01:00
}
2006-04-13 23:37:47 +02:00
2005-03-02 13:16:10 +01:00
/*****
* Stateblock related functions
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-01-09 10:23:43 +01:00
IWineD3DStateBlock * stateblock ;
HRESULT hr ;
2007-02-14 17:46:54 +01:00
2007-08-19 20:47:10 +02:00
TRACE ( " (%p) \n " , This ) ;
2007-02-14 17:46:54 +01:00
2009-01-09 10:23:43 +01:00
if ( This - > isRecordingState ) return WINED3DERR_INVALIDCALL ;
2007-02-14 17:46:54 +01:00
2009-01-09 10:23:43 +01:00
hr = IWineD3DDeviceImpl_CreateStateBlock ( iface , WINED3DSBT_RECORDED , & stateblock , NULL ) ;
if ( FAILED ( hr ) ) return hr ;
2005-07-13 16:15:54 +02:00
2005-03-02 13:16:10 +01:00
IWineD3DStateBlock_Release ( ( IWineD3DStateBlock * ) This - > updateStateBlock ) ;
2009-01-09 10:23:43 +01:00
This - > updateStateBlock = ( IWineD3DStateBlockImpl * ) stateblock ;
2005-03-02 13:16:10 +01:00
This - > isRecordingState = TRUE ;
2005-07-13 16:15:54 +02:00
2009-01-09 10:23:43 +01:00
TRACE ( " (%p) recording stateblock %p \n " , This , stateblock ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock ( IWineD3DDevice * iface , IWineD3DStateBlock * * ppStateBlock ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-08-09 17:45:29 +02:00
unsigned int i , j ;
2007-07-31 15:04:56 +02:00
IWineD3DStateBlockImpl * object = This - > updateStateBlock ;
2005-03-02 13:16:10 +01:00
if ( ! This - > isRecordingState ) {
2008-12-29 16:31:22 +01:00
WARN ( " (%p) not recording! returning error \n " , This ) ;
2005-03-02 13:16:10 +01:00
* ppStateBlock = NULL ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-03-02 13:16:10 +01:00
}
2009-01-05 10:10:16 +01:00
for ( i = 0 ; i < = WINEHIGHEST_RENDER_STATE > > 5 ; + + i )
{
DWORD map = object - > changed . renderState [ i ] ;
for ( j = 0 ; map ; map > > = 1 , + + j )
{
if ( ! ( map & 1 ) ) continue ;
object - > contained_render_states [ object - > num_contained_render_states + + ] = ( i < < 5 ) | j ;
2007-07-31 15:04:56 +02:00
}
}
2009-01-05 10:10:16 +01:00
for ( i = 0 ; i < = HIGHEST_TRANSFORMSTATE > > 5 ; + + i )
{
DWORD map = object - > changed . transform [ i ] ;
for ( j = 0 ; map ; map > > = 1 , + + j )
{
if ( ! ( map & 1 ) ) continue ;
object - > contained_transform_states [ object - > num_contained_transform_states + + ] = ( i < < 5 ) | j ;
2007-07-31 15:44:13 +02:00
}
}
2007-08-03 20:26:29 +02:00
for ( i = 0 ; i < GL_LIMITS ( vshader_constantsF ) ; i + + ) {
if ( object - > changed . vertexShaderConstantsF [ i ] ) {
object - > contained_vs_consts_f [ object - > num_contained_vs_consts_f ] = i ;
object - > num_contained_vs_consts_f + + ;
}
}
2007-08-03 20:07:30 +02:00
for ( i = 0 ; i < MAX_CONST_I ; i + + ) {
2008-12-02 18:41:33 +01:00
if ( object - > changed . vertexShaderConstantsI & ( 1 < < i ) )
{
2007-08-03 20:07:30 +02:00
object - > contained_vs_consts_i [ object - > num_contained_vs_consts_i ] = i ;
object - > num_contained_vs_consts_i + + ;
}
}
for ( i = 0 ; i < MAX_CONST_B ; i + + ) {
2008-12-02 18:41:33 +01:00
if ( object - > changed . vertexShaderConstantsB & ( 1 < < i ) )
{
2007-08-03 20:07:30 +02:00
object - > contained_vs_consts_b [ object - > num_contained_vs_consts_b ] = i ;
object - > num_contained_vs_consts_b + + ;
}
}
2008-12-16 16:37:37 +01:00
for ( i = 0 ; i < GL_LIMITS ( pshader_constantsF ) ; + + i )
{
if ( object - > changed . pixelShaderConstantsF [ i ] )
{
object - > contained_ps_consts_f [ object - > num_contained_ps_consts_f ] = i ;
+ + object - > num_contained_ps_consts_f ;
}
}
2007-08-03 20:12:54 +02:00
for ( i = 0 ; i < MAX_CONST_I ; i + + ) {
2008-12-02 18:41:33 +01:00
if ( object - > changed . pixelShaderConstantsI & ( 1 < < i ) )
{
2007-08-03 20:12:54 +02:00
object - > contained_ps_consts_i [ object - > num_contained_ps_consts_i ] = i ;
object - > num_contained_ps_consts_i + + ;
}
}
for ( i = 0 ; i < MAX_CONST_B ; i + + ) {
2008-12-02 18:41:33 +01:00
if ( object - > changed . pixelShaderConstantsB & ( 1 < < i ) )
{
2007-08-03 20:12:54 +02:00
object - > contained_ps_consts_b [ object - > num_contained_ps_consts_b ] = i ;
object - > num_contained_ps_consts_b + + ;
}
}
2007-08-09 17:45:29 +02:00
for ( i = 0 ; i < MAX_TEXTURES ; i + + ) {
2009-01-06 11:43:45 +01:00
DWORD map = object - > changed . textureState [ i ] ;
for ( j = 0 ; map ; map > > = 1 , + + j )
2009-01-06 11:43:45 +01:00
{
2009-01-06 11:43:45 +01:00
if ( ! ( map & 1 ) ) continue ;
object - > contained_tss_states [ object - > num_contained_tss_states ] . stage = i ;
object - > contained_tss_states [ object - > num_contained_tss_states ] . state = j ;
+ + object - > num_contained_tss_states ;
2007-08-09 17:45:29 +02:00
}
}
2007-08-03 20:23:52 +02:00
for ( i = 0 ; i < MAX_COMBINED_SAMPLERS ; i + + ) {
2009-01-05 10:10:16 +01:00
DWORD map = object - > changed . samplerState [ i ] ;
for ( j = 0 ; map ; map > > = 1 , + + j )
{
if ( ! ( map & 1 ) ) continue ;
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . stage = i ;
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . state = j ;
+ + object - > num_contained_sampler_states ;
2007-08-03 20:23:52 +02:00
}
}
2007-07-31 15:04:56 +02:00
* ppStateBlock = ( IWineD3DStateBlock * ) object ;
2005-03-02 13:16:10 +01:00
This - > isRecordingState = FALSE ;
2005-07-13 16:15:54 +02:00
This - > updateStateBlock = This - > stateBlock ;
2005-03-02 13:16:10 +01:00
IWineD3DStateBlock_AddRef ( ( IWineD3DStateBlock * ) This - > updateStateBlock ) ;
/* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
TRACE ( " (%p) returning token (ptr to stateblock) of %p \n " , This , * ppStateBlock ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2004-11-28 16:04:41 +01:00
/*****
* Scene related functions
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene ( IWineD3DDevice * iface ) {
2004-11-28 16:04:41 +01:00
/* At the moment we have no need for any functionality at the beginning
of a scene */
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-02-09 16:35:45 +01:00
TRACE ( " (%p) \n " , This ) ;
if ( This - > inScene ) {
TRACE ( " Already in Scene, returning WINED3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
This - > inScene = TRUE ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-28 16:04:41 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_EndScene ( IWineD3DDevice * iface ) {
2004-12-14 12:54:27 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p) \n " , This ) ;
2007-02-09 16:35:45 +01:00
if ( ! This - > inScene ) {
TRACE ( " Not in scene, returning WINED3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
2008-01-02 19:51:51 +01:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2005-03-14 11:12:52 +01:00
/* We only have to do this if we need to read the, swapbuffers performs a flush for us */
2004-12-14 12:54:27 +01:00
glFlush ( ) ;
2008-08-04 20:34:47 +02:00
/* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever
* fails
*/
2007-02-12 19:21:10 +01:00
2007-02-09 16:35:45 +01:00
This - > inScene = FALSE ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-14 12:54:27 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_Present ( IWineD3DDevice * iface ,
2005-07-13 16:15:54 +02:00
CONST RECT * pSourceRect , CONST RECT * pDestRect ,
2004-12-14 12:54:27 +01:00
HWND hDestWindowOverride , CONST RGNDATA * pDirtyRegion ) {
2005-08-22 11:13:49 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-06-23 13:05:24 +02:00
IWineD3DSwapChain * swapChain = NULL ;
int i ;
int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains ( iface ) ;
2004-12-14 12:54:27 +01:00
2005-06-23 13:05:24 +02:00
TRACE ( " (%p) Presenting the frame \n " , This ) ;
2004-12-14 12:54:27 +01:00
2005-07-13 16:15:54 +02:00
for ( i = 0 ; i < swapchains ; i + + ) {
2004-12-14 12:54:27 +01:00
2008-01-23 22:39:56 +01:00
IWineD3DDeviceImpl_GetSwapChain ( iface , i , & swapChain ) ;
2005-06-23 13:05:24 +02:00
TRACE ( " presentinng chain %d, %p \n " , i , swapChain ) ;
IWineD3DSwapChain_Present ( swapChain , pSourceRect , pDestRect , hDestWindowOverride , pDirtyRegion , 0 ) ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_Release ( swapChain ) ;
2004-12-14 12:54:27 +01:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-14 12:54:27 +01:00
}
2007-12-20 08:32:11 +01:00
/* Not called from the VTable (internal subroutine) */
HRESULT IWineD3DDeviceImpl_ClearSurface ( IWineD3DDeviceImpl * This , IWineD3DSurfaceImpl * target , DWORD Count ,
CONST WINED3DRECT * pRects , DWORD Flags , WINED3DCOLOR Color ,
float Z , DWORD Stencil ) {
GLbitfield glMask = 0 ;
unsigned int i ;
WINED3DRECT curRect ;
RECT vp_rect ;
2008-11-26 16:14:39 +01:00
const WINED3DVIEWPORT * vp = & This - > stateBlock - > viewport ;
2007-12-20 08:32:11 +01:00
UINT drawable_width , drawable_height ;
2008-01-27 14:11:16 +01:00
IWineD3DSurfaceImpl * depth_stencil = ( IWineD3DSurfaceImpl * ) This - > stencilBufferTarget ;
2008-08-31 16:05:26 +02:00
IWineD3DSwapChainImpl * swapchain = NULL ;
2007-12-20 08:32:11 +01:00
/* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
* drawable . After the clear we ' ll mark the drawable up to date , so we have to make sure that this is true
* for the cleared parts , and the untouched parts .
*
* If we ' re clearing the whole target there is no need to copy it into the drawable , it will be overwritten
* anyway . If we ' re not clearing the color buffer we don ' t have to copy either since we ' re not going to set
* the drawable up to date . We have to check all settings that limit the clear area though . Do not bother
* checking all this if the dest surface is in the drawable anyway .
*/
if ( ( Flags & WINED3DCLEAR_TARGET ) & & ! ( target - > Flags & SFLAG_INDRAWABLE ) ) {
while ( 1 ) {
if ( vp - > X ! = 0 | | vp - > Y ! = 0 | |
vp - > Width < target - > currentDesc . Width | | vp - > Height < target - > currentDesc . Height ) {
IWineD3DSurface_LoadLocation ( ( IWineD3DSurface * ) target , SFLAG_INDRAWABLE , NULL ) ;
break ;
}
if ( This - > stateBlock - > renderState [ WINED3DRS_SCISSORTESTENABLE ] & & (
This - > stateBlock - > scissorRect . left > 0 | | This - > stateBlock - > scissorRect . top > 0 | |
This - > stateBlock - > scissorRect . right < target - > currentDesc . Width | |
This - > stateBlock - > scissorRect . bottom < target - > currentDesc . Height ) ) {
IWineD3DSurface_LoadLocation ( ( IWineD3DSurface * ) target , SFLAG_INDRAWABLE , NULL ) ;
break ;
}
if ( Count > 0 & & pRects & & (
pRects [ 0 ] . x1 > 0 | | pRects [ 0 ] . y1 > 0 | |
pRects [ 0 ] . x2 < target - > currentDesc . Width | |
pRects [ 0 ] . y2 < target - > currentDesc . Height ) ) {
IWineD3DSurface_LoadLocation ( ( IWineD3DSurface * ) target , SFLAG_INDRAWABLE , NULL ) ;
break ;
}
break ;
}
}
target - > get_drawable_size ( target , & drawable_width , & drawable_height ) ;
ActivateContext ( This , ( IWineD3DSurface * ) target , CTXUSAGE_CLEAR ) ;
ENTER_GL ( ) ;
/* Only set the values up once, as they are not changing */
if ( Flags & WINED3DCLEAR_STENCIL ) {
glClearStencil ( Stencil ) ;
checkGLcall ( " glClearStencil " ) ;
glMask = glMask | GL_STENCIL_BUFFER_BIT ;
glStencilMask ( 0xFFFFFFFF ) ;
}
if ( Flags & WINED3DCLEAR_ZBUFFER ) {
2008-07-02 23:00:41 +02:00
DWORD location = This - > render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN ;
2007-12-20 08:32:11 +01:00
glDepthMask ( GL_TRUE ) ;
glClearDepth ( Z ) ;
checkGLcall ( " glClearDepth " ) ;
glMask = glMask | GL_DEPTH_BUFFER_BIT ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_ZWRITEENABLE ) ) ;
2008-01-27 14:11:16 +01:00
2008-07-02 23:00:41 +02:00
if ( vp - > X ! = 0 | | vp - > Y ! = 0 | |
vp - > Width < depth_stencil - > currentDesc . Width | | vp - > Height < depth_stencil - > currentDesc . Height ) {
surface_load_ds_location ( This - > stencilBufferTarget , location ) ;
}
else if ( This - > stateBlock - > renderState [ WINED3DRS_SCISSORTESTENABLE ] & & (
This - > stateBlock - > scissorRect . left > 0 | | This - > stateBlock - > scissorRect . top > 0 | |
This - > stateBlock - > scissorRect . right < depth_stencil - > currentDesc . Width | |
This - > stateBlock - > scissorRect . bottom < depth_stencil - > currentDesc . Height ) ) {
surface_load_ds_location ( This - > stencilBufferTarget , location ) ;
}
else if ( Count > 0 & & pRects & & (
pRects [ 0 ] . x1 > 0 | | pRects [ 0 ] . y1 > 0 | |
pRects [ 0 ] . x2 < depth_stencil - > currentDesc . Width | |
pRects [ 0 ] . y2 < depth_stencil - > currentDesc . Height ) ) {
surface_load_ds_location ( This - > stencilBufferTarget , location ) ;
2008-01-27 14:11:16 +01:00
}
2007-12-20 08:32:11 +01:00
}
if ( Flags & WINED3DCLEAR_TARGET ) {
TRACE ( " Clearing screen with glClear to color %x \n " , Color ) ;
glClearColor ( D3DCOLOR_R ( Color ) ,
D3DCOLOR_G ( Color ) ,
D3DCOLOR_B ( Color ) ,
D3DCOLOR_A ( Color ) ) ;
checkGLcall ( " glClearColor " ) ;
/* Clear ALL colors! */
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
glMask = glMask | GL_COLOR_BUFFER_BIT ;
}
vp_rect . left = vp - > X ;
vp_rect . top = vp - > Y ;
vp_rect . right = vp - > X + vp - > Width ;
vp_rect . bottom = vp - > Y + vp - > Height ;
if ( ! ( Count > 0 & & pRects ) ) {
if ( This - > stateBlock - > renderState [ WINED3DRS_SCISSORTESTENABLE ] ) {
IntersectRect ( & vp_rect , & vp_rect , & This - > stateBlock - > scissorRect ) ;
}
if ( This - > render_offscreen ) {
glScissor ( vp_rect . left , vp_rect . top ,
vp_rect . right - vp_rect . left , vp_rect . bottom - vp_rect . top ) ;
} else {
glScissor ( vp_rect . left , drawable_height - vp_rect . bottom ,
vp_rect . right - vp_rect . left , vp_rect . bottom - vp_rect . top ) ;
}
checkGLcall ( " glScissor " ) ;
glClear ( glMask ) ;
checkGLcall ( " glClear " ) ;
} else {
/* Now process each rect in turn */
for ( i = 0 ; i < Count ; i + + ) {
/* Note gl uses lower left, width/height */
2008-11-25 11:57:39 +01:00
IntersectRect ( ( RECT * ) & curRect , & vp_rect , ( const RECT * ) & pRects [ i ] ) ;
2007-12-20 08:32:11 +01:00
if ( This - > stateBlock - > renderState [ WINED3DRS_SCISSORTESTENABLE ] ) {
IntersectRect ( ( RECT * ) & curRect , ( RECT * ) & curRect , & This - > stateBlock - > scissorRect ) ;
}
TRACE ( " (%p) Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d \n " , This ,
pRects [ i ] . x1 , pRects [ i ] . y1 , pRects [ i ] . x2 , pRects [ i ] . y2 ,
curRect . x1 , ( target - > currentDesc . Height - curRect . y2 ) ,
curRect . x2 - curRect . x1 , curRect . y2 - curRect . y1 ) ;
/* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
* The rectangle is not cleared , no error is returned , but further rectanlges are
* still cleared if they are valid
*/
if ( curRect . x1 > curRect . x2 | | curRect . y1 > curRect . y2 ) {
TRACE ( " Rectangle with negative dimensions, ignoring \n " ) ;
continue ;
}
if ( This - > render_offscreen ) {
glScissor ( curRect . x1 , curRect . y1 ,
curRect . x2 - curRect . x1 , curRect . y2 - curRect . y1 ) ;
} else {
glScissor ( curRect . x1 , drawable_height - curRect . y2 ,
curRect . x2 - curRect . x1 , curRect . y2 - curRect . y1 ) ;
}
checkGLcall ( " glScissor " ) ;
glClear ( glMask ) ;
checkGLcall ( " glClear " ) ;
}
}
/* Restore the old values (why..?) */
if ( Flags & WINED3DCLEAR_STENCIL ) {
glStencilMask ( This - > stateBlock - > renderState [ WINED3DRS_STENCILWRITEMASK ] ) ;
}
if ( Flags & WINED3DCLEAR_TARGET ) {
DWORD mask = This - > stateBlock - > renderState [ WINED3DRS_COLORWRITEENABLE ] ;
glColorMask ( mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE ,
mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE ,
mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE ,
mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE ) ;
/* Dirtify the target surface for now. If the surface is locked regularly, and an up to date sysmem copy exists,
* it is most likely more efficient to perform a clear on the sysmem copy too instead of downloading it
*/
IWineD3DSurface_ModifyLocation ( This - > lastActiveRenderTarget , SFLAG_INDRAWABLE , TRUE ) ;
}
2008-07-02 23:00:41 +02:00
if ( Flags & WINED3DCLEAR_ZBUFFER ) {
/* Note that WINED3DCLEAR_ZBUFFER implies a depth stencil exists on the device */
DWORD location = This - > render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN ;
surface_modify_ds_location ( This - > stencilBufferTarget , location ) ;
}
2007-12-20 08:32:11 +01:00
LEAVE_GL ( ) ;
2008-10-16 11:52:54 +02:00
if ( SUCCEEDED ( IWineD3DSurface_GetContainer ( ( IWineD3DSurface * ) target , & IID_IWineD3DSwapChain , ( void * * ) & swapchain ) ) ) {
2008-08-31 16:05:26 +02:00
if ( target = = ( IWineD3DSurfaceImpl * ) swapchain - > frontBuffer ) {
glFlush ( ) ;
}
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
}
2007-12-20 08:32:11 +01:00
return WINED3D_OK ;
}
2006-10-12 08:22:18 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_Clear ( IWineD3DDevice * iface , DWORD Count , CONST WINED3DRECT * pRects ,
2006-10-12 08:22:59 +02:00
DWORD Flags , WINED3DCOLOR Color , float Z , DWORD Stencil ) {
2004-12-14 12:54:27 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-03-10 00:55:08 +01:00
IWineD3DSurfaceImpl * target = ( IWineD3DSurfaceImpl * ) This - > render_targets [ 0 ] ;
2004-12-14 12:54:27 +01:00
2007-06-04 18:12:31 +02:00
TRACE ( " (%p) Count (%d), pRects (%p), Flags (%x), Color (0x%08x), Z (%f), Stencil (%d) \n " , This ,
Count , pRects , Flags , Color , Z , Stencil ) ;
2004-12-14 12:54:27 +01:00
2007-03-06 13:35:56 +01:00
if ( Flags & ( WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL ) & & This - > stencilBufferTarget = = NULL ) {
WARN ( " Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL \n " ) ;
/* TODO: What about depth stencil buffers without stencil bits? */
return WINED3DERR_INVALIDCALL ;
}
2007-12-20 08:33:31 +01:00
return IWineD3DDeviceImpl_ClearSurface ( This , target , Count , pRects , Flags , Color , Z , Stencil ) ;
2004-12-14 12:54:27 +01:00
}
2004-12-09 12:42:34 +01:00
/*****
* Drawing functions
* * * * */
2009-03-05 12:30:43 +01:00
static void WINAPI IWineD3DDeviceImpl_SetPrimitiveType ( IWineD3DDevice * iface ,
WINED3DPRIMITIVETYPE primitive_type )
{
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " iface %p, primitive_type %s \n " , iface , debug_d3dprimitivetype ( primitive_type ) ) ;
This - > updateStateBlock - > changed . primitive_type = TRUE ;
This - > updateStateBlock - > gl_primitive_type = gl_primitive_type_from_d3d ( primitive_type ) ;
}
static void WINAPI IWineD3DDeviceImpl_GetPrimitiveType ( IWineD3DDevice * iface ,
WINED3DPRIMITIVETYPE * primitive_type )
{
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " iface %p, primitive_type %p \n " , iface , primitive_type ) ;
* primitive_type = d3d_primitive_type_from_gl ( This - > stateBlock - > gl_primitive_type ) ;
TRACE ( " Returning %s \n " , debug_d3dprimitivetype ( * primitive_type ) ) ;
}
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive ( IWineD3DDevice * iface , UINT StartVertex , UINT vertex_count )
2009-03-05 12:30:42 +01:00
{
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-05 12:30:43 +01:00
TRACE ( " (%p) : start %u, count %u \n " , This , StartVertex , vertex_count ) ;
2004-12-09 12:42:34 +01:00
2008-04-07 12:08:16 +02:00
if ( ! This - > stateBlock - > vertexDecl ) {
WARN ( " (%p) : Called without a valid vertex declaration set \n " , This ) ;
return WINED3DERR_INVALIDCALL ;
}
2007-03-10 00:44:46 +01:00
/* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
if ( This - > stateBlock - > streamIsUP ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_INDEXBUFFER ) ;
This - > stateBlock - > streamIsUP = FALSE ;
}
2007-01-06 18:19:55 +01:00
if ( This - > stateBlock - > loadBaseVertexIndex ! = 0 ) {
This - > stateBlock - > loadBaseVertexIndex = 0 ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_STREAMSRC ) ;
}
2007-01-02 21:07:39 +01:00
/* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
2009-03-05 12:30:43 +01:00
drawPrimitive ( iface , vertex_count , 0 /* NumVertices */ , StartVertex /* start_idx */ ,
2007-01-02 21:13:28 +01:00
0 /* indxSize */ , NULL /* indxData */ , 0 /* minIndex */ ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2009-03-05 12:30:42 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive ( IWineD3DDevice * iface ,
2009-03-05 12:30:43 +01:00
UINT minIndex , UINT NumVertices , UINT startIndex , UINT index_count )
2009-03-05 12:30:42 +01:00
{
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
UINT idxStride = 2 ;
2009-04-06 16:46:12 +02:00
IWineD3DBuffer * pIB ;
2007-02-20 22:46:31 +01:00
GLuint vbo ;
2005-07-13 16:15:54 +02:00
2007-06-02 15:54:49 +02:00
pIB = This - > stateBlock - > pIndexData ;
if ( ! pIB ) {
/* D3D9 returns D3DERR_INVALIDCALL when DrawIndexedPrimitive is called
* without an index buffer set . ( The first time at least . . . )
* D3D8 simply dies , but I doubt it can do much harm to return
* D3DERR_INVALIDCALL there as well . */
2008-12-29 16:31:22 +01:00
WARN ( " (%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL \n " , This ) ;
2007-06-02 15:54:49 +02:00
return WINED3DERR_INVALIDCALL ;
}
2008-04-07 12:08:16 +02:00
if ( ! This - > stateBlock - > vertexDecl ) {
WARN ( " (%p) : Called without a valid vertex declaration set \n " , This ) ;
return WINED3DERR_INVALIDCALL ;
}
2007-03-10 00:44:46 +01:00
if ( This - > stateBlock - > streamIsUP ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_INDEXBUFFER ) ;
This - > stateBlock - > streamIsUP = FALSE ;
}
2009-04-06 13:38:56 +02:00
vbo = ( ( struct wined3d_buffer * ) pIB ) - > buffer_object ;
2004-12-09 12:42:34 +01:00
2009-03-05 12:30:43 +01:00
TRACE ( " (%p) : min %u, vertex count %u, startIdx %u, index count %u \n " ,
This , minIndex , NumVertices , startIndex , index_count ) ;
2004-12-09 12:42:34 +01:00
2009-04-09 10:50:31 +02:00
if ( This - > stateBlock - > IndexFmt = = WINED3DFMT_R16_UINT ) {
2004-12-09 12:42:34 +01:00
idxStride = 2 ;
} else {
idxStride = 4 ;
}
2007-01-06 18:19:55 +01:00
if ( This - > stateBlock - > loadBaseVertexIndex ! = This - > stateBlock - > baseVertexIndex ) {
This - > stateBlock - > loadBaseVertexIndex = This - > stateBlock - > baseVertexIndex ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_STREAMSRC ) ;
}
2009-03-05 12:30:43 +01:00
drawPrimitive ( iface , index_count , NumVertices , startIndex , idxStride ,
2009-04-06 13:38:56 +02:00
vbo ? NULL : ( ( struct wined3d_buffer * ) pIB ) - > resource . allocatedMemory , minIndex ) ;
2004-12-09 12:42:34 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2009-03-05 12:30:43 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP ( IWineD3DDevice * iface , UINT vertex_count ,
const void * pVertexStreamZeroData , UINT VertexStreamZeroStride )
2009-03-05 12:30:42 +01:00
{
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-06 14:56:23 +01:00
IWineD3DBuffer * vb ;
2004-12-09 12:42:34 +01:00
2009-03-05 12:30:43 +01:00
TRACE ( " (%p) : vertex count %u, pVtxData %p, stride %u \n " ,
This , vertex_count , pVertexStreamZeroData , VertexStreamZeroStride ) ;
2004-12-09 12:42:34 +01:00
2008-04-07 12:08:16 +02:00
if ( ! This - > stateBlock - > vertexDecl ) {
WARN ( " (%p) : Called without a valid vertex declaration set \n " , This ) ;
return WINED3DERR_INVALIDCALL ;
}
2004-12-20 20:27:06 +01:00
/* Note in the following, it's not this type, but that's the purpose of streamIsUP */
2007-08-14 14:49:39 +02:00
vb = This - > stateBlock - > streamSource [ 0 ] ;
2009-03-06 14:56:23 +01:00
This - > stateBlock - > streamSource [ 0 ] = ( IWineD3DBuffer * ) pVertexStreamZeroData ;
if ( vb ) IWineD3DBuffer_Release ( vb ) ;
2007-04-09 01:55:27 +02:00
This - > stateBlock - > streamOffset [ 0 ] = 0 ;
2005-07-05 16:05:18 +02:00
This - > stateBlock - > streamStride [ 0 ] = VertexStreamZeroStride ;
2004-12-09 12:42:34 +01:00
This - > stateBlock - > streamIsUP = TRUE ;
2007-01-06 18:19:55 +01:00
This - > stateBlock - > loadBaseVertexIndex = 0 ;
2005-08-19 12:05:00 +02:00
2007-01-04 00:14:20 +01:00
/* TODO: Only mark dirty if drawing from a different UP address */
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_STREAMSRC ) ;
2009-03-05 12:30:43 +01:00
drawPrimitive ( iface , vertex_count , 0 /* NumVertices */ , 0 /* start_idx */ ,
0 /* indxSize*/ , NULL /* indxData */ , 0 /* indxMin */ ) ;
2006-05-10 19:57:49 +02:00
/* MSDN specifies stream zero settings must be set to NULL */
2005-07-05 16:05:18 +02:00
This - > stateBlock - > streamStride [ 0 ] = 0 ;
This - > stateBlock - > streamSource [ 0 ] = NULL ;
2004-12-09 12:42:34 +01:00
2007-01-04 00:14:20 +01:00
/* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
* the new stream sources or use UP drawing again
*/
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2009-03-05 12:30:43 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP ( IWineD3DDevice * iface , UINT MinVertexIndex ,
UINT NumVertices , UINT index_count , const void * pIndexData , WINED3DFORMAT IndexDataFormat ,
2009-03-05 12:30:42 +01:00
const void * pVertexStreamZeroData , UINT VertexStreamZeroStride )
{
2004-12-09 12:42:34 +01:00
int idxStride ;
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-03-06 14:56:23 +01:00
IWineD3DBuffer * vb ;
2009-04-06 16:46:12 +02:00
IWineD3DBuffer * ib ;
2004-12-09 12:42:34 +01:00
2009-03-05 12:30:43 +01:00
TRACE ( " (%p) : MinVtxIdx %u, NumVIdx %u, index count %u, pidxdata %p, IdxFmt %u, pVtxdata %p, stride=%u \n " ,
This , MinVertexIndex , NumVertices , index_count , pIndexData ,
IndexDataFormat , pVertexStreamZeroData , VertexStreamZeroStride ) ;
2004-12-09 12:42:34 +01:00
2008-04-07 12:08:16 +02:00
if ( ! This - > stateBlock - > vertexDecl ) {
WARN ( " (%p) : Called without a valid vertex declaration set \n " , This ) ;
return WINED3DERR_INVALIDCALL ;
}
2009-02-19 16:59:42 +01:00
if ( IndexDataFormat = = WINED3DFMT_R16_UINT ) {
2004-12-09 12:42:34 +01:00
idxStride = 2 ;
} else {
idxStride = 4 ;
}
2004-12-20 20:27:06 +01:00
/* Note in the following, it's not this type, but that's the purpose of streamIsUP */
2007-08-14 14:49:39 +02:00
vb = This - > stateBlock - > streamSource [ 0 ] ;
2009-03-06 14:56:23 +01:00
This - > stateBlock - > streamSource [ 0 ] = ( IWineD3DBuffer * ) pVertexStreamZeroData ;
if ( vb ) IWineD3DBuffer_Release ( vb ) ;
2004-12-09 12:42:34 +01:00
This - > stateBlock - > streamIsUP = TRUE ;
2007-04-09 01:55:27 +02:00
This - > stateBlock - > streamOffset [ 0 ] = 0 ;
2005-07-05 16:05:18 +02:00
This - > stateBlock - > streamStride [ 0 ] = VertexStreamZeroStride ;
2004-12-09 12:42:34 +01:00
2007-01-02 21:07:39 +01:00
/* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
This - > stateBlock - > baseVertexIndex = 0 ;
2007-01-06 18:19:55 +01:00
This - > stateBlock - > loadBaseVertexIndex = 0 ;
/* Mark the state dirty until we have nicer tracking of the stream source pointers */
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VDECL ) ;
2007-02-19 15:25:32 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_INDEXBUFFER ) ;
2007-01-02 00:35:07 +01:00
2009-03-05 12:30:43 +01:00
drawPrimitive ( iface , index_count , NumVertices , 0 /* start_idx */ ,
idxStride , pIndexData , MinVertexIndex ) ;
2004-12-09 12:42:34 +01:00
2006-05-10 19:57:49 +02:00
/* MSDN specifies stream zero settings and index buffer must be set to NULL */
2005-07-05 16:05:18 +02:00
This - > stateBlock - > streamSource [ 0 ] = NULL ;
This - > stateBlock - > streamStride [ 0 ] = 0 ;
2007-08-14 14:46:38 +02:00
ib = This - > stateBlock - > pIndexData ;
if ( ib ) {
2009-04-06 16:46:12 +02:00
IWineD3DBuffer_Release ( ib ) ;
2007-08-14 14:46:38 +02:00
This - > stateBlock - > pIndexData = NULL ;
}
2007-01-06 18:19:55 +01:00
/* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
* SetStreamSource to specify a vertex buffer
*/
2004-12-09 12:42:34 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2008-12-01 15:32:15 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided ( IWineD3DDevice * iface ,
2009-03-05 12:30:43 +01:00
UINT vertex_count , const WineDirect3DVertexStridedData * DrawPrimStrideData )
2008-12-01 15:32:15 +01:00
{
2007-01-02 00:35:07 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-05-06 16:58:57 +02:00
2007-01-02 21:07:39 +01:00
/* Mark the state dirty until we have nicer tracking
* its fine to change baseVertexIndex because that call is only called by ddraw which does not need
* that value .
*/
2007-01-02 00:35:07 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VDECL ) ;
2007-02-19 15:25:32 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_INDEXBUFFER ) ;
2007-01-02 21:07:39 +01:00
This - > stateBlock - > baseVertexIndex = 0 ;
2007-01-02 21:13:28 +01:00
This - > up_strided = DrawPrimStrideData ;
2009-03-05 12:30:43 +01:00
drawPrimitive ( iface , vertex_count , 0 , 0 , 0 , NULL , 0 ) ;
2007-01-02 21:13:28 +01:00
This - > up_strided = NULL ;
2006-05-06 16:58:57 +02:00
return WINED3D_OK ;
}
2007-07-27 14:39:55 +02:00
2008-12-01 15:32:15 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided ( IWineD3DDevice * iface ,
2009-03-05 12:30:43 +01:00
UINT vertex_count , const WineDirect3DVertexStridedData * DrawPrimStrideData ,
2009-03-05 12:30:42 +01:00
UINT NumVertices , const void * pIndexData , WINED3DFORMAT IndexDataFormat )
2008-12-01 15:32:15 +01:00
{
2007-07-27 14:39:55 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-02-19 16:59:42 +01:00
DWORD idxSize = ( IndexDataFormat = = WINED3DFMT_R32_UINT ? 4 : 2 ) ;
2007-07-27 14:39:55 +02:00
/* Mark the state dirty until we have nicer tracking
* its fine to change baseVertexIndex because that call is only called by ddraw which does not need
* that value .
*/
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VDECL ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_INDEXBUFFER ) ;
This - > stateBlock - > streamIsUP = TRUE ;
This - > stateBlock - > baseVertexIndex = 0 ;
This - > up_strided = DrawPrimStrideData ;
2009-03-05 12:30:43 +01:00
drawPrimitive ( iface , vertex_count , 0 /* numindices */ , 0 /* start_idx */ , idxSize , pIndexData , 0 /* minindex */ ) ;
2007-07-27 14:39:55 +02:00
This - > up_strided = NULL ;
return WINED3D_OK ;
}
2007-09-01 01:54:15 +02:00
static HRESULT IWineD3DDeviceImpl_UpdateVolume ( IWineD3DDevice * iface , IWineD3DVolume * pSourceVolume , IWineD3DVolume * pDestinationVolume ) {
/* This is a helper function for UpdateTexture, there is no public UpdateVolume method in d3d. Since it's
* not callable by the app directly no parameter validation checks are needed here .
*/
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
WINED3DLOCKED_BOX src ;
WINED3DLOCKED_BOX dst ;
HRESULT hr ;
TRACE ( " (%p)->(%p, %p) \n " , This , pSourceVolume , pDestinationVolume ) ;
/* TODO: Implement direct loading into the gl volume instead of using memcpy and
* dirtification to improve loading performance .
*/
hr = IWineD3DVolume_LockBox ( pSourceVolume , & src , NULL , WINED3DLOCK_READONLY ) ;
if ( FAILED ( hr ) ) return hr ;
hr = IWineD3DVolume_LockBox ( pDestinationVolume , & dst , NULL , WINED3DLOCK_DISCARD ) ;
if ( FAILED ( hr ) ) {
IWineD3DVolume_UnlockBox ( pSourceVolume ) ;
return hr ;
}
memcpy ( dst . pBits , src . pBits , ( ( IWineD3DVolumeImpl * ) pDestinationVolume ) - > resource . size ) ;
hr = IWineD3DVolume_UnlockBox ( pDestinationVolume ) ;
if ( FAILED ( hr ) ) {
IWineD3DVolume_UnlockBox ( pSourceVolume ) ;
} else {
hr = IWineD3DVolume_UnlockBox ( pSourceVolume ) ;
}
return hr ;
}
2007-07-27 14:39:55 +02:00
/* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture ( IWineD3DDevice * iface , IWineD3DBaseTexture * pSourceTexture , IWineD3DBaseTexture * pDestinationTexture ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-04-07 12:51:12 +02:00
HRESULT hr = WINED3D_OK ;
2006-03-09 23:21:16 +01:00
WINED3DRESOURCETYPE sourceType ;
WINED3DRESOURCETYPE destinationType ;
2005-11-04 13:39:17 +01:00
int i , levels ;
2005-07-12 19:02:47 +02:00
2005-11-04 13:39:17 +01:00
/* TODO: think about moving the code into IWineD3DBaseTexture */
2005-07-12 19:02:47 +02:00
2005-11-04 13:39:17 +01:00
TRACE ( " (%p) Source %p Destination %p \n " , This , pSourceTexture , pDestinationTexture ) ;
2005-07-12 19:02:47 +02:00
2005-11-23 20:14:43 +01:00
/* verify that the source and destination textures aren't NULL */
2005-11-04 13:39:17 +01:00
if ( NULL = = pSourceTexture | | NULL = = pDestinationTexture ) {
2006-04-07 12:51:12 +02:00
WARN ( " (%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL \n " ,
2005-11-04 13:39:17 +01:00
This , pSourceTexture , pDestinationTexture ) ;
2006-04-07 12:51:12 +02:00
hr = WINED3DERR_INVALIDCALL ;
2005-11-04 13:39:17 +01:00
}
2005-07-12 19:02:47 +02:00
2005-11-04 13:39:17 +01:00
if ( pSourceTexture = = pDestinationTexture ) {
2006-04-07 12:51:12 +02:00
WARN ( " (%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL \n " ,
2005-11-04 13:39:17 +01:00
This , pSourceTexture , pDestinationTexture ) ;
2006-04-07 12:51:12 +02:00
hr = WINED3DERR_INVALIDCALL ;
2005-07-12 19:02:47 +02:00
}
2005-11-04 13:39:17 +01:00
/* Verify that the source and destination textures are the same type */
sourceType = IWineD3DBaseTexture_GetType ( pSourceTexture ) ;
destinationType = IWineD3DBaseTexture_GetType ( pDestinationTexture ) ;
2005-07-12 19:02:47 +02:00
2005-11-04 13:39:17 +01:00
if ( sourceType ! = destinationType ) {
2006-04-07 12:51:12 +02:00
WARN ( " (%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL \n " ,
2005-11-04 13:39:17 +01:00
This ) ;
2006-04-07 12:51:12 +02:00
hr = WINED3DERR_INVALIDCALL ;
2005-11-04 13:39:17 +01:00
}
2005-07-12 19:02:47 +02:00
2005-11-04 13:39:17 +01:00
/* check that both textures have the identical numbers of levels */
if ( IWineD3DBaseTexture_GetLevelCount ( pDestinationTexture ) ! = IWineD3DBaseTexture_GetLevelCount ( pSourceTexture ) ) {
2008-01-23 15:16:30 +01:00
WARN ( " (%p) : source (%p) and destination (%p) textures must have identical numbers of levels, returning WINED3DERR_INVALIDCALL \n " , This , pSourceTexture , pDestinationTexture ) ;
2006-04-07 12:51:12 +02:00
hr = WINED3DERR_INVALIDCALL ;
2005-07-12 19:02:47 +02:00
}
2005-11-04 13:39:17 +01:00
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK = = hr ) {
2009-02-17 00:25:51 +01:00
IWineD3DBaseTextureImpl * pDestImpl = ( IWineD3DBaseTextureImpl * ) pDestinationTexture ;
2005-11-04 13:39:17 +01:00
/* Make sure that the destination texture is loaded */
2009-02-17 00:25:51 +01:00
pDestImpl - > baseTexture . internal_preload ( pDestinationTexture , SRGB_RGB ) ;
2005-11-04 13:39:17 +01:00
/* Update every surface level of the texture */
levels = IWineD3DBaseTexture_GetLevelCount ( pDestinationTexture ) ;
switch ( sourceType ) {
2006-03-09 23:21:16 +01:00
case WINED3DRTYPE_TEXTURE :
2005-11-04 13:39:17 +01:00
{
IWineD3DSurface * srcSurface ;
IWineD3DSurface * destSurface ;
for ( i = 0 ; i < levels ; + + i ) {
IWineD3DTexture_GetSurfaceLevel ( ( IWineD3DTexture * ) pSourceTexture , i , & srcSurface ) ;
IWineD3DTexture_GetSurfaceLevel ( ( IWineD3DTexture * ) pDestinationTexture , i , & destSurface ) ;
hr = IWineD3DDevice_UpdateSurface ( iface , srcSurface , NULL , destSurface , NULL ) ;
IWineD3DSurface_Release ( srcSurface ) ;
IWineD3DSurface_Release ( destSurface ) ;
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK ! = hr ) {
2005-11-04 13:39:17 +01:00
WARN ( " (%p) : Call to update surface failed \n " , This ) ;
return hr ;
}
}
}
break ;
2006-03-09 23:21:16 +01:00
case WINED3DRTYPE_CUBETEXTURE :
2005-11-04 13:39:17 +01:00
{
IWineD3DSurface * srcSurface ;
IWineD3DSurface * destSurface ;
2006-04-04 15:51:28 +02:00
WINED3DCUBEMAP_FACES faceType ;
2005-11-04 13:39:17 +01:00
for ( i = 0 ; i < levels ; + + i ) {
/* Update each cube face */
2006-10-31 09:20:12 +01:00
for ( faceType = WINED3DCUBEMAP_FACE_POSITIVE_X ; faceType < = WINED3DCUBEMAP_FACE_NEGATIVE_Z ; + + faceType ) {
2005-11-04 13:39:17 +01:00
hr = IWineD3DCubeTexture_GetCubeMapSurface ( ( IWineD3DCubeTexture * ) pSourceTexture , faceType , i , & srcSurface ) ;
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK ! = hr ) {
2005-11-04 13:39:17 +01:00
FIXME ( " (%p) : Failed to get src cube surface facetype %d, level %d \n " , This , faceType , i ) ;
} else {
TRACE ( " Got srcSurface %p \n " , srcSurface ) ;
}
hr = IWineD3DCubeTexture_GetCubeMapSurface ( ( IWineD3DCubeTexture * ) pDestinationTexture , faceType , i , & destSurface ) ;
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK ! = hr ) {
2005-11-04 13:39:17 +01:00
FIXME ( " (%p) : Failed to get src cube surface facetype %d, level %d \n " , This , faceType , i ) ;
} else {
TRACE ( " Got desrSurface %p \n " , destSurface ) ;
}
hr = IWineD3DDevice_UpdateSurface ( iface , srcSurface , NULL , destSurface , NULL ) ;
IWineD3DSurface_Release ( srcSurface ) ;
IWineD3DSurface_Release ( destSurface ) ;
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK ! = hr ) {
2005-11-04 13:39:17 +01:00
WARN ( " (%p) : Call to update surface failed \n " , This ) ;
return hr ;
}
}
}
}
break ;
2007-09-01 01:54:15 +02:00
2006-03-09 23:21:16 +01:00
case WINED3DRTYPE_VOLUMETEXTURE :
2005-11-04 13:39:17 +01:00
{
2007-09-01 01:54:15 +02:00
IWineD3DVolume * srcVolume = NULL ;
IWineD3DVolume * destVolume = NULL ;
2005-11-04 13:39:17 +01:00
for ( i = 0 ; i < levels ; + + i ) {
2007-09-01 01:54:15 +02:00
IWineD3DVolumeTexture_GetVolumeLevel ( ( IWineD3DVolumeTexture * ) pSourceTexture , i , & srcVolume ) ;
IWineD3DVolumeTexture_GetVolumeLevel ( ( IWineD3DVolumeTexture * ) pDestinationTexture , i , & destVolume ) ;
hr = IWineD3DDeviceImpl_UpdateVolume ( iface , srcVolume , destVolume ) ;
IWineD3DVolume_Release ( srcVolume ) ;
IWineD3DVolume_Release ( destVolume ) ;
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK ! = hr ) {
2005-11-04 13:39:17 +01:00
WARN ( " (%p) : Call to update volume failed \n " , This ) ;
return hr ;
}
}
}
break ;
2007-09-01 01:54:15 +02:00
2005-11-04 13:39:17 +01:00
default :
FIXME ( " (%p) : Unsupported source and destination type \n " , This ) ;
2006-04-07 12:51:12 +02:00
hr = WINED3DERR_INVALIDCALL ;
2005-11-04 13:39:17 +01:00
}
2005-07-12 19:02:47 +02:00
}
2005-11-04 13:39:17 +01:00
return hr ;
2005-03-02 13:16:10 +01:00
}
2005-01-26 21:54:00 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData ( IWineD3DDevice * iface , UINT iSwapChain , IWineD3DSurface * pDestSurface ) {
2005-06-23 13:05:24 +02:00
IWineD3DSwapChain * swapChain ;
HRESULT hr ;
2008-01-23 22:39:56 +01:00
hr = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapChain ) ;
2006-04-07 12:51:12 +02:00
if ( hr = = WINED3D_OK ) {
2005-06-23 13:05:24 +02:00
hr = IWineD3DSwapChain_GetFrontBufferData ( swapChain , pDestSurface ) ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_Release ( swapChain ) ;
2005-06-23 13:05:24 +02:00
}
return hr ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice ( IWineD3DDevice * iface , DWORD * pNumPasses ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-08-21 15:10:46 +02:00
IWineD3DBaseTextureImpl * texture ;
DWORD i ;
2008-09-05 13:14:47 +02:00
TRACE ( " (%p) : %p \n " , This , pNumPasses ) ;
2008-08-21 15:10:46 +02:00
for ( i = 0 ; i < MAX_COMBINED_SAMPLERS ; i + + ) {
if ( This - > stateBlock - > samplerState [ i ] [ WINED3DSAMP_MINFILTER ] = = WINED3DTEXF_NONE ) {
WARN ( " Sampler state %u has minfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER \n " , i ) ;
return WINED3DERR_UNSUPPORTEDTEXTUREFILTER ;
}
if ( This - > stateBlock - > samplerState [ i ] [ WINED3DSAMP_MAGFILTER ] = = WINED3DTEXF_NONE ) {
WARN ( " Sampler state %u has magfilter D3DTEXF_NONE, returning D3DERR_UNSUPPORTEDTEXTUREFILTER \n " , i ) ;
return WINED3DERR_UNSUPPORTEDTEXTUREFILTER ;
}
texture = ( IWineD3DBaseTextureImpl * ) This - > stateBlock - > textures [ i ] ;
2009-03-12 09:53:15 +01:00
if ( ! texture | | texture - > resource . format_desc - > Flags & WINED3DFMT_FLAG_FILTERING ) continue ;
2008-08-21 15:10:46 +02:00
if ( This - > stateBlock - > samplerState [ i ] [ WINED3DSAMP_MAGFILTER ] ! = WINED3DTEXF_POINT ) {
WARN ( " Non-filterable texture and mag filter enabled on samper %u, returning E_FAIL \n " , i ) ;
return E_FAIL ;
}
if ( This - > stateBlock - > samplerState [ i ] [ WINED3DSAMP_MINFILTER ] ! = WINED3DTEXF_POINT ) {
WARN ( " Non-filterable texture and min filter enabled on samper %u, returning E_FAIL \n " , i ) ;
return E_FAIL ;
}
if ( This - > stateBlock - > samplerState [ i ] [ WINED3DSAMP_MIPFILTER ] ! = WINED3DTEXF_NONE & &
This - > stateBlock - > samplerState [ i ] [ WINED3DSAMP_MIPFILTER ] ! = WINED3DTEXF_POINT /* sic! */ ) {
WARN ( " Non-filterable texture and mip filter enabled on samper %u, returning E_FAIL \n " , i ) ;
return E_FAIL ;
}
}
2005-03-02 13:16:10 +01:00
/* return a sensible default */
* pNumPasses = 1 ;
2008-08-21 15:10:46 +02:00
TRACE ( " returning D3D_OK \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-01-27 11:40:57 +01:00
2008-04-02 23:12:16 +02:00
static void dirtify_p8_texture_samplers ( IWineD3DDeviceImpl * device )
{
int i ;
for ( i = 0 ; i < MAX_COMBINED_SAMPLERS ; i + + ) {
IWineD3DBaseTextureImpl * texture = ( IWineD3DBaseTextureImpl * ) device - > stateBlock - > textures [ i ] ;
2009-03-13 10:44:18 +01:00
if ( texture & & ( texture - > resource . format_desc - > format = = WINED3DFMT_P8
| | texture - > resource . format_desc - > format = = WINED3DFMT_A8P8 ) )
{
2008-04-02 23:12:16 +02:00
IWineD3DDeviceImpl_MarkStateDirty ( device , STATE_SAMPLER ( i ) ) ;
}
}
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries ( IWineD3DDevice * iface , UINT PaletteNumber , CONST PALETTEENTRY * pEntries ) {
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-11 12:57:20 +02:00
int j ;
2008-03-26 23:23:04 +01:00
UINT NewSize ;
PALETTEENTRY * * palettes ;
2005-08-11 12:57:20 +02:00
TRACE ( " (%p) : PaletteNumber %u \n " , This , PaletteNumber ) ;
2008-03-26 23:23:04 +01:00
2008-01-01 14:25:28 +01:00
if ( PaletteNumber > = MAX_PALETTES ) {
2008-03-26 23:23:04 +01:00
ERR ( " (%p) : (%u) Out of range 0-%u, returning Invalid Call \n " , This , PaletteNumber , MAX_PALETTES ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-08-11 12:57:20 +02:00
}
2008-03-26 23:23:04 +01:00
if ( PaletteNumber > = This - > NumberOfPalettes ) {
NewSize = This - > NumberOfPalettes ;
do {
NewSize * = 2 ;
} while ( PaletteNumber > = NewSize ) ;
palettes = HeapReAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , This - > palettes , sizeof ( PALETTEENTRY * ) * NewSize ) ;
if ( ! palettes ) {
ERR ( " Out of memory! \n " ) ;
return E_OUTOFMEMORY ;
}
This - > palettes = palettes ;
This - > NumberOfPalettes = NewSize ;
}
if ( ! This - > palettes [ PaletteNumber ] ) {
This - > palettes [ PaletteNumber ] = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( PALETTEENTRY ) * 256 ) ;
if ( ! This - > palettes [ PaletteNumber ] ) {
ERR ( " Out of memory! \n " ) ;
return E_OUTOFMEMORY ;
}
}
2005-08-11 12:57:20 +02:00
for ( j = 0 ; j < 256 ; + + j ) {
This - > palettes [ PaletteNumber ] [ j ] . peRed = pEntries [ j ] . peRed ;
This - > palettes [ PaletteNumber ] [ j ] . peGreen = pEntries [ j ] . peGreen ;
This - > palettes [ PaletteNumber ] [ j ] . peBlue = pEntries [ j ] . peBlue ;
This - > palettes [ PaletteNumber ] [ j ] . peFlags = pEntries [ j ] . peFlags ;
}
2008-04-02 23:12:16 +02:00
if ( PaletteNumber = = This - > currentPalette ) dirtify_p8_texture_samplers ( This ) ;
2005-08-11 12:57:20 +02:00
TRACE ( " (%p) : returning \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-01-27 11:40:57 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries ( IWineD3DDevice * iface , UINT PaletteNumber , PALETTEENTRY * pEntries ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-11 12:57:20 +02:00
int j ;
TRACE ( " (%p) : PaletteNumber %u \n " , This , PaletteNumber ) ;
2008-03-26 23:23:04 +01:00
if ( PaletteNumber > = This - > NumberOfPalettes | | ! This - > palettes [ PaletteNumber ] ) {
/* What happens in such situation isn't documented; Native seems to silently abort
on such conditions . Return Invalid Call . */
2008-04-07 13:01:02 +02:00
ERR ( " (%p) : (%u) Nonexistent palette. NumberOfPalettes %u \n " , This , PaletteNumber , This - > NumberOfPalettes ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-08-11 12:57:20 +02:00
}
for ( j = 0 ; j < 256 ; + + j ) {
pEntries [ j ] . peRed = This - > palettes [ PaletteNumber ] [ j ] . peRed ;
pEntries [ j ] . peGreen = This - > palettes [ PaletteNumber ] [ j ] . peGreen ;
pEntries [ j ] . peBlue = This - > palettes [ PaletteNumber ] [ j ] . peBlue ;
pEntries [ j ] . peFlags = This - > palettes [ PaletteNumber ] [ j ] . peFlags ;
}
TRACE ( " (%p) : returning \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-01-26 21:54:00 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette ( IWineD3DDevice * iface , UINT PaletteNumber ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-11 12:57:20 +02:00
TRACE ( " (%p) : PaletteNumber %u \n " , This , PaletteNumber ) ;
2008-03-26 23:23:04 +01:00
/* Native appears to silently abort on attempt to make an uninitialized palette current and render.
( tested with reference rasterizer ) . Return Invalid Call . */
if ( PaletteNumber > = This - > NumberOfPalettes | | ! This - > palettes [ PaletteNumber ] ) {
2008-04-07 13:01:02 +02:00
ERR ( " (%p) : (%u) Nonexistent palette. NumberOfPalettes %u \n " , This , PaletteNumber , This - > NumberOfPalettes ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-08-11 12:57:20 +02:00
}
/*TODO: stateblocks */
2008-04-02 23:12:16 +02:00
if ( This - > currentPalette ! = PaletteNumber ) {
This - > currentPalette = PaletteNumber ;
dirtify_p8_texture_samplers ( This ) ;
}
2005-08-11 12:57:20 +02:00
TRACE ( " (%p) : returning \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-01-26 21:54:00 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette ( IWineD3DDevice * iface , UINT * PaletteNumber ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-11 12:57:20 +02:00
if ( PaletteNumber = = NULL ) {
WARN ( " (%p) : returning Invalid Call \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-08-11 12:57:20 +02:00
}
/*TODO: stateblocks */
* PaletteNumber = This - > currentPalette ;
TRACE ( " (%p) : returning %u \n " , This , * PaletteNumber ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-01-26 21:54:00 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing ( IWineD3DDevice * iface , BOOL bSoftware ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-12-01 15:32:14 +01:00
static BOOL warned ;
if ( ! warned )
{
2005-08-11 12:31:40 +02:00
FIXME ( " (%p) : stub \n " , This ) ;
2008-12-01 15:32:14 +01:00
warned = TRUE ;
2005-08-11 12:31:40 +02:00
}
2005-10-29 12:30:36 +02:00
This - > softwareVertexProcessing = bSoftware ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-26 21:54:00 +01:00
}
2006-06-10 13:15:32 +02:00
static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-12-01 15:32:14 +01:00
static BOOL warned ;
if ( ! warned )
{
2005-08-11 12:31:40 +02:00
FIXME ( " (%p) : stub \n " , This ) ;
2008-12-01 15:32:14 +01:00
warned = TRUE ;
2005-08-11 12:31:40 +02:00
}
2005-10-29 12:30:36 +02:00
return This - > softwareVertexProcessing ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus ( IWineD3DDevice * iface , UINT iSwapChain , WINED3DRASTER_STATUS * pRasterStatus ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-08-27 11:58:53 +02:00
IWineD3DSwapChain * swapChain ;
HRESULT hr ;
2005-07-13 16:15:54 +02:00
2005-08-27 11:58:53 +02:00
TRACE ( " (%p) : SwapChain %d returning %p \n " , This , iSwapChain , pRasterStatus ) ;
2008-01-23 22:39:56 +01:00
hr = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapChain ) ;
2006-04-07 12:51:12 +02:00
if ( hr = = WINED3D_OK ) {
2005-08-27 11:58:53 +02:00
hr = IWineD3DSwapChain_GetRasterStatus ( swapChain , pRasterStatus ) ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_Release ( swapChain ) ;
2005-08-27 11:58:53 +02:00
} else {
2005-11-10 13:14:56 +01:00
FIXME ( " (%p) IWineD3DSwapChain_GetRasterStatus returned in error \n " , This ) ;
2005-08-27 11:58:53 +02:00
}
return hr ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode ( IWineD3DDevice * iface , float nSegments ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-12-01 15:32:14 +01:00
static BOOL warned ;
2005-07-13 16:15:54 +02:00
if ( nSegments ! = 0.0f ) {
2008-12-01 15:32:14 +01:00
if ( ! warned )
{
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) : stub nSegments(%f) \n " , This , nSegments ) ;
2008-12-01 15:32:14 +01:00
warned = TRUE ;
2005-03-02 13:16:10 +01:00
}
2005-01-26 21:54:00 +01:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-26 21:54:00 +01:00
}
2005-03-02 13:16:10 +01:00
2006-06-10 13:15:32 +02:00
static float WINAPI IWineD3DDeviceImpl_GetNPatchMode ( IWineD3DDevice * iface ) {
2005-01-26 21:54:00 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2008-12-01 15:32:14 +01:00
static BOOL warned ;
if ( ! warned )
{
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) : stub returning(%f) \n " , This , 0.0f ) ;
2008-12-01 15:32:14 +01:00
warned = TRUE ;
2005-03-02 13:16:10 +01:00
}
return 0.0f ;
}
2005-01-26 21:54:00 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface ( IWineD3DDevice * iface , IWineD3DSurface * pSourceSurface , CONST RECT * pSourceRect , IWineD3DSurface * pDestinationSurface , CONST POINT * pDestPoint ) {
2005-07-12 19:02:47 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
/** TODO: remove casts to IWineD3DSurfaceImpl
* NOTE : move code to surface to accomplish this
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
IWineD3DSurfaceImpl * pSrcSurface = ( IWineD3DSurfaceImpl * ) pSourceSurface ;
2005-07-28 20:33:26 +02:00
int srcWidth , srcHeight ;
2005-11-04 12:13:45 +01:00
unsigned int srcSurfaceWidth , srcSurfaceHeight , destSurfaceWidth , destSurfaceHeight ;
2005-07-12 19:02:47 +02:00
WINED3DFORMAT destFormat , srcFormat ;
2005-11-04 12:13:45 +01:00
UINT destSize ;
2007-01-12 00:20:42 +01:00
int srcLeft , destLeft , destTop ;
2006-03-28 14:20:47 +02:00
WINED3DPOOL srcPool , destPool ;
2005-07-12 19:02:47 +02:00
int offset = 0 ;
int rowoffset = 0 ; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
glDescriptor * glDescription = NULL ;
2009-03-24 10:09:23 +01:00
const struct GlPixelFormatDesc * src_format_desc , * dst_format_desc ;
2007-08-11 20:02:01 +02:00
GLenum dummy ;
2008-07-15 23:54:44 +02:00
int sampler ;
2007-08-11 20:02:01 +02:00
int bpp ;
CONVERT_TYPES convert = NO_CONVERSION ;
2005-07-12 19:02:47 +02:00
WINED3DSURFACE_DESC winedesc ;
2005-11-04 12:13:45 +01:00
TRACE ( " (%p) : Source (%p) Rect (%p) Destination (%p) Point(%p) \n " , This , pSourceSurface , pSourceRect , pDestinationSurface , pDestPoint ) ;
2005-07-12 19:02:47 +02:00
IWineD3DSurface_GetDesc ( pSourceSurface , & winedesc ) ;
2009-06-15 09:06:50 +02:00
srcSurfaceWidth = winedesc . width ;
srcSurfaceHeight = winedesc . height ;
srcPool = winedesc . pool ;
srcFormat = winedesc . format ;
2005-07-12 19:02:47 +02:00
IWineD3DSurface_GetDesc ( pDestinationSurface , & winedesc ) ;
2009-06-15 09:06:50 +02:00
destSurfaceWidth = winedesc . width ;
destSurfaceHeight = winedesc . height ;
destPool = winedesc . pool ;
destFormat = winedesc . format ;
destSize = winedesc . size ;
2005-07-12 19:02:47 +02:00
2006-03-28 14:20:47 +02:00
if ( srcPool ! = WINED3DPOOL_SYSTEMMEM | | destPool ! = WINED3DPOOL_DEFAULT ) {
2006-04-07 12:51:12 +02:00
WARN ( " source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL \n " , pSourceSurface , pDestinationSurface ) ;
return WINED3DERR_INVALIDCALL ;
2005-07-12 19:02:47 +02:00
}
2005-11-04 12:13:45 +01:00
2007-08-11 20:02:01 +02:00
/* This call loads the opengl surface directly, instead of copying the surface to the
* destination ' s sysmem copy . If surface conversion is needed , use BltFast instead to
* copy in sysmem and use regular surface loading .
*/
d3dfmt_get_conv ( ( IWineD3DSurfaceImpl * ) pDestinationSurface , FALSE , TRUE ,
& dummy , & dummy , & dummy , & convert , & bpp , FALSE ) ;
if ( convert ! = NO_CONVERSION ) {
return IWineD3DSurface_BltFast ( pDestinationSurface ,
pDestPoint ? pDestPoint - > x : 0 ,
pDestPoint ? pDestPoint - > y : 0 ,
2008-11-25 11:57:39 +01:00
pSourceSurface , pSourceRect , 0 ) ;
2007-08-11 20:02:01 +02:00
}
2005-11-04 12:13:45 +01:00
if ( destFormat = = WINED3DFMT_UNKNOWN ) {
TRACE ( " (%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format \n " , This ) ;
IWineD3DSurface_SetFormat ( pDestinationSurface , srcFormat ) ;
/* Get the update surface description */
IWineD3DSurface_GetDesc ( pDestinationSurface , & winedesc ) ;
}
2007-03-17 23:00:39 +01:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2008-12-16 13:18:49 +01:00
ENTER_GL ( ) ;
GL_EXTCALL ( glActiveTextureARB ( GL_TEXTURE0_ARB ) ) ;
checkGLcall ( " glActiveTextureARB " ) ;
LEAVE_GL ( ) ;
2007-02-20 22:44:45 +01:00
2005-11-23 20:14:43 +01:00
/* Make sure the surface is loaded and up to date */
2009-02-17 00:25:51 +01:00
surface_internal_preload ( pDestinationSurface , SRGB_RGB ) ;
2009-01-16 16:22:09 +01:00
IWineD3DSurface_BindTexture ( pDestinationSurface , FALSE ) ;
2005-07-12 19:02:47 +02:00
IWineD3DSurface_GetGlDesc ( pDestinationSurface , & glDescription ) ;
2005-03-02 13:16:10 +01:00
2009-03-24 10:09:23 +01:00
src_format_desc = ( ( IWineD3DSurfaceImpl * ) pSrcSurface ) - > resource . format_desc ;
2009-03-13 10:44:17 +01:00
dst_format_desc = ( ( IWineD3DSurfaceImpl * ) pDestinationSurface ) - > resource . format_desc ;
2005-07-12 19:02:47 +02:00
/* this needs to be done in lines if the sourceRect != the sourceWidth */
srcWidth = pSourceRect ? pSourceRect - > right - pSourceRect - > left : srcSurfaceWidth ;
2007-03-10 04:16:44 +01:00
srcHeight = pSourceRect ? pSourceRect - > bottom - pSourceRect - > top : srcSurfaceHeight ;
2007-01-12 00:20:42 +01:00
srcLeft = pSourceRect ? pSourceRect - > left : 0 ;
2005-07-12 19:02:47 +02:00
destLeft = pDestPoint ? pDestPoint - > x : 0 ;
destTop = pDestPoint ? pDestPoint - > y : 0 ;
/* This function doesn't support compressed textures
the pitch is just bytesPerPixel * width */
2007-01-12 00:20:42 +01:00
if ( srcWidth ! = srcSurfaceWidth | | srcLeft ) {
2009-03-24 10:09:23 +01:00
rowoffset = srcSurfaceWidth * src_format_desc - > byte_count ;
offset + = srcLeft * src_format_desc - > byte_count ;
2005-07-12 19:02:47 +02:00
/* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
}
/* TODO DXT formats */
if ( pSourceRect ! = NULL & & pSourceRect - > top ! = 0 ) {
2009-03-24 10:09:23 +01:00
offset + = pSourceRect - > top * srcSurfaceWidth * src_format_desc - > byte_count ;
2005-07-12 19:02:47 +02:00
}
2008-09-24 15:56:48 +02:00
TRACE ( " (%p) glTexSubImage2D, level %d, left %d, top %d, width %d, height %d, fmt %#x, type %#x, memory %p+%#x \n " ,
2009-03-13 10:44:17 +01:00
This , glDescription - > level , destLeft , destTop , srcWidth , srcHeight , dst_format_desc - > glFormat ,
dst_format_desc - > glType , IWineD3DSurface_GetData ( pSourceSurface ) , offset ) ;
2005-07-12 19:02:47 +02:00
/* Sanity check */
if ( IWineD3DSurface_GetData ( pSourceSurface ) = = NULL ) {
2005-11-04 12:13:45 +01:00
/* need to lock the surface to get the data */
FIXME ( " Surfaces has no allocated memory, but should be an in memory only surface \n " ) ;
2005-07-12 19:02:47 +02:00
}
2005-11-04 12:13:45 +01:00
2008-10-19 02:05:10 +02:00
ENTER_GL ( ) ;
2005-07-12 19:02:47 +02:00
/* TODO: Cube and volume support */
if ( rowoffset ! = 0 ) {
/* not a whole row so we have to do it a line at a time */
int j ;
2005-11-04 12:13:45 +01:00
2008-01-09 20:37:05 +01:00
/* hopefully using pointer addition will be quicker than using a point + j * rowoffset */
2006-11-24 15:15:06 +01:00
const unsigned char * data = ( ( const unsigned char * ) IWineD3DSurface_GetData ( pSourceSurface ) ) + offset ;
2005-07-12 19:02:47 +02:00
2009-03-13 10:44:17 +01:00
for ( j = destTop ; j < ( srcHeight + destTop ) ; + + j )
{
glTexSubImage2D ( glDescription - > target , glDescription - > level , destLeft , j ,
srcWidth , 1 , dst_format_desc - > glFormat , dst_format_desc - > glType , data ) ;
2005-07-12 19:02:47 +02:00
data + = rowoffset ;
}
} else { /* Full width, so just write out the whole texture */
2008-09-24 15:56:48 +02:00
const unsigned char * data = ( ( const unsigned char * ) IWineD3DSurface_GetData ( pSourceSurface ) ) + offset ;
2005-07-12 19:02:47 +02:00
2009-06-12 09:46:03 +02:00
if ( dst_format_desc - > Flags & WINED3DFMT_FLAG_COMPRESSED )
{
2009-06-11 10:24:30 +02:00
if ( destSurfaceHeight ! = srcHeight | | destSurfaceWidth ! = srcWidth )
{
/* FIXME: The easy way to do this is to lock the destination, and copy the bits across. */
FIXME ( " Updating part of a compressed texture is not supported. \n " ) ;
}
if ( destFormat ! = srcFormat )
{
FIXME ( " Updating mixed format compressed textures is not supported. \n " ) ;
}
else
{
GL_EXTCALL ( glCompressedTexImage2DARB ( glDescription - > target , glDescription - > level ,
dst_format_desc - > glInternal , srcWidth , srcHeight , 0 , destSize , data ) ) ;
}
}
else
{
2008-09-24 15:56:48 +02:00
glTexSubImage2D ( glDescription - > target , glDescription - > level , destLeft , destTop ,
2009-03-13 10:44:17 +01:00
srcWidth , srcHeight , dst_format_desc - > glFormat , dst_format_desc - > glType , data ) ;
2005-07-12 19:02:47 +02:00
}
}
checkGLcall ( " glTexSubImage2D " ) ;
LEAVE_GL ( ) ;
2007-10-09 22:17:59 +02:00
IWineD3DSurface_ModifyLocation ( pDestinationSurface , SFLAG_INTEXTURE , TRUE ) ;
2008-07-15 23:54:44 +02:00
sampler = This - > rev_tex_unit_map [ 0 ] ;
if ( sampler ! = - 1 ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( sampler ) ) ;
}
2007-02-20 22:44:45 +01:00
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-01-26 21:54:00 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch ( IWineD3DDevice * iface , UINT Handle , CONST float * pNumSegs , CONST WINED3DRECTPATCH_INFO * pRectPatchInfo ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-07-04 17:57:45 +02:00
struct WineD3DRectPatch * patch ;
2009-03-05 12:30:43 +01:00
GLenum old_primitive_type ;
2007-07-04 17:57:45 +02:00
unsigned int i ;
struct list * e ;
BOOL found ;
2005-11-10 13:14:56 +01:00
TRACE ( " (%p) Handle(%d) noSegs(%p) rectpatch(%p) \n " , This , Handle , pNumSegs , pRectPatchInfo ) ;
2004-10-07 06:22:21 +02:00
2007-07-04 17:57:45 +02:00
if ( ! ( Handle | | pRectPatchInfo ) ) {
/* TODO: Write a test for the return value, thus the FIXME */
FIXME ( " Both Handle and pRectPatchInfo are NULL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
if ( Handle ) {
i = PATCHMAP_HASHFUNC ( Handle ) ;
found = FALSE ;
LIST_FOR_EACH ( e , & This - > patches [ i ] ) {
patch = LIST_ENTRY ( e , struct WineD3DRectPatch , entry ) ;
if ( patch - > Handle = = Handle ) {
found = TRUE ;
break ;
}
}
if ( ! found ) {
TRACE ( " Patch does not exist. Creating a new one \n " ) ;
patch = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * patch ) ) ;
patch - > Handle = Handle ;
list_add_head ( & This - > patches [ i ] , & patch - > entry ) ;
} else {
TRACE ( " Found existing patch %p \n " , patch ) ;
}
} else {
/* Since opengl does not load tesselated vertex attributes into numbered vertex
* attributes we have to tesselate , read back , and draw . This needs a patch
* management structure instance . Create one .
*
* A possible improvement is to check if a vertex shader is used , and if not directly
* draw the patch .
*/
FIXME ( " Drawing an uncached patch. This is slow \n " ) ;
patch = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( * patch ) ) ;
}
if ( pNumSegs [ 0 ] ! = patch - > numSegs [ 0 ] | | pNumSegs [ 1 ] ! = patch - > numSegs [ 1 ] | |
pNumSegs [ 2 ] ! = patch - > numSegs [ 2 ] | | pNumSegs [ 3 ] ! = patch - > numSegs [ 3 ] | |
( pRectPatchInfo & & memcmp ( pRectPatchInfo , & patch - > RectPatchInfo , sizeof ( * pRectPatchInfo ) ) ! = 0 ) ) {
HRESULT hr ;
TRACE ( " Tesselation density or patch info changed, retesselating \n " ) ;
if ( pRectPatchInfo ) {
2008-03-20 23:25:13 +01:00
patch - > RectPatchInfo = * pRectPatchInfo ;
2007-07-04 17:57:45 +02:00
}
patch - > numSegs [ 0 ] = pNumSegs [ 0 ] ;
patch - > numSegs [ 1 ] = pNumSegs [ 1 ] ;
patch - > numSegs [ 2 ] = pNumSegs [ 2 ] ;
patch - > numSegs [ 3 ] = pNumSegs [ 3 ] ;
hr = tesselate_rectpatch ( This , patch ) ;
if ( FAILED ( hr ) ) {
WARN ( " Patch tesselation failed \n " ) ;
/* Do not release the handle to store the params of the patch */
if ( ! Handle ) {
HeapFree ( GetProcessHeap ( ) , 0 , patch ) ;
}
return hr ;
}
}
This - > currentPatch = patch ;
2009-03-05 12:30:43 +01:00
old_primitive_type = This - > stateBlock - > gl_primitive_type ;
This - > stateBlock - > gl_primitive_type = GL_TRIANGLES ;
2009-03-20 19:16:52 +01:00
IWineD3DDevice_DrawPrimitiveStrided ( iface , patch - > numSegs [ 0 ] * patch - > numSegs [ 1 ] * 2 * 3 , & patch - > strided ) ;
2009-03-05 12:30:43 +01:00
This - > stateBlock - > gl_primitive_type = old_primitive_type ;
2007-07-04 17:57:45 +02:00
This - > currentPatch = NULL ;
/* Destroy uncached patches */
if ( ! Handle ) {
HeapFree ( GetProcessHeap ( ) , 0 , patch - > mem ) ;
HeapFree ( GetProcessHeap ( ) , 0 , patch ) ;
}
return WINED3D_OK ;
2004-10-07 06:22:21 +02:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch ( IWineD3DDevice * iface , UINT Handle , CONST float * pNumSegs , CONST WINED3DTRIPATCH_INFO * pTriPatchInfo ) {
2004-10-07 06:22:21 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-11-10 13:14:56 +01:00
TRACE ( " (%p) Handle(%d) noSegs(%p) tripatch(%p) \n " , This , Handle , pNumSegs , pTriPatchInfo ) ;
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) : Stub \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-01-12 20:50:22 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch ( IWineD3DDevice * iface , UINT Handle ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-07-04 17:57:45 +02:00
int i ;
struct WineD3DRectPatch * patch ;
struct list * e ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) Handle(%d) \n " , This , Handle ) ;
2007-07-04 17:57:45 +02:00
i = PATCHMAP_HASHFUNC ( Handle ) ;
LIST_FOR_EACH ( e , & This - > patches [ i ] ) {
patch = LIST_ENTRY ( e , struct WineD3DRectPatch , entry ) ;
if ( patch - > Handle = = Handle ) {
TRACE ( " Deleting patch %p \n " , patch ) ;
list_remove ( & patch - > entry ) ;
HeapFree ( GetProcessHeap ( ) , 0 , patch - > mem ) ;
HeapFree ( GetProcessHeap ( ) , 0 , patch ) ;
return WINED3D_OK ;
}
}
/* TODO: Write a test for the return value */
2007-12-07 21:01:34 +01:00
FIXME ( " Attempt to destroy nonexistent patch \n " ) ;
2007-07-04 17:57:45 +02:00
return WINED3DERR_INVALIDCALL ;
2005-07-13 16:15:54 +02:00
}
2005-03-02 13:16:10 +01:00
2007-04-16 21:21:13 +02:00
static IWineD3DSwapChain * get_swapchain ( IWineD3DSurface * target ) {
HRESULT hr ;
IWineD3DSwapChain * swapchain ;
hr = IWineD3DSurface_GetContainer ( target , & IID_IWineD3DSwapChain , ( void * * ) & swapchain ) ;
if ( SUCCEEDED ( hr ) ) {
IWineD3DSwapChain_Release ( ( IUnknown * ) swapchain ) ;
return swapchain ;
}
return NULL ;
}
2009-02-25 08:39:01 +01:00
static void color_fill_fbo ( IWineD3DDevice * iface , IWineD3DSurface * surface ,
const WINED3DRECT * rect , const float color [ 4 ] )
{
2007-04-16 21:21:13 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSwapChain * swapchain ;
swapchain = get_swapchain ( surface ) ;
if ( swapchain ) {
GLenum buffer ;
TRACE ( " Surface %p is onscreen \n " , surface ) ;
2008-08-03 21:17:57 +02:00
ActivateContext ( This , surface , CTXUSAGE_RESOURCELOAD ) ;
2008-07-30 00:24:43 +02:00
ENTER_GL ( ) ;
2007-05-03 20:57:50 +02:00
GL_EXTCALL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , 0 ) ) ;
2007-04-16 21:21:13 +02:00
buffer = surface_get_gl_buffer ( surface , swapchain ) ;
glDrawBuffer ( buffer ) ;
checkGLcall ( " glDrawBuffer() " ) ;
} else {
TRACE ( " Surface %p is offscreen \n " , surface ) ;
2008-07-30 00:24:43 +02:00
2008-08-03 21:17:57 +02:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2008-07-30 00:24:43 +02:00
ENTER_GL ( ) ;
2008-09-18 14:57:53 +02:00
context_bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > activeContext - > dst_fbo ) ;
context_attach_surface_fbo ( This , GL_FRAMEBUFFER_EXT , 0 , surface ) ;
2009-06-08 10:35:05 +02:00
context_attach_depth_stencil_fbo ( This , GL_FRAMEBUFFER_EXT , NULL , FALSE ) ;
2007-04-16 21:21:13 +02:00
}
if ( rect ) {
glEnable ( GL_SCISSOR_TEST ) ;
if ( ! swapchain ) {
glScissor ( rect - > x1 , rect - > y1 , rect - > x2 - rect - > x1 , rect - > y2 - rect - > y1 ) ;
} else {
glScissor ( rect - > x1 , ( ( IWineD3DSurfaceImpl * ) surface ) - > currentDesc . Height - rect - > y2 ,
rect - > x2 - rect - > x1 , rect - > y2 - rect - > y1 ) ;
}
checkGLcall ( " glScissor " ) ;
2008-08-04 19:28:32 +02:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SCISSORRECT ) ;
2007-04-16 21:21:13 +02:00
} else {
glDisable ( GL_SCISSOR_TEST ) ;
}
2008-08-03 21:17:57 +02:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_SCISSORTESTENABLE ) ) ;
glDisable ( GL_BLEND ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_ALPHABLENDENABLE ) ) ;
2007-04-16 21:21:13 +02:00
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_COLORWRITEENABLE ) ) ;
2009-02-25 08:39:01 +01:00
glClearColor ( color [ 0 ] , color [ 1 ] , color [ 2 ] , color [ 3 ] ) ;
2007-04-16 21:21:13 +02:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
checkGLcall ( " glClear " ) ;
2008-09-18 14:57:53 +02:00
if ( This - > activeContext - > current_fbo ) {
context_bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > activeContext - > current_fbo - > id ) ;
2007-04-16 21:21:13 +02:00
} else {
GL_EXTCALL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , 0 ) ) ;
checkGLcall ( " glBindFramebuffer() " ) ;
}
if ( swapchain & & surface = = ( ( IWineD3DSwapChainImpl * ) swapchain ) - > frontBuffer
& & ( ( IWineD3DSwapChainImpl * ) swapchain ) - > backBuffer ) {
glDrawBuffer ( GL_BACK ) ;
checkGLcall ( " glDrawBuffer() " ) ;
}
2008-07-30 00:24:43 +02:00
LEAVE_GL ( ) ;
2007-04-16 21:21:13 +02:00
}
2007-08-31 20:58:35 +02:00
static inline DWORD argb_to_fmt ( DWORD color , WINED3DFORMAT destfmt ) {
unsigned int r , g , b , a ;
DWORD ret ;
if ( destfmt = = WINED3DFMT_A8R8G8B8 | | destfmt = = WINED3DFMT_X8R8G8B8 | |
destfmt = = WINED3DFMT_R8G8B8 )
return color ;
TRACE ( " Converting color %08x to format %s \n " , color , debug_d3dformat ( destfmt ) ) ;
a = ( color & 0xff000000 ) > > 24 ;
r = ( color & 0x00ff0000 ) > > 16 ;
g = ( color & 0x0000ff00 ) > > 8 ;
b = ( color & 0x000000ff ) > > 0 ;
switch ( destfmt )
{
case WINED3DFMT_R5G6B5 :
if ( r = = 0xff & & g = = 0xff & & b = = 0xff ) return 0xffff ;
r = ( r * 32 ) / 256 ;
g = ( g * 64 ) / 256 ;
b = ( b * 32 ) / 256 ;
ret = r < < 11 ;
ret | = g < < 5 ;
ret | = b ;
TRACE ( " Returning %08x \n " , ret ) ;
return ret ;
case WINED3DFMT_X1R5G5B5 :
case WINED3DFMT_A1R5G5B5 :
a = ( a * 2 ) / 256 ;
r = ( r * 32 ) / 256 ;
g = ( g * 32 ) / 256 ;
b = ( b * 32 ) / 256 ;
ret = a < < 15 ;
ret | = r < < 10 ;
ret | = g < < 5 ;
ret | = b < < 0 ;
TRACE ( " Returning %08x \n " , ret ) ;
return ret ;
2009-02-19 16:59:42 +01:00
case WINED3DFMT_A8_UNORM :
2007-08-31 20:58:35 +02:00
TRACE ( " Returning %08x \n " , a ) ;
return a ;
case WINED3DFMT_X4R4G4B4 :
case WINED3DFMT_A4R4G4B4 :
a = ( a * 16 ) / 256 ;
r = ( r * 16 ) / 256 ;
g = ( g * 16 ) / 256 ;
b = ( b * 16 ) / 256 ;
ret = a < < 12 ;
ret | = r < < 8 ;
ret | = g < < 4 ;
ret | = b < < 0 ;
TRACE ( " Returning %08x \n " , ret ) ;
return ret ;
case WINED3DFMT_R3G3B2 :
r = ( r * 8 ) / 256 ;
g = ( g * 8 ) / 256 ;
b = ( b * 4 ) / 256 ;
ret = r < < 5 ;
ret | = g < < 2 ;
ret | = b < < 0 ;
TRACE ( " Returning %08x \n " , ret ) ;
return ret ;
case WINED3DFMT_X8B8G8R8 :
2009-02-19 16:59:42 +01:00
case WINED3DFMT_R8G8B8A8_UNORM :
2007-08-31 20:58:35 +02:00
ret = a < < 24 ;
ret | = b < < 16 ;
ret | = g < < 8 ;
ret | = r < < 0 ;
TRACE ( " Returning %08x \n " , ret ) ;
return ret ;
case WINED3DFMT_A2R10G10B10 :
a = ( a * 4 ) / 256 ;
r = ( r * 1024 ) / 256 ;
g = ( g * 1024 ) / 256 ;
b = ( b * 1024 ) / 256 ;
ret = a < < 30 ;
ret | = r < < 20 ;
ret | = g < < 10 ;
ret | = b < < 0 ;
TRACE ( " Returning %08x \n " , ret ) ;
return ret ;
2009-02-19 16:59:42 +01:00
case WINED3DFMT_R10G10B10A2_UNORM :
2007-08-31 20:58:35 +02:00
a = ( a * 4 ) / 256 ;
r = ( r * 1024 ) / 256 ;
g = ( g * 1024 ) / 256 ;
b = ( b * 1024 ) / 256 ;
ret = a < < 30 ;
ret | = b < < 20 ;
ret | = g < < 10 ;
ret | = r < < 0 ;
TRACE ( " Returning %08x \n " , ret ) ;
return ret ;
default :
FIXME ( " Add a COLORFILL conversion for format %s \n " , debug_d3dformat ( destfmt ) ) ;
return 0 ;
}
}
2006-10-12 08:22:59 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill ( IWineD3DDevice * iface , IWineD3DSurface * pSurface , CONST WINED3DRECT * pRect , WINED3DCOLOR color ) {
2006-07-22 17:37:51 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSurfaceImpl * surface = ( IWineD3DSurfaceImpl * ) pSurface ;
2007-04-14 22:44:55 +02:00
WINEDDBLTFX BltFx ;
2007-05-03 20:57:23 +02:00
TRACE ( " (%p) Colour fill Surface: %p rect: %p color: 0x%08x \n " , This , pSurface , pRect , color ) ;
2005-08-22 11:13:49 +02:00
2006-05-18 22:59:33 +02:00
if ( surface - > resource . pool ! = WINED3DPOOL_DEFAULT & & surface - > resource . pool ! = WINED3DPOOL_SYSTEMMEM ) {
FIXME ( " call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-07-18 12:32:00 +02:00
}
2005-03-02 13:16:10 +01:00
2007-04-16 21:21:13 +02:00
if ( wined3d_settings . offscreen_rendering_mode = = ORM_FBO ) {
2009-02-25 08:39:01 +01:00
const float c [ 4 ] = { D3DCOLOR_R ( color ) , D3DCOLOR_G ( color ) , D3DCOLOR_B ( color ) , D3DCOLOR_A ( color ) } ;
color_fill_fbo ( iface , pSurface , pRect , c ) ;
2007-04-27 00:17:54 +02:00
return WINED3D_OK ;
2007-04-16 21:21:13 +02:00
} else {
/* Just forward this to the DirectDraw blitting engine */
memset ( & BltFx , 0 , sizeof ( BltFx ) ) ;
BltFx . dwSize = sizeof ( BltFx ) ;
2009-03-13 10:44:18 +01:00
BltFx . u5 . dwFillColor = argb_to_fmt ( color , surface - > resource . format_desc - > format ) ;
2008-11-25 11:57:39 +01:00
return IWineD3DSurface_Blt ( pSurface , ( const RECT * ) pRect , NULL , NULL ,
WINEDDBLT_COLORFILL , & BltFx , WINED3DTEXF_NONE ) ;
2007-04-16 21:21:13 +02:00
}
2004-10-07 06:22:21 +02:00
}
2009-02-25 08:39:01 +01:00
static void WINAPI IWineD3DDeviceImpl_ClearRendertargetView ( IWineD3DDevice * iface ,
IWineD3DRendertargetView * rendertarget_view , const float color [ 4 ] )
{
IWineD3DResource * resource ;
IWineD3DSurface * surface ;
HRESULT hr ;
hr = IWineD3DRendertargetView_GetResource ( rendertarget_view , & resource ) ;
if ( FAILED ( hr ) )
{
ERR ( " Failed to get resource, hr %#x \n " , hr ) ;
return ;
}
if ( IWineD3DResource_GetType ( resource ) ! = WINED3DRTYPE_SURFACE )
{
FIXME ( " Only supported on surface resources \n " ) ;
IWineD3DResource_Release ( resource ) ;
return ;
}
surface = ( IWineD3DSurface * ) resource ;
if ( wined3d_settings . offscreen_rendering_mode = = ORM_FBO )
{
color_fill_fbo ( iface , surface , NULL , color ) ;
}
else
{
WINEDDBLTFX BltFx ;
WINED3DCOLOR c ;
WARN ( " Converting to WINED3DCOLOR, this might give incorrect results \n " ) ;
c = ( ( DWORD ) ( color [ 2 ] * 255.0 ) ) ;
c | = ( ( DWORD ) ( color [ 1 ] * 255.0 ) ) < < 8 ;
c | = ( ( DWORD ) ( color [ 0 ] * 255.0 ) ) < < 16 ;
c | = ( ( DWORD ) ( color [ 3 ] * 255.0 ) ) < < 24 ;
/* Just forward this to the DirectDraw blitting engine */
memset ( & BltFx , 0 , sizeof ( BltFx ) ) ;
BltFx . dwSize = sizeof ( BltFx ) ;
2009-03-13 10:44:18 +01:00
BltFx . u5 . dwFillColor = argb_to_fmt ( c , ( ( IWineD3DSurfaceImpl * ) surface ) - > resource . format_desc - > format ) ;
2009-02-25 08:39:01 +01:00
hr = IWineD3DSurface_Blt ( surface , NULL , NULL , NULL , WINEDDBLT_COLORFILL , & BltFx , WINED3DTEXF_NONE ) ;
if ( FAILED ( hr ) )
{
ERR ( " Blt failed, hr %#x \n " , hr ) ;
}
}
IWineD3DResource_Release ( resource ) ;
}
2008-01-09 20:37:05 +01:00
/* rendertarget and depth stencil functions */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget ( IWineD3DDevice * iface , DWORD RenderTargetIndex , IWineD3DSurface * * ppRenderTarget ) {
2004-10-07 06:22:21 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
2006-12-19 19:25:42 +01:00
if ( RenderTargetIndex > = GL_LIMITS ( buffers ) ) {
ERR ( " (%p) : Only %d render targets are supported. \n " , This , GL_LIMITS ( buffers ) ) ;
return WINED3DERR_INVALIDCALL ;
}
2005-07-13 16:15:54 +02:00
2006-12-19 19:25:42 +01:00
* ppRenderTarget = This - > render_targets [ RenderTargetIndex ] ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : RenderTarget %d Index returning %p \n " , This , RenderTargetIndex , * ppRenderTarget ) ;
2006-11-30 13:33:46 +01:00
/* Note inc ref on returned surface */
if ( * ppRenderTarget ! = NULL )
IWineD3DSurface_AddRef ( * ppRenderTarget ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2005-01-12 20:50:22 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers ( IWineD3DDevice * iface , IWineD3DSurface * Front , IWineD3DSurface * Back ) {
2006-05-15 20:09:07 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSurfaceImpl * FrontImpl = ( IWineD3DSurfaceImpl * ) Front ;
IWineD3DSurfaceImpl * BackImpl = ( IWineD3DSurfaceImpl * ) Back ;
IWineD3DSwapChainImpl * Swapchain ;
HRESULT hr ;
TRACE ( " (%p)->(%p,%p) \n " , This , FrontImpl , BackImpl ) ;
hr = IWineD3DDevice_GetSwapChain ( iface , 0 , ( IWineD3DSwapChain * * ) & Swapchain ) ;
if ( hr ! = WINED3D_OK ) {
ERR ( " Can't get the swapchain \n " ) ;
return hr ;
}
2006-11-30 13:33:11 +01:00
/* Make sure to release the swapchain */
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) Swapchain ) ;
2006-05-15 20:09:07 +02:00
if ( FrontImpl & & ! ( FrontImpl - > resource . usage & WINED3DUSAGE_RENDERTARGET ) ) {
ERR ( " Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
else if ( BackImpl & & ! ( BackImpl - > resource . usage & WINED3DUSAGE_RENDERTARGET ) ) {
ERR ( " Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
if ( Swapchain - > frontBuffer ! = Front ) {
TRACE ( " Changing the front buffer from %p to %p \n " , Swapchain - > frontBuffer , Front ) ;
if ( Swapchain - > frontBuffer )
2009-03-25 10:12:27 +01:00
{
2006-05-15 20:09:07 +02:00
IWineD3DSurface_SetContainer ( Swapchain - > frontBuffer , NULL ) ;
2009-03-25 10:12:27 +01:00
( ( IWineD3DSurfaceImpl * ) Swapchain - > frontBuffer ) - > Flags & = ~ SFLAG_SWAPCHAIN ;
}
2006-05-15 20:09:07 +02:00
Swapchain - > frontBuffer = Front ;
if ( Swapchain - > frontBuffer ) {
IWineD3DSurface_SetContainer ( Swapchain - > frontBuffer , ( IWineD3DBase * ) Swapchain ) ;
2009-03-25 10:12:27 +01:00
( ( IWineD3DSurfaceImpl * ) Swapchain - > frontBuffer ) - > Flags | = SFLAG_SWAPCHAIN ;
2006-05-15 20:09:07 +02:00
}
}
2006-06-15 12:54:19 +02:00
if ( Back & & ! Swapchain - > backBuffer ) {
/* We need memory for the back buffer array - only one back buffer this way */
Swapchain - > backBuffer = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3DSurface * ) ) ;
if ( ! Swapchain - > backBuffer ) {
ERR ( " Out of memory \n " ) ;
return E_OUTOFMEMORY ;
}
}
if ( Swapchain - > backBuffer [ 0 ] ! = Back ) {
2006-05-15 20:09:07 +02:00
TRACE ( " Changing the back buffer from %p to %p \n " , Swapchain - > backBuffer , Back ) ;
2007-03-17 23:00:39 +01:00
/* What to do about the context here in the case of multithreading? Not sure.
* This function is called by IDirect3D7 : : CreateDevice so in theory its initialization code
*/
2006-05-15 20:09:07 +02:00
ENTER_GL ( ) ;
2006-06-15 12:54:19 +02:00
if ( ! Swapchain - > backBuffer [ 0 ] ) {
2006-05-15 20:09:07 +02:00
/* GL was told to draw to the front buffer at creation,
* undo that
*/
glDrawBuffer ( GL_BACK ) ;
checkGLcall ( " glDrawBuffer(GL_BACK) " ) ;
2006-06-15 12:54:19 +02:00
/* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
Swapchain - > presentParms . BackBufferCount = 1 ;
2006-05-15 20:09:07 +02:00
} else if ( ! Back ) {
/* That makes problems - disable for now */
/* glDrawBuffer(GL_FRONT); */
checkGLcall ( " glDrawBuffer(GL_FRONT) " ) ;
2006-06-15 12:54:19 +02:00
/* We have lost our back buffer, set this to 0 to avoid confusing other code */
Swapchain - > presentParms . BackBufferCount = 0 ;
2006-05-15 20:09:07 +02:00
}
LEAVE_GL ( ) ;
2006-06-15 12:54:19 +02:00
if ( Swapchain - > backBuffer [ 0 ] )
2009-03-25 10:12:27 +01:00
{
2006-06-15 12:54:19 +02:00
IWineD3DSurface_SetContainer ( Swapchain - > backBuffer [ 0 ] , NULL ) ;
2009-03-25 10:12:27 +01:00
( ( IWineD3DSurfaceImpl * ) Swapchain - > backBuffer [ 0 ] ) - > Flags & = ~ SFLAG_SWAPCHAIN ;
}
2006-06-15 12:54:19 +02:00
Swapchain - > backBuffer [ 0 ] = Back ;
2006-05-15 20:09:07 +02:00
2006-06-15 12:54:19 +02:00
if ( Swapchain - > backBuffer [ 0 ] ) {
IWineD3DSurface_SetContainer ( Swapchain - > backBuffer [ 0 ] , ( IWineD3DBase * ) Swapchain ) ;
2009-03-25 10:12:27 +01:00
( ( IWineD3DSurfaceImpl * ) Swapchain - > backBuffer [ 0 ] ) - > Flags | = SFLAG_SWAPCHAIN ;
2006-06-15 12:54:19 +02:00
} else {
HeapFree ( GetProcessHeap ( ) , 0 , Swapchain - > backBuffer ) ;
2007-11-25 22:07:24 +01:00
Swapchain - > backBuffer = NULL ;
2006-05-15 20:09:07 +02:00
}
}
return WINED3D_OK ;
2006-04-15 22:40:14 +02:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface ( IWineD3DDevice * iface , IWineD3DSurface * * ppZStencilSurface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-11-10 00:19:19 +01:00
* ppZStencilSurface = This - > stencilBufferTarget ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : zStencilSurface returning %p \n " , This , * ppZStencilSurface ) ;
2005-01-12 20:50:22 +01:00
2006-11-30 13:33:40 +01:00
if ( * ppZStencilSurface ! = NULL ) {
/* Note inc ref on returned surface */
IWineD3DSurface_AddRef ( * ppZStencilSurface ) ;
2007-08-31 20:58:35 +02:00
return WINED3D_OK ;
} else {
return WINED3DERR_NOTFOUND ;
2006-11-30 13:33:40 +01:00
}
2005-03-02 13:16:10 +01:00
}
2007-05-03 20:57:09 +02:00
void stretch_rect_fbo ( IWineD3DDevice * iface , IWineD3DSurface * src_surface , WINED3DRECT * src_rect ,
2008-11-26 16:14:39 +01:00
IWineD3DSurface * dst_surface , WINED3DRECT * dst_rect , const WINED3DTEXTUREFILTERTYPE filter , BOOL flip )
{
2007-04-09 01:54:07 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
GLbitfield mask = GL_COLOR_BUFFER_BIT ; /* TODO: Support blitting depth/stencil surfaces */
2007-04-16 21:20:56 +02:00
IWineD3DSwapChain * src_swapchain , * dst_swapchain ;
2007-04-09 01:54:07 +02:00
GLenum gl_filter ;
2008-08-03 18:33:07 +02:00
POINT offset = { 0 , 0 } ;
2007-04-09 01:54:07 +02:00
2007-04-10 19:13:44 +02:00
TRACE ( " (%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x), flip %u \n " ,
This , src_surface , src_rect , dst_surface , dst_rect , debug_d3dtexturefiltertype ( filter ) , filter , flip ) ;
TRACE ( " src_rect [%u, %u]->[%u, %u] \n " , src_rect - > x1 , src_rect - > y1 , src_rect - > x2 , src_rect - > y2 ) ;
TRACE ( " dst_rect [%u, %u]->[%u, %u] \n " , dst_rect - > x1 , dst_rect - > y1 , dst_rect - > x2 , dst_rect - > y2 ) ;
2007-04-09 01:54:07 +02:00
switch ( filter ) {
case WINED3DTEXF_LINEAR :
gl_filter = GL_LINEAR ;
break ;
default :
FIXME ( " Unsupported filter mode %s (0x%08x) \n " , debug_d3dtexturefiltertype ( filter ) , filter ) ;
case WINED3DTEXF_NONE :
case WINED3DTEXF_POINT :
gl_filter = GL_NEAREST ;
break ;
}
/* Attach src surface to src fbo */
2007-04-16 21:20:56 +02:00
src_swapchain = get_swapchain ( src_surface ) ;
2009-06-18 09:04:02 +02:00
dst_swapchain = get_swapchain ( dst_surface ) ;
if ( src_swapchain ) ActivateContext ( This , src_surface , CTXUSAGE_RESOURCELOAD ) ;
else if ( dst_swapchain ) ActivateContext ( This , dst_surface , CTXUSAGE_RESOURCELOAD ) ;
else ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-04-16 21:20:56 +02:00
if ( src_swapchain ) {
2008-08-03 18:33:07 +02:00
GLenum buffer = surface_get_gl_buffer ( src_surface , src_swapchain ) ;
2007-04-16 21:20:56 +02:00
2007-04-10 19:13:44 +02:00
TRACE ( " Source surface %p is onscreen \n " , src_surface ) ;
2008-01-02 19:53:24 +01:00
/* Make sure the drawable is up to date. In the offscreen case
* attach_surface_fbo ( ) implicitly takes care of this . */
IWineD3DSurface_LoadLocation ( src_surface , SFLAG_INDRAWABLE , NULL ) ;
2007-04-16 21:20:56 +02:00
2008-08-03 18:33:07 +02:00
if ( buffer = = GL_FRONT ) {
RECT windowsize ;
UINT h ;
2008-08-04 21:16:49 +02:00
ClientToScreen ( ( ( IWineD3DSwapChainImpl * ) src_swapchain ) - > win_handle , & offset ) ;
GetClientRect ( ( ( IWineD3DSwapChainImpl * ) src_swapchain ) - > win_handle , & windowsize ) ;
2008-08-03 18:33:07 +02:00
h = windowsize . bottom - windowsize . top ;
src_rect - > x1 - = offset . x ; src_rect - > x2 - = offset . x ;
src_rect - > y1 = offset . y + h - src_rect - > y1 ;
src_rect - > y2 = offset . y + h - src_rect - > y2 ;
} else {
src_rect - > y1 = ( ( IWineD3DSurfaceImpl * ) src_surface ) - > currentDesc . Height - src_rect - > y1 ;
src_rect - > y2 = ( ( IWineD3DSurfaceImpl * ) src_surface ) - > currentDesc . Height - src_rect - > y2 ;
}
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2007-04-09 01:54:07 +02:00
GL_EXTCALL ( glBindFramebufferEXT ( GL_READ_FRAMEBUFFER_EXT , 0 ) ) ;
2007-04-16 21:20:56 +02:00
glReadBuffer ( buffer ) ;
checkGLcall ( " glReadBuffer() " ) ;
2007-04-09 01:54:07 +02:00
} else {
2007-04-10 19:13:44 +02:00
TRACE ( " Source surface %p is offscreen \n " , src_surface ) ;
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2008-09-18 14:57:53 +02:00
context_bind_fbo ( iface , GL_READ_FRAMEBUFFER_EXT , & This - > activeContext - > src_fbo ) ;
context_attach_surface_fbo ( This , GL_READ_FRAMEBUFFER_EXT , 0 , src_surface ) ;
2007-04-16 21:20:56 +02:00
glReadBuffer ( GL_COLOR_ATTACHMENT0_EXT ) ;
checkGLcall ( " glReadBuffer() " ) ;
2009-06-08 10:35:05 +02:00
context_attach_depth_stencil_fbo ( This , GL_READ_FRAMEBUFFER_EXT , NULL , FALSE ) ;
2007-04-09 01:54:07 +02:00
}
2007-08-06 16:27:08 +02:00
LEAVE_GL ( ) ;
2007-04-09 01:54:07 +02:00
/* Attach dst surface to dst fbo */
2007-04-16 21:20:56 +02:00
if ( dst_swapchain ) {
2008-08-03 18:33:07 +02:00
GLenum buffer = surface_get_gl_buffer ( dst_surface , dst_swapchain ) ;
2007-04-16 21:20:56 +02:00
2007-04-10 19:13:44 +02:00
TRACE ( " Destination surface %p is onscreen \n " , dst_surface ) ;
2008-01-02 19:53:24 +01:00
/* Make sure the drawable is up to date. In the offscreen case
* attach_surface_fbo ( ) implicitly takes care of this . */
IWineD3DSurface_LoadLocation ( dst_surface , SFLAG_INDRAWABLE , NULL ) ;
2007-04-16 21:20:56 +02:00
2008-08-03 18:33:07 +02:00
if ( buffer = = GL_FRONT ) {
RECT windowsize ;
UINT h ;
2008-08-04 21:16:49 +02:00
ClientToScreen ( ( ( IWineD3DSwapChainImpl * ) dst_swapchain ) - > win_handle , & offset ) ;
GetClientRect ( ( ( IWineD3DSwapChainImpl * ) dst_swapchain ) - > win_handle , & windowsize ) ;
2008-08-03 18:33:07 +02:00
h = windowsize . bottom - windowsize . top ;
dst_rect - > x1 - = offset . x ; dst_rect - > x2 - = offset . x ;
dst_rect - > y1 = offset . y + h - dst_rect - > y1 ;
dst_rect - > y2 = offset . y + h - dst_rect - > y2 ;
} else {
/* Screen coords = window coords, surface height = window height */
dst_rect - > y1 = ( ( IWineD3DSurfaceImpl * ) dst_surface ) - > currentDesc . Height - dst_rect - > y1 ;
dst_rect - > y2 = ( ( IWineD3DSurfaceImpl * ) dst_surface ) - > currentDesc . Height - dst_rect - > y2 ;
}
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2007-04-09 01:54:07 +02:00
GL_EXTCALL ( glBindFramebufferEXT ( GL_DRAW_FRAMEBUFFER_EXT , 0 ) ) ;
2007-04-16 21:20:56 +02:00
glDrawBuffer ( buffer ) ;
checkGLcall ( " glDrawBuffer() " ) ;
2007-04-09 01:54:07 +02:00
} else {
2007-04-10 19:13:44 +02:00
TRACE ( " Destination surface %p is offscreen \n " , dst_surface ) ;
2007-06-09 14:59:15 +02:00
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2008-09-18 14:57:53 +02:00
context_bind_fbo ( iface , GL_DRAW_FRAMEBUFFER_EXT , & This - > activeContext - > dst_fbo ) ;
context_attach_surface_fbo ( This , GL_DRAW_FRAMEBUFFER_EXT , 0 , dst_surface ) ;
2007-04-16 21:20:56 +02:00
glDrawBuffer ( GL_COLOR_ATTACHMENT0_EXT ) ;
checkGLcall ( " glDrawBuffer() " ) ;
2009-06-08 10:35:05 +02:00
context_attach_depth_stencil_fbo ( This , GL_DRAW_FRAMEBUFFER_EXT , NULL , FALSE ) ;
2007-04-09 01:54:07 +02:00
}
2007-06-09 14:59:15 +02:00
glDisable ( GL_SCISSOR_TEST ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_SCISSORTESTENABLE ) ) ;
2007-04-09 01:54:07 +02:00
if ( flip ) {
GL_EXTCALL ( glBlitFramebufferEXT ( src_rect - > x1 , src_rect - > y1 , src_rect - > x2 , src_rect - > y2 ,
dst_rect - > x1 , dst_rect - > y2 , dst_rect - > x2 , dst_rect - > y1 , mask , gl_filter ) ) ;
2007-06-05 04:42:04 +02:00
checkGLcall ( " glBlitFramebuffer() " ) ;
2007-04-09 01:54:07 +02:00
} else {
GL_EXTCALL ( glBlitFramebufferEXT ( src_rect - > x1 , src_rect - > y1 , src_rect - > x2 , src_rect - > y2 ,
dst_rect - > x1 , dst_rect - > y1 , dst_rect - > x2 , dst_rect - > y2 , mask , gl_filter ) ) ;
2007-06-05 04:42:04 +02:00
checkGLcall ( " glBlitFramebuffer() " ) ;
2007-04-09 01:54:07 +02:00
}
2008-01-02 19:53:24 +01:00
IWineD3DSurface_ModifyLocation ( dst_surface , SFLAG_INDRAWABLE , TRUE ) ;
2008-09-18 14:57:53 +02:00
if ( This - > activeContext - > current_fbo ) {
context_bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > activeContext - > current_fbo - > id ) ;
2007-04-09 01:54:07 +02:00
} else {
GL_EXTCALL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , 0 ) ) ;
checkGLcall ( " glBindFramebuffer() " ) ;
2007-04-16 21:20:56 +02:00
}
/* If we switched from GL_BACK to GL_FRONT above, we need to switch back here */
if ( dst_swapchain & & dst_surface = = ( ( IWineD3DSwapChainImpl * ) dst_swapchain ) - > frontBuffer
& & ( ( IWineD3DSwapChainImpl * ) dst_swapchain ) - > backBuffer ) {
glDrawBuffer ( GL_BACK ) ;
checkGLcall ( " glDrawBuffer() " ) ;
2007-04-09 01:54:07 +02:00
}
2007-06-09 14:59:15 +02:00
LEAVE_GL ( ) ;
2007-04-09 01:54:07 +02:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget ( IWineD3DDevice * iface , DWORD RenderTargetIndex , IWineD3DSurface * pRenderTarget ) {
2005-07-07 22:35:05 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
WINED3DVIEWPORT viewport ;
2005-03-02 13:16:10 +01:00
2006-12-19 19:25:42 +01:00
TRACE ( " (%p) : Setting rendertarget %d to %p \n " , This , RenderTargetIndex , pRenderTarget ) ;
if ( RenderTargetIndex > = GL_LIMITS ( buffers ) ) {
2007-11-20 21:16:25 +01:00
WARN ( " (%p) : Unsupported target %u set, returning WINED3DERR_INVALIDCALL(only %u supported) \n " ,
This , RenderTargetIndex , GL_LIMITS ( buffers ) ) ;
2006-12-19 19:25:42 +01:00
return WINED3DERR_INVALIDCALL ;
2005-07-07 22:35:05 +02:00
}
/* MSDN says that null disables the render target
2005-07-11 12:59:41 +02:00
but a device must always be associated with a render target
2005-07-07 22:35:05 +02:00
nope MSDN says that we return invalid call to a null rendertarget with an index of 0
*/
if ( RenderTargetIndex = = 0 & & pRenderTarget = = NULL ) {
FIXME ( " Trying to set render target 0 to NULL \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-07-07 22:35:05 +02:00
}
2007-12-02 14:14:30 +01:00
if ( pRenderTarget & & ! ( ( ( IWineD3DSurfaceImpl * ) pRenderTarget ) - > resource . usage & WINED3DUSAGE_RENDERTARGET ) ) {
2006-03-06 23:08:42 +01:00
FIXME ( " (%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET \n " , This , pRenderTarget ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-07-07 22:35:05 +02:00
}
2007-02-12 19:21:10 +01:00
2005-07-07 22:35:05 +02:00
/* If we are trying to set what we already have, don't bother */
2006-12-19 19:25:42 +01:00
if ( pRenderTarget = = This - > render_targets [ RenderTargetIndex ] ) {
2005-07-07 22:35:05 +02:00
TRACE ( " Trying to do a NOP SetRenderTarget operation \n " ) ;
2007-02-12 19:21:10 +01:00
return WINED3D_OK ;
2005-07-07 22:35:05 +02:00
}
2007-02-12 19:21:10 +01:00
if ( pRenderTarget ) IWineD3DSurface_AddRef ( pRenderTarget ) ;
if ( This - > render_targets [ RenderTargetIndex ] ) IWineD3DSurface_Release ( This - > render_targets [ RenderTargetIndex ] ) ;
This - > render_targets [ RenderTargetIndex ] = pRenderTarget ;
2005-07-07 22:35:05 +02:00
2007-02-12 19:21:10 +01:00
/* Render target 0 is special */
if ( RenderTargetIndex = = 0 ) {
2005-07-07 22:35:05 +02:00
/* Finally, reset the viewport as the MSDN states. */
2006-12-19 19:25:22 +01:00
viewport . Height = ( ( IWineD3DSurfaceImpl * ) This - > render_targets [ 0 ] ) - > currentDesc . Height ;
viewport . Width = ( ( IWineD3DSurfaceImpl * ) This - > render_targets [ 0 ] ) - > currentDesc . Width ;
2005-07-07 22:35:05 +02:00
viewport . X = 0 ;
viewport . Y = 0 ;
viewport . MaxZ = 1.0f ;
viewport . MinZ = 0.0f ;
IWineD3DDeviceImpl_SetViewport ( iface , & viewport ) ;
2007-03-06 14:56:58 +01:00
/* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
* SetViewport may catch NOP viewport changes , which would occur when switching between equally sized targets
*/
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VIEWPORT ) ;
2005-07-07 22:35:05 +02:00
}
2007-02-12 19:21:10 +01:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface ( IWineD3DDevice * iface , IWineD3DSurface * pNewZStencil ) {
2005-07-07 22:35:05 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-04-07 12:51:12 +02:00
HRESULT hr = WINED3D_OK ;
2005-07-07 22:35:05 +02:00
IWineD3DSurface * tmp ;
2007-11-10 00:19:19 +01:00
TRACE ( " (%p) Swapping z-buffer. Old = %p, new = %p \n " , This , This - > stencilBufferTarget , pNewZStencil ) ;
2005-07-07 22:35:05 +02:00
2005-07-13 16:15:54 +02:00
if ( pNewZStencil = = This - > stencilBufferTarget ) {
2005-07-07 22:35:05 +02:00
TRACE ( " Trying to do a NOP SetRenderTarget operation \n " ) ;
2005-07-19 13:39:24 +02:00
} else {
2008-01-09 20:37:05 +01:00
/** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incur an extra memory overhead
2005-07-11 12:59:41 +02:00
* depending on the renter target implementation being used .
2005-07-07 22:35:05 +02:00
* A shared context implementation will share all buffers between all rendertargets ( including swapchains ) ,
2005-07-11 12:59:41 +02:00
* implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
2008-01-09 20:37:05 +01:00
* stencil buffer and incur an extra memory overhead
2005-07-07 22:35:05 +02:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-07-02 23:00:41 +02:00
if ( This - > stencilBufferTarget ) {
2008-09-22 14:52:52 +02:00
if ( ( ( IWineD3DSwapChainImpl * ) This - > swapchains [ 0 ] ) - > presentParms . Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
| | ( ( IWineD3DSurfaceImpl * ) This - > stencilBufferTarget ) - > Flags & SFLAG_DISCARD ) {
surface_modify_ds_location ( This - > stencilBufferTarget , SFLAG_DS_DISCARDED ) ;
} else {
ActivateContext ( This , This - > render_targets [ 0 ] , CTXUSAGE_RESOURCELOAD ) ;
surface_load_ds_location ( This - > stencilBufferTarget , SFLAG_DS_OFFSCREEN ) ;
surface_modify_ds_location ( This - > stencilBufferTarget , SFLAG_DS_OFFSCREEN ) ;
}
2008-07-02 23:00:41 +02:00
}
2005-07-07 22:35:05 +02:00
tmp = This - > stencilBufferTarget ;
This - > stencilBufferTarget = pNewZStencil ;
/* should we be calling the parent or the wined3d surface? */
if ( NULL ! = This - > stencilBufferTarget ) IWineD3DSurface_AddRef ( This - > stencilBufferTarget ) ;
if ( NULL ! = tmp ) IWineD3DSurface_Release ( tmp ) ;
2006-04-07 12:51:12 +02:00
hr = WINED3D_OK ;
2007-03-06 13:35:56 +01:00
2007-03-06 13:54:05 +01:00
if ( ( ! tmp & & pNewZStencil ) | | ( ! pNewZStencil & & tmp ) ) {
/* Swapping NULL / non NULL depth stencil affects the depth and tests */
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_ZENABLE ) ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_STENCILENABLE ) ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_STENCILWRITEMASK ) ) ;
}
2005-07-07 22:35:05 +02:00
}
return hr ;
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties ( IWineD3DDevice * iface , UINT XHotSpot ,
2005-03-02 13:16:10 +01:00
UINT YHotSpot , IWineD3DSurface * pCursorBitmap ) {
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-03-23 14:15:18 +01:00
/* TODO: the use of Impl is deprecated. */
2005-03-02 13:16:10 +01:00
IWineD3DSurfaceImpl * pSur = ( IWineD3DSurfaceImpl * ) pCursorBitmap ;
2007-05-15 00:37:53 +02:00
WINED3DLOCKED_RECT lockedRect ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : Spot Pos(%u,%u) \n " , This , XHotSpot , YHotSpot ) ;
2006-07-23 00:03:33 +02:00
/* some basic validation checks */
2006-07-27 17:39:03 +02:00
if ( This - > cursorTexture ) {
2007-03-17 23:00:39 +01:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2006-07-27 17:39:03 +02:00
glDeleteTextures ( 1 , & This - > cursorTexture ) ;
LEAVE_GL ( ) ;
This - > cursorTexture = 0 ;
}
2007-05-15 00:37:53 +02:00
if ( ( pSur - > currentDesc . Width = = 32 ) & & ( pSur - > currentDesc . Height = = 32 ) )
This - > haveHardwareCursor = TRUE ;
else
This - > haveHardwareCursor = FALSE ;
2006-07-23 00:03:33 +02:00
if ( pCursorBitmap ) {
2007-03-13 03:44:22 +01:00
WINED3DLOCKED_RECT rect ;
2006-07-23 00:03:33 +02:00
/* MSDN: Cursor must be A8R8G8B8 */
2009-03-13 10:44:18 +01:00
if ( WINED3DFMT_A8R8G8B8 ! = pSur - > resource . format_desc - > format )
{
2006-07-23 00:03:33 +02:00
ERR ( " (%p) : surface(%p) has an invalid format \n " , This , pCursorBitmap ) ;
return WINED3DERR_INVALIDCALL ;
}
/* MSDN: Cursor must be smaller than the display mode */
if ( pSur - > currentDesc . Width > This - > ddraw_width | |
pSur - > currentDesc . Height > This - > ddraw_height ) {
2006-10-01 05:20:10 +02:00
ERR ( " (%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d \n " , This , pSur , pSur - > currentDesc . Width , pSur - > currentDesc . Height , This - > ddraw_width , This - > ddraw_height ) ;
2006-07-23 00:03:33 +02:00
return WINED3DERR_INVALIDCALL ;
}
2007-05-15 00:37:53 +02:00
if ( ! This - > haveHardwareCursor ) {
/* TODO: MSDN: Cursor sizes must be a power of 2 */
2007-03-13 03:44:22 +01:00
2007-05-15 00:37:53 +02:00
/* Do not store the surface's pointer because the application may
* release it after setting the cursor image . Windows doesn ' t
* addref the set surface , so we can ' t do this either without
* creating circular refcount dependencies . Copy out the gl texture
* instead .
*/
This - > cursorWidth = pSur - > currentDesc . Width ;
This - > cursorHeight = pSur - > currentDesc . Height ;
if ( SUCCEEDED ( IWineD3DSurface_LockRect ( pCursorBitmap , & rect , NULL , WINED3DLOCK_READONLY ) ) )
{
2009-03-13 10:44:18 +01:00
const struct GlPixelFormatDesc * glDesc = getFormatDescEntry ( WINED3DFMT_A8R8G8B8 , & GLINFO_LOCATION ) ;
2009-02-03 09:36:07 +01:00
char * mem , * bits = rect . pBits ;
2007-07-23 11:13:37 +02:00
GLint intfmt = glDesc - > glInternal ;
GLint format = glDesc - > glFormat ;
GLint type = glDesc - > glType ;
2007-05-15 00:37:53 +02:00
INT height = This - > cursorHeight ;
INT width = This - > cursorWidth ;
2009-03-13 10:44:18 +01:00
INT bpp = glDesc - > byte_count ;
2008-07-15 23:54:44 +02:00
INT i , sampler ;
2007-05-15 00:37:53 +02:00
/* Reformat the texture memory (pitch and width can be
* different ) */
mem = HeapAlloc ( GetProcessHeap ( ) , 0 , width * height * bpp ) ;
for ( i = 0 ; i < height ; i + + )
memcpy ( & mem [ width * bpp * i ] , & bits [ rect . Pitch * i ] , width * bpp ) ;
IWineD3DSurface_UnlockRect ( pCursorBitmap ) ;
2009-06-25 10:24:58 +02:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-05-15 00:37:53 +02:00
ENTER_GL ( ) ;
if ( GL_SUPPORT ( APPLE_CLIENT_STORAGE ) ) {
glPixelStorei ( GL_UNPACK_CLIENT_STORAGE_APPLE , GL_FALSE ) ;
checkGLcall ( " glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE) " ) ;
}
2007-04-19 22:52:11 +02:00
2007-05-15 00:37:53 +02:00
/* Make sure that a proper texture unit is selected */
2008-12-16 13:18:49 +01:00
GL_EXTCALL ( glActiveTextureARB ( GL_TEXTURE0_ARB ) ) ;
checkGLcall ( " glActiveTextureARB " ) ;
2008-07-15 23:54:44 +02:00
sampler = This - > rev_tex_unit_map [ 0 ] ;
if ( sampler ! = - 1 ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( sampler ) ) ;
}
2007-05-15 00:37:53 +02:00
/* Create a new cursor texture */
glGenTextures ( 1 , & This - > cursorTexture ) ;
checkGLcall ( " glGenTextures " ) ;
glBindTexture ( GL_TEXTURE_2D , This - > cursorTexture ) ;
checkGLcall ( " glBindTexture " ) ;
/* Copy the bitmap memory into the cursor texture */
glTexImage2D ( GL_TEXTURE_2D , 0 , intfmt , width , height , 0 , format , type , mem ) ;
HeapFree ( GetProcessHeap ( ) , 0 , mem ) ;
checkGLcall ( " glTexImage2D " ) ;
if ( GL_SUPPORT ( APPLE_CLIENT_STORAGE ) ) {
glPixelStorei ( GL_UNPACK_CLIENT_STORAGE_APPLE , GL_TRUE ) ;
checkGLcall ( " glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE) " ) ;
}
2007-04-19 22:52:11 +02:00
2007-05-15 00:37:53 +02:00
LEAVE_GL ( ) ;
2007-03-13 03:44:22 +01:00
}
2007-05-15 00:37:53 +02:00
else
{
FIXME ( " A cursor texture was not returned. \n " ) ;
This - > cursorTexture = 0 ;
2007-04-19 22:52:11 +02:00
}
2007-03-13 03:44:22 +01:00
}
else
{
2007-05-15 00:37:53 +02:00
/* Draw a hardware cursor */
ICONINFO cursorInfo ;
HCURSOR cursor ;
/* Create and clear maskBits because it is not needed for
* 32 - bit cursors . 32 x32 bits split into 32 - bit chunks = = 32
* chunks . */
DWORD * maskBits = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY ,
( pSur - > currentDesc . Width * pSur - > currentDesc . Height / 8 ) ) ;
IWineD3DSurface_LockRect ( pCursorBitmap , & lockedRect , NULL ,
WINED3DLOCK_NO_DIRTY_UPDATE |
WINED3DLOCK_READONLY
) ;
TRACE ( " width: %i height: %i \n " , pSur - > currentDesc . Width ,
pSur - > currentDesc . Height ) ;
cursorInfo . fIcon = FALSE ;
cursorInfo . xHotspot = XHotSpot ;
cursorInfo . yHotspot = YHotSpot ;
cursorInfo . hbmMask = CreateBitmap ( pSur - > currentDesc . Width ,
pSur - > currentDesc . Height , 1 ,
1 , & maskBits ) ;
cursorInfo . hbmColor = CreateBitmap ( pSur - > currentDesc . Width ,
pSur - > currentDesc . Height , 1 ,
32 , lockedRect . pBits ) ;
IWineD3DSurface_UnlockRect ( pCursorBitmap ) ;
/* Create our cursor and clean up. */
cursor = CreateIconIndirect ( & cursorInfo ) ;
SetCursor ( cursor ) ;
if ( cursorInfo . hbmMask ) DeleteObject ( cursorInfo . hbmMask ) ;
if ( cursorInfo . hbmColor ) DeleteObject ( cursorInfo . hbmColor ) ;
if ( This - > hardwareCursor ) DestroyCursor ( This - > hardwareCursor ) ;
This - > hardwareCursor = cursor ;
HeapFree ( GetProcessHeap ( ) , 0 , maskBits ) ;
2007-03-13 03:44:22 +01:00
}
2005-03-02 13:16:10 +01:00
}
2005-07-13 16:15:54 +02:00
2005-03-02 13:16:10 +01:00
This - > xHotSpot = XHotSpot ;
This - > yHotSpot = YHotSpot ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static void WINAPI IWineD3DDeviceImpl_SetCursorPosition ( IWineD3DDevice * iface , int XScreenSpace , int YScreenSpace , DWORD Flags ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p) : SetPos to (%u,%u) \n " , This , XScreenSpace , YScreenSpace ) ;
2005-07-13 16:15:54 +02:00
2005-03-02 13:16:10 +01:00
This - > xScreenSpace = XScreenSpace ;
This - > yScreenSpace = YScreenSpace ;
2005-07-13 16:15:54 +02:00
2005-03-02 13:16:10 +01:00
return ;
}
2006-06-10 13:15:32 +02:00
static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor ( IWineD3DDevice * iface , BOOL bShow ) {
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-08-09 22:23:31 +02:00
BOOL oldVisible = This - > bCursorVisible ;
2007-03-02 09:25:02 +01:00
POINT pt ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : visible(%d) \n " , This , bShow ) ;
2005-07-13 16:15:54 +02:00
2007-03-02 09:25:02 +01:00
/*
* When ShowCursor is first called it should make the cursor appear at the OS ' s last
* known cursor position . Because of this , some applications just repetitively call
* ShowCursor in order to update the cursor ' s position . This behavior is undocumented .
*/
GetCursorPos ( & pt ) ;
This - > xScreenSpace = pt . x ;
This - > yScreenSpace = pt . y ;
2005-07-13 16:15:54 +02:00
2007-05-15 00:37:53 +02:00
if ( This - > haveHardwareCursor ) {
This - > bCursorVisible = bShow ;
if ( bShow )
SetCursor ( This - > hardwareCursor ) ;
else
SetCursor ( NULL ) ;
}
else
{
if ( This - > cursorTexture )
This - > bCursorVisible = bShow ;
}
2006-08-09 22:23:31 +02:00
return oldVisible ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-11-16 20:28:45 +01:00
IWineD3DResourceImpl * resource ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : state (%u) \n " , This , This - > state ) ;
2007-11-16 20:28:45 +01:00
2008-04-22 08:18:14 +02:00
/* TODO: Implement wrapping of the WndProc so that mimimize and maximize can be monitored and the states adjusted. */
2005-09-21 12:55:03 +02:00
switch ( This - > state ) {
2006-04-07 12:51:12 +02:00
case WINED3D_OK :
return WINED3D_OK ;
case WINED3DERR_DEVICELOST :
2005-09-21 12:55:03 +02:00
{
2007-11-16 20:28:45 +01:00
LIST_FOR_EACH_ENTRY ( resource , & This - > resources , IWineD3DResourceImpl , resource . resource_list_entry ) {
if ( resource - > resource . pool = = WINED3DPOOL_DEFAULT )
return WINED3DERR_DEVICENOTRESET ;
2005-09-21 12:55:03 +02:00
}
2006-04-07 12:51:12 +02:00
return WINED3DERR_DEVICELOST ;
2005-09-21 12:55:03 +02:00
}
2006-04-07 12:51:12 +02:00
case WINED3DERR_DRIVERINTERNALERROR :
return WINED3DERR_DRIVERINTERNALERROR ;
2005-09-21 12:55:03 +02:00
}
/* Unknown state */
2006-04-07 12:51:12 +02:00
return WINED3DERR_DRIVERINTERNALERROR ;
2005-03-02 13:16:10 +01:00
}
2009-06-10 08:06:06 +02:00
static HRESULT WINAPI evict_managed_resource ( IWineD3DResource * resource , void * data ) {
TRACE ( " checking resource %p for eviction \n " , resource ) ;
if ( ( ( IWineD3DResourceImpl * ) resource ) - > resource . pool = = WINED3DPOOL_MANAGED ) {
TRACE ( " Evicting %p \n " , resource ) ;
IWineD3DResource_UnLoad ( resource ) ;
}
IWineD3DResource_Release ( resource ) ;
return S_OK ;
}
2005-03-02 13:16:10 +01:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources ( IWineD3DDevice * iface ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2009-06-10 08:06:06 +02:00
TRACE ( " (%p) \n " , This ) ;
IWineD3DDevice_EnumResources ( iface , evict_managed_resource , NULL ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2008-11-26 16:14:39 +01:00
static void updateSurfaceDesc ( IWineD3DSurfaceImpl * surface , const WINED3DPRESENT_PARAMETERS * pPresentationParameters )
{
2007-02-13 20:21:48 +01:00
IWineD3DDeviceImpl * This = surface - > resource . wineD3DDevice ; /* for GL_SUPPORT */
2006-12-08 16:13:15 +01:00
/* Reallocate proper memory for the front and back buffer and adjust their sizes */
if ( surface - > Flags & SFLAG_DIBSECTION ) {
/* Release the DC */
SelectObject ( surface - > hDC , surface - > dib . holdbitmap ) ;
DeleteDC ( surface - > hDC ) ;
/* Release the DIB section */
DeleteObject ( surface - > dib . DIBsection ) ;
surface - > dib . bitmap_data = NULL ;
surface - > resource . allocatedMemory = NULL ;
surface - > Flags & = ~ SFLAG_DIBSECTION ;
}
2007-02-15 22:36:50 +01:00
surface - > currentDesc . Width = pPresentationParameters - > BackBufferWidth ;
surface - > currentDesc . Height = pPresentationParameters - > BackBufferHeight ;
2008-07-09 01:59:10 +02:00
if ( GL_SUPPORT ( ARB_TEXTURE_NON_POWER_OF_TWO ) | | GL_SUPPORT ( ARB_TEXTURE_RECTANGLE ) | |
GL_SUPPORT ( WINE_NORMALIZED_TEXRECT ) ) {
2007-02-15 22:36:50 +01:00
surface - > pow2Width = pPresentationParameters - > BackBufferWidth ;
surface - > pow2Height = pPresentationParameters - > BackBufferHeight ;
2006-12-08 16:13:15 +01:00
} else {
surface - > pow2Width = surface - > pow2Height = 1 ;
2007-02-15 22:36:50 +01:00
while ( surface - > pow2Width < pPresentationParameters - > BackBufferWidth ) surface - > pow2Width < < = 1 ;
while ( surface - > pow2Height < pPresentationParameters - > BackBufferHeight ) surface - > pow2Height < < = 1 ;
2006-12-08 16:13:15 +01:00
}
2008-01-27 21:26:07 +01:00
surface - > glRect . left = 0 ;
surface - > glRect . top = 0 ;
surface - > glRect . right = surface - > pow2Width ;
surface - > glRect . bottom = surface - > pow2Height ;
2006-12-08 16:13:15 +01:00
if ( surface - > glDescription . textureName ) {
2007-03-17 23:00:39 +01:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2006-12-08 16:13:15 +01:00
glDeleteTextures ( 1 , & surface - > glDescription . textureName ) ;
LEAVE_GL ( ) ;
surface - > glDescription . textureName = 0 ;
2007-03-31 23:02:37 +02:00
surface - > Flags & = ~ SFLAG_CLIENT ;
2006-12-08 16:13:15 +01:00
}
2007-02-15 22:36:50 +01:00
if ( surface - > pow2Width ! = pPresentationParameters - > BackBufferWidth | |
surface - > pow2Height ! = pPresentationParameters - > BackBufferHeight ) {
2006-12-08 16:13:15 +01:00
surface - > Flags | = SFLAG_NONPOW2 ;
} else {
surface - > Flags & = ~ SFLAG_NONPOW2 ;
}
2008-03-23 16:14:05 +01:00
HeapFree ( GetProcessHeap ( ) , 0 , surface - > resource . heapMemory ) ;
surface - > resource . allocatedMemory = NULL ;
surface - > resource . heapMemory = NULL ;
2006-12-08 16:13:15 +01:00
surface - > resource . size = IWineD3DSurface_GetPitch ( ( IWineD3DSurface * ) surface ) * surface - > pow2Width ;
2008-06-02 21:12:54 +02:00
/* INDRAWABLE is a sane place for implicit targets after the reset, INSYSMEM is more appropriate for depth stencils. */
if ( surface - > resource . usage & WINED3DUSAGE_DEPTHSTENCIL ) {
IWineD3DSurface_ModifyLocation ( ( IWineD3DSurface * ) surface , SFLAG_INSYSMEM , TRUE ) ;
} else {
IWineD3DSurface_ModifyLocation ( ( IWineD3DSurface * ) surface , SFLAG_INDRAWABLE , TRUE ) ;
}
2006-12-08 16:13:15 +01:00
}
2008-01-08 22:34:43 +01:00
static HRESULT WINAPI reset_unload_resources ( IWineD3DResource * resource , void * data ) {
TRACE ( " Unloading resource %p \n " , resource ) ;
IWineD3DResource_UnLoad ( resource ) ;
IWineD3DResource_Release ( resource ) ;
return S_OK ;
}
2008-11-26 16:14:39 +01:00
static BOOL is_display_mode_supported ( IWineD3DDeviceImpl * This , const WINED3DPRESENT_PARAMETERS * pp )
{
2008-02-06 20:16:13 +01:00
UINT i , count ;
WINED3DDISPLAYMODE m ;
HRESULT hr ;
/* All Windowed modes are supported, as is leaving the current mode */
if ( pp - > Windowed ) return TRUE ;
if ( ! pp - > BackBufferWidth ) return TRUE ;
if ( ! pp - > BackBufferHeight ) return TRUE ;
count = IWineD3D_GetAdapterModeCount ( This - > wineD3D , This - > adapter - > num , WINED3DFMT_UNKNOWN ) ;
for ( i = 0 ; i < count ; i + + ) {
memset ( & m , 0 , sizeof ( m ) ) ;
hr = IWineD3D_EnumAdapterModes ( This - > wineD3D , This - > adapter - > num , WINED3DFMT_UNKNOWN , i , & m ) ;
if ( FAILED ( hr ) ) {
ERR ( " EnumAdapterModes failed \n " ) ;
}
if ( m . Width = = pp - > BackBufferWidth & & m . Height = = pp - > BackBufferHeight ) {
/* Mode found, it is supported */
return TRUE ;
}
}
/* Mode not found -> not supported */
return FALSE ;
}
2008-07-29 19:09:34 +02:00
void delete_opengl_contexts ( IWineD3DDevice * iface , IWineD3DSwapChain * swapchain_iface ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSwapChainImpl * swapchain = ( IWineD3DSwapChainImpl * ) swapchain_iface ;
UINT i ;
IWineD3DBaseShaderImpl * shader ;
2009-06-25 10:24:54 +02:00
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2008-07-29 19:09:34 +02:00
IWineD3DDevice_EnumResources ( iface , reset_unload_resources , NULL ) ;
LIST_FOR_EACH_ENTRY ( shader , & This - > shaders , IWineD3DBaseShaderImpl , baseShader . shader_list_entry ) {
This - > shader_backend - > shader_destroy ( ( IWineD3DBaseShader * ) shader ) ;
}
ENTER_GL ( ) ;
if ( This - > depth_blt_texture ) {
glDeleteTextures ( 1 , & This - > depth_blt_texture ) ;
This - > depth_blt_texture = 0 ;
}
if ( This - > depth_blt_rb ) {
GL_EXTCALL ( glDeleteRenderbuffersEXT ( 1 , & This - > depth_blt_rb ) ) ;
This - > depth_blt_rb = 0 ;
This - > depth_blt_rb_w = 0 ;
This - > depth_blt_rb_h = 0 ;
}
2008-10-19 01:21:06 +02:00
LEAVE_GL ( ) ;
2008-08-01 20:21:10 +02:00
This - > blitter - > free_private ( iface ) ;
2008-07-29 19:09:34 +02:00
This - > frag_pipe - > free_private ( iface ) ;
This - > shader_backend - > shader_free_private ( iface ) ;
2008-10-19 01:21:06 +02:00
ENTER_GL ( ) ;
2008-07-29 19:09:34 +02:00
for ( i = 0 ; i < GL_LIMITS ( textures ) ; i + + ) {
/* Textures are recreated below */
glDeleteTextures ( 1 , & This - > dummyTextureName [ i ] ) ;
checkGLcall ( " glDeleteTextures(1, &This->dummyTextureName[i]) " ) ;
This - > dummyTextureName [ i ] = 0 ;
}
LEAVE_GL ( ) ;
while ( This - > numContexts ) {
DestroyContext ( This , This - > contexts [ 0 ] ) ;
}
This - > activeContext = NULL ;
HeapFree ( GetProcessHeap ( ) , 0 , swapchain - > context ) ;
swapchain - > context = NULL ;
swapchain - > num_contexts = 0 ;
}
HRESULT create_primary_opengl_context ( IWineD3DDevice * iface , IWineD3DSwapChain * swapchain_iface ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSwapChainImpl * swapchain = ( IWineD3DSwapChainImpl * ) swapchain_iface ;
HRESULT hr ;
IWineD3DSurfaceImpl * target ;
/* Recreate the primary swapchain's context */
swapchain - > context = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( * swapchain - > context ) ) ;
if ( swapchain - > backBuffer ) {
target = ( IWineD3DSurfaceImpl * ) swapchain - > backBuffer [ 0 ] ;
} else {
target = ( IWineD3DSurfaceImpl * ) swapchain - > frontBuffer ;
}
swapchain - > context [ 0 ] = CreateContext ( This , target , swapchain - > win_handle , FALSE ,
& swapchain - > presentParms ) ;
swapchain - > num_contexts = 1 ;
This - > activeContext = swapchain - > context [ 0 ] ;
create_dummy_textures ( This ) ;
hr = This - > shader_backend - > shader_alloc_private ( iface ) ;
if ( FAILED ( hr ) ) {
ERR ( " Failed to recreate shader private data \n " ) ;
2008-08-01 20:21:10 +02:00
goto err_out ;
2008-07-29 19:09:34 +02:00
}
hr = This - > frag_pipe - > alloc_private ( iface ) ;
if ( FAILED ( hr ) ) {
TRACE ( " Fragment pipeline private data couldn't be allocated \n " ) ;
2008-08-01 20:21:10 +02:00
goto err_out ;
}
hr = This - > blitter - > alloc_private ( iface ) ;
if ( FAILED ( hr ) ) {
TRACE ( " Blitter private data couldn't be allocated \n " ) ;
goto err_out ;
2008-07-29 19:09:34 +02:00
}
return WINED3D_OK ;
2008-08-01 20:21:10 +02:00
err_out :
This - > blitter - > free_private ( iface ) ;
This - > frag_pipe - > free_private ( iface ) ;
This - > shader_backend - > shader_free_private ( iface ) ;
return hr ;
2008-07-29 19:09:34 +02:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_Reset ( IWineD3DDevice * iface , WINED3DPRESENT_PARAMETERS * pPresentationParameters ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-12-08 16:13:15 +01:00
IWineD3DSwapChainImpl * swapchain ;
HRESULT hr ;
BOOL DisplayModeChanged = FALSE ;
WINED3DDISPLAYMODE mode ;
TRACE ( " (%p) \n " , This ) ;
hr = IWineD3DDevice_GetSwapChain ( iface , 0 , ( IWineD3DSwapChain * * ) & swapchain ) ;
if ( FAILED ( hr ) ) {
ERR ( " Failed to get the first implicit swapchain \n " ) ;
return hr ;
}
2008-02-06 20:16:13 +01:00
if ( ! is_display_mode_supported ( This , pPresentationParameters ) ) {
WARN ( " Rejecting Reset() call because the requested display mode is not supported \n " ) ;
WARN ( " Requested mode: %d, %d \n " , pPresentationParameters - > BackBufferWidth ,
pPresentationParameters - > BackBufferHeight ) ;
2009-03-31 09:38:14 +02:00
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
2008-02-06 20:16:13 +01:00
return WINED3DERR_INVALIDCALL ;
}
2006-12-08 16:13:15 +01:00
/* Is it necessary to recreate the gl context? Actually every setting can be changed
* on an existing gl context , so there ' s no real need for recreation .
*
* TODO : Figure out how Reset influences resources in D3DPOOL_DEFAULT , D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
*
* TODO : Figure out what happens to explicit swapchains , or if we have more than one implicit swapchain
*/
TRACE ( " New params: \n " ) ;
2007-02-15 22:36:50 +01:00
TRACE ( " BackBufferWidth = %d \n " , pPresentationParameters - > BackBufferWidth ) ;
TRACE ( " BackBufferHeight = %d \n " , pPresentationParameters - > BackBufferHeight ) ;
TRACE ( " BackBufferFormat = %s \n " , debug_d3dformat ( pPresentationParameters - > BackBufferFormat ) ) ;
TRACE ( " BackBufferCount = %d \n " , pPresentationParameters - > BackBufferCount ) ;
TRACE ( " MultiSampleType = %d \n " , pPresentationParameters - > MultiSampleType ) ;
TRACE ( " MultiSampleQuality = %d \n " , pPresentationParameters - > MultiSampleQuality ) ;
TRACE ( " SwapEffect = %d \n " , pPresentationParameters - > SwapEffect ) ;
TRACE ( " hDeviceWindow = %p \n " , pPresentationParameters - > hDeviceWindow ) ;
TRACE ( " Windowed = %s \n " , pPresentationParameters - > Windowed ? " true " : " false " ) ;
TRACE ( " EnableAutoDepthStencil = %s \n " , pPresentationParameters - > EnableAutoDepthStencil ? " true " : " false " ) ;
TRACE ( " Flags = %08x \n " , pPresentationParameters - > Flags ) ;
TRACE ( " FullScreen_RefreshRateInHz = %d \n " , pPresentationParameters - > FullScreen_RefreshRateInHz ) ;
TRACE ( " PresentationInterval = %d \n " , pPresentationParameters - > PresentationInterval ) ;
2006-12-08 16:13:15 +01:00
/* No special treatment of these parameters. Just store them */
2007-02-15 22:36:50 +01:00
swapchain - > presentParms . SwapEffect = pPresentationParameters - > SwapEffect ;
swapchain - > presentParms . Flags = pPresentationParameters - > Flags ;
swapchain - > presentParms . PresentationInterval = pPresentationParameters - > PresentationInterval ;
swapchain - > presentParms . FullScreen_RefreshRateInHz = pPresentationParameters - > FullScreen_RefreshRateInHz ;
2006-12-08 16:13:15 +01:00
/* What to do about these? */
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > BackBufferCount ! = 0 & &
pPresentationParameters - > BackBufferCount ! = swapchain - > presentParms . BackBufferCount ) {
2006-12-08 16:13:15 +01:00
ERR ( " Cannot change the back buffer count yet \n " ) ;
}
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > BackBufferFormat ! = WINED3DFMT_UNKNOWN & &
pPresentationParameters - > BackBufferFormat ! = swapchain - > presentParms . BackBufferFormat ) {
2006-12-08 16:13:15 +01:00
ERR ( " Cannot change the back buffer format yet \n " ) ;
}
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > hDeviceWindow ! = NULL & &
pPresentationParameters - > hDeviceWindow ! = swapchain - > presentParms . hDeviceWindow ) {
2006-12-08 16:13:15 +01:00
ERR ( " Cannot change the device window yet \n " ) ;
}
2008-09-10 11:08:58 +02:00
if ( pPresentationParameters - > EnableAutoDepthStencil & & ! This - > auto_depth_stencil_buffer ) {
2009-04-23 08:33:21 +02:00
HRESULT hrc ;
TRACE ( " Creating the depth stencil buffer \n " ) ;
hrc = IWineD3DDeviceParent_CreateDepthStencilSurface ( This - > device_parent ,
This - > parent ,
pPresentationParameters - > BackBufferWidth ,
pPresentationParameters - > BackBufferHeight ,
pPresentationParameters - > AutoDepthStencilFormat ,
pPresentationParameters - > MultiSampleType ,
pPresentationParameters - > MultiSampleQuality ,
FALSE ,
& This - > auto_depth_stencil_buffer ) ;
if ( FAILED ( hrc ) ) {
ERR ( " Failed to create the depth stencil buffer \n " ) ;
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
return WINED3DERR_INVALIDCALL ;
}
2006-12-08 16:13:15 +01:00
}
2008-01-08 22:34:43 +01:00
2008-09-10 11:08:58 +02:00
/* Reset the depth stencil */
if ( pPresentationParameters - > EnableAutoDepthStencil )
IWineD3DDevice_SetDepthStencilSurface ( iface , This - > auto_depth_stencil_buffer ) ;
else
IWineD3DDevice_SetDepthStencilSurface ( iface , NULL ) ;
2008-07-29 19:09:34 +02:00
delete_opengl_contexts ( iface , ( IWineD3DSwapChain * ) swapchain ) ;
2008-02-05 00:05:26 +01:00
2008-07-29 19:09:34 +02:00
if ( pPresentationParameters - > Windowed ) {
2006-12-08 16:13:15 +01:00
mode . Width = swapchain - > orig_width ;
mode . Height = swapchain - > orig_height ;
mode . RefreshRate = 0 ;
mode . Format = swapchain - > presentParms . BackBufferFormat ;
} else {
2007-02-15 22:36:50 +01:00
mode . Width = pPresentationParameters - > BackBufferWidth ;
mode . Height = pPresentationParameters - > BackBufferHeight ;
mode . RefreshRate = pPresentationParameters - > FullScreen_RefreshRateInHz ;
2006-12-08 16:13:15 +01:00
mode . Format = swapchain - > presentParms . BackBufferFormat ;
}
/* Should Width == 800 && Height == 0 set 800x600? */
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > BackBufferWidth ! = 0 & & pPresentationParameters - > BackBufferHeight ! = 0 & &
( pPresentationParameters - > BackBufferWidth ! = swapchain - > presentParms . BackBufferWidth | |
pPresentationParameters - > BackBufferHeight ! = swapchain - > presentParms . BackBufferHeight ) )
2006-12-08 16:13:15 +01:00
{
2008-11-20 23:13:48 +01:00
UINT i ;
2006-12-08 16:13:15 +01:00
2007-02-15 22:36:50 +01:00
if ( ! pPresentationParameters - > Windowed ) {
2006-12-08 16:13:15 +01:00
DisplayModeChanged = TRUE ;
}
2007-02-15 22:36:50 +01:00
swapchain - > presentParms . BackBufferWidth = pPresentationParameters - > BackBufferWidth ;
swapchain - > presentParms . BackBufferHeight = pPresentationParameters - > BackBufferHeight ;
2006-12-08 16:13:15 +01:00
updateSurfaceDesc ( ( IWineD3DSurfaceImpl * ) swapchain - > frontBuffer , pPresentationParameters ) ;
for ( i = 0 ; i < swapchain - > presentParms . BackBufferCount ; i + + ) {
updateSurfaceDesc ( ( IWineD3DSurfaceImpl * ) swapchain - > backBuffer [ i ] , pPresentationParameters ) ;
}
2008-01-25 18:04:05 +01:00
if ( This - > auto_depth_stencil_buffer ) {
updateSurfaceDesc ( ( IWineD3DSurfaceImpl * ) This - > auto_depth_stencil_buffer , pPresentationParameters ) ;
}
2006-12-08 16:13:15 +01:00
}
2007-02-15 22:36:50 +01:00
if ( ( pPresentationParameters - > Windowed & & ! swapchain - > presentParms . Windowed ) | |
( swapchain - > presentParms . Windowed & & ! pPresentationParameters - > Windowed ) | |
2006-12-08 16:13:15 +01:00
DisplayModeChanged ) {
2007-02-14 17:59:08 +01:00
2008-03-10 22:24:13 +01:00
IWineD3DDevice_SetDisplayMode ( iface , 0 , & mode ) ;
2008-08-04 21:11:22 +02:00
2008-08-04 21:16:49 +02:00
if ( swapchain - > win_handle & & ! pPresentationParameters - > Windowed ) {
2008-08-04 21:11:22 +02:00
if ( swapchain - > presentParms . Windowed ) {
/* switch from windowed to fs */
2008-08-04 21:16:49 +02:00
IWineD3DDeviceImpl_SetupFullscreenWindow ( iface , swapchain - > win_handle ,
2008-08-04 21:11:22 +02:00
pPresentationParameters - > BackBufferWidth ,
pPresentationParameters - > BackBufferHeight ) ;
} else {
/* Fullscreen -> fullscreen mode change */
2008-08-04 21:16:49 +02:00
MoveWindow ( swapchain - > win_handle , 0 , 0 ,
pPresentationParameters - > BackBufferWidth , pPresentationParameters - > BackBufferHeight ,
TRUE ) ;
2008-08-04 21:11:22 +02:00
}
2008-08-04 21:16:49 +02:00
} else if ( swapchain - > win_handle & & ! swapchain - > presentParms . Windowed ) {
2008-08-04 21:11:22 +02:00
/* Fullscreen -> windowed switch */
2008-08-04 21:16:49 +02:00
IWineD3DDeviceImpl_RestoreWindow ( iface , swapchain - > win_handle ) ;
2008-08-04 21:11:22 +02:00
}
swapchain - > presentParms . Windowed = pPresentationParameters - > Windowed ;
2008-02-06 22:12:06 +01:00
} else if ( ! pPresentationParameters - > Windowed ) {
DWORD style = This - > style , exStyle = This - > exStyle ;
/* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into
* the right position . Some applications ( Battlefield 2 , Guild Wars ) move it and then call
* Reset to clear up their mess . Guild Wars also loses the device during that .
*/
This - > style = 0 ;
This - > exStyle = 0 ;
2008-08-04 21:16:49 +02:00
IWineD3DDeviceImpl_SetupFullscreenWindow ( iface , swapchain - > win_handle ,
2008-08-04 21:11:22 +02:00
pPresentationParameters - > BackBufferWidth ,
pPresentationParameters - > BackBufferHeight ) ;
2008-02-06 22:12:06 +01:00
This - > style = style ;
This - > exStyle = exStyle ;
2006-12-08 16:13:15 +01:00
}
2008-12-19 19:21:55 +01:00
TRACE ( " Resetting stateblock \n " ) ;
IWineD3DStateBlock_Release ( ( IWineD3DStateBlock * ) This - > updateStateBlock ) ;
IWineD3DStateBlock_Release ( ( IWineD3DStateBlock * ) This - > stateBlock ) ;
/* Note: No parent needed for initial internal stateblock */
hr = IWineD3DDevice_CreateStateBlock ( iface , WINED3DSBT_INIT , ( IWineD3DStateBlock * * ) & This - > stateBlock , NULL ) ;
if ( FAILED ( hr ) ) ERR ( " Resetting the stateblock failed with error 0x%08x \n " , hr ) ;
else TRACE ( " Created stateblock %p \n " , This - > stateBlock ) ;
This - > updateStateBlock = This - > stateBlock ;
IWineD3DStateBlock_AddRef ( ( IWineD3DStateBlock * ) This - > updateStateBlock ) ;
2008-02-05 21:51:53 +01:00
hr = IWineD3DStateBlock_InitStartupStateBlock ( ( IWineD3DStateBlock * ) This - > stateBlock ) ;
if ( FAILED ( hr ) ) {
ERR ( " Resetting the stateblock failed with error 0x%08x \n " , hr ) ;
}
2008-03-18 19:31:24 +01:00
2008-07-29 19:09:34 +02:00
hr = create_primary_opengl_context ( iface , ( IWineD3DSwapChain * ) swapchain ) ;
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
2008-03-18 19:31:24 +01:00
2008-02-05 00:05:26 +01:00
/* All done. There is no need to reload resources or shaders, this will happen automatically on the
* first use
*/
2008-07-29 19:09:34 +02:00
return hr ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode ( IWineD3DDevice * iface , BOOL bEnableDialogs ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
/** FIXME: always true at the moment **/
2006-09-26 20:31:58 +02:00
if ( ! bEnableDialogs ) {
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) Dialogs cannot be disabled yet \n " , This ) ;
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters ( IWineD3DDevice * iface , WINED3DDEVICE_CREATION_PARAMETERS * pParameters ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-03-07 00:29:45 +01:00
TRACE ( " (%p) : pParameters %p \n " , This , pParameters ) ;
2005-07-13 16:15:54 +02:00
2006-03-07 00:29:45 +01:00
* pParameters = This - > createParms ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static void WINAPI IWineD3DDeviceImpl_SetGammaRamp ( IWineD3DDevice * iface , UINT iSwapChain , DWORD Flags , CONST WINED3DGAMMARAMP * pRamp ) {
2005-06-23 13:05:24 +02:00
IWineD3DSwapChain * swapchain ;
TRACE ( " Relaying to swapchain \n " ) ;
2008-04-29 22:29:45 +02:00
if ( IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapchain ) = = WINED3D_OK ) {
2008-11-25 11:57:39 +01:00
IWineD3DSwapChain_SetGammaRamp ( swapchain , Flags , pRamp ) ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_Release ( swapchain ) ;
2005-06-23 13:05:24 +02:00
}
2005-03-02 13:16:10 +01:00
return ;
}
2006-06-10 13:15:32 +02:00
static void WINAPI IWineD3DDeviceImpl_GetGammaRamp ( IWineD3DDevice * iface , UINT iSwapChain , WINED3DGAMMARAMP * pRamp ) {
2005-06-23 13:05:24 +02:00
IWineD3DSwapChain * swapchain ;
2005-03-02 13:16:10 +01:00
2005-06-23 13:05:24 +02:00
TRACE ( " Relaying to swapchain \n " ) ;
2008-04-29 22:29:45 +02:00
if ( IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapchain ) = = WINED3D_OK ) {
IWineD3DSwapChain_GetGammaRamp ( swapchain , pRamp ) ;
2006-11-30 13:33:11 +01:00
IWineD3DSwapChain_Release ( swapchain ) ;
2005-06-23 13:05:24 +02:00
}
2005-03-02 13:16:10 +01:00
return ;
2004-10-07 06:22:21 +02:00
}
2005-07-26 12:34:15 +02:00
/** ********************************************************
* Notification functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/** This function must be called in the release of a resource when ref == 0,
* the contents of resource must still be correct ,
2008-01-09 20:37:05 +01:00
* any handles to other resource held by the caller must be closed
2005-07-26 12:34:15 +02:00
* ( e . g . a texture should release all held surfaces because telling the device that it ' s been released . )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-29 09:13:21 +02:00
void device_resource_add ( IWineD3DDeviceImpl * This , IWineD3DResource * resource )
{
TRACE ( " (%p) : Adding resource %p \n " , This , resource ) ;
2005-07-26 12:34:15 +02:00
2007-11-16 20:28:45 +01:00
list_add_head ( & This - > resources , & ( ( IWineD3DResourceImpl * ) resource ) - > resource . resource_list_entry ) ;
2005-07-26 12:34:15 +02:00
}
2009-05-29 09:13:21 +02:00
static void device_resource_remove ( IWineD3DDeviceImpl * This , IWineD3DResource * resource )
{
2007-11-16 20:28:45 +01:00
TRACE ( " (%p) : Removing resource %p \n " , This , resource ) ;
2005-07-26 12:34:15 +02:00
2007-11-16 20:28:45 +01:00
list_remove ( & ( ( IWineD3DResourceImpl * ) resource ) - > resource . resource_list_entry ) ;
2005-07-26 12:34:15 +02:00
}
2009-05-29 09:13:21 +02:00
void device_resource_released ( IWineD3DDeviceImpl * This , IWineD3DResource * resource )
{
2008-09-18 14:57:53 +02:00
WINED3DRESOURCETYPE type = IWineD3DResource_GetType ( resource ) ;
2005-07-26 12:34:15 +02:00
int counter ;
TRACE ( " (%p) : resource %p \n " , This , resource ) ;
2008-09-18 14:57:53 +02:00
2009-05-29 09:13:21 +02:00
context_resource_released ( ( IWineD3DDevice * ) This , resource , type ) ;
2008-09-18 14:57:53 +02:00
switch ( type ) {
2005-07-26 12:34:15 +02:00
/* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
2007-04-09 01:53:27 +02:00
case WINED3DRTYPE_SURFACE : {
unsigned int i ;
2009-06-25 10:24:56 +02:00
if ( This - > d3d_initialized )
{
2007-07-18 23:13:58 +02:00
for ( i = 0 ; i < GL_LIMITS ( buffers ) ; + + i ) {
2008-08-21 18:34:55 +02:00
if ( This - > render_targets [ i ] = = ( IWineD3DSurface * ) resource ) {
This - > render_targets [ i ] = NULL ;
2007-07-18 23:13:58 +02:00
}
}
2008-08-21 18:34:55 +02:00
if ( This - > stencilBufferTarget = = ( IWineD3DSurface * ) resource ) {
This - > stencilBufferTarget = NULL ;
}
2007-04-09 01:53:27 +02:00
}
break ;
}
2006-03-09 23:21:16 +01:00
case WINED3DRTYPE_TEXTURE :
case WINED3DRTYPE_CUBETEXTURE :
case WINED3DRTYPE_VOLUMETEXTURE :
2007-06-25 22:45:40 +02:00
for ( counter = 0 ; counter < MAX_COMBINED_SAMPLERS ; counter + + ) {
2005-07-26 12:34:15 +02:00
if ( This - > stateBlock ! = NULL & & This - > stateBlock - > textures [ counter ] = = ( IWineD3DBaseTexture * ) resource ) {
2005-12-15 10:25:47 +01:00
WARN ( " Texture being released is still by a stateblock, Stage = %u Texture = %p \n " , counter , resource ) ;
2005-07-26 12:34:15 +02:00
This - > stateBlock - > textures [ counter ] = NULL ;
}
if ( This - > updateStateBlock ! = This - > stateBlock ) {
if ( This - > updateStateBlock - > textures [ counter ] = = ( IWineD3DBaseTexture * ) resource ) {
2005-12-15 10:25:47 +01:00
WARN ( " Texture being released is still by a stateblock, Stage = %u Texture = %p \n " , counter , resource ) ;
2005-07-26 12:34:15 +02:00
This - > updateStateBlock - > textures [ counter ] = NULL ;
}
}
}
break ;
2006-03-09 23:21:16 +01:00
case WINED3DRTYPE_VOLUME :
2005-07-26 12:34:15 +02:00
/* TODO: nothing really? */
break ;
2009-04-06 16:44:00 +02:00
case WINED3DRTYPE_BUFFER :
2005-07-26 12:34:15 +02:00
{
int streamNumber ;
TRACE ( " Cleaning up stream pointers \n " ) ;
for ( streamNumber = 0 ; streamNumber < MAX_STREAMS ; streamNumber + + ) {
/* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
FINDOUT : should changes . streamSource [ StreamNumber ] be set ?
*/
if ( This - > updateStateBlock ! = NULL ) { /* ==NULL when device is being destroyed */
if ( ( IWineD3DResource * ) This - > updateStateBlock - > streamSource [ streamNumber ] = = resource ) {
2006-09-25 11:54:14 +02:00
FIXME ( " Vertex buffer released while bound to a state block, stream %d \n " , streamNumber ) ;
2005-07-26 12:34:15 +02:00
This - > updateStateBlock - > streamSource [ streamNumber ] = 0 ;
/* Set changed flag? */
}
}
2005-11-23 20:14:43 +01:00
if ( This - > stateBlock ! = NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
2005-07-26 12:34:15 +02:00
if ( ( IWineD3DResource * ) This - > stateBlock - > streamSource [ streamNumber ] = = resource ) {
2006-09-25 11:54:14 +02:00
TRACE ( " Vertex buffer released while bound to a state block, stream %d \n " , streamNumber ) ;
2005-07-26 12:34:15 +02:00
This - > stateBlock - > streamSource [ streamNumber ] = 0 ;
}
}
}
2009-04-06 16:44:00 +02:00
if ( This - > updateStateBlock ! = NULL ) { /* ==NULL when device is being destroyed */
2009-04-06 16:46:12 +02:00
if ( This - > updateStateBlock - > pIndexData = = ( IWineD3DBuffer * ) resource ) {
2009-04-06 16:44:00 +02:00
This - > updateStateBlock - > pIndexData = NULL ;
}
2005-07-26 12:34:15 +02:00
}
2009-04-06 16:44:00 +02:00
if ( This - > stateBlock ! = NULL ) { /* ==NULL when device is being destroyed */
2009-04-06 16:46:12 +02:00
if ( This - > stateBlock - > pIndexData = = ( IWineD3DBuffer * ) resource ) {
2009-04-06 16:44:00 +02:00
This - > stateBlock - > pIndexData = NULL ;
}
2005-07-26 12:34:15 +02:00
}
}
break ;
2009-02-23 09:16:02 +01:00
2005-07-26 12:34:15 +02:00
default :
2005-11-10 13:14:56 +01:00
FIXME ( " (%p) unknown resource type %p %u \n " , This , resource , IWineD3DResource_GetType ( resource ) ) ;
2005-07-26 12:34:15 +02:00
break ;
}
2008-01-09 20:37:05 +01:00
/* Remove the resource from the resourceStore */
2009-05-29 09:13:21 +02:00
device_resource_remove ( This , resource ) ;
2005-07-26 12:34:15 +02:00
TRACE ( " Resource released \n " ) ;
}
2008-01-11 15:38:54 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_EnumResources ( IWineD3DDevice * iface , D3DCB_ENUMRESOURCES pCallback , void * pData ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DResourceImpl * resource , * cursor ;
HRESULT ret ;
TRACE ( " (%p)->(%p,%p) \n " , This , pCallback , pData ) ;
LIST_FOR_EACH_ENTRY_SAFE ( resource , cursor , & This - > resources , IWineD3DResourceImpl , resource . resource_list_entry ) {
TRACE ( " enumerating resource %p \n " , resource ) ;
IWineD3DResource_AddRef ( ( IWineD3DResource * ) resource ) ;
ret = pCallback ( ( IWineD3DResource * ) resource , pData ) ;
if ( ret = = S_FALSE ) {
TRACE ( " Canceling enumeration \n " ) ;
break ;
}
}
return WINED3D_OK ;
}
2004-10-07 06:22:21 +02:00
/**********************************************************
* IWineD3DDevice VTbl follows
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-06-06 21:50:35 +02:00
const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
2004-10-07 06:22:21 +02:00
{
2005-03-02 13:16:10 +01:00
/*** IUnknown methods ***/
2004-10-07 06:22:21 +02:00
IWineD3DDeviceImpl_QueryInterface ,
IWineD3DDeviceImpl_AddRef ,
2004-10-14 02:32:04 +02:00
IWineD3DDeviceImpl_Release ,
2005-03-02 13:16:10 +01:00
/*** IWineD3DDevice methods ***/
2004-11-23 14:52:46 +01:00
IWineD3DDeviceImpl_GetParent ,
2005-03-02 13:16:10 +01:00
/*** Creation methods**/
2009-02-23 09:16:02 +01:00
IWineD3DDeviceImpl_CreateBuffer ,
2004-10-21 22:59:12 +02:00
IWineD3DDeviceImpl_CreateVertexBuffer ,
2004-11-24 19:13:41 +01:00
IWineD3DDeviceImpl_CreateIndexBuffer ,
2004-10-21 22:59:12 +02:00
IWineD3DDeviceImpl_CreateStateBlock ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_CreateSurface ,
2009-02-24 07:43:02 +01:00
IWineD3DDeviceImpl_CreateRendertargetView ,
2005-01-17 14:44:57 +01:00
IWineD3DDeviceImpl_CreateTexture ,
IWineD3DDeviceImpl_CreateVolumeTexture ,
IWineD3DDeviceImpl_CreateVolume ,
IWineD3DDeviceImpl_CreateCubeTexture ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_CreateQuery ,
2008-10-28 09:27:20 +01:00
IWineD3DDeviceImpl_CreateSwapChain ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_CreateVertexDeclaration ,
2007-04-22 11:52:11 +02:00
IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_CreateVertexShader ,
IWineD3DDeviceImpl_CreatePixelShader ,
2006-04-17 17:04:59 +02:00
IWineD3DDeviceImpl_CreatePalette ,
2005-03-02 13:16:10 +01:00
/*** Odd functions **/
2006-04-12 21:08:57 +02:00
IWineD3DDeviceImpl_Init3D ,
2008-08-05 21:23:00 +02:00
IWineD3DDeviceImpl_InitGDI ,
2006-04-12 21:08:57 +02:00
IWineD3DDeviceImpl_Uninit3D ,
2008-08-05 21:23:00 +02:00
IWineD3DDeviceImpl_UninitGDI ,
2007-03-04 17:03:03 +01:00
IWineD3DDeviceImpl_SetMultithreaded ,
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl_EvictManagedResources ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_GetAvailableTextureMem ,
IWineD3DDeviceImpl_GetBackBuffer ,
IWineD3DDeviceImpl_GetCreationParameters ,
IWineD3DDeviceImpl_GetDeviceCaps ,
IWineD3DDeviceImpl_GetDirect3D ,
IWineD3DDeviceImpl_GetDisplayMode ,
2006-04-17 17:51:21 +02:00
IWineD3DDeviceImpl_SetDisplayMode ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_GetNumberOfSwapChains ,
IWineD3DDeviceImpl_GetRasterStatus ,
IWineD3DDeviceImpl_GetSwapChain ,
IWineD3DDeviceImpl_Reset ,
IWineD3DDeviceImpl_SetDialogBoxMode ,
IWineD3DDeviceImpl_SetCursorProperties ,
IWineD3DDeviceImpl_SetCursorPosition ,
IWineD3DDeviceImpl_ShowCursor ,
IWineD3DDeviceImpl_TestCooperativeLevel ,
/*** Getters and setters **/
IWineD3DDeviceImpl_SetClipPlane ,
IWineD3DDeviceImpl_GetClipPlane ,
IWineD3DDeviceImpl_SetClipStatus ,
IWineD3DDeviceImpl_GetClipStatus ,
IWineD3DDeviceImpl_SetCurrentTexturePalette ,
IWineD3DDeviceImpl_GetCurrentTexturePalette ,
IWineD3DDeviceImpl_SetDepthStencilSurface ,
IWineD3DDeviceImpl_GetDepthStencilSurface ,
IWineD3DDeviceImpl_SetGammaRamp ,
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl_GetGammaRamp ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_SetIndices ,
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl_GetIndices ,
2007-06-04 18:12:36 +02:00
IWineD3DDeviceImpl_SetBaseVertexIndex ,
2007-06-06 18:40:02 +02:00
IWineD3DDeviceImpl_GetBaseVertexIndex ,
2004-11-29 18:53:42 +01:00
IWineD3DDeviceImpl_SetLight ,
IWineD3DDeviceImpl_GetLight ,
IWineD3DDeviceImpl_SetLightEnable ,
IWineD3DDeviceImpl_GetLightEnable ,
IWineD3DDeviceImpl_SetMaterial ,
IWineD3DDeviceImpl_GetMaterial ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_SetNPatchMode ,
2005-07-13 16:15:54 +02:00
IWineD3DDeviceImpl_GetNPatchMode ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_SetPaletteEntries ,
IWineD3DDeviceImpl_GetPaletteEntries ,
IWineD3DDeviceImpl_SetPixelShader ,
IWineD3DDeviceImpl_GetPixelShader ,
IWineD3DDeviceImpl_SetPixelShaderConstantB ,
IWineD3DDeviceImpl_GetPixelShaderConstantB ,
IWineD3DDeviceImpl_SetPixelShaderConstantI ,
IWineD3DDeviceImpl_GetPixelShaderConstantI ,
IWineD3DDeviceImpl_SetPixelShaderConstantF ,
IWineD3DDeviceImpl_GetPixelShaderConstantF ,
2004-12-13 14:35:38 +01:00
IWineD3DDeviceImpl_SetRenderState ,
IWineD3DDeviceImpl_GetRenderState ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_SetRenderTarget ,
IWineD3DDeviceImpl_GetRenderTarget ,
2006-04-15 22:40:14 +02:00
IWineD3DDeviceImpl_SetFrontBackBuffers ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_SetSamplerState ,
IWineD3DDeviceImpl_GetSamplerState ,
IWineD3DDeviceImpl_SetScissorRect ,
IWineD3DDeviceImpl_GetScissorRect ,
IWineD3DDeviceImpl_SetSoftwareVertexProcessing ,
IWineD3DDeviceImpl_GetSoftwareVertexProcessing ,
IWineD3DDeviceImpl_SetStreamSource ,
IWineD3DDeviceImpl_GetStreamSource ,
IWineD3DDeviceImpl_SetStreamSourceFreq ,
IWineD3DDeviceImpl_GetStreamSourceFreq ,
IWineD3DDeviceImpl_SetTexture ,
2005-06-24 13:53:07 +02:00
IWineD3DDeviceImpl_GetTexture ,
2004-12-13 14:35:38 +01:00
IWineD3DDeviceImpl_SetTextureStageState ,
IWineD3DDeviceImpl_GetTextureStageState ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_SetTransform ,
IWineD3DDeviceImpl_GetTransform ,
IWineD3DDeviceImpl_SetVertexDeclaration ,
IWineD3DDeviceImpl_GetVertexDeclaration ,
IWineD3DDeviceImpl_SetVertexShader ,
IWineD3DDeviceImpl_GetVertexShader ,
IWineD3DDeviceImpl_SetVertexShaderConstantB ,
IWineD3DDeviceImpl_GetVertexShaderConstantB ,
IWineD3DDeviceImpl_SetVertexShaderConstantI ,
IWineD3DDeviceImpl_GetVertexShaderConstantI ,
IWineD3DDeviceImpl_SetVertexShaderConstantF ,
IWineD3DDeviceImpl_GetVertexShaderConstantF ,
IWineD3DDeviceImpl_SetViewport ,
2008-03-04 02:30:23 +01:00
IWineD3DDeviceImpl_GetViewport ,
IWineD3DDeviceImpl_MultiplyTransform ,
IWineD3DDeviceImpl_ValidateDevice ,
IWineD3DDeviceImpl_ProcessVertices ,
/*** State block ***/
IWineD3DDeviceImpl_BeginStateBlock ,
IWineD3DDeviceImpl_EndStateBlock ,
/*** Scene management ***/
IWineD3DDeviceImpl_BeginScene ,
IWineD3DDeviceImpl_EndScene ,
IWineD3DDeviceImpl_Present ,
IWineD3DDeviceImpl_Clear ,
2009-02-25 08:39:01 +01:00
IWineD3DDeviceImpl_ClearRendertargetView ,
2008-03-04 02:30:23 +01:00
/*** Drawing ***/
2009-03-05 12:30:43 +01:00
IWineD3DDeviceImpl_SetPrimitiveType ,
IWineD3DDeviceImpl_GetPrimitiveType ,
2008-03-04 02:30:23 +01:00
IWineD3DDeviceImpl_DrawPrimitive ,
IWineD3DDeviceImpl_DrawIndexedPrimitive ,
IWineD3DDeviceImpl_DrawPrimitiveUP ,
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP ,
IWineD3DDeviceImpl_DrawPrimitiveStrided ,
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided ,
IWineD3DDeviceImpl_DrawRectPatch ,
IWineD3DDeviceImpl_DrawTriPatch ,
IWineD3DDeviceImpl_DeletePatch ,
IWineD3DDeviceImpl_ColorFill ,
IWineD3DDeviceImpl_UpdateTexture ,
IWineD3DDeviceImpl_UpdateSurface ,
IWineD3DDeviceImpl_GetFrontBufferData ,
/*** object tracking ***/
IWineD3DDeviceImpl_EnumResources
} ;
2005-07-05 16:05:18 +02:00
const DWORD SavedPixelStates_R [ NUM_SAVEDPIXELSTATES_R ] = {
WINED3DRS_ALPHABLENDENABLE ,
WINED3DRS_ALPHAFUNC ,
WINED3DRS_ALPHAREF ,
WINED3DRS_ALPHATESTENABLE ,
WINED3DRS_BLENDOP ,
WINED3DRS_COLORWRITEENABLE ,
WINED3DRS_DESTBLEND ,
WINED3DRS_DITHERENABLE ,
WINED3DRS_FILLMODE ,
WINED3DRS_FOGDENSITY ,
WINED3DRS_FOGEND ,
WINED3DRS_FOGSTART ,
WINED3DRS_LASTPIXEL ,
WINED3DRS_SHADEMODE ,
WINED3DRS_SRCBLEND ,
WINED3DRS_STENCILENABLE ,
WINED3DRS_STENCILFAIL ,
WINED3DRS_STENCILFUNC ,
WINED3DRS_STENCILMASK ,
WINED3DRS_STENCILPASS ,
WINED3DRS_STENCILREF ,
WINED3DRS_STENCILWRITEMASK ,
WINED3DRS_STENCILZFAIL ,
WINED3DRS_TEXTUREFACTOR ,
WINED3DRS_WRAP0 ,
WINED3DRS_WRAP1 ,
WINED3DRS_WRAP2 ,
WINED3DRS_WRAP3 ,
WINED3DRS_WRAP4 ,
WINED3DRS_WRAP5 ,
WINED3DRS_WRAP6 ,
WINED3DRS_WRAP7 ,
WINED3DRS_ZENABLE ,
WINED3DRS_ZFUNC ,
WINED3DRS_ZWRITEENABLE
} ;
const DWORD SavedPixelStates_T [ NUM_SAVEDPIXELSTATES_T ] = {
WINED3DTSS_ALPHAARG0 ,
WINED3DTSS_ALPHAARG1 ,
WINED3DTSS_ALPHAARG2 ,
WINED3DTSS_ALPHAOP ,
WINED3DTSS_BUMPENVLOFFSET ,
WINED3DTSS_BUMPENVLSCALE ,
WINED3DTSS_BUMPENVMAT00 ,
WINED3DTSS_BUMPENVMAT01 ,
WINED3DTSS_BUMPENVMAT10 ,
WINED3DTSS_BUMPENVMAT11 ,
WINED3DTSS_COLORARG0 ,
WINED3DTSS_COLORARG1 ,
WINED3DTSS_COLORARG2 ,
WINED3DTSS_COLOROP ,
WINED3DTSS_RESULTARG ,
WINED3DTSS_TEXCOORDINDEX ,
WINED3DTSS_TEXTURETRANSFORMFLAGS
} ;
const DWORD SavedPixelStates_S [ NUM_SAVEDPIXELSTATES_S ] = {
WINED3DSAMP_ADDRESSU ,
WINED3DSAMP_ADDRESSV ,
WINED3DSAMP_ADDRESSW ,
WINED3DSAMP_BORDERCOLOR ,
WINED3DSAMP_MAGFILTER ,
WINED3DSAMP_MINFILTER ,
WINED3DSAMP_MIPFILTER ,
WINED3DSAMP_MIPMAPLODBIAS ,
WINED3DSAMP_MAXMIPLEVEL ,
WINED3DSAMP_MAXANISOTROPY ,
WINED3DSAMP_SRGBTEXTURE ,
WINED3DSAMP_ELEMENTINDEX
} ;
const DWORD SavedVertexStates_R [ NUM_SAVEDVERTEXSTATES_R ] = {
WINED3DRS_AMBIENT ,
WINED3DRS_AMBIENTMATERIALSOURCE ,
WINED3DRS_CLIPPING ,
WINED3DRS_CLIPPLANEENABLE ,
WINED3DRS_COLORVERTEX ,
WINED3DRS_DIFFUSEMATERIALSOURCE ,
WINED3DRS_EMISSIVEMATERIALSOURCE ,
WINED3DRS_FOGDENSITY ,
WINED3DRS_FOGEND ,
WINED3DRS_FOGSTART ,
WINED3DRS_FOGTABLEMODE ,
WINED3DRS_FOGVERTEXMODE ,
WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
WINED3DRS_LIGHTING ,
WINED3DRS_LOCALVIEWER ,
WINED3DRS_MULTISAMPLEANTIALIAS ,
WINED3DRS_MULTISAMPLEMASK ,
WINED3DRS_NORMALIZENORMALS ,
WINED3DRS_PATCHEDGESTYLE ,
WINED3DRS_POINTSCALE_A ,
WINED3DRS_POINTSCALE_B ,
WINED3DRS_POINTSCALE_C ,
WINED3DRS_POINTSCALEENABLE ,
WINED3DRS_POINTSIZE ,
WINED3DRS_POINTSIZE_MAX ,
WINED3DRS_POINTSIZE_MIN ,
WINED3DRS_POINTSPRITEENABLE ,
WINED3DRS_RANGEFOGENABLE ,
WINED3DRS_SPECULARMATERIALSOURCE ,
WINED3DRS_TWEENFACTOR ,
2007-08-16 22:53:44 +02:00
WINED3DRS_VERTEXBLEND ,
WINED3DRS_CULLMODE ,
WINED3DRS_FOGCOLOR
2005-07-05 16:05:18 +02:00
} ;
const DWORD SavedVertexStates_T [ NUM_SAVEDVERTEXSTATES_T ] = {
WINED3DTSS_TEXCOORDINDEX ,
WINED3DTSS_TEXTURETRANSFORMFLAGS
} ;
const DWORD SavedVertexStates_S [ NUM_SAVEDVERTEXSTATES_S ] = {
WINED3DSAMP_DMAPOFFSET
} ;
2006-12-19 13:00:03 +01:00
void IWineD3DDeviceImpl_MarkStateDirty ( IWineD3DDeviceImpl * This , DWORD state ) {
2008-07-02 01:23:44 +02:00
DWORD rep = This - > StateTable [ state ] . representative ;
2006-12-19 13:00:03 +01:00
DWORD idx ;
BYTE shift ;
2007-02-12 19:18:31 +01:00
UINT i ;
WineD3DContext * context ;
2006-12-19 13:00:03 +01:00
2007-02-12 19:18:31 +01:00
if ( ! rep ) return ;
for ( i = 0 ; i < This - > numContexts ; i + + ) {
2007-02-12 19:35:45 +01:00
context = This - > contexts [ i ] ;
2007-02-12 19:18:31 +01:00
if ( isStateDirty ( context , rep ) ) continue ;
context - > dirtyArray [ context - > numDirtyEntries + + ] = rep ;
idx = rep > > 5 ;
shift = rep & 0x1f ;
context - > isStateDirty [ idx ] | = ( 1 < < shift ) ;
}
2006-12-19 13:00:03 +01:00
}
2007-11-30 20:22:33 +01:00
void get_drawable_size_pbuffer ( IWineD3DSurfaceImpl * This , UINT * width , UINT * height ) {
IWineD3DDeviceImpl * dev = This - > resource . wineD3DDevice ;
/* The drawable size of a pbuffer render target is the current pbuffer size
*/
* width = dev - > pbufferWidth ;
* height = dev - > pbufferHeight ;
}
void get_drawable_size_fbo ( IWineD3DSurfaceImpl * This , UINT * width , UINT * height ) {
/* The drawable size of a fbo target is the opengl texture size, which is the power of two size
*/
* width = This - > pow2Width ;
* height = This - > pow2Height ;
}
void get_drawable_size_backbuffer ( IWineD3DSurfaceImpl * This , UINT * width , UINT * height ) {
IWineD3DDeviceImpl * dev = This - > resource . wineD3DDevice ;
/* The drawable size of a backbuffer / aux buffer offscreen target is the size of the
* current context ' s drawable , which is the size of the back buffer of the swapchain
* the active context belongs to . The back buffer of the swapchain is stored as the
* surface the context belongs to .
*/
* width = ( ( IWineD3DSurfaceImpl * ) dev - > activeContext - > surface ) - > currentDesc . Width ;
* height = ( ( IWineD3DSurfaceImpl * ) dev - > activeContext - > surface ) - > currentDesc . Height ;
}