mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-02-03 12:31:15 +00:00
miniwin: Refactor D3DRM
This commit is contained in:
parent
035ba477e7
commit
14c564758a
@ -97,6 +97,8 @@ add_library(miniwin STATIC EXCLUDE_FROM_ALL
|
|||||||
miniwin/miniwin/src/miniwin_ddsurface.cpp
|
miniwin/miniwin/src/miniwin_ddsurface.cpp
|
||||||
miniwin/miniwin/src/miniwin_ddraw.cpp
|
miniwin/miniwin/src/miniwin_ddraw.cpp
|
||||||
miniwin/miniwin/src/miniwin_d3drm.cpp
|
miniwin/miniwin/src/miniwin_d3drm.cpp
|
||||||
|
miniwin/miniwin/src/miniwin_d3drmdevice.cpp
|
||||||
|
miniwin/miniwin/src/miniwin_d3drmviewport.cpp
|
||||||
)
|
)
|
||||||
# Force reported render mods from MiniWin
|
# Force reported render mods from MiniWin
|
||||||
target_compile_definitions(miniwin PRIVATE MINIWIN_PIXELFORMAT=SDL_PIXELFORMAT_RGB565)
|
target_compile_definitions(miniwin PRIVATE MINIWIN_PIXELFORMAT=SDL_PIXELFORMAT_RGB565)
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
// Enable bitwise ops only for enum classes with the ENABLE_BITMASK_OPERATORS trait
|
// Enable bitwise ops only for enum classes with the ENABLE_BITMASK_OPERATORS trait
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
// --- Typedefs ---
|
// --- Typedefs ---
|
||||||
typedef float D3DVAL;
|
typedef float D3DVAL;
|
||||||
typedef void* LPD3DRM_APPDATA;
|
typedef void* LPD3DRM_APPDATA;
|
||||||
typedef unsigned int D3DRMGROUPINDEX;
|
typedef DWORD D3DRMGROUPINDEX;
|
||||||
typedef DWORD D3DCOLOR, *LPD3DCOLOR;
|
typedef DWORD D3DCOLOR, *LPD3DCOLOR;
|
||||||
typedef float D3DVALUE, *LPD3DVALUE;
|
typedef float D3DVALUE, *LPD3DVALUE;
|
||||||
|
|
||||||
@ -116,16 +116,16 @@ typedef struct D3DRMPALETTEENTRY {
|
|||||||
} D3DRMPALETTEENTRY;
|
} D3DRMPALETTEENTRY;
|
||||||
|
|
||||||
typedef struct D3DRMIMAGE {
|
typedef struct D3DRMIMAGE {
|
||||||
unsigned int width, height, depth, bytes_per_line;
|
DWORD width, height, depth, bytes_per_line;
|
||||||
unsigned int red_mask, green_mask, blue_mask, alpha_mask;
|
DWORD red_mask, green_mask, blue_mask, alpha_mask;
|
||||||
unsigned int palette_size;
|
DWORD palette_size;
|
||||||
D3DRMPALETTEENTRY* palette;
|
D3DRMPALETTEENTRY* palette;
|
||||||
void* buffer1;
|
void* buffer1;
|
||||||
void* buffer2;
|
void* buffer2;
|
||||||
void* data;
|
void* data;
|
||||||
int rgb;
|
int rgb;
|
||||||
int aspectx, aspecty;
|
int aspectx, aspecty;
|
||||||
unsigned int format;
|
DWORD format;
|
||||||
} D3DRMIMAGE;
|
} D3DRMIMAGE;
|
||||||
|
|
||||||
typedef struct D3DRMMATRIX4D {
|
typedef struct D3DRMMATRIX4D {
|
||||||
@ -179,11 +179,11 @@ struct IDirect3DRMMesh : public IDirect3DRMVisual {
|
|||||||
) = 0;
|
) = 0;
|
||||||
virtual HRESULT GetGroup(
|
virtual HRESULT GetGroup(
|
||||||
int groupIndex,
|
int groupIndex,
|
||||||
unsigned int* vertexCount,
|
DWORD* vertexCount,
|
||||||
unsigned int* faceCount,
|
DWORD* faceCount,
|
||||||
unsigned int* vertexPerFace,
|
DWORD* vertexPerFace,
|
||||||
DWORD* dataSize,
|
DWORD* dataSize,
|
||||||
unsigned int* data
|
DWORD* data
|
||||||
) = 0;
|
) = 0;
|
||||||
virtual HRESULT SetGroupColor(int groupIndex, D3DCOLOR color) = 0;
|
virtual HRESULT SetGroupColor(int groupIndex, D3DCOLOR color) = 0;
|
||||||
virtual HRESULT SetGroupColorRGB(int groupIndex, float r, float g, float b) = 0;
|
virtual HRESULT SetGroupColorRGB(int groupIndex, float r, float g, float b) = 0;
|
||||||
@ -284,8 +284,8 @@ struct IDirect3DRMViewport : public IDirect3DRMObject {
|
|||||||
virtual D3DVALUE GetBack() = 0;
|
virtual D3DVALUE GetBack() = 0;
|
||||||
virtual HRESULT SetField(D3DVALUE field) = 0;
|
virtual HRESULT SetField(D3DVALUE field) = 0;
|
||||||
virtual D3DVALUE GetField() = 0;
|
virtual D3DVALUE GetField() = 0;
|
||||||
virtual int GetWidth() = 0;
|
virtual DWORD GetWidth() = 0;
|
||||||
virtual int GetHeight() = 0;
|
virtual DWORD GetHeight() = 0;
|
||||||
virtual HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) = 0;
|
virtual HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) = 0;
|
||||||
virtual HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) = 0;
|
virtual HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) = 0;
|
||||||
virtual HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) = 0;
|
virtual HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) = 0;
|
||||||
@ -305,11 +305,11 @@ struct IDirect3DRMWinDevice : virtual public IDirect3DRMObject {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct IDirect3DRMDevice : virtual public IDirect3DRMObject {
|
struct IDirect3DRMDevice : virtual public IDirect3DRMObject {
|
||||||
virtual unsigned int GetWidth() = 0;
|
virtual DWORD GetWidth() = 0;
|
||||||
virtual unsigned int GetHeight() = 0;
|
virtual DWORD GetHeight() = 0;
|
||||||
virtual HRESULT SetBufferCount(int count) = 0;
|
virtual HRESULT SetBufferCount(int count) = 0;
|
||||||
virtual HRESULT GetBufferCount() = 0;
|
virtual HRESULT GetBufferCount() = 0;
|
||||||
virtual HRESULT SetShades(unsigned int shadeCount) = 0;
|
virtual HRESULT SetShades(DWORD shadeCount) = 0;
|
||||||
virtual HRESULT GetShades() = 0;
|
virtual HRESULT GetShades() = 0;
|
||||||
virtual HRESULT SetQuality(D3DRMRENDERQUALITY quality) = 0;
|
virtual HRESULT SetQuality(D3DRMRENDERQUALITY quality) = 0;
|
||||||
virtual D3DRMRENDERQUALITY GetQuality() = 0;
|
virtual D3DRMRENDERQUALITY GetQuality() = 0;
|
||||||
@ -353,8 +353,8 @@ struct IDirect3DRM : virtual public IUnknown {
|
|||||||
int height,
|
int height,
|
||||||
IDirect3DRMViewport** outViewport
|
IDirect3DRMViewport** outViewport
|
||||||
) = 0;
|
) = 0;
|
||||||
virtual HRESULT SetDefaultTextureShades(unsigned int count) = 0;
|
virtual HRESULT SetDefaultTextureShades(DWORD count) = 0;
|
||||||
virtual HRESULT SetDefaultTextureColors(unsigned int count) = 0;
|
virtual HRESULT SetDefaultTextureColors(DWORD count) = 0;
|
||||||
};
|
};
|
||||||
typedef IDirect3DRM *LPDIRECT3DRM, **LPLPDIRECT3DRM;
|
typedef IDirect3DRM *LPDIRECT3DRM, **LPLPDIRECT3DRM;
|
||||||
|
|
||||||
|
|||||||
76
miniwin/miniwin/src/include/miniwin_d3drm_p.h
Normal file
76
miniwin/miniwin/src/include/miniwin_d3drm_p.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "miniwin_d3drm.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
typedef struct PositionColorVertex {
|
||||||
|
float x, y, z;
|
||||||
|
Uint8 r, g, b, a;
|
||||||
|
} PositionColorVertex;
|
||||||
|
|
||||||
|
template <typename InterfaceType, typename ArrayInterface>
|
||||||
|
class Direct3DRMArrayBase : public ArrayInterface {
|
||||||
|
public:
|
||||||
|
~Direct3DRMArrayBase() override
|
||||||
|
{
|
||||||
|
for (auto* item : items) {
|
||||||
|
if (item) {
|
||||||
|
item->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DWORD GetSize() override { return static_cast<DWORD>(items.size()); }
|
||||||
|
HRESULT AddElement(InterfaceType* in) override
|
||||||
|
{
|
||||||
|
if (!in) {
|
||||||
|
return DDERR_INVALIDPARAMS;
|
||||||
|
}
|
||||||
|
in->AddRef();
|
||||||
|
items.push_back(in);
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
HRESULT GetElement(DWORD index, InterfaceType** out) override
|
||||||
|
{
|
||||||
|
if (index >= items.size()) {
|
||||||
|
return DDERR_INVALIDPARAMS;
|
||||||
|
}
|
||||||
|
*out = static_cast<InterfaceType*>(items[index]);
|
||||||
|
if (*out) {
|
||||||
|
(*out)->AddRef();
|
||||||
|
}
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
HRESULT DeleteElement(InterfaceType* element) override
|
||||||
|
{
|
||||||
|
auto it = std::find(items.begin(), items.end(), element);
|
||||||
|
if (it == items.end()) {
|
||||||
|
return DDERR_INVALIDPARAMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*it)->Release();
|
||||||
|
items.erase(it);
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<InterfaceType*> items;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Direct3DRMFrameArrayImpl : public Direct3DRMArrayBase<IDirect3DRMFrame, IDirect3DRMFrameArray> {
|
||||||
|
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Direct3DRMLightArrayImpl : public Direct3DRMArrayBase<IDirect3DRMLight, IDirect3DRMLightArray> {
|
||||||
|
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Direct3DRMViewportArrayImpl : public Direct3DRMArrayBase<IDirect3DRMViewport, IDirect3DRMViewportArray> {
|
||||||
|
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Direct3DRMVisualArrayImpl : public Direct3DRMArrayBase<IDirect3DRMVisual, IDirect3DRMVisualArray> {
|
||||||
|
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
||||||
|
};
|
||||||
38
miniwin/miniwin/src/include/miniwin_d3drmdevice_p.h
Normal file
38
miniwin/miniwin/src/include/miniwin_d3drmdevice_p.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "miniwin_d3drm.h"
|
||||||
|
#include "miniwin_d3drmobject_p.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
struct Direct3DRMDevice2Impl : public Direct3DRMObjectBase<IDirect3DRMDevice2> {
|
||||||
|
Direct3DRMDevice2Impl(DWORD width, DWORD height, SDL_GPUDevice* device);
|
||||||
|
~Direct3DRMDevice2Impl() override;
|
||||||
|
DWORD GetWidth() override;
|
||||||
|
DWORD GetHeight() override;
|
||||||
|
HRESULT SetBufferCount(int count) override;
|
||||||
|
HRESULT GetBufferCount() override;
|
||||||
|
HRESULT SetShades(DWORD shadeCount) override;
|
||||||
|
HRESULT GetShades() override;
|
||||||
|
HRESULT SetQuality(D3DRMRENDERQUALITY quality) override;
|
||||||
|
D3DRMRENDERQUALITY GetQuality() override;
|
||||||
|
HRESULT SetDither(int dither) override;
|
||||||
|
HRESULT GetDither() override;
|
||||||
|
HRESULT SetTextureQuality(D3DRMTEXTUREQUALITY quality) override;
|
||||||
|
D3DRMTEXTUREQUALITY GetTextureQuality() override;
|
||||||
|
HRESULT SetRenderMode(D3DRMRENDERMODE mode) override;
|
||||||
|
D3DRMRENDERMODE GetRenderMode() override;
|
||||||
|
/**
|
||||||
|
* @brief Recalculating light positions, animation updates, etc.
|
||||||
|
*/
|
||||||
|
HRESULT Update() override;
|
||||||
|
HRESULT AddViewport(IDirect3DRMViewport* viewport) override;
|
||||||
|
HRESULT GetViewports(IDirect3DRMViewportArray** ppViewportArray) override;
|
||||||
|
|
||||||
|
SDL_GPUDevice* m_device;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DWORD m_width;
|
||||||
|
DWORD m_height;
|
||||||
|
IDirect3DRMViewportArray* m_viewports;
|
||||||
|
};
|
||||||
70
miniwin/miniwin/src/include/miniwin_d3drmobject_p.h
Normal file
70
miniwin/miniwin/src/include/miniwin_d3drmobject_p.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "miniwin_d3drm.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Direct3DRMObjectBase : public T {
|
||||||
|
ULONG Release() override
|
||||||
|
{
|
||||||
|
if (IUnknown::m_refCount == 1) {
|
||||||
|
for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) {
|
||||||
|
it->first(this, it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_free(m_name);
|
||||||
|
return this->T::Release();
|
||||||
|
}
|
||||||
|
HRESULT AddDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override
|
||||||
|
{
|
||||||
|
m_callbacks.push_back(std::make_pair(callback, arg));
|
||||||
|
return D3DRM_OK;
|
||||||
|
}
|
||||||
|
HRESULT DeleteDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override
|
||||||
|
{
|
||||||
|
for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) {
|
||||||
|
if (it->first == callback && it->second == arg) {
|
||||||
|
m_callbacks.erase(it);
|
||||||
|
return D3DRM_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return D3DRMERR_NOTFOUND;
|
||||||
|
}
|
||||||
|
HRESULT SetAppData(LPD3DRM_APPDATA appData) override
|
||||||
|
{
|
||||||
|
m_appData = appData;
|
||||||
|
return D3DRM_OK;
|
||||||
|
}
|
||||||
|
LPVOID GetAppData() override { return m_appData; }
|
||||||
|
HRESULT SetName(const char* name) override
|
||||||
|
{
|
||||||
|
SDL_free(m_name);
|
||||||
|
m_name = NULL;
|
||||||
|
if (name) {
|
||||||
|
m_name = SDL_strdup(name);
|
||||||
|
}
|
||||||
|
return D3DRM_OK;
|
||||||
|
}
|
||||||
|
HRESULT GetName(DWORD* size, char* name) override
|
||||||
|
{
|
||||||
|
if (!size) {
|
||||||
|
return DDERR_INVALIDPARAMS;
|
||||||
|
}
|
||||||
|
const char* s = m_name ? m_name : "";
|
||||||
|
size_t l = SDL_strlen(s);
|
||||||
|
if (name) {
|
||||||
|
SDL_strlcpy(name, s, *size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*size = l + 1;
|
||||||
|
}
|
||||||
|
return D3DRM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<D3DRMOBJECTCALLBACK, void*>> m_callbacks;
|
||||||
|
LPD3DRM_APPDATA m_appData = nullptr;
|
||||||
|
char* m_name = nullptr;
|
||||||
|
};
|
||||||
56
miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h
Normal file
56
miniwin/miniwin/src/include/miniwin_d3drmviewport_p.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "miniwin_d3drm.h"
|
||||||
|
#include "miniwin_d3drmdevice_p.h"
|
||||||
|
#include "miniwin_d3drmobject_p.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
struct Direct3DRMViewportImpl : public Direct3DRMObjectBase<IDirect3DRMViewport> {
|
||||||
|
Direct3DRMViewportImpl(
|
||||||
|
DWORD width,
|
||||||
|
DWORD height,
|
||||||
|
SDL_GPUDevice* device,
|
||||||
|
SDL_GPUTexture* transferTexture,
|
||||||
|
SDL_GPUTransferBuffer* downloadTransferBuffer,
|
||||||
|
SDL_GPUGraphicsPipeline* pipeline
|
||||||
|
);
|
||||||
|
~Direct3DRMViewportImpl() override;
|
||||||
|
HRESULT Render(IDirect3DRMFrame* group) override;
|
||||||
|
/**
|
||||||
|
* @brief Blit the render back to our backbuffer
|
||||||
|
*/
|
||||||
|
HRESULT ForceUpdate(int x, int y, int w, int h) override;
|
||||||
|
HRESULT Clear() override;
|
||||||
|
HRESULT SetCamera(IDirect3DRMFrame* camera) override;
|
||||||
|
HRESULT GetCamera(IDirect3DRMFrame** camera) override;
|
||||||
|
HRESULT SetProjection(D3DRMPROJECTIONTYPE type) override;
|
||||||
|
D3DRMPROJECTIONTYPE GetProjection() override;
|
||||||
|
HRESULT SetFront(D3DVALUE z) override;
|
||||||
|
D3DVALUE GetFront() override;
|
||||||
|
HRESULT SetBack(D3DVALUE z) override;
|
||||||
|
D3DVALUE GetBack() override;
|
||||||
|
HRESULT SetField(D3DVALUE field) override;
|
||||||
|
D3DVALUE GetField() override;
|
||||||
|
DWORD GetWidth() override;
|
||||||
|
DWORD GetHeight() override;
|
||||||
|
HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) override;
|
||||||
|
HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override;
|
||||||
|
HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override;
|
||||||
|
void CloseDevice();
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void FreeDeviceResources();
|
||||||
|
int m_vertexCount;
|
||||||
|
bool m_updated = false;
|
||||||
|
DWORD m_width;
|
||||||
|
DWORD m_height;
|
||||||
|
IDirect3DRMFrame* m_camera = nullptr;
|
||||||
|
SDL_GPUDevice* m_device;
|
||||||
|
SDL_GPUGraphicsPipeline* m_pipeline;
|
||||||
|
SDL_GPUTexture* m_transferTexture;
|
||||||
|
SDL_GPUTransferBuffer* m_downloadTransferBuffer;
|
||||||
|
SDL_GPUBuffer* m_vertexBuffer;
|
||||||
|
SDL_Surface* m_renderedImage = nullptr;
|
||||||
|
};
|
||||||
@ -1,81 +1,12 @@
|
|||||||
#include "miniwin_d3drm.h"
|
#include "miniwin_d3drm.h"
|
||||||
|
|
||||||
#include "miniwin_ddsurface_p.h"
|
|
||||||
#include "ShaderIndex.h"
|
#include "ShaderIndex.h"
|
||||||
|
#include "miniwin_d3drm_p.h"
|
||||||
|
#include "miniwin_d3drmobject_p.h"
|
||||||
|
#include "miniwin_d3drmviewport_p.h"
|
||||||
|
#include "miniwin_ddsurface_p.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <algorithm>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
typedef struct PositionColorVertex {
|
|
||||||
float x, y, z;
|
|
||||||
Uint8 r, g, b, a;
|
|
||||||
} PositionColorVertex;
|
|
||||||
|
|
||||||
template <typename InterfaceType, typename ArrayInterface>
|
|
||||||
class Direct3DRMArrayBase : public ArrayInterface {
|
|
||||||
public:
|
|
||||||
~Direct3DRMArrayBase() override
|
|
||||||
{
|
|
||||||
for (auto* item : items) {
|
|
||||||
if (item) {
|
|
||||||
item->Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DWORD GetSize() override { return static_cast<DWORD>(items.size()); }
|
|
||||||
HRESULT AddElement(InterfaceType* in) override
|
|
||||||
{
|
|
||||||
if (!in) {
|
|
||||||
return DDERR_INVALIDPARAMS;
|
|
||||||
}
|
|
||||||
in->AddRef();
|
|
||||||
items.push_back(in);
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
HRESULT GetElement(DWORD index, InterfaceType** out) override
|
|
||||||
{
|
|
||||||
if (index >= items.size()) {
|
|
||||||
return DDERR_INVALIDPARAMS;
|
|
||||||
}
|
|
||||||
*out = static_cast<InterfaceType*>(items[index]);
|
|
||||||
if (*out) {
|
|
||||||
(*out)->AddRef();
|
|
||||||
}
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
HRESULT DeleteElement(InterfaceType* element) override
|
|
||||||
{
|
|
||||||
auto it = std::find(items.begin(), items.end(), element);
|
|
||||||
if (it == items.end()) {
|
|
||||||
return DDERR_INVALIDPARAMS;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*it)->Release();
|
|
||||||
items.erase(it);
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<InterfaceType*> items;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Direct3DRMFrameArrayImpl : public Direct3DRMArrayBase<IDirect3DRMFrame, IDirect3DRMFrameArray> {
|
|
||||||
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Direct3DRMLightArrayImpl : public Direct3DRMArrayBase<IDirect3DRMLight, IDirect3DRMLightArray> {
|
|
||||||
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Direct3DRMViewportArrayImpl : public Direct3DRMArrayBase<IDirect3DRMViewport, IDirect3DRMViewportArray> {
|
|
||||||
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Direct3DRMVisualArrayImpl : public Direct3DRMArrayBase<IDirect3DRMVisual, IDirect3DRMVisualArray> {
|
|
||||||
using Direct3DRMArrayBase::Direct3DRMArrayBase;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PickRecord {
|
struct PickRecord {
|
||||||
IDirect3DRMVisual* visual;
|
IDirect3DRMVisual* visual;
|
||||||
@ -130,69 +61,6 @@ struct Direct3DRMWinDeviceImpl : public IDirect3DRMWinDevice {
|
|||||||
void HandlePaint(void* p_dc) override {}
|
void HandlePaint(void* p_dc) override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct Direct3DRMObjectBase : public T {
|
|
||||||
ULONG Release() override
|
|
||||||
{
|
|
||||||
if (IUnknown::m_refCount == 1) {
|
|
||||||
for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) {
|
|
||||||
it->first(this, it->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this->T::Release();
|
|
||||||
}
|
|
||||||
HRESULT AddDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override
|
|
||||||
{
|
|
||||||
m_callbacks.push_back(std::make_pair(callback, arg));
|
|
||||||
return D3DRM_OK;
|
|
||||||
}
|
|
||||||
HRESULT DeleteDestroyCallback(D3DRMOBJECTCALLBACK callback, void* arg) override
|
|
||||||
{
|
|
||||||
for (auto it = m_callbacks.cbegin(); it != m_callbacks.cend(); it++) {
|
|
||||||
if (it->first == callback && it->second == arg) {
|
|
||||||
m_callbacks.erase(it);
|
|
||||||
return D3DRM_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return D3DRMERR_NOTFOUND;
|
|
||||||
}
|
|
||||||
HRESULT SetAppData(LPD3DRM_APPDATA appData) override
|
|
||||||
{
|
|
||||||
m_appData = appData;
|
|
||||||
return D3DRM_OK;
|
|
||||||
}
|
|
||||||
LPVOID GetAppData() override { return m_appData; }
|
|
||||||
HRESULT SetName(const char* name) override
|
|
||||||
{
|
|
||||||
SDL_free(m_name);
|
|
||||||
m_name = NULL;
|
|
||||||
if (name) {
|
|
||||||
m_name = SDL_strdup(name);
|
|
||||||
}
|
|
||||||
return D3DRM_OK;
|
|
||||||
}
|
|
||||||
HRESULT GetName(DWORD* size, char* name) override
|
|
||||||
{
|
|
||||||
if (!size) {
|
|
||||||
return DDERR_INVALIDPARAMS;
|
|
||||||
}
|
|
||||||
const char* s = m_name ? m_name : "";
|
|
||||||
size_t l = SDL_strlen(s);
|
|
||||||
if (name) {
|
|
||||||
SDL_strlcpy(name, s, *size);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*size = l + 1;
|
|
||||||
}
|
|
||||||
return D3DRM_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<std::pair<D3DRMOBJECTCALLBACK, void*>> m_callbacks;
|
|
||||||
LPD3DRM_APPDATA m_appData = nullptr;
|
|
||||||
char* m_name = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Direct3DRMMeshImpl : public Direct3DRMObjectBase<IDirect3DRMMesh> {
|
struct Direct3DRMMeshImpl : public Direct3DRMObjectBase<IDirect3DRMMesh> {
|
||||||
HRESULT Clone(int flags, GUID iid, void** object) override
|
HRESULT Clone(int flags, GUID iid, void** object) override
|
||||||
{
|
{
|
||||||
@ -211,11 +79,11 @@ struct Direct3DRMMeshImpl : public Direct3DRMObjectBase<IDirect3DRMMesh> {
|
|||||||
}
|
}
|
||||||
HRESULT GetGroup(
|
HRESULT GetGroup(
|
||||||
int groupIndex,
|
int groupIndex,
|
||||||
unsigned int* vertexCount,
|
DWORD* vertexCount,
|
||||||
unsigned int* faceCount,
|
DWORD* faceCount,
|
||||||
unsigned int* vertexPerFace,
|
DWORD* vertexPerFace,
|
||||||
DWORD* dataSize,
|
DWORD* dataSize,
|
||||||
unsigned int* data
|
DWORD* data
|
||||||
) override
|
) override
|
||||||
{
|
{
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
@ -263,214 +131,6 @@ struct Direct3DRMTextureImpl : public Direct3DRMObjectBase<IDirect3DRMTexture2>
|
|||||||
HRESULT Changed(BOOL pixels, BOOL palette) override { return DD_OK; }
|
HRESULT Changed(BOOL pixels, BOOL palette) override { return DD_OK; }
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_GPUShader* CompileVertexShader(SDL_GPUDevice* device, VertexShaderId id)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
const SDL_GPUShaderCreateInfo* createInfo = GetVertexShaderCode(id, SDL_GetGPUShaderFormats(device));
|
|
||||||
if (!createInfo) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
SDL_GPUShader* shader = SDL_CreateGPUShader(device, createInfo);
|
|
||||||
if (!shader) {
|
|
||||||
SDL_Log("Failed to create Vertex GPU shader: %s", SDL_GetError());
|
|
||||||
}
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GPUShader* CompileFragmentShader(SDL_GPUDevice* device, FragmentShaderId id)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
const SDL_GPUShaderCreateInfo* createInfo = GetFragmentShaderCode(id, SDL_GetGPUShaderFormats(device));
|
|
||||||
if (!createInfo) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
SDL_GPUShader* shader = SDL_CreateGPUShader(device, createInfo);
|
|
||||||
if (!shader) {
|
|
||||||
SDL_Log("Failed to create Fragment GPU shader: %s", SDL_GetError());
|
|
||||||
}
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GPUDevice* m_device;
|
|
||||||
SDL_GPUGraphicsPipeline* m_pipeline;
|
|
||||||
SDL_GPUTexture* m_transferTexture;
|
|
||||||
SDL_GPUTransferBuffer* m_downloadTransferBuffer;
|
|
||||||
SDL_GPUBuffer* VertexBuffer;
|
|
||||||
int m_vertexCount = 3;
|
|
||||||
|
|
||||||
struct Direct3DRMDevice2Impl : public Direct3DRMObjectBase<IDirect3DRMDevice2> {
|
|
||||||
Direct3DRMDevice2Impl()
|
|
||||||
{
|
|
||||||
m_device = SDL_CreateGPUDevice(
|
|
||||||
SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL,
|
|
||||||
true,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
if (m_device == NULL) {
|
|
||||||
SDL_Log("GPUCreateDevice failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (DDWindow == NULL) {
|
|
||||||
SDL_Log("CreateWindow failed: %s", SDL_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!SDL_ClaimWindowForGPUDevice(m_device, DDWindow)) {
|
|
||||||
SDL_Log("GPUClaimWindow failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SDL_GPUShader* vertexShader = CompileVertexShader(m_device, VertexShaderId::PositionColor);
|
|
||||||
if (vertexShader == NULL) {
|
|
||||||
SDL_Log("Failed to create vertex shader!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SDL_GPUShader* fragmentShader = CompileFragmentShader(m_device, FragmentShaderId::SolidColor);
|
|
||||||
if (fragmentShader == NULL) {
|
|
||||||
SDL_Log("Failed to create fragment shader!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GPUColorTargetDescription colorTargets = {SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB};
|
|
||||||
SDL_GPUVertexBufferDescription vertexBufferDescs[] = {
|
|
||||||
{.slot = 0,
|
|
||||||
.pitch = sizeof(PositionColorVertex),
|
|
||||||
.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
|
|
||||||
.instance_step_rate = 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
SDL_GPUVertexAttribute vertexAttrs[] = {
|
|
||||||
{.location = 0, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, .offset = 0},
|
|
||||||
{.location = 1,
|
|
||||||
.buffer_slot = 0,
|
|
||||||
.format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM,
|
|
||||||
.offset = sizeof(float) * 3}
|
|
||||||
};
|
|
||||||
|
|
||||||
SDL_GPUVertexInputState vertexInputState = {
|
|
||||||
.vertex_buffer_descriptions = vertexBufferDescs,
|
|
||||||
.num_vertex_buffers = 1,
|
|
||||||
.vertex_attributes = vertexAttrs,
|
|
||||||
.num_vertex_attributes = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo =
|
|
||||||
{.vertex_shader = vertexShader,
|
|
||||||
.fragment_shader = fragmentShader,
|
|
||||||
.vertex_input_state = vertexInputState,
|
|
||||||
.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
|
|
||||||
.target_info = {
|
|
||||||
.color_target_descriptions = &colorTargets,
|
|
||||||
.num_color_targets = 1,
|
|
||||||
}};
|
|
||||||
|
|
||||||
m_pipeline = SDL_CreateGPUGraphicsPipeline(m_device, &pipelineCreateInfo);
|
|
||||||
if (m_pipeline == NULL) {
|
|
||||||
SDL_Log("Failed to create fill pipeline!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up shader resources
|
|
||||||
SDL_ReleaseGPUShader(m_device, vertexShader);
|
|
||||||
SDL_ReleaseGPUShader(m_device, fragmentShader);
|
|
||||||
// Create the vertex buffer
|
|
||||||
SDL_GPUBufferCreateInfo bufferCreateInfo = {
|
|
||||||
.usage = SDL_GPU_BUFFERUSAGE_VERTEX,
|
|
||||||
.size = (Uint32) (sizeof(PositionColorVertex) * m_vertexCount)
|
|
||||||
};
|
|
||||||
|
|
||||||
VertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
|
||||||
|
|
||||||
SDL_GPUTransferBufferCreateInfo transferCreateInfo = {
|
|
||||||
.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
|
|
||||||
.size = (Uint32) (sizeof(PositionColorVertex) * m_vertexCount)
|
|
||||||
};
|
|
||||||
|
|
||||||
SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer(m_device, &transferCreateInfo);
|
|
||||||
|
|
||||||
PositionColorVertex* transferData =
|
|
||||||
(PositionColorVertex*) SDL_MapGPUTransferBuffer(m_device, transferBuffer, false);
|
|
||||||
|
|
||||||
transferData[0] = (PositionColorVertex){-1, -1, 0, 255, 0, 0, 255};
|
|
||||||
transferData[1] = (PositionColorVertex){1, -1, 0, 0, 0, 255, 255};
|
|
||||||
transferData[2] = (PositionColorVertex){0, 1, 0, 0, 255, 0, 128};
|
|
||||||
|
|
||||||
SDL_UnmapGPUTransferBuffer(m_device, transferBuffer);
|
|
||||||
|
|
||||||
// Upload the transfer data to the vertex buffer
|
|
||||||
SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(m_device);
|
|
||||||
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf);
|
|
||||||
|
|
||||||
SDL_GPUTransferBufferLocation transferLocation = {.transfer_buffer = transferBuffer, .offset = 0};
|
|
||||||
|
|
||||||
SDL_GPUBufferRegion bufferRegion =
|
|
||||||
{.buffer = VertexBuffer, .offset = 0, .size = (Uint32) (sizeof(PositionColorVertex) * m_vertexCount)};
|
|
||||||
|
|
||||||
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
|
|
||||||
|
|
||||||
SDL_EndGPUCopyPass(copyPass);
|
|
||||||
SDL_SubmitGPUCommandBuffer(uploadCmdBuf);
|
|
||||||
SDL_ReleaseGPUTransferBuffer(m_device, transferBuffer);
|
|
||||||
|
|
||||||
SDL_GPUTextureCreateInfo textureInfo = {};
|
|
||||||
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
|
|
||||||
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB;
|
|
||||||
textureInfo.width = 640;
|
|
||||||
textureInfo.height = 480;
|
|
||||||
textureInfo.layer_count_or_depth = 1;
|
|
||||||
textureInfo.num_levels = 1;
|
|
||||||
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
|
||||||
m_transferTexture = SDL_CreateGPUTexture(m_device, &textureInfo);
|
|
||||||
if (m_transferTexture == NULL) {
|
|
||||||
SDL_Log("Failed to create fill pipeline!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SDL_GPUTransferBufferCreateInfo downloadTransferInfo = {
|
|
||||||
.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD,
|
|
||||||
.size = 640 * 480 * 4
|
|
||||||
};
|
|
||||||
m_downloadTransferBuffer = SDL_CreateGPUTransferBuffer(m_device, &downloadTransferInfo);
|
|
||||||
if (!m_downloadTransferBuffer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_viewports = new Direct3DRMViewportArrayImpl;
|
|
||||||
m_viewports->AddRef();
|
|
||||||
}
|
|
||||||
~Direct3DRMDevice2Impl() override
|
|
||||||
{
|
|
||||||
m_viewports->Release();
|
|
||||||
|
|
||||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_pipeline);
|
|
||||||
SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow);
|
|
||||||
SDL_ReleaseGPUBuffer(m_device, VertexBuffer);
|
|
||||||
SDL_DestroyWindow(DDWindow);
|
|
||||||
SDL_DestroyGPUDevice(m_device);
|
|
||||||
}
|
|
||||||
unsigned int GetWidth() override { return 640; }
|
|
||||||
unsigned int GetHeight() override { return 480; }
|
|
||||||
HRESULT SetBufferCount(int count) override { return DD_OK; }
|
|
||||||
HRESULT GetBufferCount() override { return DD_OK; }
|
|
||||||
HRESULT SetShades(unsigned int shadeCount) override { return DD_OK; }
|
|
||||||
HRESULT GetShades() override { return DD_OK; }
|
|
||||||
HRESULT SetQuality(D3DRMRENDERQUALITY quality) override { return DD_OK; }
|
|
||||||
D3DRMRENDERQUALITY GetQuality() override { return D3DRMRENDERQUALITY::GOURAUD; }
|
|
||||||
HRESULT SetDither(int dither) override { return DD_OK; }
|
|
||||||
HRESULT GetDither() override { return DD_OK; }
|
|
||||||
HRESULT SetTextureQuality(D3DRMTEXTUREQUALITY quality) override { return DD_OK; }
|
|
||||||
D3DRMTEXTUREQUALITY GetTextureQuality() override { return D3DRMTEXTUREQUALITY::LINEAR; }
|
|
||||||
HRESULT SetRenderMode(D3DRMRENDERMODE mode) override { return DD_OK; }
|
|
||||||
D3DRMRENDERMODE GetRenderMode() override { return D3DRMRENDERMODE::BLENDEDTRANSPARENCY; }
|
|
||||||
HRESULT Update() override { return DD_OK; }
|
|
||||||
HRESULT AddViewport(IDirect3DRMViewport* viewport) override { return m_viewports->AddElement(viewport); }
|
|
||||||
HRESULT GetViewports(IDirect3DRMViewportArray** ppViewportArray) override
|
|
||||||
{
|
|
||||||
*ppViewportArray = m_viewports;
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
IDirect3DRMViewportArray* m_viewports;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Direct3DRMFrameImpl : public Direct3DRMObjectBase<IDirect3DRMFrame2> {
|
struct Direct3DRMFrameImpl : public Direct3DRMObjectBase<IDirect3DRMFrame2> {
|
||||||
Direct3DRMFrameImpl()
|
Direct3DRMFrameImpl()
|
||||||
{
|
{
|
||||||
@ -550,130 +210,76 @@ struct Direct3DRMFrameImpl : public Direct3DRMObjectBase<IDirect3DRMFrame2> {
|
|||||||
IDirect3DRMTexture* m_texture = nullptr;
|
IDirect3DRMTexture* m_texture = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Direct3DRMViewportImpl : public Direct3DRMObjectBase<IDirect3DRMViewport> {
|
|
||||||
HRESULT Render(IDirect3DRMFrame* group) override
|
|
||||||
{
|
|
||||||
if (!m_transferTexture || !DDBackBuffer) {
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
|
||||||
if (cmdbuf == NULL) {
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the graphics
|
|
||||||
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
|
||||||
colorTargetInfo.texture = m_transferTexture;
|
|
||||||
// Make the render target transparent so we can combine it with the back buffer
|
|
||||||
colorTargetInfo.clear_color = {0, 0, 0, 0};
|
|
||||||
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
|
||||||
|
|
||||||
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL);
|
|
||||||
SDL_BindGPUGraphicsPipeline(renderPass, m_pipeline);
|
|
||||||
SDL_GPUBufferBinding vertexBufferBinding = {.buffer = VertexBuffer, .offset = 0};
|
|
||||||
SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1);
|
|
||||||
SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0);
|
|
||||||
SDL_EndGPURenderPass(renderPass);
|
|
||||||
|
|
||||||
// Download rendered image
|
|
||||||
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
|
|
||||||
SDL_GPUTextureRegion region = {};
|
|
||||||
region.texture = m_transferTexture;
|
|
||||||
region.w = DDBackBuffer->w;
|
|
||||||
region.h = DDBackBuffer->h;
|
|
||||||
region.d = 1;
|
|
||||||
SDL_GPUTextureTransferInfo transferInfo = {};
|
|
||||||
transferInfo.transfer_buffer = m_downloadTransferBuffer;
|
|
||||||
transferInfo.offset = 0;
|
|
||||||
SDL_DownloadFromGPUTexture(copyPass, ®ion, &transferInfo);
|
|
||||||
SDL_EndGPUCopyPass(copyPass);
|
|
||||||
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
|
|
||||||
if (!cmdbuf || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) {
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
SDL_ReleaseGPUFence(m_device, fence);
|
|
||||||
void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadTransferBuffer, false);
|
|
||||||
if (!downloadedData) {
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
SDL_Surface* renderedImage = SDL_CreateSurfaceFrom(
|
|
||||||
DDBackBuffer->w,
|
|
||||||
DDBackBuffer->h,
|
|
||||||
SDL_PIXELFORMAT_ABGR8888,
|
|
||||||
downloadedData,
|
|
||||||
DDBackBuffer->w * 4
|
|
||||||
);
|
|
||||||
if (!renderedImage) {
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Blit the render back to our backbuffer
|
|
||||||
SDL_Rect srcRect{0, 0, DDBackBuffer->w, DDBackBuffer->h};
|
|
||||||
|
|
||||||
if (renderedImage->format == DDBackBuffer->format) {
|
|
||||||
// No conversion needed
|
|
||||||
SDL_BlitSurface(renderedImage, &srcRect, DDBackBuffer, &srcRect);
|
|
||||||
SDL_DestroySurface(renderedImage);
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format);
|
|
||||||
if (details->Amask != 0) {
|
|
||||||
// Backbuffer supports transparnacy
|
|
||||||
SDL_Surface* convertedRender = SDL_ConvertSurface(renderedImage, DDBackBuffer->format);
|
|
||||||
SDL_DestroySurface(renderedImage);
|
|
||||||
SDL_BlitSurface(convertedRender, &srcRect, DDBackBuffer, &srcRect);
|
|
||||||
SDL_DestroySurface(convertedRender);
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert backbuffer to a format that supports transparancy
|
|
||||||
SDL_Surface* tempBackbuffer = SDL_ConvertSurface(DDBackBuffer, renderedImage->format);
|
|
||||||
SDL_BlitSurface(renderedImage, &srcRect, tempBackbuffer, &srcRect);
|
|
||||||
SDL_DestroySurface(renderedImage);
|
|
||||||
// Then convert the result back to the backbuffer format and write it back
|
|
||||||
SDL_Surface* newBackBuffer = SDL_ConvertSurface(tempBackbuffer, DDBackBuffer->format);
|
|
||||||
SDL_DestroySurface(tempBackbuffer);
|
|
||||||
SDL_BlitSurface(newBackBuffer, &srcRect, DDBackBuffer, &srcRect);
|
|
||||||
SDL_DestroySurface(newBackBuffer);
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
HRESULT ForceUpdate(int x, int y, int w, int h) override { return DD_OK; }
|
|
||||||
HRESULT Clear() override { return DD_OK; }
|
|
||||||
HRESULT SetCamera(IDirect3DRMFrame* camera) override
|
|
||||||
{
|
|
||||||
m_camera = camera;
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
HRESULT GetCamera(IDirect3DRMFrame** camera) override
|
|
||||||
{
|
|
||||||
*camera = m_camera;
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
HRESULT SetProjection(D3DRMPROJECTIONTYPE type) override { return DD_OK; }
|
|
||||||
D3DRMPROJECTIONTYPE GetProjection() override { return D3DRMPROJECTIONTYPE::PERSPECTIVE; }
|
|
||||||
HRESULT SetFront(D3DVALUE z) override { return DD_OK; }
|
|
||||||
D3DVALUE GetFront() override { return 0; }
|
|
||||||
HRESULT SetBack(D3DVALUE z) override { return DD_OK; }
|
|
||||||
D3DVALUE GetBack() override { return 0; }
|
|
||||||
HRESULT SetField(D3DVALUE field) override { return DD_OK; }
|
|
||||||
D3DVALUE GetField() override { return 0; }
|
|
||||||
int GetWidth() override { return 640; }
|
|
||||||
int GetHeight() override { return 480; }
|
|
||||||
HRESULT Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) override { return DD_OK; }
|
|
||||||
HRESULT InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) override { return DD_OK; }
|
|
||||||
HRESULT Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray) override { return DD_OK; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
IDirect3DRMFrame* m_camera = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Direct3DRMLightImpl : public Direct3DRMObjectBase<IDirect3DRMLight> {
|
struct Direct3DRMLightImpl : public Direct3DRMObjectBase<IDirect3DRMLight> {
|
||||||
HRESULT SetColorRGB(float r, float g, float b) override { return DD_OK; }
|
HRESULT SetColorRGB(float r, float g, float b) override { return DD_OK; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Direct3DRMMaterialImpl : public Direct3DRMObjectBase<IDirect3DRMMaterial> {};
|
struct Direct3DRMMaterialImpl : public Direct3DRMObjectBase<IDirect3DRMMaterial> {};
|
||||||
|
|
||||||
|
SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device)
|
||||||
|
{
|
||||||
|
const SDL_GPUShaderCreateInfo* vertexCreateInfo =
|
||||||
|
GetVertexShaderCode(VertexShaderId::PositionColor, SDL_GetGPUShaderFormats(device));
|
||||||
|
if (!vertexCreateInfo) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
SDL_GPUShader* vertexShader = SDL_CreateGPUShader(device, vertexCreateInfo);
|
||||||
|
if (!vertexShader) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SDL_GPUShaderCreateInfo* fragmentCreateInfo =
|
||||||
|
GetFragmentShaderCode(FragmentShaderId::SolidColor, SDL_GetGPUShaderFormats(device));
|
||||||
|
if (!fragmentCreateInfo) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
SDL_GPUShader* fragmentShader = SDL_CreateGPUShader(device, fragmentCreateInfo);
|
||||||
|
if (!fragmentShader) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GPUVertexBufferDescription vertexBufferDescs[1] = {};
|
||||||
|
vertexBufferDescs[0].slot = 0;
|
||||||
|
vertexBufferDescs[0].pitch = sizeof(PositionColorVertex);
|
||||||
|
vertexBufferDescs[0].input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
|
||||||
|
vertexBufferDescs[0].instance_step_rate = 0;
|
||||||
|
|
||||||
|
SDL_GPUVertexAttribute vertexAttrs[2] = {};
|
||||||
|
vertexAttrs[0].location = 0;
|
||||||
|
vertexAttrs[0].buffer_slot = 0;
|
||||||
|
vertexAttrs[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
|
||||||
|
vertexAttrs[0].offset = 0;
|
||||||
|
|
||||||
|
vertexAttrs[1].location = 1;
|
||||||
|
vertexAttrs[1].buffer_slot = 0;
|
||||||
|
vertexAttrs[1].format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM;
|
||||||
|
vertexAttrs[1].offset = sizeof(float) * 3;
|
||||||
|
|
||||||
|
SDL_GPUVertexInputState vertexInputState = {};
|
||||||
|
vertexInputState.vertex_buffer_descriptions = vertexBufferDescs;
|
||||||
|
vertexInputState.num_vertex_buffers = 1;
|
||||||
|
vertexInputState.vertex_attributes = vertexAttrs;
|
||||||
|
vertexInputState.num_vertex_attributes = 2;
|
||||||
|
|
||||||
|
SDL_GPUColorTargetDescription colorTargets = {};
|
||||||
|
colorTargets.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB;
|
||||||
|
|
||||||
|
SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = {};
|
||||||
|
pipelineCreateInfo.vertex_shader = vertexShader;
|
||||||
|
pipelineCreateInfo.fragment_shader = fragmentShader;
|
||||||
|
pipelineCreateInfo.vertex_input_state = vertexInputState;
|
||||||
|
pipelineCreateInfo.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
|
||||||
|
pipelineCreateInfo.target_info.color_target_descriptions = &colorTargets;
|
||||||
|
pipelineCreateInfo.target_info.num_color_targets = 1;
|
||||||
|
|
||||||
|
SDL_GPUGraphicsPipeline* pipeline = SDL_CreateGPUGraphicsPipeline(device, &pipelineCreateInfo);
|
||||||
|
// Clean up shader resources
|
||||||
|
SDL_ReleaseGPUShader(device, vertexShader);
|
||||||
|
SDL_ReleaseGPUShader(device, fragmentShader);
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
struct Direct3DRMImpl : virtual public IDirect3DRM2 {
|
struct Direct3DRMImpl : virtual public IDirect3DRM2 {
|
||||||
// IUnknown interface
|
// IUnknown interface
|
||||||
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override
|
HRESULT QueryInterface(const GUID& riid, void** ppvObject) override
|
||||||
@ -683,15 +289,34 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 {
|
|||||||
*ppvObject = static_cast<IDirect3DRM2*>(this);
|
*ppvObject = static_cast<IDirect3DRM2*>(this);
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Direct3DRMImpl does not implement guid");
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
// IDirect3DRM interface
|
// IDirect3DRM interface
|
||||||
|
HRESULT CreateDevice(IDirect3DRMDevice2** outDevice, DWORD width, DWORD height)
|
||||||
|
{
|
||||||
|
SDL_GPUDevice* device = SDL_CreateGPUDevice(
|
||||||
|
SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_MSL,
|
||||||
|
true,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if (device == NULL) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
if (DDWindow == NULL) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
if (!SDL_ClaimWindowForGPUDevice(device, DDWindow)) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outDevice = static_cast<IDirect3DRMDevice2*>(new Direct3DRMDevice2Impl(width, height, device));
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
HRESULT CreateDeviceFromD3D(const IDirect3D2* d3d, IDirect3DDevice2* d3dDevice, IDirect3DRMDevice2** outDevice)
|
HRESULT CreateDeviceFromD3D(const IDirect3D2* d3d, IDirect3DDevice2* d3dDevice, IDirect3DRMDevice2** outDevice)
|
||||||
override
|
override
|
||||||
{
|
{
|
||||||
*outDevice = static_cast<IDirect3DRMDevice2*>(new Direct3DRMDevice2Impl);
|
return CreateDevice(outDevice, 640, 480);
|
||||||
return DD_OK;
|
|
||||||
}
|
}
|
||||||
HRESULT CreateDeviceFromSurface(
|
HRESULT CreateDeviceFromSurface(
|
||||||
const GUID* guid,
|
const GUID* guid,
|
||||||
@ -700,8 +325,10 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 {
|
|||||||
IDirect3DRMDevice2** outDevice
|
IDirect3DRMDevice2** outDevice
|
||||||
) override
|
) override
|
||||||
{
|
{
|
||||||
*outDevice = static_cast<IDirect3DRMDevice2*>(new Direct3DRMDevice2Impl);
|
DDSURFACEDESC DDSDesc;
|
||||||
return DD_OK;
|
DDSDesc.dwSize = sizeof(DDSURFACEDESC);
|
||||||
|
surface->GetSurfaceDesc(&DDSDesc);
|
||||||
|
return CreateDevice(outDevice, DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||||
}
|
}
|
||||||
HRESULT CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) override
|
HRESULT CreateTexture(D3DRMIMAGE* image, IDirect3DRMTexture2** outTexture) override
|
||||||
{
|
{
|
||||||
@ -734,7 +361,7 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 {
|
|||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
HRESULT CreateViewport(
|
HRESULT CreateViewport(
|
||||||
IDirect3DRMDevice2* device,
|
IDirect3DRMDevice2* iDevice,
|
||||||
IDirect3DRMFrame* camera,
|
IDirect3DRMFrame* camera,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
@ -743,12 +370,49 @@ struct Direct3DRMImpl : virtual public IDirect3DRM2 {
|
|||||||
IDirect3DRMViewport** outViewport
|
IDirect3DRMViewport** outViewport
|
||||||
) override
|
) override
|
||||||
{
|
{
|
||||||
*outViewport = static_cast<IDirect3DRMViewport*>(new Direct3DRMViewportImpl);
|
auto device = static_cast<Direct3DRMDevice2Impl*>(iDevice);
|
||||||
|
|
||||||
|
SDL_GPUGraphicsPipeline* pipeline = InitializeGraphicsPipeline(device->m_device);
|
||||||
|
if (!pipeline) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GPUTextureCreateInfo textureInfo = {};
|
||||||
|
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
|
||||||
|
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB;
|
||||||
|
textureInfo.width = width;
|
||||||
|
textureInfo.height = height;
|
||||||
|
textureInfo.layer_count_or_depth = 1;
|
||||||
|
textureInfo.num_levels = 1;
|
||||||
|
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||||
|
SDL_GPUTexture* transferTexture = SDL_CreateGPUTexture(device->m_device, &textureInfo);
|
||||||
|
if (transferTexture == NULL) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup texture GPU-to-CPU transfer
|
||||||
|
SDL_GPUTransferBufferCreateInfo downloadTransferInfo = {};
|
||||||
|
downloadTransferInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD;
|
||||||
|
downloadTransferInfo.size = static_cast<Uint32>(width * height * 4);
|
||||||
|
SDL_GPUTransferBuffer* downloadTransferBuffer =
|
||||||
|
SDL_CreateGPUTransferBuffer(device->m_device, &downloadTransferInfo);
|
||||||
|
if (!downloadTransferBuffer) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outViewport = static_cast<IDirect3DRMViewport*>(new Direct3DRMViewportImpl(
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
device->m_device,
|
||||||
|
transferTexture,
|
||||||
|
downloadTransferBuffer,
|
||||||
|
pipeline
|
||||||
|
));
|
||||||
device->AddViewport(*outViewport);
|
device->AddViewport(*outViewport);
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
HRESULT SetDefaultTextureShades(unsigned int count) override { return DD_OK; }
|
HRESULT SetDefaultTextureShades(DWORD count) override { return DD_OK; }
|
||||||
HRESULT SetDefaultTextureColors(unsigned int count) override { return DD_OK; }
|
HRESULT SetDefaultTextureColors(DWORD count) override { return DD_OK; }
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT WINAPI Direct3DRMCreate(IDirect3DRM** direct3DRM)
|
HRESULT WINAPI Direct3DRMCreate(IDirect3DRM** direct3DRM)
|
||||||
|
|||||||
117
miniwin/miniwin/src/miniwin_d3drmdevice.cpp
Normal file
117
miniwin/miniwin/src/miniwin_d3drmdevice.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include "miniwin_d3drm.h"
|
||||||
|
#include "miniwin_d3drm_p.h"
|
||||||
|
#include "miniwin_d3drmobject_p.h"
|
||||||
|
#include "miniwin_d3drmviewport_p.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
Direct3DRMDevice2Impl::Direct3DRMDevice2Impl(DWORD width, DWORD height, SDL_GPUDevice* device)
|
||||||
|
: m_width(width), m_height(height), m_device(device), m_viewports(new Direct3DRMViewportArrayImpl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Direct3DRMDevice2Impl::~Direct3DRMDevice2Impl()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_viewports->GetSize(); i++) {
|
||||||
|
IDirect3DRMViewport* viewport;
|
||||||
|
m_viewports->GetElement(i, &viewport);
|
||||||
|
static_cast<Direct3DRMViewportImpl*>(viewport)->CloseDevice();
|
||||||
|
viewport->Release();
|
||||||
|
}
|
||||||
|
m_viewports->Release();
|
||||||
|
|
||||||
|
SDL_ReleaseWindowFromGPUDevice(m_device, DDWindow);
|
||||||
|
SDL_DestroyGPUDevice(m_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD Direct3DRMDevice2Impl::GetWidth()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD Direct3DRMDevice2Impl::GetHeight()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::SetBufferCount(int count)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::GetBufferCount()
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::SetShades(DWORD shadeCount)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::GetShades()
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::SetQuality(D3DRMRENDERQUALITY quality)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DRMRENDERQUALITY Direct3DRMDevice2Impl::GetQuality()
|
||||||
|
{
|
||||||
|
return D3DRMRENDERQUALITY::GOURAUD;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::SetDither(int dither)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::GetDither()
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::SetTextureQuality(D3DRMTEXTUREQUALITY quality)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DRMTEXTUREQUALITY Direct3DRMDevice2Impl::GetTextureQuality()
|
||||||
|
{
|
||||||
|
return D3DRMTEXTUREQUALITY::LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::SetRenderMode(D3DRMRENDERMODE mode)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DRMRENDERMODE Direct3DRMDevice2Impl::GetRenderMode()
|
||||||
|
{
|
||||||
|
return D3DRMRENDERMODE::BLENDEDTRANSPARENCY;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::Update()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_viewports->GetSize(); i++) {
|
||||||
|
IDirect3DRMViewport* viewport;
|
||||||
|
m_viewports->GetElement(i, &viewport);
|
||||||
|
static_cast<Direct3DRMViewportImpl*>(viewport)->Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::AddViewport(IDirect3DRMViewport* viewport)
|
||||||
|
{
|
||||||
|
return m_viewports->AddElement(viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMDevice2Impl::GetViewports(IDirect3DRMViewportArray** ppViewportArray)
|
||||||
|
{
|
||||||
|
*ppViewportArray = m_viewports;
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
267
miniwin/miniwin/src/miniwin_d3drmviewport.cpp
Normal file
267
miniwin/miniwin/src/miniwin_d3drmviewport.cpp
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
#include "miniwin_d3drm_p.h"
|
||||||
|
#include "miniwin_d3drmviewport_p.h"
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
Direct3DRMViewportImpl::Direct3DRMViewportImpl(
|
||||||
|
DWORD width,
|
||||||
|
DWORD height,
|
||||||
|
SDL_GPUDevice* device,
|
||||||
|
SDL_GPUTexture* transferTexture,
|
||||||
|
SDL_GPUTransferBuffer* downloadTransferBuffer,
|
||||||
|
SDL_GPUGraphicsPipeline* pipeline
|
||||||
|
)
|
||||||
|
: m_width(width), m_height(height), m_device(device), m_transferTexture(transferTexture),
|
||||||
|
m_downloadTransferBuffer(downloadTransferBuffer), m_pipeline(pipeline)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Direct3DRMViewportImpl::FreeDeviceResources()
|
||||||
|
{
|
||||||
|
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
|
||||||
|
SDL_ReleaseGPUGraphicsPipeline(m_device, m_pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
Direct3DRMViewportImpl::~Direct3DRMViewportImpl()
|
||||||
|
{
|
||||||
|
FreeDeviceResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Direct3DRMViewportImpl::Update()
|
||||||
|
{
|
||||||
|
m_vertexCount = 3;
|
||||||
|
|
||||||
|
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
|
||||||
|
bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
|
||||||
|
bufferCreateInfo.size = static_cast<Uint32>(sizeof(PositionColorVertex) * m_vertexCount);
|
||||||
|
|
||||||
|
m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
||||||
|
|
||||||
|
SDL_GPUTransferBufferCreateInfo transferCreateInfo = {};
|
||||||
|
transferCreateInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||||
|
transferCreateInfo.size = static_cast<Uint32>(sizeof(PositionColorVertex) * m_vertexCount);
|
||||||
|
|
||||||
|
SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer(m_device, &transferCreateInfo);
|
||||||
|
|
||||||
|
PositionColorVertex* transferData =
|
||||||
|
(PositionColorVertex*) SDL_MapGPUTransferBuffer(m_device, transferBuffer, false);
|
||||||
|
|
||||||
|
transferData[0] = {-1, -1, 0, 255, 0, 0, 255};
|
||||||
|
transferData[1] = {1, -1, 0, 0, 0, 255, 255};
|
||||||
|
transferData[2] = {0, 1, 0, 0, 255, 0, 128};
|
||||||
|
|
||||||
|
SDL_UnmapGPUTransferBuffer(m_device, transferBuffer);
|
||||||
|
|
||||||
|
// Upload the transfer data to the vertex buffer
|
||||||
|
SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||||
|
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf);
|
||||||
|
SDL_GPUTransferBufferLocation transferLocation = {};
|
||||||
|
transferLocation.transfer_buffer = transferBuffer;
|
||||||
|
transferLocation.offset = 0;
|
||||||
|
|
||||||
|
SDL_GPUBufferRegion bufferRegion = {};
|
||||||
|
bufferRegion.buffer = m_vertexBuffer;
|
||||||
|
bufferRegion.offset = 0;
|
||||||
|
bufferRegion.size = static_cast<Uint32>(sizeof(PositionColorVertex) * m_vertexCount);
|
||||||
|
|
||||||
|
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
|
||||||
|
|
||||||
|
SDL_EndGPUCopyPass(copyPass);
|
||||||
|
SDL_SubmitGPUCommandBuffer(uploadCmdBuf);
|
||||||
|
SDL_ReleaseGPUTransferBuffer(m_device, transferBuffer);
|
||||||
|
|
||||||
|
m_updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::Render(IDirect3DRMFrame* group)
|
||||||
|
{
|
||||||
|
if (!m_updated) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_device) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||||
|
if (cmdbuf == NULL) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the graphics
|
||||||
|
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
||||||
|
colorTargetInfo.texture = m_transferTexture;
|
||||||
|
// Make the render target transparent so we can combine it with the back buffer
|
||||||
|
colorTargetInfo.clear_color = {0, 0, 0, 0};
|
||||||
|
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||||
|
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, NULL);
|
||||||
|
SDL_BindGPUGraphicsPipeline(renderPass, m_pipeline);
|
||||||
|
SDL_GPUBufferBinding vertexBufferBinding = {};
|
||||||
|
vertexBufferBinding.buffer = m_vertexBuffer;
|
||||||
|
vertexBufferBinding.offset = 0;
|
||||||
|
SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1);
|
||||||
|
SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0);
|
||||||
|
SDL_EndGPURenderPass(renderPass);
|
||||||
|
|
||||||
|
// Download rendered image
|
||||||
|
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
|
||||||
|
SDL_GPUTextureRegion region = {};
|
||||||
|
region.texture = m_transferTexture;
|
||||||
|
region.w = DDBackBuffer->w;
|
||||||
|
region.h = DDBackBuffer->h;
|
||||||
|
region.d = 1;
|
||||||
|
SDL_GPUTextureTransferInfo transferInfo = {};
|
||||||
|
transferInfo.transfer_buffer = m_downloadTransferBuffer;
|
||||||
|
transferInfo.offset = 0;
|
||||||
|
SDL_DownloadFromGPUTexture(copyPass, ®ion, &transferInfo);
|
||||||
|
SDL_EndGPUCopyPass(copyPass);
|
||||||
|
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
|
||||||
|
if (!cmdbuf || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
SDL_ReleaseGPUFence(m_device, fence);
|
||||||
|
void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadTransferBuffer, false);
|
||||||
|
if (!downloadedData) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_updated = false;
|
||||||
|
|
||||||
|
SDL_DestroySurface(m_renderedImage);
|
||||||
|
m_renderedImage = SDL_CreateSurfaceFrom(
|
||||||
|
DDBackBuffer->w,
|
||||||
|
DDBackBuffer->h,
|
||||||
|
SDL_PIXELFORMAT_ABGR8888,
|
||||||
|
downloadedData,
|
||||||
|
DDBackBuffer->w * 4
|
||||||
|
);
|
||||||
|
|
||||||
|
SDL_Surface* convertedRender = SDL_ConvertSurface(m_renderedImage, SDL_PIXELFORMAT_RGBA8888);
|
||||||
|
SDL_DestroySurface(m_renderedImage);
|
||||||
|
SDL_UnmapGPUTransferBuffer(m_device, m_downloadTransferBuffer);
|
||||||
|
m_renderedImage = convertedRender;
|
||||||
|
|
||||||
|
return ForceUpdate(0, 0, DDBackBuffer->w, DDBackBuffer->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::ForceUpdate(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
if (!m_renderedImage) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
// Blit the render back to our backbuffer
|
||||||
|
SDL_Rect srcRect{0, 0, DDBackBuffer->w, DDBackBuffer->h};
|
||||||
|
|
||||||
|
const SDL_PixelFormatDetails* details = SDL_GetPixelFormatDetails(DDBackBuffer->format);
|
||||||
|
if (details->Amask != 0) {
|
||||||
|
// Backbuffer supports transparnacy
|
||||||
|
SDL_Surface* convertedRender = SDL_ConvertSurface(m_renderedImage, DDBackBuffer->format);
|
||||||
|
SDL_DestroySurface(m_renderedImage);
|
||||||
|
m_renderedImage = convertedRender;
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_renderedImage->format == DDBackBuffer->format) {
|
||||||
|
// No conversion needed
|
||||||
|
SDL_BlitSurface(m_renderedImage, &srcRect, DDBackBuffer, &srcRect);
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert backbuffer to a format that supports transparancy
|
||||||
|
SDL_Surface* tempBackbuffer = SDL_ConvertSurface(DDBackBuffer, m_renderedImage->format);
|
||||||
|
SDL_BlitSurface(m_renderedImage, &srcRect, tempBackbuffer, &srcRect);
|
||||||
|
// Then convert the result back to the backbuffer format and write it back
|
||||||
|
SDL_Surface* newBackBuffer = SDL_ConvertSurface(tempBackbuffer, DDBackBuffer->format);
|
||||||
|
SDL_DestroySurface(tempBackbuffer);
|
||||||
|
SDL_BlitSurface(newBackBuffer, &srcRect, DDBackBuffer, &srcRect);
|
||||||
|
SDL_DestroySurface(newBackBuffer);
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::Clear()
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::SetCamera(IDirect3DRMFrame* camera)
|
||||||
|
{
|
||||||
|
m_camera = camera;
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::GetCamera(IDirect3DRMFrame** camera)
|
||||||
|
{
|
||||||
|
*camera = m_camera;
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::SetProjection(D3DRMPROJECTIONTYPE type)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DRMPROJECTIONTYPE Direct3DRMViewportImpl::GetProjection()
|
||||||
|
{
|
||||||
|
return D3DRMPROJECTIONTYPE::PERSPECTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::SetFront(D3DVALUE z)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DVALUE Direct3DRMViewportImpl::GetFront()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::SetBack(D3DVALUE z)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DVALUE Direct3DRMViewportImpl::GetBack()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::SetField(D3DVALUE field)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DVALUE Direct3DRMViewportImpl::GetField()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD Direct3DRMViewportImpl::GetWidth()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD Direct3DRMViewportImpl::GetHeight()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMViewportImpl::Pick(float x, float y, LPDIRECT3DRMPICKEDARRAY* pickedArray)
|
||||||
|
{
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Direct3DRMViewportImpl::CloseDevice()
|
||||||
|
{
|
||||||
|
FreeDeviceResources();
|
||||||
|
m_device = nullptr;
|
||||||
|
}
|
||||||
@ -35,7 +35,7 @@ HRESULT DirectDrawSurfaceImpl::QueryInterface(const GUID& riid, void** ppvObject
|
|||||||
*ppvObject = static_cast<IDirectDrawSurface3*>(this);
|
*ppvObject = static_cast<IDirectDrawSurface3*>(this);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawImpl does not implement guid");
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "DirectDrawSurfaceImpl does not implement guid");
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user