diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index 0cbec886..7ad35f61 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -269,6 +269,11 @@ void Direct3DRMSDL3GPURenderer::SetProjection(D3DRMMATRIX4D perspective, D3DVALU memcpy(&m_uniforms.perspective, perspective, sizeof(D3DRMMATRIX4D)); } +Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* texture) +{ + return NO_TEXTURE_ID; +} + DWORD Direct3DRMSDL3GPURenderer::GetWidth() { return m_width; diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp index 227b701b..05c51043 100644 --- a/miniwin/src/d3drm/backends/software/renderer.cpp +++ b/miniwin/src/d3drm/backends/software/renderer.cpp @@ -1,5 +1,6 @@ #include "d3drmrenderer.h" #include "d3drmrenderer_software.h" +#include "ddsurface_impl.h" #include "miniwin.h" #include @@ -240,6 +241,32 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected( SDL_Color c1 = ApplyLighting(v1); SDL_Color c2 = ApplyLighting(v2); + SDL_Surface* texture = nullptr; + Uint32 texId = v0.texId; + if (texId != NO_TEXTURE_ID) { + texture = m_textures[texId]; + if (texture && SDL_LockSurface(texture)) { + // Pointer to first pixel data + Uint8* pixelAddr = static_cast(texture->pixels); + + Uint32 pixel; + memcpy(&pixel, pixelAddr, m_bytesPerPixel); + + Uint8 r, g, b, a; + SDL_GetRGBA(pixel, m_format, m_palette, &r, &g, &b, &a); + + // TODO use the UV to read out and blend texels on the triangle + c0.r = r; + c0.g = g; + c0.b = b; + c0.a = a; + c1 = c0; + c2 = c0; + + SDL_UnlockSurface(texture); + } + } + Uint8* pixels = (Uint8*) m_backbuffer->pixels; int pitch = m_backbuffer->pitch; @@ -284,6 +311,55 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected( } } +struct TextureDestroyContext { + Direct3DRMSoftwareRenderer* renderer; + Uint32 textureId; +}; + +void Direct3DRMSoftwareRenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture) +{ + auto* ctx = new TextureDestroyContext{this, id}; + texture->AddDestroyCallback( + [](IDirect3DRMObject* obj, void* arg) { + auto* ctx = static_cast(arg); + auto& sufRef = ctx->renderer->m_textures[ctx->textureId]; + SDL_DestroySurface(sufRef); + sufRef = nullptr; + delete ctx; + }, + ctx + ); +} + +Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture) +{ + auto texture = static_cast(iTexture); + auto surface = static_cast(texture->m_surface); + SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, m_backbuffer->format); + // Check if already mapped + for (Uint32 i = 0; i < m_textures.size(); ++i) { + if (m_textures[i] == convertedRender) { + return i; + } + } + + // Reuse freed slot + for (Uint32 i = 0; i < m_textures.size(); ++i) { + auto& texRef = m_textures[i]; + if (texRef == nullptr) { + texRef = convertedRender; + AddTextureDestroyCallback(i, texture); + return i; + } + } + + // Append new + Uint32 newId = static_cast(m_textures.size()); + m_textures.push_back(convertedRender); + AddTextureDestroyCallback(newId, texture); + return newId; +} + DWORD Direct3DRMSoftwareRenderer::GetWidth() { return m_width; diff --git a/miniwin/src/d3drm/d3drmmesh.cpp b/miniwin/src/d3drm/d3drmmesh.cpp index ac852478..b515e981 100644 --- a/miniwin/src/d3drm/d3drmmesh.cpp +++ b/miniwin/src/d3drm/d3drmmesh.cpp @@ -153,8 +153,13 @@ HRESULT Direct3DRMMeshImpl::SetGroupTexture(DWORD groupIndex, IDirect3DRMTexture return DDERR_INVALIDPARAMS; } + auto& group = m_groups[groupIndex]; + if (group.texture) { + group.texture->Release(); + } + texture->AddRef(); - m_groups[groupIndex].texture = texture; + group.texture = texture; return DD_OK; } diff --git a/miniwin/src/d3drm/d3drmtexture.cpp b/miniwin/src/d3drm/d3drmtexture.cpp index 77c5e391..4d53d5d4 100644 --- a/miniwin/src/d3drm/d3drmtexture.cpp +++ b/miniwin/src/d3drm/d3drmtexture.cpp @@ -27,6 +27,6 @@ HRESULT Direct3DRMTextureImpl::Changed(BOOL pixels, BOOL palette) if (!m_surface) { return DDERR_GENERIC; } - MINIWIN_NOT_IMPLEMENTED(); + m_version++; return DD_OK; } diff --git a/miniwin/src/d3drm/d3drmviewport.cpp b/miniwin/src/d3drm/d3drmviewport.cpp index 4dffea61..40636da0 100644 --- a/miniwin/src/d3drm/d3drmviewport.cpp +++ b/miniwin/src/d3drm/d3drmviewport.cpp @@ -221,6 +221,13 @@ HRESULT Direct3DRMViewportImpl::CollectSceneData() D3DCOLOR color = mesh->GetGroupColor(gi); D3DRMRENDERQUALITY quality = mesh->GetGroupQuality(gi); + IDirect3DRMTexture* texture = nullptr; + mesh->GetGroupTexture(gi, &texture); + Uint32 texId = NO_TEXTURE_ID; + if (texture) { + texId = m_renderer->GetTextureId(texture); + texture->Release(); + } for (DWORD fi = 0; fi < faceCount; ++fi) { D3DVECTOR norm; @@ -277,6 +284,7 @@ HRESULT Direct3DRMViewportImpl::CollectSceneData() vtx.g = (color >> 8) & 0xFF; vtx.b = (color >> 0) & 0xFF; vtx.a = (color >> 24) & 0xFF; + vtx.texId = texId; verts.push_back(vtx); } } diff --git a/miniwin/src/ddraw/ddsurface.cpp b/miniwin/src/ddraw/ddsurface.cpp index d76ebd4a..5c8ee6db 100644 --- a/miniwin/src/ddraw/ddsurface.cpp +++ b/miniwin/src/ddraw/ddsurface.cpp @@ -216,7 +216,7 @@ HRESULT DirectDrawSurfaceImpl::Lock( return DDERR_GENERIC; } - if (SDL_LockSurface(m_surface) < 0) { + if (!SDL_LockSurface(m_surface)) { return DDERR_GENERIC; } diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index d00a8035..7be78a32 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -4,10 +4,13 @@ #include +#define NO_TEXTURE_ID 0xffffffff + typedef struct PositionColorVertex { float x, y, z; float nx, ny, nz; Uint8 r, g, b, a; + Uint32 texId = NO_TEXTURE_ID; } PositionColorVertex; struct FColor { @@ -28,6 +31,7 @@ class Direct3DRMRenderer : public IDirect3DDevice2 { virtual void PushVertices(const PositionColorVertex* vertices, size_t count) = 0; virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) = 0; + virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0; virtual DWORD GetWidth() = 0; virtual DWORD GetHeight() = 0; virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0; diff --git a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h index c7b9d88a..92359861 100644 --- a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h +++ b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h @@ -22,6 +22,7 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { void SetBackbuffer(SDL_Surface* backbuffer) override; void PushVertices(const PositionColorVertex* vertices, size_t count) override; void PushLights(const SceneLight* vertices, size_t count) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture) override; void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) override; DWORD GetWidth() override; DWORD GetHeight() override; diff --git a/miniwin/src/internal/d3drmrenderer_software.h b/miniwin/src/internal/d3drmrenderer_software.h index b322aa49..08675adb 100644 --- a/miniwin/src/internal/d3drmrenderer_software.h +++ b/miniwin/src/internal/d3drmrenderer_software.h @@ -1,6 +1,7 @@ #pragma once #include "d3drmrenderer.h" +#include "d3drmtexture_impl.h" #include #include @@ -14,6 +15,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { void SetBackbuffer(SDL_Surface* backbuffer) override; void PushVertices(const PositionColorVertex* vertices, size_t count) override; void PushLights(const SceneLight* vertices, size_t count) override; + Uint32 GetTextureId(IDirect3DRMTexture* texture) override; void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) override; DWORD GetWidth() override; DWORD GetHeight() override; @@ -32,6 +34,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { void ProjectVertex(const PositionColorVertex&, float&, float&, float&) const; void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a); SDL_Color ApplyLighting(const PositionColorVertex& vertex); + void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); DWORD m_width; DWORD m_height; @@ -40,6 +43,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { const SDL_PixelFormatDetails* m_format; int m_bytesPerPixel; std::vector m_lights; + std::vector m_textures; D3DVALUE m_front; D3DVALUE m_back; std::vector m_vertexBuffer; diff --git a/miniwin/src/internal/d3drmtexture_impl.h b/miniwin/src/internal/d3drmtexture_impl.h index 1cc19384..dc3d8b70 100644 --- a/miniwin/src/internal/d3drmtexture_impl.h +++ b/miniwin/src/internal/d3drmtexture_impl.h @@ -8,6 +8,8 @@ struct Direct3DRMTextureImpl : public Direct3DRMObjectBaseImpl