2002-09-28 00:46:16 +02:00
/*
* IDirect3DSurface8 implementation
*
2004-05-02 06:22:31 +02:00
* Copyright 2002 - 2004 Jason Edmeades
* Copyright 2002 - 2003 Raphael Junqueira
* Copyright 2004 Christian Costa
2002-09-28 00:46:16 +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
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2003-04-12 02:06:42 +02:00
# include "config.h"
2005-08-03 23:25:10 +02:00
# include "wine/port.h"
2003-04-12 02:06:42 +02:00
2003-09-06 01:08:26 +02:00
# include <stdarg.h>
# include <stdio.h>
2004-10-07 05:06:48 +02:00
# define COBJMACROS
2003-07-08 23:01:48 +02:00
# define NONAMELESSUNION
# define NONAMELESSSTRUCT
2004-10-07 05:06:48 +02:00
2002-09-28 00:46:16 +02:00
# include "windef.h"
# include "winbase.h"
# include "winuser.h"
# include "wingdi.h"
# include "wine/debug.h"
# include "d3d8_private.h"
2003-05-17 20:33:02 +02:00
WINE_DEFAULT_DEBUG_CHANNEL ( d3d_surface ) ;
2002-09-28 00:46:16 +02:00
/* IDirect3DVolume IUnknown parts follow: */
HRESULT WINAPI IDirect3DSurface8Impl_QueryInterface ( LPDIRECT3DSURFACE8 iface , REFIID riid , LPVOID * ppobj )
{
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2002-09-28 00:46:16 +02:00
if ( IsEqualGUID ( riid , & IID_IUnknown )
2002-12-17 02:15:15 +01:00
| | IsEqualGUID ( riid , & IID_IDirect3DSurface8 ) ) {
2002-09-28 00:46:16 +02:00
IDirect3DSurface8Impl_AddRef ( iface ) ;
* ppobj = This ;
return D3D_OK ;
}
WARN ( " (%p)->(%s,%p),not found \n " , This , debugstr_guid ( riid ) , ppobj ) ;
return E_NOINTERFACE ;
}
ULONG WINAPI IDirect3DSurface8Impl_AddRef ( LPDIRECT3DSURFACE8 iface ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2005-01-24 12:31:45 +01:00
ULONG ref = InterlockedIncrement ( & This - > ref ) ;
TRACE ( " (%p) : AddRef from %ld \n " , This , ref - 1 ) ;
return ref ;
2002-09-28 00:46:16 +02:00
}
ULONG WINAPI IDirect3DSurface8Impl_Release ( LPDIRECT3DSURFACE8 iface ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2005-01-24 12:31:45 +01:00
ULONG ref = InterlockedDecrement ( & This - > ref ) ;
TRACE ( " (%p) : ReleaseRef to %ld \n " , This , ref ) ;
2002-09-28 00:46:16 +02:00
if ( ref = = 0 ) {
2003-05-11 05:35:27 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , This - > allocatedMemory ) ;
HeapFree ( GetProcessHeap ( ) , 0 , This ) ;
2002-09-28 00:46:16 +02:00
}
return ref ;
}
/* IDirect3DSurface8: */
HRESULT WINAPI IDirect3DSurface8Impl_GetDevice ( LPDIRECT3DSURFACE8 iface , IDirect3DDevice8 * * ppDevice ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2002-09-28 00:46:16 +02:00
TRACE ( " (%p) : returning %p \n " , This , This - > Device ) ;
* ppDevice = ( LPDIRECT3DDEVICE8 ) This - > Device ;
2003-01-15 00:05:39 +01:00
/**
* Note Calling this method will increase the internal reference count
* on the IDirect3DDevice8 interface .
*/
2002-10-07 20:24:28 +02:00
IDirect3DDevice8Impl_AddRef ( * ppDevice ) ;
2002-09-28 00:46:16 +02:00
return D3D_OK ;
}
2003-07-08 23:01:48 +02:00
2003-01-15 00:05:39 +01:00
HRESULT WINAPI IDirect3DSurface8Impl_SetPrivateData ( LPDIRECT3DSURFACE8 iface , REFGUID refguid , CONST void * pData , DWORD SizeOfData , DWORD Flags ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-05-12 05:10:27 +02:00
FIXME ( " (%p) : stub \n " , This ) ;
return D3D_OK ;
2002-09-28 00:46:16 +02:00
}
2003-07-08 23:01:48 +02:00
2003-01-15 00:05:39 +01:00
HRESULT WINAPI IDirect3DSurface8Impl_GetPrivateData ( LPDIRECT3DSURFACE8 iface , REFGUID refguid , void * pData , DWORD * pSizeOfData ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-05-12 05:10:27 +02:00
FIXME ( " (%p) : stub \n " , This ) ;
return D3D_OK ;
2002-09-28 00:46:16 +02:00
}
2003-07-08 23:01:48 +02:00
2002-09-28 00:46:16 +02:00
HRESULT WINAPI IDirect3DSurface8Impl_FreePrivateData ( LPDIRECT3DSURFACE8 iface , REFGUID refguid ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-05-12 05:10:27 +02:00
FIXME ( " (%p) : stub \n " , This ) ;
return D3D_OK ;
2002-09-28 00:46:16 +02:00
}
2003-07-08 23:01:48 +02:00
2003-01-15 00:05:39 +01:00
HRESULT WINAPI IDirect3DSurface8Impl_GetContainer ( LPDIRECT3DSURFACE8 iface , REFIID riid , void * * ppContainer ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-01-15 00:05:39 +01:00
HRESULT res ;
res = IUnknown_QueryInterface ( This - > Container , riid , ppContainer ) ;
if ( E_NOINTERFACE = = res ) {
/**
* If the surface is created using CreateImageSurface , CreateRenderTarget ,
* or CreateDepthStencilSurface , the surface is considered stand alone . In this case ,
* GetContainer will return the Direct3D device used to create the surface .
*/
res = IUnknown_QueryInterface ( This - > Container , & IID_IDirect3DDevice8 , ppContainer ) ;
}
TRACE ( " (%p) : returning %p \n " , This , * ppContainer ) ;
return res ;
2002-09-28 00:46:16 +02:00
}
2003-07-08 23:01:48 +02:00
2002-09-28 00:46:16 +02:00
HRESULT WINAPI IDirect3DSurface8Impl_GetDesc ( LPDIRECT3DSURFACE8 iface , D3DSURFACE_DESC * pDesc ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2002-09-28 00:46:16 +02:00
TRACE ( " (%p) : copying into %p \n " , This , pDesc ) ;
memcpy ( pDesc , & This - > myDesc , sizeof ( D3DSURFACE_DESC ) ) ;
return D3D_OK ;
}
2003-07-08 23:01:48 +02:00
2003-05-11 05:35:27 +02:00
HRESULT WINAPI IDirect3DSurface8Impl_LockRect ( LPDIRECT3DSURFACE8 iface , D3DLOCKED_RECT * pLockedRect , CONST RECT * pRect , DWORD Flags ) {
2003-05-12 05:10:27 +02:00
HRESULT hr ;
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-05-12 05:10:27 +02:00
2002-09-28 00:46:16 +02:00
/* fixme: should we really lock as such? */
2004-04-27 01:34:17 +02:00
if ( This - > inTexture & & This - > inPBuffer ) {
FIXME ( " Warning: Surface is in texture memory or pbuffer \n " ) ;
This - > inTexture = 0 ;
This - > inPBuffer = 0 ;
}
2003-05-11 05:35:27 +02:00
if ( FALSE = = This - > lockable ) {
2003-07-03 20:10:22 +02:00
/* Note: UpdateTextures calls CopyRects which calls this routine to populate the
texture regions , and since the destination is an unlockable region we need
to tolerate this */
TRACE ( " Warning: trying to lock unlockable surf@%p \n " , This ) ;
/*return D3DERR_INVALIDCALL; */
2003-05-11 05:35:27 +02:00
}
2003-06-04 23:55:29 +02:00
if ( This = = This - > Device - > backBuffer | | This = = This - > Device - > renderTarget | | This = = This - > Device - > frontBuffer | | This - > Device - > depthStencilBuffer ) {
2003-05-17 20:33:02 +02:00
if ( This = = This - > Device - > backBuffer ) {
TRACE ( " (%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p \n " , This , pRect , Flags , pLockedRect , This - > allocatedMemory ) ;
} else if ( This = = This - > Device - > frontBuffer ) {
TRACE ( " (%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p \n " , This , pRect , Flags , pLockedRect , This - > allocatedMemory ) ;
2003-06-04 23:55:29 +02:00
} else if ( This = = This - > Device - > renderTarget ) {
TRACE ( " (%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p \n " , This , pRect , Flags , pLockedRect , This - > allocatedMemory ) ;
2003-05-17 20:33:02 +02:00
} else if ( This = = This - > Device - > depthStencilBuffer ) {
TRACE ( " (%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p \n " , This , pRect , Flags , pLockedRect , This - > allocatedMemory ) ;
}
} else {
TRACE ( " (%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p \n " , This , pRect , Flags , pLockedRect , This - > allocatedMemory ) ;
}
2002-09-28 00:46:16 +02:00
2004-01-06 23:08:33 +01:00
/* DXTn formats don't have exact pitches as they are to the new row of blocks,
2005-09-29 12:31:22 +02:00
where each block is 4 x4 pixels , 8 bytes ( dxt1 ) and 16 bytes ( dxt2 / 3 / 4 / 5 )
2003-10-07 05:31:46 +02:00
ie pitch = ( width / 4 ) * bytes per block */
if ( This - > myDesc . Format = = D3DFMT_DXT1 ) /* DXT1 is 8 bytes per block */
pLockedRect - > Pitch = ( This - > myDesc . Width / 4 ) * 8 ;
2005-09-29 12:31:22 +02:00
else if ( This - > myDesc . Format = = D3DFMT_DXT2 | | This - > myDesc . Format = = D3DFMT_DXT3 | |
This - > myDesc . Format = = D3DFMT_DXT4 | | This - > myDesc . Format = = D3DFMT_DXT5 ) /* DXT2/3/4/5 is 16 bytes per block */
2003-10-07 05:31:46 +02:00
pLockedRect - > Pitch = ( This - > myDesc . Width / 4 ) * 16 ;
else
pLockedRect - > Pitch = This - > bytesPerPixel * This - > myDesc . Width ; /* Bytes / row */
2003-06-05 00:47:53 +02:00
if ( NULL = = pRect ) {
2003-05-11 05:35:27 +02:00
pLockedRect - > pBits = This - > allocatedMemory ;
2003-06-05 00:47:53 +02:00
This - > lockedRect . left = 0 ;
This - > lockedRect . top = 0 ;
This - > lockedRect . right = This - > myDesc . Width ;
2003-05-11 05:35:27 +02:00
This - > lockedRect . bottom = This - > myDesc . Height ;
2003-06-05 00:47:53 +02:00
TRACE ( " Locked Rect (%p) = l %ld, t %ld, r %ld, b %ld \n " , & This - > lockedRect , This - > lockedRect . left , This - > lockedRect . top , This - > lockedRect . right , This - > lockedRect . bottom ) ;
2003-05-11 05:35:27 +02:00
} else {
TRACE ( " Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld \n " , pRect , pRect - > left , pRect - > top , pRect - > right , pRect - > bottom ) ;
2003-09-19 02:20:19 +02:00
if ( This - > myDesc . Format = = D3DFMT_DXT1 ) { /* DXT1 is half byte per pixel */
pLockedRect - > pBits = This - > allocatedMemory + ( pLockedRect - > Pitch * pRect - > top ) + ( ( pRect - > left * This - > bytesPerPixel / 2 ) ) ;
} else {
pLockedRect - > pBits = This - > allocatedMemory + ( pLockedRect - > Pitch * pRect - > top ) + ( pRect - > left * This - > bytesPerPixel ) ;
}
2003-06-05 00:47:53 +02:00
This - > lockedRect . left = pRect - > left ;
This - > lockedRect . top = pRect - > top ;
This - > lockedRect . right = pRect - > right ;
2003-05-11 05:35:27 +02:00
This - > lockedRect . bottom = pRect - > bottom ;
}
if ( 0 = = This - > myDesc . Usage ) { /* classic surface */
/* Nothing to do ;) */
2004-05-02 06:22:31 +02:00
} else if ( D3DUSAGE_RENDERTARGET & This - > myDesc . Usage & & ! ( Flags & D3DLOCK_DISCARD ) ) { /* render surfaces */
2003-05-11 05:35:27 +02:00
2003-06-04 23:55:29 +02:00
if ( This = = This - > Device - > backBuffer | | This = = This - > Device - > renderTarget | | This = = This - > Device - > frontBuffer ) {
2003-05-11 05:35:27 +02:00
GLint prev_store ;
2005-07-28 12:16:54 +02:00
GLint prev_read ;
2003-05-11 05:35:27 +02:00
ENTER_GL ( ) ;
/**
* for render - > surface copy begin to begin of allocatedMemory
* unlock can be more easy
*/
pLockedRect - > pBits = This - > allocatedMemory ;
glFlush ( ) ;
vcheckGLcall ( " glFlush " ) ;
glGetIntegerv ( GL_READ_BUFFER , & prev_read ) ;
vcheckGLcall ( " glIntegerv " ) ;
glGetIntegerv ( GL_PACK_SWAP_BYTES , & prev_store ) ;
vcheckGLcall ( " glIntegerv " ) ;
if ( This = = This - > Device - > backBuffer ) {
glReadBuffer ( GL_BACK ) ;
2003-06-04 23:55:29 +02:00
} else if ( This = = This - > Device - > frontBuffer | | This = = This - > Device - > renderTarget ) {
2003-05-11 05:35:27 +02:00
glReadBuffer ( GL_FRONT ) ;
2003-06-04 23:55:29 +02:00
} else if ( This = = This - > Device - > depthStencilBuffer ) {
ERR ( " Stencil Buffer lock unsupported for now \n " ) ;
2003-05-11 05:35:27 +02:00
}
vcheckGLcall ( " glReadBuffer " ) ;
2003-05-17 20:33:02 +02:00
{
long j ;
2003-06-13 21:14:34 +02:00
GLenum format = D3DFmt2GLFmt ( This - > Device , This - > myDesc . Format ) ;
GLenum type = D3DFmt2GLType ( This - > Device , This - > myDesc . Format ) ;
2003-05-17 20:33:02 +02:00
for ( j = This - > lockedRect . top ; j < This - > lockedRect . bottom - This - > lockedRect . top ; + + j ) {
glReadPixels ( This - > lockedRect . left ,
This - > lockedRect . bottom - j - 1 ,
This - > lockedRect . right - This - > lockedRect . left ,
1 ,
2003-06-13 21:14:34 +02:00
format ,
type ,
2003-06-05 00:51:14 +02:00
( char * ) pLockedRect - > pBits + ( pLockedRect - > Pitch * ( j - This - > lockedRect . top ) ) ) ;
2003-05-17 20:33:02 +02:00
vcheckGLcall ( " glReadPixels " ) ;
}
}
2003-05-11 05:35:27 +02:00
glReadBuffer ( prev_read ) ;
vcheckGLcall ( " glReadBuffer " ) ;
2003-06-18 05:17:42 +02:00
2003-05-11 05:35:27 +02:00
LEAVE_GL ( ) ;
2003-06-18 05:17:42 +02:00
2003-05-11 05:35:27 +02:00
} else {
FIXME ( " unsupported locking to Rendering surface surf@%p usage(%lu) \n " , This , This - > myDesc . Usage ) ;
}
} else if ( D3DUSAGE_DEPTHSTENCIL & This - > myDesc . Usage ) { /* stencil surfaces */
FIXME ( " TODO stencil depth surface locking surf@%p usage(%lu) \n " , This , This - > myDesc . Usage ) ;
2002-09-28 00:46:16 +02:00
} else {
2003-05-11 05:35:27 +02:00
FIXME ( " unsupported locking to surface surf@%p usage(%lu) \n " , This , This - > myDesc . Usage ) ;
2002-09-28 00:46:16 +02:00
}
2003-05-11 05:35:27 +02:00
2003-05-12 05:10:27 +02:00
if ( Flags & ( D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY ) ) {
2004-01-06 23:08:33 +01:00
/* Don't dirtify */
2003-05-12 05:10:27 +02:00
} else {
/**
* Dirtify on lock
* as seen in msdn docs
*/
2003-06-05 01:05:46 +02:00
IDirect3DSurface8Impl_AddDirtyRect ( iface , & This - > lockedRect ) ;
2003-05-12 05:10:27 +02:00
/** Dirtify Container if needed */
if ( NULL ! = This - > Container ) {
IDirect3DBaseTexture8 * cont = NULL ;
2004-05-21 22:52:57 +02:00
hr = IUnknown_QueryInterface ( This - > Container , & IID_IDirect3DBaseTexture8 , ( void * * ) & cont ) ;
2003-05-12 05:10:27 +02:00
if ( SUCCEEDED ( hr ) & & NULL ! = cont ) {
2003-06-04 23:55:29 +02:00
IDirect3DBaseTexture8Impl_SetDirty ( cont , TRUE ) ;
2003-05-12 05:10:27 +02:00
IDirect3DBaseTexture8_Release ( cont ) ;
cont = NULL ;
}
}
}
2003-05-17 20:33:02 +02:00
TRACE ( " returning memory@%p, pitch(%d) dirtyfied(%d) \n " , pLockedRect - > pBits , pLockedRect - > Pitch , This - > Dirty ) ;
2003-05-11 05:35:27 +02:00
This - > locked = TRUE ;
2002-09-28 00:46:16 +02:00
return D3D_OK ;
}
2003-07-08 23:01:48 +02:00
2002-09-28 00:46:16 +02:00
HRESULT WINAPI IDirect3DSurface8Impl_UnlockRect ( LPDIRECT3DSURFACE8 iface ) {
2003-10-31 05:15:07 +01:00
GLint skipBytes = 0 ;
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-10-31 05:15:07 +01:00
2003-05-11 05:35:27 +02:00
if ( FALSE = = This - > locked ) {
2003-11-04 05:17:52 +01:00
ERR ( " trying to Unlock an unlocked surf@%p \n " , This ) ;
2003-05-11 05:35:27 +02:00
return D3DERR_INVALIDCALL ;
}
2004-05-02 06:22:31 +02:00
if ( This = = This - > Device - > backBuffer | | This = = This - > Device - > frontBuffer | | This - > Device - > depthStencilBuffer | | This = = This - > Device - > renderTarget ) {
2003-05-17 20:33:02 +02:00
if ( This = = This - > Device - > backBuffer ) {
TRACE ( " (%p, backBuffer) : dirtyfied(%d) \n " , This , This - > Dirty ) ;
} else if ( This = = This - > Device - > frontBuffer ) {
TRACE ( " (%p, frontBuffer) : dirtyfied(%d) \n " , This , This - > Dirty ) ;
} else if ( This = = This - > Device - > depthStencilBuffer ) {
TRACE ( " (%p, stencilBuffer) : dirtyfied(%d) \n " , This , This - > Dirty ) ;
2004-05-02 06:22:31 +02:00
} else if ( This = = This - > Device - > renderTarget ) {
TRACE ( " (%p, renderTarget) : dirtyfied(%d) \n " , This , This - > Dirty ) ;
2003-05-17 20:33:02 +02:00
}
} else {
TRACE ( " (%p) : dirtyfied(%d) \n " , This , This - > Dirty ) ;
}
2003-05-12 05:10:27 +02:00
if ( FALSE = = This - > Dirty ) {
TRACE ( " (%p) : Not Dirtified so nothing to do, return now \n " , This ) ;
goto unlock_end ;
}
2002-09-28 00:46:16 +02:00
2003-05-11 05:35:27 +02:00
if ( 0 = = This - > myDesc . Usage ) { /* classic surface */
2003-06-04 23:55:29 +02:00
/**
* nothing to do
* waiting to reload the surface via IDirect3DDevice8 : : UpdateTexture
*/
2003-05-11 05:35:27 +02:00
} else if ( D3DUSAGE_RENDERTARGET & This - > myDesc . Usage ) { /* render surfaces */
2004-05-02 06:22:31 +02:00
if ( This = = This - > Device - > backBuffer | | This = = This - > Device - > frontBuffer | | This = = This - > Device - > renderTarget ) {
2003-05-11 05:35:27 +02:00
GLint prev_store ;
2005-07-28 12:16:54 +02:00
GLint prev_draw ;
2003-05-17 20:33:02 +02:00
GLint prev_rasterpos [ 4 ] ;
2003-05-11 05:35:27 +02:00
ENTER_GL ( ) ;
glFlush ( ) ;
vcheckGLcall ( " glFlush " ) ;
glGetIntegerv ( GL_DRAW_BUFFER , & prev_draw ) ;
vcheckGLcall ( " glIntegerv " ) ;
glGetIntegerv ( GL_PACK_SWAP_BYTES , & prev_store ) ;
vcheckGLcall ( " glIntegerv " ) ;
2003-05-17 20:33:02 +02:00
glGetIntegerv ( GL_CURRENT_RASTER_POSITION , & prev_rasterpos [ 0 ] ) ;
vcheckGLcall ( " glIntegerv " ) ;
2003-09-30 02:20:08 +02:00
glPixelZoom ( 1.0 , - 1.0 ) ;
vcheckGLcall ( " glPixelZoom " ) ;
2003-05-11 05:35:27 +02:00
2003-10-30 23:46:29 +01:00
/* glDrawPixels transforms the raster position as though it was a vertex -
we want to draw at screen position 0 , 0 - Set up ortho ( rhw ) mode as
per drawprim ( and leave set - it will sort itself out due to last_was_rhw */
if ( ! This - > Device - > last_was_rhw ) {
double X , Y , height , width , minZ , maxZ ;
This - > Device - > last_was_rhw = TRUE ;
/* Transformed already into viewport coordinates, so we do not need transform
matrices . Reset all matrices to identity and leave the default matrix in world
mode . */
glMatrixMode ( GL_MODELVIEW ) ;
checkGLcall ( " glMatrixMode " ) ;
glLoadIdentity ( ) ;
checkGLcall ( " glLoadIdentity " ) ;
glMatrixMode ( GL_PROJECTION ) ;
checkGLcall ( " glMatrixMode " ) ;
glLoadIdentity ( ) ;
checkGLcall ( " glLoadIdentity " ) ;
/* Set up the viewport to be full viewport */
X = This - > Device - > StateBlock - > viewport . X ;
Y = This - > Device - > StateBlock - > viewport . Y ;
height = This - > Device - > StateBlock - > viewport . Height ;
width = This - > Device - > StateBlock - > viewport . Width ;
minZ = This - > Device - > StateBlock - > viewport . MinZ ;
maxZ = This - > Device - > StateBlock - > viewport . MaxZ ;
TRACE ( " Calling glOrtho with %f, %f, %f, %f \n " , width , height , - minZ , - maxZ ) ;
glOrtho ( X , X + width , Y + height , Y , - minZ , - maxZ ) ;
checkGLcall ( " glOrtho " ) ;
/* Window Coord 0 is the middle of the first pixel, so translate by half
a pixel ( See comment above glTranslate below ) */
glTranslatef ( 0.5 , 0.5 , 0 ) ;
checkGLcall ( " glTranslatef(0.5, 0.5, 0) " ) ;
}
2003-05-11 05:35:27 +02:00
if ( This = = This - > Device - > backBuffer ) {
glDrawBuffer ( GL_BACK ) ;
2004-05-02 06:22:31 +02:00
} else if ( This = = This - > Device - > frontBuffer | | This = = This - > Device - > renderTarget ) {
2003-05-11 05:35:27 +02:00
glDrawBuffer ( GL_FRONT ) ;
}
vcheckGLcall ( " glDrawBuffer " ) ;
2003-10-31 05:15:07 +01:00
/* If not fullscreen, we need to skip a number of bytes to find the next row of data */
glGetIntegerv ( GL_UNPACK_ROW_LENGTH , & skipBytes ) ;
glPixelStorei ( GL_UNPACK_ROW_LENGTH , This - > myDesc . Width ) ;
/* And back buffers are not blended */
glDisable ( GL_BLEND ) ;
glRasterPos3i ( This - > lockedRect . left , This - > lockedRect . top , 1 ) ;
2003-05-11 05:35:27 +02:00
vcheckGLcall ( " glRasterPos2f " ) ;
switch ( This - > myDesc . Format ) {
case D3DFMT_R5G6B5 :
{
2003-10-31 05:15:07 +01:00
glDrawPixels ( This - > lockedRect . right - This - > lockedRect . left , ( This - > lockedRect . bottom - This - > lockedRect . top ) - 1 ,
2003-05-11 05:35:27 +02:00
GL_RGB , GL_UNSIGNED_SHORT_5_6_5 , This - > allocatedMemory ) ;
vcheckGLcall ( " glDrawPixels " ) ;
}
break ;
case D3DFMT_R8G8B8 :
{
2003-10-31 05:15:07 +01:00
glDrawPixels ( This - > lockedRect . right - This - > lockedRect . left , ( This - > lockedRect . bottom - This - > lockedRect . top ) - 1 ,
2003-05-11 05:35:27 +02:00
GL_RGB , GL_UNSIGNED_BYTE , This - > allocatedMemory ) ;
vcheckGLcall ( " glDrawPixels " ) ;
}
break ;
case D3DFMT_A8R8G8B8 :
{
glPixelStorei ( GL_PACK_SWAP_BYTES , TRUE ) ;
vcheckGLcall ( " glPixelStorei " ) ;
2003-10-31 05:15:07 +01:00
glDrawPixels ( This - > lockedRect . right - This - > lockedRect . left , ( This - > lockedRect . bottom - This - > lockedRect . top ) - 1 ,
2003-05-11 05:35:27 +02:00
GL_BGRA , GL_UNSIGNED_BYTE , This - > allocatedMemory ) ;
vcheckGLcall ( " glDrawPixels " ) ;
glPixelStorei ( GL_PACK_SWAP_BYTES , prev_store ) ;
vcheckGLcall ( " glPixelStorei " ) ;
}
break ;
default :
FIXME ( " Unsupported Format %u in locking func \n " , This - > myDesc . Format ) ;
}
2003-09-30 02:20:08 +02:00
glPixelZoom ( 1.0 , 1.0 ) ;
vcheckGLcall ( " glPixelZoom " ) ;
2003-05-11 05:35:27 +02:00
glDrawBuffer ( prev_draw ) ;
vcheckGLcall ( " glDrawBuffer " ) ;
2003-05-17 20:33:02 +02:00
glRasterPos3iv ( & prev_rasterpos [ 0 ] ) ;
vcheckGLcall ( " glRasterPos3iv " ) ;
2003-06-18 05:17:42 +02:00
2003-10-31 05:15:07 +01:00
/* Reset to previous pack row length / blending state */
glPixelStorei ( GL_UNPACK_ROW_LENGTH , skipBytes ) ;
if ( This - > Device - > StateBlock - > renderstate [ D3DRS_ALPHABLENDENABLE ] ) glEnable ( GL_BLEND ) ;
2003-05-11 05:35:27 +02:00
LEAVE_GL ( ) ;
2003-06-04 23:55:29 +02:00
2003-06-05 01:05:46 +02:00
/** restore clean dirty state */
IDirect3DSurface8Impl_CleanDirtyRect ( iface ) ;
2003-06-04 23:55:29 +02:00
2003-05-11 05:35:27 +02:00
} else {
FIXME ( " unsupported unlocking to Rendering surface surf@%p usage(%lu) \n " , This , This - > myDesc . Usage ) ;
}
} else if ( D3DUSAGE_DEPTHSTENCIL & This - > myDesc . Usage ) { /* stencil surfaces */
if ( This = = This - > Device - > depthStencilBuffer ) {
FIXME ( " TODO stencil depth surface unlocking surf@%p usage(%lu) \n " , This , This - > myDesc . Usage ) ;
} else {
FIXME ( " unsupported unlocking to StencilDepth surface surf@%p usage(%lu) \n " , This , This - > myDesc . Usage ) ;
}
} else {
FIXME ( " unsupported unlocking to surface surf@%p usage(%lu) \n " , This , This - > myDesc . Usage ) ;
2002-09-28 00:46:16 +02:00
}
2003-05-12 05:10:27 +02:00
unlock_end :
2003-05-11 05:35:27 +02:00
This - > locked = FALSE ;
2003-06-05 01:05:46 +02:00
memset ( & This - > lockedRect , 0 , sizeof ( RECT ) ) ;
2002-09-28 00:46:16 +02:00
return D3D_OK ;
}
2003-07-08 23:01:48 +02:00
2005-05-27 22:17:35 +02:00
const IDirect3DSurface8Vtbl Direct3DSurface8_Vtbl =
2002-09-28 00:46:16 +02:00
{
IDirect3DSurface8Impl_QueryInterface ,
IDirect3DSurface8Impl_AddRef ,
IDirect3DSurface8Impl_Release ,
IDirect3DSurface8Impl_GetDevice ,
IDirect3DSurface8Impl_SetPrivateData ,
IDirect3DSurface8Impl_GetPrivateData ,
IDirect3DSurface8Impl_FreePrivateData ,
IDirect3DSurface8Impl_GetContainer ,
IDirect3DSurface8Impl_GetDesc ,
IDirect3DSurface8Impl_LockRect ,
IDirect3DSurface8Impl_UnlockRect ,
} ;
2003-06-04 23:55:29 +02:00
2003-07-08 23:01:48 +02:00
2005-01-09 18:37:02 +01:00
HRESULT WINAPI IDirect3DSurface8Impl_LoadTexture ( LPDIRECT3DSURFACE8 iface , UINT gl_target , UINT gl_level ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-06-04 23:55:29 +02:00
2004-04-27 01:34:17 +02:00
if ( This - > inTexture )
return D3D_OK ;
if ( This - > inPBuffer ) {
ENTER_GL ( ) ;
if ( gl_level ! = 0 )
FIXME ( " Surface in texture is only supported for level 0 \n " ) ;
else if ( This - > myDesc . Format = = D3DFMT_P8 | | This - > myDesc . Format = = D3DFMT_A8P8 | |
2005-09-29 12:31:22 +02:00
This - > myDesc . Format = = D3DFMT_DXT1 | | This - > myDesc . Format = = D3DFMT_DXT2 | |
This - > myDesc . Format = = D3DFMT_DXT3 | | This - > myDesc . Format = = D3DFMT_DXT4 | |
2004-04-27 01:34:17 +02:00
This - > myDesc . Format = = D3DFMT_DXT5 )
FIXME ( " Format %d not supported \n " , This - > myDesc . Format ) ;
else {
glCopyTexImage2D ( gl_target ,
0 ,
D3DFmt2GLIntFmt ( This - > Device ,
This - > myDesc . Format ) ,
0 ,
0 , /*This->surfaces[j][i]->myDesc.Height-1,*/
This - > myDesc . Width ,
This - > myDesc . Height ,
0 ) ;
TRACE ( " Updating target %d \n " , gl_target ) ;
This - > inTexture = TRUE ;
}
LEAVE_GL ( ) ;
return D3D_OK ;
}
2004-04-26 22:12:28 +02:00
if ( ( This - > myDesc . Format = = D3DFMT_P8 | | This - > myDesc . Format = = D3DFMT_A8P8 ) & &
! GL_SUPPORT_DEV ( EXT_PALETTED_TEXTURE , This - > Device ) ) {
2003-06-04 23:55:29 +02:00
/**
* wanted a paletted texture and not really support it in HW
* so software emulation code begin
*/
UINT i ;
PALETTEENTRY * pal = This - > Device - > palettes [ This - > Device - > currentPalette ] ;
2005-03-24 22:01:35 +01:00
VOID * surface = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , This - > myDesc . Width * This - > myDesc . Height * sizeof ( DWORD ) ) ;
BYTE * dst = surface ;
2003-06-04 23:55:29 +02:00
BYTE * src = ( BYTE * ) This - > allocatedMemory ;
for ( i = 0 ; i < This - > myDesc . Width * This - > myDesc . Height ; i + + ) {
BYTE color = * src + + ;
* dst + + = pal [ color ] . peRed ;
* dst + + = pal [ color ] . peGreen ;
* dst + + = pal [ color ] . peBlue ;
if ( This - > myDesc . Format = = D3DFMT_A8P8 )
* dst + + = pal [ color ] . peFlags ;
else
* dst + + = 0xFF ;
}
2003-06-18 05:17:42 +02:00
ENTER_GL ( ) ;
2003-06-04 23:55:29 +02:00
TRACE ( " Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p \n " ,
gl_target ,
gl_level ,
GL_RGBA ,
This - > myDesc . Width ,
This - > myDesc . Height ,
0 ,
GL_RGBA ,
GL_UNSIGNED_BYTE ,
surface ) ;
glTexImage2D ( gl_target ,
gl_level ,
GL_RGBA ,
This - > myDesc . Width ,
This - > myDesc . Height ,
0 ,
GL_RGBA ,
GL_UNSIGNED_BYTE ,
surface ) ;
checkGLcall ( " glTexImage2D " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , surface ) ;
2003-06-18 05:17:42 +02:00
LEAVE_GL ( ) ;
2003-06-04 23:55:29 +02:00
return D3D_OK ;
}
2003-06-05 00:12:34 +02:00
if ( This - > myDesc . Format = = D3DFMT_DXT1 | |
2005-09-29 12:31:22 +02:00
This - > myDesc . Format = = D3DFMT_DXT2 | |
2003-06-05 00:12:34 +02:00
This - > myDesc . Format = = D3DFMT_DXT3 | |
2005-09-29 12:31:22 +02:00
This - > myDesc . Format = = D3DFMT_DXT4 | |
2003-06-05 00:12:34 +02:00
This - > myDesc . Format = = D3DFMT_DXT5 ) {
if ( GL_SUPPORT_DEV ( EXT_TEXTURE_COMPRESSION_S3TC , This - > Device ) ) {
TRACE ( " Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p \n " ,
gl_target ,
gl_level ,
D3DFmt2GLIntFmt ( This - > Device , This - > myDesc . Format ) ,
This - > myDesc . Width ,
This - > myDesc . Height ,
0 ,
This - > myDesc . Size ,
This - > allocatedMemory ) ;
2003-06-18 05:17:42 +02:00
ENTER_GL ( ) ;
2004-04-29 02:20:18 +02:00
GL_EXTCALL_DEV ( glCompressedTexImage2DARB , This - > Device ) ( gl_target ,
gl_level ,
D3DFmt2GLIntFmt ( This - > Device , This - > myDesc . Format ) ,
This - > myDesc . Width ,
This - > myDesc . Height ,
0 ,
This - > myDesc . Size ,
This - > allocatedMemory ) ;
2003-06-05 00:12:34 +02:00
checkGLcall ( " glCommpressedTexTexImage2D " ) ;
2003-06-18 05:17:42 +02:00
LEAVE_GL ( ) ;
2004-04-26 22:12:28 +02:00
} else {
FIXME ( " Using DXT1/3/5 without advertized support \n " ) ;
2003-06-05 00:12:34 +02:00
}
} else {
2004-05-19 06:33:42 +02:00
TRACE ( " Calling glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p \n " ,
2003-06-05 00:12:34 +02:00
gl_target ,
gl_level ,
2004-05-19 06:33:42 +02:00
debug_d3dformat ( This - > myDesc . Format ) ,
D3DFmt2GLIntFmt ( This - > Device , This - > myDesc . Format ) ,
2003-06-05 00:12:34 +02:00
This - > myDesc . Width ,
This - > myDesc . Height ,
0 ,
D3DFmt2GLFmt ( This - > Device , This - > myDesc . Format ) ,
D3DFmt2GLType ( This - > Device , This - > myDesc . Format ) ,
This - > allocatedMemory ) ;
2003-06-18 05:17:42 +02:00
ENTER_GL ( ) ;
2003-06-05 00:12:34 +02:00
glTexImage2D ( gl_target ,
gl_level ,
D3DFmt2GLIntFmt ( This - > Device , This - > myDesc . Format ) ,
This - > myDesc . Width ,
This - > myDesc . Height ,
0 ,
D3DFmt2GLFmt ( This - > Device , This - > myDesc . Format ) ,
D3DFmt2GLType ( This - > Device , This - > myDesc . Format ) ,
This - > allocatedMemory ) ;
checkGLcall ( " glTexImage2D " ) ;
2003-06-18 05:17:42 +02:00
LEAVE_GL ( ) ;
2003-06-05 00:12:34 +02:00
#if 0
{
2003-06-05 00:47:53 +02:00
static unsigned int gen = 0 ;
2003-06-05 00:12:34 +02:00
char buffer [ 4096 ] ;
+ + gen ;
if ( ( gen % 10 ) = = 0 ) {
2004-05-19 06:33:42 +02:00
snprintf ( buffer , sizeof ( buffer ) , " /tmp/surface%p_type%u_level%u_%u.ppm " , This , gl_target , gl_level , gen ) ;
2003-06-05 00:12:34 +02:00
IDirect3DSurface8Impl_SaveSnapshot ( ( LPDIRECT3DSURFACE8 ) This , buffer ) ;
}
2004-05-19 06:33:42 +02:00
/*
* debugging crash code
if ( gen = = 250 ) {
void * * test = NULL ;
* test = 0 ;
}
*/
2003-06-05 00:12:34 +02:00
}
# endif
}
return D3D_OK ;
}
# include <errno.h>
HRESULT WINAPI IDirect3DSurface8Impl_SaveSnapshot ( LPDIRECT3DSURFACE8 iface , const char * filename ) {
FILE * f = NULL ;
2003-06-05 00:51:14 +02:00
ULONG i ;
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-06-05 00:12:34 +02:00
f = fopen ( filename , " w+ " ) ;
if ( NULL = = f ) {
ERR ( " opening of %s failed with: %s \n " , filename , strerror ( errno ) ) ;
return D3DERR_INVALIDCALL ;
}
2003-06-04 23:55:29 +02:00
2003-06-05 00:47:53 +02:00
TRACE ( " opened %s with format %s \n " , filename , debug_d3dformat ( This - > myDesc . Format ) ) ;
2003-06-05 00:12:34 +02:00
fprintf ( f , " P6 \n %u %u \n 255 \n " , This - > myDesc . Width , This - > myDesc . Height ) ;
switch ( This - > myDesc . Format ) {
case D3DFMT_X8R8G8B8 :
case D3DFMT_A8R8G8B8 :
{
DWORD color ;
for ( i = 0 ; i < This - > myDesc . Width * This - > myDesc . Height ; i + + ) {
color = ( ( DWORD * ) This - > allocatedMemory ) [ i ] ;
fputc ( ( color > > 16 ) & 0xFF , f ) ;
fputc ( ( color > > 8 ) & 0xFF , f ) ;
fputc ( ( color > > 0 ) & 0xFF , f ) ;
}
}
break ;
case D3DFMT_R8G8B8 :
{
BYTE * color ;
for ( i = 0 ; i < This - > myDesc . Width * This - > myDesc . Height ; i + + ) {
color = ( ( BYTE * ) This - > allocatedMemory ) + ( 3 * i ) ;
fputc ( ( color [ 0 ] ) & 0xFF , f ) ;
fputc ( ( color [ 1 ] ) & 0xFF , f ) ;
fputc ( ( color [ 2 ] ) & 0xFF , f ) ;
}
}
break ;
case D3DFMT_A1R5G5B5 :
{
WORD color ;
for ( i = 0 ; i < This - > myDesc . Width * This - > myDesc . Height ; i + + ) {
color = ( ( WORD * ) This - > allocatedMemory ) [ i ] ;
2003-06-05 00:47:53 +02:00
fputc ( ( ( color > > 10 ) & 0x1F ) * 255 / 31 , f ) ;
fputc ( ( ( color > > 5 ) & 0x1F ) * 255 / 31 , f ) ;
fputc ( ( ( color > > 0 ) & 0x1F ) * 255 / 31 , f ) ;
}
}
break ;
case D3DFMT_A4R4G4B4 :
{
WORD color ;
for ( i = 0 ; i < This - > myDesc . Width * This - > myDesc . Height ; i + + ) {
color = ( ( WORD * ) This - > allocatedMemory ) [ i ] ;
fputc ( ( ( color > > 8 ) & 0x0F ) * 255 / 15 , f ) ;
fputc ( ( ( color > > 4 ) & 0x0F ) * 255 / 15 , f ) ;
fputc ( ( ( color > > 0 ) & 0x0F ) * 255 / 15 , f ) ;
2003-06-05 00:12:34 +02:00
}
}
break ;
2003-06-05 00:47:53 +02:00
2003-06-05 00:12:34 +02:00
case D3DFMT_R5G6B5 :
{
WORD color ;
for ( i = 0 ; i < This - > myDesc . Width * This - > myDesc . Height ; i + + ) {
color = ( ( WORD * ) This - > allocatedMemory ) [ i ] ;
2003-06-05 00:47:53 +02:00
fputc ( ( ( color > > 11 ) & 0x1F ) * 255 / 31 , f ) ;
fputc ( ( ( color > > 5 ) & 0x3F ) * 255 / 63 , f ) ;
fputc ( ( ( color > > 0 ) & 0x1F ) * 255 / 31 , f ) ;
2003-06-05 00:12:34 +02:00
}
}
break ;
default :
FIXME ( " Unimplemented dump mode format(%u,%s) \n " , This - > myDesc . Format , debug_d3dformat ( This - > myDesc . Format ) ) ;
}
fclose ( f ) ;
2003-06-04 23:55:29 +02:00
return D3D_OK ;
}
2003-06-05 01:05:46 +02:00
HRESULT WINAPI IDirect3DSurface8Impl_CleanDirtyRect ( LPDIRECT3DSURFACE8 iface ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-06-05 01:05:46 +02:00
This - > Dirty = FALSE ;
This - > dirtyRect . left = This - > myDesc . Width ;
This - > dirtyRect . top = This - > myDesc . Height ;
This - > dirtyRect . right = 0 ;
This - > dirtyRect . bottom = 0 ;
return D3D_OK ;
}
/**
* Raphael :
* very stupid way to handle multiple dirty rects but it works : )
*/
extern HRESULT WINAPI IDirect3DSurface8Impl_AddDirtyRect ( LPDIRECT3DSURFACE8 iface , CONST RECT * pDirtyRect ) {
2004-09-08 03:50:37 +02:00
IDirect3DSurface8Impl * This = ( IDirect3DSurface8Impl * ) iface ;
2003-06-05 01:05:46 +02:00
This - > Dirty = TRUE ;
2003-06-16 22:20:25 +02:00
if ( NULL ! = pDirtyRect ) {
This - > dirtyRect . left = min ( This - > dirtyRect . left , pDirtyRect - > left ) ;
This - > dirtyRect . top = min ( This - > dirtyRect . top , pDirtyRect - > top ) ;
This - > dirtyRect . right = max ( This - > dirtyRect . right , pDirtyRect - > right ) ;
This - > dirtyRect . bottom = max ( This - > dirtyRect . bottom , pDirtyRect - > bottom ) ;
} else {
This - > dirtyRect . left = 0 ;
This - > dirtyRect . top = 0 ;
This - > dirtyRect . right = This - > myDesc . Width ;
This - > dirtyRect . bottom = This - > myDesc . Height ;
}
2003-06-05 01:05:46 +02:00
return D3D_OK ;
}