feat(gx): add broken cursor drawing implementation

This commit is contained in:
superp00t 2024-09-06 12:32:50 -04:00
parent 520b6254b3
commit 9fc5476ef7
16 changed files with 423 additions and 273 deletions

View File

@ -188,6 +188,10 @@ uint32_t GxVertexAttribOffset(EGxVertexBufferFormat format, EGxVertexAttrib attr
return Buffer::s_vertexBufOffset[format][attrib];
}
CGxBuf* GxBufStream(EGxPoolTarget target, uint32_t itemSize, uint32_t itemCount) {
return g_theGxDevicePtr->BufStream(target, itemSize, itemCount);
}
CGxBuf* GxBufCreate(CGxPool* pool, uint32_t itemSize, uint32_t itemCount, uint32_t index) {
return g_theGxDevicePtr->BufCreate(pool, itemSize, itemCount, index);
}

View File

@ -25,6 +25,8 @@ namespace Buffer {
uint32_t GxVertexAttribOffset(EGxVertexBufferFormat, EGxVertexAttrib);
CGxBuf* GxBufStream(EGxPoolTarget target, uint32_t itemSize, uint32_t itemCount);
CGxBuf* GxBufCreate(CGxPool*, uint32_t, uint32_t, uint32_t);
void GxBufData(CGxBuf* buf, const void* data, uint32_t size, uint32_t offset);

View File

@ -22,6 +22,7 @@ class CGxCaps {
int32_t m_texFilterAnisotropic = 0;
uint32_t m_maxTexAnisotropy = 0;
int32_t m_depthBias = 0;
int32_t m_hardwareCursor = 0;
int32_t int130 = 1;
int32_t int134 = 0;
int32_t int138 = 0;

View File

@ -2,10 +2,16 @@
#include "gx/Gx.hpp"
#include "gx/Shader.hpp"
#include "gx/texture/CGxTex.hpp"
#include "gx/Texture.hpp"
#include "gx/RenderState.hpp"
#include "gx/Transform.hpp"
#include "gx/Draw.hpp"
#include "util/SFile.hpp"
#include "event/Input.hpp"
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <limits>
#include <new>
#include <storm/Error.hpp>
@ -97,6 +103,9 @@ uint32_t CGxDevice::s_texFormatBytesPerBlock[] = {
4 // GxTex_D24X8
};
CGxShader* CGxDevice::s_uiVertexShader = nullptr;
CGxShader* CGxDevice::s_uiPixelShader = nullptr;
void CGxDevice::Log(const char* format, ...) {
// TODO
}
@ -144,6 +153,16 @@ uint32_t CGxDevice::PrimCalcCount(EGxPrim primType, uint32_t count) {
return count - CGxDevice::s_primVtxAdjust[primType];
}
void CGxDevice::ICursorUpdate(EGxTexCommand command, uint32_t width, uint32_t height, uint32_t face, uint32_t level, void* userArg, uint32_t& texelStrideInBytes, const void*& texels) {
// TODO
if (command == GxTex_Latch) {
auto device = static_cast<CGxDevice*>(userArg);
texelStrideInBytes = 0x80;
texels = device->m_cursor;
}
}
CGxDevice::CGxDevice() {
// TODO
// - implement rest of constructor
@ -264,7 +283,201 @@ const CRect& CGxDevice::DeviceDefWindow() {
}
void CGxDevice::ICursorCreate(const CGxFormat& format) {
// TODO
int32_t hardwareCursor = format.hwCursor && this->m_caps.m_hardwareCursor;
this->m_hardwareCursor = hardwareCursor;
// If hardware cursor is disabled, and there is no cursor texture yet, create one
if (!hardwareCursor && this->m_cursorTexture == nullptr) {
// default flags?
CGxTexFlags cursorTextureFlags;
// Create a 32x32 cursor texture
GxTexCreate(
32,
32,
GxTex_Argb8888,
cursorTextureFlags,
reinterpret_cast<void*>(this),
CGxDevice::ICursorUpdate,
this->m_cursorTexture
);
}
}
void CGxDevice::ICursorDestroy() {
if (this->m_cursorTexture) {
GxTexDestroy(this->m_cursorTexture);
this->m_cursorTexture = nullptr;
}
}
void CGxDevice::ICursorDraw() {
if (!this->m_cursorVisible) {
return;
}
if (this->m_hardwareCursor) {
return;
}
int32_t mouseX;
int32_t mouseY;
OsInputGetMousePosition(&mouseX, &mouseY);
if (mouseX <= -1 || mouseY <= -1 || mouseX >= this->m_curWindowRect.maxX || mouseY >= this->m_curWindowRect.maxY) {
return;
}
GxRsPush();
// Turn off everything
GxRsSet(GxRs_PolygonOffset, 0);
GxRsSet(GxRs_NormalizeNormals, 0);
GxRsSet(GxRs_BlendingMode, 1);
GxRsSetAlphaRef();
GxRsSet(GxRs_Lighting, 0);
GxRsSet(GxRs_Fog, 0);
GxRsSet(GxRs_DepthTest, 0);
GxRsSet(GxRs_DepthWrite, 0);
GxRsSet(GxRs_ColorWrite, 15);
GxRsSet(GxRs_Culling, 0);
GxRsSet(GxRs_ClipPlaneMask, 0);
GxRsSet(GxRs_Texture0, this->m_cursorTexture);
GxRsSet(GxRs_Texture1, static_cast<CGxTex*>(nullptr));
GxRsSet(GxRs_ColorOp0, 0);
GxRsSet(GxRs_AlphaOp0, 0);
GxRsSet(GxRs_TexGen0, 0);
GxRsSet(GxRs_Unk61, 0);
C44Matrix identity;
GxXformPush(GxXform_World, identity);
float cursorDepth = 1.0f;
C44Matrix projection;
if (!this->StereoEnabled() ||
(CGxDevice::s_uiVertexShader == 0 || !s_uiVertexShader->Valid()) ||
(CGxDevice::s_uiPixelShader == 0 || !s_uiPixelShader->Valid())) {
// Disable shaders
GxRsSet(GxRs_VertexShader, static_cast<CGxShader*>(nullptr));
GxRsSet(GxRs_PixelShader, static_cast<CGxShader*>(nullptr));
} else {
cursorDepth = this->m_cursorDepth;
float minX, maxX, minY, maxY, minZ, maxZ;
GxXformViewport(minX, maxX, minY, maxY, minZ, maxZ);
GxXformProjection(projection);
C44Matrix mProj;
mProj.a0 = 2.0f / (maxX - minX);
mProj.b0 = 0.0f;
mProj.c0 = 0.0f;
mProj.d0 = -((minX + maxX) / (maxX - minX));
mProj.a1 = 0.0f;
mProj.b1 = 2.0f / (maxY - minY);
mProj.c1 = 0.0f;
mProj.d1 = -((minY + maxY) / (maxY - minY));
mProj.a2 = 0.0f;
mProj.b2 = 0.0f;
mProj.c2 = 1.00008f;
mProj.d2 = -0.400016f;
mProj.a3 = 0.0f;
mProj.b3 = 0.0f;
mProj.c3 = 1.0f;
mProj.d3 = 0.0f;
GxXformSetProjection(mProj);
GxRsSet(GxRs_VertexShader, CGxDevice::s_uiVertexShader);
GxRsSet(GxRs_PixelShader, CGxDevice::s_uiPixelShader);
C44Matrix transposition;
GxXformProjNativeTranspose(transposition);
GxShaderConstantsSet(GxSh_Vertex, 0, reinterpret_cast<float*>(&transposition), 0);
}
auto buffer = GxBufStream(GxPoolTarget_Vertex, sizeof(CGxVertexPCT), 4);
auto vertices = reinterpret_cast<CGxVertexPCT*>(GxBufLock(buffer));
if (!vertices) {
return;
}
auto scaleX = this->m_curWindowRect.maxX > 0.0f ? 1.0f / this->m_curWindowRect.maxX : 0.0f;
auto scaleY = this->m_curWindowRect.maxY > 0.0f ? 1.0f / this->m_curWindowRect.maxY : 0.0f;
mouseX -= this->m_cursorHotspotX;
mouseY -= this->m_cursorHotspotY;
auto minX = std::fabsf(static_cast<float>(mouseX)) * scaleX;
auto maxX = std::fabsf(static_cast<float>(mouseX + 32)) * scaleX;
auto minY = 1.0f - (std::fabsf(static_cast<float>(mouseY)) * scaleY);
auto maxY = 1.0f - (std::fabsf(static_cast<float>(mouseY + 32)) * scaleY);
if (this->m_api == GxApi_D3d9 || this->m_api == GxApi_D3d9Ex) {
minX -= (scaleX * 0.5f);
maxX += (scaleX * 0.5f);
minY -= (scaleY * 0.5f);
maxY += (scaleY * 0.5f);
}
// Vertex coordinates
vertices[0].p.x = minX;
vertices[0].p.y = minY;
vertices[0].p.z = cursorDepth;
vertices[1].p.x = minX;
vertices[1].p.y = maxY;
vertices[1].p.z = cursorDepth;
vertices[2].p.x = maxX;
vertices[2].p.y = minY;
vertices[2].p.z = cursorDepth;
vertices[3].p.x = maxX;
vertices[3].p.y = maxY;
vertices[3].p.z = cursorDepth;
// Color values
vertices[0].c = { 0xFF, 0xFF, 0xFF, 0xFF };
vertices[1].c = { 0xFF, 0xFF, 0xFF, 0xFF };
vertices[2].c = { 0xFF, 0xFF, 0xFF, 0xFF };
vertices[3].c = { 0xFF, 0xFF, 0xFF, 0xFF };
// Texture coordinates
vertices[0].tc[0].x = 0.0f;
vertices[0].tc[0].y = 0.0f;
vertices[1].tc[0].x = 0.0f;
vertices[1].tc[0].y = 1.0f;
vertices[2].tc[0].x = 1.0f;
vertices[2].tc[0].y = 0.0f;
vertices[3].tc[0].x = 1.0f;
vertices[3].tc[0].y = 1.0f;
GxBufUnlock(buffer, 0);
GxPrimVertexPtr(buffer, GxVBF_PCT);
CGxBatch batch;
batch.m_primType = GxPrim_TriangleStrip;
batch.m_count = 4;
batch.m_start = 0;
batch.m_minIndex = 0;
batch.m_maxIndex = 3;
GxDraw(&batch, 0);
GxXformPop(GxXform_World);
if (this->StereoEnabled()) {
GxXformSetProjection(projection);
}
GxRsPop();
}
int32_t CGxDevice::IDevIsWindowed() {
@ -1030,6 +1243,12 @@ void CGxDevice::XformPush(EGxXform xf) {
this->m_xforms[xf].Push();
}
// 1-liner for Push/Set
void CGxDevice::XformPush(EGxXform xf, const C44Matrix& matrix) {
this->m_xforms[xf].Push();
this->m_xforms[xf].Top() = matrix;
}
void CGxDevice::XformSet(EGxXform xf, const C44Matrix& matrix) {
this->m_xforms[xf].Top() = matrix;
}
@ -1082,3 +1301,16 @@ void CGxDevice::XformViewport(float& minX, float& maxX, float& minY, float& maxY
minZ = this->m_viewport.z.l;
maxZ = this->m_viewport.z.h;
}
void CGxDevice::CursorSetVisible(int32_t visible) {
this->m_cursorVisible = visible;
}
uint32_t* CGxDevice::CursorLock() {
return this->m_cursor;
}
void CGxDevice::CursorUnlock(uint32_t x, uint32_t y) {
this->m_cursorHotspotX = x;
this->m_cursorHotspotY = y;
}

View File

@ -8,6 +8,7 @@
#include "gx/CGxStateBom.hpp"
#include "gx/Types.hpp"
#include "gx/Shader.hpp"
#include "cursor/Cursor.hpp"
#include <cstdint>
#include <storm/Hash.hpp>
#include <tempest/Box.hpp>
@ -46,6 +47,8 @@ class CGxDevice {
static uint32_t s_streamPoolSize[];
static uint32_t s_texFormatBitDepth[];
static uint32_t s_texFormatBytesPerBlock[];
static CGxShader* s_uiVertexShader;
static CGxShader* s_uiPixelShader;
// Static functions
static void Log(const char* format, ...);
@ -62,6 +65,7 @@ class CGxDevice {
#endif
static CGxDevice* NewOpenGl();
static uint32_t PrimCalcCount(EGxPrim primType, uint32_t count);
static void ICursorUpdate(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&);
// Member variables
TSGrowableArray<CGxPushedRenderState> m_pushedStates;
@ -102,11 +106,20 @@ class CGxDevice {
TSFixedArray<CGxAppRenderState> m_appRenderStates;
TSFixedArray<CGxStateBom> m_hwRenderStates;
uint32_t m_baseMipLevel = 0; // TODO placeholder
int32_t m_cursorVisible = 0;
int32_t m_hardwareCursor = 0;
uint32_t m_cursorHotspotX = 0;
uint32_t m_cursorHotspotY = 0;
uint32_t m_cursor[CURSOR_IMAGE_SIZE] = { 0 };
CGxTex* m_cursorTexture = nullptr;
float m_cursorDepth = 0.0f;
// Virtual member functions
virtual void ITexMarkAsUpdated(CGxTex*) = 0;
virtual void IRsSendToHw(EGxRenderState) = 0;
virtual void ICursorCreate(const CGxFormat& format);
virtual void ICursorDestroy();
virtual void ICursorDraw();
virtual int32_t DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat&);
virtual int32_t DeviceSetFormat(const CGxFormat&);
virtual void* DeviceWindow() = 0;
@ -130,6 +143,9 @@ class CGxDevice {
virtual void ShaderConstantsSet(EGxShTarget, uint32_t, const float*, uint32_t);
virtual void IShaderCreate(CGxShader*) = 0;
virtual int32_t StereoEnabled(void) = 0;
virtual void CursorSetVisible(int32_t visible);
virtual uint32_t* CursorLock();
virtual void CursorUnlock(uint32_t x, uint32_t y);
// Member functions
CGxDevice();
@ -142,6 +158,7 @@ class CGxDevice {
void DeviceSetCurWindow(const CRect&);
void DeviceSetDefWindow(CRect const&);
const CRect& DeviceDefWindow(void);
void ICursorUpdate();
int32_t IDevIsWindowed();
void IRsDirty(EGxRenderState);
void IRsForceUpdate(void);
@ -173,10 +190,12 @@ class CGxDevice {
void XformProjection(C44Matrix&);
void XformProjNative(C44Matrix&);
void XformPush(EGxXform xf);
void XformPush(EGxXform xf, const C44Matrix& matrix);
void XformSet(EGxXform xf, const C44Matrix& matrix);
void XformSetViewport(float, float, float, float, float, float);
void XformView(C44Matrix&);
void XformViewport(float&, float&, float&, float&, float&, float&);
};
#endif

View File

@ -21,6 +21,8 @@ class CGxFormat {
// Member variables
bool hwTnL;
bool hwCursor;
bool fixLag;
int8_t window;
int32_t maximize;
Format depthFormat;

View File

@ -31,6 +31,11 @@ void GxXformPush(EGxXform xf) {
g_theGxDevicePtr->XformPush(xf);
}
// 1-liner for Push/Set
void GxXformPush(EGxXform xf, const C44Matrix& matrix) {
g_theGxDevicePtr->XformPush(xf, matrix);
}
void GxXformSet(EGxXform xf, const C44Matrix& matrix) {
g_theGxDevicePtr->XformSet(xf, matrix);
}

View File

@ -16,6 +16,8 @@ void GxXformProjNativeTranspose(C44Matrix&);
void GxXformPush(EGxXform xf);
void GxXformPush(EGxXform xf, const C44Matrix& matrix);
void GxXformSet(EGxXform xf, const C44Matrix& matrix);
void GxXformSetProjection(const C44Matrix&);

View File

@ -339,10 +339,17 @@ enum PIXEL_FORMAT {
};
struct C4Pixel {
char b;
char g;
char r;
char a;
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
struct C4LargePixel {
uint64_t b;
uint64_t g;
uint64_t r;
uint64_t a;
};
struct MipBits {

View File

@ -336,12 +336,7 @@ LRESULT CGxDeviceD3d::WindowProcD3d(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
if (device) {
if (device->m_d3dDevice && lParam == 1) {
SetCursor(nullptr);
BOOL show = TRUE;
// if (device->unk2904[0x13] == 0) || (device->.unk2904[0x14] == 0)) {
// show = FALSE;
// } else {
// show = TRUE;
// }
BOOL show = device->m_cursorVisible && device->m_hardwareCursor ? TRUE : FALSE;
device->m_d3dDevice->ShowCursor(show);
}
}
@ -889,6 +884,8 @@ int32_t CGxDeviceD3d::ICreateD3dDevice(const CGxFormat& format) {
this->IStateSetD3dDefaults();
this->ICursorCreate(format);
// TODO
return 1;
@ -1199,6 +1196,94 @@ void CGxDeviceD3d::IRsSendToHw(EGxRenderState which) {
}
}
void CGxDeviceD3d::ICursorCreate(const CGxFormat& format) {
CGxDevice::ICursorCreate(format);
if (this->m_hardwareCursor && this->m_hwCursorTexture == nullptr) {
this->m_d3dDevice->CreateTexture(
32,
32,
1,
0,
D3DFMT_A8R8G8B8,
D3DPOOL_MANAGED,
&this->m_hwCursorTexture,
nullptr);
if (this->m_hwCursorTexture) {
this->m_hwCursorTexture->GetSurfaceLevel(0, &this->m_hwCursorBitmap);
}
this->m_hwCursorNeedsUpdate = 1;
this->ICursorDraw();
}
}
void CGxDeviceD3d::ICursorDestroy() {
CGxDevice::ICursorDestroy();
if (this->m_hwCursorBitmap) {
this->m_hwCursorBitmap->Release();
this->m_hwCursorBitmap = nullptr;
}
if (this->m_hwCursorTexture) {
this->m_hwCursorTexture->Release();
this->m_hwCursorTexture = nullptr;
}
}
void CGxDeviceD3d::CursorSetVisible(int32_t visible) {
CGxDevice::CursorSetVisible(visible);
if (this->m_hardwareCursor && this->m_context) {
POINT point;
RECT rect;
GetCursorPos(&point);
ScreenToClient(this->m_hwnd, &point);
GetClientRect(this->m_hwnd, &rect);
if (rect.left <= point.x && (point.x < rect.right && (rect.top <= point.y)) && point.y < rect.bottom) {
this->m_d3dDevice->ShowCursor(this->m_cursorVisible);
}
}
}
void CGxDeviceD3d::ICursorDraw() {
if (!this->m_hardwareCursor) {
this->ISceneBegin();
}
CGxDevice::ICursorDraw();
if (!this->m_hardwareCursor) {
this->ISceneEnd();
if (!this->m_hardwareCursor) {
return;
}
}
if (this->m_hwCursorNeedsUpdate && this->m_hwCursorBitmap && this->m_context) {
D3DLOCKED_RECT lockedRect;
if SUCCEEDED(this->m_hwCursorBitmap->LockRect(&lockedRect, nullptr, 0)) {
// upload cursor texture data
auto src = reinterpret_cast<uint8_t*>(this->m_cursor);
for (int32_t i = 0; i < 32; i++) {
auto dest = reinterpret_cast<uint8_t*>(lockedRect.pBits) + (lockedRect.Pitch * i);
memcpy(dest, src, 128);
src += 128;
}
this->m_hwCursorBitmap->UnlockRect();
this->m_d3dDevice->SetCursorProperties(this->m_cursorHotspotX, this->m_cursorHotspotY, this->m_hwCursorBitmap);
}
this->m_hwCursorNeedsUpdate = 0;
}
}
void CGxDeviceD3d::ISceneBegin() {
if (this->m_context) {
this->ShaderConstantsClear();
@ -1303,6 +1388,10 @@ void CGxDeviceD3d::ISetCaps(const CGxFormat& format) {
// TODO modify shader targets based on format
// Detect hardware cursor
this->m_caps.m_hardwareCursor = this->m_d3dCaps.CursorCaps & D3DCURSORCAPS_COLOR;
// Texture formats
for (int32_t i = 0; i < GxTexFormats_Last; i++) {
@ -1596,7 +1685,7 @@ void CGxDeviceD3d::IStateSync() {
this->IShaderConstantsFlush();
this->IRsSync(0);
if (this->m_hwRenderStates[GxRs_VertexShader] == nullptr && this->m_appRenderStates[GxRs_VertexShader].m_value == nullptr) {
if (this->m_hwRenderStates[GxRs_VertexShader] == nullptr || this->m_appRenderStates[GxRs_VertexShader].m_value == nullptr) {
this->IStateSyncLights();
this->IStateSyncMaterial();
this->IStateSyncXforms();
@ -1734,7 +1823,9 @@ void CGxDeviceD3d::IStateSyncXforms() {
this->m_xforms[GxXform_View].m_dirty = 0;
}
// TODO world
if (this->m_xforms[GxXform_World].m_dirty) {
this->IXformSetWorld();
}
// TODO tex
}
@ -1932,6 +2023,7 @@ UNLOCK:
void CGxDeviceD3d::IXformSetProjection(const C44Matrix& matrix) {
#if defined(_MSC_VER)
// This is the correct way
DirectX::XMMATRIX projNative;
memcpy(&projNative, &matrix, sizeof(projNative));
@ -1966,6 +2058,8 @@ void CGxDeviceD3d::IXformSetProjection(const C44Matrix& matrix) {
this->m_xforms[GxXform_Projection].m_dirty = 1;
memcpy(&this->m_projNative, &projNative, sizeof(this->m_projNative));
#else
// Without the DirectX::XMMATRIX, we can soldier on
// with a Tempest matrix
C44Matrix projNative;
memcpy(&projNative, &matrix, sizeof(projNative));
@ -2026,6 +2120,19 @@ void CGxDeviceD3d::IXformSetViewport() {
this->intF6C = 0;
}
void CGxDeviceD3d::IXformSetWorld() {
static int32_t isIdent = 0;
auto& stack = this->m_xforms[GxXform_World];
if (!isIdent || !(stack.m_flags[stack.m_level] & CGxMatrixStack::F_Identity)) {
this->m_d3dDevice->SetTransform(D3DTS_WORLD, reinterpret_cast<const D3DMATRIX*>(&stack.TopConst()));
}
isIdent = stack.m_flags[stack.m_level] & CGxMatrixStack::F_Identity;
stack.m_dirty = 0;
}
void CGxDeviceD3d::PoolSizeSet(CGxPool* pool, uint32_t size) {
// TODO
}
@ -2059,6 +2166,8 @@ void CGxDeviceD3d::ScenePresent() {
CGxDevice::ScenePresent();
this->ISceneEnd();
this->ICursorDraw();
// TODO
// TODO fixLag
@ -2092,3 +2201,4 @@ void CGxDeviceD3d::XformSetProjection(const C44Matrix& matrix) {
CGxDevice::XformSetProjection(matrix);
this->IXformSetProjection(matrix);
}

View File

@ -235,6 +235,9 @@ class CGxDeviceD3d : public CGxDevice {
D3DFORMAT m_devAdapterFormat;
LPDIRECT3DSURFACE9 m_defColorSurface = nullptr;
LPDIRECT3DSURFACE9 m_defDepthSurface = nullptr;
int32_t m_hwCursorNeedsUpdate = 1;
LPDIRECT3DTEXTURE9 m_hwCursorTexture = nullptr;
LPDIRECT3DSURFACE9 m_hwCursorBitmap = nullptr;
LPDIRECT3DVERTEXDECLARATION9 m_d3dCurrentVertexDecl;
LPDIRECT3DINDEXBUFFER9 m_d3dCurrentIndexBuf;
LPDIRECT3DVERTEXBUFFER9 m_d3dVertexStreamBuf[8];
@ -245,6 +248,10 @@ class CGxDeviceD3d : public CGxDevice {
// Virtual member functions
virtual void ITexMarkAsUpdated(CGxTex* texId);
virtual void IRsSendToHw(EGxRenderState which);
virtual void ICursorCreate(const CGxFormat& format);
virtual void ICursorDestroy();
virtual void ICursorDraw();
virtual void CursorSetVisible(int32_t visible);
virtual int32_t DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat& format);
virtual int32_t DeviceSetFormat(const CGxFormat& format);
virtual void* DeviceWindow();
@ -302,6 +309,7 @@ class CGxDeviceD3d : public CGxDevice {
void ITexUpload(CGxTex* texId);
void IXformSetProjection(const C44Matrix& matrix);
void IXformSetViewport();
void IXformSetWorld();
};
#endif

View File

@ -703,6 +703,8 @@ void CGxDeviceGLL::ISetCaps(const CGxFormat& format) {
this->m_caps.m_texMaxSize[GxTex_Rectangle] = 4096;
this->m_caps.m_texMaxSize[GxTex_NonPow2] = 4096;
this->m_caps.m_hardwareCursor = 0;
// TODO
}

View File

@ -320,7 +320,7 @@ int32_t CGxDeviceGLSDL::DeviceSetFormat(const CGxFormat& format) {
}
void* CGxDeviceGLSDL::DeviceWindow() {
return &this->m_GLSDLWindow;
return this->m_GLSDLWindow.m_sdlWindow;
}
void CGxDeviceGLSDL::Draw(CGxBatch* batch, int32_t indexed) {
@ -681,6 +681,8 @@ void CGxDeviceGLSDL::ISetCaps(const CGxFormat& format) {
this->m_caps.m_texMaxSize[GxTex_Rectangle] = 4096;
this->m_caps.m_texMaxSize[GxTex_NonPow2] = 4096;
this->m_caps.m_hardwareCursor = 0;
// TODO
}
@ -926,7 +928,17 @@ void CGxDeviceGLSDL::IStateSyncVertexPtrs() {
);
}
void CGxDeviceGLSDL::IXformSetWorld() {
auto& stack = this->m_xforms[GxXform_World];
this->m_GLSDLDevice.SetTransform('WRLD', reinterpret_cast<const float*>(&stack.TopConst()));
stack.m_dirty = 0;
}
void CGxDeviceGLSDL::IStateSyncXforms() {
if (this->m_xforms[GxXform_World].m_dirty) {
this->IXformSetWorld();
}
// TODO this->IXformSetWorld();
// TODO this->IXformSetTex();
@ -1268,13 +1280,13 @@ void CGxDeviceGLSDL::SceneClear(uint32_t mask, CImVector color) {
}
void CGxDeviceGLSDL::ScenePresent() {
this->m_GLSDLWindow.DispatchEvents();
if (this->m_context) {
// TODO
CGxDevice::ScenePresent();
this->ICursorDraw();
// TODO
this->m_GLSDLDevice.Swap();

View File

@ -74,6 +74,7 @@ class CGxDeviceGLSDL : public CGxDevice {
void IXformSetProjection(const C44Matrix&);
void IXformSetView(const C44Matrix&);
void IXformSetViewport();
void IXformSetWorld();
void PatchPixelShader(CGxShader*);
void PatchVertexShader(CGxShader*);
void Resize(uint32_t width, uint32_t height);

View File

@ -12,136 +12,6 @@
static bool s_GLSDL_Initialized = false;
static const std::map<SDL_Scancode, KEY> s_keyConversion = {
{SDL_SCANCODE_LSHIFT, KEY_LSHIFT},
{SDL_SCANCODE_RSHIFT, KEY_RSHIFT},
{SDL_SCANCODE_LCTRL, KEY_LCONTROL},
{SDL_SCANCODE_RCTRL, KEY_RCONTROL},
{SDL_SCANCODE_LALT, KEY_LALT},
{SDL_SCANCODE_RALT, KEY_RALT},
{SDL_SCANCODE_SPACE, KEY_SPACE},
{SDL_SCANCODE_0, KEY_0},
{SDL_SCANCODE_1, KEY_1},
{SDL_SCANCODE_2, KEY_2},
{SDL_SCANCODE_3, KEY_3},
{SDL_SCANCODE_4, KEY_4},
{SDL_SCANCODE_5, KEY_5},
{SDL_SCANCODE_6, KEY_6},
{SDL_SCANCODE_7, KEY_7},
{SDL_SCANCODE_8, KEY_8},
{SDL_SCANCODE_9, KEY_9},
{SDL_SCANCODE_A, KEY_A},
{SDL_SCANCODE_B, KEY_B},
{SDL_SCANCODE_C, KEY_C},
{SDL_SCANCODE_D, KEY_D},
{SDL_SCANCODE_E, KEY_E},
{SDL_SCANCODE_F, KEY_F},
{SDL_SCANCODE_G, KEY_G},
{SDL_SCANCODE_H, KEY_H},
{SDL_SCANCODE_I, KEY_I},
{SDL_SCANCODE_J, KEY_J},
{SDL_SCANCODE_K, KEY_K},
{SDL_SCANCODE_L, KEY_L},
{SDL_SCANCODE_M, KEY_M},
{SDL_SCANCODE_N, KEY_N},
{SDL_SCANCODE_O, KEY_O},
{SDL_SCANCODE_P, KEY_P},
{SDL_SCANCODE_Q, KEY_Q},
{SDL_SCANCODE_R, KEY_R},
{SDL_SCANCODE_S, KEY_S},
{SDL_SCANCODE_T, KEY_T},
{SDL_SCANCODE_U, KEY_U},
{SDL_SCANCODE_V, KEY_V},
{SDL_SCANCODE_W, KEY_W},
{SDL_SCANCODE_X, KEY_X},
{SDL_SCANCODE_Y, KEY_Y},
{SDL_SCANCODE_Z, KEY_Z},
{SDL_SCANCODE_GRAVE, KEY_TILDE},
{SDL_SCANCODE_KP_0, KEY_NUMPAD0},
{SDL_SCANCODE_KP_1, KEY_NUMPAD1},
{SDL_SCANCODE_KP_2, KEY_NUMPAD2},
{SDL_SCANCODE_KP_3, KEY_NUMPAD3},
{SDL_SCANCODE_KP_4, KEY_NUMPAD4},
{SDL_SCANCODE_KP_5, KEY_NUMPAD5},
{SDL_SCANCODE_KP_6, KEY_NUMPAD6},
{SDL_SCANCODE_KP_7, KEY_NUMPAD7},
{SDL_SCANCODE_KP_8, KEY_NUMPAD8},
{SDL_SCANCODE_KP_9, KEY_NUMPAD9},
{SDL_SCANCODE_KP_PLUS, KEY_NUMPAD_PLUS},
{SDL_SCANCODE_KP_MINUS, KEY_NUMPAD_MINUS},
{SDL_SCANCODE_KP_MULTIPLY, KEY_NUMPAD_MULTIPLY},
{SDL_SCANCODE_KP_DIVIDE, KEY_NUMPAD_DIVIDE},
{SDL_SCANCODE_KP_DECIMAL, KEY_NUMPAD_DECIMAL},
{SDL_SCANCODE_KP_EQUALS, KEY_NUMPAD_EQUALS},
{SDL_SCANCODE_EQUALS, KEY_PLUS},
{SDL_SCANCODE_MINUS, KEY_MINUS},
{SDL_SCANCODE_LEFTBRACKET, KEY_BRACKET_OPEN},
{SDL_SCANCODE_RIGHTBRACKET, KEY_BRACKET_CLOSE},
{SDL_SCANCODE_SLASH, KEY_SLASH},
{SDL_SCANCODE_BACKSLASH, KEY_BACKSLASH},
{SDL_SCANCODE_SEMICOLON, KEY_SEMICOLON},
{SDL_SCANCODE_APOSTROPHE, KEY_APOSTROPHE},
{SDL_SCANCODE_COMMA, KEY_COMMA},
{SDL_SCANCODE_PERIOD, KEY_PERIOD},
{SDL_SCANCODE_ESCAPE, KEY_ESCAPE},
{SDL_SCANCODE_RETURN, KEY_ENTER},
{SDL_SCANCODE_BACKSPACE, KEY_BACKSPACE},
{SDL_SCANCODE_TAB, KEY_TAB},
{SDL_SCANCODE_LEFT, KEY_LEFT},
{SDL_SCANCODE_UP, KEY_UP},
{SDL_SCANCODE_RIGHT, KEY_RIGHT},
{SDL_SCANCODE_DOWN, KEY_DOWN},
{SDL_SCANCODE_INSERT, KEY_INSERT},
{SDL_SCANCODE_DELETE, KEY_DELETE},
{SDL_SCANCODE_HOME, KEY_HOME},
{SDL_SCANCODE_END, KEY_END},
{SDL_SCANCODE_PAGEUP, KEY_PAGEUP},
{SDL_SCANCODE_PAGEDOWN, KEY_PAGEDOWN},
{SDL_SCANCODE_CAPSLOCK, KEY_CAPSLOCK},
{SDL_SCANCODE_NUMLOCKCLEAR, KEY_NUMLOCK},
{SDL_SCANCODE_SCROLLLOCK, KEY_SCROLLLOCK},
{SDL_SCANCODE_PAUSE, KEY_PAUSE},
{SDL_SCANCODE_PRINTSCREEN, KEY_PRINTSCREEN},
{SDL_SCANCODE_F1, KEY_F1},
{SDL_SCANCODE_F2, KEY_F2},
{SDL_SCANCODE_F3, KEY_F3},
{SDL_SCANCODE_F4, KEY_F4},
{SDL_SCANCODE_F5, KEY_F5},
{SDL_SCANCODE_F6, KEY_F6},
{SDL_SCANCODE_F7, KEY_F7},
{SDL_SCANCODE_F8, KEY_F8},
{SDL_SCANCODE_F9, KEY_F9},
{SDL_SCANCODE_F10, KEY_F10},
{SDL_SCANCODE_F11, KEY_F11},
{SDL_SCANCODE_F12, KEY_F12},
{SDL_SCANCODE_F13, KEY_F13},
{SDL_SCANCODE_F14, KEY_F14},
{SDL_SCANCODE_F15, KEY_F15},
{SDL_SCANCODE_F16, KEY_F16},
{SDL_SCANCODE_F17, KEY_F17},
{SDL_SCANCODE_F18, KEY_F18},
{SDL_SCANCODE_F19, KEY_F19}
};
static MOUSEBUTTON s_buttonConversion[16] = {
MOUSE_BUTTON_NONE,
MOUSE_BUTTON_LEFT,
MOUSE_BUTTON_MIDDLE,
MOUSE_BUTTON_RIGHT,
MOUSE_BUTTON_XBUTTON1,
MOUSE_BUTTON_XBUTTON2,
MOUSE_BUTTON_XBUTTON3,
MOUSE_BUTTON_XBUTTON4,
MOUSE_BUTTON_XBUTTON5,
MOUSE_BUTTON_XBUTTON6,
MOUSE_BUTTON_XBUTTON7,
MOUSE_BUTTON_XBUTTON8,
MOUSE_BUTTON_XBUTTON9,
MOUSE_BUTTON_XBUTTON10,
MOUSE_BUTTON_XBUTTON11,
MOUSE_BUTTON_XBUTTON12
};
void GLSDLWindow::Create(const char* title, const GLSDLWindowRect& rect, GLTextureFormat depthFormat, uint32_t sampleCount) {
BLIZZARD_ASSERT(this->m_sdlWindow == nullptr);
@ -213,13 +83,6 @@ void GLSDLWindow::Swap() {
SDL_GL_SwapWindow(this->m_sdlWindow);
}
void GLSDLWindow::DispatchEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
this->DispatchSDLEvent(event);
}
}
void GLSDLWindow::Destroy() {
SDL_DestroyWindow(this->m_sdlWindow);
this->m_sdlWindow = nullptr;
@ -275,116 +138,3 @@ int32_t GLSDLWindow::GetHeight() {
return this->GetBackingRect().size.height;
}
void GLSDLWindow::DispatchSDLEvent(const SDL_Event& event) {
switch (event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
this->DispatchSDLKeyboardEvent(event);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
this->DispatchSDLMouseButtonEvent(event);
break;
case SDL_MOUSEMOTION:
this->DispatchSDLMouseMotionEvent(event);
break;
case SDL_TEXTINPUT:
this->DispatchSDLTextInputEvent(event);
break;
case SDL_WINDOWEVENT_RESIZED:
this->DispatchSDLWindowResizedEvent(event);
break;
case SDL_QUIT:
EventPostClose();
break;
default:
break;
}
}
void GLSDLWindow::DispatchSDLKeyboardEvent(const SDL_Event& event) {
// Is this an up or down keypress?
OSINPUT inputclass = event.type == SDL_KEYUP ? OS_INPUT_KEY_UP : OS_INPUT_KEY_DOWN;
// What key does this SDL scancode correspond to?
auto lookup = s_keyConversion.find(event.key.keysym.scancode);
if (lookup != s_keyConversion.end()) {
// Scancode was found
KEY key = lookup->second;
// Push key event into input queue
OsQueuePut(inputclass, key, 0, 0, 0);
return;
}
}
void GLSDLWindow::DispatchSDLMouseMotionEvent(const SDL_Event& event) {
auto x = static_cast<int32_t>(event.motion.x);
auto y = static_cast<int32_t>(event.motion.y);
OsQueuePut(OS_INPUT_MOUSE_MOVE, 0, x, y, 0);
}
void GLSDLWindow::DispatchSDLMouseButtonEvent(const SDL_Event& event) {
// Is this an up or down mouse click?
OSINPUT inputclass = event.type == SDL_MOUSEBUTTONUP ? OS_INPUT_MOUSE_UP : OS_INPUT_MOUSE_DOWN;
// XY click coordinates
auto x = static_cast<int32_t>(event.button.x);
auto y = static_cast<int32_t>(event.button.y);
// Convert SDL button index into internal MOUSEBUTTON ID
auto buttonIndex = event.button.button;
if (buttonIndex > 15) {
return;
}
auto button = s_buttonConversion[buttonIndex];
// Push mousebutton event into input queue
OsQueuePut(inputclass, button, x, y, 0);
}
void GLSDLWindow::DispatchSDLTextInputEvent(const SDL_Event& event) {
// text input string holding one or more UTF-8 characters
auto text = reinterpret_cast<const uint8_t*>(event.text.text);
// Because SDL_TextInputEvent can hold multiple UTF-8 characters
// explode variable number of these characters into
// individual OS_INPUT_CHAR events
while (*text != '\0') {
// byte size of current UTF-8 character
int32_t charactersize = 0;
// Read UTF-8 character
auto character = static_cast<int32_t>(SUniSGetUTF8(text, &charactersize));
if (character < 0) {
// Cancel in case of invalid input
break;
}
// Push character to input queue
OsQueuePut(OS_INPUT_CHAR, character, 1, 0, 0);
// Advance text pointer
text += charactersize;
}
}
void GLSDLWindow::DispatchSDLWindowResizedEvent(const SDL_Event& event) {
auto width = static_cast<int32_t>(event.window.data1);
auto height = static_cast<int32_t>(event.window.data2);
static_cast<CGxDeviceGLSDL*>(g_theGxDevicePtr)->Resize(width, height);
OsQueuePut(OS_INPUT_SIZE, width, height, 0, 0);
auto bounds = GetSavedWindowBounds();
Rect newBounds = {
bounds->top,
bounds->left,
static_cast<int16_t>(bounds->top + height),
static_cast<int16_t>(bounds->left + width)
};
SetSavedWindowBounds(newBounds);
}

View File

@ -30,13 +30,6 @@ class GLSDLWindow {
void Create(const char* title, const GLSDLWindowRect& rect, GLTextureFormat depthFormat, uint32_t sampleCount);
void Destroy();
void Swap();
void DispatchEvents();
void DispatchSDLEvent(const SDL_Event& event);
void DispatchSDLKeyboardEvent(const SDL_Event& event);
void DispatchSDLMouseMotionEvent(const SDL_Event& event);
void DispatchSDLMouseButtonEvent(const SDL_Event& event);
void DispatchSDLTextInputEvent(const SDL_Event& event);
void DispatchSDLWindowResizedEvent(const SDL_Event& event);
void Resize(const GLSDLWindowRect& rect);
GLSDLWindowRect GetRect();