/***************************************************************************\ Blits one surface to another. \**************************************************************************/ int IMR_DirectXInterface::Blit(LPDIRECTDRAWSURFACE4 Source, LPDIRECTDRAWSURFACE4 Target) { RECT Dest; HRESULT ddrval; DDSURFACEDESC2 SourceDesc, TargetDesc; int BltX, BltY; // Make sure DirectDraw is active: if (!Flags.DirectDrawActive) { IMR_SetErrorText("IMR_DirectXInterface::Blit(): Interface not initialized!"); return IMRERR_NOTREADY; } // Make sure we have surfaces: if (!Source || !Target) { IMR_SetErrorText("IMR_DirectXInterface::Blit(): NULL surface(s) specified!"); return IMRERR_NODATA; } // Get a surface descriptor for the surfaces: TargetDesc.dwSize = sizeof(TargetDesc); Target->GetSurfaceDesc(&TargetDesc); SourceDesc.dwSize = sizeof(SourceDesc); Source->GetSurfaceDesc(&SourceDesc); // Now find the blit coords: BltX = (TargetDesc.dwWidth / 2) - (SourceDesc.dwWidth / 2); BltY = (TargetDesc.dwHeight / 2) - (SourceDesc.dwHeight / 2); // Blit the surface: ddrval = Target->BltFast(BltX, BltY, Source, NULL, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT); // If we lost the surface, return failure: if (ddrval == DDERR_SURFACELOST) { Restore(Source); Restore(Target); IMR_SetErrorText("IMR_DirectXInterface::Blit(): Lost surface!"); return IMRERR_DIRECTX; } // Return ok: return IMR_OK; }
/***************************************************************************\ Prepares all surfaces for rendering. \***************************************************************************/ void IMR_DirectXInterface::Prepare_Frame(LPDIRECTDRAWSURFACE4 Target) { D3DRECT ClearRect; DDSURFACEDESC2 TargetDesc; // Make sure we have a target surface and a viewport interface: if (!Direct3DViewport || !Target) return; // Get target size info: TargetDesc.dwSize = sizeof(TargetDesc); Target->GetSurfaceDesc(&TargetDesc); // Setup the area to clear: ClearRect.x1 = 0; ClearRect.y1 = 0; ClearRect.x2 = TargetDesc.dwWidth; ClearRect.y2 = TargetDesc.dwHeight; // Clear the viewport: Direct3DViewport->Clear2(1, &ClearRect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, (float)1.0, NULL); }
/***************************************************************************\ Initializes Direct3D. \***************************************************************************/ int IMR_DirectXInterface::InitDirect3D(LPDIRECTDRAWSURFACE4 Target) { int err; D3DVIEWPORT2 PortInitData; DDPIXELFORMAT ZBufferPixelFormat; DDSURFACEDESC2 ZBufferDesc, TargetDesc; D3DDEVICEDESC HALDesc, HELDesc; int DeviceFound = FALSE, FormatFound = FALSE; // Make sure DirectDraw is active: if (!Flags.DirectDrawActive) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): DirectDraw not initialized!"); return IMRERR_NOTREADY; } // Make sure we have a target surface: if (!Target) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): NULL target specified!"); return IMRERR_NODATA; } // Get target size info: TargetDesc.dwSize = sizeof(TargetDesc); Target->GetSurfaceDesc(&TargetDesc); // Release all Direct3D interfaces: if (Direct3DViewport) { Direct3DViewport->Release(); Direct3DViewport = NULL; } if (Direct3DDevice) { Direct3DDevice->Release(); Direct3DDevice = NULL; } if (Direct3D) { Direct3D->Release(); Direct3D = NULL; } Flags.Direct3DActive = 0; // Now get a new Direct3D3 interface: DirectDraw->QueryInterface(IID_IDirect3D3, (void **)&Direct3D); if (err != DD_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 1 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Enumerate the devices and find one to use: err = Direct3D->EnumDevices(DeviceCallback, &DeviceFound); if (err != D3D_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 2 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } if (!DeviceFound) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): No usable rendering devices!"); return IMRERR_DIRECTX; } // Find a pixel format for our z-buffer and verify that it worked: Direct3D->EnumZBufferFormats(Direct3DDeviceInfo.Guid, ZBufferCallback, (void *)&ZBufferPixelFormat); if (ZBufferPixelFormat.dwSize != sizeof(DDPIXELFORMAT)) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): Couldn't find Z-Buffer pixel format!"); return IMRERR_DIRECTX; } // Create a Z-Buffer: ZeroMemory((void *)&ZBufferDesc, sizeof(ZBufferDesc)); ZBufferDesc.dwSize = sizeof(ZBufferDesc); ZBufferDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; ZBufferDesc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; ZBufferDesc.dwWidth = TargetDesc.dwWidth; ZBufferDesc.dwHeight = TargetDesc.dwHeight; memcpy(&ZBufferDesc.ddpfPixelFormat, &ZBufferPixelFormat, sizeof(DDPIXELFORMAT)); if (IsEqualIID(Direct3DDeviceInfo.Guid, IID_IDirect3DHALDevice)) ZBufferDesc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; else ZBufferDesc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; err = DirectDraw->CreateSurface(&ZBufferDesc, &DDZBuffer, NULL); if (err != DD_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 3 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Now attach the Z-buffer to the target surface: err = Target->AddAttachedSurface(DDZBuffer); if (err != DD_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 4 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Now create the device: err = Direct3D->CreateDevice(Direct3DDeviceInfo.Guid, Target, &Direct3DDevice, NULL); if (err != D3D_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 5 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Setup the device: Direct3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); Direct3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD); Direct3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); Direct3DDevice->SetLightState(D3DLIGHTSTATE_MATERIAL, NULL); // Make sure this device can handle our textures: Direct3DDevice->EnumTextureFormats(TextureFormatCallback, (void *)&FormatFound); if (!FormatFound) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): No acceptable texture formats found!"); return IMRERR_DIRECTX; } // Now create a viewport init structure: ZeroMemory(&PortInitData, sizeof(D3DVIEWPORT2)); PortInitData.dwSize = sizeof(D3DVIEWPORT2); PortInitData.dwX = 0; PortInitData.dwY = 0; PortInitData.dwWidth = TargetDesc.dwWidth; PortInitData.dwHeight = TargetDesc.dwHeight; PortInitData.dvClipX = 0; PortInitData.dvClipY = 0; PortInitData.dvClipWidth = TargetDesc.dwWidth; PortInitData.dvClipHeight = TargetDesc.dwHeight; PortInitData.dvMinZ = 0.0f; PortInitData.dvMaxZ = 1.0f; // Create the viewport: err = Direct3D->CreateViewport(&Direct3DViewport, NULL); if (err != D3D_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 6 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Associate the viewport with the device: Direct3DDevice->AddViewport(Direct3DViewport); // Set the parameters for the new viewport: Direct3DViewport->SetViewport2(&PortInitData); // Set the current viewport for the device: Direct3DDevice->SetCurrentViewport(Direct3DViewport); // Flag that Direct3D is up and running: Flags.Direct3DActive = 1; // Whew! That's done, so return success: return IMR_OK; }