Skip to content

Commit

Permalink
Fix loading 16bit textures and add support for other 16bit formats
Browse files Browse the repository at this point in the history
Zengine have a bug where it don't accept pitch different than ((width >> MipLevel) * bytesPerPixel) when loading mipmaps from tiled texture
  • Loading branch information
SaiyansKing committed Oct 4, 2022
1 parent f3b6cef commit fb7d631
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 17 deletions.
1 change: 1 addition & 0 deletions D3D11Engine/D3D11Engine.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ copy "$(OutDir)$(TargetName).pdb" "$(G1_SYSTEM_PATH)\ddraw.pdb"</Command>
<ClInclude Include="D3D11VertexBuffer.h" />
<ClInclude Include="D3D11VShader.h" />
<ClInclude Include="D3D11_Helpers.h" />
<ClInclude Include="D3D7\Conversions.h" />
<ClInclude Include="D3D7\FakeDirectDrawSurface7.h" />
<ClInclude Include="D3D7\MyClipper.h" />
<ClInclude Include="D3D7\MyDirect3D7.h" />
Expand Down
3 changes: 3 additions & 0 deletions D3D11Engine/D3D11Engine.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,9 @@
<ClInclude Include="oCVisFX.h">
<Filter>ZenGin\Classes</Filter>
</ClInclude>
<ClInclude Include="D3D7\Conversions.h">
<Filter>D3D7</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp" />
Expand Down
113 changes: 113 additions & 0 deletions D3D11Engine/D3D7/Conversions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#pragma once
#include <Windows.h>
#include <intrin.h>

static void Convert555to8888(unsigned char* dst, unsigned char* src, UINT realDataSize)
{
for(UINT i = 0; i < realDataSize / 4; ++i)
{
unsigned char temp0 = src[2 * i + 0];
unsigned char temp1 = src[2 * i + 1];
UINT pixel_data = temp1 << 8 | temp0;

unsigned char blueComponent = (pixel_data & 31) << 3;
unsigned char greenComponent = ((pixel_data >> 5) & 31) << 3;
unsigned char redComponent = ((pixel_data >> 10) & 31) << 3;

dst[4 * i + 2] = redComponent;
dst[4 * i + 1] = greenComponent;
dst[4 * i + 0] = blueComponent;
dst[4 * i + 3] = 255;
}
}

static void Convert565to8888(unsigned char* dst, unsigned char* src, UINT realDataSize)
{
for(UINT i = 0; i < realDataSize / 4; ++i)
{
unsigned char temp0 = src[2 * i + 0];
unsigned char temp1 = src[2 * i + 1];
UINT pixel_data = temp1 << 8 | temp0;

unsigned char redComponent = (pixel_data & 31) << 3;
unsigned char greenComponent = ((pixel_data >> 5) & 63) << 2;
unsigned char blueComponent = ((pixel_data >> 11) & 31) << 3;

dst[4 * i + 2] = redComponent;
dst[4 * i + 1] = greenComponent;
dst[4 * i + 0] = blueComponent;
dst[4 * i + 3] = 255;
}
}

static void Convert1555to8888(unsigned char* dst, unsigned char* src, UINT realDataSize)
{
for(UINT i = 0; i < realDataSize / 4; ++i)
{
unsigned char temp0 = src[2 * i + 0];
unsigned char temp1 = src[2 * i + 1];
UINT pixel_data = temp1 << 8 | temp0;

unsigned char redComponent = (pixel_data & 31) << 3;
unsigned char greenComponent = ((pixel_data >> 5) & 31) << 3;
unsigned char blueComponent = ((pixel_data >> 10) & 31) << 3;
unsigned char alphaComponent = (pixel_data >> 15) * 0xFF;

dst[4 * i + 2] = redComponent;
dst[4 * i + 1] = greenComponent;
dst[4 * i + 0] = blueComponent;
dst[4 * i + 3] = alphaComponent;
}
}

static void Convert4444to8888(unsigned char* dst, unsigned char* src, UINT realDataSize)
{
for(UINT i = 0; i < realDataSize / 4; ++i)
{
unsigned char temp0 = src[2 * i + 0];
unsigned char temp1 = src[2 * i + 1];
UINT pixel_data = temp1 << 8 | temp0;

unsigned char redComponent = (pixel_data & 15) << 4;
unsigned char greenComponent = ((pixel_data >> 4) & 15) << 4;
unsigned char blueComponent = ((pixel_data >> 8) & 15) << 4;
unsigned char alphaComponent = ((pixel_data >> 12) & 15) << 4;

dst[4 * i + 2] = redComponent;
dst[4 * i + 1] = greenComponent;
dst[4 * i + 0] = blueComponent;
dst[4 * i + 3] = alphaComponent;
}
}

static void ConvertRGBAtoBGRA(unsigned char* dst, unsigned char* src, UINT realDataSize)
{
__m128i mask = _mm_setr_epi8(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0);
INT textureDataSize = static_cast<INT>(realDataSize) - 32;
INT i = 0;
for(; i <= textureDataSize; i += 32)
{
__m128i data0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&src[i]));
__m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&src[i + 16]));
__m128i gaComponents0 = _mm_andnot_si128(mask, data0);
__m128i brComponents0 = _mm_and_si128(data0, mask);
__m128i gaComponents1 = _mm_andnot_si128(mask, data1);
__m128i brComponents1 = _mm_and_si128(data1, mask);
__m128i brSwapped0 = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents0, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
__m128i brSwapped1 = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents1, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[i]), _mm_or_si128(gaComponents0, brSwapped0));
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[i + 16]), _mm_or_si128(gaComponents1, brSwapped1));
}
textureDataSize += 32;
for(; i < textureDataSize; i += 4)
{
unsigned char R = src[i + 0];
unsigned char G = src[i + 1];
unsigned char B = src[i + 2];
unsigned char A = src[i + 2];
dst[i + 0] = B;
dst[i + 1] = G;
dst[i + 2] = R;
dst[i + 3] = A;
}
}
17 changes: 15 additions & 2 deletions D3D11Engine/D3D7/FakeDirectDrawSurface7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "../D3D11Texture.h"
#include "../Engine.h"
#include "../GothicAPI.h"
#include "Conversions.h"

FakeDirectDrawSurface7::FakeDirectDrawSurface7() {
RefCount = 0;
Expand Down Expand Up @@ -169,11 +170,23 @@ HRESULT FakeDirectDrawSurface7::Lock( LPRECT lpDestRect, LPDDSURFACEDESC2 lpDDSu
DebugWrite( "FakeDirectDrawSurface7(%p)::Lock(%s, %s)" );
*lpDDSurfaceDesc = OriginalDesc;

// Check for 16-bit surface. We allocate the texture as 32-bit, so we need to divide the size by two for that
int redBits = Toolbox::GetNumberOfBits( OriginalDesc.ddpfPixelFormat.dwRBitMask );
int greenBits = Toolbox::GetNumberOfBits( OriginalDesc.ddpfPixelFormat.dwGBitMask );
int blueBits = Toolbox::GetNumberOfBits( OriginalDesc.ddpfPixelFormat.dwBBitMask );
int alphaBits = Toolbox::GetNumberOfBits( OriginalDesc.ddpfPixelFormat.dwRGBAlphaBitMask );

int bpp = redBits + greenBits + blueBits + alphaBits;
int divisor = 1;

if ( bpp == 16 )
divisor = 2;

// Allocate some temporary data
delete [] Data;
Data = new unsigned char[Resource->GetEngineTexture()->GetSizeInBytes( MipLevel )];
Data = new unsigned char[Resource->GetEngineTexture()->GetSizeInBytes( MipLevel ) / divisor];
lpDDSurfaceDesc->lpSurface = Data;
lpDDSurfaceDesc->lPitch = Resource->GetEngineTexture()->GetRowPitchBytes( MipLevel );
lpDDSurfaceDesc->lPitch = Resource->GetEngineTexture()->GetRowPitchBytes( MipLevel ) / divisor;

int px = (OriginalDesc.dwWidth >> MipLevel);
int py = (OriginalDesc.dwHeight >> MipLevel);
Expand Down
16 changes: 16 additions & 0 deletions D3D11Engine/D3D7/MyDirectDraw.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,22 @@ class MyDirectDraw : public IDirectDraw7 {
lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask = 0x000000FF;
}

// Check potential texture conversions
if ( lpDDSurfaceDesc2->ddpfPixelFormat.dwRGBBitCount == 16 ) {
if ( lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask == 0x7C00
&& lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask == 0x3E0
&& lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask == 0x1F
&& lpDDSurfaceDesc2->ddpfPixelFormat.dwRGBAlphaBitMask == 0x8000 )
lpDDSurfaceDesc2->ddpfPixelFormat.dwFourCC = 1;
else if ( lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask == 0xF00
&& lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask == 0xF0
&& lpDDSurfaceDesc2->ddpfPixelFormat.dwBBitMask == 0x0F
&& lpDDSurfaceDesc2->ddpfPixelFormat.dwRGBAlphaBitMask == 0xF000 )
lpDDSurfaceDesc2->ddpfPixelFormat.dwFourCC = 2;
else
lpDDSurfaceDesc2->ddpfPixelFormat.dwFourCC = 0;
}

// Calculate bpp
int redBits = Toolbox::GetNumberOfBits( lpDDSurfaceDesc2->ddpfPixelFormat.dwRBitMask );
int greenBits = Toolbox::GetNumberOfBits( lpDDSurfaceDesc2->ddpfPixelFormat.dwGBitMask );
Expand Down
22 changes: 7 additions & 15 deletions D3D11Engine/D3D7/MyDirectDrawSurface7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../D3D11GraphicsEngineBase.h"
#include "../D3D11Texture.h"
#include "../zCTexture.h"
#include "Conversions.h"

#define DebugWriteTex(x) DebugWrite(x)

Expand Down Expand Up @@ -404,21 +405,12 @@ HRESULT MyDirectDrawSurface7::Unlock( LPRECT lpRect ) {

if ( bpp == 16 ) {
// Convert
unsigned char* dst = new unsigned char[EngineTexture->GetSizeInBytes( 0 )];
for ( unsigned int i = 0; i < EngineTexture->GetSizeInBytes( 0 ) / 4; i++ ) {
unsigned char temp0 = LockedData[i * 2 + 0];
unsigned char temp1 = LockedData[i * 2 + 1];
unsigned pixel_data = temp1 << 8 | temp0;

unsigned char blueComponent = (pixel_data & 0x1F);
unsigned char greenComponent = (pixel_data >> 6) & 0x1F;
unsigned char redComponent = (pixel_data >> 11) & 0x1F;

// Extract red, green and blue components from the 16 bits
dst[4 * i + 0] = static_cast<unsigned char>((redComponent / 32.0) * 255.0f);
dst[4 * i + 1] = static_cast<unsigned char>((greenComponent / 32.0) * 255.0f);
dst[4 * i + 2] = static_cast<unsigned char>((blueComponent / 32.0) * 255.0f);
dst[4 * i + 3] = 255;
UINT realDataSize = EngineTexture->GetSizeInBytes( 0 );
unsigned char* dst = new unsigned char[realDataSize];
switch ( OriginalSurfaceDesc.ddpfPixelFormat.dwFourCC ) {
case 1: Convert1555to8888( dst, LockedData, realDataSize ); break;
case 2: Convert4444to8888( dst, LockedData, realDataSize ); break;
default: Convert565to8888( dst, LockedData, realDataSize ); break;
}

if ( Engine::GAPI->GetMainThreadID() != GetCurrentThreadId() ) {
Expand Down

0 comments on commit fb7d631

Please sign in to comment.