From 28029a2e2aad9def303aae1a0f18bfe7b099a5d4 Mon Sep 17 00:00:00 2001 From: cxgeorge <> Date: Fri, 1 Mar 2002 00:29:40 +0000 Subject: [PATCH] another non-working save --- panda/src/dxgsg8/Sources.pp | 2 +- panda/src/dxgsg8/config_dxgsg8.cxx | 70 +- panda/src/dxgsg8/config_dxgsg8.h | 8 +- panda/src/dxgsg8/dxGeomNodeContext8.I | 2 + panda/src/dxgsg8/dxGeomNodeContext8.cxx | 2 + panda/src/dxgsg8/dxGeomNodeContext8.h | 13 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.I | 90 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 1718 ++++++----------- panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 119 +- panda/src/dxgsg8/dxTextureContext8.cxx | 1472 +++++++------- panda/src/dxgsg8/dxTextureContext8.h | 51 +- panda/src/wdxdisplay8/Sources.pp | 2 +- panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx | 83 +- 13 files changed, 1590 insertions(+), 2042 deletions(-) diff --git a/panda/src/dxgsg8/Sources.pp b/panda/src/dxgsg8/Sources.pp index ec929e9676..2a6b7c3847 100644 --- a/panda/src/dxgsg8/Sources.pp +++ b/panda/src/dxgsg8/Sources.pp @@ -6,7 +6,7 @@ #if $[BUILD_DX8] #begin lib_target - #define TARGET dxgsg + #define TARGET dxgsg8 #define LOCAL_LIBS \ cull gsgmisc gsgbase gobj sgattrib sgraphutil graph display light \ putil linmath sgraph mathutil pnmimage event diff --git a/panda/src/dxgsg8/config_dxgsg8.cxx b/panda/src/dxgsg8/config_dxgsg8.cxx index 0592bbf1a1..4d7ec4de8d 100644 --- a/panda/src/dxgsg8/config_dxgsg8.cxx +++ b/panda/src/dxgsg8/config_dxgsg8.cxx @@ -16,10 +16,10 @@ // //////////////////////////////////////////////////////////////////// -#include "config_dxgsg.h" -#include "dxGraphicsStateGuardian.h" -#include "dxSavedFrameBuffer.h" -#include "dxTextureContext.h" +#include "config_dxgsg8.h" +#include "dxGraphicsStateGuardian8.h" +#include "dxSavedFrameBuffer8.h" +#include "dxTextureContext8.h" #include @@ -40,9 +40,8 @@ bool dx_full_screen = config_dxgsg.GetBool("dx-full-screen", false); // irrespective of the video refresh. bool dx_sync_video = config_dxgsg.GetBool("sync-video", true); -// enable this to turn on full-screen anti-aliasing, if the HW supports it -// this var is also used in wdxGraphicsWindows.cxx -bool dx_full_screen_antialiasing = config_dxgsg.GetBool("dx-antialias", false); +// Set Level of MultiSampling to be used, if HW supports it. Valid values are 2-16. +DWORD dx_multisample_antialiasing_level = (DWORD) config_dxgsg.GetInt("dx-multisample-antialiasing-level", 0); // Configure this true to perform a cull traversal over the geometry // by default, false otherwise. The cull traversal provides support @@ -52,6 +51,9 @@ bool dx_cull_traversal = config_dxgsg.GetBool("dx-cull-traversal", true); // if true, if card only supports per-vertex fog, it will be treated as no-HW fog capability bool dx_no_vertex_fog = config_dxgsg.GetBool("dx-no-vertex-fog", false); +// if true, triangle filter will be used to generate mipmap levels instead of default box filter +bool dx_use_triangle_mipgen_filter = config_dxgsg.GetBool("dx-use-triangle-mipgen-filter", false); + // Configure this true to cause all lighting normals to automatically // be normalized by the CPU before rendering. This is // necessary if you intend to render things under scale transforms and @@ -138,3 +140,57 @@ init_libdxgsg() { (DXGraphicsStateGuardian::get_class_type(), DXGraphicsStateGuardian::make_DXGraphicsStateGuardian); } + +const char *D3DFormatStr(D3DFORMAT fmt) { + +#define CASESTR(XX) case XX: return #XX; + + switch(fmt) { + CASESTR(D3DFMT_UNKNOWN); + CASESTR(D3DFMT_R8G8B8); + CASESTR(D3DFMT_A8R8G8B8); + CASESTR(D3DFMT_X8R8G8B8); + CASESTR(D3DFMT_R5G6B5); + CASESTR(D3DFMT_X1R5G5B5); + CASESTR(D3DFMT_A1R5G5B5); + CASESTR(D3DFMT_A4R4G4B4); + CASESTR(D3DFMT_R3G3B2); + CASESTR(D3DFMT_A8); + CASESTR(D3DFMT_A8R3G3B2); + CASESTR(D3DFMT_X4R4G4B4); + CASESTR(D3DFMT_A2B10G10R10); + CASESTR(D3DFMT_G16R16); + CASESTR(D3DFMT_A8P8); + CASESTR(D3DFMT_P8); + CASESTR(D3DFMT_L8); + CASESTR(D3DFMT_A8L8); + CASESTR(D3DFMT_A4L4); + CASESTR(D3DFMT_V8U8); + CASESTR(D3DFMT_L6V5U5); + CASESTR(D3DFMT_X8L8V8U8); + CASESTR(D3DFMT_Q8W8V8U8); + CASESTR(D3DFMT_V16U16); + CASESTR(D3DFMT_W11V11U10); + CASESTR(D3DFMT_A2W10V10U10); + CASESTR(D3DFMT_UYVY); + CASESTR(D3DFMT_YUY2); + CASESTR(D3DFMT_DXT1); + CASESTR(D3DFMT_DXT2); + CASESTR(D3DFMT_DXT3); + CASESTR(D3DFMT_DXT4); + CASESTR(D3DFMT_DXT5); + CASESTR(D3DFMT_D16_LOCKABLE); + CASESTR(D3DFMT_D32); + CASESTR(D3DFMT_D15S1); + CASESTR(D3DFMT_D24S8); + CASESTR(D3DFMT_D16); + CASESTR(D3DFMT_D24X8); + CASESTR(D3DFMT_D24X4S4); + CASESTR(D3DFMT_VERTEXDATA); + CASESTR(D3DFMT_INDEX16); + CASESTR(D3DFMT_INDEX32); + } + + return "Invalid D3DFORMAT"; +} + diff --git a/panda/src/dxgsg8/config_dxgsg8.h b/panda/src/dxgsg8/config_dxgsg8.h index 3b64ca9c02..057f59b828 100644 --- a/panda/src/dxgsg8/config_dxgsg8.h +++ b/panda/src/dxgsg8/config_dxgsg8.h @@ -16,11 +16,12 @@ // //////////////////////////////////////////////////////////////////// -#ifndef CONFIG_DXGSG_H -#define CONFIG_DXGSG_H +#ifndef CONFIG_DXGSG8_H +#define CONFIG_DXGSG8_H #include #include +#include NotifyCategoryDecl(dxgsg, EXPCL_PANDADX, EXPTP_PANDADX); @@ -34,6 +35,9 @@ extern float dx_fps_meter_update_interval; extern bool dx_auto_normalize_lighting; extern bool dx_use_rangebased_fog; extern const bool link_tristrips; +extern DWORD dx_multisample_antialiasing_level; +extern bool dx_use_triangle_mipgen_filter; +extern const char *D3DFormatStr(D3DFORMAT fmt); // debug flags we might want to use in full optimized build extern bool dx_ignore_mipmaps; diff --git a/panda/src/dxgsg8/dxGeomNodeContext8.I b/panda/src/dxgsg8/dxGeomNodeContext8.I index 8d30be3c3b..739d1d127a 100644 --- a/panda/src/dxgsg8/dxGeomNodeContext8.I +++ b/panda/src/dxgsg8/dxGeomNodeContext8.I @@ -26,6 +26,8 @@ INLINE DXGeomNodeContext:: DXGeomNodeContext(GeomNode *node) : GeomNodeContext(node) { _num_verts = 0; +/* _pVB = NULL; _pXformed_VB = NULL; +*/ } diff --git a/panda/src/dxgsg8/dxGeomNodeContext8.cxx b/panda/src/dxgsg8/dxGeomNodeContext8.cxx index fc77d6723f..ccf16586d7 100644 --- a/panda/src/dxgsg8/dxGeomNodeContext8.cxx +++ b/panda/src/dxgsg8/dxGeomNodeContext8.cxx @@ -22,6 +22,7 @@ TypeHandle DXGeomNodeContext::_type_handle; DXGeomNodeContext::~DXGeomNodeContext() { +/* if(_pXformed_VB!=NULL) _pXformed_VB->Release(); _pXformed_VB=NULL; @@ -29,5 +30,6 @@ DXGeomNodeContext::~DXGeomNodeContext() if(_pVB!=NULL) _pVB->Release(); _pVB=NULL; +*/ } diff --git a/panda/src/dxgsg8/dxGeomNodeContext8.h b/panda/src/dxgsg8/dxGeomNodeContext8.h index 35ded17e6f..926129bf40 100644 --- a/panda/src/dxgsg8/dxGeomNodeContext8.h +++ b/panda/src/dxgsg8/dxGeomNodeContext8.h @@ -35,12 +35,16 @@ #define D3D_OVERLOADS // get D3DVECTOR '+' operator, etc from d3dtypes.h #include +#if D3D_SDK_VERSION != 220 +#error you have DX 8.0 headers, not DX 8.1, you need to install newer MS Platform SDK! +#endif + #if DIRECT3D_VERSION != 0x0800 #error DX8.1 headers not available, you need to install newer MS Platform SDK! #endif -#if D3D_SDK_VERSION != 220 -#error you have DX 8.0 headers, not DX 8.1, you need to install newer MS Platform SDK! +#ifndef D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD +#error you have pre-release DX8.1 headers, you need to install newer MS Platform SDK! #endif typedef struct { @@ -48,6 +52,8 @@ typedef struct { D3DPRIMITIVETYPE primtype; } DPInfo; +// empty shell unimplemented for DX8 right now + //////////////////////////////////////////////////////////////////// // Class : DXGeomNodeContext // Description : @@ -66,8 +72,11 @@ public: // but we will want a way to know if VB has already been xformed by ProcessVerts this frame // if multiple geomnodes share VBs +/* unimplemented right now LPDIRECT3DVERTEXBUFFER7 _pVB; LPDIRECT3DVERTEXBUFFER7 _pXformed_VB; +*/ + int _start_index; // starting offset of this geom's verts within the VB int _num_verts; // number of verts used by this geomcontext within the VB diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.I b/panda/src/dxgsg8/dxGraphicsStateGuardian8.I index 2a04aac13c..b8f845cfe2 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.I +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.I @@ -16,7 +16,7 @@ // //////////////////////////////////////////////////////////////////// -#include "config_dxgsg.h" +#include "config_dxgsg8.h" #include //////////////////////////////////////////////////////////////////// @@ -30,12 +30,12 @@ enable_line_smooth(bool val) { _line_smooth_enabled = val; #ifdef NDEBUG { - if(val && (scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)) + if(val && (scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_ANTIALIASEDGES)) dxgsg_cat.error() << "no HW support for line smoothing!!\n"; } #endif - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, (DWORD)val); } } @@ -47,7 +47,7 @@ enable_line_smooth(bool val) { INLINE void DXGraphicsStateGuardian:: enable_lighting(bool val) { if (_lighting_enabled != val) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_LIGHTING, (DWORD)val); if(_lighting_enabled = val) _lighting_enabled_this_frame = true; } @@ -64,14 +64,14 @@ enable_dither(bool val) { #ifdef _DEBUG { - if(val && !(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)) + if(val && !(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)) dxgsg_cat.error() << "no HW support for color dithering!!\n"; return; } #endif _dither_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, (DWORD)val); } } @@ -84,7 +84,7 @@ INLINE void DXGraphicsStateGuardian:: enable_stencil_test(bool val) { if (_stencil_test_enabled != val) { _stencil_test_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, (DWORD)val); } } @@ -100,27 +100,55 @@ enable_color_material(bool val) { } } + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian::enable_clip_plane // Access: // Description: //////////////////////////////////////////////////////////////////// INLINE void DXGraphicsStateGuardian:: -enable_clip_plane(int clip_plane, bool val) +enable_clip_plane(int clip_plane_id, bool val) { - if (_clip_plane_enabled[clip_plane] != val) - { - _clip_plane_enabled[clip_plane] = val; + assert(clip_plane_id < D3DMAXUSERCLIPPLANES); + + if (_clip_plane_enabled[clip_plane_id] != val) { + DWORD bitflag = 1 << clip_plane_id; + + _clip_plane_enabled[clip_plane_id] = val; DWORD ClipPlaneBits; - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE , &ClipPlaneBits); + scrn.pD3DDevice->GetRenderState(D3DRS_CLIPPLANEENABLE , &ClipPlaneBits); if (val) - ClipPlaneBits |= 1 << clip_plane; + ClipPlaneBits |= bitflag; else - ClipPlaneBits &= ~(1 << clip_plane); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE , ClipPlaneBits); - } + ClipPlaneBits &= ~bitflag; + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE , ClipPlaneBits); + } } +#if 0 +//////////////////////////////////////////////////////////////////// +// Function: DXGraphicsStateGuardian::enable_clip_plane +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void DXGraphicsStateGuardian:: +enable_clip_plane(int clip_plane_id, bool val) +{ + assert(clip_plane_id < D3DMAXUSERCLIPPLANES); + + // clip plane stuff needs total rewriting to get rid of these arrays +// if (((_clip_planes_enabled & bitflag)!=0) != val) + if (_clip_plane_enabled[clip_plane_id] != val) { + _clip_plane_enabled[clip_plane_id] = val; + if(val) + _clip_plane_enabled |= bitflag; + else _clip_plane_enabled &= ~bitflag; + + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE , _clip_planes_enabled); + } +} +#endif + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian::enable_blend // Access: @@ -130,7 +158,7 @@ INLINE void DXGraphicsStateGuardian:: enable_blend(bool val) { if (_blend_enabled != val) { _blend_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)val); } } @@ -140,10 +168,10 @@ enable_blend(bool val) { // Description: //////////////////////////////////////////////////////////////////// INLINE void DXGraphicsStateGuardian:: -set_shademode(D3DSHADEMODE val) { - if (_CurShadeMode != val) { - _CurShadeMode = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, (DWORD)val); +enable_gouraud_shading(bool val) { + if (_bGouraudShadingOn != val) { + _bGouraudShadingOn = val; + scrn.pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, (DWORD)val); } } @@ -151,7 +179,7 @@ INLINE void DXGraphicsStateGuardian:: enable_primitive_clipping(bool val) { if (_clipping_enabled != val) { _clipping_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, (DWORD)val); } } @@ -164,7 +192,7 @@ INLINE void DXGraphicsStateGuardian:: enable_fog(bool val) { if ((_fog_enabled != val) && (_doFogType!=None)) { _fog_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_FOGENABLE, (DWORD)val); } } @@ -178,7 +206,7 @@ enable_alpha_test(bool val ) { if (_alpha_test_enabled != val) { _alpha_test_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, (DWORD)val); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, (DWORD)val); } } @@ -195,8 +223,8 @@ call_dxLightModelAmbient( const Colorf& color) #ifdef GSG_VERBOSE dxgsg_cat.debug() << "dxLightModel(LIGHT_MODEL_AMBIENT, " << color << ")" << endl; #endif - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, - D3DRGBA(color[0], color[1], color[2], color[3])); + scrn.pD3DDevice->SetRenderState( D3DRS_AMBIENT, + D3DCOLOR_COLORVALUE(color[0], color[1], color[2], color[3])); } } @@ -242,8 +270,8 @@ call_dxAlphaFunc(D3DCMPFUNC func, DWORD ref) } dxgsg_cat.debug() << ref << ")" << endl; #endif - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, func); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, ref); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, func); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAREF, ref); } } @@ -254,7 +282,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc ) if (_blend_source_func != sfunc) { _blend_source_func = sfunc; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, sfunc); + scrn.pD3DDevice->SetRenderState(D3DRS_SRCBLEND, sfunc); #ifdef GSG_VERBOSE dxgsg_cat.debug() << "dxSrcBlendFunc("; switch (sfunc) @@ -296,7 +324,7 @@ call_dxBlendFunc(D3DBLEND sfunc, D3DBLEND dfunc ) if ( _blend_dest_func != dfunc) { _blend_dest_func = dfunc; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, dfunc); + scrn.pD3DDevice->SetRenderState(D3DRS_DESTBLEND, dfunc); #ifdef GSG_VERBOSE dxgsg_cat.debug() << "dxDstBlendFunc("; switch (dfunc) @@ -338,7 +366,7 @@ INLINE void DXGraphicsStateGuardian:: enable_zwritemask(bool val) { if (_depth_write_enabled != val) { _depth_write_enabled = val; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, val); + scrn.pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, val); } } diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 19dc79ae05..c888376ef6 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -60,8 +60,8 @@ #include #endif -#include "config_dxgsg.h" -#include "dxGraphicsStateGuardian.h" +#include "config_dxgsg8.h" +#include "dxGraphicsStateGuardian8.h" // disable nameless struct 'warning' #pragma warning (disable : 4201) @@ -79,11 +79,6 @@ // currently doesnt work well enough in toontown models for us to use // prob is when viewer gets close to decals, they disappear into wall poly, need to investigate -// test non-optimized general geom pipe for all models -// apparently DPStrided faults for some color G_OVERALL cases, so comment out for now -// not clear that it is actually faster in practice, it may even be slightly slower -#define DONT_USE_DRAWPRIMSTRIDED - //const int VERT_BUFFER_SIZE = (8*1024L); // For sparkle particles, we can have 4 vertices per sparkle, and a // particle pool size of 1024 particles @@ -107,9 +102,7 @@ typedef enum { NothingSet=0,NormalOnly,ColorOnly,Normal_Color,TexCoordOnly, #define PER_COLOR ColorOnly #define PER_TEXCOORD TexCoordOnly -// technically DX7's front-end has no limit on the number of lights, but it's simpler for -// this implementation to set a small GL-like limit to make the light array traversals short -// and so I dont have to write code that reallocs light arrays +// DX8's SW front-end has no limit on the number of lights, but HW is usually limited to 8 #define DXGSG_MAX_LIGHTS 8 static D3DMATRIX matIdentity; @@ -122,9 +115,9 @@ static DWORD cVertcount=0; static DWORD cTricount=0; static DWORD cGeomcount=0; -static LPDIRECTDRAWSURFACE7 pLastTexture=NULL; +static IDirect3DTexture8 *pLastTexture=NULL; static DWORD cDP_noTexChangeCount=0; -static LPDIRECT3DDEVICE7 global_pD3DDevice = NULL; +static LPDIRECT3DDEVICE8 global_pD3DDevice = NULL; static void CountDPs(DWORD nVerts,DWORD nTris) { cDPcount++; @@ -139,12 +132,14 @@ static void CountDPs(DWORD nVerts,DWORD nTris) { #define CountDPs(nv,nt) #endif -#define MY_D3DRGBA(r,g,b,a) ((D3DCOLOR) D3DRGBA(r,g,b,a)) +#define MY_D3DRGBA(r,g,b,a) ((D3DCOLOR) D3DCOLOR_COLORVALUE(r,g,b,a)) #if defined(DO_PSTATS) || defined(PRINT_TEXSTATS) static bool bTexStatsRetrievalImpossible=false; #endif +HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark); + //#define Colorf_to_D3DCOLOR(out_color) (MY_D3DRGBA((out_color)[0], (out_color)[1], (out_color)[2], (out_color)[3])) INLINE DWORD @@ -200,6 +195,47 @@ Colorf_to_D3DCOLOR(const Colorf &cColorf) { #endif //!_X86_ } +map g_D3DFORMATmap; + +void make_D3DFORMAT_map(void) { + if(g_D3DFORMATmap.size()!=0) + return; + +#define INSERT_ELEM(XX) g_D3DFORMATmap[XX##_FLAG] = D3DFMT_##XX; + + INSERT_ELEM(R8G8B8); + INSERT_ELEM(A8R8G8B8); + INSERT_ELEM(X8R8G8B8); + INSERT_ELEM(R5G6B5); + INSERT_ELEM(X1R5G5B5); + INSERT_ELEM(A1R5G5B5); + INSERT_ELEM(A4R4G4B4); + INSERT_ELEM(R3G3B2); + INSERT_ELEM(A8); + INSERT_ELEM(A8R3G3B2); + INSERT_ELEM(X4R4G4B4); + INSERT_ELEM(A2B10G10R10); + INSERT_ELEM(A8P8); + INSERT_ELEM(P8); + INSERT_ELEM(L8); + INSERT_ELEM(A8L8); + INSERT_ELEM(A4L4); + INSERT_ELEM(V8U8); + INSERT_ELEM(L6V5U5); + INSERT_ELEM(X8L8V8U8); + INSERT_ELEM(Q8W8V8U8); + INSERT_ELEM(V16U16); + INSERT_ELEM(W11V11U10); + INSERT_ELEM(A2W10V10U10); + INSERT_ELEM(UYVY); + INSERT_ELEM(YUY2); + INSERT_ELEM(DXT1); + INSERT_ELEM(DXT2); + INSERT_ELEM(DXT3); + INSERT_ELEM(DXT4); + INSERT_ELEM(DXT5); +} + void DXGraphicsStateGuardian:: set_color_clear_value(const Colorf& value) { _color_clear_value = value; @@ -282,7 +318,7 @@ void DXGraphicsStateGuardian::FillFPSMeterTexture(void) { // init it to transparent black if(FAILED( hr = _fpsmeter_font_surf->Lock( NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) { - dxgsg_cat.error() << "fps meter creation failed, Lock() failed on texture! hr = " << ConvD3DErrorToString(hr) << "\n"; + dxgsg_cat.error() << "fps meter creation failed, Lock() failed on texture! hr = " << D3DERRORSTRING(hr); _bShowFPSMeter = false; return; } @@ -292,7 +328,7 @@ void DXGraphicsStateGuardian::FillFPSMeterTexture(void) { // draw FPS text using GDI HDC hDC; if(FAILED( hr = _fpsmeter_font_surf->GetDC(&hDC))) { - dxgsg_cat.error() << "fps meter creation failed, GetDC failed on fps font surface! hr = " << ConvD3DErrorToString(hr) << "\n"; + dxgsg_cat.error() << "fps meter creation failed, GetDC failed on fps font surface! hr = " << D3DERRORSTRING(hr); _bShowFPSMeter = false; return; } @@ -325,7 +361,7 @@ void DXGraphicsStateGuardian::FillFPSMeterTexture(void) { // GDI writes 0x00 for alpha, have to make letter pixels opaque again if(FAILED( hr = _fpsmeter_font_surf->Lock( NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) { - dxgsg_cat.error() << "fps meter creation failed, Lock() failed on texture! hr = " << ConvD3DErrorToString(hr) << "\n"; + dxgsg_cat.error() << "fps meter creation failed, Lock() failed on texture! hr = " << D3DERRORSTRING(hr); _bShowFPSMeter = false; return; } @@ -375,6 +411,8 @@ DXGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) { // called and dx objects need to be recreated (otherwise they // belong in dx_init, with other renderstate + make_D3DFORMAT_map(); + ZeroMemory(&matIdentity,sizeof(D3DMATRIX)); matIdentity._11 = matIdentity._22 = matIdentity._33 = matIdentity._44 = 1.0f; @@ -457,20 +495,6 @@ free_dxgsg_objects(void) { RELEASE(scrn.pddsPrimary,dxgsg,"primary surface",false); } -HRESULT CALLBACK EnumTexFmtsCallback( LPDDPIXELFORMAT pddpf, VOID* param ) { - // wont build if its a member fn, so had to do this stuff -#ifdef USE_TEXFMTVEC - DDPixelFormatVec *pPixFmtVec = (DDPixelFormatVec *) param; - pPixFmtVec->push_back(*pddpf); -#else - DXGraphicsStateGuardian *mystate = (DXGraphicsStateGuardian *) param; - assert(mystate->_cNumTexPixFmts < MAX_DX_TEXPIXFMTS); - memcpy( &(mystate->_pTexPixFmts[mystate->_cNumTexPixFmts]), pddpf, sizeof(DDPIXELFORMAT) ); - mystate->_cNumTexPixFmts++; -#endif - return DDENUMRET_OK; -} - //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian::reset // Access: Public, Virtual @@ -478,56 +502,34 @@ HRESULT CALLBACK EnumTexFmtsCallback( LPDDPIXELFORMAT pddpf, VOID* param ) { // set up. //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: -dx_init( void) { -/* - LPDIRECTDRAW7 context, - LPDIRECTDRAWSURFACE7 pri, - LPDIRECTDRAWSURFACE7 back, - LPDIRECTDRAWSURFACE7 zbuf, - LPDIRECT3D7 pD3D, - LPDIRECT3DDEVICE7 pDevice, - RECT viewrect) */ +dx_init(void) { + assert(scrn.pDD!=NULL); assert(scrn.pD3D!=NULL); assert(scrn.pD3DDevice!=NULL); - assert(scrn.pddsPrimary!=NULL); - assert(scrn.pddsBack!=NULL); - _pDD=scrn.pDD; // save for speed of access _pCurD3DDevice = scrn.pD3DDevice; -/* _pDD = context; - scrn.pddsPrimary = pri; - scrn.pddsBack = back; - scrn.pddsZBuf = zbuf; - scrn.pD3D = pD3D; - scrn.pD3DDevice = pDevice; - _view_rect = viewrect; -*/ - ZeroMemory(&_lmodel_ambient,sizeof(Colorf)); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0x0); + scrn.pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0x0); _light_enabled = (bool *)NULL; _cur_light_enabled = (bool *)NULL; + + // bugbug: rewrite clipplane stuff _clip_plane_enabled = (bool *)NULL; _cur_clip_plane_enabled = (bool *)NULL; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPLANEENABLE , 0x0); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE , 0x0); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, true); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, true); _clipping_enabled = true; - _CurShadeMode = D3DSHADE_FLAT; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, _CurShadeMode); + _bGouraudShadingOn = false; + scrn.pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, _bGouraudShadingOn); _depth_test_enabled = true; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, _depth_test_enabled); + scrn.pD3DDevice->SetRenderState(D3DRS_ZWRITEENABLE, _depth_test_enabled); - // need to free these properly -#ifndef USE_TEXFMTVEC - _cNumTexPixFmts = 0; - _pTexPixFmts = NULL; -#endif _pCurTexContext = NULL; //Color and alpha transform variables @@ -536,30 +538,27 @@ dx_init( void) { _color_transform_required = _color_transform_enabled || _alpha_transform_enabled; _current_color_mat = LMatrix4f::ident_mat(); - _current_alpha_offset = 0; - _current_alpha_scale = 1; - - // none of these are implemented - //_multisample_enabled = false; - //_point_smooth_enabled = false; + _current_alpha_offset = 0.0f; + _current_alpha_scale = 1.0f; _line_smooth_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_EDGEANTIALIAS, false); + scrn.pD3DDevice->SetRenderState(D3DRS_EDGEANTIALIAS, false); _color_material_enabled = false; _normals_enabled = false; _depth_test_enabled = D3DZB_FALSE; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + scrn.pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); _blend_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, (DWORD)_blend_enabled); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, (DWORD)_blend_enabled); - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_SRCBLEND, (DWORD*)&_blend_source_func); - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_DESTBLEND, (DWORD*)&_blend_dest_func); + // just use whatever d3d defaults to here + scrn.pD3DDevice->GetRenderState(D3DRS_SRCBLEND, (DWORD*)&_blend_source_func); + scrn.pD3DDevice->GetRenderState(D3DRS_DESTBLEND, (DWORD*)&_blend_dest_func); _fog_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, _fog_enabled); + scrn.pD3DDevice->SetRenderState(D3DRS_FOGENABLE, _fog_enabled); _decal_level = 0; _current_projection_mat = LMatrix4f::ident_mat(); @@ -568,14 +567,16 @@ dx_init( void) { _enable_all_color = true; // GL stuff that hasnt been translated to DX + // none of these are implemented + //_multisample_enabled = false; // bugbug: translate this to dx_multisample_antialiasing_level? + //_point_smooth_enabled = false; + // _scissor_enabled = false; // _multisample_alpha_one_enabled = false; // _multisample_alpha_mask_enabled = false; // _line_width = 1.0f; // _point_size = 1.0f; - assert(scrn.pddsBack!=NULL); // dxgsg is always double-buffered right now - #ifdef COUNT_DRAWPRIMS global_pD3DDevice = pDevice; #endif @@ -589,128 +590,101 @@ dx_init( void) { HRESULT hr; -#ifdef USE_TEXFMTVEC - assert(scrn.TexPixFmts.size()==0); - - if(FAILED(hr=_pCurD3DDevice->EnumTextureFormats(EnumTexFmtsCallback, &scrn.TexPixFmts))) { -#else - _pTexPixFmts = new DDPIXELFORMAT[MAX_DX_TEXPIXFMTS]; _cNumTexPixFmts = 0; - assert(_pTexPixFmts!=NULL); - if(FAILED(hr=_pCurD3DDevice->EnumTextureFormats(EnumTexFmtsCallback, this))) { -#endif - if(hr==D3DERR_TEXTURE_NO_SUPPORT) { - dxgsg_cat.error() << "EnumTextureFormats indicates No Texturing Support on this HW!, exiting...\n"; - exit(1); - } else { - dxgsg_cat.error() << "EnumTextureFormats failed! hr = " << ConvD3DErrorToString(hr) << endl; - } - } - -/* - if(FAILED(hr = pDevice->GetCaps(&scrn.D3DDevDesc))) { - dxgsg_cat.fatal() << "GetCaps failed on D3D Device! hr = " << ConvD3DErrorToString(hr) << endl; - exit(1); - } -*/ - DX_DECLARE_CLEAN(DDCAPS,ddCaps); - if (FAILED(hr = scrn.pDD->GetCaps(&ddCaps,NULL))) { - dxgsg_cat.fatal() << "GetCaps failed on DDraw! hr = " << ConvD3DErrorToString(hr) << "\n"; - exit(1); + for(i=0;iCheckDeviceFormat(Display.CardIDNum,D3DDEVTYPE_HAL,Display.DisplayMode.Format, + 0x0,D3DRTYPE_TEXTURE,g_D3DFORMATmap[fmtflag]); + if(SUCCEEDED(hr)){ + SupportedTexFmtsMask|=fmtflag; + _cNumTexPixFmts++; + } } // s3 virge drivers sometimes give crap values for these - if(scrn.D3DDevDesc.dwMaxTextureWidth==0) - scrn.D3DDevDesc.dwMaxTextureWidth=256; + if(scrn.d3dcaps.dwMaxTextureWidth==0) + scrn.d3dcaps.dwMaxTextureWidth=256; - if(scrn.D3DDevDesc.dwMaxTextureHeight==0) - scrn.D3DDevDesc.dwMaxTextureHeight=256; + if(scrn.d3dcaps.dwMaxTextureHeight==0) + scrn.d3dcaps.dwMaxTextureHeight=256; -// shouldve already been set -// sc_bIsTNLDevice = (IsEqualGUID(scrn.D3DDevDesc.deviceGUID,IID_IDirect3DTnLHalDevice)!=0); - - if ((dx_decal_type==GDT_offset) && !(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBIAS)) { -#ifdef _DEBUG - // dx7 doesnt support PLANEMASK renderstate -#if(DIRECT3D_VERSION < 0x700) - dxgsg_cat.debug() << "dx-decal-type 'offset' not supported by hardware, switching to decal masking\n"; -#else - dxgsg_cat.debug() << "dx-decal-type 'offset' not supported by hardware, switching to decal double-draw blend-based masking\n"; -#endif -#endif -#if(DIRECT3D_VERSION < 0x700) - dx_decal_type = GDT_mask; -#else - dx_decal_type = GDT_blend; -#endif + if ((dx_decal_type==GDT_offset) && !(scrn.d3dcaps.dwRasterCaps & D3DPRASTERCAPS_ZBIAS)) { + if(scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) { + if(dxgsg_cat.is_debug() + dxgsg_cat.debug() << "dx-decal-type 'offset' not supported by hardware, switching to mask type decals\n"; + dx_decal_type = GDT_mask; + } else { + if(dxgsg_cat.is_debug() + dxgsg_cat.debug() << "dx-decal-type 'offset' not supported by hardware, switching to decal double-draw blend-based masking\n"; + dx_decal_type = GDT_blend; } #ifdef DISABLE_POLYGON_OFFSET_DECALING -#ifdef _DEBUG - dxgsg_cat.spam() << "polygon-offset decaling disabled in dxgsg, switching to double-draw decaling\n"; + if(dx_decal_type==GDT_offset) { + if(dxgsg_cat.is_spam() + dxgsg_cat.spam() << "polygon-offset decaling disabled in dxgsg, switching to double-draw decaling\n"; + + if(scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) { + if(dxgsg_cat.is_debug() + dxgsg_cat.debug() << "using dx-decal-type 'GDT_mask'\n"; + dx_decal_type = GDT_mask; + } else { + if(dxgsg_cat.is_debug() + dxgsg_cat.debug() << "dx-decal-type 'mask' not supported by hardware, switching to GDT_blend\n"; + dx_decal_type = GDT_blend; + } + } #endif -#if(DIRECT3D_VERSION < 0x700) - dx_decal_type = GDT_mask; -#else - dx_decal_type = GDT_blend; -#endif -#endif - - if ((dx_decal_type==GDT_mask) && !(scrn.D3DDevDesc.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKPLANES)) { -#ifdef _DEBUG - dxgsg_cat.debug() << "No hardware support for colorwrite disabling, switching to dx-decal-type 'mask' to 'blend'\n"; -#endif - dx_decal_type = GDT_blend; + if (((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_MASKZ)) { + dxgsg_cat.error() << "dx-decal-types mask&blend impossible to implement, no hardware support for Z-masking, decals will not appear correctly!\n"; } - if (((dx_decal_type==GDT_blend)||(dx_decal_type==GDT_mask)) && !(scrn.D3DDevDesc.dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKZ)) { - dxgsg_cat.error() << "dx-decal-type mask impossible to implement, no hardware support for Z-masking, decals will not appear correctly!\n"; +#define REQUIRED_DESTBLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| D3DPBLENDCAPS_SRCALPHA) +#define REQUIRED_SRCBLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| D3DPBLENDCAPS_INVSRCALPHA) + + if (((scrn.d3dcaps.SrcBlendCaps & REQUIRED_SRCBLENDCAPS)!=REQUIRED_SRCBLENDCAPS) || + ((scrn.d3dcaps.DestBlendCaps & REQUIRED_DESTBLENDCAPS)!=REQUIRED_DESTBLENDCAPS)) { + dxgsg_cat.error() << "device is missing alpha blending capabilities, blending may not work correctly: SrcBlendCaps: 0x"<< (void*) scrn.D3DDevDesc.SrcBlendCaps << " DestBlendCaps: "<< (void*) scrn.D3DDevDesc.DestBlendCaps << endl; } -//#define REQUIRED_BLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE|D3DPBLENDCAPS_SRCCOLOR|D3DPBLENDCAPS_INVSRCCOLOR| \ -// D3DPBLENDCAPS_SRCALPHA|D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA|D3DPBLENDCAPS_INVDESTALPHA|D3DPBLENDCAPS_DESTCOLOR|D3DPBLENDCAPS_INVDESTCOLOR) -// voodoo3 doesnt support commented out ones, & we dont need them now +// just 'require' bilinear with mip nearest. +#define REQUIRED_TEXFILTERCAPS (D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MINFLINEAR) -#define REQUIRED_BLENDCAPS (D3DPBLENDCAPS_ZERO|D3DPBLENDCAPS_ONE| /*D3DPBLENDCAPS_SRCCOLOR|D3DPBLENDCAPS_INVSRCCOLOR| */ \ - D3DPBLENDCAPS_SRCALPHA|D3DPBLENDCAPS_INVSRCALPHA /* | D3DPBLENDCAPS_DESTALPHA|D3DPBLENDCAPS_INVDESTALPHA|D3DPBLENDCAPS_DESTCOLOR|D3DPBLENDCAPS_INVDESTCOLOR*/) - - if (((scrn.D3DDevDesc.dpcTriCaps.dwSrcBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS) || - ((scrn.D3DDevDesc.dpcTriCaps.dwDestBlendCaps & REQUIRED_BLENDCAPS)!=REQUIRED_BLENDCAPS)) { - dxgsg_cat.error() << "device is missing alpha blending capabilities, blending may not work correctly: SrcBlendCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwSrcBlendCaps << " DestBlendCaps: "<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwDestBlendCaps << endl; + if ((scrn.d3dcaps.TextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) { + dxgsg_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky! TextureFilterCaps: 0x"<< (void*) scrn.d3dcaps.TextureFilterCaps << endl; } - if (!(scrn.D3DDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_TRANSPARENCY)) { - dxgsg_cat.error() << "device is missing texture transparency capability, transparency may not work correctly! TextureCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureCaps << endl; - } +#define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR) - // just require trilinear. if it can do that, it can probably do all the lesser point-sampling variations too -#define REQUIRED_TEXFILTERCAPS (D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_LINEAR) - if ((scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_TEXFILTERCAPS)!=REQUIRED_TEXFILTERCAPS) { - dxgsg_cat.error() << "device is missing texture bilinear filtering capability, textures may appear blocky! TextureFilterCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; - } -#define REQUIRED_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR) - - if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) { - dxgsg_cat.debug() << "device does not have mipmap texturing filtering capability! TextureFilterCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; + // give a warning if we dont at least have bilinear + nearest mip filtering + if (!(scrn.d3dcaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)) { + if(dxgsg_cat.is_debug() + dxgsg_cat.debug() << "device does not have mipmap texturing filtering capability! TextureFilterCaps: 0x"<< (void*) scrn.d3dcaps.TextureFilterCaps << endl; dx_ignore_mipmaps = TRUE; - } else if ((scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps & REQUIRED_MIPMAP_TEXFILTERCAPS)!=REQUIRED_MIPMAP_TEXFILTERCAPS) { - dxgsg_cat.debug() << "device is missing tri-linear mipmap filtering capability, texture mipmaps may not supported! TextureFilterCaps: 0x"<< (void*) scrn.D3DDevDesc.dpcTriCaps.dwTextureFilterCaps << endl; + } else if ((scrn.d3dcaps.dwTextureFilterCaps & REQUIRED_MIPMAP_TEXFILTERCAPS)!=REQUIRED_MIPMAP_TEXFILTERCAPS) { + if(dxgsg_cat.is_debug() + dxgsg_cat.debug() << "device is missing tri-linear mipmap filtering capability, textures may look crappy\n"; + } else if(scrn.d3dcaps.DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) { + // this cap is pretty much voodoo2-specific + // turn off trilinear filtering on voodoo2 since it doubles the reqd texture memory, degrade to mip point filtering + scrn.d3dcaps.TextureFilterCaps &= (~D3DPTFILTERCAPS_MIPFLINEAR); } #define REQUIRED_TEXBLENDCAPS (D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2) - if ((scrn.D3DDevDesc.dwTextureOpCaps & REQUIRED_TEXBLENDCAPS)!=REQUIRED_TEXBLENDCAPS) { - dxgsg_cat.error() << "device is missing some required texture blending capabilities, texture blending may not work properly! TextureOpCaps: 0x"<< (void*) scrn.D3DDevDesc.dwTextureOpCaps << endl; + if ((scrn.d3dcaps.TextureOpCaps & REQUIRED_TEXBLENDCAPS)!=REQUIRED_TEXBLENDCAPS) { + dxgsg_cat.error() << "device is missing some required texture blending capabilities, texture blending may not work properly! TextureOpCaps: 0x"<< (void*) scrn.d3dcaps.TextureOpCaps << endl; } - if(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE) { + if(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) { // watch out for drivers that emulate per-pixel fog with per-vertex fog (Riva128, Matrox Millen G200) // some of these require gouraud-shading to be set to work, as if you were using vertex fog _doFogType=PerPixelFog; } else { // every card is going to have vertex fog, since it's implemented in d3d runtime - assert((scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGVERTEX )!=0); + assert((scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX )!=0); // vtx fog may look crappy if you have large polygons in the foreground and they get clipped, // so you may want to disable it @@ -721,8 +695,8 @@ dx_init( void) { _doFogType = PerVertexFog; // range-based fog only works with vertex fog in dx7/8 - if(dx_use_rangebased_fog && (scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGRANGE)) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_RANGEFOGENABLE, true); + if(dx_use_rangebased_fog && (scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE)) + scrn.pD3DDevice->SetRenderState(D3DRS_RANGEFOGENABLE, true); } } @@ -730,37 +704,34 @@ dx_init( void) { // Lighting, let's turn it off by default _lighting_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, _lighting_enabled); + scrn.pD3DDevice->SetRenderState(D3DRS_LIGHTING, _lighting_enabled); // turn on dithering if the rendertarget is < 8bits/color channel - DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_back); - scrn.pddsBack->GetSurfaceDesc(&ddsd_back); - _dither_enabled = (!dx_no_dithering) && ((ddsd_back.ddpfPixelFormat.dwRGBBitCount < 24) && - (scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_DITHER)); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, _dither_enabled); + _dither_enabled = (!dx_no_dithering) && IS_16BPP_FMT(scrn.PresParams.BackBufferFormat) + && (scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_DITHER)); + scrn.pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, _dither_enabled); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING,true); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING,true); // Stencil test is off by default _stencil_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILENABLE, _stencil_test_enabled); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILENABLE, _stencil_test_enabled); // Antialiasing. enable_line_smooth(false); // enable_multisample(true); _current_fill_mode = RenderModeProperty::M_filled; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); + scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); + scrn.pD3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); // Use the diffuse vertex color. - // technically DX7's front-end has no limit on the number of lights, but it's simpler for - // this implementation to set a small GL-like limit to make the light array traversals short - // and so I dont have to write code that reallocs light arrays - assert((scrn.D3DDevDesc.dwMaxActiveLights==0) || // 0 means infinite lights - (DXGSG_MAX_LIGHTS <= scrn.D3DDevDesc.dwMaxActiveLights)); - - _max_lights = DXGSG_MAX_LIGHTS; + if(scrn.d3dcaps.dwMaxActiveLights==0) { + // 0 indicates no limit on # of lights, but we use DXGSG_MAX_LIGHTS anyway for now + _max_lights = DXGSG_MAX_LIGHTS; + } else { + _max_lights = min(DXGSG_MAX_LIGHTS,scrn.d3dcaps.dwMaxActiveLights); + } _available_light_ids = PTA(Light*)::empty_array(_max_lights); _light_enabled = new bool[_max_lights]; @@ -773,10 +744,13 @@ dx_init( void) { } if(dx_auto_normalize_lighting) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_NORMALIZENORMALS, true); + scrn.pD3DDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true); + + // Set up the clip plane id map (need to rewrite this) + if(scrn.d3dcaps.MaxUserClipPlanes==0) + _max_clip_planes = D3DMAXUSERCLIPPLANES; + else _max_clip_planes = scrn.d3dcaps.MaxUserClipPlanes; - // Set up the clip plane id map - _max_clip_planes = D3DMAXUSERCLIPPLANES; _available_clip_plane_ids = PTA(PlaneNode*)::empty_array(_max_clip_planes); _clip_plane_enabled = new bool[_max_clip_planes]; _cur_clip_plane_enabled = new bool[_max_clip_planes]; @@ -812,139 +786,44 @@ dx_init( void) { scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV,get_texture_wrap_mode(_CurTexWrapModeV)); #ifdef _DEBUG - if ((scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) && + if ((scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) && (dx_global_miplevel_bias!=0.0f)) { scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&dx_global_miplevel_bias)) ); } #endif - if(dx_full_screen_antialiasing) { - if(scrn.D3DDevDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ANTIALIAS,D3DANTIALIAS_SORTINDEPENDENT); - if(dxgsg_cat.is_debug()) - dxgsg_cat.debug() << "enabling full-screen anti-aliasing\n"; - } else { - if(dxgsg_cat.is_debug()) - dxgsg_cat.debug() << "device doesnt support full-screen anti-aliasing\n"; - } - } - #ifndef NDEBUG if(dx_force_backface_culling!=0) { if((dx_force_backface_culling > 0) && (dx_force_backface_culling < D3DCULL_FORCE_DWORD)) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling); } else { dx_force_backface_culling=0; if(dxgsg_cat.is_debug()) dxgsg_cat.debug() << "error, invalid value for dx-force-backface-culling\n"; } } - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, dx_force_backface_culling); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, dx_force_backface_culling); #else - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); #endif _alpha_func = D3DCMP_ALWAYS; _alpha_func_ref = 0; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, _alpha_func); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, _alpha_func_ref); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, _alpha_func); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHAREF, _alpha_func_ref); _alpha_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, _alpha_test_enabled); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, _alpha_test_enabled); + // this is a new DX8 state that lets you do additional operations other than ADD (e.g. subtract/max/min) + // must check (scrn.d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) (yes on GF2/Radeon85, no on TNT) + scrn.pD3DDevice->SetRenderState(D3DRS_BLENDOP,D3DBLENDOP_ADD); + hr = CreateDX8Cursor(scrn.pD3DDevice,_hCursor,true); + if(FAILED(hr)) + dxgsg_cat.error() << "CreateDX8Cursor failed!\n"; - - // all this must be moved to dx_init, since we need to create DX surface - string windows_icon_filename = get_icon_filename().to_os_specific(); - string windows_mono_cursor_filename = get_mono_cursor_filename().to_os_specific(); - string windows_color_cursor_filename = get_color_cursor_filename().to_os_specific(); - - if(!windows_icon_filename.empty()) { - // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) - // if icon is more than 8bpp - - // loads a .ico fmt file - wc.hIcon = (HICON) LoadImage(NULL, windows_icon_filename.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE ); - - if(wc.hIcon==NULL) { - wdxdisplay_cat.warning() << "windows icon filename '" << windows_icon_filename << "' not found!!\n"; - } - } else { - wc.hIcon = NULL; // use default app icon - } - - - if(!windows_color_cursor_filename.empty()) { - // card support for full color non-black/white GDI cursors varies greatly. if the cursor is not supported, - // it is rendered in software by GDI, which causes a flickering effect (because it's not synced - // with flip?). GDI transparently masks the lack of HW support so there is no easy way for app to detect - // if HW cursor support exists. alternatives are to tie cursor motion to frame rate using DDraw blts - // or overlays (this is done automatically by DX8 runtime mouse cursor support), or to have separate thread draw cursor - // (sync issues?). instead we do mono cursor unless card is known to support 256 color cursors - bool bSupportsColorCursor=true; - - /* if any card doesnt support color, dont load it*/ - for(int w=0;w<_windows.size();w++) - bSupportsColorCursor &= supports_color_cursors(_windows[w]->_dxgsg->scrn.DXDeviceID); - - if(bSupportsColorCursor) { - DWORD load_flags = LR_LOADFROMFILE; - - if(dx_full_screen) { - // I think cursors should use LR_CREATEDIBSECTION since they should not be mapped to the device palette (in the case of 256-color cursors) - // since they are not going to be used on the desktop - load_flags |= LR_CREATEDIBSECTION; - } - - // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) - // if icon is more than 8bpp - - // loads a .cur fmt file. - _hMouseCursor = (HCURSOR) LoadImage(NULL, windows_color_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, load_flags ); - - if(_hMouseCursor==NULL) { - wdxdisplay_cat.warning() << "windows color cursor filename '" << windows_color_cursor_filename << "' not found!!\n"; - goto try_mono_cursor; - - } - -/* dont need these anymore since we are do mousestuff before window creation - SetClassLongPtr(_mwindow, GCLP_HCURSOR, (LONG_PTR) hNewMouseCursor); - SetCursor(hNewMouseCursor); - - if(_bLoadedCustomCursor) - DestroyCursor(_hMouseCursor); -*/ - _bLoadedCustomCursor=true; - } - } - - try_mono_cursor: - - if((!_bLoadedCustomCursor) && (!windows_mono_cursor_filename.empty())) { - // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) - // if icon is more than 8bpp - - DWORD load_flags = LR_LOADFROMFILE; - - if(dx_full_screen) { - // I think cursors should use LR_CREATEDIBSECTION since they should not be mapped to the device palette (in the case of 256-color cursors) - // since they are not going to be used on the desktop - load_flags |= LR_CREATEDIBSECTION; - } - // loads a .cur fmt file. - _hMouseCursor = (HCURSOR) LoadImage(NULL, windows_mono_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, load_flags); - - if(_hMouseCursor==NULL) { - wdxdisplay_cat.warning() << "windows mono cursor filename '" << windows_mono_cursor_filename << "' not found!!\n"; - } else _bLoadedCustomCursor=true; - } - - if(!_bLoadedCustomCursor) - _hMouseCursor = LoadCursor(NULL, DEFAULT_CURSOR); - - + #if 0 // need to release this better, so dx_init can be called multiple times if(_bShowFPSMeter) { _start_time = timeGetTime(); @@ -1016,7 +895,7 @@ dx_init( void) { // could handle this case less wastefully by creating font texture w/multiple rows, // so its naturally square - if(scrn.D3DDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) { + if(scrn.d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) { if(texdim_y> texdim_x) texdim_x = texdim_y; texdim_y = texdim_x; @@ -1034,7 +913,7 @@ dx_init( void) { // Create a new surface for the texture if(FAILED( hr = scrn.pDD->CreateSurface( &ddsd, &_fpsmeter_font_surf, NULL ) )) { - dxgsg_cat.error() << "CreateSurface() failed for fpsmeter font! hr = " << ConvD3DErrorToString(hr) << "\n"; + dxgsg_cat.error() << "CreateSurface() failed for fpsmeter font! hr = " << D3DERRORSTRING(hr); _bShowFPSMeter = false; return; } @@ -1058,6 +937,9 @@ dx_init( void) { SetFPSMeterPosition(scrn.view_rect); } + #else + _bShowFPSMeter = false; + #endif // Make sure the DX state matches all of our initial attribute states. PT(DepthTestTransition) dta = new DepthTestTransition; @@ -1086,24 +968,28 @@ clear(const RenderBuffer &buffer) { nassertv(buffer._gsg == this); int buffer_type = buffer._buffer_type; - int flags = 0; + DWORD flags = 0; - if (buffer_type & RenderBuffer::T_depth) { + if(buffer_type & RenderBuffer::T_depth) { flags |= D3DCLEAR_ZBUFFER; - assert(scrn.pddsZBuf!=NULL); + assert(scrn.pPresParams.EnableAutoDepthStencil); } - if (buffer_type & RenderBuffer::T_back) //set appropriate flags - flags |= D3DCLEAR_TARGET; - if (buffer_type & RenderBuffer::T_stencil) - flags |= D3DCLEAR_STENCIL; - HRESULT hr = scrn.pD3DDevice->Clear(0, NULL, flags, _d3dcolor_clear_value, - (D3DVALUE) _depth_clear_value, (DWORD)_stencil_clear_value); - if (hr != DD_OK) - dxgsg_cat.error() << "clear_buffer failed: Clear returned " << ConvD3DErrorToString(hr) << endl; - /* The following line will cause the background to always clear to a medium red + if(buffer_type & RenderBuffer::T_back) //set appropriate flags + flags |= D3DCLEAR_TARGET; + + if(buffer_type & RenderBuffer::T_stencil) { + flags |= D3DCLEAR_STENCIL; + assert(scrn.pPresParams.EnableAutoDepthStencil && IS_STENCIL_FORMAT(AutoDepthStencilFormat)); + } + + HRESULT hr = scrn.pD3DDevice->Clear(0, NULL, flags, _d3dcolor_clear_value, + _depth_clear_value, (DWORD)_stencil_clear_value); + if(FAILED(hr)) + dxgsg_cat.error() << "clear_buffer failed: Clear returned " << D3DERRORSTRING(hr); + /* The following line will cause the background to always clear to a medium red _color_clear_value[0] = .5; - /* The following lines will cause the background color to cycle from black to red. + /* The following lines will cause the background color to cycle from black to red. _color_clear_value[0] += .001; if (_color_clear_value[0] > 1.0f) _color_clear_value[0] = 0.0f; */ @@ -1129,17 +1015,16 @@ clear(const RenderBuffer &buffer, const DisplayRegion *region) { // Description: //////////////////////////////////////////////////////////////////// bool DXGraphicsStateGuardian:: -enable_light(int light, bool val) { - if (_light_enabled[light] != val) { - _light_enabled[light] = val; - HRESULT res = scrn.pD3DDevice->LightEnable( light, val ); +enable_light(int light_id, bool val) { + if (_light_enabled[light_id] != val) { + _light_enabled[light_id] = val; + HRESULT hr = scrn.pD3DDevice->LightEnable( light_id, val ); #ifdef GSG_VERBOSE - dxgsg_cat.debug() - << "LightEnable(" << light << "=" << val << ")" << endl; + dxgsg_cat.debug() << "LightEnable(" << light_id << "=" << val << ")" << endl; #endif - return(res == DD_OK); + return(hr == DD_OK); } return TRUE; } @@ -1232,15 +1117,15 @@ void DXGraphicsStateGuardian::set_clipper(RECT cliprect) { #endif #if defined(_DEBUG) || defined(COUNT_DRAWPRIMS) -typedef enum {DrawPrim,DrawIndexedPrim,DrawPrimStrided} DP_Type; -static const char *DP_Type_Strs[3] = {"DrawPrimitive","DrawIndexedPrimitive","DrawPrimitiveStrided"}; +typedef enum {DrawPrim,DrawIndexedPrim} DP_Type; +static const char *DP_Type_Strs[3] = {"DrawPrimitive","DrawIndexedPrimitive"}; void INLINE TestDrawPrimFailure(DP_Type dptype,HRESULT hr,LPDIRECTDRAW7 pDD,DWORD nVerts,DWORD nTris) { if(FAILED(hr)) { // loss of exclusive mode is not a real DrawPrim problem, ignore it HRESULT testcooplvl_hr = pDD->TestCooperativeLevel(); if((testcooplvl_hr != DDERR_NOEXCLUSIVEMODE)||(testcooplvl_hr != DDERR_EXCLUSIVEMODEALREADYSET)) { - dxgsg_cat.fatal() << DP_Type_Strs[dptype] << "() failed: result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.fatal() << DP_Type_Strs[dptype] << "() failed: result = " << D3DERRORSTRING(hr); exit(1); } } @@ -1283,13 +1168,13 @@ render_frame() { HRESULT hr = scrn.pD3DDevice->BeginScene(); if(FAILED(hr)) { - if((hr==DDERR_SURFACELOST)||(hr==DDERR_SURFACEBUSY)) { + if((hr==D3DERR_DEVICELOST)||(hr==DDERR_SURFACELOST)||(hr==DDERR_SURFACEBUSY)) { if(dxgsg_cat.is_debug()) - dxgsg_cat.debug() << "BeginScene returns " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.debug() << "BeginScene returns " << D3DERRORSTRING(hr); CheckCooperativeLevel(); } else { - dxgsg_cat.error() << "BeginScene failed, unhandled error hr == " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "BeginScene failed, unhandled error hr == " << D3DERRORSTRING(hr); exit(1); } return; @@ -1400,33 +1285,32 @@ render_frame() { #ifdef MAKE_FPSMETER_TRANSPARENT call_dxBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); if(!_blend_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); #else if(_blend_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); #endif - if (_CurShadeMode != D3DSHADE_FLAT) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT); - } + if(_bGouraudShadingOn) + scrn.pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, false); DWORD saved_zfunc; - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_ZFUNC,&saved_zfunc); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC,D3DCMP_ALWAYS); + scrn.pD3DDevice->GetRenderState(D3DRS_ZFUNC,&saved_zfunc); + scrn.pD3DDevice->SetRenderState(D3DRS_ZFUNC,D3DCMP_ALWAYS); DWORD saved_fill_state; if(_current_fill_mode != RenderModeProperty::M_filled) { - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &saved_fill_state); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); + scrn.pD3DDevice->GetRenderState(D3DRS_FILLMODE, &saved_fill_state); + scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); } DWORD saved_clipping_state,saved_cull_state; - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_CULLMODE, &saved_cull_state); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + scrn.pD3DDevice->GetRenderState(D3DRS_CULLMODE, &saved_cull_state); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_CLIPPING, &saved_clipping_state); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, false); + scrn.pD3DDevice->GetRenderState(D3DRS_CLIPPING, &saved_clipping_state); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, false); // ignore lighting state since verts are post-xform @@ -1463,7 +1347,7 @@ render_frame() { hr = scrn.pD3DDevice->SetTexture(0, _fpsmeter_font_surf); if(FAILED(hr)) { - dxgsg_cat.error() << "SetTexture failed in draw fps meter, result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "SetTexture failed in draw fps meter, result = " << D3DERRORSTRING(hr); exit(1); } @@ -1473,16 +1357,16 @@ render_frame() { #ifdef MAKE_FPSMETER_TRANSPARENT if(!_blend_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); #else if(_blend_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true); + scrn.pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); #endif - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, saved_zfunc); + scrn.pD3DDevice->SetRenderState(D3DRS_ZFUNC, saved_zfunc); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, saved_clipping_state); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, saved_cull_state); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, saved_clipping_state); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, saved_cull_state); scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, saved_magfilter); scrn.pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, saved_minfilter); @@ -1492,12 +1376,11 @@ render_frame() { scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, saved_alphaop); scrn.pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, saved_alphaarg1); - if (_CurShadeMode != D3DSHADE_FLAT) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, _CurShadeMode); - } + if(_bGouraudShadingOn) + scrn.pD3DDevice->SetRenderState(D3DRS_COLORVERTEX, true); if(_current_fill_mode != RenderModeProperty::M_filled) { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, saved_fill_state); + scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, saved_fill_state); } scrn.pD3DDevice->SetTexture(0, ((_pCurTexContext != NULL) ? _pCurTexContext->_surface : NULL)); @@ -1534,11 +1417,11 @@ render_frame() { if(FAILED(hr)) { if((hr==DDERR_SURFACELOST)||(hr==DDERR_SURFACEBUSY)) { if(dxgsg_cat.is_debug()) - dxgsg_cat.debug() << "EndScene returns " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.debug() << "EndScene returns " << D3DERRORSTRING(hr); CheckCooperativeLevel(); } else { - dxgsg_cat.error() << "EndScene failed, unhandled error hr == " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "EndScene failed, unhandled error hr == " << D3DERRORSTRING(hr); exit(1); } return; @@ -1655,13 +1538,13 @@ report_texmgr_stats() { ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; if(FAILED( hr = scrn.pDD->GetAvailableVidMem(&ddsCaps,&dwVidTotal,&dwVidFree))) { - dxgsg_cat.debug() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.debug() << "report_texmgr GetAvailableVidMem for VIDMEM failed : result = " << D3DERRORSTRING(hr); exit(1); } ddsCaps.dwCaps = DDSCAPS_TEXTURE; if(FAILED( hr = scrn.pDD->GetAvailableVidMem(&ddsCaps,&dwTexTotal,&dwTexFree))) { - dxgsg_cat.debug() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.debug() << "report_texmgr GetAvailableVidMem for TEXTURE failed : result = " << D3DERRORSTRING(hr); exit(1); } } @@ -1681,7 +1564,7 @@ report_texmgr_stats() { bTexStatsRetrievalImpossible=true; } } else { - dxgsg_cat.error() << "d3ddev->GetInfo(TEXTUREMANAGER) failed to get tex stats: result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "d3ddev->GetInfo(TEXTUREMANAGER) failed to get tex stats: result = " << D3DERRORSTRING(hr); return; } } @@ -1713,7 +1596,7 @@ report_texmgr_stats() { ZeroMemory(&texappinfo,sizeof(D3DDEVINFO_TEXTURING)); hr = scrn.pD3DDevice->GetInfo(D3DDEVINFOID_TEXTURING,&texappinfo,sizeof(D3DDEVINFO_TEXTURING)); if (hr!=D3D_OK) { - dxgsg_cat.error() << "GetInfo(TEXTURING) failed : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "GetInfo(TEXTURING) failed : result = " << D3DERRORSTRING(hr); return; } else { dxgsg_cat.spam() @@ -2065,11 +1948,11 @@ draw_prim_setup(const Geom *geom) { // (note, TNT does the right thing tho). So I guess we must do gouraud shading for all fog rendering for now // note that if _doFogType==None, _fog_enabled will always be false - D3DSHADEMODE needed_shademode = + bool bDoGouraudShading = (((_perVertex & (PER_COLOR | (wants_normals() ? PER_NORMAL : 0))) || _fog_enabled) ? - D3DSHADE_GOURAUD : D3DSHADE_FLAT); + true : false); - set_shademode(needed_shademode); + set_shademode(bDoGouraudShading); return vertex_size; } @@ -2223,27 +2106,9 @@ draw_point(GeomPoint *geom, GeomContext *gc) { geom->get_colors(colors,bind,cindexes); geom->get_texcoords(texcoords,bind,tindexes); - GeomVertFormat GeomVrtFmt=FlatVerts; - - // first determine if we're indexed or non-indexed - - if ((vindexes!=NULL)&&(cindexes!=NULL)&&(tindexes!=NULL)&&(nindexes!=NULL)) { - GeomVrtFmt=IndexedVerts; - } else if (!((vindexes==NULL)&&(cindexes==NULL)&&(tindexes==NULL)&&(nindexes==NULL))) - GeomVrtFmt=MixedFmtVerts; - -#ifdef DONT_USE_DRAWPRIMSTRIDED - GeomVrtFmt=MixedFmtVerts; -#else - if(_bDrawPrimDoSetupVertexBuffer) { - GeomVrtFmt=MixedFmtVerts; - } -#endif - // for Indexed Prims and mixed indexed/non-indexed prims, we will use old pipeline for now // need to add code to handle fully indexed mode (and handle cases with index arrays of different lengths, // values (may only be possible to handle certain cases without reverting to old pipeline) - if (GeomVrtFmt!=FlatVerts) { _perVertex = 0x0; _perPrim = 0; @@ -2265,59 +2130,12 @@ draw_point(GeomPoint *geom, GeomContext *gc) { } else { COPYVERTDATA_2_VERTEXBUFFER(D3DPT_POINTLIST,nPrims); } - } else { // setup for strided - - size_t vertex_size = draw_prim_setup(geom); - - // new code only handles non-indexed pointlists (is this enough?) - nassertv((vindexes==NULL)&&(cindexes==NULL)&&(tindexes==NULL)&&(nindexes==NULL)); - - D3DDRAWPRIMITIVESTRIDEDDATA dps_data; - memset(&dps_data,0,sizeof(D3DDRAWPRIMITIVESTRIDEDDATA)); - - dps_data.position.lpvData = (VOID*)coords; - dps_data.position.dwStride = sizeof(D3DVECTOR); - - if (_curFVFflags & D3DFVF_NORMAL) { - dps_data.normal.lpvData = (VOID*)norms; - dps_data.normal.dwStride = sizeof(D3DVECTOR); - } - - if (_curFVFflags & D3DFVF_DIFFUSE) { - _pCurFvfBufPtr=_pFvfBufBasePtr; - - dps_data.diffuse.lpvData = (VOID*)_pFvfBufBasePtr; - dps_data.diffuse.dwStride = sizeof(D3DCOLOR); - - // Geom nodes store floats for colors, drawprim requires ARGB dwords - // BUGBUG: eventually this hack every-frame all-colors conversion needs - // to be done only once as part of a vertex buffer - - if(_color_transform_required) { - for (int i=0;iDrawPrimitiveStrided(D3DPT_POINTLIST, _curFVFflags, &dps_data, nPrims, NULL); - TestDrawPrimFailure(DrawPrimStrided,hr,scrn.pDD,nPrims,0); - } + _pCurFvfBufPtr = NULL; } + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian::draw_line // Access: Public, Virtual @@ -2339,20 +2157,22 @@ draw_line(GeomLine* geom, GeomContext *gc) { if (!bPrintedMsg && (geom->get_width()!=1.0f)) { bPrintedMsg=TRUE; - dxgsg_cat.warning() << "DX does not support drawing lines with a non-1.0f pixel width, setting width to 1.0f!\n"; + if(dxgsg_cat.is_debug()) + dxgsg_cat.debug() << "DX does not support drawing lines with a non-1.0f pixel width, setting width to 1.0f!\n"; } #endif int nPrims = geom->get_num_prims(); if (nPrims==0) { - dxgsg_cat.warning() << "draw_line() called with ZERO vertices!!" << endl; + if(dxgsg_cat.is_debug()) + dxgsg_cat.debug() << "draw_line() called with ZERO vertices!!" << endl; return; } - assert(geom->get_binding(G_COORD) == G_PER_VERTEX); _perVertex = 0x0; - _perPrim = _perComp = 0x0; + _perPrim = 0x0; + _perComp = 0x0; switch(geom->get_binding(G_NORMAL)) { case G_PER_VERTEX: @@ -2378,13 +2198,13 @@ draw_line(GeomLine* geom, GeomContext *gc) { size_t vertex_size = draw_prim_setup(geom); - char *_tmp_fvf = NULL; + BYTE *_tmp_fvfOverrunBuf = NULL; nassertv(_pCurFvfBufPtr == NULL); // make sure the storage pointer is clean. // nassertv(nPrims * 2 * vertex_size < VERT_BUFFER_SIZE); if (nPrims * 2 * vertex_size > VERT_BUFFER_SIZE) { // bugbug: need cleaner way to handle tmp buffer size overruns (malloc/realloc?) - _pCurFvfBufPtr = _tmp_fvf = new char[nPrims * 2 * vertex_size]; + _pCurFvfBufPtr = _tmp_fvfOverrunBuf = new BYTE[nPrims * 2 * vertex_size]; } else _pCurFvfBufPtr = _pFvfBufBasePtr; // _pCurFvfBufPtr changes, _pFvfBufBasePtr doesn't for (int i = 0; i < nPrims; i++) { @@ -2398,18 +2218,20 @@ draw_line(GeomLine* geom, GeomContext *gc) { HRESULT hr; - DWORD vertCount = nPrims<<1; + DWORD nVerts = nPrims<<1; if(!_bDrawPrimDoSetupVertexBuffer) { - if (_tmp_fvf == NULL) - hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _pFvfBufBasePtr, vertCount, NULL); - else { - hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _tmp_fvf, vertCount, NULL); - delete [] _tmp_fvf; + if (_tmp_fvfOverrunBuf == NULL) { + nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); + hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); + } else { + nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_tmp_fvfOverrunBuf)); + hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINELIST, _curFVFflags, _tmp_fvfOverrunBuf, nVerts, NULL); + delete [] _tmp_fvfOverrunBuf; } - TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,vertCount,0); + TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,0); } else { - COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINELIST,vertCount); + COPYVERTDATA_2_VERTEXBUFFER(D3DPT_LINELIST,nVerts); } _pCurFvfBufPtr = NULL; @@ -2437,6 +2259,7 @@ draw_linestrip(GeomLinestrip* geom, GeomContext *gc) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian:: draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { +// Note draw_linestrip_base() may be called from non-line draw_fns to support wireframe mode #ifdef GSG_VERBOSE dxgsg_cat.debug() << "draw_linestrip()" << endl; @@ -2446,17 +2269,18 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { DO_PSTATS_STUFF(_vertices_other_pcollector.add_level(geom->get_num_vertices())); int nPrims = geom->get_num_prims(); - const int *plen = geom->get_lengths(); + const int *pLengthArr = geom->get_lengths(); - if (nPrims==0) { - dxgsg_cat.warning() << "draw_linestrip() called with ZERO vertices!!" << endl; + if(nPrims==0) { + if(dxgsg_cat.is_debug()) + dxgsg_cat.debug() << "draw_linestrip() called with ZERO vertices!!" << endl; return; } - assert(geom->get_binding(G_COORD) == G_PER_VERTEX); _perVertex = 0x0; + _perPrim = 0x0; + _perComp = 0x0; - _perPrim = _perComp = 0; switch(geom->get_binding(G_NORMAL)) { case G_PER_VERTEX: _perVertex |= PER_NORMAL; @@ -2482,18 +2306,26 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { size_t vertex_size = draw_prim_setup(geom); ushort perFlags = _perVertex | _perComp; + bool bPerPrimColor = ((_perPrim & PER_COLOR)!=0); + bool bPerPrimNormal = ((_perPrim & PER_NORMAL)!=0); + + DWORD nVerts; + + if(pLengthArr==NULL) // we've been called by draw_quad, which has no lengths array + nVerts=4; + for (int i = 0; i < nPrims; i++) { - if (_perPrim & PER_COLOR) { + if (bPerPrimColor) { GET_NEXT_COLOR(); } - int nVerts; + if (bPerPrimNormal) { + p_normal = geom->get_next_normal(ni); // set primitive normal if there is one. + } - if(plen!=NULL) { - nVerts= *(plen++); + if(pLengthArr!=NULL) { + nVerts= *(pLengthArr++); nassertv(nVerts >= 2); - } else { - nVerts=4; // we've been called by draw_quad, which has no lengths array } nassertv(_pCurFvfBufPtr == NULL); // make sure the storage pointer is clean. @@ -2509,6 +2341,8 @@ draw_linestrip_base(Geom* geom, GeomContext *gc, bool bConnectEnds) { nVerts++; } + nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); + if(!_bDrawPrimDoSetupVertexBuffer) { HRESULT hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_LINESTRIP, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,0); @@ -2959,7 +2793,7 @@ draw_polygon(GeomPolygon *geom, GeomContext *gc) { // wireframe polygon will be drawn as linestrip, otherwise draw as multi-tri trifan DWORD rstate; - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate); + scrn.pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate); if(rstate==D3DFILL_WIREFRAME) { draw_linestrip_base(geom,gc,true); } else { @@ -2983,7 +2817,7 @@ draw_quad(GeomQuad *geom, GeomContext *gc) { // wireframe quad will be drawn as linestrip, otherwise draw as multi-tri trifan DWORD rstate; - scrn.pD3DDevice->GetRenderState(D3DRENDERSTATE_FILLMODE, &rstate); + scrn.pD3DDevice->GetRenderState(D3DRS_FILLMODE, &rstate); if(rstate==D3DFILL_WIREFRAME) { draw_linestrip_base(geom,gc,true); } else { @@ -2991,6 +2825,7 @@ draw_quad(GeomQuad *geom, GeomContext *gc) { } } + //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian::draw_tri // Access: Public, Virtual @@ -3029,50 +2864,38 @@ draw_tri(GeomTri *geom, GeomContext *gc) { geom->get_normals(norms,NormalBinding,nindexes); geom->get_colors(colors,ColorBinding,cindexes); geom->get_texcoords(texcoords,TexCoordBinding,tindexes); - - GeomVertFormat GeomVrtFmt=FlatVerts; - - // first determine if we're indexed or non-indexed - - if ((vindexes!=NULL)&&(cindexes!=NULL)&&(tindexes!=NULL)&&(nindexes!=NULL)) { - GeomVrtFmt=IndexedVerts; - //make sure array sizes are consistent, we can only pass 1 size to DrawIPrm -// nassertv(coords.size==norms.size); nassertv(coords.size==colors.size); nassertv(coords.size==texcoords.size); need to assert only if we have this w/same binding - // indexed mode requires all used norms,colors,texcoords,coords array be the same - // length, or 0 or 1 (dwStride==0), also requires all elements to use the same index array - } else if (!((vindexes==NULL)&&(cindexes==NULL)&&(tindexes==NULL)&&(nindexes==NULL))) - GeomVrtFmt=MixedFmtVerts; - -#ifdef DONT_USE_DRAWPRIMSTRIDED - GeomVrtFmt=MixedFmtVerts; -#else - if(_bDrawPrimDoSetupVertexBuffer) { - GeomVrtFmt=MixedFmtVerts; - } -#endif - - // for Indexed Prims and mixed indexed/non-indexed prims, we will use old pipeline for now - // need to add code to handle fully indexed mode (and handle cases with index arrays of different lengths, - // values (may only be possible to handle certain cases without reverting to old pipeline) - if (GeomVrtFmt!=FlatVerts) { + // this is the old geom setup, it reformats every vtx into an output array passed to d3d _perVertex = 0x0; _perPrim = 0x0; - if(NormalBinding == G_PER_VERTEX) - _perVertex |= PER_NORMAL; - else if(NormalBinding == G_PER_PRIM) - _perPrim |= PER_NORMAL; + bool bUseTexCoordOnlyLoop = ((ColorBinding != G_PER_VERTEX) && + (NormalBinding == G_OFF) && + (TexCoordBinding != G_OFF)); - if(ColorBinding == G_PER_PRIM) + bool bPerPrimNormal; + bool bPerPrimColor=((_perPrim & PER_COLOR)!=0); + + if(bUseTexCoordOnlyLoop) { + _perVertex |= PER_TEXCOORD; // TexCoords are either G_OFF or G_PER_VERTEX + } else { + if(NormalBinding == G_PER_VERTEX) + _perVertex |= PER_NORMAL; + else if(NormalBinding == G_PER_PRIM) + _perPrim |= PER_NORMAL; + + bPerPrimNormal=((_perPrim & PER_NORMAL)!=0); + + if(TexCoordBinding == G_PER_VERTEX) + _perVertex |= PER_TEXCOORD; + } + + if(bPerPrimColor) _perPrim |= PER_COLOR; else if(ColorBinding == G_PER_VERTEX) _perVertex |= PER_COLOR; - if (TexCoordBinding == G_PER_VERTEX) - _perVertex |= PER_TEXCOORD; - size_t vertex_size = draw_prim_setup(geom); nassertv(_pCurFvfBufPtr == NULL); // make sure the storage pointer is clean. @@ -3082,21 +2905,24 @@ draw_tri(GeomTri *geom, GeomContext *gc) { // iterate through the triangle primitive for (uint i = 0; i < nPrims; i++) { - if (_perPrim & PER_COLOR) { + if(bPerPrimColor) { // remember color might be G_OVERALL too! GET_NEXT_COLOR(); } - if (_perPrim & PER_NORMAL) - p_normal = geom->get_next_normal(ni); // set primitive normal if there is one. - - - if(_perVertex==TexCoordOnly) + if(bUseTexCoordOnlyLoop) { draw_prim_inner_loop_coordtexonly(3, geom); - else draw_prim_inner_loop(3, geom, _perVertex); + } else { + if(bPerPrimNormal) + p_normal = geom->get_next_normal(ni); // set primitive normal if there is one. + + draw_prim_inner_loop(3, geom, _perVertex); + } } DWORD nVerts=nPrims*3; + nassertv((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); + if(!_bDrawPrimDoSetupVertexBuffer) { hr = scrn.pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,nPrims); @@ -3105,197 +2931,7 @@ draw_tri(GeomTri *geom, GeomContext *gc) { } _pCurFvfBufPtr = NULL; - } else { - // new geom setup that uses strided DP calls to avoid making an extra pass over the data - - D3DDRAWPRIMITIVESTRIDEDDATA dps_data; - memset(&dps_data,0,sizeof(D3DDRAWPRIMITIVESTRIDEDDATA)); - -#ifdef _DEBUG - nassertv(!geom->uses_components()); // code ignores lengths array - nassertv(geom->get_binding(G_COORD) == G_PER_VERTEX); -#endif - - D3DPRIMITIVETYPE primtype=D3DPT_TRIANGLELIST; - - DWORD fvf_flags = D3DFVF_XYZ; - dps_data.position.lpvData = (VOID*)coords; - dps_data.position.dwStride = sizeof(D3DVECTOR); - - // see fog comment in draw_prim_setup - D3DSHADEMODE NeededShadeMode = (_fog_enabled) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT; - - const DWORD dwVertsperPrim=3; - - if ((NormalBinding != G_OFF) && wants_normals()) { - - dps_data.normal.lpvData = (VOID*)norms; - dps_data.normal.dwStride = sizeof(D3DVECTOR); - -#ifdef _DEBUG - nassertv(geom->get_num_vertices_per_prim()==3); - nassertv( nPrims*dwVertsperPrim*sizeof(D3DVECTOR) <= D3DMAXNUMVERTICES*sizeof(WORD)); - if (NormalBinding==G_PER_VERTEX) - nassertv(norms.size()>=nPrims*dwVertsperPrim); -#endif - - fvf_flags |= D3DFVF_NORMAL; - NeededShadeMode = D3DSHADE_GOURAUD; - - Normalf *pExpandedNormalArray = (Normalf *)_index_buf; // BUGBUG: need to use real permanent buffers for this conversion - if (NormalBinding==G_PER_PRIM) { - // must use tmp array to duplicate-expand per-prim norms to per-vert norms - Normalf *pOutVec = pExpandedNormalArray; - Normalf *pInVec=norms; - - nassertv(norms.size()>=nPrims); - - for (uint i=0;iis_real()) - bDoColor=FALSE; // this turns off any Geom colors - else { - ColorBinding=G_OVERALL; - bDoGlobalSceneGraphColor=TRUE; - } - } - - if (bDoColor || bDoGlobalSceneGraphColor) { - D3DCOLOR *pOutColor,*pConvertedColorArray; - Colorf *pInColor=colors; - pOutColor = pConvertedColorArray = (D3DCOLOR *)_pFvfBufBasePtr; - -#ifdef _DEBUG - nassertv( nPrims*dwVertsperPrim*sizeof(D3DCOLOR) <= VERT_BUFFER_SIZE); -#endif - - fvf_flags |= D3DFVF_DIFFUSE; - - dps_data.diffuse.lpvData = (VOID*)pConvertedColorArray; - dps_data.diffuse.dwStride = sizeof(D3DCOLOR); - - if (ColorBinding==G_PER_PRIM) { - // must use tmp array to expand per-prim info to per-vert info - - // Geom nodes store floats for colors, drawprim requires ARGB dwords - // BUGBUG: eventually this hack every-frame all-colors conversion needs - // to be done only once as part of a vertex buffer - - if (NeededShadeMode!=D3DSHADE_FLAT) { - // but if lighting enabled, we need to color every vert since shading will be GOURAUD - - if(!_color_transform_required) { - for (uint i=0;iget_color(); - *pConvertedColorArray = Colorf_to_D3DCOLOR(colr); - } else { - *pConvertedColorArray = Colorf_to_D3DCOLOR(*pInColor); - } - } else { - if (bDoGlobalSceneGraphColor) { - Colorf colr = catt->get_color(); - transform_color(colr,*pConvertedColorArray); - } else { - transform_color(*pInColor,*pConvertedColorArray); - } - } - - dps_data.diffuse.dwStride = 0; - } - } - - if ((TexCoordBinding != G_OFF) && _texturing_enabled) { - -#ifdef _DEBUG - nassertv(TexCoordBinding == G_PER_VERTEX); // only sensible choice for a tri -#endif - - dps_data.textureCoords[0].lpvData = (VOID*)texcoords; - dps_data.textureCoords[0].dwStride = sizeof(TexCoordf); - fvf_flags |= (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); - } - - set_shademode(NeededShadeMode); - - DWORD nVerts = nPrims*dwVertsperPrim; - - hr = scrn.pD3DDevice->DrawPrimitiveStrided(primtype, fvf_flags, &dps_data, nVerts, NULL); - TestDrawPrimFailure(DrawPrimStrided,hr,scrn.pDD,nVerts,nPrims); - - _pCurFvfBufPtr = NULL; - } /////////////////////////// #if 0 @@ -3385,89 +3021,73 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { geom->get_colors(colors,ColorBinding,cindexes); geom->get_texcoords(texcoords,TexCoordBinding,tindexes); - GeomVertFormat GeomVrtFmt; - -#ifdef DONT_USE_DRAWPRIMSTRIDED - GeomVrtFmt=MixedFmtVerts; -#else - GeomVrtFmt=FlatVerts; - - if(!geom->uses_components()) { - GeomVrtFmt=MixedFmtVerts; // dont need efficiency here, just use simpler codepath - } else { - // first determine if we're indexed or non-indexed - if((vindexes!=NULL)&&(cindexes!=NULL)&&(tindexes!=NULL)&&(nindexes!=NULL)) { - GeomVrtFmt=IndexedVerts; - //make sure array sizes are consistent, we can only pass 1 size to DrawIPrm - // nassertv(coords.size==norms.size); nassertv(coords.size==colors.size); nassertv(coords.size==texcoords.size); need to assert only if we have this w/same binding - // indexed mode requires all used norms,colors,texcoords,coords array be the same - // length, or 0 or 1 (dwStride==0), also requires all elements to use the same index array - } else if (!((vindexes==NULL)&&(cindexes==NULL)&&(tindexes==NULL)&&(nindexes==NULL))) - GeomVrtFmt=MixedFmtVerts; - } - - if(_bDrawPrimDoSetupVertexBuffer) { - GeomVrtFmt=MixedFmtVerts; - } -#endif - - // for Indexed Prims and mixed indexed/non-indexed prims, we will use old pipeline - // cant handle indexed prims because usually have different index arrays for different components, - // and DrIdxPrmStrd only accepts 1 index array for all components - if (GeomVrtFmt!=FlatVerts) { + { + size_t vertex_size = draw_prim_setup(geom); // this is the old geom setup, it reformats every vtx into an output array passed to d3d _perVertex = 0x0; - _perPrim = _perComp = 0; + _perPrim = 0x0; + _perComp = 0x0; - switch (NormalBinding) { - case G_OFF: - break; - case G_PER_VERTEX: - _perVertex |= PER_NORMAL; - break; - case G_PER_PRIM: - _perPrim |= PER_NORMAL; - break; - case G_PER_COMPONENT: - _perComp |= PER_NORMAL; - break; - } + bool bIsTriList=(trilisttype==D3DPT_TRIANGLESTRIP); + bool bPerPrimColor=false; + bool bPerPrimNormal; + bool bUseTexCoordOnlyLoop = (((ColorBinding == G_OVERALL) || (ColorBinding == G_PER_PRIM)) && + (NormalBinding == G_OFF) && + (TexCoordBinding != G_OFF)); - switch (ColorBinding) { - case G_PER_PRIM: + if(bUseTexCoordOnlyLoop) { + if(ColorBinding == G_PER_PRIM) { _perPrim |= PER_COLOR; - break; - case G_PER_COMPONENT: - _perComp |= PER_COLOR; - break; - case G_PER_VERTEX: - _perVertex |= PER_COLOR; - break; + bPerPrimColor=true; + } + } else { + switch (NormalBinding) { + case G_PER_VERTEX: + _perVertex |= PER_NORMAL; + break; + case G_PER_PRIM: + _perPrim |= PER_NORMAL; + break; + case G_PER_COMPONENT: + _perComp |= PER_NORMAL; + break; + } + + bPerPrimNormal=((_perPrim & PER_NORMAL)!=0); + + if (TexCoordBinding == G_PER_VERTEX) + _perVertex |= PER_TEXCOORD; + + switch (ColorBinding) { + case G_PER_PRIM: + _perPrim |= PER_COLOR; + break; + case G_PER_COMPONENT: + _perComp |= PER_COLOR; + break; + case G_PER_VERTEX: + _perVertex |= PER_COLOR; + break; + } } - if (TexCoordBinding == G_PER_VERTEX) - _perVertex |= PER_TEXCOORD; - - size_t vertex_size = draw_prim_setup(geom); - // iterate through the triangle primitives - for (uint i = 0; i < nPrims; i++) { + int nVerts; + if(pLengthArr==NULL) { + // we've been called by draw_quad, which has no lengths array + nVerts=4; + } - if (_perPrim & PER_COLOR) { - GET_NEXT_COLOR(); - } - if (_perPrim & PER_NORMAL) - p_normal = geom->get_next_normal(ni); // set primitive normal if there is one. - - int nVerts; + for (uint i = 0; i < nPrims; i++) { if(pLengthArr!=NULL) { nVerts = *(pLengthArr++); - } else { - // we've been called by draw_quad, which has no lengths array - nVerts=4; + } + + if(bPerPrimColor) { // remember color might be G_OVERALL too! + GET_NEXT_COLOR(); } #ifdef _DEBUG @@ -3478,33 +3098,41 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { _pCurFvfBufPtr = _pFvfBufBasePtr; // _pCurFvfBufPtr changes, _pFvfBufBasePtr doesn't if(_perComp==0x0) { - if(_perVertex==TexCoordOnly) + if(bUseTexCoordOnlyLoop) { draw_prim_inner_loop_coordtexonly(nVerts, geom); - else draw_prim_inner_loop(nVerts, geom, _perVertex); + } else { + if (bPerPrimNormal) + p_normal = geom->get_next_normal(ni); // set primitive normal if there is one. + + draw_prim_inner_loop(nVerts, geom, _perVertex); + } } else { - if(trilisttype==D3DPT_TRIANGLESTRIP) { - // in flat shade mode, D3D strips color using the 1st vertex. - // (note: differs from OGL, which always uses last vtx for strips&fans + if(bPerPrimNormal) + p_normal = geom->get_next_normal(ni); // set primitive normal if there is one. - // Store all but last 2 verts - draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp); + if(bIsTriList) { + // in flat shade mode, D3D strips color using the 1st vertex. + // (note: differs from OGL, which always uses last vtx for strips&fans - // _perComp attribs should not be fetched for last 2 verts - draw_prim_inner_loop(2, geom, _perVertex); - } else { - // in flat shade mode, D3D fans color using the 2nd vertex. - // (note: differs from OGL, which always uses last vtx for strips&fans - // _perComp attribs should not be fetched for first & last verts, they will - // be associated with middle n-2 verts + // Store all but last 2 verts + draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp); - draw_prim_inner_loop(1, geom, _perVertex); + // _perComp attribs should not be fetched for last 2 verts + draw_prim_inner_loop(2, geom, _perVertex); + } else { + // in flat shade mode, D3D fans color using the 2nd vertex. + // (note: differs from OGL, which always uses last vtx for strips&fans + // _perComp attribs should not be fetched for first & last verts, they will + // be associated with middle n-2 verts - draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp); - - draw_prim_inner_loop(1, geom, _perVertex); - } + draw_prim_inner_loop(1, geom, _perVertex); + draw_prim_inner_loop(nVerts-2, geom, _perVertex | _perComp); + draw_prim_inner_loop(1, geom, _perVertex); + } } + assert((nVerts*vertex_size) == (_pCurFvfBufPtr-_pFvfBufBasePtr)); + if(!_bDrawPrimDoSetupVertexBuffer) { hr = scrn.pD3DDevice->DrawPrimitive(trilisttype, _curFVFflags, _pFvfBufBasePtr, nVerts, NULL); TestDrawPrimFailure(DrawPrim,hr,scrn.pDD,nVerts,nVerts-2); @@ -3514,251 +3142,8 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) { _pCurFvfBufPtr = NULL; } - } else { - - // new geom setup that uses strided DP calls to avoid making an extra pass over the data - - D3DDRAWPRIMITIVESTRIDEDDATA dps_data; - memset(&dps_data,0,sizeof(D3DDRAWPRIMITIVESTRIDEDDATA)); - -#ifdef _DEBUG - nassertv(geom->uses_components()); - nassertv(geom->get_binding(G_COORD) == G_PER_VERTEX); -#endif - - DWORD fvf_flags = D3DFVF_XYZ; - dps_data.position.lpvData = (VOID*)coords; - dps_data.position.dwStride = sizeof(D3DVECTOR); - - D3DSHADEMODE NeededShadeMode = D3DSHADE_FLAT; - - DWORD cTotalVerts=0; - - for (uint i=0;iget_num_more_vertices_than_components()==2); - nassertv(NormalBinding!=G_PER_COMPONENT); // makes no sense, unimplementable for strips since normals always shared across tris - nassertv( cTotalVerts*sizeof(D3DVECTOR) <= D3DMAXNUMVERTICES*sizeof(WORD)); - if(NormalBinding==G_PER_VERTEX) - nassertv(norms.size()>=cTotalVerts); -#endif - fvf_flags |= D3DFVF_NORMAL; - NeededShadeMode = D3DSHADE_GOURAUD; - - Normalf *pExpandedNormalArray = (Normalf *)_index_buf; // BUGBUG: need to use real permanent buffers instead of _indexbuf hack - - if(NormalBinding==G_PER_PRIM) { - // we have 1 normal per strip - // must use tmp array to duplicate-expand per-prim norms to per-vert norms - Normalf *pOutVec = pExpandedNormalArray; - Normalf *pInVec=norms; - const uint *pLengths=pLengthArr; - - nassertv(norms.size()>=nPrims); - - for (uint i=0;iis_real()) - bDoColor=FALSE; // this turns off any Geom colors - else { - ColorBinding=G_OVERALL; - bDoGlobalSceneGraphColor=TRUE; - } - } - - if (bDoColor || bDoGlobalSceneGraphColor) { - D3DCOLOR *pOutColor,*pConvertedColorArray; - Colorf *pInColor=colors; - pOutColor = pConvertedColorArray = (D3DCOLOR *)_pFvfBufBasePtr; - -#ifdef _DEBUG - nassertv( cTotalVerts*sizeof(D3DCOLOR) <= VERT_BUFFER_SIZE); -#endif - - fvf_flags |= D3DFVF_DIFFUSE; - - dps_data.diffuse.lpvData = (VOID*)pConvertedColorArray; - dps_data.diffuse.dwStride = sizeof(D3DCOLOR); - - if (ColorBinding==G_PER_VERTEX) { - NeededShadeMode = D3DSHADE_GOURAUD; - - if(!_color_transform_required) { - for (uint i=0;i= cTotalVerts-nPrims*cNumMoreVertsthanTris); - - #define MULTITRI_COLORCOPY_LOOP \ - DWORD cCurStripColorCnt=pLengthArr[j]-cNumMoreVertsthanTris; \ - for (uint i=0;iget_color(); - *pConvertedColorArray = Colorf_to_D3DCOLOR(colr); - } else { - *pConvertedColorArray = Colorf_to_D3DCOLOR(*pInColor); - } - } else { - if (bDoGlobalSceneGraphColor) { - Colorf colr = catt->get_color(); - transform_color(colr,*pConvertedColorArray); - } else { - transform_color(*pInColor,*pConvertedColorArray); - } - } - - dps_data.diffuse.dwStride = 0; - } - } - - if ((TexCoordBinding != G_OFF) && _texturing_enabled) { - -#ifdef _DEBUG - nassertv(TexCoordBinding == G_PER_VERTEX); // only sensible choice for a tri -#endif - - dps_data.textureCoords[0].lpvData = (VOID*)texcoords; - dps_data.textureCoords[0].dwStride = sizeof(TexCoordf); - fvf_flags |= (D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0)); - } - - set_shademode(NeededShadeMode); - - for (uint j=0;jDrawPrimitiveStrided(trilisttype, fvf_flags, &dps_data, cCurNumStripVerts, NULL); - TestDrawPrimFailure(DrawPrimStrided,hr,scrn.pDD,cCurNumStripVerts,cCurNumStripVerts-2); - - dps_data.position.lpvData = (VOID*)(((char*) dps_data.position.lpvData) + cCurNumStripVerts*dps_data.position.dwStride); - dps_data.diffuse.lpvData = (VOID*)(((char*) dps_data.diffuse.lpvData) + cCurNumStripVerts*dps_data.diffuse.dwStride); - dps_data.normal.lpvData = (VOID*)(((char*) dps_data.normal.lpvData) + cCurNumStripVerts*dps_data.normal.dwStride); - dps_data.textureCoords[0].lpvData = (VOID*)(((char*) dps_data.textureCoords[0].lpvData) + cCurNumStripVerts*dps_data.textureCoords[0].dwStride); - } - - nassertv(_pCurFvfBufPtr == NULL); } + } //----------------------------------------------------------------------------- @@ -4086,11 +3471,7 @@ prepare_texture(Texture *tex) { apply_texture_immediate(tex); #else -#ifdef USE_TEXFMTVEC - if (dtc->CreateTexture(scrn.pD3DDevice,scrn.TexPixFmts,&scrn.D3DDevDesc) == NULL) { -#else - if (dtc->CreateTexture(scrn.pD3DDevice,_cNumTexPixFmts,_pTexPixFmts,&scrn.D3DDevDesc) == NULL) { -#endif + if (dtc->CreateTexture(scrn) == NULL) { delete dtc; return NULL; } @@ -4146,11 +3527,8 @@ apply_texture(TextureContext *tc) { } dtc->DeleteTexture(); -#ifdef USE_TEXFMTVEC - if (dtc->CreateTexture(scrn.pD3DDevice,scrn.TexPixFmts,&scrn.D3DDevDesc) == NULL) { -#else - if (dtc->CreateTexture(scrn.pD3DDevice,_cNumTexPixFmts,_pTexPixFmts,&scrn.D3DDevDesc) == NULL) { -#endif + if (dtc->CreateTexture(scrn) == NULL) { + // Oops, we can't re-create the texture for some reason. dxgsg_cat.error() << "Unable to re-create texture " << *dtc->_texture << endl; @@ -4508,8 +3886,6 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb, void DXGraphicsStateGuardian:: copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { - extern HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf); - nassertv(pb != NULL && dr != NULL); int xo, yo, w, h; @@ -4521,17 +3897,25 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) { nassertv(w==pb->get_xsize()); nassertv(h==pb->get_ysize()); -/* - set_pack_alignment(1); - glReadPixels( pb->get_xorg() + xo, pb->get_yorg() + yo, - pb->get_xsize(), pb->get_ysize(), - get_external_image_format(pb->get_format()), - get_image_type(pb->get_image_type()), - pb->_image.p() ); -*/ + IDirect3DSurface8 *pD3DSurf; + HRESULT hr; + // just handling front and backbuf for now, not textures yet + if(_cur_read_pixel_buffer & RenderBuffer::T_back) { + hr=GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf); + } else { + hr=GetFrontBuffer(&pD3DSurf); + } - (void) ConvertDDSurftoPixBuf(pb,((_cur_read_pixel_buffer & RenderBuffer::T_back) ? scrn.pddsBack : scrn.pddsPrimary)); + if(FAILED(hr)) { + dxgsg_cat.error() << "copy_pixel_buffer: " << ((_cur_read_pixel_buffer & RenderBuffer::T_back) ? "GetBackBuffer" : "GetFrontBuffer") + << " failed, hr = " << D3DERRORSTRING(hr); + exit(1); + } + + (void) ConvertD3DSurftoPixBuf(pD3DSurf,pb); + + SAFE_RELEASE(pD3DSurf); nassertv(!pb->_image.empty()); } @@ -4710,10 +4094,10 @@ apply_fog(Fog *fog) { // should probably avoid doing redundant SetRenderStates, but whatever - scrn.pD3DDevice->SetRenderState((D3DRENDERSTATETYPE)_doFogType, d3dfogmode); + scrn.pD3DDevice->SetRenderState((D3DRSTYPE)_doFogType, d3dfogmode); const Colorf &fog_colr = fog->get_color(); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, + scrn.pD3DDevice->SetRenderState(D3DRS_FOGCOLOR, MY_D3DRGBA(fog_colr[0], fog_colr[1], fog_colr[2], 0.0f)); // Alpha bits are not used // do we need to adjust fog start/end values based on D3DPRASTERCAPS_WFOG/D3DPRASTERCAPS_ZFOG ? @@ -4731,9 +4115,9 @@ apply_fog(Fog *fog) { _current_camera, _coordinate_system); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGSTART, + scrn.pD3DDevice->SetRenderState( D3DRS_FOGSTART, *((LPDWORD) (&fog_start)) ); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGEND, + scrn.pD3DDevice->SetRenderState( D3DRS_FOGEND, *((LPDWORD) (&fog_end)) ); } break; @@ -4742,7 +4126,7 @@ apply_fog(Fog *fog) { { // Exponential fog is always camera-relative. float fog_density = fog->get_exp_density(); - scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_FOGDENSITY, + scrn.pD3DDevice->SetRenderState( D3DRS_FOGDENSITY, *((LPDWORD) (&fog_density)) ); } break; @@ -4812,7 +4196,7 @@ void DXGraphicsStateGuardian::apply_light( DirectionalLight* light ) { HRESULT res = scrn.pD3DDevice->SetLight(_cur_light_id, &alight); // scrn.pD3DDevice->LightEnable( _cur_light_id, TRUE ); -// scrn.pD3DDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE ); +// scrn.pD3DDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); } //////////////////////////////////////////////////////////////////// @@ -5171,11 +4555,11 @@ issue_render_mode(const RenderModeTransition *attrib) { switch (mode) { case RenderModeProperty::M_filled: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID); + scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); break; case RenderModeProperty::M_wireframe: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME); + scrn.pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); break; default: @@ -5490,11 +4874,11 @@ issue_depth_test(const DepthTestTransition *attrib) { if (mode == DepthTestProperty::M_none) { _depth_test_enabled = false; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + scrn.pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); } else { _depth_test_enabled = true; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, get_depth_func_type(mode)); + scrn.pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + scrn.pD3DDevice->SetRenderState(D3DRS_ZFUNC, get_depth_func_type(mode)); } } @@ -5528,13 +4912,13 @@ issue_stencil(const StencilTransition *attrib) { } #endif // TODO: need to cache all these - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILFUNC, get_stencil_func_type(mode)); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILPASS, pass_op); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILFAIL, fail_op); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILZFAIL, zfail_op); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILREF, attrib->get_reference_value()); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILMASK, attrib->get_func_mask()); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_STENCILWRITEMASK, attrib->get_write_mask()); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILFUNC, get_stencil_func_type(mode)); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILPASS, pass_op); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILFAIL, fail_op); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILZFAIL, zfail_op); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILREF, attrib->get_reference_value()); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILMASK, attrib->get_func_mask()); + scrn.pD3DDevice->SetRenderState(D3DRS_STENCILWRITEMASK, attrib->get_write_mask()); } } @@ -5556,17 +4940,17 @@ issue_cull_face(const CullFaceTransition *attrib) { switch (mode) { case CullFaceProperty::M_cull_none: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); break; case CullFaceProperty::M_cull_clockwise: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); break; case CullFaceProperty::M_cull_counter_clockwise: - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); break; case CullFaceProperty::M_cull_all: dxgsg_cat.warning() << "M_cull_all is invalid for DX GSG renderer, using CULL_CCW \n"; - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW); + scrn.pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); break; default: dxgsg_cat.error() @@ -5641,7 +5025,7 @@ issue_clip_plane(const ClipPlaneTransition *attrib) { _cur_clip_plane_enabled[_cur_clip_plane_id] = true; const Planef clip_plane = plane_node->get_plane(); - D3DVALUE equation[4]; + float equation[4]; equation[0] = clip_plane._a; equation[1] = clip_plane._b; equation[2] = clip_plane._c; @@ -5798,7 +5182,7 @@ begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib) { // Just draw the base geometry normally. base_geom->draw(this); - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, POLYGON_OFFSET_MULTIPLIER * _decal_level); // _decal_level better not be higher than 8! + scrn.pD3DDevice->SetRenderState(D3DRS_ZBIAS, POLYGON_OFFSET_MULTIPLIER * _decal_level); // _decal_level better not be higher than 8! } else #endif @@ -5854,7 +5238,7 @@ end_decal(GeomNode *base_geom) { #ifndef DISABLE_POLYGON_OFFSET_DECALING if (dx_decal_type == GDT_offset) { // Restore the Zbias offset. - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, POLYGON_OFFSET_MULTIPLIER * _decal_level); // _decal_level better not be higher than 8! + scrn.pD3DDevice->SetRenderState(D3DRS_ZBIAS, POLYGON_OFFSET_MULTIPLIER * _decal_level); // _decal_level better not be higher than 8! } else #endif { // for GDT_mask @@ -5881,7 +5265,7 @@ end_decal(GeomNode *base_geom) { #if(DIRECT3D_VERSION < 0x700) else { // dx7 doesn't support planemask rstate // note: not saving current planemask val, assumes this is always all 1's. should be ok - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_PLANEMASK,0x0); // note PLANEMASK is supposedly obsolete for DX7 + scrn.pD3DDevice->SetRenderState(D3DRS_PLANEMASK,0x0); // note PLANEMASK is supposedly obsolete for DX7 } #endif // Note: For DX8, use D3DRS_COLORWRITEENABLE (check D3DPMISCCAPS_COLORWRITEENABLE first) @@ -5905,7 +5289,7 @@ end_decal(GeomNode *base_geom) { } #if(DIRECT3D_VERSION < 0x700) else { - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_PLANEMASK,0xFFFFFFFF); // this is unlikely to work due to poor driver support + scrn.pD3DDevice->SetRenderState(D3DRS_PLANEMASK,0xFFFFFFFF); // this is unlikely to work due to poor driver support } #endif enable_texturing(was_textured); @@ -6319,7 +5703,7 @@ dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled) { if(dxgsg_cat.is_spam()) dxgsg_cat.spam() << "dx_cleanup - Restoring original desktop DisplayMode\n"; if(FAILED(hr)) { - dxgsg_cat.error() << "dx_cleanup - RestoreDisplayMode failed, hr = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "dx_cleanup - RestoreDisplayMode failed, hr = " << D3DERRORSTRING(hr); } } @@ -6385,7 +5769,7 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { HRESULT hr; if (FAILED(hr = scrn.pDD->CreateSurface( &ddsd, &scrn.pddsPrimary, NULL ))) { - dxgsg_cat.fatal() << "resize() - CreateSurface failed for primary : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.fatal() << "resize() - CreateSurface failed for primary : result = " << D3DERRORSTRING(hr); exit(1); } @@ -6396,7 +5780,7 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { if (FAILED(hr = scrn.pDD->CreateClipper( 0, &Clipper, NULL ))) { dxgsg_cat.fatal() - << "CreateClipper after resize failed : result = " << ConvD3DErrorToString(hr) << endl; + << "CreateClipper after resize failed : result = " << D3DERRORSTRING(hr); exit(1); } // Associate the clipper with our window. Note that, afterwards, the @@ -6415,7 +5799,7 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { PRINTVIDMEM(scrn.pDD,&ddsd_back.ddsCaps,"resize backbuffer surf"); if (FAILED(hr = scrn.pDD->CreateSurface( &ddsd_back, &scrn.pddsBack, NULL ))) { - dxgsg_cat.fatal() << "resize() - CreateSurface failed for backbuffer : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.fatal() << "resize() - CreateSurface failed for backbuffer : result = " << D3DERRORSTRING(hr); exit(1); } @@ -6423,18 +5807,18 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { // Recreate and attach a z-buffer. if (FAILED(hr = scrn.pDD->CreateSurface( &ddsd_zbuf, &scrn.pddsZBuf, NULL ))) { - dxgsg_cat.fatal() << "resize() - CreateSurface failed for Z buffer: result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.fatal() << "resize() - CreateSurface failed for Z buffer: result = " << D3DERRORSTRING(hr); exit(1); } // Attach the z-buffer to the back buffer. if ((hr = scrn.pddsBack->AddAttachedSurface( scrn.pddsZBuf ) ) != DD_OK) { - dxgsg_cat.fatal() << "resize() - AddAttachedSurface failed : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.fatal() << "resize() - AddAttachedSurface failed : result = " << D3DERRORSTRING(hr); exit(1); } if ((hr = scrn.pD3DDevice->SetRenderTarget(scrn.pddsBack,0x0) ) != DD_OK) { - dxgsg_cat.fatal() << "resize() - SetRenderTarget failed : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.fatal() << "resize() - SetRenderTarget failed : result = " << D3DERRORSTRING(hr); exit(1); } @@ -6443,7 +5827,7 @@ dx_setup_after_resize(RECT viewrect, HWND mwindow) { hr = scrn.pD3DDevice->SetViewport( &vp ); if (hr != DD_OK) { dxgsg_cat.fatal() - << "SetViewport failed : result = " << ConvD3DErrorToString(hr) << endl; + << "SetViewport failed : result = " << D3DERRORSTRING(hr); exit(1); } @@ -6476,12 +5860,7 @@ bool recreate_tex_callback(TextureContext *tc,void *void_dxgsg_ptr) { // Re-fill the contents of textures and vertex buffers // which just got restored now. - LPDIRECTDRAWSURFACE7 ddtex = -#ifdef USE_TEXFMTVEC - dtc->CreateTexture(dxgsg->scrn.pD3DDevice,scrn.TexPixFmts,&dxgsg->scrn.D3DDevDesc); -#else - dtc->CreateTexture(dxgsg->scrn.pD3DDevice,dxgsg->_cNumTexPixFmts,dxgsg->_pTexPixFmts,&dxgsg->scrn.D3DDevDesc); -#endif + LPDIRECTDRAWSURFACE7 ddtex = dtc->CreateTexture(dxgsg->scrn); return ddtex!=NULL; } @@ -6524,7 +5903,7 @@ HRESULT DXGraphicsStateGuardian::RestoreAllVideoSurfaces(void) { // note: could go through and just restore surfs that return IsLost() true // apparently that isnt as reliable w/some drivers tho if (FAILED(hr = scrn.pDD->RestoreAllSurfaces() )) { - dxgsg_cat.fatal() << "RestoreAllSurfs failed : result = " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.fatal() << "RestoreAllSurfs failed : result = " << D3DERRORSTRING(hr); exit(1); } @@ -6589,7 +5968,7 @@ void DXGraphicsStateGuardian::show_full_screen_frame(void) { if((hr == DDERR_SURFACELOST) || (hr == DDERR_SURFACEBUSY)) { CheckCooperativeLevel(); } else { - dxgsg_cat.error() << "show_frame() - Flip failed w/unexpected error code: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "show_frame() - Flip failed w/unexpected error code: " << D3DERRORSTRING(hr); exit(1); } } @@ -6631,7 +6010,7 @@ void DXGraphicsStateGuardian::show_windowed_frame(void) { if (dx_sync_video) { HRESULT hr = scrn.pDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL); if(hr != DD_OK) { - dxgsg_cat.error() << "WaitForVerticalBlank() failed : " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "WaitForVerticalBlank() failed : " << D3DERRORSTRING(hr); exit(1); } } @@ -6640,7 +6019,7 @@ void DXGraphicsStateGuardian::show_windowed_frame(void) { if((hr == DDERR_SURFACELOST) || (hr == DDERR_SURFACEBUSY)) { CheckCooperativeLevel(); } else { - dxgsg_cat.error() << "show_frame() - Blt failed : " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "show_frame() - Blt failed : " << D3DERRORSTRING(hr); exit(1); } } @@ -6686,10 +6065,10 @@ bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) { // This means that the desktop mode has changed // need to destroy all of dx stuff and recreate everything // back again, which is a big hit - dxgsg_cat.error() << "detected display mode change in TestCoopLevel, must recreate all DDraw surfaces, D3D devices, this is not handled yet. hr == " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "detected display mode change in TestCoopLevel, must recreate all DDraw surfaces, D3D devices, this is not handled yet. hr == " << D3DERRORSTRING(hr); exit(1); } else if(FAILED(hr)) { - dxgsg_cat.error() << "unexpected return code from TestCoopLevel: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "unexpected return code from TestCoopLevel: " << D3DERRORSTRING(hr); exit(1); } } else { @@ -6715,11 +6094,11 @@ bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) { // This means that the desktop mode has changed // need to destroy all of dx stuff and recreate everything // back again, which is a big hit - dxgsg_cat.error() << "detected desktop display mode change in TestCoopLevel, must recreate all DDraw surfaces & D3D devices, this is not handled yet. " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "detected desktop display mode change in TestCoopLevel, must recreate all DDraw surfaces & D3D devices, this is not handled yet. " << D3DERRORSTRING(hr); _win->close_window(); exit(1); } else if((hr!=DDERR_NOEXCLUSIVEMODE) && (hr!=DDERR_EXCLUSIVEMODEALREADYSET)) { - dxgsg_cat.error() << "unexpected return code from TestCoopLevel: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "unexpected return code from TestCoopLevel: " << D3DERRORSTRING(hr); exit(1); } } @@ -7226,7 +6605,7 @@ prepare_geom_node(GeomNode *node) { hr=pD3D->CreateVertexBuffer(&VBdesc,&pD3DVertexBuffer,0x0); if(FAILED(hr)) { - dxgsg_cat.error() << "error creating vertex buffer: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "error creating vertex buffer: " << D3DERRORSTRING(hr); delete dx_gnc; exit(1); } @@ -7243,7 +6622,7 @@ prepare_geom_node(GeomNode *node) { hr=pD3D->CreateVertexBuffer(&VBdesc,&pD3DVertexBuffer,0x0); if(FAILED(hr)) { - dxgsg_cat.error() << "error creating xformed vertex buffer: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "error creating xformed vertex buffer: " << D3DERRORSTRING(hr); delete dx_gnc; exit(1); } @@ -7262,7 +6641,7 @@ prepare_geom_node(GeomNode *node) { hr=dx_gnc->_pVB->Lock(dwVBFlags,&pVertData,NULL); if(FAILED(hr)) { - dxgsg_cat.error() << "error locking vertex buffer: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "error locking vertex buffer: " << D3DERRORSTRING(hr); delete dx_gnc; exit(1); } @@ -7295,7 +6674,7 @@ prepare_geom_node(GeomNode *node) { hr=dx_gnc->_pVB->Unlock(); if(FAILED(hr)) { - dxgsg_cat.error() << "error unlocking vertex buffer: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "error unlocking vertex buffer: " << D3DERRORSTRING(hr); delete dx_gnc; exit(1); } @@ -7304,7 +6683,7 @@ prepare_geom_node(GeomNode *node) { hr=dx_gnc->_pVB->Optimize(scrn.pD3DDevice,0x0); if(FAILED(hr)) { - dxgsg_cat.error() << "error optimizing vertex buffer: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "error optimizing vertex buffer: " << D3DERRORSTRING(hr); delete dx_gnc; exit(1); } @@ -7371,7 +6750,7 @@ draw_geom_node(GeomNode *node, GeomNodeContext *gnc) { VBdesc.dwSize=sizeof(VBdesc); hr=dx_gnc->_pVB->GetVertexBufferDesc(&VBdesc); // would be useful to keep fvf in vertbuf struct to avoid having to do this if(FAILED(hr)) { - dxgsg_cat.error() << "error in getvbdesc: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "error in getvbdesc: " << D3DERRORSTRING(hr); exit(1); } @@ -7381,13 +6760,13 @@ draw_geom_node(GeomNode *node, GeomNodeContext *gnc) { hr=dx_gnc->_pXformed_VB->ProcessVertices(PVOp,0,dx_gnc->_num_verts,dx_gnc->_pVB,0,scrn.pD3DDevice,0x0); if(FAILED(hr)) { - dxgsg_cat.error() << "error in ProcessVertices: " << ConvD3DErrorToString(hr) << endl; + dxgsg_cat.error() << "error in ProcessVertices: " << D3DERRORSTRING(hr); exit(1); } // disable clipping, since VB is already xformed and clipped if(_clipping_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, false); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, false); } // assume we need gouraud for now. we can make this more complex to select flat conditionally later @@ -7415,7 +6794,7 @@ draw_geom_node(GeomNode *node, GeomNodeContext *gnc) { } if((!scrn.bIsTNLDevice) && _clipping_enabled) - scrn.pD3DDevice->SetRenderState(D3DRENDERSTATE_CLIPPING, true); + scrn.pD3DDevice->SetRenderState(D3DRS_CLIPPING, true); // Also draw all the dynamic Geoms. for (i = 0; i < dx_gnc->_other_geoms.size(); i++) { @@ -7450,3 +6829,154 @@ release_geom_node(GeomNodeContext *gnc) { delete dx_gnc; // should release vertex buffer } } + +HRESULT CreateDX8Cursor(LPDIRECT3DDEVICE8 pd3dDevice, HCURSOR hCursor,BOOL bAddWatermark) { +// copied directly from dxsdk SetDeviceCursor + HRESULT hr = E_FAIL; + ICONINFO iconinfo; + LPDIRECT3DSURFACE8 pCursorBitmap = NULL; + HDC hdcColor = NULL; + HDC hdcMask = NULL; + HDC hdcScreen = NULL; + BITMAP bm; + DWORD dwWidth,dwHeightSrc,dwHeightDest; + COLORREF crColor,crMask; + UINT x,y; + BITMAPINFO bmi; + COLORREF* pcrArrayColor = NULL; + COLORREF* pcrArrayMask = NULL; + DWORD* pBitmap; + HGDIOBJ hgdiobjOld; + BOOL bBWCursor; + + ZeroMemory( &iconinfo, sizeof(iconinfo) ); + if( !GetIconInfo( hCursor, &iconinfo ) ) + goto End; + + if (0 == GetObject((HGDIOBJ)iconinfo.hbmMask, sizeof(BITMAP), (LPVOID)&bm)) + goto End; + dwWidth = bm.bmWidth; + dwHeightSrc = bm.bmHeight; + + if( iconinfo.hbmColor == NULL ) { + bBWCursor = TRUE; + dwHeightDest = dwHeightSrc / 2; + } else { + bBWCursor = FALSE; + dwHeightDest = dwHeightSrc; + } + + // Create a surface for the cursor + if( FAILED( hr = pd3dDevice->CreateImageSurface( dwWidth, dwHeightDest, + D3DFMT_A8R8G8B8, &pCursorBitmap ) ) ) { + goto End; + } + + pcrArrayMask = new DWORD[dwWidth * dwHeightSrc]; + + ZeroMemory(&bmi, sizeof(bmi)); + bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); + bmi.bmiHeader.biWidth = dwWidth; + bmi.bmiHeader.biHeight = dwHeightSrc; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + + hdcScreen = GetDC( NULL ); + hdcMask = CreateCompatibleDC( hdcScreen ); + if( hdcMask == NULL ) + { + hr = E_FAIL; + goto End; + } + hgdiobjOld = SelectObject(hdcMask, iconinfo.hbmMask); + GetDIBits(hdcMask, iconinfo.hbmMask, 0, dwHeightSrc, + pcrArrayMask, &bmi, DIB_RGB_COLORS); + SelectObject(hdcMask, hgdiobjOld); + + if (!bBWCursor) + { + pcrArrayColor = new DWORD[dwWidth * dwHeightDest]; + hdcColor = CreateCompatibleDC( GetDC( NULL ) ); + if( hdcColor == NULL ) + { + hr = E_FAIL; + goto End; + } + SelectObject(hdcColor, iconinfo.hbmColor); + GetDIBits(hdcColor, iconinfo.hbmColor, 0, dwHeightDest, + pcrArrayColor, &bmi, DIB_RGB_COLORS); + } + + // Transfer cursor image into the surface + D3DLOCKED_RECT lr; + pCursorBitmap->LockRect( &lr, NULL, 0 ); + pBitmap = (DWORD*)lr.pBits; + for( y = 0; y < dwHeightDest; y++ ) + { + for( x = 0; x < dwWidth; x++ ) + { + if (bBWCursor) + { + crColor = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x]; + crMask = pcrArrayMask[dwWidth*(dwHeightSrc-1-y) + x]; + } + else + { + crColor = pcrArrayColor[dwWidth*(dwHeightDest-1-y) + x]; + crMask = pcrArrayMask[dwWidth*(dwHeightDest-1-y) + x]; + } + if (crMask == 0) + pBitmap[dwWidth*y + x] = 0xff000000 | crColor; + else + pBitmap[dwWidth*y + x] = 0x00000000; + + // It may be helpful to make the D3D cursor look slightly + // different from the Windows cursor so you can distinguish + // between the two when developing/testing code. When + // bAddWatermark is TRUE, the following code adds some + // small grey "D3D" characters to the upper-left corner of + // the D3D cursor image. + if( bAddWatermark && x < 12 && y < 5 ) + { + // 11.. 11.. 11.. .... CCC0 + // 1.1. ..1. 1.1. .... A2A0 + // 1.1. .1.. 1.1. .... A4A0 + // 1.1. ..1. 1.1. .... A2A0 + // 11.. 11.. 11.. .... CCC0 + + const WORD wMask[5] = { 0xccc0, 0xa2a0, 0xa4a0, 0xa2a0, 0xccc0 }; + if( wMask[y] & (1 << (15 - x)) ) + { + pBitmap[dwWidth*y + x] |= 0xff808080; + } + } + } + } + pCursorBitmap->UnlockRect(); + + // Set the device cursor + if( FAILED( hr = pd3dDevice->SetCursorProperties( iconinfo.xHotspot, + iconinfo.yHotspot, pCursorBitmap ) ) ) + { + goto End; + } + + hr = S_OK; + +End: + if( iconinfo.hbmMask != NULL ) + DeleteObject( iconinfo.hbmMask ); + if( iconinfo.hbmColor != NULL ) + DeleteObject( iconinfo.hbmColor ); + if( hdcScreen != NULL ) + ReleaseDC( NULL, hdcScreen ); + if( hdcColor != NULL ) + DeleteDC( hdcColor ); + if( hdcMask != NULL ) + DeleteDC( hdcMask ); + SAFE_DELETE_ARRAY( pcrArrayColor ); + SAFE_DELETE_ARRAY( pcrArrayMask ); + SAFE_RELEASE( pCursorBitmap ); + return hr; +} diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index 6ee3e65b93..10fbfe8ac8 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -38,40 +38,49 @@ #include #include -#include "dxGeomNodeContext.h" -#include "dxTextureContext.h" +#include "dxGeomNodeContext8.h" +#include "dxTextureContext8.h" #include -extern char * ConvD3DErrorToString(const HRESULT &error); // defined in wdxGraphicsPipe.cxx +#define FLG(NN) (1< ScreenDataVector; +#define IS_16BPP_FORMAT(FMT) (((FMT)>=D3DFMT_R5G6B5)&&((FMT)<=D3DFMT_A1R5G5B5)) +#define IS_STENCIL_FORMAT(FMT) (((FMT)==D3DFMT_D24S8) || ((FMT)==D3DFMT_D15S1) || ((FMT)==D3DFMT_D24X4S4)) class PlaneNode; class Light; @@ -94,10 +103,14 @@ INLINE ostream &operator << (ostream &out, GLenum v) { ZeroMemory(&var, sizeof(type)); \ var.dwSize = sizeof(type); -// #define DEBUG_RELEASES +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } // this is bDoDownToZero argument to RELEASE() #define RELEASE_DOWN_TO_ZERO true +#define RELEASE_ONCE false + +// #define DEBUG_RELEASES #ifdef DEBUG_RELEASES #define RELEASE(OBJECT,MODULE,DBGSTR,bDoDownToZero) \ @@ -263,16 +276,9 @@ public: public: // recreate_tex_callback needs these to be public - LPDIRECT3DDEVICE7 _pCurD3DDevice; //this needs to be set every device iteration - LPDIRECTDRAW7 _pDD; +// LPDIRECT3DDEVICE7 _pCurD3DDevice; //this needs to be set every device iteration DXScreenData scrn; -#ifndef USE_TEXFMTVEC - LPDDPIXELFORMAT _pTexPixFmts; - int _cNumTexPixFmts; -#endif -// D3DDEVICEDESC7 _D3DDevDesc; - protected: void free_pointers(); // free local internal buffers void free_dxgsg_objects(void); // free the DirectX objects we create @@ -290,24 +296,8 @@ protected: bool _dx_ready; HRESULT _last_testcooplevel_result; - -/* - moved to per display data - bool _bIsTNLDevice; - LPDIRECTDRAWSURFACE7 _back; - LPDIRECTDRAWSURFACE7 _zbuf; - LPDIRECTDRAWSURFACE7 _pri; - - LPDIRECT3D7 _d3d; - LPDIRECTDRAW7 _pDD; - RECT _view_rect; - RECT clip_rect; -*/ - LPDIRECT3D7 _pCurD3D7; - LPDIRECTDRAW7 _pCurDD; bool _bShowFPSMeter; - - HDC _front_hdc; +// HDC _front_hdc; DXTextureContext *_pCurTexContext; bool _bTransformIssued; // decaling needs to tell when a transform has been issued @@ -331,10 +321,10 @@ protected: */ INLINE void enable_color_material(bool val); - INLINE void enable_clip_plane(int clip_plane, bool val); + INLINE void enable_clip_plane(int clip_plane_id, bool val); INLINE void enable_fog(bool val); INLINE void enable_zwritemask(bool val); - INLINE void set_shademode(D3DSHADEMODE val); + INLINE void enable_gouraud_shading(bool val); INLINE D3DTEXTUREADDRESS get_texture_wrap_mode(Texture::WrapMode wm) const; INLINE D3DCMPFUNC get_depth_func_type(DepthTestProperty::Mode m) const; @@ -375,7 +365,8 @@ protected: Colorf _issued_color; // WBD ADDED D3DCOLOR _issued_color_D3DCOLOR; // WBD ADDED D3DCOLOR _d3dcolor_clear_value; - D3DSHADEMODE _CurShadeMode; +// D3DSHADEMODE _CurShadeMode; + bool _bGouraudShadingOn; bool _bDrawPrimDoSetupVertexBuffer; // if true, draw methods just copy vertex data into pCurrentGeomContext DXGeomNodeContext *_pCurrentGeomContext; // used in vertex buffer setup @@ -408,8 +399,8 @@ protected: float _material_emission; typedef enum {None, - PerVertexFog=D3DRENDERSTATE_FOGVERTEXMODE, - PerPixelFog=D3DRENDERSTATE_FOGTABLEMODE + PerVertexFog=D3DRS_FOGVERTEXMODE, + PerPixelFog=D3DRS_FOGTABLEMODE } DxgsgFogType; DxgsgFogType _doFogType; bool _fog_enabled; @@ -523,15 +514,13 @@ public: RECT viewrect); */ void dx_init(void); - friend HRESULT CALLBACK EnumTexFmtsCallback( LPDDPIXELFORMAT pddpf, VOID* param ); - private: static TypeHandle _type_handle; }; #define ISPOW2(X) (((X) & ((X)-1))==0) -#include "dxGraphicsStateGuardian.I" +#include "dxGraphicsStateGuardian8.I" #endif diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index 6e845c148b..21ecc6a61a 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -1,5 +1,5 @@ -// Filename: dxTextureContext.cxx -// Created by: drose (07Oct99) +// Filename: dxTextureContext8.cxx +// Created by: georges (02Feb02) // //////////////////////////////////////////////////////////////////// // @@ -18,29 +18,49 @@ #include #include -#include "dxTextureContext.h" -#include "config_dxgsg.h" -#include "dxGraphicsStateGuardian.h" -#include "pnmImage.h" +#include "dxTextureContext8.h" +#include "config_dxgsg8.h" +#include "dxGraphicsStateGuardian8.h" +//#include "pnmImage.h" +#include "d3dx8tex.h" //#define FORCE_16bpp_1555 +static const DWORD g_LowByteMask = 0x000000FF; +#define PANDA_BGRA_ORDER + +#ifdef PANDA_BGRA_ORDER +// assume Panda uses byte-order BGRA/LA to store pixels, which when read into little-endian word is ARGB/AL +// these macros GET from PixelBuffer, (wont work from DDSurface) +#define GET_RED_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 16) & g_LowByteMask)) +#define GET_BLUE_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD) & g_LowByteMask)) +#else +// otherwise Panda uses int ABGR (big-endian RGBA order), (byte-order RGBA or RGB) +#define GET_RED_BYTE(PIXEL_DWORD) ((BYTE)(PIXEL_DWORD & g_LowByteMask)) +#define GET_BLUE_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 16) & g_LowByteMask)) +#endif + +#define GET_GREEN_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 8) & g_LowByteMask)) +#define GET_ALPHA_BYTE(PIXEL_DWORD) ((BYTE)(((DWORD)PIXEL_DWORD) >> 24)) // unsigned >> shifts in 0's, so dont need to mask off upper bits + +#ifdef DO_CUSTOM_CONVERSIONS typedef enum { - None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_0555, + None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_X555, Conv32to16_1555,Conv32to16_0565,Conv32to16_4444,Conv24to32,Conv24to24, - Conv24to16_0555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444, - ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_0555,ConvLum8to16_0565, - ConvAlpha8to16_4444,ConvAlpha8to32,ConvAlpha8to8 + Conv24to16_X555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444, + ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_X555,ConvLum8to16_0565,ConvLum8to16_A8L8, + ConvAlpha8to16_4444,ConvAlpha8to32,ConvAlpha8to8,ConvAlpha8to16_A8L8 } ConversionType; #ifndef NDEBUG -char *ConvNameStrs[] = {"None","Conv32to32","Conv32to32_NoAlpha","Conv32to24","Conv32to16_0555", - "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24", - "Conv24to16_0555","Conv24to16_0565","ConvLum16to16_1555","ConvLum16to16_4444", - "ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32", - "ConvLum8to16_0555","ConvLum8to16_0565","ConvAlpha8to16_4444","ConvAlpha8to32","ConvAlpha8to8" +char *ConvNameStrs[] = {"None","Conv32to32","Conv32to32_NoAlpha","Conv32to24","Conv32to16_X555", + "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24","Conv24to16_X555","Conv24to16_0565", + "ConvLum16to16_1555","ConvLum16to16_4444","ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32", + "ConvLum8to16_X555","ConvLum8to16_0565","ConvLum8to16_A8L8", + "ConvAlpha8to16_4444","ConvAlpha8to32","ConvAlpha8to8","ConvAlpha8to16_A8L8" }; #endif +#endif char *PandaFilterNameStrs[] = {"FT_nearest","FT_linear","FT_nearest_mipmap_nearest","FT_linear_mipmap_nearest", "FT_nearest_mipmap_linear", "FT_linear_mipmap_linear" @@ -145,12 +165,12 @@ get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { switch(format) { case PixelBuffer::F_alpha: *alphbits = 8; - return 8; case PixelBuffer::F_color_index: case PixelBuffer::F_red: case PixelBuffer::F_green: case PixelBuffer::F_blue: case PixelBuffer::F_rgb332: + return 8; case PixelBuffer::F_luminance_alphamask: *alphbits = 1; return 16; @@ -173,10 +193,10 @@ get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { return 24; case PixelBuffer::F_rgba8: case PixelBuffer::F_rgba: - *alphbits = 8; - return 32; case PixelBuffer::F_rgbm: - *alphbits = 1; + if(format==PixelBuffer::F_rgbm) // does this make any sense? + *alphbits = 1; + else *alphbits = 8; return 32; case PixelBuffer::F_rgb12: return 36; @@ -187,6 +207,9 @@ get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { return 8; } +/* // This is superseded by D3DXLoadSurfaceFromMemory(), but keep this stuff around in case its needed + +#ifdef DO_CUSTOM_CONVERSIONS HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWSURFACE7 pDDSurf) { HRESULT hr; DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); @@ -200,6 +223,7 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS dxgsg_cat.error() << "CreateTexture failed: _surface->Lock() failed on texture! hr = " << ConvD3DErrorToString(hr) << "\n"; return hr; } + //pbuf contains raw ARGB in PixelBuffer byteorder DWORD lPitch = ddsd.lPitch; @@ -210,70 +234,72 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS case Conv32to32: case Conv32to32_NoAlpha: { - DWORD *pSrcWord = (DWORD *) pbuf; - DWORD *pDstWord; - DWORD dwAlphaMaskOff = (ConvNeeded==Conv32to32_NoAlpha) ? 0x00FFFFFF : 0xFFFFFFFF; +#ifdef PANDA_BGRA_ORDER + if(ConvNeeded==Conv32to32) { + memcpy(pDDSurfBytes,(BYTE*) pbuf,dwOrigWidth*dwOrigHeight*sizeof(DWORD)); + } else { + DWORD *pSrcWord = (DWORD *) pbuf; + DWORD *pDstWord; + + // need to set all pixels alpha to 0xFF + for(DWORD y=0; y>24)); // unsigned >>, no need to & - b = (BYTE)((dwPixel>>16)&0x000000ff); - g = (BYTE)((dwPixel>> 8)&0x000000ff); - r = (BYTE)((dwPixel )&0x000000ff); + // pixel buffer is in ABGR format(it stores big-endian RGBA) + // need to change byte order to ARGB - *pDstWord = (a << 24) | (r << 16)| (g << 8) | b; -#else BYTE r,b; - // simpler: just swap r & b - b = (BYTE)((dwPixel>>16)&0x000000ff); - r = (BYTE)((dwPixel )&0x000000ff); - *pDstWord = ((dwPixel & 0xff00ff00) | (r<<16) | b) & dwAlphaMaskOff; -#endif + // just swap r & b + b = GET_BLUE_BYTE(dwPixel); + r = GET_RED_BYTE(dwPixel); + *pDstWord = ((dwPixel & 0xff00ff00) | (r<<16) | b) | dwAlphaMaskOn; } } +#endif break; } case Conv32to16_1555: - case Conv32to16_0555: { + case Conv32to16_X555: { DWORD *pSrcWord = (DWORD *) pbuf; WORD *pDstWord; - DWORD dwAlphaMaskOff = (ConvNeeded==Conv32to16_0555) ? 0x7FFF : 0xFFFF; + + unsigned short dwAlphaMaskOn = (ConvNeeded==Conv32to16_X555) ? 0x8000 : 0x0; assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00); - // for some reason, bits are 'in-order' when converting to 16bit - // just handle 1/15 alpha/rgb for(DWORD y=0; y>16) & 0x00008000); // just copy high bit + abit = ((dwPixel>>16) & 0x00008000) | dwAlphaMaskOn; // just copy high bit + g = GET_GREEN_BYTE(dwPixel) >> 3; + b = GET_BLUE_BYTE(dwPixel) >> 3; + r = GET_RED_BYTE(dwPixel) >> 3; - // just look at most-signf-bit for alpha. (alternately, could - // convert any non-zero alpha to full transparent) + // truncates 8 bit values to 5 bit (or 1 for alpha) - b = (BYTE)((dwPixel>>16) & 0x000000ff) >> 3; - g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 3; - r = (BYTE)((dwPixel ) & 0x000000ff) >> 3; - - // code truncates 8 bit values to 5 bit (or 1 for alpha) - - *pDstWord = (abit | (r << 10)| (g << 5) | b) & dwAlphaMaskOff; + *pDstWord = (abit | (r << 10)| (g << 5) | b); } } break; @@ -284,9 +310,8 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS WORD *pDstWord; assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - // for some reason, bits are 'in-order' when converting to 16bit + // for some reason, bits are 'in-order' when converting to 16bit - // just handle 1/15 alpha/rgb for(DWORD y=0; y>16) & 0x000000ff) >> 3; - g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 2; - r = (BYTE)((dwPixel ) & 0x000000ff) >> 3; - - // code truncates 8 bit values to 5 bit (or 1 for alpha) - + g = GET_GREEN_BYTE(dwPixel) >> 2; + b = GET_BLUE_BYTE(dwPixel) >> 3; + r = GET_RED_BYTE(dwPixel) >> 3; *pDstWord = ((r << 11)| (g << 5) | b); } } break; } - - case Conv32to24: { - - DWORD *pSrcWord = (DWORD *) pbuf; - BYTE *pDstWord; - - for(DWORD y=0; y>16) & 0x000000ff); - g = (BYTE)((dwPixel>> 8) & 0x000000ff); - r = (BYTE)((dwPixel ) & 0x000000ff); - - *pDstWord = r; - *(pDstWord+1) = g; - *(pDstWord+2) = b; - } - } - break; - } - - case Conv32to16_4444: { DWORD *pSrcWord = (DWORD *) pbuf; WORD *pDstWord; @@ -354,13 +342,10 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS BYTE r,g,b,a; DWORD dwPixel = *pSrcWord; - // pixel buffer is in ABGR format (orig fmt designed for big-endian RGBA) - // need to change byte order to ARGB - - a = (BYTE)((dwPixel>>24)) >> 4; - b = (BYTE)((dwPixel>>16) & 0x000000ff) >> 4; - g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 4; - r = (BYTE)((dwPixel ) & 0x000000ff) >> 4; + a = GET_ALPHA_BYTE(dwPixel) >> 4; + g = GET_GREEN_BYTE(dwPixel) >> 4; + b = GET_BLUE_BYTE(dwPixel) >> 4; + r = GET_RED_BYTE(dwPixel) >> 4; *pDstWord = (a << 12) | (r << 8)| (g << 4) | b; } @@ -368,19 +353,43 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS break; } + case Conv32to24: { - case Conv24to24: { - - BYTE *pSrcWord = (BYTE *) pbuf; + DWORD *pSrcWord = (DWORD *) pbuf; BYTE *pDstWord; + for(DWORD y=0; y> 3; + r = *(pSrcWord+2) >> 3; + #else r = *pSrcWord >> 3; + b = *(pSrcWord+2) >> 3; + #endif g = *(pSrcWord+1) >> 3; - b = *(pSrcWord+2) >> 3; - // code truncates 8 bit values to 5 bit, leaves high bit as 0 - - *pDstWord = (r << 10)| (g << 5) | b; + *pDstWord = 0x8000 | (r << 10)| (g << 5) | b; } } break; @@ -426,7 +437,6 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS WORD *pDstWord; assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - // for some reason, bits are 'in-order' when converting to 16bit for(DWORD y=0; y> 3; + g = *(pSrcWord+1) >> 2; + r = *(pSrcWord+2) >> 3; + #else r = *pSrcWord >> 3; g = *(pSrcWord+1) >> 2; b = *(pSrcWord+2) >> 3; - - // code truncates 8 bit values to 5 bit, leaves high bit as 0 - - *pDstWord = (r << 11)| (g << 5) | b; + #endif + // code truncates 8 bit values to 5 bit + *pDstWord = (r << 11)| (g << 5) | b; } } break; } case Conv24to32: { - BYTE *pSrcWord = (BYTE *) pbuf; DWORD *pDstWord; @@ -458,25 +469,25 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS for(DWORD x=0; x> 8; - r = dwPixel & 0xFF; - - *pDstWord = (a<<24)| (r << 16)| (r << 8) | r; + lum = dwPixel & 0xFF; + *pDstWord = (a<<24) | lum | (lum << 8) | (lum << 16); } } break; @@ -509,13 +519,13 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS for(DWORD x=0; x>8) >> 4; - r = (BYTE)(dwPixel & 0x000000ff) >> 4; + a = (BYTE)(dwPixel>>8) >> 4; + lum = (BYTE)(dwPixel & 0x000000ff) >> 4; - *pDstWord = (a << 12) | (r << 8)| (r << 4) | r; + *pDstWord = (a << 12) | lum | (lum << 4)| (lum << 8); } } break; @@ -531,30 +541,30 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS pDstWord = (WORD*)pDDSurfBytes; for(DWORD x=0; x> 3; + lum = (BYTE)(dwPixel & 0x00FF) >> 3; - *pDstWord = (dwPixel & 0x8000) | (r << 10)| (r << 5) | r; + *pDstWord = (dwPixel & 0x8000) | lum | (lum << 5) | (lum << 10); } } break; } case ConvLum16to16: { - // AL bytes are in same order + // All bytes are in same order? CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight*2); break; } case ConvLum8to16_0565: - case ConvLum8to16_0555: { + case ConvLum8to16_X555: { BYTE *pSrcWord = (BYTE *) pbuf; WORD *pDstWord; DWORD FarShift,OrVal,MiddleRoundShift; - if(ConvNeeded==ConvLum8to16_0555) { + if(ConvNeeded==ConvLum8to16_X555) { FarShift=10; OrVal=0x8000; // turn on alpha bit, just in case MiddleRoundShift = 3; assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00); @@ -574,7 +584,7 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS r = (BYTE) dwPixel >> 3; GrnVal = (BYTE) dwPixel >> MiddleRoundShift; - // code truncates 8 bit values to 5 bit (set alpha=1 for opaque) + // code truncates 8 bit values to 5 bit (set alpha=1 for opaque) *pDstWord = ((r << FarShift)| (GrnVal << 5) | r) | OrVal; } @@ -599,15 +609,14 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS for(DWORD x=0; xget_num_components(); assert(pixbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now assert(pixbuf->get_image_type()==PixelBuffer::T_unsigned_byte); // cant handle anything else now assert((dwNumComponents==3) || (dwNumComponents==4)); // cant handle anything else now + assert(pD3DSurf8!=NULL); BYTE *pbuf=pixbuf->_image.p(); - if(IsBadWritePtr(pDDSurf,sizeof(DWORD))) { - dxgsg_cat.error() << "ConvertDDSurftoPixBuf failed: bad pDDSurf ptr value (" << ((void*)pDDSurf) << ")\n"; + if(IsBadWritePtr(pD3DSurf8,sizeof(DWORD))) { + dxgsg_cat.error() << "ConvertDDSurftoPixBuf failed: bad pD3DSurf ptr value (" << ((void*)pD3DSurf8) << ")\n"; exit(1); } - if(FAILED( hr = pDDSurf->Lock( NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) { - dxgsg_cat.error() << "ConvertDDSurftoPixBuf Lock() failed! hr = " << ConvD3DErrorToString(hr) << "\n"; + D3DLOCKED_RECT LockedRect; + D3DSURFACE_DESC SurfDesc; + + hr = pD3DSurf8->GetDesc(&SurfDesc); + + hr = pD3DSurf8->LockRect(&LockedRect,(CONST RECT*)NULL,(D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE /* | D3DLOCK_NOSYSLOCK */)); + if(FAILED(hr)) { + dxgsg_cat.error() << "ConvertDDSurftoPixBuf LockRect() failed! hr = " << D3DERRORSTRING(hr); return hr; } DWORD dwXWindowOffset=0,dwYWindowOffset=0; - DWORD dwCopyWidth=ddsd.dwWidth,dwCopyHeight=ddsd.dwHeight; + DWORD dwCopyWidth=SurfDesc.Width,dwCopyHeight=SurfDesc.Height; - // get window offset so we know where to start grabbing pixels +/* + + bugbug: need to test scrngrab for windowed case. do I need to do the clientrect stuff? + + // get window offset so we know where to start grabbing pixels. note for + // fullscreen primary no clipper will be attached, that 'error' should be ignored LPDIRECTDRAWCLIPPER pDDClipper; hr = pDDSurf->GetClipper(&pDDClipper); @@ -727,62 +777,128 @@ HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) pDDClipper->Release(); // dec ref cnt } - +*/ //make sure there's enough space in the pixbuf, its size must match (especially xsize) // or scanlines will be too long - if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=pixbuf->get_ysize()))) { - pDDSurf->Unlock(NULL); + if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) { + pD3DSurf8->UnlockRect(); + dxgsg_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size does not match display surface!\n"; assert(0); - dxgsg_cat.error() << "ConvertDDSurftoPixBuf, PixBuf incorrect size to hold display surface!\n"; return E_FAIL; } - // others not handled yet - assert((ddsd.ddpfPixelFormat.dwRGBBitCount==32)||(ddsd.ddpfPixelFormat.dwRGBBitCount==16)||(ddsd.ddpfPixelFormat.dwRGBBitCount==24)); + // ones not listed not handled yet + assert((SurfDesc.Format==D3DFMT_A8R8G8B8)||(SurfDesc.Format==D3DFMT_X8R8G8B8)||(SurfDesc.Format==D3DFMT_R8G8B8)|| + (SurfDesc.Format==D3DFMT_R5G6B5)||(SurfDesc.Format==D3DFMT_X1R5G5B5)||(SurfDesc.Format==D3DFMT_A1R5G5B5)|| + (SurfDesc.Format==D3DFMT_A4R4G4B4)); //pbuf contains raw ARGB in PixelBuffer byteorder - DWORD lPitch = ddsd.lPitch; - BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; + DWORD BytePitch = LockedRect.Pitch; + BYTE* pSurfBytes = (BYTE*)LockedRect.pBits; - if(dwNumComponents==4) { - DWORD *pDstWord = (DWORD *) pbuf; - switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { + // writes out last line in DDSurf first in PixelBuf, so Y line order precedes inversely - case 32: { + if(dxgsg_cat.is_debug()) { + dxgsg_cat.debug() << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to " + << dwNumComponents << "-channel panda PixelBuffer\n"; + } + + DWORD *pDstWord = (DWORD *) pbuf; + BYTE *pDstByte = (BYTE *) pbuf; + + switch(SurfDesc.Format) { + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: { + if(dwNumComponents==4) { DWORD *pSrcWord; - - pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); - for(DWORD y=0; y>16)&0x000000ff); - g = (BYTE)((dwPixel>> 8)&0x000000ff); - b = (BYTE)((dwPixel )&0x000000ff); - - *pDstWord = (dwPixel & 0xff00ff00) | (r<<16) | b; + #ifdef PANDA_BGRA_ORDER + BYTE *pDstLine = (BYTE*)pDstWord; + #endif + + pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1); + for(DWORD y=0; y> 16) & g_LowByteMask); + b = (BYTE) (dwPixel & g_LowByteMask); + + // want to write out ABGR + *pDstWord = (dwPixel & 0xFF00FF00) | (b<<16) | r; + } + #endif } + } else { + // 24bpp pixbuf case (numComponents==3) + DWORD *pSrcWord; + pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1); + for(DWORD y=0; y>16) & g_LowByteMask); + g = (BYTE)((dwPixel>> 8) & g_LowByteMask); + b = (BYTE)((dwPixel ) & g_LowByteMask); + + #ifdef PANDA_BGRA_ORDER + *pDstByte++ = b; + *pDstByte++ = g; + *pDstByte++ = r; + #else + *pDstByte++ = r; + *pDstByte++ = g; + *pDstByte++ = b; + #endif } - break; } + } + break; + } - case 24: { - BYTE *pSrcByte; + case D3DFMT_R8G8B8: { + BYTE *pSrcByte; + pSurfBytes+=BytePitch*(dwYWindowOffset+dwCopyHeight-1); - pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); - for(DWORD y=0; y> greenshift; r = (dwPixel & redmask) >> redshift; - *pDstWord = 0xFF000000 | (b << 16) | (g << 8) | r; + // alpha is just set to 0xFF + + #ifdef PANDA_BGRA_ORDER + *pDstWord = 0xFF000000 | (r << 16) | (g << 8) | b; + #else + *pDstWord = 0xFF000000 | (b << 16) | (g << 8) | r; + #endif } } - } - break; - } - } else { // convert to 24bpp pixbuf - BYTE *pDstByte = (BYTE *) pbuf; - switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { - - case 32: { - DWORD *pSrcWord; - - pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); - for(DWORD y=0; y>16)&0x000000ff); - g = (BYTE)((dwPixel>> 8)&0x000000ff); - b = (BYTE)((dwPixel )&0x000000ff); - - *pDstByte++ = r; - *pDstByte++ = g; - *pDstByte++ = b; - } - } - break; - } - - case 24: { - BYTE *pSrcByte; - - pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); - for(DWORD y=0; y> greenshift; r = (dwPixel & redmask) >> redshift; - *pDstByte++ = r; - *pDstByte++ = g; - *pDstByte++ = b; + #ifdef PANDA_BGRA_ORDER + *pDstByte++ = b; + *pDstByte++ = g; + *pDstByte++ = r; + #else + *pDstByte++ = r; + *pDstByte++ = g; + *pDstByte++ = b; + #endif } } } break; } + + default: + dxgsg_cat.error() << "ConvertD3DSurftoPixBuf: unsupported D3DFORMAT!\n"; } - - pDDSurf->Unlock(NULL); - + pD3DSurf8->UnlockRect(); return S_OK; } //----------------------------------------------------------------------------- -// Name: CreateTextureFromBitmap() -// Desc: Use a bitmap to create a texture for the specified device. This code -// gets the attributes of the texture from the bitmap, creates the +// Name: CreateTexture() +// Desc: Use panda texture's pixelbuffer to create a texture for the specified device. +// This code gets the attributes of the texture from the bitmap, creates the // texture, and then copies the bitmap into the texture. //----------------------------------------------------------------------------- -LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevice, -#ifdef USE_TEXFMTVEC - DDPixelFormatVec &TexFmts,LPD3DDEVICEDESC7 pD3DDevDesc) -#else - int cNumTexPixFmts, DDPIXELFORMAT *pTexFmts,LPD3DDEVICEDESC7 pD3DDevDesc) -#endif - { +IDirect3DTexture8 *DXTextureContext::CreateTexture(DXScreenData &scrn) { HRESULT hr; - int i,cNumAlphaBits; // number of alpha bits in texture pixfmt - DDPIXELFORMAT *pDesiredPixFmt; - LPDIRECTDRAWSURFACE7 pddsRender; - LPDIRECTDRAW7 pDD = NULL; - ConversionType ConvNeeded; + int cNumAlphaBits; // number of alpha bits in texture pixfmt + D3DFORMAT PixBufD3DFmt; + D3DFORMAT TargetPixFmt=D3DFMT_UNKNOWN; + bool bNeedLuminance = false; assert(_texture!=NULL); PixelBuffer *pbuf = _texture->_pbuffer; - -#ifdef USE_TEXFMTVEC - int cNumTexPixFmts=TexturePixelFormats.size(); -#endif - DDPIXELFORMAT *pTexPixFmts = new DDPIXELFORMAT[cNumTexPixFmts]; - - // make local copy of array so I can muck with it during searches for this texture fmt - // (such as marking pixfmts that no search will be interested in) - // probably should do this faster way - -#ifdef USE_TEXFMTVEC - memcpy(pTexPixFmts,&TexturePixelFormats[0],cNumTexPixFmts*sizeof(DDPIXELFORMAT)); -#else - memcpy(pTexPixFmts,pTexFmts,cNumTexPixFmts*sizeof(DDPIXELFORMAT)); -#endif - // bpp indicates requested fmt, not pixbuf fmt - DWORD bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits); + DWORD target_bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits); PixelBuffer::Type pixbuf_type = pbuf->get_image_type(); DWORD cNumColorChannels = pbuf->get_num_components(); @@ -1019,56 +1040,53 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic DWORD dwOrigWidth = (DWORD)pbuf->get_xsize(); DWORD dwOrigHeight = (DWORD)pbuf->get_ysize(); - - // Use the device caps so we can check if the device has any constraints - // when using textures. - - assert((pD3DDevDesc->dwMaxTextureWidth>0) && (pD3DDevDesc->dwMaxTextureHeight>0)); - - // Setup the new surface desc for the texture. Note how we are using the - // texture manage attribute, so Direct3D does alot of dirty work for us - DDSURFACEDESC2 ddsd; - ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) ); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH - | DDSD_PIXELFORMAT ; - - ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); - - // setup ddpf to match against avail fmts - - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - + if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)|| (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) || (pbuf->get_format() == PixelBuffer::F_luminance)) { - ddsd.ddpfPixelFormat.dwFlags = DDPF_LUMINANCE; + bNeedLuminance = true; } - ddsd.ddpfPixelFormat.dwRGBBitCount = bpp; - - if(cNumAlphaBits) { - if(bpp == 8 && cNumAlphaBits == 8) { // handle special case: Alpha only buffer - ddsd.dwFlags |= DDPF_ALPHA; - ddsd.dwAlphaBitDepth = 8; - ddsd.ddpfPixelFormat.dwAlphaBitDepth = 8; - ddsd.ddpfPixelFormat.dwFlags = DDPF_ALPHA; - ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff; - } else { - ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS; - if(cNumAlphaBits == 8) - ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000; - else if(cNumAlphaBits == 4) - ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xf000; + if(cNumAlphaBits>0) { + if(cNumColorChannels==3) { + dxgsg_cat.error() << "ERROR: texture " << _tex->get_name() << " has no inherent alpha channel, but alpha format is requested (that would be wasteful)!\n"; + exit(1); } } - ddsd.dwWidth = dwOrigWidth; - ddsd.dwHeight = dwOrigHeight; +#ifndef DO_CUSTOM_CONVERSIONS + // figure out what 'D3DFMT' the PixelBuffer is in, so D3DXLoadSurfFromMem knows how to perform copy + PixBufD3DFmt=D3DFMT_UNKNOWN; - if(!ISPOW2(ddsd.dwWidth) || !ISPOW2(ddsd.dwHeight)) { - dxgsg_cat.error() << "ERROR: texture dimensions are not a power of 2 for " << _tex->get_name() << "!!!!! \n"; - #ifdef _DEBUG + switch(cNumColorChannels) { + case 1: + if(cNumAlphaBits>0) + PixBufD3DFmt=D3DFMT_A8; + else if(bNeedLuminance) + PixBufD3DFmt=D3DFMT_L8; + break; + case 2: + assert(bNeedLuminance && (cNumAlphaBits>0)); + PixBufD3DFmt=D3DFMT_A8L8; + break; + case 3: + PixBufD3DFmt=D3DFMT_R8G8B8; + break; + case 4: + PixBufD3DFmt=D3DFMT_A8R8G8B8; + break; + } + + // make sure we handled all the possible cases + assert(PixBufD3DFmt!=D3DFMT_UNKNOWN); +#endif + + DWORD TargetWidth=dwOrigWidth; + DWORD TargetHeight=dwOrigHeight; + + if(!ISPOW2(dwOrigWidth) || !ISPOW2(dwOrigHeight)) { + dxgsg_cat.error() << "ERROR: texture dimensions are not a power of 2 for " << _tex->get_name() << "! Please rescale them so it doesnt have to be done at runtime.\n"; + #ifndef NDEBUG exit(1); // want to catch badtexsize errors #else goto error_exit; @@ -1078,38 +1096,38 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic bool bShrinkOriginal; bShrinkOriginal=false; - if((dwOrigWidth>pD3DDevDesc->dwMaxTextureWidth)||(dwOrigHeight>pD3DDevDesc->dwMaxTextureHeight)) { + if((dwOrigWidth>scrn.d3dcaps.MaxTextureWidth)||(dwOrigHeight>scrn.d3dcaps.MaxTextureHeight)) { #ifdef _DEBUG - dxgsg_cat.error() << "WARNING: " <<_tex->get_name() << ": Image size exceeds max texture dimensions of (" << pD3DDevDesc->dwMaxTextureWidth << "," << pD3DDevDesc->dwMaxTextureHeight << ") !!\n" - << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< pD3DDevDesc->dwMaxTextureWidth << "," << pD3DDevDesc->dwMaxTextureHeight << ") !\n"; + dxgsg_cat.error() << "WARNING: " <<_tex->get_name() << ": Image size exceeds max texture dimensions of (" << scrn.d3dcaps.MaxTextureWidth << "," << scrn.d3dcaps.MaxTextureHeight << ") !!\n" + << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< scrn.d3dcaps.MaxTextureWidth << "," << scrn.d3dcaps.MaxTextureHeight << ") !\n"; #endif - if(dwOrigWidth>pD3DDevDesc->dwMaxTextureWidth) - ddsd.dwWidth=pD3DDevDesc->dwMaxTextureWidth; - if(dwOrigHeight>pD3DDevDesc->dwMaxTextureHeight) - ddsd.dwHeight=pD3DDevDesc->dwMaxTextureHeight; + if(dwOrigWidth>scrn.d3dcaps.MaxTextureWidth) + TargetWidth=scrn.d3dcaps.MaxTextureWidth; + if(dwOrigHeight>scrn.d3dcaps.MaxTextureHeight) + TargetHeight=scrn.d3dcaps.MaxTextureHeight; bShrinkOriginal=true; } // checks for SQUARE reqmt (nvidia riva128 needs this) - if((ddsd.dwWidth != ddsd.dwHeight) && (pD3DDevDesc->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )) { - + if((TargetWidth != TargetHeight) && (scrn.d3dcaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)) { // assume pow2 textures. sum exponents, divide by 2 rounding down to get sq size int i,width_exp,height_exp; - for(i=ddsd.dwWidth,width_exp=0;i>1;width_exp++,i>>=1); - for(i=ddsd.dwHeight,height_exp=0;i>1;height_exp++,i>>=1); - ddsd.dwHeight = ddsd.dwWidth = 1<<((width_exp+height_exp)>>1); + for(i=TargetWidth,width_exp=0;i>1;width_exp++,i>>=1); + for(i=TargetHeight,height_exp=0;i>1;height_exp++,i>>=1); + TargetHeight = TargetWidth = 1<<((width_exp+height_exp)>>1); bShrinkOriginal=true; #ifdef _DEBUG - dxgsg_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< ddsd.dwWidth<<"," << ddsd.dwHeight << ") to meet HW square texture reqmt\n"; + dxgsg_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< TargetWidth<<"," << TargetHeight << ") to meet HW square texture reqmt\n"; #endif } - +/* + // we now use D3DXLoadSurfFromMem to do resizing as well as fmt conversion if(bShrinkOriginal) { // need 2 add checks for errors PNMImage pnmi_src; - PNMImage *pnmi = new PNMImage(ddsd.dwWidth, ddsd.dwHeight, cNumColorChannels); + PNMImage *pnmi = new PNMImage(TargetWidth, TargetHeight, cNumColorChannels); pbuf->store(pnmi_src); pnmi->quick_filter_from(pnmi_src,0,0); @@ -1119,78 +1137,62 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic dwOrigHeight = (DWORD)pbuf->get_ysize(); delete pnmi; } +*/ -#if 0 -//#ifdef _DEBUG -// easier to use dxcapsviewer instead of this - { static BOOL bPrinted=FALSE; - if(!bPrinted) { - dxgsg_cat.debug() << "Gfx card supported TexFmts:\n"; - for(i=0;idwFlags & (DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) ) || - ( pCurPixFmt->dwFourCC != 0 ) || - ((cNumAlphaBits==0) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS))) { + // I could possibly replace some of this logic with D3DXCheckTextureRequirements(), but + // it wouldnt handle all my specialized low-memory cases perfectly - // Make sure to skip any FourCC formats, bump formats - // they are not handled by this code yet +#ifdef DO_CUSTOM_CONVERSIONS + ConversionType ConvNeeded; - // note: I'm screening out alpha if no alpha requested, so - // search fails if 32-rgba avail, but not 32-bit rgb - // I could recode for that case too, hopefully this case will not pop up +#define CONVTYPE_STMT ConvNeeded=CONV +#else +#define CONVTYPE_STMT +#endif - pCurPixFmt->dwRGBBitCount+=1; // incr so it wont be an exact match anymore - } - } +#define CHECK_FOR_FMT(FMT,CONV) \ + if(scrn.SupportedTexFmtsMask & FMT##_FLAG) { \ + CONVTYPE_STMT; \ + TargetPixFmt=D3DFMT_##FMT; \ + goto found_matching_format; } - // handle each bitdepth separately + // handle each target bitdepth separately. might be less confusing to reorg by cNumColorChannels (input type, rather + // than desired 1st target) + switch(target_bpp) { - switch(bpp) { // bpp is REQUESTED bpp, not what exists in the pixbuf array + // IMPORTANT NOTE: + // target_bpp is REQUESTED bpp, not what exists in the pixbuf array (the pixbuf array contains cNumColorChannels*8bits) case 32: + if(!((cNumColorChannels==3) || (cNumColorChannels==4))) + break; //bail -#ifdef _DEBUG - if(!dx_force_16bpptextures) -#endif - for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==32) && - (((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)!=0)==(cNumAlphaBits!=0))) { - // we should have a match - assert(pCurPixFmt->dwRGBAlphaBitMask==0xFF000000); - ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32); - goto found_matching_format; - break; - } + if(!dx_force_16bpptextures) { + if(cNumColorChannels==4) { + CHECK_FOR_FMT(A8R8G8B8,Conv32to32); + } else { + CHECK_FOR_FMT(A8R8G8B8,Conv24to32); } + } if(cNumAlphaBits>0) { + assert(cNumColorChannels==4); + // no 32-bit fmt, look for 16 bit w/alpha (1-15) // 32 bit RGBA was requested, but only 16 bit alpha fmts are avail // by default, convert to 4-4-4-4 which has 4-bit alpha for blurry edges // if we know tex only needs 1 bit alpha (i.e. for a mask), use 1555 instead - ConversionType ConvTo1=Conv32to16_4444,ConvTo2=Conv32to16_1555; - DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000; +// ConversionType ConvTo1=Conv32to16_4444,ConvTo2=Conv32to16_1555; +// DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000; // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion // this should be true on most cards. @@ -1198,250 +1200,128 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic if(cNumAlphaBits==1) #endif { - ConvTo1=Conv32to16_1555; - dwAlphaMask1=0x8000; + CHECK_FOR_FMT(A1R5G5B5,Conv32to16_1555); } - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) { - ConvNeeded=ConvTo1; - goto found_matching_format; - } - } + // normally prefer 4444 due to better alpha channel resolution + CHECK_FOR_FMT(A4R4G4B4,Conv32to16_4444); + CHECK_FOR_FMT(A1R5G5B5,Conv32to16_1555); -#ifdef FORCE_16bpp_1555 - break; -#endif - - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) { - ConvNeeded=ConvTo2; - goto found_matching_format; - } - } - - // at this point, bail. dont worry about converting to non-alpha formats yet, - // I think this will be a very rare case + // at this point, bail. dont worry about converting to non-alpha formats yet, + // I think this will be a very rare case szErrorMsg = "CreateTexture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!\n"; - } + } else { + // convert 3 or 4 channel to closest 16bpp color fmt + if(cNumColorChannels==3) { + CHECK_FOR_FMT(R5G6B5,Conv24to16_4444); + CHECK_FOR_FMT(X1R5G5B5,Conv24to16_X555); + } else { + CHECK_FOR_FMT(R5G6B5,Conv32to16_4444); + CHECK_FOR_FMT(X1R5G5B5,Conv32to16_X555); + } + } break; case 24: - - assert(cNumAlphaBits==0); // dont know how to handle non-zero alpha for 24bit total - - if(!dx_force_16bpptextures) - for(i=0,pCurPixFmt=pTexPixFmts;idwFlags & DDPF_RGB)&&(pCurPixFmt->dwRGBBitCount==24)) { - ConvNeeded=((cNumColorChannels==3) ? Conv24to24 : Conv32to24); - goto found_matching_format; - } - } + assert(cNumColorChannels==3); if(!dx_force_16bpptextures) { + CHECK_FOR_FMT(R8G8B8,Conv24to24); + // no 24-bit fmt. look for 32 bit fmt (note: this is memory-hogging choice // instead I could look for memory-conserving 16-bit fmt). - // check mask to ensure ARGB, not RGBA (which I am not handling here) - for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB) - && ((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0xFFFFFF) - ) { - // I'm allowing alpha formats here. will set alpha to opaque - ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32_NoAlpha); - goto found_matching_format; - } - } + + CHECK_FOR_FMT(X8R8G8B8,Conv24to32); } - // no 24-bit or 32 fmt. look for 16 bit fmt - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i16 conversion, should be true on most cards. - if((pCurPixFmt->dwFlags & DDPF_RGB) && (pCurPixFmt->dwRGBBitCount==16) - && !(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) { // no alpha fmts - // if numchan==4,this means user has requested we throw away the input alpha channel - if(pCurPixFmt->dwGBitMask==0x7E0) { - // assumes GBitMask is the biggest one, if we have 16 bit 3-channel - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565); - } else { - assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF); - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0555 : Conv32to16_0555); - } - goto found_matching_format; - } - } - - // at this point, bail. + // no 24-bit or 32 fmt. look for 16 bit fmt (higher res 565 1st) + CHECK_FOR_FMT(R5G6B5,Conv24to16_0565); + CHECK_FOR_FMT(X1R5G5B5,Conv24to16_X555); break; case 16: + if(bNeedLuminance) { + assert(cNumAlphaBits>0); + assert(cNumColorChannels==2); - if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) { - // look for native lum fmt + CHECK_FOR_FMT(A8L8,ConvLum16to16); + if(!dx_force_16bpptextures) { - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) && - (pCurPixFmt->dwFlags & DDPF_LUMINANCE)) { - ConvNeeded=ConvLum16to16; - goto found_matching_format; - } - } - - // else look for 32bpp ARGB - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) && - (pCurPixFmt->dwFlags & DDPF_RGB)) { - ConvNeeded=ConvLum16to32; - goto found_matching_format; - } - } + CHECK_FOR_FMT(A8R8G8B8,ConvLum16to32); } - // find compatible 16bpp fmt - ConversionType ConvTo1=ConvLum16to16_4444,ConvTo2=ConvLum16to16_1555; - DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000; - // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion - // this should be true on most cards. - -#ifndef FORCE_16bpp_1555 + #ifndef FORCE_16bpp_1555 if(cNumAlphaBits==1) -#endif + #endif { - ConvTo1=ConvLum16to16_1555; - dwAlphaMask1=0x8000; + CHECK_FOR_FMT(A1R5G5B5,ConvLum16to16_1555); } - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) { - ConvNeeded=ConvTo1; - goto found_matching_format; - } - } - -#ifdef FORCE_16bpp_1555 - break; -#endif - - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) { - ConvNeeded=ConvTo2; - goto found_matching_format; - } - } - - } else - + // normally prefer 4444 due to better alpha channel resolution + CHECK_FOR_FMT(A4R4G4B4,ConvLum16to16_4444); + CHECK_FOR_FMT(A1R5G5B5,ConvLum16to16_1555); + } else { + assert((cNumColorChannels==3)||(cNumColorChannels==4)); // look for compatible 16bit fmts, if none then give up // (dont worry about other bitdepths for 16 bit) - - for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==16)&&(pCurPixFmt->dwFlags & DDPF_RGB)) { - switch(cNumAlphaBits) { - case 0: - if(!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) { - // if numchan==4,this means user has requested we throw away the input alpha channel - if(pCurPixFmt->dwGBitMask==0x7E0) { - // assumes GBitMask is the biggest one, if we have 16 bit 3-channel - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565); - } else { - assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF); - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0555 : Conv32to16_0555); - } - goto found_matching_format; - } - break; - case 1: - if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&& - (pCurPixFmt->dwRGBAlphaBitMask==0x8000)) { - ConvNeeded=Conv32to16_1555; - goto found_matching_format; - } - break; - case 4: - if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&& - (pCurPixFmt->dwRGBAlphaBitMask==0xF000)) { - ConvNeeded=Conv32to16_4444; - goto found_matching_format; - } - break; - } - } + switch(cNumAlphaBits) { + case 0: + if(cNumColorChannels==3) { + CHECK_FOR_FMT(R5G6B5,Conv24to16_0565); + CHECK_FOR_FMT(X1R5G5B5,Conv24to16_X555); + } else { + assert(cNumColorChannels==4); + // it could be 4 if user asks us to throw away the alpha channel + CHECK_FOR_FMT(R5G6B5,Conv32to16_0565); + CHECK_FOR_FMT(X1R5G5B5,Conv32to16_X555); + } + break; + case 1: + // app specifically requests 1-5-5-5 F_rgba5 case, where you explicitly want 1-5-5-5 fmt, as opposed + // to F_rgbm, which could use 32bpp ARGB. fail if this particular fmt not avail. + assert(cNumColorChannels==4); + CHECK_FOR_FMT(X1R5G5B5,Conv32to16_X555); + break; + case 4: + // app specifically requests 4-4-4-4 F_rgba4 case, as opposed to F_rgba, which could use 32bpp ARGB + assert(cNumColorChannels==4); + CHECK_FOR_FMT(A4R4G4B4,Conv32to16_4444); + break; + default: assert(0); // problem in get_bits_per_pixel()? } - - break; - + } case 8: - if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) { - // look for native lum fmt + if(bNeedLuminance) { + assert(cNumAlphaBits>0); // dont bother handling those other 8bit lum fmts like 4-4, since 16 8-8 is usually supported too + assert(cNumColorChannels==1); - assert(cNumAlphaBits==0); // dont handle those other 8bit lum fmts like 4-4, since 16 8-8 is usually supported too - if(!dx_force_16bpptextures) - { - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==8) && (pCurPixFmt->dwFlags & DDPF_LUMINANCE) && - (pCurPixFmt->dwLuminanceBitMask==0xFF)) { - ConvNeeded=ConvLum8to8; - goto found_matching_format; - } - } + // look for native lum fmt first + CHECK_FOR_FMT(L8,ConvLum8to8); + CHECK_FOR_FMT(L8,ConvLum8to16_A8L8); - // else look for 24bpp RGB - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==24) && (pCurPixFmt->dwFlags & DDPF_RGB)) { - ConvNeeded=ConvLum8to24; - goto found_matching_format; - } - } - - // else look for 32bpp RGB - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB)) { - ConvNeeded=ConvLum8to32; - goto found_matching_format; - } - } + if(!dx_force_16bpptextures) { + CHECK_FOR_FMT(R8G8B8,ConvLum8to24); + CHECK_FOR_FMT(X8R8G8B8,ConvLum8to32); } - // find compatible 16bpp fmt, just look for any 565, then 0555 - DWORD dwMasks[2] = {0xF800, 0x7C00}; - ConversionType ConvType[2] = {ConvLum8to16_0565,ConvLum8to16_0555}; + CHECK_FOR_FMT(R5G6B5,ConvLum8to16_0565); + CHECK_FOR_FMT(X1R5G5B5,ConvLum8to16_X555); - for(DWORD modenum=0;modenum<2;modenum++) - for(i=0,pCurPixFmt=&pTexPixFmts[0];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_RGB) - && (!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) - && (pCurPixFmt->dwRBitMask==dwMasks[modenum])) { - ConvNeeded=ConvType[modenum]; - goto found_matching_format; - } - } - } else if(ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHA) { - // look for 32-bit ARGB, else 16-4444. - // skip 8bit alpha only, because I think only voodoo supports it - // and the voodoo support isn't the kind of blending model we need - // w/color assumed to be white (but need to verify this) - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB) && - (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) { - ConvNeeded=ConvAlpha8to32; - goto found_matching_format; - } + } else if(cNumAlphaBits==8) { + // look for 16bpp A8L8, else 32-bit ARGB, else 16-4444. + + // skip 8bit alpha only (D3DFMT_A8), because I think only voodoo supports it + // and the voodoo support isn't the kind of blending model we need somehow + // (is it that voodoo assumes color is white? isnt that what we do in ConvAlpha8to32 anyway?) + + CHECK_FOR_FMT(A8L8,ConvAlpha8to16_A8L8); + + if(!dx_force_16bpptextures) { + CHECK_FOR_FMT(A8R8G8B8,ConvAlpha8to32); } - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) - && (pCurPixFmt->dwFlags & DDPF_RGB) - && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==0xF000)) { - ConvNeeded=ConvAlpha8to16_4444; - goto found_matching_format; - } - } + CHECK_FOR_FMT(A8L8,ConvAlpha8to16_4444); } break; @@ -1451,28 +1331,12 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic // if we've gotten here, haven't found a match - dxgsg_cat.error() << szErrorMsg << "; requested tex bitdepth: " << bpp << "\n"; + dxgsg_cat.error() << szErrorMsg << endl; goto error_exit; /////////////////////////////////////////////////////////// - found_matching_format: - - ddsd.ddpfPixelFormat = *pCurPixFmt; - - // Get the device's render target, so we can then use the render target to - // get a ptr to a DDraw object. We need the DirectDraw interface for - // creating surfaces. - - pd3dDevice->GetRenderTarget( &pddsRender ); - pddsRender->GetDDInterface( (VOID**)&pDD ); - pddsRender->Release(); - - ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; - - ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE // Turn on texture management - | DDSCAPS2_HINTSTATIC; // BUGBUG: is this ok for ALL textures? - + found_matching_format: // validate magfilter setting // degrade filtering if no HW support @@ -1480,12 +1344,13 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic ft =_tex->get_magfilter(); if((ft!=Texture::FT_linear) && ft!=Texture::FT_nearest) { - if(ft==Texture::FT_nearest_mipmap_nearest) + // mipmap settings make no sense for magfilter + if(ft==Texture::FT_nearest_mipmap_nearest) ft=Texture::FT_nearest; else ft=Texture::FT_linear; } - if((ft==Texture::FT_linear) && !(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR)) + if((ft==Texture::FT_linear) && !(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)) ft=Texture::FT_nearest; _tex->set_magfilter(ft); @@ -1504,8 +1369,9 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic if(dx_mipmap_everything) { // debug toggle, ok to leave in since its just a creation cost _bHasMipMaps=TRUE; - if(ft != Texture::FT_linear_mipmap_linear) { - dxgsg_cat.spam() << "Forcing mipmap filtering on DX texture [" << _tex->get_name() << "]\n"; + if(dxgsg_cat.is_spam()) { + if(ft != Texture::FT_linear_mipmap_linear) + dxgsg_cat.spam() << "Forcing trilinear mipmapping on DX texture [" << _tex->get_name() << "]\n"; } ft = Texture::FT_linear_mipmap_linear; _tex->set_minfilter(ft); @@ -1518,26 +1384,32 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic ft=Texture::FT_linear; } - assert((pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_NEAREST)!=0); + assert((scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT)!=0); +#define TRILINEAR_MIPMAP_TEXFILTERCAPS (D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MINFLINEAR) + + // do any other filter type degradations necessary switch(ft) { - case Texture::FT_nearest_mipmap_linear: - if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPNEAREST)) - ft=Texture::FT_nearest_mipmap_nearest; - break; - case Texture::FT_linear_mipmap_nearest: - if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR)) - ft=Texture::FT_nearest_mipmap_nearest; - break; case Texture::FT_linear_mipmap_linear: - if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR)) { - if(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR) - ft=Texture::FT_linear_mipmap_nearest; + if((scrn.d3dcaps.TextureFilterCaps & TRILINEAR_MIPMAP_TEXFILTERCAPS)!=TRILINEAR_MIPMAP_TEXFILTERCAPS) { + if(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) + ft=Texture::FT_linear_mipmap_nearest; else ft=Texture::FT_nearest_mipmap_nearest; // if you cant do linear in a level, you probably cant do linear b/w levels, so just do nearest-all } break; + case Texture::FT_nearest_mipmap_linear: + // if we dont have bilinear, do nearest_nearest + if(!((scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT) && + (scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR))) + ft=Texture::FT_nearest_mipmap_nearest; + break; + case Texture::FT_linear_mipmap_nearest: + // if we dont have mip linear, do nearest_nearest + if(!(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)) + ft=Texture::FT_nearest_mipmap_nearest; + break; case Texture::FT_linear: - if(!(pD3DDevDesc->dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR)) + if(!(scrn.d3dcaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)) ft=Texture::FT_nearest; break; } @@ -1547,78 +1419,62 @@ LPDIRECTDRAWSURFACE7 DXTextureContext::CreateTexture(LPDIRECT3DDEVICE7 pd3dDevic uint aniso_degree; aniso_degree=1; - if(pD3DDevDesc->dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANISOTROPY) { + if(scrn.d3dcaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) { aniso_degree=_tex->get_anisotropic_degree(); - if((aniso_degree>pD3DDevDesc->dwMaxAnisotropy) -#ifdef _DEBUG - || dx_force_anisotropic_filtering -#endif - ) - aniso_degree=pD3DDevDesc->dwMaxAnisotropy; + if((aniso_degree>scrn.d3dcaps.MaxAnisotropy) || dx_force_anisotropic_filtering) + aniso_degree=scrn.d3dcaps.MaxAnisotropy; } _tex->set_anisotropic_degree(aniso_degree); + #ifdef _DEBUG dxgsg_cat.spam() << "CreateTexture: setting aniso degree for "<< _tex->get_name() << " to: " << aniso_degree << endl; #endif + UINT cMipLevelCount; + if(_bHasMipMaps) { - // We dont specify mipmapcount, so CreateSurface will auto-create surfs - // for all mipmaps down to 1x1 (if driver supports deep-mipmaps, otherwise Nx1) - ddsd.ddsCaps.dwCaps |= (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX); - dxgsg_cat.debug() << "CreateTexture: generating mipmaps for "<< _tex->get_name() << endl; - } + cMipLevelCount=0; // tell CreateTex to alloc space for all mip levels down to 1x1 - if(pD3DDevDesc->dwDevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) { - // must assign a texture to a specific stage - // for now I'm just going to use stage 0 for all - ddsd.dwTextureStage=0; - ddsd.dwFlags |= DDSD_TEXTURESTAGE; - } - - PRINTVIDMEM(pDD,&ddsd.ddsCaps,"texture surf (includes AGP mem)"); - - // Create a new surface for the texture - if(FAILED( hr = pDD->CreateSurface( &ddsd, &_surface, NULL ) )) { - dxgsg_cat.error() << "CreateTexture failed: pDD->CreateSurface() failed! hr = " << ConvD3DErrorToString(hr) << "\n"; + if(dxgsg_cat.is_debug()) + dxgsg_cat.debug() << "CreateTexture: generating mipmaps for "<< _tex->get_name() << endl; + } else cMipLevelCount=1; + + if(FAILED( hr = scrn.pD3DDevice->CreateTexture(TargetWidth,TargetHeight,cMipLevelCount,0x0, + TargetPixFmt,D3DPOOL_MANAGED,&_pD3DTexture8) )) { + dxgsg_cat.error() << "pD3DDevice->CreateTexture() failed! hr = " << D3DERRORSTRING(hr); goto error_exit; } - -#ifdef _DEBUG - dxgsg_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converted " << ConvNameStrs[ConvNeeded] << " \n"; +#ifdef DO_CUSTOM_CONVERSIONS + _PixBufConversionType=ConvNeeded; #endif - _PixBufConversionType=ConvNeeded; +#ifdef _DEBUG +#ifdef DO_CUSTOM_CONVERSIONS + dxgsg_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting " << ConvNameStrs[ConvNeeded] << " \n"; +#else + dxgsg_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting " << D3DFormatStr(PixBufD3DFmt) << " => " << D3DFormatStr(TargetPixFmt) << endl; +#endif +#endif - hr = FillDDSurfTexturePixels(); + hr = FillDDSurfTexturePixels(TargetWidth,TargetHeight,PixBufD3DFmt); if(FAILED(hr)) { goto error_exit; } - // Done with DDraw - pDD->Release(); - - delete [] pTexPixFmts; - // Return the newly created texture - return _surface; + return _pD3DTexture8; error_exit: + ULONG refcnt; - if(pDD!=NULL) - pDD->Release(); - if(_surface!=NULL) { - _surface->Release(); - _surface = NULL; - } - - delete [] pTexPixFmts; + RELEASE(_pD3DTexture8,dxgsg,"texture",RELEASE_ONCE); return NULL; } HRESULT DXTextureContext:: -FillDDSurfTexturePixels(void) { - +FillDDSurfTexturePixels(DWORD TargetWidth,DWORD TargetHeight,D3DFORMAT PixBufD3DFmt) { + HRESULT hr=E_FAIL; PixelBuffer *pbuf = _texture->get_ram_image(); if (pbuf == (PixelBuffer *)NULL) { dxgsg_cat.fatal() << "CreateTexture: get_ram_image() failed\n"; @@ -1626,6 +1482,59 @@ FillDDSurfTexturePixels(void) { return E_FAIL; } + assert(_pD3DTexture8!=NULL); + + DWORD OrigWidth = (DWORD) pbuf->get_xsize(); + DWORD OrigHeight = (DWORD) pbuf->get_ysize(); + DWORD cNumColorChannels = pbuf->get_num_components(); + + IDirect3DSurface8 *pMipLevel0; + hr=_pD3DTexture8->GetSurfaceLevel(0,&pMipLevel0); + if(FAILED(hr)) { + dxgsg_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", GetSurfaceLevel returns hr = " << D3DERRORSTRING(hr); + return E_FAIL; + } + + RECT SrcSize; + SrcSize.left = SrcSize.top = 0; + SrcSize.right = OrigWidth; + SrcSize.bottom = OrigHeight; + + DWORD Lev0Filter,MipFilterFlags; + + // need filtering if size changes, (also if bitdepth reduced (need dithering)??) + Lev0Filter = D3DX_FILTER_LINEAR | D3DX_FILTER_DITHER; + + // filtering may be done here if texture if targetsize!=origsize + hr=D3DXLoadSurfaceFromMemory(pMipLevel0,(PALETTEENTRY*)NULL,(RECT*)NULL,(LPCVOID) pbuf,PixBufD3DFmt, + OrigWidth*cNumColorChannels,(PALETTEENTRY*)NULL,&SrcSize,Lev0Filter,(D3DCOLOR)0x0); + if(FAILED(hr)) { + dxgsg_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXLoadSurfFromMem returns hr = " << D3DERRORSTRING(hr); + goto exit_FillDDSurf; + } + + if(_bHasMipMaps) { + if(!dx_use_triangle_mipgen_filter) + MipFilterFlags = D3DX_FILTER_BOX; + else MipFilterFlags = D3DX_FILTER_TRIANGLE; + + // MipFilterFlags|= D3DX_FILTER_DITHER; + + hr=D3DXFilterTexture(_pD3DTexture8,(PALETTEENTRY*)NULL,0,MipFilterFlags); + if(FAILED(hr)) { + dxgsg_cat.error() << "FillDDSurfaceTexturePixels failed for "<< _tex->get_name() <<", D3DXFilterTex returns hr = " << D3DERRORSTRING(hr); + goto exit_FillDDSurf; + } + } + + exit_FillDDSurf: + ULONG refcnt; + RELEASE(pMipLevel0,dxgsg,"texture",RELEASE_ONCE); + return hr; + +/* old, custom conversion and mipmap-generation stuff + + HRESULT hr = ConvertPixBuftoDDSurf((ConversionType)_PixBufConversionType,pbuf->_image.p(),_surface); if(FAILED(hr)) { return hr; @@ -1726,7 +1635,7 @@ FillDDSurfTexturePixels(void) { hr = pCurDDSurf->GetAttachedSurface(&ddsCaps, &pMipLevel_DDSurf); if(FAILED(hr)) { - dxgsg_cat.error() << "CreateTexture failed creating mipmaps: GetAttachedSurf hr = " << ConvD3DErrorToString(hr) << "\n"; + dxgsg_cat.error() << "CreateTexture failed creating mipmaps: GetAttachedSurf hr = " << D3DERRORSTRING(hr); delete [] pMipMapPixBufSpace; pCurDDSurf->Release(); return hr; @@ -1781,7 +1690,7 @@ FillDDSurfTexturePixels(void) { hr = pTexturePrev->GetDC(&hTexDC); if(FAILED(hr)) { - dxgsg_cat.error() << "GetDC failed hr = " << ConvD3DErrorToString(hr) << "\n"; + dxgsg_cat.error() << "GetDC failed hr = " << D3DERRORSTRING(hr); break; } @@ -1823,7 +1732,7 @@ FillDDSurfTexturePixels(void) { hr = pTexturePrev->ReleaseDC(hTexDC); if(FAILED(hr)) { - dxgsg_cat.error() << "tex ReleaseDC failed for mip "<get_name() << "], minfilter(" << PandaFilterNameStrs[tex->get_minfilter()] << "), magfilter("<get_magfilter()] << "), anisodeg(" << tex->get_anisotropic_degree() << ")\n"; } -//#endif - _surface = NULL; + + _pD3DTexture8 = NULL; _bHasMipMaps = FALSE; _tex = tex; } diff --git a/panda/src/dxgsg8/dxTextureContext8.h b/panda/src/dxgsg8/dxTextureContext8.h index dc670ce1d1..cee171622b 100644 --- a/panda/src/dxgsg8/dxTextureContext8.h +++ b/panda/src/dxgsg8/dxTextureContext8.h @@ -21,6 +21,8 @@ #include +//#define DO_CUSTOM_CONVERSIONS + #define WIN32_LEAN_AND_MEAN #ifndef STRICT // enable strict type checking in windows.h, see msdn @@ -28,27 +30,41 @@ #endif #include - #include #define D3D_OVERLOADS // get D3DVECTOR '+' operator, etc from d3dtypes.h #include +#include +#include #undef WIN32_LEAN_AND_MEAN + #ifndef D3DERRORSTRING -#define D3DERRORSTRING(HRESULT) " at (" << __FILE__ << ":" << __LINE__"), hr=" << DXGetErrorString8(HRESULT) << ": " << DXGetErrorDescription8(HRESULT) << endl +#define D3DERRORSTRING(HRESULT) " at (" << __FILE__ << ":" << __LINE__ << "), hr=" << DXGetErrorString8(HRESULT) << ": " << DXGetErrorDescription8(HRESULT) << endl #endif #include #include -//#define USE_TEXFMTVEC // doesnt work now, crashes in destructor - -#ifdef USE_TEXFMTVEC -typedef pvector DDPixelFormatVec; -#else -#define MAX_DX_TEXPIXFMTS 20 // should be enough for any card -#endif +typedef struct { + LPDIRECT3DDEVICE8 pD3DDevice; + LPDIRECT3D8 pD3D8; + HWND hWnd; + HMONITOR hMon; + RECT view_rect,clip_rect; + DWORD MaxAvailVidMem; + bool bIsLowVidMemCard; + bool bIsTNLDevice; + bool bIsDX81; + ushort depth_buffer_bitdepth; //GetSurfaceDesc is not reliable so must store this explicitly + ushort CardIDNum; // adapter ID + DWORD dwSupportedScreenDepthsMask; + DWORD SupportedTexFmtsMask; + D3DCAPS8 d3dcaps; + D3DDISPLAYMODE DisplayMode; + D3DPRESENT_PARAMETERS PresParams; // not redundant with DisplayMode since width/height must be 0 for windowed mode + D3DADAPTER_IDENTIFIER8 DXDeviceID; +} DXScreenData; //////////////////////////////////////////////////////////////////// // Class : DXTextureContext @@ -62,23 +78,19 @@ public: DXTextureContext(Texture *tex); ~DXTextureContext(); - LPDIRECTDRAWSURFACE7 _surface; + IDirect3DTexture8 *_pD3DTexture8; Texture *_tex; // ptr to parent, primarily for access to namestr - -// static is_unused_texpixelformat(DDPIXELFORMAT *) - -#ifdef USE_TEXFMTVEC - LPDIRECTDRAWSURFACE7 CreateTexture(LPDIRECT3DDEVICE7 pd3dDevice, DDPixelFormatVec &TexFmts,LPD3DDEVICEDESC7 pD3DDevDesc); -#else - LPDIRECTDRAWSURFACE7 CreateTexture(LPDIRECT3DDEVICE7 pd3dDevice, int cNumTexPixFmts, DDPIXELFORMAT *pTexFmts,LPD3DDEVICEDESC7 pD3DDevDesc); -#endif + IDirect3DTexture8 *CreateTexture(DXScreenData &scrn); bool _bHasMipMaps; + +#ifdef DO_CUSTOM_CONVERSIONS DWORD _PixBufConversionType; // enum ConversionType +#endif // must be public since called from global callback fns void DeleteTexture(void); - HRESULT FillDDSurfTexturePixels(void); + HRESULT FillDDSurfTexturePixels(DWORD TargetWidth,DWORD TargetHeight,D3DFORMAT PixBufD3DFmt); protected: unsigned int get_bits_per_pixel(PixelBuffer::Format format, int *alphbits); @@ -101,6 +113,7 @@ private: static TypeHandle _type_handle; }; +extern HRESULT ConvertD3DSurftoPixBuf(IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf); #endif diff --git a/panda/src/wdxdisplay8/Sources.pp b/panda/src/wdxdisplay8/Sources.pp index 33162da8c5..5a61788401 100644 --- a/panda/src/wdxdisplay8/Sources.pp +++ b/panda/src/wdxdisplay8/Sources.pp @@ -6,7 +6,7 @@ #if $[BUILD_DX8] #begin lib_target - #define TARGET wdxdisplay + #define TARGET wdxdisplay8 #define LOCAL_LIBS \ dxgsg diff --git a/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx b/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx index fdc4bebe7b..67f0507282 100644 --- a/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx +++ b/panda/src/wdxdisplay8/wdxGraphicsWindow8.cxx @@ -20,13 +20,12 @@ #include #include #include -#include "wdxGraphicsWindow.h" -#include "wdxGraphicsPipe.h" -#include "config_wdxdisplay.h" +#include "wdxGraphicsWindow8.h" +#include "wdxGraphicsPipe8.h" +#include "config_wdxdisplay8.h" #include #include - #include #ifdef DO_PSTATS @@ -901,11 +900,10 @@ void wdxGraphicsWindowGroup::CreateWindows(void) { wc.hInstance = hProgramInstance; wc.hCursor = NULL; // for DX8 we handle the cursor messages ourself -#if 0 + // all this must be moved to dx_init, since we need to create DX surface string windows_icon_filename = get_icon_filename().to_os_specific(); - string windows_mono_cursor_filename = get_mono_cursor_filename().to_os_specific(); - string windows_color_cursor_filename = get_color_cursor_filename().to_os_specific(); + if(!windows_icon_filename.empty()) { // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) @@ -921,6 +919,8 @@ void wdxGraphicsWindowGroup::CreateWindows(void) { wc.hIcon = NULL; // use default app icon } + // Note: dx_init() uses the cursor handle to create the dx cursor surface + string windows_color_cursor_filename = get_color_cursor_filename().to_os_specific(); if(!windows_color_cursor_filename.empty()) { // card support for full color non-black/white GDI cursors varies greatly. if the cursor is not supported, @@ -931,9 +931,12 @@ void wdxGraphicsWindowGroup::CreateWindows(void) { // (sync issues?). instead we do mono cursor unless card is known to support 256 color cursors bool bSupportsColorCursor=true; + #if 0 + // remove this check for now, since dx8 should emulate color cursors /* if any card doesnt support color, dont load it*/ - for(int w=0;w<_windows.size();w++) - bSupportsColorCursor &= supports_color_cursors(_windows[w]->_dxgsg->scrn.DXDeviceID); + for(int w=0;w<_windows.size();w++) + bSupportsColorCursor &= supports_color_cursors(_windows[w]->_dxgsg->scrn.DXDeviceID); + #endif if(bSupportsColorCursor) { DWORD load_flags = LR_LOADFROMFILE; @@ -956,44 +959,38 @@ void wdxGraphicsWindowGroup::CreateWindows(void) { } -/* dont need these anymore since we are do mousestuff before window creation - SetClassLongPtr(_mwindow, GCLP_HCURSOR, (LONG_PTR) hNewMouseCursor); - SetCursor(hNewMouseCursor); - - if(_bLoadedCustomCursor) - DestroyCursor(_hMouseCursor); -*/ _bLoadedCustomCursor=true; } } try_mono_cursor: - if((!_bLoadedCustomCursor) && (!windows_mono_cursor_filename.empty())) { - // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) - // if icon is more than 8bpp - - DWORD load_flags = LR_LOADFROMFILE; - - if(dx_full_screen) { - // I think cursors should use LR_CREATEDIBSECTION since they should not be mapped to the device palette (in the case of 256-color cursors) - // since they are not going to be used on the desktop - load_flags |= LR_CREATEDIBSECTION; + if(!_bLoadedCustomCursor) { + string windows_mono_cursor_filename = get_mono_cursor_filename().to_os_specific(); + + if(!windows_mono_cursor_filename.empty()) { + // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) + // if icon is more than 8bpp + + DWORD load_flags = LR_LOADFROMFILE; + + if(dx_full_screen) { + // I think cursors should use LR_CREATEDIBSECTION since they should not be mapped to the device palette (in the case of 256-color cursors) + // since they are not going to be used on the desktop + load_flags |= LR_CREATEDIBSECTION; + } + // loads a .cur fmt file. + _hMouseCursor = (HCURSOR) LoadImage(NULL, windows_mono_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, load_flags); + + if(_hMouseCursor==NULL) { + wdxdisplay_cat.warning() << "windows mono cursor filename '" << windows_mono_cursor_filename << "' not found!!\n"; + } else _bLoadedCustomCursor=true; } - // loads a .cur fmt file. - _hMouseCursor = (HCURSOR) LoadImage(NULL, windows_mono_cursor_filename.c_str(), IMAGE_CURSOR, 0, 0, load_flags); - - if(_hMouseCursor==NULL) { - wdxdisplay_cat.warning() << "windows mono cursor filename '" << windows_mono_cursor_filename << "' not found!!\n"; - } else _bLoadedCustomCursor=true; } if(!_bLoadedCustomCursor) _hMouseCursor = LoadCursor(NULL, DEFAULT_CURSOR); - -#endif - if (!wc_registered) { // We only need to register the window class once per session. wc.hCursor = _hMouseCursor; @@ -1609,6 +1606,10 @@ bool wdxGraphicsWindow::search_for_device(LPDIRECT3D8 pD3D8,DXDeviceInfo *pDevin exit(1); } + if(d3dcaps.MaxStreams==0) { + wdxdisplay_cat.info() << "Warning: video driver predates DX8\n"; + } + if(bWantStencil & (d3dcaps.StencilCaps==0x0)) { wdxdisplay_cat.fatal() << "Stencil ability requested, but device #" << pDevInfo->cardID << " (" << _dxgsg->scrn.DXDeviceID.szDescription<<"), has no stencil capability!\n"; exit(1); @@ -1901,7 +1902,7 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { // LPDIRECTDRAW7 pDD=Display.pDD; // D3DDEVICEDESC7 *pD3DDevDesc=&Display.D3DDevDesc; LPD3DCAPS8 pD3Dcaps = &Display.d3dcaps; - + D3DPRESENT_PARAMETERS* pPresParams = &Display.PresParams; LPDIRECTDRAWSURFACE7 pPrimaryDDSurf,pBackDDSurf,pZDDSurf; LPDIRECT3DDEVICE7 pD3DDevice; RECT view_rect; @@ -1946,8 +1947,6 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { } */ - ResourceManagerDiscardBytes(0); - // DX_DECLARE_CLEAN(DDCAPS,DDCaps); // pDD->GetCaps(&DDCaps,NULL); @@ -1986,7 +1985,6 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { } } - D3DPRESENT_PARAMETERS* pPresParams = &Display.PresParams; pPresParams->Windowed = dx_full_screen; DWORD dwBehaviorFlags=0x0; @@ -2061,8 +2059,6 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { hr = pD3D8->CreateDevice(Display.CardIDNum, D3DDEVTYPE_HAL, _pParentWindowGroup->_hParentWindow, dwBehaviorFlags, pPresParams, &Display.pD3DDevice); - #define IS_16BPP_FORMAT(FMT) (((FMT)>=D3DFMT_R5G6B5)&&((FMT)<=D3DFMT_A1R5G5B5)) - if(FAILED(hr)) { wdxdisplay_cat.fatal() << "D3D CreateDevice failed for device #" << Display.CardIDnum << ", " << D3DERRORSTRING(hr); @@ -2131,6 +2127,11 @@ CreateScreenBuffersAndDevice(DXScreenData &Display) { } } // end create windowed buffers + hr = Display.pD3DDevice->ResourceManagerDiscardBytes(0); + if(hr != DD_OK) { + wdxdisplay_cat.fatal() << "ResourceManagerDiscardBytes failed for device #" << Display.CardIDnum << ", " << D3DERRORSTRING(hr); + } + // clear to transparent black to get rid of visible garbage hr = Display.pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,0,0.0,0); if(hr != DD_OK) {