123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702 |
- #include "pch.h"
- //////////////////////////////////////////////////////////////////////////////
- //
- //
- //
- //////////////////////////////////////////////////////////////////////////////
- class D3DRasterizerImpl : public D3DRasterizer {
- private:
- TRef<DDDevice> m_pdddevice;
- TRef<D3DDevice> m_pd3ddevice;
- TRef<IDirect3DDeviceX> m_pd3dd;
- TRef<IDirect3DViewportX> m_pd3dview;
- PrivateSurface* m_psurface;
- DDSurface* m_pddsurface;
- DWORD m_dwDrawPrimitiveFlags;
- Rect m_rectGuard;
- Rect m_rectClip;
- #ifdef _DEBUG
- bool m_bSurfaceLost;
- void InitializeD3DCall()
- {
- m_bSurfaceLost = false;
- }
- void D3DError(HRESULT hr, const char* pszCall, const char* pszFile, int line, const char* pszModule)
- {
- if (m_bSurfaceLost) {
- // ignore all errors if the surface is lost
- } else {
- if (
- hr == DDERR_SURFACELOST
- || hr == D3DERR_SCENE_BEGIN_FAILED
- ) {
- m_bSurfaceLost = true;
- } else {
- DDError(hr, pszCall, pszFile, line, pszModule);
- }
- }
- }
- #define D3DCall(hr) D3DError(hr, #hr, __FILE__, __LINE__, __MODULE__)
- #else
- void InitializeD3DCall() {}
- void D3DCall(HRESULT hr) {}
- #endif
- public:
- //////////////////////////////////////////////////////////////////////////////
- //
- // Constructor
- //
- //////////////////////////////////////////////////////////////////////////////
- D3DRasterizerImpl(PrivateSurface* psurface) :
- m_psurface(psurface),
- m_dwDrawPrimitiveFlags(
- D3DDP_DONOTUPDATEEXTENTS
- | D3DDP_DONOTCLIP
- )
- {
- CastTo(m_pddsurface, psurface->GetVideoSurface());
- InitializeD3DCall();
- //
- // Tell the device about this rasterizer
- //
- m_pdddevice = m_pddsurface->GetDDDevice();
- m_pdddevice->AddRasterizer(this);
- //
- // Create a D3D device
- //
- m_pd3ddevice = m_pdddevice->CreateD3DDevice(m_pddsurface);
- if (m_pd3ddevice == NULL) {
- return;
- }
- m_pd3dd = m_pd3ddevice->GetD3DDeviceX();
- D3DDeviceDescription d3dddSW;
- D3DDeviceDescription d3dddHW;
- D3DCall(m_pd3dd->GetCaps(&d3dddHW, &d3dddSW));
- #ifndef DREAMCAST
- m_rectGuard =
- Rect(
- d3dddHW.dvGuardBandLeft,
- d3dddHW.dvGuardBandTop,
- d3dddHW.dvGuardBandRight,
- d3dddHW.dvGuardBandBottom
- );
- #endif
- //
- // Create the D3D viewport
- //
- D3DCall(m_pdddevice->GetD3D()->CreateViewport(&m_pd3dview, NULL));
- D3DCall(m_pd3dd->AddViewport(m_pd3dview));
- UpdateViewport();
- //
- // default rendering states
- //
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL));
- }
- bool IsValid()
- {
- return m_pd3ddevice != NULL;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Destructor
- //
- //////////////////////////////////////////////////////////////////////////////
- ~D3DRasterizerImpl()
- {
- m_pdddevice->RemoveRasterizer(this);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Termination
- //
- //////////////////////////////////////////////////////////////////////////////
- void Terminate()
- {
- m_pd3dview = NULL;
- m_pd3dd = NULL;
- }
- TRef<IDirect3DDeviceX> GetD3DDeviceX()
- {
- return m_pd3dd;
- }
- TRef<IDirect3DX> GetD3D()
- {
- return m_pdddevice->GetD3D();
- }
- TRef<IDirect3DViewportX> GetViewport()
- {
- return m_pd3dview;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Change Render target
- //
- //////////////////////////////////////////////////////////////////////////////
- /* , make this work
- void SetSurface(ISurfaceImpl* psurface)
- {
- ZAssert(!m_bRendering);
- m_psurface = psurface;
- D3DCall(m_pd3dd->SetRenderTarget(m_psurface->GetDDS(), 0));
- }
- */
- //////////////////////////////////////////////////////////////////////////////
- //
- // Scene
- //
- //////////////////////////////////////////////////////////////////////////////
- void BeginScene()
- {
- m_pddsurface->BeginScene();
- m_pdddevice->BeginScene();
- D3DCall(m_pd3dd->BeginScene());
- }
- void EndScene()
- {
- m_pddsurface->EndScene();
- //
- // 11/16/99 not checking return codes here since the Permedia 2
- // driver on Win2K returns error every once in a while
- //
- m_pd3dd->EndScene();
- m_pdddevice->EndScene();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Viewport
- //
- //////////////////////////////////////////////////////////////////////////////
- void UpdateViewport()
- {
- const WinPoint& size = m_psurface->GetSize();
- float aspect = (float)size.X() / (float)size.Y();
- D3DVIEWPORT2 view;
- view.dwSize = sizeof(D3DVIEWPORT2);
- view.dwX = 0;
- view.dwY = 0;
- view.dwWidth = (int)size.X();
- view.dwHeight = (int)size.Y();
- view.dvClipX = -1;
- view.dvClipWidth = 2;
- view.dvClipY = aspect;
- view.dvClipHeight = 2 * aspect;
- view.dvMinZ = 0;
- view.dvMaxZ = 1;
- D3DCall(m_pd3dview->SetViewport2(&view));
- D3DCall(m_pd3dd->SetCurrentViewport(m_pd3dview));
- }
- void SetClipRect(const Rect& rectClip)
- {
- m_rectClip = rectClip;
- }
- void ClearZBuffer()
- {
- ZTrace(
- "Clearing ZBuffer ("
- + ZString(m_rectClip.XMin()) + ", "
- + ZString(m_rectClip.YMin()) + ", "
- + ZString(m_rectClip.XMax()) + ", "
- + ZString(m_rectClip.YMax()) + ")"
- );
- D3DRect rect(
- (int)m_rectClip.XMin(),
- (int)m_rectClip.YMin(),
- (int)m_rectClip.XMax(),
- (int)m_rectClip.YMax()
- );
- HRESULT hr = m_pd3dview->Clear(1, &rect, D3DCLEAR_ZBUFFER);
- //
- // This is actually a DDraw call so it's possible it can fail.
- //
- if (hr != DDERR_UNSUPPORTED) {
- D3DCall(hr);
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Attributes
- //
- //////////////////////////////////////////////////////////////////////////////
- bool HasZBuffer()
- {
- return m_pddsurface->HasZBuffer();
- }
- bool Has3DAcceleration()
- {
- return m_pdddevice->GetAllow3DAcceleration();
- }
- Point GetSurfaceSize()
- {
- return Point::Cast(m_pddsurface->GetSize());
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // State
- //
- //////////////////////////////////////////////////////////////////////////////
- void SetTexture(Surface* psurfaceTextureArg)
- {
- PrivateSurface* psurfaceTexture; CastTo(psurfaceTexture, psurfaceTextureArg);
- if (psurfaceTexture != NULL) {
- DDSurface* pddsurfaceTexture; CastTo(pddsurfaceTexture, psurfaceTexture->GetVideoSurface());
- D3DCall(m_pd3dd->SetTexture(
- 0,
- m_pdddevice->GetTextureX(m_pd3ddevice, pddsurfaceTexture)
- ));
- } else {
- D3DCall(m_pd3dd->SetTexture(0, NULL));
- }
- }
- void SetShadeMode(ShadeMode shadeMode)
- {
- switch (shadeMode) {
- case ShadeModeNone:
- case ShadeModeCopy:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_DECAL));
- break;
- case ShadeModeFlat:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE));
- break;
- case ShadeModeGlobalColor:
- case ShadeModeGouraud:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_TEXTUREMAPBLEND, D3DTBLEND_MODULATE));
- break;
- default:
- ZError("Invalid ShadeMode");
- }
- }
- void SetBlendMode(BlendMode blendMode)
- {
- switch (blendMode) {
- case BlendModeSource:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false));
- break;
- case BlendModeAdd:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE));
- break;
- case BlendModeSourceAlpha:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA));
- break;
- default:
- ZError("Invalid BlendMode");
- }
- }
- void SetWrapMode(WrapMode wrapMode)
- {
- switch (wrapMode) {
- case WrapModeNone:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPU, false));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPV, false));
- break;
- case WrapModeUCylinder:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPU, true));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPV, false));
- break;
- case WrapModeVCylinder:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPU, false));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPV, true));
- break;
- case WrapModeTorus:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPU, true));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_WRAPV, true));
- break;
- default:
- ZError("Invalid WrapMode");
- }
- }
- void SetCullMode(CullMode cullMode)
- {
- switch (cullMode) {
- case CullModeNone:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE));
- break;
- case CullModeCW:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW));
- break;
- case CullModeCCW:
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW));
- break;
- case CullModeBoth:
- ZUnimplemented();
- break;
- default:
- ZError("Invalid CullMode");
- }
- }
- void SetZTest(bool bZTest)
- {
- D3DCall(m_pd3dd->SetRenderState(
- D3DRENDERSTATE_ZENABLE,
- HasZBuffer() && bZTest
- ));
- }
- void SetZWrite(bool bZWrite)
- {
- D3DCall(m_pd3dd->SetRenderState(
- D3DRENDERSTATE_ZWRITEENABLE,
- HasZBuffer() && bZWrite
- ));
- }
- void SetLinearFilter(bool bLinearFilter)
- {
- if (bLinearFilter && Has3DAcceleration()) {
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_TEXTUREMAG, D3DFILTER_LINEAR));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_TEXTUREMIN, D3DFILTER_LINEAR));
- } else {
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_TEXTUREMAG, D3DFILTER_NEAREST));
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_TEXTUREMIN, D3DFILTER_NEAREST));
- }
- }
- void SetPerspectiveCorrection(bool bPerspectiveCorrection)
- {
- D3DCall(m_pd3dd->SetRenderState(
- D3DRENDERSTATE_TEXTUREPERSPECTIVE,
- bPerspectiveCorrection || Has3DAcceleration()
- ));
- }
- void SetDither(bool bDither)
- {
- D3DCall(m_pd3dd->SetRenderState(
- D3DRENDERSTATE_DITHERENABLE,
- false //bDither || Has3DAcceleration()
- ));
- }
- void SetColorKey(bool bColorKey)
- {
- D3DCall(m_pd3dd->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, bColorKey));
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Debug
- //
- //////////////////////////////////////////////////////////////////////////////
- void CheckVertices(const VertexScreen* pvertex, int vcount)
- {
- /*
- #ifdef _DEBUG
- {
- const float error = 0.5f;
- for (int index = 0; index < vcount; index++) {
- ZAssert(pvertex[index].x >= m_rectClip.XMin() - error);
- ZAssert(pvertex[index].x <= m_rectClip.XMax() + error);
- ZAssert(pvertex[index].y >= m_rectClip.YMin() - error);
- ZAssert(pvertex[index].y <= m_rectClip.YMax() + error);
- ZAssert(pvertex[index].z >= 0.0f - error);
- ZAssert(pvertex[index].z <= 1.0f + error);
- }
- }
- #endif
- */
- VertexScreen* pcheck = (VertexScreen*)pvertex;
- for (int index = 0; index < vcount; index++) {
- if (pcheck[index].x < m_rectClip.XMin()) {
- pcheck[index].x = m_rectClip.XMin();
- } else if (pcheck[index].x > m_rectClip.XMax()) {
- pcheck[index].x = m_rectClip.XMax();
- }
- if (pcheck[index].y < m_rectClip.YMin()) {
- pcheck[index].y = m_rectClip.YMin();
- } else if (pcheck[index].y > m_rectClip.YMax()) {
- pcheck[index].y = m_rectClip.YMax();
- }
- if (pcheck[index].z < 0) {
- pcheck[index].z = 0;
- } else if (pcheck[index].z > 1) {
- pcheck[index].z = 1;
- }
- }
- }
- void CheckIndices(const MeshIndex* pindex, int icount, int vcount)
- {
- #ifdef _DEBUG
- for (int index = 0; index < icount; index++) {
- ZAssert(pindex[index] >= 0 && pindex[index] < vcount);
- }
- #endif
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Rendering
- //
- //////////////////////////////////////////////////////////////////////////////
- void DrawTrianglesD3D(const D3DLVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
- {
- D3DCall(m_pd3dd->DrawIndexedPrimitive(
- D3DPT_TRIANGLELIST,
- D3DFVF_LVERTEX,
- (void*)pvertex,
- vcount,
- (MeshIndex*)pindex,
- icount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawLinesD3D(const D3DLVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
- {
- D3DCall(m_pd3dd->DrawIndexedPrimitive(
- D3DPT_LINELIST,
- D3DFVF_LVERTEX,
- (void*)pvertex,
- vcount,
- (MeshIndex*)pindex,
- icount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawPointsD3D(const D3DLVertex* pvertex, int vcount)
- {
- D3DCall(m_pd3dd->DrawPrimitive(
- D3DPT_POINTLIST,
- D3DFVF_LVERTEX,
- (void*)pvertex,
- vcount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawTrianglesD3D(const D3DVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
- {
- D3DCall(m_pd3dd->DrawIndexedPrimitive(
- D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX,
- (void*)pvertex,
- vcount,
- (MeshIndex*)pindex,
- icount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawLinesD3D(const D3DVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
- {
- D3DCall(m_pd3dd->DrawIndexedPrimitive(
- D3DPT_LINELIST,
- D3DFVF_VERTEX,
- (void*)pvertex,
- vcount,
- (MeshIndex*)pindex,
- icount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawPointsD3D(const D3DVertex* pvertex, int vcount)
- {
- D3DCall(m_pd3dd->DrawPrimitive(
- D3DPT_POINTLIST,
- D3DFVF_VERTEX,
- (void*)pvertex,
- vcount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawTriangles(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
- {
- CheckVertices(pvertex, vcount);
- CheckIndices(pindex, icount, vcount);
- D3DCall(m_pd3dd->DrawIndexedPrimitive(
- D3DPT_TRIANGLELIST,
- D3DFVF_TLVERTEX,
- (void*)pvertex,
- vcount,
- (MeshIndex*)pindex,
- icount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawLines(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
- {
- CheckVertices(pvertex, vcount);
- CheckIndices(pindex, icount, vcount);
- D3DCall(m_pd3dd->DrawIndexedPrimitive(
- D3DPT_LINELIST,
- D3DFVF_TLVERTEX,
- (void*)pvertex,
- vcount,
- (MeshIndex*)pindex,
- icount,
- m_dwDrawPrimitiveFlags
- ));
- }
- void DrawPoints(const VertexScreen* pvertex, int vcount)
- {
- if (true) {
- PixelFormat* ppf = m_psurface->GetPixelFormat();
- int pitch = m_psurface->GetPitch();
- BYTE* pdata = m_psurface->GetWritablePointer();
- ZAssert(ppf->PixelBytes() == 2 );
- ZAssert(ppf->RedSize() == 0x1f);
- ZAssert(ppf->BlueSize() == 0x1f);
- if (ppf->GreenSize() == 0x1f) {
- // 555
- for (int index = 0; index < vcount; index++) {
- BYTE* ppixel =
- pdata
- + FloorInt(pvertex[index].x) * 2
- + FloorInt(pvertex[index].y) * pitch;
- DWORD color = pvertex[index].color;
- WORD
- pixel =
- (WORD)(
- ((color >> 9) & 0x7c00)
- | ((color >> 6) & 0x03e0)
- | ((color >> 3) & 0x001f)
- );
- *(WORD*)(ppixel) = pixel;
- }
- } else {
- // 565
- ZAssert(ppf->GreenSize() == 0x3f);
- for (int index = 0; index < vcount; index++) {
- BYTE* ppixel =
- pdata
- + FloorInt(pvertex[index].x) * 2
- + FloorInt(pvertex[index].y) * pitch;
- DWORD color = pvertex[index].color;
- WORD pixel =
- (WORD)(
- ((color >> 8) & 0xf800)
- | ((color >> 5) & 0x07e0)
- | ((color >> 3) & 0x001f)
- );
- *(WORD*)(ppixel) = pixel;
- }
- }
- m_psurface->ReleasePointer();
- } else {
- CheckVertices(pvertex, vcount);
- D3DCall(m_pd3dd->DrawPrimitive(
- D3DPT_POINTLIST,
- D3DFVF_TLVERTEX,
- (void*)pvertex,
- vcount,
- m_dwDrawPrimitiveFlags
- ));
- }
- }
- };
- TRef<D3DRasterizer> CreateD3DRasterizer(PrivateSurface* psurface)
- {
- TRef<D3DRasterizer> prasterizer = new D3DRasterizerImpl(psurface);
- return prasterizer->IsValid() ? prasterizer : NULL;
- }
|