mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-14 19:41:15 +00:00
204 lines
5.9 KiB
C++
204 lines
5.9 KiB
C++
#pragma once
|
|
|
|
#include "d3drmrenderer.h"
|
|
#include "d3drmtexture_impl.h"
|
|
#include "ddpalette_impl.h"
|
|
#include "ddraw_impl.h"
|
|
#include "gxm_context.h"
|
|
|
|
#include <SDL3/SDL.h>
|
|
#include <psp2/gxm.h>
|
|
#include <psp2/kernel/clib.h>
|
|
#include <psp2/types.h>
|
|
#include <vector>
|
|
|
|
DEFINE_GUID(GXM_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x58, 0x4D);
|
|
|
|
#define GXM_VERTEX_BUFFER_COUNT 2
|
|
#define GXM_FRAGMENT_BUFFER_COUNT 3
|
|
#define GXM_TEXTURE_BUFFER_COUNT 2
|
|
|
|
// #define GXM_PRECOMPUTE
|
|
|
|
struct GXMTextureCacheEntry {
|
|
IDirect3DRMTexture* texture;
|
|
Uint32 version;
|
|
int bufferCount;
|
|
int currentIndex;
|
|
SceGxmTexture gxmTexture[GXM_TEXTURE_BUFFER_COUNT];
|
|
SceGxmNotification* notifications[GXM_TEXTURE_BUFFER_COUNT];
|
|
};
|
|
|
|
struct GXMMeshCacheEntry {
|
|
const MeshGroup* meshGroup;
|
|
int version;
|
|
bool flat;
|
|
|
|
void* meshData;
|
|
void* vertexBuffer;
|
|
void* indexBuffer;
|
|
uint16_t indexCount;
|
|
|
|
#ifdef GXM_PRECOMPUTE
|
|
void* precomputeData;
|
|
void* uniformBuffers;
|
|
SceGxmPrecomputedVertexState vertexState[GXM_VERTEX_BUFFER_COUNT];
|
|
SceGxmPrecomputedFragmentState fragmentState[GXM_FRAGMENT_BUFFER_COUNT];
|
|
SceGxmPrecomputedDraw drawState;
|
|
#endif
|
|
};
|
|
|
|
typedef struct GXMDisplayData {
|
|
void* address;
|
|
} GXMDisplayData;
|
|
|
|
struct SceneLightGXM {
|
|
float color[4];
|
|
float vec[4];
|
|
float isDirectional;
|
|
float _align;
|
|
};
|
|
|
|
struct GXMSceneLightUniform {
|
|
SceneLightGXM lights[2];
|
|
float ambientLight[3];
|
|
};
|
|
|
|
typedef struct Vertex {
|
|
float position[3];
|
|
float normal[3];
|
|
float texCoord[2];
|
|
} Vertex;
|
|
|
|
class GXMRenderer : public Direct3DRMRenderer {
|
|
public:
|
|
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
|
GXMRenderer(DWORD width, DWORD height);
|
|
~GXMRenderer() override;
|
|
|
|
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
|
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
|
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
|
Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi, float scaleX, float scaleY) override;
|
|
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
|
HRESULT BeginFrame() override;
|
|
void EnableTransparency() override;
|
|
void SubmitDraw(
|
|
DWORD meshId,
|
|
const D3DRMMATRIX4D& modelViewMatrix,
|
|
const D3DRMMATRIX4D& worldMatrix,
|
|
const D3DRMMATRIX4D& viewMatrix,
|
|
const Matrix3x3& normalMatrix,
|
|
const Appearance& appearance
|
|
) override;
|
|
HRESULT FinalizeFrame() override;
|
|
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
|
|
void Clear(float r, float g, float b) override;
|
|
void Flip() override;
|
|
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect, FColor color) override;
|
|
void Download(SDL_Surface* target) override;
|
|
void SetDither(bool dither) override;
|
|
|
|
private:
|
|
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
|
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
|
|
|
GXMMeshCacheEntry GXMUploadMesh(const MeshGroup& meshGroup);
|
|
|
|
void StartScene();
|
|
inline const SceGxmTexture* UseTexture(GXMTextureCacheEntry& texture)
|
|
{
|
|
texture.notifications[texture.currentIndex] = &this->fragmentNotifications[this->currentFragmentBufferIndex];
|
|
const SceGxmTexture* gxmTexture = &texture.gxmTexture[texture.currentIndex];
|
|
sceGxmSetFragmentTexture(gxm->context, 0, gxmTexture);
|
|
return gxmTexture;
|
|
}
|
|
|
|
inline Vertex2D* QuadVerticesBuffer()
|
|
{
|
|
Vertex2D* verts = &this->quadVertices[this->currentVertexBufferIndex][this->quadsUsed * 4];
|
|
this->quadsUsed += 1;
|
|
if (this->quadsUsed >= 50) {
|
|
SDL_Log("QuadVerticesBuffer overflow");
|
|
this->quadsUsed = 0; // declare bankruptcy
|
|
}
|
|
return verts;
|
|
}
|
|
|
|
inline GXMSceneLightUniform* LightsBuffer() { return this->lights[this->currentFragmentBufferIndex]; }
|
|
|
|
std::vector<GXMTextureCacheEntry> m_textures;
|
|
std::vector<GXMMeshCacheEntry> m_meshes;
|
|
D3DRMMATRIX4D m_projection;
|
|
std::vector<SceneLight> m_lights;
|
|
|
|
bool transparencyEnabled = false;
|
|
|
|
// shader
|
|
SceGxmShaderPatcherId mainVertexProgramId;
|
|
SceGxmShaderPatcherId mainColorFragmentProgramId;
|
|
SceGxmShaderPatcherId mainTextureFragmentProgramId;
|
|
|
|
SceGxmVertexProgram* mainVertexProgram;
|
|
SceGxmFragmentProgram* opaqueColorFragmentProgram;
|
|
SceGxmFragmentProgram* blendedColorFragmentProgram;
|
|
SceGxmFragmentProgram* opaqueTextureFragmentProgram;
|
|
SceGxmFragmentProgram* blendedTextureFragmentProgram;
|
|
|
|
// main shader vertex uniforms
|
|
const SceGxmProgramParameter* uModelViewMatrix;
|
|
const SceGxmProgramParameter* uNormalMatrix;
|
|
const SceGxmProgramParameter* uProjectionMatrix;
|
|
|
|
// main shader fragment uniforms
|
|
const SceGxmProgramParameter* uShininess;
|
|
const SceGxmProgramParameter* uColor;
|
|
const SceGxmProgramParameter* uLights;
|
|
const SceGxmProgramParameter* uAmbientLight;
|
|
|
|
// uniforms / quad meshes
|
|
GXMSceneLightUniform* lights[GXM_FRAGMENT_BUFFER_COUNT];
|
|
Vertex2D* quadVertices[GXM_VERTEX_BUFFER_COUNT];
|
|
uint16_t* quadIndices;
|
|
int quadsUsed = 0;
|
|
bool cleared = false;
|
|
|
|
SceGxmNotification vertexNotifications[GXM_VERTEX_BUFFER_COUNT];
|
|
SceGxmNotification fragmentNotifications[GXM_FRAGMENT_BUFFER_COUNT];
|
|
int currentFragmentBufferIndex = 0;
|
|
int currentVertexBufferIndex = 0;
|
|
|
|
SDL_Gamepad* gamepad;
|
|
bool button_dpad_up;
|
|
bool button_dpad_down;
|
|
bool button_dpad_left;
|
|
bool button_dpad_right;
|
|
|
|
bool m_initialized = false;
|
|
};
|
|
|
|
int gxm_library_init();
|
|
|
|
inline static void GXMRenderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
|
{
|
|
D3DDEVICEDESC halDesc = {};
|
|
halDesc.dcmColorModel = D3DCOLORMODEL::RGB;
|
|
halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
|
halDesc.dwDeviceZBufferBitDepth = DDBD_16;
|
|
halDesc.dwDeviceZBufferBitDepth |= DDBD_32;
|
|
halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
|
halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
|
halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
|
|
|
D3DDEVICEDESC helDesc = {};
|
|
helDesc.dwDeviceRenderBitDepth = DDBD_32;
|
|
|
|
int ret = gxm_library_init();
|
|
if (ret < 0) {
|
|
SDL_Log("gxm_library_init failed: %08x", ret);
|
|
return;
|
|
}
|
|
|
|
EnumDevice(cb, ctx, "GXM HAL", &halDesc, &helDesc, GXM_GUID);
|
|
}
|