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
2007-07-27 13:22:54 +02:00
* Copyright 2006 - 2007 Stefan D <EFBFBD> singer for CodeWeavers
2007-04-09 01:53:27 +02:00
* Copyright 2006 - 2007 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
} ;
2005-07-26 12:34:15 +02:00
/* static function declarations */
static void WINAPI IWineD3DDeviceImpl_AddResource ( IWineD3DDevice * iface , IWineD3DResource * resource ) ;
2005-03-02 13:16:10 +01:00
/* helper macros */
2006-04-07 12:51:12 +02:00
# define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
2005-03-02 13:16:10 +01:00
2005-07-13 16:15:54 +02:00
# define D3DCREATEOBJECTINSTANCE(object, type) { \
2005-03-02 13:16:10 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3D # # type # # Impl ) ) ; \
D3DMEMCHECK ( object , pp # # type ) ; \
object - > lpVtbl = & IWineD3D # # type # # _Vtbl ; \
object - > wineD3DDevice = This ; \
object - > parent = parent ; \
object - > ref = 1 ; \
* pp # # type = ( IWineD3D # # type * ) object ; \
}
2006-09-27 13:14:46 +02:00
# define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3D # # type # # Impl ) ) ; \
D3DMEMCHECK ( object , pp # # type ) ; \
object - > lpVtbl = & IWineD3D # # type # # _Vtbl ; \
object - > parent = parent ; \
object - > ref = 1 ; \
object - > baseShader . device = ( IWineD3DDevice * ) This ; \
2007-02-27 20:51:53 +01:00
list_init ( & object - > baseShader . linked_programs ) ; \
2006-09-27 13:14:46 +02:00
* pp # # type = ( IWineD3D # # type * ) object ; \
}
2005-07-13 13:34:55 +02:00
# define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
2005-03-02 13:16:10 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3D # # type # # Impl ) ) ; \
D3DMEMCHECK ( object , pp # # type ) ; \
object - > lpVtbl = & IWineD3D # # type # # _Vtbl ; \
2005-03-29 21:01:00 +02:00
object - > resource . wineD3DDevice = This ; \
object - > resource . parent = parent ; \
object - > resource . resourceType = d3dtype ; \
object - > resource . ref = 1 ; \
object - > resource . pool = Pool ; \
object - > resource . format = Format ; \
object - > resource . usage = Usage ; \
2005-07-13 13:34:55 +02:00
object - > resource . size = _size ; \
2007-05-07 20:46:24 +02:00
list_init ( & object - > resource . privateData ) ; \
2005-07-13 13:34:55 +02:00
/* Check that we have enough video ram left */ \
2006-03-28 14:20:47 +02:00
if ( Pool = = WINED3DPOOL_DEFAULT ) { \
2005-07-13 13:34:55 +02:00
if ( IWineD3DDevice_GetAvailableTextureMem ( iface ) < = _size ) { \
WARN ( " Out of 'bogus' video memory \n " ) ; \
2005-08-03 13:00:28 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ; \
2005-07-13 13:34:55 +02:00
* pp # # type = NULL ; \
2006-04-07 12:51:12 +02:00
return WINED3DERR_OUTOFVIDEOMEMORY ; \
2005-07-13 13:34:55 +02:00
} \
2007-09-23 00:46:21 +02:00
WineD3DAdapterChangeGLRam ( This , _size ) ; \
2005-07-13 13:34:55 +02:00
} \
2006-03-28 14:20:47 +02:00
object - > resource . allocatedMemory = ( 0 = = _size ? NULL : Pool = = WINED3DPOOL_DEFAULT ? NULL : HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , _size ) ) ; \
if ( object - > resource . allocatedMemory = = NULL & & _size ! = 0 & & Pool ! = WINED3DPOOL_DEFAULT ) { \
2005-07-13 13:34:55 +02:00
FIXME ( " Out of memory! \n " ) ; \
HeapFree ( GetProcessHeap ( ) , 0 , object ) ; \
* pp # # type = NULL ; \
2006-04-07 12:51:12 +02:00
return WINED3DERR_OUTOFVIDEOMEMORY ; \
2005-07-13 13:34:55 +02:00
} \
2005-03-02 13:16:10 +01:00
* pp # # type = ( IWineD3D # # type * ) object ; \
2005-07-26 12:34:15 +02:00
IWineD3DDeviceImpl_AddResource ( iface , ( IWineD3DResource * ) object ) ; \
2005-07-13 13:34:55 +02:00
TRACE ( " (%p) : Created resource %p \n " , This , object ) ; \
2005-03-02 13:16:10 +01:00
}
2005-11-23 20:14:43 +01:00
# define D3DINITIALIZEBASETEXTURE(_basetexture) { \
2005-03-14 11:12:52 +01:00
_basetexture . levels = Levels ; \
2006-04-06 19:02:16 +02:00
_basetexture . filterType = ( Usage & WINED3DUSAGE_AUTOGENMIPMAP ) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE ; \
2005-03-14 11:12:52 +01:00
_basetexture . LOD = 0 ; \
2005-06-23 18:44:19 +02:00
_basetexture . dirty = TRUE ; \
2007-06-07 01:13:16 +02:00
_basetexture . is_srgb = FALSE ; \
_basetexture . srgb_mode_change_count = 0 ; \
2005-03-14 11:12:52 +01: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
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 ) {
2006-11-27 20:51:07 +01:00
if ( This - > fbo ) {
GL_EXTCALL ( glDeleteFramebuffersEXT ( 1 , & This - > fbo ) ) ;
}
2007-04-09 01:54:07 +02:00
if ( This - > src_fbo ) {
GL_EXTCALL ( glDeleteFramebuffersEXT ( 1 , & This - > src_fbo ) ) ;
}
if ( This - > dst_fbo ) {
GL_EXTCALL ( glDeleteFramebuffersEXT ( 1 , & This - > dst_fbo ) ) ;
}
2006-11-27 20:51:07 +01:00
2007-02-27 20:51:53 +01:00
if ( This - > glsl_program_lookup ) hash_table_destroy ( This - > glsl_program_lookup ) ;
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
2006-04-18 22:38:30 +02:00
if ( This - > resources ! = NULL ) {
FIXME ( " (%p) Device released with resources still bound, acceptable but unexpected \n " , This ) ;
dumpResources ( This - > resources ) ;
}
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
}
2006-06-21 15:05:38 +02:00
static void CreateVBO ( IWineD3DVertexBufferImpl * object ) {
IWineD3DDeviceImpl * This = object - > resource . wineD3DDevice ; /* Needed for GL_EXTCALL */
GLenum error , glUsage ;
DWORD vboUsage = object - > resource . usage ;
2006-07-21 14:02:44 +02:00
if ( object - > Flags & VBFLAG_VBOCREATEFAIL ) {
WARN ( " Creating a vbo failed once, not trying again \n " ) ;
return ;
}
2006-07-28 21:33:20 +02:00
TRACE ( " Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s) \n " , object , debug_d3dusage ( vboUsage ) ) ;
2006-06-21 15:05:38 +02:00
2007-03-17 23:00:39 +01:00
/* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2007-03-17 23:00:39 +01:00
2006-06-21 15:05:38 +02:00
/* Make sure that the gl error is cleared. Do not use checkGLcall
* here because checkGLcall just prints a fixme and continues . However ,
* if an error during VBO creation occurs we can fall back to non - vbo operation
* with full functionality ( but performance loss )
*/
while ( glGetError ( ) ! = GL_NO_ERROR ) ;
/* Basically the FVF parameter passed to CreateVertexBuffer is no good
* It is the FVF set with IWineD3DDevice : : SetFVF or the Vertex Declaration set with
* IWineD3DDevice : : SetVertexDeclaration that decides how the vertices in the buffer
* look like . This means that on each DrawPrimitive call the vertex buffer has to be verified
* to check if the rhw and color values are in the correct format .
*/
GL_EXTCALL ( glGenBuffersARB ( 1 , & object - > vbo ) ) ;
error = glGetError ( ) ;
if ( object - > vbo = = 0 | | error ! = GL_NO_ERROR ) {
2007-05-03 20:58:13 +02:00
WARN ( " Failed to create a VBO with error %s (%#x) \n " , debug_glerror ( error ) , error ) ;
2006-06-21 15:05:38 +02:00
goto error ;
}
GL_EXTCALL ( glBindBufferARB ( GL_ARRAY_BUFFER_ARB , object - > vbo ) ) ;
error = glGetError ( ) ;
if ( error ! = GL_NO_ERROR ) {
2007-05-03 20:58:13 +02:00
WARN ( " Failed to bind the VBO with error %s (%#x) \n " , debug_glerror ( error ) , error ) ;
2006-06-21 15:05:38 +02:00
goto error ;
}
/* Don't use static, because dx apps tend to update the buffer
2007-02-14 17:51:21 +01:00
* quite often even if they specify 0 usage . Because we always keep the local copy
* we never read from the vbo and can create a write only opengl buffer .
*/
2007-02-14 23:30:23 +01:00
switch ( vboUsage & ( WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC ) ) {
case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC :
case WINED3DUSAGE_DYNAMIC :
2006-06-21 15:05:38 +02:00
TRACE ( " Gl usage = GL_STREAM_DRAW \n " ) ;
glUsage = GL_STREAM_DRAW_ARB ;
break ;
2007-02-14 23:30:23 +01:00
case WINED3DUSAGE_WRITEONLY :
2007-02-14 17:51:21 +01:00
default :
2006-07-28 21:33:20 +02:00
TRACE ( " Gl usage = GL_DYNAMIC_DRAW \n " ) ;
2006-06-21 15:05:38 +02:00
glUsage = GL_DYNAMIC_DRAW_ARB ;
break ;
}
/* Reserve memory for the buffer. The amount of data won't change
2007-02-14 17:51:21 +01:00
* so we are safe with calling glBufferData once with a NULL ptr and
* calling glBufferSubData on updates
*/
2006-06-21 15:05:38 +02:00
GL_EXTCALL ( glBufferDataARB ( GL_ARRAY_BUFFER_ARB , object - > resource . size , NULL , glUsage ) ) ;
error = glGetError ( ) ;
if ( error ! = GL_NO_ERROR ) {
2007-05-03 20:58:13 +02:00
WARN ( " glBufferDataARB failed with error %s (%#x) \n " , debug_glerror ( error ) , error ) ;
2006-06-21 15:05:38 +02:00
goto error ;
}
LEAVE_GL ( ) ;
return ;
error :
/* Clean up all vbo init, but continue because we can work without a vbo :-) */
FIXME ( " Failed to create a vertex buffer object. Continuing, but performance issues can occur \n " ) ;
if ( object - > vbo ) GL_EXTCALL ( glDeleteBuffersARB ( 1 , & object - > vbo ) ) ;
object - > vbo = 0 ;
2006-07-21 14:02:44 +02:00
object - > Flags | = VBFLAG_VBOCREATEFAIL ;
2006-06-21 15:05:38 +02:00
LEAVE_GL ( ) ;
return ;
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer ( IWineD3DDevice * iface , UINT Size , DWORD Usage ,
2006-03-28 14:20:47 +02:00
DWORD FVF , WINED3DPOOL Pool , IWineD3DVertexBuffer * * ppVertexBuffer , HANDLE * sharedHandle ,
2004-11-23 14:52:46 +01:00
IUnknown * parent ) {
2004-10-14 02:32:04 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-03-02 13:16:10 +01:00
IWineD3DVertexBufferImpl * object ;
2005-03-29 21:01:00 +02:00
WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA ; /* Dummy format for now */
2006-06-21 15:05:38 +02:00
int dxVersion = ( ( IWineD3DImpl * ) This - > wineD3D ) - > dxVersion ;
BOOL conv ;
2007-02-13 20:24:39 +01:00
if ( Size = = 0 ) {
WARN ( " Size 0 requested, returning WINED3DERR_INVALIDCALL \n " ) ;
* ppVertexBuffer = NULL ;
return WINED3DERR_INVALIDCALL ;
}
2006-03-09 23:21:16 +01:00
D3DCREATERESOURCEOBJECTINSTANCE ( object , VertexBuffer , WINED3DRTYPE_VERTEXBUFFER , Size )
2006-06-21 15:05:38 +02:00
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p \n " , This , Size , Usage , FVF , Pool , object - > resource . allocatedMemory , object ) ;
2006-06-21 15:05:38 +02:00
* ppVertexBuffer = ( IWineD3DVertexBuffer * ) object ;
2006-03-28 14:20:47 +02:00
if ( Pool = = WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
2005-07-13 13:34:55 +02:00
object - > resource . allocatedMemory = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , object - > resource . size ) ;
}
object - > fvf = FVF ;
2004-10-14 02:32:04 +02:00
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 ) ) ;
2006-06-21 15:05:38 +02:00
if ( GL_SUPPORT ( ARB_VERTEX_BUFFER_OBJECT ) & & Pool ! = WINED3DPOOL_SYSTEMMEM & & ! ( Usage & WINED3DUSAGE_DYNAMIC ) & &
( dxVersion > 7 | | ! conv ) ) {
CreateVBO ( object ) ;
}
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
2007-02-19 15:25:32 +01:00
static void CreateIndexBufferVBO ( IWineD3DDeviceImpl * This , IWineD3DIndexBufferImpl * object ) {
GLenum error , glUsage ;
TRACE ( " Creating VBO for Index Buffer %p \n " , object ) ;
2007-02-26 13:38:17 +01:00
/* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
* restored on the next draw
*/
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_INDEXBUFFER ) ;
2007-03-17 23:00:39 +01:00
/* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2007-03-17 23:00:39 +01:00
2007-02-19 15:25:32 +01:00
while ( glGetError ( ) ) ;
GL_EXTCALL ( glGenBuffersARB ( 1 , & object - > vbo ) ) ;
error = glGetError ( ) ;
if ( error ! = GL_NO_ERROR | | object - > vbo = = 0 ) {
2007-05-03 20:58:13 +02:00
ERR ( " Creating a vbo failed with error %s (%#x), continuing without vbo for this buffer \n " , debug_glerror ( error ) , error ) ;
2007-02-26 13:38:17 +01:00
goto out ;
2007-02-19 15:25:32 +01:00
}
GL_EXTCALL ( glBindBufferARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , object - > vbo ) ) ;
error = glGetError ( ) ;
if ( error ! = GL_NO_ERROR ) {
2007-05-03 20:58:13 +02:00
ERR ( " Failed to bind index buffer with error %s (%#x), continuing without vbo for this buffer \n " , debug_glerror ( error ) , error ) ;
2007-02-19 15:25:32 +01:00
goto out ;
}
/* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
* copy no readback will be needed
*/
2007-02-25 23:10:20 +01:00
glUsage = GL_STATIC_DRAW_ARB ;
2007-02-19 15:25:32 +01:00
GL_EXTCALL ( glBufferDataARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , object - > resource . size , NULL , glUsage ) ) ;
error = glGetError ( ) ;
if ( error ! = GL_NO_ERROR ) {
2007-05-03 20:58:13 +02:00
ERR ( " Failed to initialize the index buffer with error %s (%#x) \n " , debug_glerror ( error ) , error ) ;
2007-02-19 15:25:32 +01:00
goto out ;
}
LEAVE_GL ( ) ;
TRACE ( " Successfully created vbo %d for index buffer %p \n " , object - > vbo , object ) ;
return ;
out :
GL_EXTCALL ( glBindBufferARB ( GL_ELEMENT_ARRAY_BUFFER_ARB , 0 ) ) ;
GL_EXTCALL ( glDeleteBuffersARB ( 1 , & object - > vbo ) ) ;
LEAVE_GL ( ) ;
object - > vbo = 0 ;
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer ( IWineD3DDevice * iface , UINT Length , DWORD Usage ,
2006-03-28 14:20:47 +02:00
WINED3DFORMAT Format , WINED3DPOOL Pool , IWineD3DIndexBuffer * * ppIndexBuffer ,
2004-11-24 19:13:41 +01:00
HANDLE * sharedHandle , IUnknown * parent ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-03-02 13:16:10 +01:00
IWineD3DIndexBufferImpl * object ;
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 */
2006-03-09 23:21:16 +01:00
D3DCREATERESOURCEOBJECTINSTANCE ( object , IndexBuffer , WINED3DRTYPE_INDEXBUFFER , Length )
2007-02-19 15:25:32 +01:00
if ( Pool = = WINED3DPOOL_DEFAULT ) { /* We need a local copy for drawStridedSlow */
2005-07-13 13:34:55 +02:00
object - > resource . allocatedMemory = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , object - > resource . size ) ;
}
2004-11-24 19:13:41 +01:00
2007-02-19 15:25:32 +01:00
if ( Pool ! = WINED3DPOOL_SYSTEMMEM & & ! ( Usage & WINED3DUSAGE_DYNAMIC ) & & GL_SUPPORT ( ARB_VERTEX_BUFFER_OBJECT ) ) {
CreateIndexBufferVBO ( This , object ) ;
}
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p \n " , This , Length , Usage , Format ,
2005-03-29 21:01:00 +02:00
debug_d3dformat ( Format ) , Pool , object , object - > resource . allocatedMemory ) ;
2004-11-24 19:13:41 +01:00
* ppIndexBuffer = ( IWineD3DIndexBuffer * ) object ;
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 ;
2005-09-21 12:19:29 +02:00
int i , j ;
2006-07-19 06:06:07 +02:00
HRESULT temp_result ;
2005-03-02 13:16:10 +01:00
D3DCREATEOBJECTINSTANCE ( object , StateBlock )
2005-07-13 16:15:54 +02:00
object - > blockType = Type ;
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 ] ) ;
}
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 */
2005-07-26 20:49:30 +02:00
if ( Type = = WINED3DSBT_INIT ) {
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
}
2006-07-19 06:06:07 +02:00
temp_result = allocate_shader_constants ( object ) ;
if ( WINED3D_OK ! = temp_result )
return temp_result ;
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 + + ) {
for ( j = 1 ; j < = WINED3D_HIGHEST_TEXTURE_STATE ; j + + ) {
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 ] ) {
IWineD3DVertexBuffer_AddRef ( object - > streamSource [ i ] ) ;
}
}
2007-08-19 20:42:29 +02:00
if ( object - > pIndexData ) {
IWineD3DIndexBuffer_AddRef ( object - > pIndexData ) ;
}
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 */
2007-08-03 20:26:29 +02:00
for ( i = 0 ; i < GL_LIMITS ( vshader_constantsF ) ; + + i ) {
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
}
object - > num_contained_ps_consts_f = GL_LIMITS ( vshader_constantsF ) ;
2007-08-03 20:12:54 +02:00
for ( i = 0 ; i < MAX_CONST_B ; + + i ) {
object - > contained_ps_consts_b [ i ] = i ;
2006-06-06 08:46:59 +02:00
object - > changed . pixelShaderConstantsB [ i ] = TRUE ;
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 ;
2006-06-06 08:46:59 +02:00
object - > changed . pixelShaderConstantsI [ i ] = TRUE ;
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 + + ) {
object - > changed . renderState [ SavedPixelStates_R [ i ] ] = TRUE ;
2007-07-31 15:04:56 +02:00
object - > contained_render_states [ i ] = SavedPixelStates_R [ i ] ;
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 + + ) {
object - > changed . textureState [ j ] [ SavedPixelStates_T [ i ] ] = TRUE ;
2007-08-09 17:45:29 +02:00
object - > contained_tss_states [ object - > num_contained_tss_states ] . stage = j ;
object - > contained_tss_states [ object - > num_contained_tss_states ] . state = SavedPixelStates_T [ i ] ;
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 + + ) {
object - > changed . samplerState [ j ] [ SavedPixelStates_S [ i ] ] = TRUE ;
2007-08-03 20:23:52 +02:00
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . stage = j ;
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . state = SavedPixelStates_S [ i ] ;
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 ) {
2006-06-06 08:46:59 +02:00
object - > changed . vertexShaderConstantsB [ i ] = TRUE ;
2007-08-03 20:07:30 +02:00
object - > contained_vs_consts_b [ i ] = i ;
}
object - > num_contained_vs_consts_b = MAX_CONST_B ;
for ( i = 0 ; i < MAX_CONST_I ; + + i ) {
2006-06-06 08:46:59 +02:00
object - > changed . vertexShaderConstantsI [ i ] = TRUE ;
2007-08-03 20:07:30 +02:00
object - > contained_vs_consts_i [ i ] = i ;
}
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 + + ) {
object - > changed . renderState [ SavedVertexStates_R [ i ] ] = TRUE ;
2007-07-31 15:04:56 +02:00
object - > contained_render_states [ i ] = SavedVertexStates_R [ i ] ;
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 + + ) {
object - > changed . textureState [ j ] [ SavedVertexStates_T [ i ] ] = TRUE ;
2007-08-09 17:45:29 +02:00
object - > contained_tss_states [ object - > num_contained_tss_states ] . stage = j ;
object - > contained_tss_states [ object - > num_contained_tss_states ] . state = SavedVertexStates_T [ i ] ;
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 + + ) {
object - > changed . samplerState [ j ] [ SavedVertexStates_S [ i ] ] = TRUE ;
2007-08-03 20:23:52 +02:00
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . stage = j ;
object - > contained_sampler_states [ object - > num_contained_sampler_states ] . state = SavedVertexStates_S [ i ] ;
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 ] ) {
IWineD3DVertexBuffer_AddRef ( object - > streamSource [ i ] ) ;
}
}
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
}
2005-03-02 13:16:10 +01:00
/* ************************************
MSDN :
[ in ] Render targets are not lockable unless the application specifies TRUE for Lockable . Note that lockable render targets reduce performance on some graphics hardware .
Discard
[ in ] Set this flag to TRUE to enable z - buffer discarding , and FALSE otherwise .
If this flag is set , the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9 : : Present or IDirect3DDevice9 : : SetDepthStencilSurface with a different depth surface .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface ( IWineD3DDevice * iface , UINT Width , UINT Height , WINED3DFORMAT Format , BOOL Lockable , BOOL Discard , UINT Level , IWineD3DSurface * * ppSurface , WINED3DRESOURCETYPE Type , DWORD Usage , WINED3DPOOL Pool , WINED3DMULTISAMPLE_TYPE MultiSample , DWORD MultisampleQuality , HANDLE * pSharedHandle , WINED3DSURFTYPE Impl , IUnknown * parent ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSurfaceImpl * object ; /*NOTE: impl ref allowed since this is a create function */
2005-07-13 13:34:55 +02:00
unsigned int Size = 1 ;
2007-07-27 13:22:54 +02:00
const StaticPixelFormatDesc * tableEntry = getFormatDescEntry ( Format , NULL , NULL ) ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) Create surface \n " , This ) ;
2005-01-09 18:37:02 +01:00
2005-03-02 13:16:10 +01:00
/** FIXME: Check ranges on the inputs are valid
* MSDN
* MultisampleQuality
* [ in ] Quality level . The valid range is between zero and one less than the level
* returned by pQualityLevels used by IDirect3D9 : : CheckDeviceMultiSampleType .
2006-04-07 12:51:12 +02:00
* Passing a larger value returns the error WINED3DERR_INVALIDCALL . The MultisampleQuality
2005-03-02 13:16:10 +01:00
* values of paired render targets , depth stencil surfaces , and the MultiSample type
* must all match .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* TODO : Discard MSDN
2005-07-13 16:15:54 +02:00
* [ in ] Set this flag to TRUE to enable z - buffer discarding , and FALSE otherwise .
2005-03-02 13:16:10 +01:00
*
* If this flag is set , the contents of the depth stencil buffer will be
* invalid after calling either IDirect3DDevice9 : : Present or * IDirect3DDevice9 : : SetDepthStencilSurface
* with a different depth surface .
*
* This flag has the same behavior as the constant , D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL , in D3DPRESENTFLAG .
* * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-13 16:15:54 +02:00
if ( MultisampleQuality < 0 ) {
2006-10-01 05:20:10 +02:00
FIXME ( " Invalid multisample level %d \n " , MultisampleQuality ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ; /* TODO: Check that this is the case! */
2005-01-09 18:37:02 +01:00
}
2005-07-13 16:15:54 +02:00
if ( MultisampleQuality > 0 ) {
2006-10-01 05:20:10 +02:00
FIXME ( " MultisampleQuality set to %d, substituting 0 \n " , MultisampleQuality ) ;
2005-03-02 13:16:10 +01:00
MultisampleQuality = 0 ;
2005-01-09 18:37:02 +01:00
}
2005-07-30 21:05:58 +02:00
/** FIXME: Check that the format is supported
* by the device .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-13 13:34:55 +02:00
/** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
* it is based around 4 x4 pixel blocks it requires padding , so allocate enough
* space !
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-11-02 21:01:54 +01:00
if ( WINED3DFMT_UNKNOWN = = Format ) {
Size = 0 ;
} else if ( Format = = WINED3DFMT_DXT1 ) {
2005-07-13 13:34:55 +02:00
/* DXT1 is half byte per pixel */
2007-02-13 20:21:48 +01:00
Size = ( ( max ( Width , 4 ) * tableEntry - > bpp ) * max ( Height , 4 ) ) > > 1 ;
2005-07-13 13:34:55 +02:00
} else if ( Format = = WINED3DFMT_DXT2 | | Format = = WINED3DFMT_DXT3 | |
Format = = WINED3DFMT_DXT4 | | Format = = WINED3DFMT_DXT5 ) {
2007-02-13 20:21:48 +01:00
Size = ( ( max ( Width , 4 ) * tableEntry - > bpp ) * max ( Height , 4 ) ) ;
2005-07-13 13:34:55 +02:00
} else {
2006-09-24 09:49:05 +02:00
/* The pitch is a multiple of 4 bytes */
2007-06-08 22:28:04 +02:00
Size = ( ( Width * tableEntry - > bpp ) + This - > surface_alignment - 1 ) & ~ ( This - > surface_alignment - 1 ) ;
2007-02-13 20:21:48 +01:00
Size * = Height ;
2005-07-13 13:34:55 +02:00
}
2005-11-23 20:14:43 +01:00
/** Create and initialise the surface resource **/
2006-03-09 23:21:16 +01:00
D3DCREATERESOURCEOBJECTINSTANCE ( object , Surface , WINED3DRTYPE_SURFACE , Size )
2006-02-07 12:26:26 +01:00
/* "Standalone" surface */
IWineD3DSurface_SetContainer ( ( IWineD3DSurface * ) object , NULL ) ;
2005-07-11 22:38:27 +02:00
2005-03-02 13:16:10 +01:00
object - > currentDesc . Width = Width ;
object - > currentDesc . Height = Height ;
object - > currentDesc . MultiSampleType = MultiSample ;
object - > currentDesc . MultiSampleQuality = MultisampleQuality ;
2005-07-11 22:38:27 +02:00
object - > glDescription . level = Level ;
2006-05-06 16:15:37 +02:00
/* Flags */
2007-05-26 19:45:02 +02:00
object - > Flags = 0 ;
2006-05-06 16:15:37 +02:00
object - > Flags | = Discard ? SFLAG_DISCARD : 0 ;
object - > Flags | = ( WINED3DFMT_D16_LOCKABLE = = Format ) ? SFLAG_LOCKABLE : 0 ;
object - > Flags | = Lockable ? SFLAG_LOCKABLE : 0 ;
2005-11-02 21:01:54 +01:00
if ( WINED3DFMT_UNKNOWN ! = Format ) {
2006-06-21 10:36:14 +02:00
object - > bytesPerPixel = tableEntry - > bpp ;
2005-11-02 21:01:54 +01:00
} else {
object - > bytesPerPixel = 0 ;
}
2005-07-11 16:25:54 +02:00
/** TODO: change this into a texture transform matrix so that it's processed in hardware **/
2006-10-05 11:11:03 +02:00
TRACE ( " Pool %d %d %d %d \n " , Pool , WINED3DPOOL_DEFAULT , WINED3DPOOL_MANAGED , WINED3DPOOL_SYSTEMMEM ) ;
2005-01-17 14:44:57 +01:00
2006-10-13 02:19:42 +02:00
/** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
* this function is too deep to need to care about things like this .
* Levels need to be checked too , and possibly Type since they all affect what can be done .
2005-03-02 13:16:10 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
switch ( Pool ) {
2006-03-28 14:20:47 +02:00
case WINED3DPOOL_SCRATCH :
2006-09-26 20:31:58 +02:00
if ( ! Lockable )
2007-01-09 23:42:26 +01:00
FIXME ( " Create surface called with a pool of SCRATCH and a Lockable of FALSE "
" which are mutually exclusive, setting lockable to TRUE \n " ) ;
2005-03-02 13:16:10 +01:00
Lockable = TRUE ;
break ;
2006-03-28 14:20:47 +02:00
case WINED3DPOOL_SYSTEMMEM :
2007-01-09 23:42:26 +01:00
if ( ! Lockable ) FIXME ( " Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
" this is acceptable but unexpected (I can't know how the surface can be usable!) \n " ) ;
2006-03-28 14:20:47 +02:00
case WINED3DPOOL_MANAGED :
2007-01-09 23:42:26 +01:00
if ( Usage = = WINED3DUSAGE_DYNAMIC ) FIXME ( " Create surface called with a pool of MANAGED and a "
" Usage of DYNAMIC which are mutually exclusive, not doing "
" anything just telling you. \n " ) ;
2005-07-13 16:15:54 +02:00
break ;
2006-03-28 14:20:47 +02:00
case WINED3DPOOL_DEFAULT : /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
2006-03-06 23:08:42 +01:00
if ( ! ( Usage & WINED3DUSAGE_DYNAMIC ) & & ! ( Usage & WINED3DUSAGE_RENDERTARGET )
2006-05-24 10:46:06 +02:00
& & ! ( Usage & & WINED3DUSAGE_DEPTHSTENCIL ) & & Lockable )
2006-05-24 17:33:34 +02:00
WARN ( " Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage. \n " ) ;
2005-03-02 13:16:10 +01:00
break ;
2005-07-13 16:15:54 +02:00
default :
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) Unknown pool %d \n " , This , Pool ) ;
break ;
} ;
2005-07-13 16:15:54 +02:00
2006-03-28 14:20:47 +02:00
if ( Usage & WINED3DUSAGE_RENDERTARGET & & Pool ! = WINED3DPOOL_DEFAULT ) {
2005-03-02 13:16:10 +01:00
FIXME ( " Trying to create a render target that isn't in the default pool \n " ) ;
}
2005-01-17 14:44:57 +01:00
2006-10-13 02:19:42 +02:00
/* mark the texture as dirty so that it gets loaded first time around*/
2005-06-23 18:44:19 +02:00
IWineD3DSurface_AddDirtyRect ( * ppSurface , NULL ) ;
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes \n " ,
This , Width , Height , Format , debug_d3dformat ( Format ) ,
2005-03-29 21:01:00 +02:00
( WINED3DFMT_D16_LOCKABLE = = Format ) , * ppSurface , object - > resource . allocatedMemory , object - > resource . size ) ;
2006-05-13 22:22:16 +02:00
/* Store the DirectDraw primary surface. This is the first rendertarget surface created */
if ( ( Usage & WINED3DUSAGE_RENDERTARGET ) & & ( ! This - > ddraw_primary ) )
This - > ddraw_primary = ( IWineD3DSurface * ) object ;
/* Look at the implementation and set the correct Vtable */
switch ( Impl ) {
case SURFACE_OPENGL :
2007-07-16 20:53:44 +02:00
/* Check if a 3D adapter is available when creating gl surfaces */
if ( ! This - > adapter ) {
ERR ( " OpenGL surfaces are not available without opengl \n " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , object - > resource . allocatedMemory ) ;
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
return WINED3DERR_NOTAVAILABLE ;
}
2006-05-13 22:22:16 +02:00
break ;
case SURFACE_GDI :
object - > lpVtbl = & IWineGDISurface_Vtbl ;
break ;
default :
/* To be sure to catch this */
ERR ( " Unknown requested surface implementation %d! \n " , Impl ) ;
IWineD3DSurface_Release ( ( IWineD3DSurface * ) object ) ;
return WINED3DERR_INVALIDCALL ;
}
2007-04-09 01:53:32 +02:00
list_init ( & object - > renderbuffers ) ;
2006-05-13 22:22:16 +02:00
/* Call the private setup routine */
return IWineD3DSurface_PrivateSetup ( ( IWineD3DSurface * ) object ) ;
2005-03-02 13:16:10 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture ( IWineD3DDevice * iface , UINT Width , UINT Height , UINT Levels ,
2006-03-28 14:20:47 +02:00
DWORD Usage , WINED3DFORMAT Format , WINED3DPOOL Pool ,
2005-03-02 13:16:10 +01:00
IWineD3DTexture * * ppTexture , HANDLE * pSharedHandle , IUnknown * parent ,
D3DCB_CREATESURFACEFN D3DCB_CreateSurface ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
IWineD3DTextureImpl * object ;
2005-03-02 13:16:10 +01:00
unsigned int i ;
UINT tmpW ;
UINT tmpH ;
HRESULT hr ;
2006-09-26 20:31:48 +02:00
unsigned int pow2Width ;
unsigned int pow2Height ;
2007-09-21 23:47:40 +02:00
const GlPixelFormatDesc * glDesc ;
getFormatDescEntry ( Format , & GLINFO_LOCATION , & glDesc ) ;
2005-08-03 21:49:05 +02:00
2005-03-02 13:16:10 +01: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 ) ;
2006-07-30 23:26:21 +02:00
TRACE ( " Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p \n " ,
Format , debug_d3dformat ( Format ) , Pool , ppTexture , pSharedHandle , parent ) ;
2005-01-17 14:44:57 +01:00
2005-11-17 12:40:43 +01:00
/* TODO: It should only be possible to create textures for formats
that are reported as supported */
if ( WINED3DFMT_UNKNOWN > = Format ) {
2006-10-11 03:51:13 +02:00
WARN ( " (%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-11-17 12:40:43 +01:00
}
2006-03-09 23:21:16 +01:00
D3DCREATERESOURCEOBJECTINSTANCE ( object , Texture , WINED3DRTYPE_TEXTURE , 0 ) ;
2005-11-23 20:14:43 +01:00
D3DINITIALIZEBASETEXTURE ( object - > baseTexture ) ;
2005-01-17 14:44:57 +01:00
object - > width = Width ;
object - > height = Height ;
2005-08-03 21:49:05 +02:00
/** Non-power2 support **/
2007-02-13 20:21:48 +01:00
if ( GL_SUPPORT ( ARB_TEXTURE_NON_POWER_OF_TWO ) ) {
2006-09-26 20:31:48 +02:00
pow2Width = Width ;
pow2Height = Height ;
} else {
/* Find the nearest pow2 match */
pow2Width = pow2Height = 1 ;
while ( pow2Width < Width ) pow2Width < < = 1 ;
while ( pow2Height < Height ) pow2Height < < = 1 ;
}
2005-08-03 21:49:05 +02:00
/** FIXME: add support for real non-power-two if it's provided by the video card **/
/* Precalculated scaling for 'faked' non power of two texture coords */
object - > pow2scalingFactorX = ( ( ( float ) Width ) / ( ( float ) pow2Width ) ) ;
object - > pow2scalingFactorY = ( ( ( float ) Height ) / ( ( float ) pow2Height ) ) ;
2005-11-10 13:14:56 +01:00
TRACE ( " xf(%f) yf(%f) \n " , object - > pow2scalingFactorX , object - > pow2scalingFactorY ) ;
2005-08-03 21:49:05 +02:00
2005-01-17 14:44:57 +01:00
/* Calculate levels for mip mapping */
2007-08-31 20:56:15 +02:00
if ( Usage & WINED3DUSAGE_AUTOGENMIPMAP ) {
if ( ! GL_SUPPORT ( SGIS_GENERATE_MIPMAP ) ) {
WARN ( " No mipmap generation support, returning D3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
if ( Levels > 1 ) {
WARN ( " D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
object - > baseTexture . levels = 1 ;
} else if ( Levels = = 0 ) {
2005-03-02 13:16:10 +01:00
TRACE ( " calculating levels %d \n " , object - > baseTexture . levels ) ;
2005-01-17 14:44:57 +01:00
object - > baseTexture . levels + + ;
tmpW = Width ;
tmpH = Height ;
2006-04-21 10:21:47 +02:00
while ( tmpW > 1 | | tmpH > 1 ) {
2005-03-02 13:16:10 +01:00
tmpW = max ( 1 , tmpW > > 1 ) ;
tmpH = max ( 1 , tmpH > > 1 ) ;
2005-01-17 14:44:57 +01:00
object - > baseTexture . levels + + ;
}
TRACE ( " Calculated levels = %d \n " , object - > baseTexture . levels ) ;
}
2005-07-13 16:15:54 +02:00
2005-01-17 14:44:57 +01:00
/* Generate all the surfaces */
tmpW = Width ;
tmpH = Height ;
2005-07-13 16:15:54 +02:00
for ( i = 0 ; i < object - > baseTexture . levels ; i + + )
2005-01-17 14:44:57 +01:00
{
2005-03-02 13:16:10 +01:00
/* use the callback to create the texture surface */
2007-04-24 10:29:22 +02:00
hr = D3DCB_CreateSurface ( This - > parent , parent , tmpW , tmpH , Format , Usage , Pool , i , WINED3DCUBEMAP_FACE_POSITIVE_X , & object - > surfaces [ i ] , NULL ) ;
2006-05-19 00:13:29 +02:00
if ( hr ! = WINED3D_OK | | ( ( IWineD3DSurfaceImpl * ) object - > surfaces [ i ] ) - > Flags & SFLAG_OVERSIZE ) {
2005-11-10 13:14:56 +01:00
FIXME ( " Failed to create surface %p \n " , object ) ;
2005-03-02 13:16:10 +01:00
/* clean up */
2006-05-29 22:51:33 +02:00
object - > surfaces [ i ] = NULL ;
IWineD3DTexture_Release ( ( IWineD3DTexture * ) object ) ;
2005-01-17 14:44:57 +01:00
2005-03-02 13:16:10 +01:00
* ppTexture = NULL ;
return hr ;
2005-01-18 12:42:29 +01:00
}
2005-07-13 16:15:54 +02:00
2006-02-06 11:30:48 +01:00
IWineD3DSurface_SetContainer ( object - > surfaces [ i ] , ( IWineD3DBase * ) object ) ;
2005-03-02 13:16:10 +01:00
TRACE ( " Created surface level %d @ %p \n " , i , object - > surfaces [ i ] ) ;
/* calculate the next mipmap level */
tmpW = max ( 1 , tmpW > > 1 ) ;
tmpH = max ( 1 , tmpH > > 1 ) ;
2005-01-17 14:44:57 +01:00
}
2007-09-21 23:47:40 +02:00
object - > baseTexture . shader_conversion_group = glDesc - > conversion_group ;
2005-07-13 16:15:54 +02:00
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) : Created texture %p \n " , This , 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_CreateVolumeTexture ( IWineD3DDevice * iface ,
2005-07-13 16:15:54 +02:00
UINT Width , UINT Height , UINT Depth ,
UINT Levels , DWORD Usage ,
2006-03-28 14:20:47 +02:00
WINED3DFORMAT Format , WINED3DPOOL Pool ,
2005-08-22 11:13:49 +02:00
IWineD3DVolumeTexture * * ppVolumeTexture ,
HANDLE * pSharedHandle , IUnknown * parent ,
2005-01-17 14:44:57 +01:00
D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DVolumeTextureImpl * object ;
unsigned int i ;
UINT tmpW ;
UINT tmpH ;
UINT tmpD ;
2007-09-21 23:47:40 +02:00
const GlPixelFormatDesc * glDesc ;
getFormatDescEntry ( Format , & GLINFO_LOCATION , & glDesc ) ;
2005-01-17 14:44:57 +01:00
2005-11-17 12:40:43 +01:00
/* TODO: It should only be possible to create textures for formats
that are reported as supported */
if ( WINED3DFMT_UNKNOWN > = Format ) {
2006-10-11 03:51:13 +02:00
WARN ( " (%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-11-17 12:40:43 +01:00
}
2006-03-09 23:21:16 +01:00
D3DCREATERESOURCEOBJECTINSTANCE ( object , VolumeTexture , WINED3DRTYPE_VOLUMETEXTURE , 0 ) ;
2005-11-23 20:14:43 +01:00
D3DINITIALIZEBASETEXTURE ( object - > baseTexture ) ;
2005-07-13 16:15:54 +02:00
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s) \n " , This , Width , Height ,
2005-01-17 14:44:57 +01:00
Depth , Levels , Usage , Format , debug_d3dformat ( Format ) , debug_d3dpool ( Pool ) ) ;
object - > width = Width ;
object - > height = Height ;
object - > depth = Depth ;
/* Calculate levels for mip mapping */
2007-08-31 20:56:15 +02:00
if ( Usage & WINED3DUSAGE_AUTOGENMIPMAP ) {
if ( ! GL_SUPPORT ( SGIS_GENERATE_MIPMAP ) ) {
WARN ( " No mipmap generation support, returning D3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
if ( Levels > 1 ) {
WARN ( " D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL \n " ) ;
return WINED3DERR_INVALIDCALL ;
}
Levels = 1 ;
} else if ( Levels = = 0 ) {
2005-01-17 14:44:57 +01:00
object - > baseTexture . levels + + ;
tmpW = Width ;
tmpH = Height ;
tmpD = Depth ;
2006-04-21 10:21:47 +02:00
while ( tmpW > 1 | | tmpH > 1 | | tmpD > 1 ) {
2005-03-14 11:12:52 +01:00
tmpW = max ( 1 , tmpW > > 1 ) ;
tmpH = max ( 1 , tmpH > > 1 ) ;
tmpD = max ( 1 , tmpD > > 1 ) ;
2005-01-17 14:44:57 +01:00
object - > baseTexture . levels + + ;
}
TRACE ( " Calculated levels = %d \n " , object - > baseTexture . levels ) ;
}
/* Generate all the surfaces */
tmpW = Width ;
tmpH = Height ;
tmpD = Depth ;
2005-07-13 16:15:54 +02:00
for ( i = 0 ; i < object - > baseTexture . levels ; i + + )
2005-01-17 14:44:57 +01:00
{
2007-02-19 15:18:45 +01:00
HRESULT hr ;
2005-03-14 11:12:52 +01:00
/* Create the volume */
2007-04-23 22:02:55 +02:00
hr = D3DCB_CreateVolume ( This - > parent , parent , tmpW , tmpH , tmpD , Format , Pool , Usage ,
2007-02-19 15:18:45 +01:00
( IWineD3DVolume * * ) & object - > volumes [ i ] , pSharedHandle ) ;
if ( FAILED ( hr ) ) {
ERR ( " Creating a volume for the volume texture failed(%08x) \n " , hr ) ;
IWineD3DVolumeTexture_Release ( ( IWineD3DVolumeTexture * ) object ) ;
* ppVolumeTexture = NULL ;
return hr ;
}
2005-08-03 21:49:05 +02:00
2006-10-13 02:19:42 +02:00
/* Set its container to this object */
2006-02-06 11:30:48 +01:00
IWineD3DVolume_SetContainer ( object - > volumes [ i ] , ( IWineD3DBase * ) object ) ;
2005-01-17 14:44:57 +01:00
2005-08-03 21:49:05 +02:00
/* calcualte the next mipmap level */
2005-03-14 11:12:52 +01:00
tmpW = max ( 1 , tmpW > > 1 ) ;
tmpH = max ( 1 , tmpH > > 1 ) ;
tmpD = max ( 1 , tmpD > > 1 ) ;
2005-01-17 14:44:57 +01:00
}
2007-09-21 23:47:40 +02:00
object - > baseTexture . shader_conversion_group = glDesc - > conversion_group ;
2005-01-17 14:44:57 +01:00
* ppVolumeTexture = ( IWineD3DVolumeTexture * ) object ;
TRACE ( " (%p) : Created volume texture %p \n " , This , 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_CreateVolume ( IWineD3DDevice * iface ,
2005-07-13 16:15:54 +02:00
UINT Width , UINT Height , UINT Depth ,
DWORD Usage ,
2006-03-28 14:20:47 +02:00
WINED3DFORMAT Format , WINED3DPOOL Pool ,
2005-01-17 14:44:57 +01:00
IWineD3DVolume * * ppVolume ,
HANDLE * pSharedHandle , IUnknown * parent ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-03-02 13:16:10 +01:00
IWineD3DVolumeImpl * object ; /** NOTE: impl ref allowed since this is a create function **/
2007-07-27 13:22:54 +02:00
const StaticPixelFormatDesc * formatDesc = getFormatDescEntry ( Format , NULL , NULL ) ;
2005-01-17 14:44:57 +01:00
2006-06-21 10:36:14 +02:00
D3DCREATERESOURCEOBJECTINSTANCE ( object , Volume , WINED3DRTYPE_VOLUME , ( ( Width * formatDesc - > bpp ) * Height * Depth ) )
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 ;
2006-06-21 10:36:14 +02:00
object - > bytesPerPixel = formatDesc - > bpp ;
2005-03-02 13:16:10 +01:00
/** 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 ;
return IWineD3DVolume_AddDirtyBox ( ( IWineD3DVolume * ) object , NULL ) ;
2005-01-17 14:44:57 +01:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture ( IWineD3DDevice * iface , UINT EdgeLength ,
2005-07-13 16:15:54 +02:00
UINT Levels , DWORD Usage ,
2006-03-28 14:20:47 +02:00
WINED3DFORMAT Format , WINED3DPOOL Pool ,
2005-08-22 11:13:49 +02:00
IWineD3DCubeTexture * * ppCubeTexture ,
HANDLE * pSharedHandle , IUnknown * parent ,
2005-01-17 14:44:57 +01:00
D3DCB_CREATESURFACEFN D3DCB_CreateSurface ) {
2005-08-03 21:49:05 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DCubeTextureImpl * object ; /** NOTE: impl ref allowed since this is a create function **/
2005-08-22 11:13:49 +02:00
unsigned int i , j ;
2005-08-03 21:49:05 +02:00
UINT tmpW ;
HRESULT hr ;
unsigned int pow2EdgeLength = EdgeLength ;
2007-09-21 23:47:40 +02:00
const GlPixelFormatDesc * glDesc ;
getFormatDescEntry ( Format , & GLINFO_LOCATION , & glDesc ) ;
2005-08-03 21:49:05 +02:00
2005-11-17 12:40:43 +01:00
/* TODO: It should only be possible to create textures for formats
that are reported as supported */
if ( WINED3DFMT_UNKNOWN > = Format ) {
2006-10-11 03:51:13 +02:00
WARN ( " (%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-11-17 12:40:43 +01:00
}
2007-03-30 21:29:38 +02:00
if ( ! GL_SUPPORT ( ARB_TEXTURE_CUBE_MAP ) & & Pool ! = WINED3DPOOL_SCRATCH ) {
WARN ( " (%p) : Tried to create not supported cube texture \n " , This ) ;
return WINED3DERR_INVALIDCALL ;
}
2006-03-09 23:21:16 +01:00
D3DCREATERESOURCEOBJECTINSTANCE ( object , CubeTexture , WINED3DRTYPE_CUBETEXTURE , 0 ) ;
2005-11-23 20:14:43 +01:00
D3DINITIALIZEBASETEXTURE ( object - > baseTexture ) ;
2005-08-03 21:49:05 +02:00
2005-11-10 13:14:56 +01:00
TRACE ( " (%p) Create Cube Texture \n " , This ) ;
2005-08-03 21:49:05 +02:00
/** Non-power2 support **/
/* Find the nearest pow2 match */
pow2EdgeLength = 1 ;
while ( pow2EdgeLength < EdgeLength ) pow2EdgeLength < < = 1 ;
2005-08-22 11:13:49 +02:00
object - > edgeLength = EdgeLength ;
2005-08-03 21:49:05 +02:00
/* TODO: support for native non-power 2 */
/* Precalculated scaling for 'faked' non power of two texture coords */
object - > pow2scalingFactor = ( ( float ) EdgeLength ) / ( ( float ) pow2EdgeLength ) ;
/* Calculate levels for mip mapping */
2007-08-31 20:56:15 +02:00
if ( Usage & WINED3DUSAGE_AUTOGENMIPMAP ) {
if ( ! GL_SUPPORT ( SGIS_GENERATE_MIPMAP ) ) {
WARN ( " No mipmap generation support, returning D3DERR_INVALIDCALL \n " ) ;
2007-10-19 05:39:22 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppCubeTexture = NULL ;
2007-08-31 20:56:15 +02:00
return WINED3DERR_INVALIDCALL ;
}
if ( Levels > 1 ) {
WARN ( " D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL \n " ) ;
2007-10-19 05:39:22 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppCubeTexture = NULL ;
2007-08-31 20:56:15 +02:00
return WINED3DERR_INVALIDCALL ;
}
Levels = 1 ;
} else if ( Levels = = 0 ) {
2005-08-03 21:49:05 +02:00
object - > baseTexture . levels + + ;
tmpW = EdgeLength ;
while ( tmpW > 1 ) {
2005-08-22 11:13:49 +02:00
tmpW = max ( 1 , tmpW > > 1 ) ;
2005-08-03 21:49:05 +02:00
object - > baseTexture . levels + + ;
}
TRACE ( " Calculated levels = %d \n " , object - > baseTexture . levels ) ;
}
2005-01-17 14:44:57 +01:00
/* Generate all the surfaces */
tmpW = EdgeLength ;
for ( i = 0 ; i < object - > baseTexture . levels ; i + + ) {
/* Create the 6 faces */
for ( j = 0 ; j < 6 ; j + + ) {
2005-07-13 16:15:54 +02:00
2006-12-03 21:52:03 +01:00
hr = D3DCB_CreateSurface ( This - > parent , parent , tmpW , tmpW , Format , Usage , Pool ,
2007-04-24 10:29:22 +02:00
i /* Level */ , j , & object - > surfaces [ j ] [ i ] , pSharedHandle ) ;
2005-07-13 16:15:54 +02:00
2006-04-07 12:51:12 +02:00
if ( hr ! = WINED3D_OK ) {
2005-03-02 13:16:10 +01:00
/* clean up */
int k ;
2005-03-14 11:12:52 +01:00
int l ;
2005-08-22 11:13:49 +02:00
for ( l = 0 ; l < j ; l + + ) {
2007-10-19 05:39:22 +02:00
IWineD3DSurface_Release ( object - > surfaces [ l ] [ i ] ) ;
2005-03-14 11:12:52 +01:00
}
2005-08-22 11:13:49 +02:00
for ( k = 0 ; k < i ; k + + ) {
for ( l = 0 ; l < 6 ; l + + ) {
2007-10-19 05:39:22 +02:00
IWineD3DSurface_Release ( object - > surfaces [ l ] [ k ] ) ;
2005-03-02 13:16:10 +01:00
}
}
2005-03-14 11:12:52 +01:00
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) Failed to create surface \n " , object ) ;
HeapFree ( GetProcessHeap ( ) , 0 , object ) ;
* ppCubeTexture = NULL ;
return hr ;
2005-03-14 11:12:52 +01:00
}
2006-02-06 11:30:48 +01:00
IWineD3DSurface_SetContainer ( object - > surfaces [ j ] [ i ] , ( IWineD3DBase * ) object ) ;
2005-11-10 13:14:56 +01:00
TRACE ( " Created surface level %d @ %p, \n " , i , object - > surfaces [ j ] [ i ] ) ;
2005-01-17 14:44:57 +01:00
}
2005-03-14 11:12:52 +01:00
tmpW = max ( 1 , tmpW > > 1 ) ;
2005-01-17 14:44:57 +01:00
}
2007-09-21 23:47:40 +02:00
object - > baseTexture . shader_conversion_group = glDesc - > conversion_group ;
2005-01-17 14:44:57 +01:00
TRACE ( " (%p) : Created Cube Texture %p \n " , This , object ) ;
* 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 ;
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 " ) ;
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 ) ;
}
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 :
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 ;
}
D3DCREATEOBJECTINSTANCE ( object , Query )
object - > type = Type ;
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 ) ;
2006-07-25 00:51:33 +02:00
GL_EXTCALL ( glGenQueriesARB ( 1 , & ( ( WineQueryOcclusionData * ) ( object - > extendedData ) ) - > queryId ) ) ;
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 ;
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 " ) ;
}
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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow ( IWineD3DDevice * iface , HWND window ) {
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 ;
/* Filter out window decorations */
style & = ~ WS_CAPTION ;
style & = ~ WS_THICKFRAME ;
exStyle & = ~ WS_EX_WINDOWEDGE ;
exStyle & = ~ WS_EX_CLIENTEDGE ;
/* Make sure the window is managed, otherwise we won't get keyboard input */
style | = WS_POPUP | WS_SYSMENU ;
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 ,
This - > ddraw_width , This - > ddraw_height , SWP_FRAMECHANGED ) ;
2007-02-22 11:20:35 +01:00
ShowWindow ( window , SW_NORMAL ) ;
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
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void WINAPI IWineD3DDeviceImpl_RestoreWindow ( IWineD3DDevice * iface , HWND window ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
/* 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 ) ;
SetWindowLongW ( window , GWL_STYLE , This - > style ) ;
SetWindowLongW ( window , GWL_EXSTYLE , This - > exStyle ) ;
/* 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 */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain ( IWineD3DDevice * iface , WINED3DPRESENT_PARAMETERS * pPresentationParameters , IWineD3DSwapChain * * ppSwapChain ,
2005-03-02 13:16:10 +01:00
IUnknown * parent ,
D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget ,
2005-07-13 16:15:54 +02:00
D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil ) {
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 **/
2006-04-07 12:51:12 +02:00
HRESULT hr = WINED3D_OK ;
2007-02-12 19:22:41 +01:00
IUnknown * bufferParent ;
2005-06-23 13:05:24 +02:00
TRACE ( " (%p) : Created Aditional Swap Chain \n " , This ) ;
/** 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
}
2005-06-23 13:05:24 +02:00
D3DCREATEOBJECTINSTANCE ( object , SwapChain )
/*********************
* 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 ;
}
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
object - > orig_width = GetSystemMetrics ( SM_CXSCREEN ) ;
object - > orig_height = GetSystemMetrics ( SM_CYSCREEN ) ;
2007-02-15 13:53:33 +01:00
object - > orig_fmt = pixelformat_for_depth ( GetDeviceCaps ( hDc , BITSPIXEL ) * GetDeviceCaps ( hDc , PLANES ) ) ;
2007-08-08 03:09:38 +02:00
ReleaseDC ( object - > win_handle , hDc ) ;
2006-12-08 16:13:15 +01:00
2007-02-12 19:22:41 +01:00
/** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
* then the corresponding dimension of the client area of the hDeviceWindow
* ( or the focus window , if hDeviceWindow is NULL ) is taken .
* * * * * * * * * * * * * * * * * * * * * */
2005-06-23 13:05:24 +02: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 " ) ;
hr = D3DCB_CreateRenderTarget ( ( IUnknown * ) This - > parent ,
parent ,
object - > presentParms . BackBufferWidth ,
object - > presentParms . BackBufferHeight ,
object - > presentParms . BackBufferFormat ,
object - > presentParms . MultiSampleType ,
object - > presentParms . MultiSampleQuality ,
TRUE /* Lockable */ ,
& object - > frontBuffer ,
NULL /* pShared (always null)*/ ) ;
if ( object - > frontBuffer ! = NULL ) {
2007-10-09 22:17:59 +02:00
IWineD3DSurface_ModifyLocation ( object - > frontBuffer , SFLAG_INDRAWABLE , TRUE ) ;
2007-02-12 19:22:41 +01:00
IWineD3DSurface_SetContainer ( object - > frontBuffer , ( IWineD3DBase * ) object ) ;
} else {
ERR ( " Failed to create the front buffer \n " ) ;
goto error ;
2005-06-23 13:05:24 +02:00
}
2007-02-12 19:22:41 +01: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 **/
2007-03-04 17:31:06 +01:00
object - > context = HeapAlloc ( GetProcessHeap ( ) , 0 , sizeof ( object - > context ) ) ;
2007-05-12 10:22:42 +02:00
if ( ! object - > context )
return E_OUTOFMEMORY ;
2007-03-04 17:31:06 +01:00
object - > num_contexts = 1 ;
2007-08-11 12:17:56 +02:00
object - > context [ 0 ] = CreateContext ( This , ( IWineD3DSurfaceImpl * ) object - > frontBuffer , object - > win_handle , FALSE /* pbuffer */ , pPresentationParameters ) ;
2007-05-12 10:22:42 +02:00
if ( ! object - > context [ 0 ] ) {
2007-02-12 19:22:41 +01:00
ERR ( " Failed to create a new context \n " ) ;
hr = WINED3DERR_NOTAVAILABLE ;
goto error ;
2005-06-23 13:05:24 +02:00
} else {
2007-08-08 03:09:38 +02:00
TRACE ( " Context created (HWND=%p, glContext=%p) \n " ,
object - > win_handle , object - > context [ 0 ] - > glCtx ) ;
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 ) {
2005-06-23 13:05:24 +02:00
DEVMODEW devmode ;
HDC hdc ;
int bpp = 0 ;
2006-12-29 20:25:25 +01:00
RECT clip_rc ;
2005-06-23 13:05:24 +02:00
/* Get info on the current display setup */
2007-01-02 17:16:36 +01:00
hdc = GetDC ( 0 ) ;
2005-06-23 13:05:24 +02:00
bpp = GetDeviceCaps ( hdc , BITSPIXEL ) ;
2007-01-02 17:16:36 +01:00
ReleaseDC ( 0 , hdc ) ;
2005-06-23 13:05:24 +02:00
/* Change the display settings */
2007-08-05 20:23:42 +02:00
memset ( & devmode , 0 , sizeof ( devmode ) ) ;
devmode . dmSize = sizeof ( devmode ) ;
2005-06-23 13:05:24 +02:00
devmode . dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT ;
devmode . dmBitsPerPel = ( bpp > = 24 ) ? 32 : bpp ; /* Stupid XVidMode cannot change bpp */
2007-02-15 22:36:50 +01:00
devmode . dmPelsWidth = pPresentationParameters - > BackBufferWidth ;
devmode . dmPelsHeight = pPresentationParameters - > BackBufferHeight ;
2007-08-13 16:47:17 +02:00
ChangeDisplaySettingsExW ( This - > adapter - > DeviceName , & devmode , NULL , CDS_FULLSCREEN , NULL ) ;
2005-06-23 13:05:24 +02:00
2006-05-18 22:42:22 +02:00
/* For GetDisplayMode */
This - > ddraw_width = devmode . dmPelsWidth ;
This - > ddraw_height = devmode . dmPelsHeight ;
2007-02-15 22:36:50 +01:00
This - > ddraw_format = pPresentationParameters - > BackBufferFormat ;
2006-12-29 20:25:25 +01:00
2007-02-14 17:59:08 +01:00
IWineD3DDevice_SetFullscreen ( iface , TRUE ) ;
2007-01-18 23:41:43 +01:00
2006-12-29 20:25:25 +01:00
/* And finally clip mouse to our screen */
SetRect ( & clip_rc , 0 , 0 , devmode . dmPelsWidth , devmode . dmPelsHeight ) ;
ClipCursor ( & clip_rc ) ;
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 ) {
2006-06-15 12:54:19 +02:00
int i ;
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 " ) ;
hr = D3DCB_CreateRenderTarget ( ( IUnknown * ) This - > parent ,
2006-12-03 21:52:03 +01:00
parent ,
2006-06-15 12:54:19 +02:00
object - > presentParms . BackBufferWidth ,
object - > presentParms . BackBufferHeight ,
object - > presentParms . BackBufferFormat ,
object - > presentParms . MultiSampleType ,
object - > presentParms . MultiSampleQuality ,
TRUE /* Lockable */ ,
& object - > backBuffer [ i ] ,
NULL /* pShared (always null)*/ ) ;
if ( hr = = WINED3D_OK & & object - > backBuffer [ i ] ) {
IWineD3DSurface_SetContainer ( object - > backBuffer [ i ] , ( IWineD3DBase * ) object ) ;
} 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
}
2007-02-12 19:22:41 +01:00
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 */
ENTER_GL ( ) ;
glDrawBuffer ( GL_FRONT ) ;
checkGLcall ( " glDrawBuffer(GL_FRONT) " ) ;
LEAVE_GL ( ) ;
}
2005-06-23 13:05:24 +02:00
/* Under directX swapchains share the depth stencil, so only create one depth-stencil */
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > EnableAutoDepthStencil & & hr = = WINED3D_OK ) {
2005-06-23 13:05:24 +02:00
TRACE ( " Creating depth stencil buffer \n " ) ;
if ( This - > depthStencilBuffer = = NULL ) {
hr = D3DCB_CreateDepthStencil ( ( IUnknown * ) This - > parent ,
2006-12-03 21:52:03 +01:00
parent ,
2005-06-23 13:05:24 +02:00
object - > presentParms . BackBufferWidth ,
object - > presentParms . BackBufferHeight ,
object - > presentParms . AutoDepthStencilFormat ,
object - > presentParms . MultiSampleType ,
object - > presentParms . MultiSampleQuality ,
FALSE /* FIXME: Discard */ ,
& This - > depthStencilBuffer ,
NULL /* pShared (always null)*/ ) ;
if ( This - > depthStencilBuffer ! = NULL )
2006-03-06 19:28:03 +01:00
IWineD3DSurface_SetContainer ( This - > depthStencilBuffer , 0 ) ;
2005-06-23 13:05:24 +02:00
}
/** TODO: A check on width, height and multisample types
* ( since the zbuffer must be at least as large as the render target and have the same multisample parameters )
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
object - > wantsDepthStencilBuffer = TRUE ;
} else {
object - > wantsDepthStencilBuffer = FALSE ;
}
2007-02-12 19:22:41 +01:00
TRACE ( " Created swapchain %p \n " , object ) ;
2006-06-24 11:44:11 +02:00
TRACE ( " FrontBuf @ %p, BackBuf @ %p, DepthStencil %d \n " , object - > frontBuffer , object - > backBuffer ? object - > backBuffer [ 0 ] : NULL , object - > wantsDepthStencilBuffer ) ;
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 :
if ( object - > backBuffer ) {
int i ;
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 ;
}
2007-05-12 10:22:42 +02:00
if ( 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 ,
IUnknown * parent , const WINED3DVERTEXELEMENT * elements , size_t 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 ) ;
2005-03-02 13:16:10 +01:00
D3DCREATEOBJECTINSTANCE ( object , VertexDeclaration )
2007-02-13 23:12:36 +01:00
hr = IWineD3DVertexDeclaration_SetDeclaration ( ( IWineD3DVertexDeclaration * ) object , elements , element_count ) ;
2005-03-02 13:16:10 +01:00
return hr ;
}
2007-04-25 17:04:46 +02:00
static size_t ConvertFvfToDeclaration ( DWORD fvf , WINED3DVERTEXELEMENT * * ppVertexElements ) {
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 ;
DWORD texcoords = ( fvf & 0x00FF0000 ) > > 16 ;
WINED3DVERTEXELEMENT end_element = WINED3DDECL_END ( ) ;
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 +
has_psize + has_diffuse + has_specular + num_textures + 1 ;
/* convert the declaration */
elements = HeapAlloc ( GetProcessHeap ( ) , 0 , size * sizeof ( WINED3DVERTEXELEMENT ) ) ;
if ( ! elements )
return 0 ;
memcpy ( & elements [ size - 1 ] , & end_element , sizeof ( WINED3DVERTEXELEMENT ) ) ;
idx = 0 ;
if ( has_pos ) {
if ( ! has_blend & & ( fvf & WINED3DFVF_XYZRHW ) ) {
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT4 ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_POSITIONT ;
}
else {
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT3 ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_POSITION ;
}
elements [ idx ] . UsageIndex = 0 ;
idx + + ;
}
if ( has_blend & & ( num_blends > 0 ) ) {
if ( ( ( fvf & WINED3DFVF_XYZB5 ) = = WINED3DFVF_XYZB2 ) & & ( fvf & WINED3DFVF_LASTBETA_D3DCOLOR ) )
elements [ idx ] . Type = WINED3DDECLTYPE_D3DCOLOR ;
else
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT1 + num_blends - 1 ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_BLENDWEIGHT ;
elements [ idx ] . UsageIndex = 0 ;
idx + + ;
}
if ( has_blend_idx ) {
if ( fvf & WINED3DFVF_LASTBETA_UBYTE4 | |
( ( ( fvf & WINED3DFVF_XYZB5 ) = = WINED3DFVF_XYZB2 ) & & ( fvf & WINED3DFVF_LASTBETA_D3DCOLOR ) ) )
elements [ idx ] . Type = WINED3DDECLTYPE_UBYTE4 ;
else if ( fvf & WINED3DFVF_LASTBETA_D3DCOLOR )
elements [ idx ] . Type = WINED3DDECLTYPE_D3DCOLOR ;
else
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT1 ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_BLENDINDICES ;
elements [ idx ] . UsageIndex = 0 ;
idx + + ;
}
if ( has_normal ) {
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT3 ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_NORMAL ;
elements [ idx ] . UsageIndex = 0 ;
idx + + ;
}
if ( has_psize ) {
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT1 ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_PSIZE ;
elements [ idx ] . UsageIndex = 0 ;
idx + + ;
}
if ( has_diffuse ) {
elements [ idx ] . Type = WINED3DDECLTYPE_D3DCOLOR ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_COLOR ;
elements [ idx ] . UsageIndex = 0 ;
idx + + ;
}
if ( has_specular ) {
elements [ idx ] . Type = WINED3DDECLTYPE_D3DCOLOR ;
elements [ idx ] . Usage = WINED3DDECLUSAGE_COLOR ;
elements [ idx ] . UsageIndex = 1 ;
idx + + ;
}
for ( idx2 = 0 ; idx2 < num_textures ; idx2 + + ) {
unsigned int numcoords = ( texcoords > > ( idx2 * 2 ) ) & 0x03 ;
switch ( numcoords ) {
case WINED3DFVF_TEXTUREFORMAT1 :
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT1 ;
break ;
case WINED3DFVF_TEXTUREFORMAT2 :
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT2 ;
break ;
case WINED3DFVF_TEXTUREFORMAT3 :
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT3 ;
break ;
case WINED3DFVF_TEXTUREFORMAT4 :
elements [ idx ] . Type = WINED3DDECLTYPE_FLOAT4 ;
break ;
}
elements [ idx ] . Usage = WINED3DDECLUSAGE_TEXCOORD ;
elements [ idx ] . UsageIndex = idx2 ;
idx + + ;
}
/* Now compute offsets, and initialize the rest of the fields */
for ( idx = 0 , offset = 0 ; idx < size - 1 ; idx + + ) {
elements [ idx ] . Stream = 0 ;
elements [ idx ] . Method = WINED3DDECLMETHOD_DEFAULT ;
elements [ idx ] . Offset = offset ;
offset + = WINED3D_ATR_SIZE ( elements [ idx ] . Type ) * WINED3D_ATR_TYPESIZE ( elements [ idx ] . Type ) ;
}
* 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 ;
size_t size ;
DWORD hr ;
size = ConvertFvfToDeclaration ( Fvf , & elements ) ;
if ( size = = 0 ) return WINED3DERR_OUTOFVIDEOMEMORY ;
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
}
2005-03-02 13:16:10 +01:00
/* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
2007-02-13 23:12:29 +01:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader ( IWineD3DDevice * iface , IWineD3DVertexDeclaration * vertex_declaration , CONST DWORD * pFunction , 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 ;
2006-09-27 13:14:46 +02:00
D3DCREATESHADEROBJECTINSTANCE ( object , VertexShader )
2006-03-30 19:14:31 +02:00
object - > baseShader . shader_ins = IWineD3DVertexShaderImpl_shader_ins ;
2005-03-02 13:16:10 +01:00
2005-08-19 12:05:00 +02:00
TRACE ( " (%p) : Created Vertex shader %p \n " , This , * ppVertexShader ) ;
2006-03-16 22:42:00 +01:00
2007-02-13 23:12:29 +01:00
if ( vertex_declaration ) {
IWineD3DVertexShader_FakeSemantics ( * ppVertexShader , vertex_declaration ) ;
2006-03-16 22:42:00 +01:00
}
2005-12-09 11:23:52 +01:00
hr = IWineD3DVertexShader_SetFunction ( * ppVertexShader , pFunction ) ;
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK ! = hr ) {
FIXME ( " (%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL \n " , iface ) ;
2005-12-09 11:23:52 +01:00
IWineD3DVertexShader_Release ( * ppVertexShader ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-12-09 11:23:52 +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_CreatePixelShader ( IWineD3DDevice * iface , CONST DWORD * pFunction , 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
2006-09-27 13:14:46 +02:00
D3DCREATESHADEROBJECTINSTANCE ( object , PixelShader )
2006-03-30 19:14:31 +02:00
object - > baseShader . shader_ins = IWineD3DPixelShaderImpl_shader_ins ;
2005-11-21 17:27:55 +01:00
hr = IWineD3DPixelShader_SetFunction ( * ppPixelShader , pFunction ) ;
2006-04-07 12:51:12 +02:00
if ( WINED3D_OK = = hr ) {
2005-11-21 17:27:55 +01:00
TRACE ( " (%p) : Created Pixel shader %p \n " , This , * ppPixelShader ) ;
} else {
WARN ( " (%p) : Failed to create pixel shader \n " , This ) ;
}
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
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette ( IWineD3DDevice * iface , DWORD Flags , 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 ;
hbm = ( HBITMAP ) LoadImageA ( NULL , filename , IMAGE_BITMAP , 0 , 0 , LR_LOADFROMFILE | LR_CREATEDIBSECTION ) ;
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 ;
}
hr = IWineD3DDevice_CreateSurface ( ( IWineD3DDevice * ) This , bm . bmWidth , bm . bmHeight , WINED3DFMT_R5G6B5 ,
TRUE , FALSE , 0 , & This - > logo_surface , WINED3DRTYPE_SURFACE , 0 ,
WINED3DPOOL_DEFAULT , WINED3DMULTISAMPLE_NONE , 0 , NULL , SURFACE_OPENGL , NULL ) ;
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 ;
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_Init3D ( IWineD3DDevice * iface , WINED3DPRESENT_PARAMETERS * pPresentationParameters , D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain ) {
2006-04-18 22:38:30 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSwapChainImpl * swapchain ;
2007-06-12 17:49:58 +02:00
HRESULT hr ;
2006-12-15 19:16:36 +01:00
DWORD state ;
2006-04-18 22:38:30 +02:00
TRACE ( " (%p)->(%p,%p) \n " , This , pPresentationParameters , D3DCB_CreateAdditionalSwapChain ) ;
if ( This - > d3d_initialized ) return WINED3DERR_INVALIDCALL ;
/* 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 ) ;
hr = allocate_shader_constants ( This - > updateStateBlock ) ;
2007-10-09 22:04:18 +02:00
if ( WINED3D_OK ! = hr ) {
goto err_out ;
}
2007-07-22 23:09:11 +02:00
2007-07-16 19:49:34 +02:00
This - > render_targets = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3DSurface * ) * GL_LIMITS ( buffers ) ) ;
This - > fbo_color_attachments = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3DSurface * ) * GL_LIMITS ( buffers ) ) ;
This - > draw_buffers = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( GLenum ) * GL_LIMITS ( buffers ) ) ;
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
}
2006-04-18 22:38:30 +02:00
/* Setup the implicit swapchain */
TRACE ( " Creating implicit swapchain \n " ) ;
2007-06-12 17:49:58 +02:00
hr = D3DCB_CreateAdditionalSwapChain ( ( IUnknown * ) This - > parent , pPresentationParameters , ( IWineD3DSwapChain * * ) & swapchain ) ;
if ( FAILED ( hr ) | | ! swapchain ) {
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 ;
2007-02-14 17:59:08 +01:00
if ( ! This - > ddraw_window ) IWineD3DDevice_SetHWND ( iface , swapchain - > win_handle ) ;
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 */
This - > stencilBufferTarget = This - > depthStencilBuffer ;
if ( NULL ! = This - > stencilBufferTarget ) {
IWineD3DSurface_AddRef ( This - > stencilBufferTarget ) ;
}
/* Set up some starting GL setup */
ENTER_GL ( ) ;
/* Setup all the devices defaults */
IWineD3DStateBlock_InitStartupStateBlock ( ( IWineD3DStateBlock * ) This - > stateBlock ) ;
#if 0
IWineD3DImpl_CheckGraphicsMemory ( ) ;
# endif
{ /* Set a default viewport */
2006-10-11 03:57:25 +02:00
WINED3DVIEWPORT vp ;
2006-04-18 22:38:30 +02:00
vp . X = 0 ;
vp . Y = 0 ;
2007-02-15 22:36:50 +01:00
vp . Width = pPresentationParameters - > BackBufferWidth ;
vp . Height = pPresentationParameters - > BackBufferHeight ;
2006-04-18 22:38:30 +02:00
vp . MinZ = 0.0f ;
vp . MaxZ = 1.0f ;
IWineD3DDevice_SetViewport ( ( IWineD3DDevice * ) This , & vp ) ;
}
/* 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 :
{
2007-03-04 23:29:28 +01:00
if ( GL_LIMITS ( 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 ) ;
}
2006-04-18 22:38:30 +02:00
return WINED3D_OK ;
2007-10-09 22:04:18 +02:00
err_out :
HeapFree ( GetProcessHeap ( ) , 0 , This - > render_targets ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > fbo_color_attachments ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > draw_buffers ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > swapchains ) ;
This - > NumberOfSwapChains = 0 ;
if ( swapchain ) {
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
}
This - > draw_buffers = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( GLenum ) * GL_LIMITS ( buffers ) ) ;
if ( This - > stateBlock ) {
IWineD3DStateBlock_Release ( ( IWineD3DStateBlock * ) This - > stateBlock ) ;
This - > stateBlock = NULL ;
}
return hr ;
2006-04-12 21:08:57 +02:00
}
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 ;
2007-03-17 23:00:39 +01:00
/* I don't think that the interface guarants that the device is destroyed from the same thread
* 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 ) ;
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 ) {
GL_EXTCALL ( glDeleteProgramsARB ( 1 , & This - > paletteConversionShader ) ) ;
}
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
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 ) ;
}
}
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 ) ) {
if ( This - > depthStencilBuffer ! = This - > stencilBufferTarget )
FIXME ( " (%p) Something's still holding the depthStencilBuffer \n " , This ) ;
}
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 ) {
2006-04-18 22:38:30 +02:00
/* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
}
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
2006-07-21 05:06:32 +02:00
if ( This - > depthStencilBuffer ) {
2006-12-18 00:16:40 +01:00
if ( D3DCB_DestroyDepthStencilSurface ( This - > depthStencilBuffer ) > 0 ) {
2006-12-05 00:29:31 +01:00
FIXME ( " (%p) Something's still holding the depthStencilBuffer \n " , This ) ;
2006-07-21 05:06:32 +02:00
}
This - > depthStencilBuffer = 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
2007-07-16 19:49:34 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , This - > render_targets ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > fbo_color_attachments ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This - > draw_buffers ) ;
This - > render_targets = NULL ;
This - > fbo_color_attachments = 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
}
2006-09-09 13:33:17 +02:00
static void WINAPI IWineD3DDeviceImpl_SetFullscreen ( IWineD3DDevice * iface , BOOL fullscreen ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p) Setting DDraw fullscreen mode to %s \n " , This , fullscreen ? " true " : " false " ) ;
2007-02-14 17:59:08 +01:00
/* Setup the window for fullscreen mode */
if ( fullscreen & & ! This - > ddraw_fullscreen ) {
IWineD3DDeviceImpl_SetupFullscreenWindow ( iface , This - > ddraw_window ) ;
} else if ( ! fullscreen & & This - > ddraw_fullscreen ) {
IWineD3DDeviceImpl_RestoreWindow ( iface , This - > ddraw_window ) ;
}
2006-09-09 13:33:17 +02:00
/* DirectDraw apps can change between fullscreen and windowed mode after device creation with
* IDirectDraw7 : : SetCooperativeLevel . The GDI surface implementation needs to know this .
2006-11-07 00:37:42 +01:00
* DDraw doesn ' t necessarily have a swapchain , so we have to store the fullscreen flag
* separately .
2006-09-09 13:33:17 +02:00
*/
This - > ddraw_fullscreen = fullscreen ;
}
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 ;
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode ( IWineD3DDevice * iface , UINT iSwapChain , WINED3DDISPLAYMODE * pMode ) {
2006-05-18 22:42:22 +02:00
DEVMODEW devmode ;
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
LONG ret ;
2007-07-27 13:22:54 +02:00
const StaticPixelFormatDesc * formatDesc = getFormatDescEntry ( pMode - > Format , NULL , NULL ) ;
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 ;
2006-06-21 10:36:14 +02:00
devmode . dmBitsPerPel = formatDesc - > bpp * 8 ;
2006-05-18 22:42:22 +02:00
if ( devmode . dmBitsPerPel = = 24 ) devmode . dmBitsPerPel = 32 ;
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 ;
/* Only do this with a window of course */
if ( This - > ddraw_window )
MoveWindow ( This - > ddraw_window , 0 , 0 , pMode - > Width , pMode - > Height , TRUE ) ;
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
}
2005-07-13 13:34:55 +02:00
2004-10-21 22:59:12 +02:00
/*****
* Get / Set FVF
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF ( IWineD3DDevice * iface , DWORD fvf ) {
2004-10-21 22:59:12 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-03-02 13:16:10 +01:00
/* Update the current state block */
2004-10-21 22:59:12 +02:00
This - > updateStateBlock - > changed . fvf = TRUE ;
2007-01-04 00:07:00 +01:00
if ( This - > updateStateBlock - > fvf = = fvf ) {
TRACE ( " Application is setting the old fvf over, nothing to do \n " ) ;
return WINED3D_OK ;
}
This - > updateStateBlock - > fvf = fvf ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : FVF Shader FVF set to %x \n " , This , fvf ) ;
2007-01-02 00:35:07 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VDECL ) ;
return WINED3D_OK ;
2004-10-21 22:59:12 +02:00
}
2005-07-07 22:45:39 +02:00
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF ( IWineD3DDevice * iface , DWORD * pfvf ) {
2004-10-21 22:59:12 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : GetFVF returning %x \n " , This , This - > stateBlock - > fvf ) ;
2004-10-21 22:59:12 +02:00
* pfvf = This - > stateBlock - > fvf ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-10-21 22:59:12 +02:00
}
2004-10-07 06:22:21 +02:00
2004-11-23 14:52:46 +01:00
/*****
* Get / Set Stream Source
* * * * */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource ( IWineD3DDevice * iface , UINT StreamNumber , IWineD3DVertexBuffer * pStreamData , UINT OffsetInBytes , UINT Stride ) {
2005-09-02 13:17:17 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2004-11-23 14:52:46 +01:00
IWineD3DVertexBuffer * oldSrc ;
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
}
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
2005-07-05 16:05:18 +02:00
This - > updateStateBlock - > changed . streamSource [ StreamNumber ] = TRUE ;
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 " ) ;
2007-08-19 20:40:44 +02:00
if ( pStreamData ) IWineD3DVertexBuffer_AddRef ( pStreamData ) ;
if ( oldSrc ) IWineD3DVertexBuffer_Release ( oldSrc ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-11-23 14:52:46 +01:00
}
2005-09-02 13:17:17 +02:00
/* Need to do a getParent and pass the reffs up */
/* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
which suggests that we shouldn ' t be ref counting ? and do need a _release on the stream source to reset the stream source
so for now , just count internally */
2005-07-26 20:49:30 +02:00
if ( pStreamData ! = NULL ) {
2006-06-21 15:05:38 +02:00
IWineD3DVertexBufferImpl * vbImpl = ( IWineD3DVertexBufferImpl * ) pStreamData ;
2007-01-12 19:01:59 +01:00
InterlockedIncrement ( & vbImpl - > bindCount ) ;
2007-08-14 14:49:39 +02:00
IWineD3DVertexBuffer_AddRef ( pStreamData ) ;
2005-07-26 20:49:30 +02:00
}
if ( oldSrc ! = NULL ) {
2007-01-12 19:01:59 +01:00
InterlockedDecrement ( & ( ( IWineD3DVertexBufferImpl * ) oldSrc ) - > bindCount ) ;
2007-08-14 14:49:39 +02:00
IWineD3DVertexBuffer_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
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource ( IWineD3DDevice * iface , UINT StreamNumber , IWineD3DVertexBuffer * * 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 ) {
IWineD3DVertexBuffer_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
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
This - > updateStateBlock - > changed . streamFreq [ StreamNumber ] = TRUE ;
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 " ) ;
This - > updateStateBlock - > changed . transform [ d3dts ] = TRUE ;
2006-10-12 08:21:39 +02:00
memcpy ( & This - > updateStateBlock - > transforms [ d3dts ] , lpmatrix , sizeof ( WINED3DMATRIX ) ) ;
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 */
2007-01-02 22:47:39 +01:00
if ( d3dts = = WINED3DTS_VIEW ) { /* handle the VIEW matrice */
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 ) ) ;
2006-10-12 08:21:39 +02:00
memcpy ( pMatrix , & This - > stateBlock - > transforms [ State ] , sizeof ( WINED3DMATRIX ) ) ;
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 ) {
WINED3DMATRIX * mat = NULL ;
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
if ( State < HIGHEST_TRANSFORMSTATE )
{
mat = & This - > updateStateBlock - > transforms [ State ] ;
} else {
FIXME ( " Unhandled transform state!! \n " ) ;
}
2006-11-24 15:15:06 +01:00
multiply_matrix ( & temp , mat , ( const WINED3DMATRIX * ) 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 */
2006-10-11 03:55:47 +02:00
memcpy ( & object - > OriginalParms , pLight , sizeof ( WINED3DLIGHT ) ) ;
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
}
2006-09-17 19:54:33 +02: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
}
2006-10-11 03:55:47 +02:00
memcpy ( pLight , & lightInfo - > OriginalParms , sizeof ( WINED3DLIGHT ) ) ;
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
2006-07-14 02:17:55 +02:00
/* Tests show true = 128...not clear why */
Enable = Enable ? 128 : 0 ;
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
2007-02-14 17:46:54 +01:00
This - > stateBlock - > activeLights [ lightInfo - > glIndex ] = NULL ;
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
}
} else {
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 + + ) {
if ( This - > stateBlock - > activeLights [ i ] = = NULL ) {
This - > stateBlock - > activeLights [ i ] = lightInfo ;
lightInfo - > glIndex = i ;
break ;
2004-11-29 18:53:42 +01:00
}
}
2007-02-14 17:46:54 +01:00
if ( lightInfo - > glIndex = = - 1 ) {
ERR ( " Too many concurrently active lights \n " ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
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 */
* pEnable = lightInfo - > glIndex ! = - 1 ? 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
}
This - > updateStateBlock - > changed . clipplane [ Index ] = TRUE ;
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 ;
memcpy ( & This - > updateStateBlock - > material , pMaterial , sizeof ( WINED3DMATERIAL ) ) ;
/* 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 ;
memcpy ( pMaterial , & This - > updateStateBlock - > material , sizeof ( WINED3DMATERIAL ) ) ;
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
* * * * */
2007-06-05 18:52:21 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices ( IWineD3DDevice * iface , IWineD3DIndexBuffer * pIndexData ) {
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DIndexBuffer * oldIdxs ;
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 ;
/* Handle recording of state blocks */
if ( This - > isRecordingState ) {
TRACE ( " Recording... not performing anything \n " ) ;
2007-08-19 20:42:29 +02:00
if ( pIndexData ) IWineD3DIndexBuffer_AddRef ( pIndexData ) ;
if ( oldIdxs ) IWineD3DIndexBuffer_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 ) ;
2007-08-14 14:46:38 +02:00
if ( pIndexData ) IWineD3DIndexBuffer_AddRef ( pIndexData ) ;
if ( oldIdxs ) IWineD3DIndexBuffer_Release ( oldIdxs ) ;
2007-02-19 15:25:32 +01:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-09 12:42:34 +01:00
}
2007-06-06 18:40:09 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices ( IWineD3DDevice * iface , IWineD3DIndexBuffer * * 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 ) {
2006-11-30 13:33:18 +01:00
IWineD3DIndexBuffer_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 ;
memcpy ( & This - > updateStateBlock - > viewport , pViewport , sizeof ( WINED3DVIEWPORT ) ) ;
/* 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 ) ;
memcpy ( pViewport , & This - > stateBlock - > viewport , sizeof ( WINED3DVIEWPORT ) ) ;
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
2004-12-13 14:35:38 +01:00
This - > updateStateBlock - > changed . renderState [ State ] = TRUE ;
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
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 ;
2005-08-22 12:07:10 +02:00
This - > updateStateBlock - > changed . samplerState [ Sampler ] [ Type ] = Value ;
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 ) ;
}
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 ;
2007-01-10 11:28:42 +01:00
memcpy ( pRect , & This - > updateStateBlock - > scissorRect , sizeof ( pRect ) ) ;
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 ;
2006-07-19 06:06:07 +02:00
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
2006-06-06 08:46:59 +02:00
if ( srcData = = NULL | | cnt < 0 )
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 ) {
2006-06-06 08:46:59 +02:00
This - > updateStateBlock - > changed . vertexShaderConstantsB [ i ] = TRUE ;
2005-08-17 12:27:01 +02:00
}
2005-09-21 12:19:29 +02:00
2007-01-06 18:17:27 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VERTEXSHADERCONSTANT ) ;
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 ;
2006-07-19 06:06:07 +02:00
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 ) ;
if ( srcData = = NULL | | cnt < 0 )
return WINED3DERR_INVALIDCALL ;
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 ) {
This - > updateStateBlock - > changed . vertexShaderConstantsI [ i ] = TRUE ;
}
2007-01-06 18:17:27 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VERTEXSHADERCONSTANT ) ;
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 ;
2007-02-20 22:43:53 +01:00
int 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 */
if ( srcData = = NULL | | start + count > GL_LIMITS ( vshader_constantsF ) | | start > GL_LIMITS ( vshader_constantsF ) )
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
2007-02-20 22:43:53 +01:00
for ( i = start ; i < count + start ; + + i ) {
2007-07-30 19:28:33 +02:00
if ( ! This - > updateStateBlock - > changed . vertexShaderConstantsF [ i ] ) {
2007-02-27 20:51:58 +01:00
constants_entry * ptr = LIST_ENTRY ( list_head ( & This - > updateStateBlock - > set_vconstantsF ) , constants_entry , entry ) ;
if ( ! ptr | | ptr - > count > = sizeof ( ptr - > idx ) / sizeof ( * ptr - > idx ) ) {
ptr = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( constants_entry ) ) ;
list_add_head ( & This - > updateStateBlock - > set_vconstantsF , & ptr - > entry ) ;
}
ptr - > idx [ ptr - > count + + ] = i ;
2007-07-30 19:28:33 +02:00
This - > updateStateBlock - > changed . vertexShaderConstantsF [ i ] = TRUE ;
2006-08-19 17:24:02 +02:00
}
2006-06-06 08:46:59 +02:00
}
2007-01-06 18:17:27 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_VERTEXSHADERCONSTANT ) ;
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_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 ;
2006-07-19 06:06:07 +02:00
int cnt = min ( count , GL_LIMITS ( vshader_constantsF ) - 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 ;
for ( i = 0 ; i < WINED3D_HIGHEST_TEXTURE_STATE ; i + + ) {
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 ;
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 */
while ( i < MAX_TEXTURES ) {
This - > fixed_function_usage_map [ i ] = FALSE ;
+ + i ;
}
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 ) ) ) {
This - > fixed_function_usage_map [ i ] = TRUE ;
} else {
This - > fixed_function_usage_map [ i ] = FALSE ;
}
if ( ( color_op = = WINED3DTOP_BUMPENVMAP | | color_op = = WINED3DTOP_BUMPENVMAPLUMINANCE ) & & i < MAX_TEXTURES - 1 ) {
This - > fixed_function_usage_map [ i + 1 ] = TRUE ;
}
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 ) {
int i , tex ;
device_update_fixed_function_usage_map ( This ) ;
2007-07-01 23:40:57 +02:00
if ( ! GL_SUPPORT ( NV_REGISTER_COMBINERS ) | | This - > stateBlock - > lowest_disabled_stage < = GL_LIMITS ( textures ) ) {
2007-06-28 23:32:38 +02:00
for ( i = 0 ; i < This - > stateBlock - > lowest_disabled_stage ; + + i ) {
if ( ! This - > fixed_function_usage_map [ i ] ) continue ;
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 ;
for ( i = 0 ; i < This - > stateBlock - > lowest_disabled_stage ; + + i ) {
2007-06-28 23:32:38 +02:00
if ( ! This - > fixed_function_usage_map [ i ] ) 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 ) {
2007-06-28 23:32:53 +02:00
DWORD * sampler_tokens = ( ( IWineD3DPixelShaderImpl * ) This - > stateBlock - > pixelShader ) - > baseShader . reg_maps . samplers ;
2007-06-22 20:43:42 +02:00
int i ;
2007-06-25 22:45:40 +02:00
for ( i = 0 ; i < MAX_FRAGMENT_SAMPLERS ; + + i ) {
2007-06-28 23:32:53 +02:00
if ( sampler_tokens [ 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 ) ;
}
}
}
}
2007-06-27 23:47:06 +02:00
static BOOL device_unit_free_for_vs ( IWineD3DDeviceImpl * This , DWORD * pshader_sampler_tokens , DWORD * vshader_sampler_tokens , int unit ) {
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 */
return current_mapping > = MAX_TEXTURES | | ! This - > fixed_function_usage_map [ current_mapping ] ;
}
/* 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 ) {
DWORD * vshader_sampler_tokens = ( ( IWineD3DVertexShaderImpl * ) This - > stateBlock - > vertexShader ) - > baseShader . reg_maps . samplers ;
DWORD * pshader_sampler_tokens = NULL ;
int start = GL_LIMITS ( combined_samplers ) - 1 ;
int i ;
if ( ps ) {
IWineD3DPixelShaderImpl * pshader = ( IWineD3DPixelShaderImpl * ) This - > stateBlock - > pixelShader ;
/* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */
IWineD3DPixelShader_CompileShader ( ( IWineD3DPixelShader * ) pshader ) ;
pshader_sampler_tokens = pshader - > baseShader . reg_maps . samplers ;
}
for ( i = 0 ; i < MAX_VERTEX_SAMPLERS ; + + i ) {
int vsampler_idx = i + MAX_FRAGMENT_SAMPLERS ;
if ( vshader_sampler_tokens [ i ] ) {
if ( This - > texUnitMap [ vsampler_idx ] ! = - 1 ) {
/* Already mapped somewhere */
continue ;
}
while ( start > = 0 ) {
if ( device_unit_free_for_vs ( This , pshader_sampler_tokens , vshader_sampler_tokens , start ) ) {
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 ) {
2007-06-27 23:47:06 +02:00
BOOL vs = use_vs ( This ) ;
2007-06-22 20:43:42 +02:00
BOOL ps = use_ps ( This ) ;
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 ;
2006-07-19 06:06:07 +02:00
int i , cnt = min ( count , MAX_CONST_B - start ) ;
2005-08-25 21:24:21 +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-03-02 13:16:10 +01:00
2006-06-06 08:46:59 +02:00
if ( srcData = = NULL | | cnt < 0 )
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 ) {
2006-06-06 08:46:59 +02:00
This - > updateStateBlock - > changed . pixelShaderConstantsB [ i ] = TRUE ;
2005-08-25 21:24:21 +02:00
}
2005-09-28 12:13:00 +02:00
2007-01-06 18:17:27 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADERCONSTANT ) ;
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 ;
2006-07-19 06:06:07 +02:00
int i , cnt = min ( count , MAX_CONST_I - start ) ;
2005-09-28 12:13:00 +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-28 12:13:00 +02:00
2006-06-06 08:46:59 +02:00
if ( srcData = = NULL | | cnt < 0 )
return WINED3DERR_INVALIDCALL ;
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 ) {
This - > updateStateBlock - > changed . pixelShaderConstantsI [ i ] = TRUE ;
}
2005-09-28 12:13:00 +02:00
2007-01-06 18:17:27 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADERCONSTANT ) ;
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 ;
2007-02-20 22:43:53 +01:00
int 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 */
if ( srcData = = NULL | | start + count > GL_LIMITS ( pshader_constantsF ) | | start > GL_LIMITS ( pshader_constantsF ) )
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
2007-02-20 22:43:53 +01:00
for ( i = start ; i < count + start ; + + i ) {
2007-07-30 19:28:33 +02:00
if ( ! This - > updateStateBlock - > changed . pixelShaderConstantsF [ i ] ) {
2007-02-27 20:51:58 +01:00
constants_entry * ptr = LIST_ENTRY ( list_head ( & This - > updateStateBlock - > set_pconstantsF ) , constants_entry , entry ) ;
if ( ! ptr | | ptr - > count > = sizeof ( ptr - > idx ) / sizeof ( * ptr - > idx ) ) {
ptr = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( constants_entry ) ) ;
list_add_head ( & This - > updateStateBlock - > set_pconstantsF , & ptr - > entry ) ;
}
ptr - > idx [ ptr - > count + + ] = i ;
2007-07-30 19:28:33 +02:00
This - > updateStateBlock - > changed . pixelShaderConstantsF [ i ] = TRUE ;
2006-08-19 17:24:02 +02:00
}
2006-06-06 08:46:59 +02:00
}
2007-01-06 18:17:27 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_PIXELSHADERCONSTANT ) ;
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_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 ;
2006-07-19 06:06:07 +02:00
int cnt = min ( count , GL_LIMITS ( pshader_constantsF ) - 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
}
2006-05-12 22:21:31 +02:00
# define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
static HRESULT
2007-04-22 18:06:07 +02:00
process_vertices_strided ( IWineD3DDeviceImpl * This , DWORD dwDestIndex , DWORD dwCount , WineDirect3DVertexStridedData * lpStrideData , IWineD3DVertexBufferImpl * dest , DWORD dwFlags ) {
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 ;
DWORD DestFVF = dest - > fvf ;
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 ;
int numTextures ;
2007-04-22 18:06:07 +02:00
if ( lpStrideData - > u . s . normal . lpData ) {
2006-05-12 22:21:31 +02:00
WARN ( " lighting state not saved yet... Some strange stuff may happen ! \n " ) ;
}
2007-04-22 18:06:07 +02:00
if ( lpStrideData - > u . s . position . lpData = = NULL ) {
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 ) {
2006-06-21 15:05:38 +02:00
/* This may happen if we do direct locking into a vbo. Unlikely,
* but theoretically possible ( ddraw processvertices test )
*/
dest - > resource . allocatedMemory = HeapAlloc ( GetProcessHeap ( ) , 0 , dest - > resource . size ) ;
if ( ! dest - > resource . allocatedMemory ) {
LEAVE_GL ( ) ;
ERR ( " Out of memory \n " ) ;
return E_OUTOFMEMORY ;
}
if ( dest - > vbo ) {
void * src ;
GL_EXTCALL ( glBindBufferARB ( GL_ARRAY_BUFFER_ARB , dest - > vbo ) ) ;
checkGLcall ( " glBindBufferARB " ) ;
2006-06-27 00:32:25 +02:00
src = GL_EXTCALL ( glMapBufferARB ( GL_ARRAY_BUFFER_ARB , GL_READ_ONLY_ARB ) ) ;
2006-06-21 15:05:38 +02:00
if ( src ) {
memcpy ( dest - > resource . allocatedMemory , src , dest - > resource . size ) ;
}
GL_EXTCALL ( glUnmapBufferARB ( GL_ARRAY_BUFFER_ARB ) ) ;
checkGLcall ( " glUnmapBufferARB " ) ;
}
}
/* 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
*/
if ( ! dest - > vbo & & GL_SUPPORT ( ARB_VERTEX_BUFFER_OBJECT ) ) {
CreateVBO ( dest ) ;
}
if ( dest - > vbo ) {
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 ;
dest_ptr = ( ( char * ) dest - > resource . allocatedMemory ) + dwDestIndex * get_flexible_vertex_size ( DestFVF ) ;
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 */
float * p =
( float * ) ( ( ( char * ) lpStrideData - > u . s . position . lpData ) + i * lpStrideData - > u . s . position . dwStride ) ;
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 !
*/
/* Clipping conditions: From
* http : //msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
*
* 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 ) {
2006-05-12 22:21:31 +02:00
float * normal =
( float * ) ( ( ( float * ) lpStrideData - > u . s . normal . lpData ) + i * lpStrideData - > u . s . normal . dwStride ) ;
/* 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 ) {
2006-05-12 22:21:31 +02:00
DWORD * color_d =
( DWORD * ) ( ( ( char * ) lpStrideData - > u . s . diffuse . lpData ) + i * lpStrideData - > u . s . diffuse . dwStride ) ;
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? */
DWORD * color_s =
( DWORD * ) ( ( ( char * ) lpStrideData - > u . s . specular . lpData ) + i * lpStrideData - > u . s . specular . dwStride ) ;
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 + + ) {
float * tex_coord =
( float * ) ( ( ( char * ) lpStrideData - > u . s . texCoords [ tex_index ] . lpData ) +
i * lpStrideData - > u . s . texCoords [ tex_index ] . dwStride ) ;
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 ) {
2007-02-20 23:00:02 +01:00
GL_EXTCALL ( glBindBufferARB ( GL_ARRAY_BUFFER_ARB , dest - > vbo ) ) ;
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
2007-04-22 18:06:07 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices ( IWineD3DDevice * iface , UINT SrcStartIndex , UINT DestIndex , UINT VertexCount , IWineD3DVertexBuffer * pDestBuffer , IWineD3DVertexDeclaration * pVertexDecl , DWORD Flags ) {
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2006-05-12 22:21:31 +02:00
WineDirect3DVertexStridedData strided ;
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
/* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway,
* and this call is quite performance critical , so don ' t call needlessly
*/
if ( This - > createParms . BehaviorFlags & WINED3DCREATE_MULTITHREADED ) {
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
}
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 ;
2007-04-22 18:06:07 +02:00
memset ( & strided , 0 , sizeof ( strided ) ) ;
2007-06-04 14:16:32 +02:00
primitiveDeclarationConvertToStridedData ( iface , FALSE , & strided , & 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 ;
/* ProcessVertices can't convert FROM a vbo, and vertex buffers used to source into ProcesVerticse are
* unlikely to ever be used for drawing . Release vbos in those buffers and fix up the strided structure
*
* Also get the start index in , but only loop over all elements if there ' s something to add at all .
*/
2007-05-06 18:39:29 +02:00
# define FIXSRC(type) \
if ( strided . u . s . type . VBO ) { \
IWineD3DVertexBufferImpl * vb = ( IWineD3DVertexBufferImpl * ) This - > stateBlock - > streamSource [ strided . u . s . type . streamNo ] ; \
strided . u . s . type . VBO = 0 ; \
strided . u . s . type . lpData = ( BYTE * ) ( ( unsigned long ) strided . u . s . type . lpData + ( unsigned long ) vb - > resource . allocatedMemory ) ; \
ENTER_GL ( ) ; \
GL_EXTCALL ( glDeleteBuffersARB ( 1 , & vb - > vbo ) ) ; \
vb - > vbo = 0 ; \
LEAVE_GL ( ) ; \
} \
if ( strided . u . s . type . lpData ) { \
strided . u . s . type . lpData + = strided . u . s . type . dwStride * SrcStartIndex ; \
}
FIXSRC ( position ) ;
FIXSRC ( blendWeights ) ;
FIXSRC ( blendMatrixIndices ) ;
FIXSRC ( normal ) ;
FIXSRC ( pSize ) ;
FIXSRC ( diffuse ) ;
FIXSRC ( specular ) ;
for ( i = 0 ; i < WINED3DDP_MAXTEXCOORD ; i + + ) {
FIXSRC ( texCoords [ i ] ) ;
2006-06-21 15:05:38 +02:00
}
2007-05-06 18:39:29 +02:00
FIXSRC ( position2 ) ;
FIXSRC ( normal2 ) ;
FIXSRC ( tangent ) ;
FIXSRC ( binormal ) ;
FIXSRC ( tessFactor ) ;
FIXSRC ( fog ) ;
FIXSRC ( depth ) ;
FIXSRC ( sample ) ;
# undef FIXSRC
2006-06-21 15:05:38 +02:00
}
2007-04-22 18:06:07 +02:00
return process_vertices_strided ( This , DestIndex , VertexCount , & strided , ( IWineD3DVertexBufferImpl * ) pDestBuffer , Flags ) ;
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 ;
}
2005-08-22 12:07:10 +02:00
This - > updateStateBlock - > changed . textureState [ Stage ] [ Type ] = TRUE ;
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 & &
StateTable [ STATE_TEXTURESTAGE ( 0 , Type ) ] . representative = = STATE_TEXTURESTAGE ( 0 , WINED3DTSS_COLOROP ) ) {
/* 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 ) {
int i ;
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 + + ) {
TRACE ( " Additionally dirtifying stage %d \n " , i ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( i , WINED3DTSS_COLOROP ) ) ;
}
This - > stateBlock - > lowest_disabled_stage = Stage ;
TRACE ( " New lowest disabled: %d \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 ;
}
TRACE ( " Additionally dirtifying stage %d due to enable \n " , i ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_TEXTURESTAGE ( i , WINED3DTSS_COLOROP ) ) ;
}
This - > stateBlock - > lowest_disabled_stage = i ;
TRACE ( " New lowest disabled: %d \n " , i ) ;
}
if ( GL_SUPPORT ( NV_REGISTER_COMBINERS ) & & ! This - > stateBlock - > pixelShader ) {
/* TODO: Built a stage -> texture unit mapping for register combiners */
}
}
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
oldTexture = This - > updateStateBlock - > textures [ Stage ] ;
2005-08-01 11:20:55 +02:00
2006-02-06 20:57:42 +01:00
if ( pTexture ! = NULL ) {
2006-05-18 22:59:33 +02:00
/* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
*/
if ( ( ( IWineD3DTextureImpl * ) pTexture ) - > resource . pool = = WINED3DPOOL_SCRATCH ) {
2006-02-06 20:57:42 +01:00
WARN ( " (%p) Attempt to set scratch texture rejected \n " , pTexture ) ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2006-02-06 20:57:42 +01:00
}
2006-12-19 23:26:39 +01:00
This - > stateBlock - > textureDimensions [ Stage ] = IWineD3DBaseTexture_GetTextureDimensions ( pTexture ) ;
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 ) ;
2005-01-18 12:42:29 +01:00
This - > updateStateBlock - > changed . textures [ Stage ] = TRUE ;
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 ) ;
2005-12-15 10:25:47 +01:00
IWineD3DBaseTexture_AddRef ( This - > updateStateBlock - > textures [ Stage ] ) ;
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
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 ) {
hr = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , ( IWineD3DSwapChain * * ) & swapChain ) ;
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
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND ( IWineD3DDevice * iface , HWND hWnd ) {
2006-04-18 23:39:52 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p)->(%p) \n " , This , hWnd ) ;
2006-04-13 23:37:47 +02:00
2007-02-14 17:59:08 +01:00
if ( This - > ddraw_fullscreen ) {
if ( This - > ddraw_window & & This - > ddraw_window ! = hWnd ) {
IWineD3DDeviceImpl_RestoreWindow ( iface , This - > ddraw_window ) ;
}
if ( hWnd & & This - > ddraw_window ! = hWnd ) {
IWineD3DDeviceImpl_SetupFullscreenWindow ( iface , hWnd ) ;
}
}
2006-04-18 23:39:52 +02:00
This - > ddraw_window = hWnd ;
return WINED3D_OK ;
2006-04-13 23:37:47 +02:00
}
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND ( IWineD3DDevice * iface , HWND * hWnd ) {
2006-04-18 23:39:52 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
TRACE ( " (%p)->(%p) \n " , This , hWnd ) ;
2006-04-13 23:37:47 +02:00
2006-04-18 23:39:52 +02:00
* hWnd = This - > ddraw_window ;
return WINED3D_OK ;
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 ;
IWineD3DStateBlockImpl * object ;
2006-07-19 06:06:07 +02:00
HRESULT temp_result ;
2007-02-14 17:46:54 +01:00
int i ;
2007-08-19 20:47:10 +02:00
TRACE ( " (%p) \n " , This ) ;
2005-12-03 18:04:26 +01:00
if ( This - > isRecordingState ) {
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-12-03 18:04:26 +01:00
}
2005-03-02 13:16:10 +01:00
object = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( IWineD3DStateBlockImpl ) ) ;
2005-08-22 11:13:49 +02:00
if ( NULL = = object ) {
2005-03-02 13:16:10 +01:00
FIXME ( " (%p)Error allocating memory for stateblock \n " , This ) ;
return E_OUTOFMEMORY ;
}
2006-07-19 06:06:07 +02:00
TRACE ( " (%p) created object %p \n " , This , object ) ;
2005-07-13 16:15:54 +02:00
object - > wineD3DDevice = This ;
2005-03-02 13:16:10 +01:00
/** FIXME: object->parent = parent; **/
object - > parent = NULL ;
2007-08-04 00:46:37 +02:00
object - > blockType = WINED3DSBT_RECORDED ;
2005-03-02 13:16:10 +01:00
object - > ref = 1 ;
2005-07-13 16:15:54 +02:00
object - > lpVtbl = & IWineD3DStateBlock_Vtbl ;
2007-02-14 17:46:54 +01:00
for ( i = 0 ; i < LIGHTMAP_SIZE ; i + + ) {
list_init ( & object - > lightMap [ i ] ) ;
}
2006-07-19 06:06:07 +02:00
temp_result = allocate_shader_constants ( object ) ;
if ( WINED3D_OK ! = temp_result )
return temp_result ;
2005-07-13 16:15:54 +02:00
2005-03-02 13:16:10 +01:00
IWineD3DStateBlock_Release ( ( IWineD3DStateBlock * ) This - > updateStateBlock ) ;
This - > updateStateBlock = object ;
This - > isRecordingState = TRUE ;
2005-07-13 16:15:54 +02:00
2005-03-02 13:16:10 +01:00
TRACE ( " (%p) recording stateblock %p \n " , This , object ) ;
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 ) {
FIXME ( " (%p) not recording! returning error \n " , This ) ;
* ppStateBlock = NULL ;
2006-04-07 12:51:12 +02:00
return WINED3DERR_INVALIDCALL ;
2005-03-02 13:16:10 +01:00
}
2007-07-31 15:04:56 +02:00
for ( i = 1 ; i < = WINEHIGHEST_RENDER_STATE ; i + + ) {
if ( object - > changed . renderState [ i ] ) {
object - > contained_render_states [ object - > num_contained_render_states ] = i ;
object - > num_contained_render_states + + ;
}
}
2007-07-31 15:44:13 +02:00
for ( i = 1 ; i < = HIGHEST_TRANSFORMSTATE ; i + + ) {
if ( object - > changed . transform [ i ] ) {
object - > contained_transform_states [ object - > num_contained_transform_states ] = i ;
object - > num_contained_transform_states + + ;
}
}
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 + + ) {
if ( object - > changed . vertexShaderConstantsI [ i ] ) {
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 + + ) {
if ( object - > changed . vertexShaderConstantsB [ i ] ) {
object - > contained_vs_consts_b [ object - > num_contained_vs_consts_b ] = i ;
object - > num_contained_vs_consts_b + + ;
}
}
2007-08-03 20:12:54 +02:00
for ( i = 0 ; i < MAX_CONST_I ; i + + ) {
if ( object - > changed . pixelShaderConstantsI [ i ] ) {
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 + + ) {
if ( object - > changed . pixelShaderConstantsB [ i ] ) {
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 + + ) {
for ( j = 1 ; j < = WINED3D_HIGHEST_TEXTURE_STATE ; j + + ) {
if ( object - > changed . textureState [ i ] [ j ] ) {
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 + + ) {
if ( object - > changed . samplerState [ i ] [ 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
* 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 ;
}
2007-03-17 23:00:39 +01:00
if ( This - > createParms . BehaviorFlags & WINED3DCREATE_MULTITHREADED ) {
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 */
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2004-12-14 12:54:27 +01:00
glFlush ( ) ;
checkGLcall ( " glFlush " ) ;
LEAVE_GL ( ) ;
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
2005-06-23 13:05:24 +02:00
IWineD3DDeviceImpl_GetSwapChain ( iface , i , ( IWineD3DSwapChain * * ) & swapChain ) ;
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
}
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
GLbitfield glMask = 0 ;
unsigned int i ;
2006-10-12 08:22:18 +02:00
CONST WINED3DRECT * curRect ;
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-03-17 23:00:39 +01:00
/* This is for offscreen rendering as well as for multithreading, thus activate the set render target
* and not the last active one .
*/
2007-08-13 16:11:21 +02:00
ActivateContext ( This , This - > render_targets [ 0 ] , CTXUSAGE_CLEAR ) ;
ENTER_GL ( ) ;
2007-04-09 01:53:27 +02:00
if ( wined3d_settings . offscreen_rendering_mode = = ORM_FBO ) {
apply_fbo_state ( iface ) ;
}
2004-12-14 12:54:27 +01:00
if ( Count > 0 & & pRects ) {
curRect = pRects ;
} else {
curRect = NULL ;
}
/* Only set the values up once, as they are not changing */
2006-10-31 09:17:43 +01:00
if ( Flags & WINED3DCLEAR_STENCIL ) {
2004-12-14 12:54:27 +01:00
glClearStencil ( Stencil ) ;
checkGLcall ( " glClearStencil " ) ;
glMask = glMask | GL_STENCIL_BUFFER_BIT ;
glStencilMask ( 0xFFFFFFFF ) ;
}
2006-10-31 09:17:43 +01:00
if ( Flags & WINED3DCLEAR_ZBUFFER ) {
2005-07-13 16:15:54 +02:00
glDepthMask ( GL_TRUE ) ;
2004-12-14 12:54:27 +01:00
glClearDepth ( Z ) ;
checkGLcall ( " glClearDepth " ) ;
glMask = glMask | GL_DEPTH_BUFFER_BIT ;
2007-02-20 22:44:12 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_ZWRITEENABLE ) ) ;
2004-12-14 12:54:27 +01:00
}
2006-10-31 09:17:43 +01:00
if ( Flags & WINED3DCLEAR_TARGET ) {
2006-10-01 05:20:10 +02:00
TRACE ( " Clearing screen with glClear to color %x \n " , Color ) ;
2005-11-15 13:03:13 +01:00
glClearColor ( D3DCOLOR_R ( Color ) ,
D3DCOLOR_G ( Color ) ,
D3DCOLOR_B ( Color ) ,
D3DCOLOR_A ( Color ) ) ;
2004-12-14 12:54:27 +01:00
checkGLcall ( " glClearColor " ) ;
/* Clear ALL colors! */
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
glMask = glMask | GL_COLOR_BUFFER_BIT ;
}
2007-02-26 13:42:25 +01:00
if ( ! curRect ) {
2007-03-10 00:55:08 +01:00
/* In drawable flag is set below */
2007-07-26 00:38:50 +02:00
if ( This - > render_offscreen ) {
glScissor ( This - > stateBlock - > viewport . X ,
This - > stateBlock - > viewport . Y ,
This - > stateBlock - > viewport . Width ,
This - > stateBlock - > viewport . Height ) ;
} else {
glScissor ( This - > stateBlock - > viewport . X ,
( ( ( IWineD3DSurfaceImpl * ) This - > render_targets [ 0 ] ) - > currentDesc . Height -
( This - > stateBlock - > viewport . Y + This - > stateBlock - > viewport . Height ) ) ,
This - > stateBlock - > viewport . Width ,
This - > stateBlock - > viewport . Height ) ;
}
2007-03-02 09:25:02 +01:00
checkGLcall ( " glScissor " ) ;
2007-02-26 13:42:25 +01:00
glClear ( glMask ) ;
checkGLcall ( " glClear " ) ;
} else {
2007-03-10 00:55:08 +01:00
if ( ! ( target - > Flags & SFLAG_INDRAWABLE ) & &
! ( wined3d_settings . offscreen_rendering_mode = = ORM_FBO & & This - > render_offscreen & & target - > Flags & SFLAG_INTEXTURE ) ) {
if ( curRect [ 0 ] . x1 > 0 | | curRect [ 0 ] . y1 > 0 | |
curRect [ 0 ] . x2 < target - > currentDesc . Width | |
curRect [ 0 ] . y2 < target - > currentDesc . Height ) {
TRACE ( " Partial clear, and surface not in drawable. Blitting texture to drawable \n " ) ;
blt_to_drawable ( This , target ) ;
}
}
2007-02-26 13:42:25 +01:00
/* Now process each rect in turn */
for ( i = 0 ; i < Count ; i + + ) {
2004-12-14 12:54:27 +01:00
/* Note gl uses lower left, width/height */
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d \n " , This , curRect ,
2007-02-26 13:42:25 +01:00
curRect [ i ] . x1 , curRect [ i ] . y1 , curRect [ i ] . x2 , curRect [ i ] . y2 ,
2007-03-10 00:55:08 +01:00
curRect [ i ] . x1 , ( target - > currentDesc . Height - curRect [ i ] . y2 ) ,
2007-02-26 13:42:25 +01:00
curRect [ i ] . x2 - curRect [ i ] . x1 , curRect [ i ] . y2 - curRect [ i ] . y1 ) ;
2004-12-14 12:54:27 +01:00
2007-02-26 13:42:25 +01:00
/* 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 [ i ] . x1 > curRect [ i ] . x2 | | curRect [ i ] . y1 > curRect [ i ] . y2 ) {
TRACE ( " Rectangle with negative dimensions, ignoring \n " ) ;
continue ;
}
2004-12-14 12:54:27 +01:00
2007-03-07 01:43:53 +01:00
if ( This - > render_offscreen ) {
glScissor ( curRect [ i ] . x1 , curRect [ i ] . y1 ,
curRect [ i ] . x2 - curRect [ i ] . x1 , curRect [ i ] . y2 - curRect [ i ] . y1 ) ;
} else {
glScissor ( curRect [ i ] . x1 , target - > currentDesc . Height - curRect [ i ] . y2 ,
curRect [ i ] . x2 - curRect [ i ] . x1 , curRect [ i ] . y2 - curRect [ i ] . y1 ) ;
}
2007-02-26 13:42:25 +01:00
checkGLcall ( " glScissor " ) ;
glClear ( glMask ) ;
checkGLcall ( " glClear " ) ;
}
2004-12-14 12:54:27 +01:00
}
/* Restore the old values (why..?) */
2006-10-31 09:17:43 +01:00
if ( Flags & WINED3DCLEAR_STENCIL ) {
2005-03-03 14:57:15 +01:00
glStencilMask ( This - > stateBlock - > renderState [ WINED3DRS_STENCILWRITEMASK ] ) ;
2005-07-13 16:15:54 +02:00
}
2006-10-31 09:17:43 +01:00
if ( Flags & WINED3DCLEAR_TARGET ) {
2007-02-26 13:42:25 +01:00
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 ) ;
2004-12-14 12:54:27 +01:00
}
LEAVE_GL ( ) ;
2007-06-07 11:48:55 +02:00
/* 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
2007-02-16 19:08:28 +01:00
*/
2007-10-09 22:17:59 +02:00
IWineD3DSurface_ModifyLocation ( This - > lastActiveRenderTarget , SFLAG_INDRAWABLE , TRUE ) ;
/* TODO: Move the fbo logic into ModifyLocation() */
2007-03-06 21:47:45 +01:00
if ( This - > render_offscreen & & wined3d_settings . offscreen_rendering_mode = = ORM_FBO ) {
2007-03-10 00:55:08 +01:00
target - > Flags | = SFLAG_INTEXTURE ;
2007-03-06 21:47:45 +01:00
}
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2004-12-14 12:54:27 +01:00
}
2004-12-09 12:42:34 +01:00
/*****
* Drawing functions
* * * * */
2006-10-12 08:23:55 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive ( IWineD3DDevice * iface , WINED3DPRIMITIVETYPE PrimitiveType , UINT StartVertex ,
2004-12-09 12:42:34 +01:00
UINT PrimitiveCount ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2005-07-13 16:15:54 +02:00
TRACE ( " (%p) : Type=(%d,%s), Start=%d, Count=%d \n " , This , PrimitiveType ,
debug_d3dprimitivetype ( PrimitiveType ) ,
2004-12-09 12:42:34 +01:00
StartVertex , PrimitiveCount ) ;
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 */
2007-01-06 18:19:55 +01:00
drawPrimitive ( iface , PrimitiveType , PrimitiveCount , StartVertex , 0 /* NumVertices */ , - 1 /* indxStart */ ,
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
}
/* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
2006-06-10 13:15:32 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive ( IWineD3DDevice * iface ,
2006-10-12 08:23:55 +02:00
WINED3DPRIMITIVETYPE PrimitiveType ,
2007-01-02 21:07:39 +01:00
UINT minIndex , UINT NumVertices , UINT startIndex , UINT primCount ) {
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
UINT idxStride = 2 ;
IWineD3DIndexBuffer * pIB ;
2006-03-14 23:14:40 +01:00
WINED3DINDEXBUFFER_DESC IdxBufDsc ;
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 . */
ERR ( " (%p) : Called without a valid index buffer set, returning WINED3DERR_INVALIDCALL \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 ;
}
2007-02-19 15:25:32 +01:00
vbo = ( ( IWineD3DIndexBufferImpl * ) pIB ) - > vbo ;
2004-12-09 12:42:34 +01:00
2007-01-02 21:07:39 +01:00
TRACE ( " (%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n " , This ,
2004-12-09 12:42:34 +01:00
PrimitiveType , debug_d3dprimitivetype ( PrimitiveType ) ,
2007-01-02 21:07:39 +01:00
minIndex , NumVertices , startIndex , primCount ) ;
2004-12-09 12:42:34 +01:00
IWineD3DIndexBuffer_GetDesc ( pIB , & IdxBufDsc ) ;
2005-03-03 14:57:15 +01:00
if ( IdxBufDsc . Format = = WINED3DFMT_INDEX16 ) {
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 ) ;
}
2007-01-02 21:07:39 +01:00
drawPrimitive ( iface , PrimitiveType , primCount , 0 , NumVertices , startIndex ,
2007-02-19 15:25:32 +01:00
idxStride , vbo ? NULL : ( ( IWineD3DIndexBufferImpl * ) 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
}
2006-10-12 08:23:55 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP ( IWineD3DDevice * iface , WINED3DPRIMITIVETYPE PrimitiveType ,
2004-12-09 12:42:34 +01:00
UINT PrimitiveCount , CONST void * pVertexStreamZeroData ,
UINT VertexStreamZeroStride ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-08-14 14:49:39 +02:00
IWineD3DVertexBuffer * vb ;
2004-12-09 12:42:34 +01:00
2005-07-13 16:15:54 +02:00
TRACE ( " (%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d \n " , This , PrimitiveType ,
debug_d3dprimitivetype ( PrimitiveType ) ,
2004-12-09 12:42:34 +01:00
PrimitiveCount , pVertexStreamZeroData , VertexStreamZeroStride ) ;
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 ] ;
2005-07-05 16:05:18 +02:00
This - > stateBlock - > streamSource [ 0 ] = ( IWineD3DVertexBuffer * ) pVertexStreamZeroData ;
2007-08-14 14:49:39 +02:00
if ( vb ) IWineD3DVertexBuffer_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 ) ;
2007-01-06 18:19:55 +01:00
drawPrimitive ( iface , PrimitiveType , PrimitiveCount , 0 /* start vertex */ , 0 /* NumVertices */ ,
2007-01-02 21:13:28 +01:00
0 /* indxStart*/ , 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
}
2006-10-12 08:23:55 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP ( IWineD3DDevice * iface , WINED3DPRIMITIVETYPE PrimitiveType ,
2005-08-19 12:05:00 +02:00
UINT MinVertexIndex , UINT NumVertices ,
UINT PrimitiveCount , CONST void * pIndexData ,
WINED3DFORMAT IndexDataFormat , CONST void * pVertexStreamZeroData ,
2004-12-09 12:42:34 +01:00
UINT VertexStreamZeroStride ) {
int idxStride ;
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
2007-08-14 14:49:39 +02:00
IWineD3DVertexBuffer * vb ;
2007-08-14 14:46:38 +02:00
IWineD3DIndexBuffer * ib ;
2004-12-09 12:42:34 +01:00
2005-07-13 16:15:54 +02:00
TRACE ( " (%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d \n " ,
2004-12-09 12:42:34 +01:00
This , PrimitiveType , debug_d3dprimitivetype ( PrimitiveType ) ,
2005-08-19 12:05:00 +02:00
MinVertexIndex , NumVertices , PrimitiveCount , pIndexData ,
2004-12-09 12:42:34 +01:00
IndexDataFormat , pVertexStreamZeroData , VertexStreamZeroStride ) ;
2005-03-03 14:57:15 +01:00
if ( IndexDataFormat = = WINED3DFMT_INDEX16 ) {
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 ] ;
2005-07-05 16:05:18 +02:00
This - > stateBlock - > streamSource [ 0 ] = ( IWineD3DVertexBuffer * ) pVertexStreamZeroData ;
2007-08-14 14:49:39 +02:00
if ( vb ) IWineD3DVertexBuffer_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
2007-01-02 21:13:28 +01:00
drawPrimitive ( iface , PrimitiveType , PrimitiveCount , 0 /* vertexStart */ , NumVertices , 0 /* indxStart */ , 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 ) {
IWineD3DIndexBuffer_Release ( ib ) ;
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
}
2006-10-12 08:23:55 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided ( IWineD3DDevice * iface , WINED3DPRIMITIVETYPE PrimitiveType , UINT PrimitiveCount , WineDirect3DVertexStridedData * DrawPrimStrideData ) {
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 ;
drawPrimitive ( iface , PrimitiveType , PrimitiveCount , 0 , 0 , 0 , 0 , NULL , 0 ) ;
This - > up_strided = NULL ;
2006-05-06 16:58:57 +02:00
return WINED3D_OK ;
}
2007-07-27 14:39:55 +02:00
static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided ( IWineD3DDevice * iface , WINED3DPRIMITIVETYPE PrimitiveType , UINT PrimitiveCount , WineDirect3DVertexStridedData * DrawPrimStrideData , UINT NumVertices , CONST void * pIndexData , WINED3DFORMAT IndexDataFormat ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
DWORD idxSize = ( IndexDataFormat = = WINED3DFMT_INDEX32 ? 4 : 2 ) ;
/* 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 ;
drawPrimitive ( iface , PrimitiveType , PrimitiveCount , 0 /* startvertexidx */ , 0 /* numindices */ , 0 /* startidx */ , idxSize , pIndexData , 0 /* minindex */ ) ;
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 ) ) {
2006-04-07 12:51:12 +02:00
WARN ( " (%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL \n " , This , pSourceTexture , pDestinationTexture ) ;
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 ) {
2005-11-04 13:39:17 +01:00
/* Make sure that the destination texture is loaded */
IWineD3DBaseTexture_PreLoad ( pDestinationTexture ) ;
/* 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 ;
hr = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , ( IWineD3DSwapChain * * ) & 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 ;
/* return a sensible default */
* pNumPasses = 1 ;
2006-04-07 12:51:12 +02:00
/* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
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-27 11:40:57 +01:00
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 ;
TRACE ( " (%p) : PaletteNumber %u \n " , This , PaletteNumber ) ;
if ( PaletteNumber < 0 | | PaletteNumber > = MAX_PALETTES ) {
WARN ( " (%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
}
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 ;
}
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 ) ;
if ( PaletteNumber < 0 | | PaletteNumber > = MAX_PALETTES ) {
WARN ( " (%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
}
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 ) ;
if ( PaletteNumber < 0 | | PaletteNumber > = MAX_PALETTES ) {
WARN ( " (%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
}
/*TODO: stateblocks */
This - > currentPalette = PaletteNumber ;
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 ;
2005-08-11 12:31:40 +02:00
static BOOL showFixmes = TRUE ;
if ( showFixmes ) {
FIXME ( " (%p) : stub \n " , This ) ;
showFixmes = FALSE ;
}
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 ;
2005-08-11 12:31:40 +02:00
static BOOL showFixmes = TRUE ;
if ( showFixmes ) {
FIXME ( " (%p) : stub \n " , This ) ;
showFixmes = FALSE ;
}
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 ) ;
hr = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , ( IWineD3DSwapChain * * ) & 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 ;
static BOOL showfixmes = TRUE ;
2005-07-13 16:15:54 +02:00
if ( nSegments ! = 0.0f ) {
if ( showfixmes ) {
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) : stub nSegments(%f) \n " , This , nSegments ) ;
showfixmes = FALSE ;
}
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 ;
2005-03-02 13:16:10 +01:00
static BOOL showfixmes = TRUE ;
2005-07-13 16:15:54 +02:00
if ( showfixmes ) {
2005-03-02 13:16:10 +01:00
FIXME ( " (%p) : stub returning(%f) \n " , This , 0.0f ) ;
showfixmes = FALSE ;
}
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 ;
2007-08-11 20:02:01 +02:00
GLenum dummy ;
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
memset ( & winedesc , 0 , sizeof ( winedesc ) ) ;
winedesc . Width = & srcSurfaceWidth ;
winedesc . Height = & srcSurfaceHeight ;
winedesc . Pool = & srcPool ;
winedesc . Format = & srcFormat ;
IWineD3DSurface_GetDesc ( pSourceSurface , & winedesc ) ;
winedesc . Width = & destSurfaceWidth ;
winedesc . Height = & destSurfaceHeight ;
winedesc . Pool = & destPool ;
winedesc . Format = & destFormat ;
winedesc . Size = & destSize ;
IWineD3DSurface_GetDesc ( pDestinationSurface , & winedesc ) ;
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 ,
pSourceSurface , ( RECT * ) pSourceRect , 0 ) ;
}
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 ) ;
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2007-02-20 22:44:45 +01:00
if ( GL_SUPPORT ( ARB_MULTITEXTURE ) ) {
GL_EXTCALL ( glActiveTextureARB ( GL_TEXTURE0_ARB ) ) ;
checkGLcall ( " glActiveTextureARB " ) ;
}
2005-11-23 20:14:43 +01:00
/* Make sure the surface is loaded and up to date */
2005-07-12 19:02:47 +02:00
IWineD3DSurface_PreLoad ( pDestinationSurface ) ;
IWineD3DSurface_GetGlDesc ( pDestinationSurface , & glDescription ) ;
2005-03-02 13:16:10 +01:00
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 ) {
2007-03-31 13:01:48 +02:00
rowoffset = srcSurfaceWidth * pSrcSurface - > bytesPerPixel ;
2007-01-12 00:20:42 +01:00
offset + = srcLeft * pSrcSurface - > bytesPerPixel ;
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 ) {
2007-03-31 13:01:48 +02:00
offset + = pSourceRect - > top * srcSurfaceWidth * pSrcSurface - > bytesPerPixel ;
2005-07-12 19:02:47 +02:00
}
TRACE ( " (%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p \n "
, This
, glDescription - > level
, destLeft
, destTop
, srcWidth
, srcHeight
, glDescription - > glFormat
, glDescription - > glType
, IWineD3DSurface_GetData ( pSourceSurface )
) ;
/* 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
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
2005-07-12 19:02:47 +02:00
/* hopefully using pointer addtion 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
for ( j = destTop ; j < ( srcHeight + destTop ) ; j + + ) {
glTexSubImage2D ( glDescription - > target
, glDescription - > level
, destLeft
, j
, srcWidth
, 1
, glDescription - > glFormat
, glDescription - > glType
2005-11-04 12:13:45 +01:00
, data /* could be quicker using */
2005-07-12 19:02:47 +02:00
) ;
data + = rowoffset ;
}
} else { /* Full width, so just write out the whole texture */
if ( WINED3DFMT_DXT1 = = destFormat | |
2005-08-29 14:20:02 +02:00
WINED3DFMT_DXT2 = = destFormat | |
2005-07-12 19:02:47 +02:00
WINED3DFMT_DXT3 = = destFormat | |
2005-08-29 14:20:02 +02:00
WINED3DFMT_DXT4 = = destFormat | |
2005-07-12 19:02:47 +02:00
WINED3DFMT_DXT5 = = destFormat ) {
if ( GL_SUPPORT ( EXT_TEXTURE_COMPRESSION_S3TC ) ) {
if ( destSurfaceHeight ! = srcHeight | | destSurfaceWidth ! = srcWidth ) {
2006-11-12 19:51:37 +01:00
/* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
2005-07-12 19:02:47 +02:00
FIXME ( " Updating part of a compressed texture is not supported at the moment \n " ) ;
} if ( destFormat ! = srcFormat ) {
FIXME ( " Updating mixed format compressed texture is not curretly support \n " ) ;
} else {
GL_EXTCALL ( glCompressedTexImage2DARB ) ( glDescription - > target ,
glDescription - > level ,
glDescription - > glFormatInternal ,
srcWidth ,
srcHeight ,
0 ,
destSize ,
IWineD3DSurface_GetData ( pSourceSurface ) ) ;
}
} else {
FIXME ( " Attempting to update a DXT compressed texture without hardware support \n " ) ;
}
} else {
2007-02-13 20:21:48 +01:00
glTexSubImage2D ( glDescription - > target
2005-07-12 19:02:47 +02:00
, glDescription - > level
, destLeft
, destTop
2007-02-13 20:21:48 +01:00
, srcWidth
, srcHeight
2005-07-12 19:02:47 +02:00
, glDescription - > glFormat
, glDescription - > glType
, IWineD3DSurface_GetData ( pSourceSurface )
) ;
}
}
checkGLcall ( " glTexSubImage2D " ) ;
LEAVE_GL ( ) ;
2007-10-09 22:17:59 +02:00
IWineD3DSurface_ModifyLocation ( pDestinationSurface , SFLAG_INTEXTURE , TRUE ) ;
2007-02-20 22:44:45 +01:00
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( 0 ) ) ;
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 ;
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 ) {
memcpy ( & patch - > RectPatchInfo , pRectPatchInfo , sizeof ( * pRectPatchInfo ) ) ;
}
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 ;
IWineD3DDevice_DrawPrimitiveStrided ( iface , WINED3DPT_TRIANGLELIST , patch - > numSegs [ 0 ] * patch - > numSegs [ 1 ] * 2 , & patch - > strided ) ;
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
}
2005-03-02 13:16:10 +01:00
/* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
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 */
FIXME ( " Attempt to destroy nonexistant patch \n " ) ;
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 ;
}
static void bind_fbo ( IWineD3DDevice * iface , GLenum target , GLuint * fbo ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
if ( ! * fbo ) {
GL_EXTCALL ( glGenFramebuffersEXT ( 1 , fbo ) ) ;
checkGLcall ( " glGenFramebuffersEXT() " ) ;
}
GL_EXTCALL ( glBindFramebufferEXT ( target , * fbo ) ) ;
checkGLcall ( " glBindFramebuffer() " ) ;
}
static void attach_surface_fbo ( IWineD3DDeviceImpl * This , GLenum fbo_target , DWORD idx , IWineD3DSurface * surface ) {
const IWineD3DSurfaceImpl * surface_impl = ( IWineD3DSurfaceImpl * ) surface ;
2007-06-07 18:57:15 +02:00
IWineD3DBaseTextureImpl * texture_impl ;
2007-04-16 21:21:13 +02:00
GLenum texttarget , target ;
GLint old_binding ;
texttarget = surface_impl - > glDescription . target ;
target = texttarget = = GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB ;
glGetIntegerv ( texttarget = = GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB , & old_binding ) ;
IWineD3DSurface_PreLoad ( surface ) ;
2007-06-07 18:57:15 +02:00
glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
2007-04-16 21:21:13 +02:00
glBindTexture ( target , old_binding ) ;
2007-06-07 18:57:15 +02:00
/* Update base texture states array */
if ( SUCCEEDED ( IWineD3DSurface_GetContainer ( surface , & IID_IWineD3DBaseTexture , ( void * * ) & texture_impl ) ) ) {
texture_impl - > baseTexture . states [ WINED3DTEXSTA_MINFILTER ] = WINED3DTEXF_POINT ;
texture_impl - > baseTexture . states [ WINED3DTEXSTA_MAGFILTER ] = WINED3DTEXF_POINT ;
if ( texture_impl - > baseTexture . bindCount ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( texture_impl - > baseTexture . sampler ) ) ;
}
IWineD3DBaseTexture_Release ( ( IWineD3DBaseTexture * ) texture_impl ) ;
}
2007-08-21 23:22:33 +02:00
GL_EXTCALL ( glFramebufferTexture2DEXT ( fbo_target , GL_COLOR_ATTACHMENT0_EXT + idx , texttarget ,
surface_impl - > glDescription . textureName , surface_impl - > glDescription . level ) ) ;
2007-04-16 21:21:13 +02:00
checkGLcall ( " attach_surface_fbo " ) ;
}
static void color_fill_fbo ( IWineD3DDevice * iface , IWineD3DSurface * surface , CONST WINED3DRECT * rect , WINED3DCOLOR color ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSwapChain * swapchain ;
swapchain = get_swapchain ( surface ) ;
if ( swapchain ) {
GLenum buffer ;
TRACE ( " Surface %p is onscreen \n " , surface ) ;
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 ) ;
2007-05-03 20:57:50 +02:00
bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > dst_fbo ) ;
attach_surface_fbo ( This , GL_FRAMEBUFFER_EXT , 0 , surface ) ;
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 " ) ;
} else {
glDisable ( GL_SCISSOR_TEST ) ;
}
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_SCISSORTESTENABLE ) ) ;
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_RENDER ( WINED3DRS_COLORWRITEENABLE ) ) ;
glClearColor ( D3DCOLOR_R ( color ) , D3DCOLOR_G ( color ) , D3DCOLOR_B ( color ) , D3DCOLOR_A ( color ) ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
checkGLcall ( " glClear " ) ;
if ( This - > render_offscreen ) {
bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > fbo ) ;
} else {
GL_EXTCALL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , 0 ) ) ;
checkGLcall ( " glBindFramebuffer() " ) ;
}
if ( swapchain & & surface = = ( ( IWineD3DSwapChainImpl * ) swapchain ) - > frontBuffer
& & ( ( IWineD3DSwapChainImpl * ) swapchain ) - > backBuffer ) {
glDrawBuffer ( GL_BACK ) ;
checkGLcall ( " glDrawBuffer() " ) ;
}
}
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 ;
case WINED3DFMT_A8 :
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 :
case WINED3DFMT_A8B8G8R8 :
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 ;
case WINED3DFMT_A2B10G10R10 :
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 ) {
color_fill_fbo ( iface , pSurface , pRect , color ) ;
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 ) ;
2007-08-31 20:58:35 +02:00
BltFx . u5 . dwFillColor = argb_to_fmt ( color , surface - > resource . format ) ;
2007-04-16 21:21:13 +02:00
return IWineD3DSurface_Blt ( pSurface , ( RECT * ) pRect , NULL , NULL , WINEDDBLT_COLORFILL , & BltFx , WINED3DTEXF_NONE ) ;
}
2004-10-07 06:22:21 +02:00
}
2005-03-02 13:16:10 +01:00
/* rendertarget and deptth 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 )
IWineD3DSurface_SetContainer ( Swapchain - > frontBuffer , NULL ) ;
Swapchain - > frontBuffer = Front ;
if ( Swapchain - > frontBuffer ) {
IWineD3DSurface_SetContainer ( Swapchain - > frontBuffer , ( IWineD3DBase * ) Swapchain ) ;
}
}
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 ] )
IWineD3DSurface_SetContainer ( Swapchain - > backBuffer [ 0 ] , NULL ) ;
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 ) ;
} else {
HeapFree ( GetProcessHeap ( ) , 0 , Swapchain - > backBuffer ) ;
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 ;
2005-07-26 20:56:18 +02:00
* ppZStencilSurface = This - > depthStencilBuffer ;
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
}
2006-11-17 13:24:00 +01:00
/* TODO: Handle stencil attachments */
static void set_depth_stencil_fbo ( IWineD3DDevice * iface , IWineD3DSurface * depth_stencil ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSurfaceImpl * depth_stencil_impl = ( IWineD3DSurfaceImpl * ) depth_stencil ;
2007-04-09 01:53:27 +02:00
TRACE ( " Set depth stencil to %p \n " , depth_stencil ) ;
2006-11-17 13:24:00 +01:00
if ( depth_stencil_impl ) {
2007-04-09 01:53:32 +02:00
if ( depth_stencil_impl - > current_renderbuffer ) {
GL_EXTCALL ( glFramebufferRenderbufferEXT ( GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_RENDERBUFFER_EXT , depth_stencil_impl - > current_renderbuffer - > id ) ) ;
checkGLcall ( " glFramebufferRenderbufferEXT() " ) ;
} else {
2007-06-07 18:57:15 +02:00
IWineD3DBaseTextureImpl * texture_impl ;
2007-04-09 01:53:32 +02:00
GLenum texttarget , target ;
GLint old_binding = 0 ;
2006-11-18 17:07:47 +01:00
2007-04-09 01:53:32 +02:00
texttarget = depth_stencil_impl - > glDescription . target ;
target = texttarget = = GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB ;
glGetIntegerv ( texttarget = = GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB , & old_binding ) ;
2007-04-09 01:53:27 +02:00
2007-04-09 01:53:32 +02:00
IWineD3DSurface_PreLoad ( depth_stencil ) ;
2007-04-09 01:53:27 +02:00
2007-04-09 01:53:32 +02:00
glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( target , GL_DEPTH_TEXTURE_MODE_ARB , GL_LUMINANCE ) ;
glBindTexture ( target , old_binding ) ;
2006-11-17 13:24:00 +01:00
2007-06-07 18:57:15 +02:00
/* Update base texture states array */
if ( SUCCEEDED ( IWineD3DSurface_GetContainer ( depth_stencil , & IID_IWineD3DBaseTexture , ( void * * ) & texture_impl ) ) ) {
texture_impl - > baseTexture . states [ WINED3DTEXSTA_MINFILTER ] = WINED3DTEXF_POINT ;
texture_impl - > baseTexture . states [ WINED3DTEXSTA_MAGFILTER ] = WINED3DTEXF_POINT ;
if ( texture_impl - > baseTexture . bindCount ) {
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( texture_impl - > baseTexture . sampler ) ) ;
}
IWineD3DBaseTexture_Release ( ( IWineD3DBaseTexture * ) texture_impl ) ;
}
2007-08-21 23:22:33 +02:00
GL_EXTCALL ( glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , texttarget ,
depth_stencil_impl - > glDescription . textureName , depth_stencil_impl - > glDescription . level ) ) ;
2007-04-09 01:53:32 +02:00
checkGLcall ( " glFramebufferTexture2DEXT() " ) ;
}
2006-11-17 13:24:00 +01:00
} else {
GL_EXTCALL ( glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT , GL_DEPTH_ATTACHMENT_EXT , GL_TEXTURE_2D , 0 , 0 ) ) ;
checkGLcall ( " glFramebufferTexture2DEXT() " ) ;
}
}
2007-04-09 01:53:58 +02:00
static void set_render_target_fbo ( IWineD3DDevice * iface , DWORD idx , IWineD3DSurface * render_target ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSurfaceImpl * rtimpl = ( IWineD3DSurfaceImpl * ) render_target ;
2006-12-19 19:25:35 +01:00
2007-04-09 01:53:58 +02:00
TRACE ( " Set render target %u to %p \n " , idx , render_target ) ;
if ( rtimpl ) {
attach_surface_fbo ( This , GL_FRAMEBUFFER_EXT , idx , render_target ) ;
2006-12-19 19:25:35 +01:00
This - > draw_buffers [ idx ] = GL_COLOR_ATTACHMENT0_EXT + idx ;
2006-11-17 13:24:00 +01:00
} else {
2006-12-19 19:25:35 +01:00
GL_EXTCALL ( glFramebufferTexture2DEXT ( GL_FRAMEBUFFER_EXT , GL_COLOR_ATTACHMENT0_EXT + idx , GL_TEXTURE_2D , 0 , 0 ) ) ;
checkGLcall ( " glFramebufferTexture2DEXT() " ) ;
This - > draw_buffers [ idx ] = GL_NONE ;
}
2007-04-09 01:53:27 +02:00
}
2006-12-19 19:25:35 +01:00
2007-04-09 01:53:27 +02:00
static void check_fbo_status ( IWineD3DDevice * iface ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
GLenum status ;
status = GL_EXTCALL ( glCheckFramebufferStatusEXT ( GL_FRAMEBUFFER_EXT ) ) ;
2007-04-16 21:19:20 +02:00
if ( status = = GL_FRAMEBUFFER_COMPLETE_EXT ) {
TRACE ( " FBO complete \n " ) ;
} else {
FIXME ( " FBO status %s (%#x) \n " , debug_fbostatus ( status ) , status ) ;
/* Dump the FBO attachments */
if ( status = = GL_FRAMEBUFFER_UNSUPPORTED_EXT ) {
IWineD3DSurfaceImpl * attachment ;
int i ;
for ( i = 0 ; i < GL_LIMITS ( buffers ) ; + + i ) {
attachment = ( IWineD3DSurfaceImpl * ) This - > fbo_color_attachments [ i ] ;
if ( attachment ) {
FIXME ( " \t Color attachment %d: (%p) %s %ux%u \n " , i , attachment , debug_d3dformat ( attachment - > resource . format ) ,
attachment - > pow2Width , attachment - > pow2Height ) ;
}
}
attachment = ( IWineD3DSurfaceImpl * ) This - > fbo_depth_attachment ;
if ( attachment ) {
FIXME ( " \t Depth attachment: (%p) %s %ux%u \n " , attachment , debug_d3dformat ( attachment - > resource . format ) ,
attachment - > pow2Width , attachment - > pow2Height ) ;
}
}
2006-12-19 19:25:35 +01:00
}
2007-04-09 01:53:27 +02:00
}
2006-12-19 19:25:35 +01:00
2007-04-09 01:53:32 +02:00
static BOOL depth_mismatch_fbo ( IWineD3DDevice * iface ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
IWineD3DSurfaceImpl * rt_impl = ( IWineD3DSurfaceImpl * ) This - > render_targets [ 0 ] ;
IWineD3DSurfaceImpl * ds_impl = ( IWineD3DSurfaceImpl * ) This - > stencilBufferTarget ;
if ( ! ds_impl ) return FALSE ;
if ( ds_impl - > current_renderbuffer ) {
return ( rt_impl - > pow2Width ! = ds_impl - > current_renderbuffer - > width | |
rt_impl - > pow2Height ! = ds_impl - > current_renderbuffer - > height ) ;
}
return ( rt_impl - > pow2Width ! = ds_impl - > pow2Width | |
rt_impl - > pow2Height ! = ds_impl - > pow2Height ) ;
}
2007-04-09 01:53:27 +02:00
void apply_fbo_state ( IWineD3DDevice * iface ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
unsigned int i ;
if ( This - > render_offscreen ) {
2007-04-09 01:53:47 +02:00
bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > fbo ) ;
2007-04-09 01:53:27 +02:00
/* Apply render targets */
for ( i = 0 ; i < GL_LIMITS ( buffers ) ; + + i ) {
IWineD3DSurface * render_target = This - > render_targets [ i ] ;
if ( This - > fbo_color_attachments [ i ] ! = render_target ) {
set_render_target_fbo ( iface , i , render_target ) ;
This - > fbo_color_attachments [ i ] = render_target ;
}
}
/* Apply depth targets */
2007-04-09 01:53:32 +02:00
if ( This - > fbo_depth_attachment ! = This - > stencilBufferTarget | | depth_mismatch_fbo ( iface ) ) {
unsigned int w = ( ( IWineD3DSurfaceImpl * ) This - > render_targets [ 0 ] ) - > pow2Width ;
unsigned int h = ( ( IWineD3DSurfaceImpl * ) This - > render_targets [ 0 ] ) - > pow2Height ;
if ( This - > stencilBufferTarget ) {
surface_set_compatible_renderbuffer ( This - > stencilBufferTarget , w , h ) ;
}
2007-04-09 01:53:27 +02:00
set_depth_stencil_fbo ( iface , This - > stencilBufferTarget ) ;
This - > fbo_depth_attachment = This - > stencilBufferTarget ;
}
if ( GL_SUPPORT ( ARB_DRAW_BUFFERS ) ) {
GL_EXTCALL ( glDrawBuffersARB ( GL_LIMITS ( buffers ) , This - > draw_buffers ) ) ;
checkGLcall ( " glDrawBuffers() " ) ;
2007-04-16 21:20:01 +02:00
} else {
glDrawBuffer ( This - > draw_buffers [ 0 ] ) ;
checkGLcall ( " glDrawBuffer() " ) ;
2007-04-09 01:53:27 +02:00
}
} else {
2006-11-17 13:24:00 +01:00
GL_EXTCALL ( glBindFramebufferEXT ( GL_FRAMEBUFFER_EXT , 0 ) ) ;
}
2007-04-09 01:53:27 +02:00
check_fbo_status ( iface ) ;
2006-11-17 13:24:00 +01:00
}
2007-05-03 20:57:09 +02:00
void stretch_rect_fbo ( IWineD3DDevice * iface , IWineD3DSurface * src_surface , WINED3DRECT * src_rect ,
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 ;
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 ) ;
if ( src_swapchain ) {
GLenum buffer ;
2007-04-10 19:13:44 +02:00
TRACE ( " Source surface %p is onscreen \n " , src_surface ) ;
2007-06-09 14:59:15 +02:00
ActivateContext ( This , src_surface , CTXUSAGE_RESOURCELOAD ) ;
2007-04-16 21:20:56 +02:00
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
buffer = surface_get_gl_buffer ( src_surface , src_swapchain ) ;
glReadBuffer ( buffer ) ;
checkGLcall ( " glReadBuffer() " ) ;
2007-05-03 20:57:09 +02:00
src_rect - > y1 = ( ( IWineD3DSurfaceImpl * ) src_surface ) - > currentDesc . Height - src_rect - > y1 ;
src_rect - > y2 = ( ( IWineD3DSurfaceImpl * ) src_surface ) - > currentDesc . Height - src_rect - > y2 ;
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 ( ) ;
2007-04-09 01:54:07 +02:00
bind_fbo ( iface , GL_READ_FRAMEBUFFER_EXT , & This - > src_fbo ) ;
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() " ) ;
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
dst_swapchain = get_swapchain ( dst_surface ) ;
if ( dst_swapchain ) {
GLenum buffer ;
2007-04-10 19:13:44 +02:00
TRACE ( " Destination surface %p is onscreen \n " , dst_surface ) ;
2007-06-09 14:59:15 +02:00
ActivateContext ( This , dst_surface , CTXUSAGE_RESOURCELOAD ) ;
2007-04-16 21:20:56 +02:00
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
buffer = surface_get_gl_buffer ( dst_surface , dst_swapchain ) ;
glDrawBuffer ( buffer ) ;
checkGLcall ( " glDrawBuffer() " ) ;
2007-05-03 20:57:09 +02:00
dst_rect - > y1 = ( ( IWineD3DSurfaceImpl * ) dst_surface ) - > currentDesc . Height - dst_rect - > y1 ;
dst_rect - > y2 = ( ( IWineD3DSurfaceImpl * ) dst_surface ) - > currentDesc . Height - dst_rect - > y2 ;
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
/* No src or dst swapchain? Make sure some context is active(multithreading) */
if ( ! src_swapchain ) {
ActivateContext ( This , This - > lastActiveRenderTarget , CTXUSAGE_RESOURCELOAD ) ;
}
2007-08-06 16:27:08 +02:00
ENTER_GL ( ) ;
2007-04-09 01:54:07 +02:00
bind_fbo ( iface , GL_DRAW_FRAMEBUFFER_EXT , & This - > dst_fbo ) ;
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() " ) ;
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
}
if ( This - > render_offscreen ) {
bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > fbo ) ;
} 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 ) ) {
ERR ( " (%p) : Only %d render targets are supported. \n " , This , GL_LIMITS ( buffers ) ) ;
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
see http : //msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
for more details
*/
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
}
2006-12-19 19:25:42 +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 ) ;
2007-02-12 19:21:10 +01:00
/* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
* ctx properly .
* Use resourceload usage , this will just set the drawables and context but not apply any states . The stateblock may be
* incomplete or incorrect when SetRenderTarget is called . DrawPrim ( ) will apply the states when it is called .
*/
ActivateContext ( This , This - > render_targets [ 0 ] , CTXUSAGE_RESOURCELOAD ) ;
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 ;
TRACE ( " (%p) Swapping z-buffer \n " , This ) ;
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 {
2005-07-07 22:35:05 +02:00
/** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure 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
2005-07-07 22:35:05 +02:00
* stencil buffer and incure an extra memory overhead
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
tmp = This - > stencilBufferTarget ;
This - > stencilBufferTarget = pNewZStencil ;
2007-04-09 01:53:27 +02:00
This - > depth_copy_state = WINED3D_DCS_NO_COPY ;
2005-07-07 22:35:05 +02:00
/* 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 */
if ( WINED3DFMT_A8R8G8B8 ! = pSur - > resource . format ) {
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 ) ) )
{
2007-07-23 11:13:37 +02:00
const GlPixelFormatDesc * glDesc ;
2007-07-27 13:22:54 +02:00
const StaticPixelFormatDesc * tableEntry = getFormatDescEntry ( WINED3DFMT_A8R8G8B8 , & GLINFO_LOCATION , & glDesc ) ;
2007-05-15 00:37:53 +02:00
char * mem , * bits = ( char * ) 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 ;
INT bpp = tableEntry - > bpp ;
INT i ;
/* 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 ) ;
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 */
if ( GL_SUPPORT ( ARB_MULTITEXTURE ) ) {
GL_EXTCALL ( glActiveTextureARB ( GL_TEXTURE0_ARB ) ) ;
checkGLcall ( " glActiveTextureARB " ) ;
}
IWineD3DDeviceImpl_MarkStateDirty ( This , STATE_SAMPLER ( 0 ) ) ;
/* 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 ;
2006-10-01 05:20:10 +02:00
TRACE ( " (%p) : state (%u) \n " , This , This - > state ) ;
2005-09-21 12:55:03 +02:00
/* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
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
{
ResourceList * resourceList = This - > resources ;
while ( NULL ! = resourceList ) {
2006-03-28 14:20:47 +02:00
if ( ( ( IWineD3DResourceImpl * ) resourceList - > resource ) - > resource . pool = = WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/ )
2006-04-07 12:51:12 +02:00
return WINED3DERR_DEVICENOTRESET ;
2005-09-21 12:55:03 +02:00
resourceList = resourceList - > next ;
}
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
}
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 ;
/** FIXME: Resource tracking needs to be done,
* The closes we can do to this is set the priorities of all managed textures low
* and then reset them .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
FIXME ( " (%p) : stub \n " , This ) ;
2006-04-07 12:51:12 +02:00
return WINED3D_OK ;
2005-03-02 13:16:10 +01:00
}
2007-03-12 16:50:54 +01:00
static void updateSurfaceDesc ( IWineD3DSurfaceImpl * surface , 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 ;
2007-02-13 20:21:48 +01:00
if ( GL_SUPPORT ( ARB_TEXTURE_NON_POWER_OF_TWO ) ) {
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
}
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 ;
}
HeapFree ( GetProcessHeap ( ) , 0 , surface - > resource . allocatedMemory ) ;
surface - > resource . size = IWineD3DSurface_GetPitch ( ( IWineD3DSurface * ) surface ) * surface - > pow2Width ;
}
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 ;
}
/* 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 " ) ;
}
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > EnableAutoDepthStencil ! = swapchain - > presentParms . EnableAutoDepthStencil ) {
2006-12-08 16:13:15 +01:00
ERR ( " What do do about a changed auto depth stencil parameter? \n " ) ;
}
2007-02-15 22:36:50 +01: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
{
WINED3DVIEWPORT vp ;
int i ;
vp . X = 0 ;
vp . Y = 0 ;
2007-02-15 22:36:50 +01:00
vp . Width = pPresentationParameters - > BackBufferWidth ;
vp . Height = pPresentationParameters - > BackBufferHeight ;
2006-12-08 16:13:15 +01:00
vp . MinZ = 0 ;
vp . MaxZ = 1 ;
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 ) ;
}
/* Now set the new viewport */
IWineD3DDevice_SetViewport ( iface , & vp ) ;
}
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
/* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
2007-02-15 22:36:50 +01:00
if ( ! pPresentationParameters - > Windowed ) {
2007-02-14 17:59:08 +01:00
IWineD3DDevice_SetFullscreen ( iface , TRUE ) ;
}
2006-12-08 16:13:15 +01:00
IWineD3DDevice_SetDisplayMode ( iface , 0 , & mode ) ;
2007-02-14 17:59:08 +01:00
/* Switching out of fullscreen mode? First set the original res, then change the window */
2007-02-15 22:36:50 +01:00
if ( pPresentationParameters - > Windowed ) {
2007-02-14 17:59:08 +01:00
IWineD3DDevice_SetFullscreen ( iface , FALSE ) ;
}
2007-02-15 22:36:50 +01:00
swapchain - > presentParms . Windowed = pPresentationParameters - > Windowed ;
2006-12-08 16:13:15 +01:00
}
IWineD3DSwapChain_Release ( ( IWineD3DSwapChain * ) swapchain ) ;
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_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 ;
2006-04-07 12:51:12 +02:00
HRESULT hrc = WINED3D_OK ;
2005-06-23 13:05:24 +02:00
TRACE ( " Relaying to swapchain \n " ) ;
2006-04-07 12:51:12 +02:00
if ( ( hrc = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapchain ) ) = = WINED3D_OK ) {
2006-04-04 13:44:17 +02:00
IWineD3DSwapChain_SetGammaRamp ( swapchain , Flags , ( WINED3DGAMMARAMP * ) 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 ;
2006-04-07 12:51:12 +02:00
HRESULT hrc = WINED3D_OK ;
2005-03-02 13:16:10 +01:00
2005-06-23 13:05:24 +02:00
TRACE ( " Relaying to swapchain \n " ) ;
2006-04-07 12:51:12 +02:00
if ( ( hrc = IWineD3DDeviceImpl_GetSwapChain ( iface , iSwapChain , & swapchain ) ) = = WINED3D_OK ) {
2005-06-23 13:05:24 +02:00
hrc = 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 ,
* any handels to other resource held by the caller must be closed
* ( e . g . a texture should release all held surfaces because telling the device that it ' s been released . )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void WINAPI IWineD3DDeviceImpl_AddResource ( IWineD3DDevice * iface , IWineD3DResource * resource ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
ResourceList * resourceList ;
TRACE ( " (%p) : resource %p \n " , This , resource ) ;
/* add a new texture to the frot of the linked list */
resourceList = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( ResourceList ) ) ;
resourceList - > resource = resource ;
/* Get the old head */
resourceList - > next = This - > resources ;
This - > resources = resourceList ;
TRACE ( " Added resource %p with element %p pointing to %p \n " , resource , resourceList , resourceList - > next ) ;
return ;
}
static void WINAPI IWineD3DDeviceImpl_RemoveResource ( IWineD3DDevice * iface , IWineD3DResource * resource ) {
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
ResourceList * resourceList = NULL ;
ResourceList * previousResourceList = NULL ;
TRACE ( " (%p) : resource %p \n " , This , resource ) ;
resourceList = This - > resources ;
while ( resourceList ! = NULL ) {
if ( resourceList - > resource = = resource ) break ;
previousResourceList = resourceList ;
resourceList = resourceList - > next ;
}
if ( resourceList = = NULL ) {
FIXME ( " Attempted to remove resource %p that hasn't been stored \n " , resource ) ;
return ;
} else {
TRACE ( " Found resource %p with element %p pointing to %p (previous %p) \n " , resourceList - > resource , resourceList , resourceList - > next , previousResourceList ) ;
}
/* make sure we don't leave a hole in the list */
if ( previousResourceList ! = NULL ) {
previousResourceList - > next = resourceList - > next ;
} else {
This - > resources = resourceList - > next ;
}
return ;
}
2006-06-10 13:15:32 +02:00
static void WINAPI IWineD3DDeviceImpl_ResourceReleased ( IWineD3DDevice * iface , IWineD3DResource * resource ) {
2005-07-26 12:34:15 +02:00
IWineD3DDeviceImpl * This = ( IWineD3DDeviceImpl * ) iface ;
int counter ;
TRACE ( " (%p) : resource %p \n " , This , resource ) ;
switch ( IWineD3DResource_GetType ( resource ) ) {
/* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
2007-04-09 01:53:27 +02:00
case WINED3DRTYPE_SURFACE : {
unsigned int i ;
2007-07-18 23:13:58 +02:00
/* Cleanup any FBO attachments if d3d is enabled */
if ( This - > d3d_initialized ) {
2007-09-17 14:55:08 +02:00
if ( ( IWineD3DSurface * ) resource = = This - > lastActiveRenderTarget ) {
IWineD3DSwapChainImpl * swapchain = This - > swapchains ? ( IWineD3DSwapChainImpl * ) This - > swapchains [ 0 ] : NULL ;
TRACE ( " Last active render target destroyed \n " ) ;
/* Find a replacement surface for the currently active back buffer. The context manager does not do NULL
* checks , so switch to a valid target as long as the currently set surface is still valid . Use the
* surface of the implicit swpchain . If that is the same as the destroyed surface the device is destroyed
* and the lastActiveRenderTarget member shouldn ' t matter
*/
if ( swapchain ) {
if ( swapchain - > backBuffer & & swapchain - > backBuffer [ 0 ] ! = ( IWineD3DSurface * ) resource ) {
TRACE ( " Activating primary back buffer \n " ) ;
ActivateContext ( This , swapchain - > backBuffer [ 0 ] , CTXUSAGE_RESOURCELOAD ) ;
} else if ( ! swapchain - > backBuffer & & swapchain - > frontBuffer ! = ( IWineD3DSurface * ) resource ) {
/* Single buffering environment */
TRACE ( " Activating primary front buffer \n " ) ;
ActivateContext ( This , swapchain - > frontBuffer , CTXUSAGE_RESOURCELOAD ) ;
} else {
TRACE ( " Device is being destroyed, setting lastActiveRenderTarget = 0xdeadbabe \n " ) ;
/* Implicit render target destroyed, that means the device is being destroyed
* whatever we set here , it shouldn ' t matter
*/
This - > lastActiveRenderTarget = ( IWineD3DSurface * ) 0xdeadbabe ;
}
} else {
/* May happen during ddraw uninitialization */
TRACE ( " Render target set, but swapchain does not exist! \n " ) ;
This - > lastActiveRenderTarget = ( IWineD3DSurface * ) 0xdeadcafe ;
}
}
2007-07-18 23:13:58 +02:00
for ( i = 0 ; i < GL_LIMITS ( buffers ) ; + + i ) {
if ( This - > fbo_color_attachments [ i ] = = ( IWineD3DSurface * ) resource ) {
bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > fbo ) ;
set_render_target_fbo ( iface , i , NULL ) ;
This - > fbo_color_attachments [ i ] = NULL ;
}
}
if ( This - > fbo_depth_attachment = = ( IWineD3DSurface * ) resource ) {
2007-04-09 01:53:47 +02:00
bind_fbo ( iface , GL_FRAMEBUFFER_EXT , & This - > fbo ) ;
2007-07-18 23:13:58 +02:00
set_depth_stencil_fbo ( iface , NULL ) ;
This - > fbo_depth_attachment = 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 ;
2006-03-09 23:21:16 +01:00
case WINED3DRTYPE_VERTEXBUFFER :
2005-07-26 12:34:15 +02:00
/* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
{
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 ;
}
}
#if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
else { /* This shouldn't happen */
FIXME ( " Calling application has released the device before relasing all the resources bound to the device \n " ) ;
}
# endif
}
}
break ;
2006-03-09 23:21:16 +01:00
case WINED3DRTYPE_INDEXBUFFER :
2005-07-26 12:34:15 +02:00
/* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
if ( This - > updateStateBlock ! = NULL ) { /* ==NULL when device is being destroyed */
if ( This - > updateStateBlock - > pIndexData = = ( IWineD3DIndexBuffer * ) resource ) {
This - > updateStateBlock - > pIndexData = NULL ;
}
}
if ( This - > stateBlock ! = NULL ) { /* ==NULL when device is being destroyed */
if ( This - > stateBlock - > pIndexData = = ( IWineD3DIndexBuffer * ) resource ) {
This - > stateBlock - > pIndexData = NULL ;
}
}
break ;
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 ;
}
/* Remove the resoruce from the resourceStore */
IWineD3DDeviceImpl_RemoveResource ( iface , resource ) ;
TRACE ( " Resource released \n " ) ;
}
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**/
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 ,
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 ,
IWineD3DDeviceImpl_CreateAdditionalSwapChain ,
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 ,
IWineD3DDeviceImpl_Uninit3D ,
2006-09-09 13:33:17 +02:00
IWineD3DDeviceImpl_SetFullscreen ,
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 ,
2006-04-13 23:37:47 +02:00
IWineD3DDeviceImpl_GetHWND ,
IWineD3DDeviceImpl_SetHWND ,
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 ,
2004-10-21 22:59:12 +02:00
IWineD3DDeviceImpl_SetFVF ,
2004-11-23 14:52:46 +01:00
IWineD3DDeviceImpl_GetFVF ,
2005-03-02 13:16:10 +01:00
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 ,
IWineD3DDeviceImpl_GetViewport ,
IWineD3DDeviceImpl_MultiplyTransform ,
IWineD3DDeviceImpl_ValidateDevice ,
IWineD3DDeviceImpl_ProcessVertices ,
/*** State block ***/
IWineD3DDeviceImpl_BeginStateBlock ,
IWineD3DDeviceImpl_EndStateBlock ,
/*** Scene management ***/
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl_BeginScene ,
2004-12-14 12:54:27 +01:00
IWineD3DDeviceImpl_EndScene ,
IWineD3DDeviceImpl_Present ,
IWineD3DDeviceImpl_Clear ,
2005-03-02 13:16:10 +01:00
/*** Drawing ***/
2004-12-09 12:42:34 +01:00
IWineD3DDeviceImpl_DrawPrimitive ,
IWineD3DDeviceImpl_DrawIndexedPrimitive ,
IWineD3DDeviceImpl_DrawPrimitiveUP ,
2004-12-13 14:35:38 +01:00
IWineD3DDeviceImpl_DrawIndexedPrimitiveUP ,
2006-05-06 16:58:57 +02:00
IWineD3DDeviceImpl_DrawPrimitiveStrided ,
2007-07-27 14:39:55 +02:00
IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided ,
2005-03-02 13:16:10 +01:00
IWineD3DDeviceImpl_DrawRectPatch ,
IWineD3DDeviceImpl_DrawTriPatch ,
IWineD3DDeviceImpl_DeletePatch ,
IWineD3DDeviceImpl_ColorFill ,
IWineD3DDeviceImpl_UpdateTexture ,
IWineD3DDeviceImpl_UpdateSurface ,
IWineD3DDeviceImpl_GetFrontBufferData ,
2005-07-26 12:34:15 +02:00
/*** object tracking ***/
IWineD3DDeviceImpl_ResourceReleased
2004-10-07 06:22:21 +02:00
} ;
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_ADDRESSW ,
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 ) {
DWORD rep = StateTable [ state ] . representative ;
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
}