2007-09-16 13:29:44 +02:00
/*
* IWineD3DSurface Implementation of management ( non - rendering ) functions
*
* Copyright 1998 Lionel Ulmer
* Copyright 2000 - 2001 TransGaming Technologies Inc .
* Copyright 2002 - 2005 Jason Edmeades
* Copyright 2002 - 2003 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
2007-09-16 14:03:39 +02:00
* Copyright 2006 - 2007 Stefan D <EFBFBD> singer for CodeWeavers
2007-09-16 13:29:44 +02:00
* Copyright 2007 Henri Verbeet
* Copyright 2006 - 2007 Roderick Colenbrander
*
* 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 . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
*/
# include "config.h"
# include "wine/port.h"
# include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL ( d3d_surface ) ;
/* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */
/* *******************************************
IWineD3DSurface IUnknown parts follow
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface ( IWineD3DSurface * iface , REFIID riid , LPVOID * ppobj )
{
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
/* Warn ,but be nice about things */
TRACE ( " (%p)->(%s,%p) \n " , This , debugstr_guid ( riid ) , ppobj ) ;
if ( IsEqualGUID ( riid , & IID_IUnknown )
| | IsEqualGUID ( riid , & IID_IWineD3DBase )
| | IsEqualGUID ( riid , & IID_IWineD3DResource )
| | IsEqualGUID ( riid , & IID_IWineD3DSurface ) ) {
IUnknown_AddRef ( ( IUnknown * ) iface ) ;
* ppobj = This ;
return S_OK ;
}
* ppobj = NULL ;
return E_NOINTERFACE ;
}
2007-09-16 13:42:18 +02:00
ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef ( IWineD3DSurface * iface ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
ULONG ref = InterlockedIncrement ( & This - > resource . ref ) ;
TRACE ( " (%p) : AddRef increasing from %d \n " , This , ref - 1 ) ;
return ref ;
}
/* ****************************************************
IWineD3DSurface IWineD3DResource parts follow
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDevice ( IWineD3DSurface * iface , IWineD3DDevice * * ppDevice ) {
return IWineD3DResourceImpl_GetDevice ( ( IWineD3DResource * ) iface , ppDevice ) ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData ( IWineD3DSurface * iface , REFGUID refguid , CONST void * pData , DWORD SizeOfData , DWORD Flags ) {
return IWineD3DResourceImpl_SetPrivateData ( ( IWineD3DResource * ) iface , refguid , pData , SizeOfData , Flags ) ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData ( IWineD3DSurface * iface , REFGUID refguid , void * pData , DWORD * pSizeOfData ) {
return IWineD3DResourceImpl_GetPrivateData ( ( IWineD3DResource * ) iface , refguid , pData , pSizeOfData ) ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData ( IWineD3DSurface * iface , REFGUID refguid ) {
return IWineD3DResourceImpl_FreePrivateData ( ( IWineD3DResource * ) iface , refguid ) ;
}
DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority ( IWineD3DSurface * iface , DWORD PriorityNew ) {
return IWineD3DResourceImpl_SetPriority ( ( IWineD3DResource * ) iface , PriorityNew ) ;
}
DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority ( IWineD3DSurface * iface ) {
return IWineD3DResourceImpl_GetPriority ( ( IWineD3DResource * ) iface ) ;
}
WINED3DRESOURCETYPE WINAPI IWineD3DBaseSurfaceImpl_GetType ( IWineD3DSurface * iface ) {
TRACE ( " (%p) : calling resourceimpl_GetType \n " , iface ) ;
return IWineD3DResourceImpl_GetType ( ( IWineD3DResource * ) iface ) ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetParent ( IWineD3DSurface * iface , IUnknown * * pParent ) {
TRACE ( " (%p) : calling resourceimpl_GetParent \n " , iface ) ;
return IWineD3DResourceImpl_GetParent ( ( IWineD3DResource * ) iface , pParent ) ;
}
2007-09-16 14:03:39 +02:00
/* ******************************************************
IWineD3DSurface IWineD3DSurface parts follow
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetContainer ( IWineD3DSurface * iface , REFIID riid , void * * ppContainer ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
IWineD3DBase * container = 0 ;
TRACE ( " (This %p, riid %s, ppContainer %p) \n " , This , debugstr_guid ( riid ) , ppContainer ) ;
if ( ! ppContainer ) {
ERR ( " Called without a valid ppContainer. \n " ) ;
}
/** From MSDN:
* If the surface is created using CreateImageSurface / CreateOffscreenPlainSurface , CreateRenderTarget ,
* or CreateDepthStencilSurface , the surface is considered stand alone . In this case ,
* GetContainer will return the Direct3D device used to create the surface .
*/
if ( This - > container ) {
container = This - > container ;
} else {
container = ( IWineD3DBase * ) This - > resource . wineD3DDevice ;
}
TRACE ( " Relaying to QueryInterface \n " ) ;
return IUnknown_QueryInterface ( container , riid , ppContainer ) ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc ( IWineD3DSurface * iface , WINED3DSURFACE_DESC * pDesc ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p) : copying into %p \n " , This , pDesc ) ;
if ( pDesc - > Format ! = NULL ) * ( pDesc - > Format ) = This - > resource . format ;
if ( pDesc - > Type ! = NULL ) * ( pDesc - > Type ) = This - > resource . resourceType ;
if ( pDesc - > Usage ! = NULL ) * ( pDesc - > Usage ) = This - > resource . usage ;
if ( pDesc - > Pool ! = NULL ) * ( pDesc - > Pool ) = This - > resource . pool ;
if ( pDesc - > Size ! = NULL ) * ( pDesc - > Size ) = This - > resource . size ; /* dx8 only */
if ( pDesc - > MultiSampleType ! = NULL ) * ( pDesc - > MultiSampleType ) = This - > currentDesc . MultiSampleType ;
if ( pDesc - > MultiSampleQuality ! = NULL ) * ( pDesc - > MultiSampleQuality ) = This - > currentDesc . MultiSampleQuality ;
if ( pDesc - > Width ! = NULL ) * ( pDesc - > Width ) = This - > currentDesc . Width ;
if ( pDesc - > Height ! = NULL ) * ( pDesc - > Height ) = This - > currentDesc . Height ;
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus ( IWineD3DSurface * iface , DWORD Flags ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p)->(%x) \n " , This , Flags ) ;
switch ( Flags )
{
case WINEDDGBS_CANBLT :
case WINEDDGBS_ISBLTDONE :
return WINED3D_OK ;
default :
return WINED3DERR_INVALIDCALL ;
}
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus ( IWineD3DSurface * iface , DWORD Flags ) {
/* XXX: DDERR_INVALIDSURFACETYPE */
TRACE ( " (%p)->(%08x) \n " , iface , Flags ) ;
switch ( Flags ) {
case WINEDDGFS_CANFLIP :
case WINEDDGFS_ISFLIPDONE :
return WINED3D_OK ;
default :
return WINED3DERR_INVALIDCALL ;
}
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost ( IWineD3DSurface * iface ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p) \n " , This ) ;
/* D3D8 and 9 loose full devices, ddraw only surfaces */
return This - > Flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore ( IWineD3DSurface * iface ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p) \n " , This ) ;
/* So far we don't lose anything :) */
This - > Flags & = ~ SFLAG_LOST ;
return WINED3D_OK ;
}
2007-09-16 16:27:58 +02:00
HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette ( IWineD3DSurface * iface , IWineD3DPalette * Pal ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
IWineD3DPaletteImpl * PalImpl = ( IWineD3DPaletteImpl * ) Pal ;
TRACE ( " (%p)->(%p) \n " , This , Pal ) ;
if ( This - > palette ! = NULL )
if ( This - > resource . usage & WINED3DUSAGE_RENDERTARGET )
This - > palette - > Flags & = ~ WINEDDPCAPS_PRIMARYSURFACE ;
if ( PalImpl ! = NULL ) {
if ( This - > resource . usage & WINED3DUSAGE_RENDERTARGET ) {
/* Set the device's main palette if the palette
* wasn ' t a primary palette before
*/
if ( ! ( PalImpl - > Flags & WINEDDPCAPS_PRIMARYSURFACE ) ) {
IWineD3DDeviceImpl * device = This - > resource . wineD3DDevice ;
unsigned int i ;
for ( i = 0 ; i < 256 ; i + + ) {
device - > palettes [ device - > currentPalette ] [ i ] = PalImpl - > palents [ i ] ;
}
}
( PalImpl ) - > Flags | = WINEDDPCAPS_PRIMARYSURFACE ;
}
}
This - > palette = PalImpl ;
return IWineD3DSurface_RealizePalette ( iface ) ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey ( IWineD3DSurface * iface , DWORD Flags , WINEDDCOLORKEY * CKey ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p)->(%08x,%p) \n " , This , Flags , CKey ) ;
if ( ( Flags & WINEDDCKEY_COLORSPACE ) ! = 0 ) {
FIXME ( " colorkey value not supported (%08x) ! \n " , Flags ) ;
return WINED3DERR_INVALIDCALL ;
}
/* Dirtify the surface, but only if a key was changed */
if ( CKey ) {
switch ( Flags & ~ WINEDDCKEY_COLORSPACE ) {
case WINEDDCKEY_DESTBLT :
This - > DestBltCKey = * CKey ;
This - > CKeyFlags | = WINEDDSD_CKDESTBLT ;
break ;
case WINEDDCKEY_DESTOVERLAY :
This - > DestOverlayCKey = * CKey ;
This - > CKeyFlags | = WINEDDSD_CKDESTOVERLAY ;
break ;
case WINEDDCKEY_SRCOVERLAY :
This - > SrcOverlayCKey = * CKey ;
This - > CKeyFlags | = WINEDDSD_CKSRCOVERLAY ;
break ;
case WINEDDCKEY_SRCBLT :
This - > SrcBltCKey = * CKey ;
This - > CKeyFlags | = WINEDDSD_CKSRCBLT ;
break ;
}
}
else {
switch ( Flags & ~ WINEDDCKEY_COLORSPACE ) {
case WINEDDCKEY_DESTBLT :
This - > CKeyFlags & = ~ WINEDDSD_CKDESTBLT ;
break ;
case WINEDDCKEY_DESTOVERLAY :
This - > CKeyFlags & = ~ WINEDDSD_CKDESTOVERLAY ;
break ;
case WINEDDCKEY_SRCOVERLAY :
This - > CKeyFlags & = ~ WINEDDSD_CKSRCOVERLAY ;
break ;
case WINEDDCKEY_SRCBLT :
This - > CKeyFlags & = ~ WINEDDSD_CKSRCBLT ;
break ;
}
}
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette ( IWineD3DSurface * iface , IWineD3DPalette * * Pal ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p)->(%p) \n " , This , Pal ) ;
* Pal = ( IWineD3DPalette * ) This - > palette ;
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_RealizePalette ( IWineD3DSurface * iface ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
RGBQUAD col [ 256 ] ;
IWineD3DPaletteImpl * pal = This - > palette ;
unsigned int n ;
TRACE ( " (%p) \n " , This ) ;
if ( This - > resource . format = = WINED3DFMT_P8 | |
This - > resource . format = = WINED3DFMT_A8P8 )
{
if ( ! This - > Flags & SFLAG_INSYSMEM ) {
FIXME ( " Palette changed with surface that does not have an up to date system memory copy \n " ) ;
}
TRACE ( " Dirtifying surface \n " ) ;
This - > Flags & = ~ ( SFLAG_INTEXTURE | SFLAG_INDRAWABLE ) ;
}
if ( This - > Flags & SFLAG_DIBSECTION ) {
TRACE ( " (%p): Updating the hdc's palette \n " , This ) ;
for ( n = 0 ; n < 256 ; n + + ) {
if ( pal ) {
col [ n ] . rgbRed = pal - > palents [ n ] . peRed ;
col [ n ] . rgbGreen = pal - > palents [ n ] . peGreen ;
col [ n ] . rgbBlue = pal - > palents [ n ] . peBlue ;
} else {
IWineD3DDeviceImpl * device = This - > resource . wineD3DDevice ;
/* Use the default device palette */
col [ n ] . rgbRed = device - > palettes [ device - > currentPalette ] [ n ] . peRed ;
col [ n ] . rgbGreen = device - > palettes [ device - > currentPalette ] [ n ] . peGreen ;
col [ n ] . rgbBlue = device - > palettes [ device - > currentPalette ] [ n ] . peBlue ;
}
col [ n ] . rgbReserved = 0 ;
}
SetDIBColorTable ( This - > hDC , 0 , 256 , col ) ;
}
return WINED3D_OK ;
}
DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch ( IWineD3DSurface * iface ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
DWORD ret ;
TRACE ( " (%p) \n " , This ) ;
/* DXTn formats don't have exact pitches as they are to the new row of blocks,
where each block is 4 x4 pixels , 8 bytes ( dxt1 ) and 16 bytes ( dxt2 / 3 / 4 / 5 )
ie pitch = ( width / 4 ) * bytes per block */
if ( This - > resource . format = = WINED3DFMT_DXT1 ) /* DXT1 is 8 bytes per block */
ret = ( ( This - > currentDesc . Width + 3 ) > > 2 ) < < 3 ;
else if ( This - > resource . format = = WINED3DFMT_DXT2 | | This - > resource . format = = WINED3DFMT_DXT3 | |
This - > resource . format = = WINED3DFMT_DXT4 | | This - > resource . format = = WINED3DFMT_DXT5 ) /* DXT2/3/4/5 is 16 bytes per block */
ret = ( ( This - > currentDesc . Width + 3 ) > > 2 ) < < 4 ;
else {
unsigned char alignment = This - > resource . wineD3DDevice - > surface_alignment ;
ret = This - > bytesPerPixel * This - > currentDesc . Width ; /* Bytes / row */
ret = ( ret + alignment - 1 ) & ~ ( alignment - 1 ) ;
}
TRACE ( " (%p) Returning %d \n " , This , ret ) ;
return ret ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition ( IWineD3DSurface * iface , LONG X , LONG Y ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
FIXME ( " (%p)->(%d,%d) Stub! \n " , This , X , Y ) ;
if ( ! ( This - > resource . usage & WINED3DUSAGE_OVERLAY ) )
{
TRACE ( " (%p): Not an overlay surface \n " , This ) ;
return WINEDDERR_NOTAOVERLAYSURFACE ;
}
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition ( IWineD3DSurface * iface , LONG * X , LONG * Y ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
FIXME ( " (%p)->(%p,%p) Stub! \n " , This , X , Y ) ;
if ( ! ( This - > resource . usage & WINED3DUSAGE_OVERLAY ) )
{
TRACE ( " (%p): Not an overlay surface \n " , This ) ;
return WINEDDERR_NOTAOVERLAYSURFACE ;
}
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder ( IWineD3DSurface * iface , DWORD Flags , IWineD3DSurface * Ref ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
IWineD3DSurfaceImpl * RefImpl = ( IWineD3DSurfaceImpl * ) Ref ;
FIXME ( " (%p)->(%08x,%p) Stub! \n " , This , Flags , RefImpl ) ;
if ( ! ( This - > resource . usage & WINED3DUSAGE_OVERLAY ) )
{
TRACE ( " (%p): Not an overlay surface \n " , This ) ;
return WINEDDERR_NOTAOVERLAYSURFACE ;
}
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay ( IWineD3DSurface * iface , RECT * SrcRect , IWineD3DSurface * DstSurface , RECT * DstRect , DWORD Flags , WINEDDOVERLAYFX * FX ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
IWineD3DSurfaceImpl * Dst = ( IWineD3DSurfaceImpl * ) DstSurface ;
FIXME ( " (%p)->(%p, %p, %p, %08x, %p) \n " , This , SrcRect , Dst , DstRect , Flags , FX ) ;
if ( ! ( This - > resource . usage & WINED3DUSAGE_OVERLAY ) )
{
TRACE ( " (%p): Not an overlay surface \n " , This ) ;
return WINEDDERR_NOTAOVERLAYSURFACE ;
}
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper ( IWineD3DSurface * iface , IWineD3DClipper * clipper )
{
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p)->(%p) \n " , This , clipper ) ;
This - > clipper = clipper ;
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper ( IWineD3DSurface * iface , IWineD3DClipper * * clipper )
{
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " (%p)->(%p) \n " , This , clipper ) ;
* clipper = This - > clipper ;
if ( * clipper ) {
IWineD3DClipper_AddRef ( * clipper ) ;
}
return WINED3D_OK ;
}
HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetContainer ( IWineD3DSurface * iface , IWineD3DBase * container ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
TRACE ( " This %p, container %p \n " , This , container ) ;
/* We can't keep a reference to the container, since the container already keeps a reference to us. */
TRACE ( " Setting container to %p from %p \n " , container , This - > container ) ;
This - > container = container ;
return WINED3D_OK ;
}
2007-09-16 16:49:02 +02:00
HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat ( IWineD3DSurface * iface , WINED3DFORMAT format ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
const StaticPixelFormatDesc * formatEntry = getFormatDescEntry ( format , NULL , NULL ) ;
if ( This - > resource . format ! = WINED3DFMT_UNKNOWN ) {
FIXME ( " (%p) : The format of the surface must be WINED3DFORMAT_UNKNOWN \n " , This ) ;
return WINED3DERR_INVALIDCALL ;
}
TRACE ( " (%p) : Setting texture format to (%d,%s) \n " , This , format , debug_d3dformat ( format ) ) ;
if ( format = = WINED3DFMT_UNKNOWN ) {
This - > resource . size = 0 ;
} else if ( format = = WINED3DFMT_DXT1 ) {
/* DXT1 is half byte per pixel */
This - > resource . size = ( ( max ( This - > pow2Width , 4 ) * formatEntry - > bpp ) * max ( This - > pow2Height , 4 ) ) > > 1 ;
} else if ( format = = WINED3DFMT_DXT2 | | format = = WINED3DFMT_DXT3 | |
format = = WINED3DFMT_DXT4 | | format = = WINED3DFMT_DXT5 ) {
This - > resource . size = ( ( max ( This - > pow2Width , 4 ) * formatEntry - > bpp ) * max ( This - > pow2Height , 4 ) ) ;
} else {
unsigned char alignment = This - > resource . wineD3DDevice - > surface_alignment ;
This - > resource . size = ( ( This - > pow2Width * formatEntry - > bpp ) + alignment - 1 ) & ~ ( alignment - 1 ) ;
This - > resource . size * = This - > pow2Height ;
}
if ( format ! = WINED3DFMT_UNKNOWN ) {
This - > bytesPerPixel = formatEntry - > bpp ;
} else {
This - > bytesPerPixel = 0 ;
}
This - > Flags | = ( WINED3DFMT_D16_LOCKABLE = = format ) ? SFLAG_LOCKABLE : 0 ;
This - > resource . format = format ;
TRACE ( " (%p) : Size %d, bytesPerPixel %d \n " , This , This - > resource . size , This - > bytesPerPixel ) ;
return WINED3D_OK ;
}
2007-09-17 13:48:11 +02:00
HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection ( IWineD3DSurface * iface ) {
IWineD3DSurfaceImpl * This = ( IWineD3DSurfaceImpl * ) iface ;
int extraline = 0 ;
SYSTEM_INFO sysInfo ;
void * oldmem = This - > resource . allocatedMemory ;
BITMAPINFO * b_info ;
HDC ddc ;
DWORD * masks ;
const StaticPixelFormatDesc * formatEntry = getFormatDescEntry ( This - > resource . format , NULL , NULL ) ;
UINT usage ;
switch ( This - > bytesPerPixel ) {
case 2 :
case 4 :
/* Allocate extra space to store the RGB bit masks. */
b_info = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( BITMAPINFOHEADER ) + 3 * sizeof ( DWORD ) ) ;
break ;
case 3 :
b_info = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY , sizeof ( BITMAPINFOHEADER ) ) ;
break ;
default :
/* Allocate extra space for a palette. */
b_info = HeapAlloc ( GetProcessHeap ( ) , HEAP_ZERO_MEMORY ,
sizeof ( BITMAPINFOHEADER )
+ sizeof ( RGBQUAD )
* ( 1 < < ( This - > bytesPerPixel * 8 ) ) ) ;
break ;
}
if ( ! b_info )
return E_OUTOFMEMORY ;
/* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
* surface . So we need at least extra 4 bytes at the end of the surface . Check against the page size ,
* if the last page used for the surface has at least 4 spare bytes we ' re safe , otherwise
* add an extra line to the dib section
*/
GetSystemInfo ( & sysInfo ) ;
if ( ( ( This - > resource . size + 3 ) % sysInfo . dwPageSize ) < 4 ) {
extraline = 1 ;
TRACE ( " Adding an extra line to the dib section \n " ) ;
}
b_info - > bmiHeader . biSize = sizeof ( BITMAPINFOHEADER ) ;
/* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
b_info - > bmiHeader . biWidth = IWineD3DSurface_GetPitch ( iface ) / This - > bytesPerPixel ;
b_info - > bmiHeader . biHeight = - This - > currentDesc . Height - extraline ;
b_info - > bmiHeader . biSizeImage = ( This - > currentDesc . Height + extraline ) * IWineD3DSurface_GetPitch ( iface ) ;
b_info - > bmiHeader . biPlanes = 1 ;
b_info - > bmiHeader . biBitCount = This - > bytesPerPixel * 8 ;
b_info - > bmiHeader . biXPelsPerMeter = 0 ;
b_info - > bmiHeader . biYPelsPerMeter = 0 ;
b_info - > bmiHeader . biClrUsed = 0 ;
b_info - > bmiHeader . biClrImportant = 0 ;
/* Get the bit masks */
masks = ( DWORD * ) & ( b_info - > bmiColors ) ;
switch ( This - > resource . format ) {
case WINED3DFMT_R8G8B8 :
usage = DIB_RGB_COLORS ;
b_info - > bmiHeader . biCompression = BI_RGB ;
break ;
case WINED3DFMT_X1R5G5B5 :
case WINED3DFMT_A1R5G5B5 :
case WINED3DFMT_A4R4G4B4 :
case WINED3DFMT_X4R4G4B4 :
case WINED3DFMT_R3G3B2 :
case WINED3DFMT_A8R3G3B2 :
case WINED3DFMT_A2B10G10R10 :
case WINED3DFMT_A8B8G8R8 :
case WINED3DFMT_X8B8G8R8 :
case WINED3DFMT_A2R10G10B10 :
case WINED3DFMT_R5G6B5 :
case WINED3DFMT_A16B16G16R16 :
usage = 0 ;
b_info - > bmiHeader . biCompression = BI_BITFIELDS ;
masks [ 0 ] = formatEntry - > redMask ;
masks [ 1 ] = formatEntry - > greenMask ;
masks [ 2 ] = formatEntry - > blueMask ;
break ;
default :
/* Don't know palette */
b_info - > bmiHeader . biCompression = BI_RGB ;
usage = 0 ;
break ;
}
ddc = GetDC ( 0 ) ;
if ( ddc = = 0 ) {
HeapFree ( GetProcessHeap ( ) , 0 , b_info ) ;
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
}
TRACE ( " Creating a DIB section with size %dx%dx%d, size=%d \n " , b_info - > bmiHeader . biWidth , b_info - > bmiHeader . biHeight , b_info - > bmiHeader . biBitCount , b_info - > bmiHeader . biSizeImage ) ;
This - > dib . DIBsection = CreateDIBSection ( ddc , b_info , usage , & This - > dib . bitmap_data , 0 /* Handle */ , 0 /* Offset */ ) ;
ReleaseDC ( 0 , ddc ) ;
if ( ! This - > dib . DIBsection ) {
ERR ( " CreateDIBSection failed! \n " ) ;
HeapFree ( GetProcessHeap ( ) , 0 , b_info ) ;
return HRESULT_FROM_WIN32 ( GetLastError ( ) ) ;
}
TRACE ( " DIBSection at : %p \n " , This - > dib . bitmap_data ) ;
/* copy the existing surface to the dib section */
if ( This - > resource . allocatedMemory ) {
memcpy ( This - > dib . bitmap_data , This - > resource . allocatedMemory , b_info - > bmiHeader . biSizeImage ) ;
} else {
/* This is to make LockRect read the gl Texture although memory is allocated */
This - > Flags & = ~ SFLAG_INSYSMEM ;
}
This - > dib . bitmap_size = b_info - > bmiHeader . biSizeImage ;
HeapFree ( GetProcessHeap ( ) , 0 , b_info ) ;
/* Now allocate a HDC */
This - > hDC = CreateCompatibleDC ( 0 ) ;
This - > dib . holdbitmap = SelectObject ( This - > hDC , This - > dib . DIBsection ) ;
TRACE ( " using wined3d palette %p \n " , This - > palette ) ;
SelectPalette ( This - > hDC ,
This - > palette ? This - > palette - > hpal : 0 ,
FALSE ) ;
This - > Flags | = SFLAG_DIBSECTION ;
HeapFree ( GetProcessHeap ( ) , 0 , oldmem ) ;
return WINED3D_OK ;
}