This commit is contained in:
gabest
2008-12-01 10:59:20 +00:00
parent 2bf7d2c879
commit ef7dc5be54
22 changed files with 2339 additions and 2424 deletions

View File

@@ -102,7 +102,7 @@ EXPORT_C_(INT32) GPUopen(HWND hWnd)
rs.m_aspectratio = AfxGetApp()->GetProfileInt(_T("Settings"), _T("aspectratio"), 1);
rs.m_vsync = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("vsync"), FALSE);
s_gpu = new GPURendererSW<GSDevice10>(rs);
s_gpu = new GPURendererSW<GSDevice9>(rs);
s_hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);

File diff suppressed because it is too large Load Diff

View File

@@ -59,7 +59,7 @@ class GPUDrawScanline : public GSAlignedClass<16>, public IDrawScanline
__declspec(align(16)) struct ScanlineEnvironment
{
WORD* vm;
GPULocalMemory* mem;
const void* tex;
const WORD* clut;
@@ -69,22 +69,25 @@ class GPUDrawScanline : public GSAlignedClass<16>, public IDrawScanline
GSVector4i a;
GSVector4i md; // similar to gs fba
GSVector4 ds[3], dt[3];
GSVector4i dr, dg, db, dc;
};
ScanlineSelector m_sel;
ScanlineEnvironment m_slenv;
typedef void (GPUDrawScanline::*DrawScanlinePtr)(int top, int left, int right, const Vertex& v, const Vertex& dv);
DrawScanlinePtr m_ds[2048], m_dsf;
void InitEx();
void Init();
void DrawScanlineT(int top, int left, int right, const Vertex& v);
template<DWORD sel>
void DrawScanlineExT(int top, int left, int right, const Vertex& v, const Vertex& dv);
void DrawScanlineExT(int top, int left, int right, const Vertex& v);
__forceinline void SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin, GSVector4i& test, const GSVector4* s, const GSVector4* t, GSVector4i* c);
__forceinline void ColorTFX(DWORD tfx, const GSVector4* r, const GSVector4* g, const GSVector4* b, GSVector4i* c);
__forceinline void ColorTFX(DWORD tfx, const GSVector4i& r, const GSVector4i& g, const GSVector4i& b, GSVector4i* c);
__forceinline void AlphaBlend(UINT32 abr, UINT32 tme, const GSVector4i& d, GSVector4i* c);
__forceinline void WriteFrame(WORD* RESTRICT fb, const GSVector4i& test, const GSVector4i* c, int pixels);
@@ -102,6 +105,8 @@ public:
// IDrawScanline
void SetupDraw(Vertex* vertices, int count, const void* texture);
void DrawScanline(int top, int left, int right, const Vertex& v, const Vertex& dv);
void SetupScanline(const Vertex& dv);
void DrawScanline(int top, int left, int right, const Vertex& v);
void FillRect(const GSVector4i& r, const Vertex& v);
DrawScanlinePtr GetDrawScanlinePtr();
};

View File

@@ -39,107 +39,226 @@ static void CheckRect(const CRect& r)
GPULocalMemory::GPULocalMemory()
{
m_vm8 = (BYTE*)VirtualAlloc(NULL, m_vmsize * 2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
m_vm = (WORD*)VirtualAlloc(NULL, m_size * 2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
memset(m_vm8, 0, m_vmsize);
memset(m_vm, 0, m_size * 2);
//
m_clut.buff = m_vm + m_size;
m_clut.dirty = true;
//
int size = 256 * 256 * (1 + 1 + 4) * 32;
m_texture.buff[0] = (BYTE*)VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
m_texture.buff[1] = m_texture.buff[0] + 256 * 256 * 32;
m_texture.buff[2] = m_texture.buff[1] + 256 * 256 * 32;
memset(m_texture.buff[0], 0, size);
memset(m_texture.valid, 0, sizeof(m_texture.valid));
for(int y = 0, offset = 0; y < 2; y++)
{
for(int x = 0; x < 16; x++, offset += 256 * 256)
{
m_texture.page[0][y][x] = &((BYTE*)m_texture.buff[0])[offset];
m_texture.page[1][y][x] = &((BYTE*)m_texture.buff[1])[offset];
}
}
for(int y = 0, offset = 0; y < 2; y++)
{
for(int x = 0; x < 16; x++, offset += 256 * 256)
{
m_texture.page[2][y][x] = &((DWORD*)m_texture.buff[2])[offset];
}
}
}
GPULocalMemory::~GPULocalMemory()
{
VirtualFree(m_vm8, 0, MEM_RELEASE);
VirtualFree(m_vm, 0, MEM_RELEASE);
VirtualFree(m_texture.buff[0], 0, MEM_RELEASE);
}
const WORD* GPULocalMemory::GetCLUT(int tp, int cx, int cy)
{
if(m_clut.dirty || m_clut.tp != tp || m_clut.cx != cx || m_clut.cy != cy)
{
WORD* src = GetPixelAddress(cx << (4 + 1), cy << 1);
WORD* dst = m_clut.buff;
// TODO: at normal horizontal resolution just return src
if(tp == 0)
{
for(int i = 0; i < 16; i++)
{
dst[i] = src[i * 2];
}
}
else if(tp == 1)
{
for(int i = 0; i < 256; i++)
{
dst[i] = src[i * 2];
}
}
m_clut.tp = tp;
m_clut.cx = cx;
m_clut.cy = cy;
m_clut.dirty = false;
}
return m_clut.buff;
}
const void* GPULocalMemory::GetTexture(int tp, int tx, int ty)
{
if(tp == 3)
{
ASSERT(0);
return NULL;
}
void* buff = m_texture.page[tp][ty][tx];
UINT32 flag = 1 << tx;
if((m_texture.valid[tp][ty] & flag) == 0)
{
int bpp = 0;
switch(tp)
{
case 0:
ReadPage4(tx, ty, (BYTE*)buff);
bpp = 4;
break;
case 1:
ReadPage8(tx, ty, (BYTE*)buff);
bpp = 8;
break;
case 2:
case 3:
ReadPage16(tx, ty, (WORD*)buff);
bpp = 16;
default:
// FIXME: __assume(0); // vc9 generates bogus code in release mode
break;
}
// TODO: m_state->m_perfmon.Put(GSPerfMon::Unswizzle, 256 * 256 * bpp >> 3);
m_texture.valid[tp][ty] |= flag;
}
return buff;
}
void GPULocalMemory::Invalidate(const CRect& r)
{
if(!m_clut.dirty)
{
if(r.top <= m_clut.cy && m_clut.cy < r.bottom)
{
int left = m_clut.cx << 4;
int right = left + (m_clut.tp == 0 ? 16 : 256);
if(r.left < right && r.right > left)
{
m_clut.dirty = true;
}
}
}
for(int y = 0, ye = min(r.bottom, 512), j = 0; y < ye; y += 256, j++)
{
if(r.top >= y + 256) continue;
for(int x = 0, xe = min(r.right, 1024), i = 0; x < xe; x += 64, i++)
{
DWORD flag = 1 << i;
if(r.left >= x + 256) continue;
m_texture.valid[2][j] &= ~flag;
if(r.left >= x + 128) continue;
m_texture.valid[1][j] &= ~flag;
if(r.left >= x + 64) continue;
m_texture.valid[0][j] &= ~flag;
}
}
}
void GPULocalMemory::FillRect(const CRect& r, WORD c)
{
CheckRect(r);
CRect clip;
clip.left = (r.left + 7) & ~7;
clip.top = r.top;
clip.right = r.right & ~7;
clip.bottom = r.bottom;
Invalidate(r);
for(int y = r.top; y < clip.top; y++)
WORD* RESTRICT dst = GetPixelAddress(r.left << 1, r.top << 1);
int w = r.Width() << 1;
int h = r.Height() << 1;
for(int j = 0; j < h; j++, dst += m_width)
{
WORD* p = &m_vm16[y << 10];
for(int x = r.left; x < r.right; x++)
for(int i = 0; i < w; i++)
{
p[x] = c;
}
}
for(int y = clip.bottom; y < r.bottom; y++)
{
WORD* p = &m_vm16[y << 10];
for(int x = r.left; x < r.right; x++)
{
p[x] = c;
}
}
if(r.left < clip.left || clip.right < r.right)
{
for(int y = clip.top; y < clip.bottom; y++)
{
WORD* p = &m_vm16[y << 10];
for(int x = r.left; x < clip.left; x++)
{
p[x] = c;
}
for(int x = clip.right; x < r.right; x++)
{
p[x] = c;
}
}
}
GSVector4i c128((c << 16) | c);
for(int y = clip.top; y < clip.bottom; y++)
{
GSVector4i* p = (GSVector4i*)&m_vm16[(y << 10) + clip.left];
for(int i = 0, n = (clip.right - clip.left) >> 3; i < n; i++)
{
p[i] = c128;
dst[i] = c;
}
}
}
void GPULocalMemory::WriteRect(const CRect& r, const WORD* c)
void GPULocalMemory::WriteRect(const CRect& r, const WORD* RESTRICT src)
{
CheckRect(r);
Invalidate(r);
WORD* RESTRICT dst = GetPixelAddress(r.left << 1, r.top << 1);
int w = r.Width();
int h = r.Height();
for(int y = r.top; y < r.bottom; y++)
for(int j = 0; j < h; j++, src += w, dst += m_width << 1)
{
WORD* p = &m_vm16[y << 10];
memcpy(&p[r.left], c, w * 2);
c += w;
for(int i = 0; i < w; i++)
{
dst[i * 2] = src[i];
dst[i * 2 + 1] = src[i];
dst[i * 2 + m_width] = src[i];
dst[i * 2 + m_width + 1] = src[i];
}
}
}
void GPULocalMemory::ReadRect(const CRect& r, WORD* c)
void GPULocalMemory::ReadRect(const CRect& r, WORD* RESTRICT dst)
{
CheckRect(r);
WORD* RESTRICT src = GetPixelAddress(r.left << 1, r.top << 1);
int w = r.Width();
int h = r.Height();
for(int y = r.top; y < r.bottom; y++)
for(int j = 0; j < h; j++, src += m_width << 1, dst += w)
{
WORD* p = &m_vm16[y << 10];
memcpy(c, &p[r.left], w * 2);
c += w;
for(int i = 0; i < w; i++)
{
dst[i] = src[i * 2];
}
}
}
@@ -148,12 +267,17 @@ void GPULocalMemory::MoveRect(const CPoint& src, const CPoint& dst, int w, int h
CheckRect(CRect(src, CSize(w, h)));
CheckRect(CRect(dst, CSize(w, h)));
WORD* s = &m_vm16[(src.y << 10) + src.x];
WORD* d = &m_vm16[(dst.y << 10) + dst.x];
Invalidate(CRect(dst, CSize(w, h)));
for(int i = 0; i < h; i++, s += 1024, d += 1024)
WORD* s = GetPixelAddress(src.x << 1, src.y << 1);
WORD* d = GetPixelAddress(dst.x << 1, dst.y << 1);
w <<= 1;
h <<= 1;
for(int i = 0; i < h; i++, s += m_width, d += m_width)
{
memcpy(d, s, w * 2);
memcpy(d, s, w * sizeof(WORD));
}
}
@@ -161,54 +285,64 @@ void GPULocalMemory::ReadPage4(int tx, int ty, BYTE* dst)
{
GSVector4i mask(0x0f0f0f0f);
WORD* src = &m_vm16[(ty << 18) + (tx << 6)];
WORD* src = GetPixelAddress(tx << (6 + 1), ty << (8 + 1));
for(int j = 0; j < 256; j++, src += 1024, dst += 256)
for(int j = 0; j < 256; j++, src += m_width << 1, dst += 256)
{
GSVector4i* s = (GSVector4i*)src;
GSVector4i* d = (GSVector4i*)dst;
for(int i = 0; i < 8; i++)
for(int i = 0; i < 64; i++)
{
GSVector4i c = s[i];
GSVector4i l = c & mask;
GSVector4i h = c.andnot(mask) >> 4;
d[i * 2 + 0] = l.upl8(h);
d[i * 2 + 1] = l.uph8(h);
dst[i * 4 + 0] = (src[i * 2] >> 0) & 0xf;
dst[i * 4 + 1] = (src[i * 2] >> 4) & 0xf;
dst[i * 4 + 2] = (src[i * 2] >> 8) & 0xf;
dst[i * 4 + 3] = (src[i * 2] >> 12) & 0xf;
}
}
}
void GPULocalMemory::ReadPage8(int tx, int ty, BYTE* dst)
{
WORD* src = &m_vm16[(ty << 18) + (tx << 6)];
WORD* src = GetPixelAddress(tx << (6 + 1), ty << (8 + 1));
for(int j = 0; j < 256; j++, src += 1024, dst += 256)
for(int j = 0; j < 256; j++, src += m_width << 1, dst += 256)
{
memcpy(dst, src, 256);
for(int i = 0; i < 128; i++)
{
((WORD*)dst)[i] = src[i * 2];
}
}
}
void GPULocalMemory::ReadPage16(int tx, int ty, WORD* dst)
{
WORD* src = &m_vm16[(ty << 18) + (tx << 6)];
WORD* src = GetPixelAddress(tx << (6 + 1), ty << (8 + 1));
for(int j = 0; j < 256; j++, src += 1024, dst += 256)
for(int j = 0; j < 256; j++, src += m_width << 1, dst += 256)
{
memcpy(dst, src, 256 * sizeof(WORD));
for(int i = 0; i < 256; i++)
{
dst[i] = src[i * 2];
}
}
}
void GPULocalMemory::ReadPalette4(int cx, int cy, WORD* dst)
void GPULocalMemory::ReadFrame32(const CRect& r, DWORD* dst, bool rgb24)
{
memcpy(dst, &m_vm16[(cy << 10) + (cx << 4)], 16 * sizeof(WORD));
}
WORD* src = GetPixelAddress(r.left, r.top);
void GPULocalMemory::ReadPalette8(int cx, int cy, WORD* dst)
{
memcpy(dst, &m_vm16[(cy << 10) + (cx << 4)], 256 * sizeof(WORD));
if(rgb24)
{
for(int i = r.top; i < r.bottom; i++, src += m_width, dst += m_width)
{
Expand24(src, dst, r.Width());
}
}
else
{
for(int i = r.top; i < r.bottom; i++, src += m_width, dst += m_width)
{
Expand16(src, dst, r.Width());
}
}
}
void GPULocalMemory::Expand16(const WORD* RESTRICT src, DWORD* RESTRICT dst, int pixels)
@@ -239,8 +373,102 @@ void GPULocalMemory::Expand24(const WORD* RESTRICT src, DWORD* RESTRICT dst, int
BYTE* s = (BYTE*)src;
for(int i = 0; i < pixels; i++, s += 3)
for(int i = 0; i < pixels; i += 4, s += 12)
{
dst[i] = (s[2] << 16) | (s[1] << 8) | s[0];
dst[i + 0] = dst[i + 1] = (s[4] << 16) | (s[1] << 8) | s[0];
dst[i + 2] = dst[i + 3] = (s[9] << 16) | (s[8] << 8) | s[5];
}
}
void GPULocalMemory::SaveBMP(LPCTSTR path, CRect r, int tp, int cx, int cy)
{
r.left <<= 1;
r.top <<= 1;
r.right <<= 1;
r.bottom <<= 1;
r.left &= ~1;
r.right &= ~1;
if(FILE* fp = _tfopen(path, _T("wb")))
{
BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(bih));
bih.biSize = sizeof(bih);
bih.biWidth = r.Width();
bih.biHeight = r.Height();
bih.biPlanes = 1;
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biSizeImage = bih.biWidth * bih.biHeight * 4;
BITMAPFILEHEADER bfh;
memset(&bfh, 0, sizeof(bfh));
bfh.bfType = 'MB';
bfh.bfOffBits = sizeof(bfh) + sizeof(bih);
bfh.bfSize = bfh.bfOffBits + bih.biSizeImage;
bfh.bfReserved1 = bfh.bfReserved2 = 0;
fwrite(&bfh, 1, sizeof(bfh), fp);
fwrite(&bih, 1, sizeof(bih), fp);
WORD* buff = (WORD*)_aligned_malloc(sizeof(WORD) * m_width, 16);
DWORD* buff32 = (DWORD*)_aligned_malloc(sizeof(DWORD) * m_width, 16);
WORD* src = GetPixelAddress(r.left, r.bottom - 1);
const WORD* clut = GetCLUT(tp, cx, cy);
for(int j = r.bottom - 1; j >= r.top; j--, src -= m_width)
{
switch(tp)
{
case 0: // 4 bpp
for(int i = 0, k = r.Width() / 2; i < k; i++)
{
buff[i * 2 + 0] = clut[((BYTE*)src)[i] & 0xf];
buff[i * 2 + 1] = clut[((BYTE*)src)[i] >> 4];
}
break;
case 1: // 8 bpp
for(int i = 0, k = r.Width(); i < k; i++)
{
buff[i] = clut[((BYTE*)src)[i]];
}
break;
case 2: // 16 bpp;
for(int i = 0, k = r.Width(); i < k; i++)
{
buff[i] = src[i];
}
break;
case 3: // 24 bpp
// TODO
break;
}
Expand16(buff, buff32, r.Width());
for(int i = 0, k = r.Width(); i < k; i++)
{
buff32[i] = (buff32[i] & 0xff00ff00) | ((buff32[i] & 0x00ff0000) >> 16) | ((buff32[i] & 0x000000ff) << 16);
}
fwrite(buff32, 1, r.Width() * 4, fp);
}
_aligned_free(buff);
_aligned_free(buff32);
fclose(fp);
}
}

View File

@@ -31,29 +31,53 @@ class GPULocalMemory
static const GSVector4i m_xgxx;
static const GSVector4i m_rxxx;
public:
static const int m_vmsize = 1024 * 1024;
WORD* m_vm;
union {BYTE* m_vm8; WORD* m_vm16; DWORD* m_vm32;};
struct
{
WORD* buff;
int tp, cx, cy;
bool dirty;
} m_clut;
struct
{
BYTE* buff[3];
void* page[3][2][16];
WORD valid[3][2];
} m_texture;
public:
static const int m_width = (1024 << 1);
static const int m_height = (512 << 1);
static const int m_size = m_width * m_height * 2;
public:
GPULocalMemory();
virtual ~GPULocalMemory();
WORD* GetPixelAddress(int x, int y) const {return &m_vm[(y << (10 + 1)) + x];}
const WORD* GetCLUT(int tp, int cx, int cy);
const void* GetTexture(int tp, int tx, int ty);
void Invalidate(const CRect& r);
void FillRect(const CRect& r, WORD c);
void WriteRect(const CRect& r, const WORD* c);
void ReadRect(const CRect& r, WORD* c);
void WriteRect(const CRect& r, const WORD* RESTRICT src);
void ReadRect(const CRect& r, WORD* RESTRICT dst);
void MoveRect(const CPoint& src, const CPoint& dst, int w, int h);
void ReadPage4(int tx, int ty, BYTE* dst);
void ReadPage8(int tx, int ty, BYTE* dst);
void ReadPage16(int tx, int ty, WORD* dst);
void ReadPalette4(int cx, int cy, WORD* dst);
void ReadPalette8(int cx, int cy, WORD* dst);
void ReadFrame32(const CRect& r, DWORD* dst, bool rgb24);
static void Expand16(const WORD* RESTRICT src, DWORD* RESTRICT dst, int pixels);
static void Expand24(const WORD* RESTRICT src, DWORD* RESTRICT dst, int pixels);
void SaveBMP(LPCTSTR path, CRect r, int tp, int cx, int cy);
};
#pragma warning(default: 4244)

View File

@@ -57,7 +57,7 @@ protected:
{
if(wParam == VK_DELETE)
{
m_filter = m_filter ? 0 : 1;
m_filter = (m_filter + 1) % 3;
return 0;
}
@@ -372,36 +372,11 @@ public:
ResetDevice();
}
static const int ar[][2] = {{0, 0}, {4, 3}, {16, 9}};
int arx = ar[m_aspectratio][0];
int ary = ar[m_aspectratio][1];
CRect cr;
CRect r;
GetClientRect(m_hWnd, &cr);
GetClientRect(m_hWnd, &r);
CRect r = cr;
if(arx > 0 && ary > 0)
{
if(r.Width() * ary > r.Height() * arx)
{
int w = r.Height() * arx / ary;
r.left = r.CenterPoint().x - w / 2;
if(r.left & 1) r.left++;
r.right = r.left + w;
}
else
{
int h = r.Width() * ary / arx;
r.top = r.CenterPoint().y - h / 2;
if(r.top & 1) r.top++;
r.bottom = r.top + h;
}
}
r &= cr;
GSUtil::FitRect(r, m_aspectratio);
m_dev.Present(r);
}

View File

@@ -22,7 +22,6 @@
#pragma once
#include "GPURenderer.h"
#include "GPUTextureCacheSW.h"
#include "GPUDrawScanline.h"
template <class Device>
@@ -32,18 +31,9 @@ class GPURendererSW : public GPURenderer<Device, GSVertexSW>
protected:
long m_threads;
GPUTextureCacheSW* m_tc;
GPUDrawScanline* m_ds;
GSRasterizer* m_rst;
Texture m_texture;
void Reset()
{
m_tc->Invalidate(CRect(0, 0, 1024, 512));
__super::Reset();
}
void ResetDevice()
{
m_texture = Texture();
@@ -53,6 +43,11 @@ protected:
{
CRect r = m_env.GetDisplayRect();
r.left <<= 1;
r.top <<= 1;
r.right <<= 1;
r.bottom <<= 1;
if(m_texture.GetWidth() != r.Width() || m_texture.GetHeight() != r.Height())
{
m_texture = Texture();
@@ -64,31 +59,13 @@ protected:
}
// TODO
static DWORD* buff = (DWORD*)_aligned_malloc(1024 * 512 * 4, 16);
static int pitch = 1024 * 4;
static DWORD* buff = (DWORD*)_aligned_malloc(GPULocalMemory::m_size * 2, 16);
if(m_env.STATUS.ISRGB24)
{
DWORD* dst = buff;
for(int i = r.top; i < r.bottom; i++, dst += 1024)
{
m_mem.Expand24(&m_mem.m_vm16[(i << 10) + r.left], dst, r.Width());
}
}
else
{
DWORD* dst = buff;
for(int i = r.top; i < r.bottom; i++, dst += 1024)
{
m_mem.Expand16(&m_mem.m_vm16[(i << 10) + r.left], dst, r.Width());
}
}
m_mem.ReadFrame32(r, buff, !!m_env.STATUS.ISRGB24);
r.OffsetRect(-r.TopLeft());
m_texture.Update(r, buff, pitch);
m_texture.Update(r, buff, GPULocalMemory::m_width * 4);
t = m_texture;
@@ -107,11 +84,11 @@ protected:
int s = m_v.UV.X;
int t = m_v.UV.Y;
GSVector4 pt(x, y, s, t);
GSVector4 pt(x << 1, y << 1, s, t);
v.p = pt.xyxy(GSVector4::zero());
v.t = pt.zwzw(GSVector4::zero()) + GSVector4(0.5f);
v.c = GSVector4((DWORD)m_v.RGB.ai32);
v.t = pt.zwzw(GSVector4::zero()) + GSVector4(0.25f);
v.c = GSVector4((DWORD)m_v.RGB.ai32) * 128.0f;
__super::VertexKick();
}
@@ -137,25 +114,27 @@ protected:
if(m_env.PRIM.TME)
{
texture = m_tc->Lookup(m_env.STATUS);
texture = m_mem.GetTexture(m_env.STATUS.TP, m_env.STATUS.TX, m_env.STATUS.TY);
if(!texture) {ASSERT(0); return;}
}
//
m_ds->SetOptions(m_filter, m_dither);
GPUDrawScanline* ds = (GPUDrawScanline*)m_rst->GetDrawScanline();
ds->SetOptions(m_filter, m_dither);
m_ds->SetupDraw(m_vertices, m_count, texture);
ds->SetupDraw(m_vertices, m_count, texture);
//
GSVector4i scissor;
scissor.x = m_env.DRAREATL.X;
scissor.y = m_env.DRAREATL.Y;
scissor.z = min(m_env.DRAREABR.X + 1, 1024);
scissor.w = min(m_env.DRAREABR.Y + 1, 512);
scissor.x = m_env.DRAREATL.X << 1;
scissor.y = m_env.DRAREATL.Y << 1;
scissor.z = min((m_env.DRAREABR.X + 1) << 1, 1024 << 1);
scissor.w = min((m_env.DRAREABR.Y + 1) << 1, 512 << 1);
//
@@ -207,31 +186,22 @@ protected:
CRect r;
r.left = max(scissor.x, min(scissor.z, (int)tl.x));
r.top = max(scissor.y, min(scissor.w, (int)tl.y));
r.right = max(scissor.x, min(scissor.z, (int)br.x));
r.bottom = max(scissor.y, min(scissor.w, (int)br.y));
r.left = max(scissor.x, min(scissor.z, (int)tl.x)) >> 1;
r.top = max(scissor.y, min(scissor.w, (int)tl.y)) >> 1;
r.right = max(scissor.x, min(scissor.z, (int)br.x)) >> 1;
r.bottom = max(scissor.y, min(scissor.w, (int)br.y)) >> 1;
Invalidate(r);
}
}
void Invalidate(const CRect& r)
{
__super::Invalidate(r);
m_tc->Invalidate(r);
}
public:
GPURendererSW(const GPURendererSettings& rs)
: GPURenderer(rs)
{
m_threads = 1;
m_tc = new GPUTextureCacheSW(this);
m_ds = new GPUDrawScanline(this, m_filter, m_dither);
m_rst = new GSRasterizer(m_ds, 0, m_threads);
m_rst = new GSRasterizer(new GPUDrawScanline(this, m_filter, m_dither), 0, m_threads);
m_fpDrawingKickHandlers[GPU_POLYGON] = (DrawingKickHandler)&GPURendererSW::DrawingKickTriangle;
m_fpDrawingKickHandlers[GPU_LINE] = (DrawingKickHandler)&GPURendererSW::DrawingKickLine;
@@ -240,8 +210,6 @@ public:
virtual ~GPURendererSW()
{
delete m_tc;
delete m_ds;
delete m_rst;
}
};

View File

@@ -63,6 +63,8 @@ void GPUState::Reset()
{
m_env.Reset();
m_mem.Invalidate(CRect(0, 0, 1024, 512));
memset(&m_v, 0, sizeof(m_v));
}
@@ -132,6 +134,11 @@ void GPUState::SetTPAGE(GPUReg* r)
}
}
void GPUState::Invalidate(const CRect& r)
{
m_mem.Invalidate(r);
}
void GPUState::WriteData(const BYTE* mem, UINT32 size)
{
GSPerfMonAutoTimer pmat(m_perfmon);
@@ -209,14 +216,14 @@ void GPUState::Freeze(GPUFreezeData* data)
{
data->status = m_env.STATUS.ai32;
memcpy(data->control, m_status, 256 * 4);
memcpy(data->vram, m_mem.m_vm16, 1024 * 512 * 2);
m_mem.ReadRect(CRect(0, 0, 1024, 512), data->vram);
}
void GPUState::Defrost(const GPUFreezeData* data)
{
m_env.STATUS.ai32 = data->status;
memcpy(m_status, data->control, 256 * 4);
memcpy(m_mem.m_vm16, data->vram, 1024 * 512 * 2);
m_mem.WriteRect(CRect(0, 0, 1024, 512), data->vram);
for(int i = 0; i <= 8; i++)
{
@@ -618,8 +625,6 @@ int GPUState::PH_Read(GPUReg* r, int size)
m_mem.ReadRect(r2, (WORD*)m_read.buff);
Invalidate(r2);
Dump(_T("r"));
m_env.STATUS.IMG = 1;
@@ -681,85 +686,6 @@ int GPUState::PH_Environment(GPUReg* r, int size)
return 1;
}
void GPUState::SaveBMP(LPCTSTR path, UINT32 TP, CRect r)
{
r.left &= ~1;
r.right &= ~1;
if(FILE* fp = _tfopen(path, _T("wb")))
{
BITMAPINFOHEADER bih;
memset(&bih, 0, sizeof(bih));
bih.biSize = sizeof(bih);
bih.biWidth = r.Width();
bih.biHeight = r.Height();
bih.biPlanes = 1;
bih.biBitCount = 32;
bih.biCompression = BI_RGB;
bih.biSizeImage = bih.biWidth * bih.biHeight * 4;
BITMAPFILEHEADER bfh;
memset(&bfh, 0, sizeof(bfh));
bfh.bfType = 'MB';
bfh.bfOffBits = sizeof(bfh) + sizeof(bih);
bfh.bfSize = bfh.bfOffBits + bih.biSizeImage;
bfh.bfReserved1 = bfh.bfReserved2 = 0;
fwrite(&bfh, 1, sizeof(bfh), fp);
fwrite(&bih, 1, sizeof(bih), fp);
WORD* buff = (WORD*)_aligned_malloc(sizeof(WORD) * 1024, 16);
DWORD* buff32 = (DWORD*)_aligned_malloc(sizeof(DWORD) * 1024, 16);
WORD* clut = GetCLUT();
for(int j = r.bottom - 1; j >= r.top; j--)
{
WORD* p = &m_mem.m_vm16[(j << 10) + r.left];
if(TP == 0) // 4 bpp
{
for(int i = 0, k = r.Width() / 2; i < k; i++)
{
buff[i * 2 + 0] = clut[((BYTE*)p)[i] & 0xf];
buff[i * 2 + 1] = clut[((BYTE*)p)[i] >> 4];
}
}
else if(TP == 1) // 8 bpp
{
for(int i = 0, k = r.Width(); i < k; i++)
{
buff[i] = clut[((BYTE*)p)[i]];
}
}
else if(TP == 2) // 16 bpp;
{
for(int i = 0, k = r.Width(); i < k; i++)
{
buff[i] = p[i];
}
}
else if(TP == 3) // 24 bpp
{
// TODO
}
m_mem.Expand16(buff, buff32, r.Width());
for(int i = 0, k = r.Width(); i < k; i++)
{
buff32[i] = (buff32[i] & 0xff00ff00) | ((buff32[i] & 0x00ff0000) >> 16) | ((buff32[i] & 0x000000ff) << 16);
}
fwrite(buff32, 1, r.Width() * 4, fp);
}
_aligned_free(buff);
_aligned_free(buff32);
fclose(fp);
}
}
//
GPUState::Buffer::Buffer()

View File

@@ -105,7 +105,7 @@ protected:
#endif
CString str;
str.Format(_T("c:\\temp%d\\%04d_%s.bmp"), dir, s_n, s);
SaveBMP(str, TP, r);
m_mem.SaveBMP(str, r, TP, m_env.CLUT.X, m_env.CLUT.Y);
}
void Dump(LPCTSTR s, int inc = true)
@@ -113,8 +113,6 @@ protected:
Dump(s, 2, CRect(0, 0, 1024, 512), inc);
}
void SaveBMP(LPCTSTR path, UINT32 TP, CRect r);
public:
GPUDrawingEnvironment m_env;
GPULocalMemory m_mem;
@@ -131,9 +129,7 @@ public:
virtual void FlushPrim() = 0;
virtual void ResetPrim() = 0;
virtual void VertexKick() = 0;
virtual void Invalidate(const CRect& r) {}
WORD* GetCLUT() {return &m_mem.m_vm16[(m_env.CLUT.Y << 10) + (m_env.CLUT.X << 4)];}
virtual void Invalidate(const CRect& r);
void WriteData(const BYTE* mem, UINT32 size);
void ReadData(BYTE* mem, UINT32 size);

View File

@@ -1,130 +0,0 @@
/*
* Copyright (C) 2007 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "StdAfx.h"
#include "GPUTextureCacheSW.h"
GPUTextureCacheSW::GPUTextureCacheSW(GPUState* state)
: m_state(state)
{
int size = 256 * 256 * (1 + 1 + 4) * 32;
m_buff[0] = (BYTE*)VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
m_buff[1] = m_buff[0] + 256 * 256 * 32;
m_buff[2] = m_buff[1] + 256 * 256 * 32;
memset(m_buff[0], 0, size);
memset(m_valid, 0, sizeof(m_valid));
for(int y = 0, offset = 0; y < 2; y++)
{
for(int x = 0; x < 16; x++, offset += 256 * 256)
{
m_texture[0][y][x] = &((BYTE*)m_buff[0])[offset];
m_texture[1][y][x] = &((BYTE*)m_buff[1])[offset];
}
}
for(int y = 0, offset = 0; y < 2; y++)
{
for(int x = 0; x < 16; x++, offset += 256 * 256)
{
m_texture[2][y][x] = &((DWORD*)m_buff[2])[offset];
}
}
}
GPUTextureCacheSW::~GPUTextureCacheSW()
{
VirtualFree(m_buff[0], 0, MEM_RELEASE);
}
const void* GPUTextureCacheSW::Lookup(const GPURegSTATUS& TPAGE)
{
if(TPAGE.TP == 3)
{
ASSERT(0);
return NULL;
}
void* buff = m_texture[TPAGE.TP][TPAGE.TY][TPAGE.TX];
UINT32 flag = 1 << TPAGE.TX;
if(TPAGE.TY) flag <<= 16;
if((m_valid[TPAGE.TP] & flag) == 0)
{
int bpp = 0;
switch(TPAGE.TP)
{
case 0:
m_state->m_mem.ReadPage4(TPAGE.TX, TPAGE.TY, (BYTE*)buff);
bpp = 4;
break;
case 1:
m_state->m_mem.ReadPage8(TPAGE.TX, TPAGE.TY, (BYTE*)buff);
bpp = 8;
break;
case 2:
case 3:
m_state->m_mem.ReadPage16(TPAGE.TX, TPAGE.TY, (WORD*)buff);
bpp = 16;
default:
// FIXME: __assume(0); // vc9 generates bogus code in release mode
break;
}
m_state->m_perfmon.Put(GSPerfMon::Unswizzle, 256 * 256 * bpp >> 3);
m_valid[TPAGE.TP] |= flag;
}
return buff;
}
void GPUTextureCacheSW::Invalidate(const CRect& r)
{
for(int y = 0, ye = min(r.bottom, 512), j = 0; y < ye; y += 256, j += 16)
{
if(r.top >= y + 256) continue;
for(int x = 0, xe = min(r.right, 1024), i = 0; x < xe; x += 64, i++)
{
DWORD flag = (1 << i) << j;
if(r.left >= x + 256) continue;
m_valid[2] &= ~flag;
if(r.left >= x + 128) continue;
m_valid[1] &= ~flag;
if(r.left >= x + 64) continue;
m_valid[0] &= ~flag;
}
}
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) 2007 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GPURenderer.h"
class GPUTextureCacheSW
{
protected:
GPUState* m_state;
BYTE* m_buff[3];
void* m_texture[3][2][16];
DWORD m_valid[3];
public:
GPUTextureCacheSW(GPUState* state);
virtual ~GPUTextureCacheSW();
const void* Lookup(const GPURegSTATUS& TPAGE);
void Invalidate(const CRect& r);
};

View File

@@ -1,96 +0,0 @@
/*
* Copyright (C) 2007 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GSVector.h"
__declspec(align(16)) union GPUVertexSW
{
typedef GSVector4 Vector;
struct {Vector p, c;};
struct {Vector v[2];};
struct {float f[8];};
GPUVertexSW() {}
GPUVertexSW(const GPUVertexSW& v) {*this = v;}
void operator = (const GPUVertexSW& v) {c = v.c; p = v.p;}
void operator += (const GPUVertexSW& v) {c += v.c; p += v.p;}
friend GPUVertexSW operator + (const GPUVertexSW& v1, const GPUVertexSW& v2);
friend GPUVertexSW operator - (const GPUVertexSW& v1, const GPUVertexSW& v2);
friend GPUVertexSW operator * (const GPUVertexSW& v, const Vector& vv);
friend GPUVertexSW operator / (const GPUVertexSW& v, const Vector& vv);
friend GPUVertexSW operator * (const GPUVertexSW& v, float f);
friend GPUVertexSW operator / (const GPUVertexSW& v, float f);
};
__forceinline GPUVertexSW operator + (const GPUVertexSW& v1, const GPUVertexSW& v2)
{
GPUVertexSW v0;
v0.c = v1.c + v2.c;
v0.p = v1.p + v2.p;
return v0;
}
__forceinline GPUVertexSW operator - (const GPUVertexSW& v1, const GPUVertexSW& v2)
{
GPUVertexSW v0;
v0.c = v1.c - v2.c;
v0.p = v1.p - v2.p;
return v0;
}
__forceinline GPUVertexSW operator * (const GPUVertexSW& v, const GPUVertexSW::Vector& vv)
{
GPUVertexSW v0;
v0.c = v.c * vv;
v0.p = v.p * vv;
return v0;
}
__forceinline GPUVertexSW operator / (const GPUVertexSW& v, const GPUVertexSW::Vector& vv)
{
GPUVertexSW v0;
v0.c = v.c / vv;
v0.p = v.p / vv;
return v0;
}
__forceinline GPUVertexSW operator * (const GPUVertexSW& v, float f)
{
GPUVertexSW v0;
GPUVertexSW::Vector vf(f);
v0.c = v.c * vf;
v0.p = v.p * vf;
return v0;
}
__forceinline GPUVertexSW operator / (const GPUVertexSW& v, float f)
{
GPUVertexSW v0;
GPUVertexSW::Vector vf(f);
v0.c = v.c / vf;
v0.p = v.p / vf;
return v0;
}

View File

@@ -26,7 +26,7 @@
#pragma once
#define PLUGIN_VERSION 11
#define PLUGIN_VERSION 12
#include "GSVector.h"

File diff suppressed because it is too large Load Diff

View File

@@ -87,6 +87,10 @@ class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
GSVector4 afix;
GSVector4 afix2;
GSVector4 fc;
GSVector4 dp, dp4;
GSVector4 dt, dt4;
GSVector4 dc, dc4;
};
struct Offset
@@ -106,18 +110,16 @@ class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
void SetupOffset(Offset*& co, DWORD bp, DWORD bw, DWORD psm);
void FreeOffsets();
typedef void (GSDrawScanline::*DrawScanlinePtr)(int top, int left, int right, const Vertex& v, const Vertex& dv);
DrawScanlinePtr m_ds[4][4][4][2], m_dsf;
CRBMap<DWORD, DrawScanlinePtr> m_dsmap, m_dsmap2;
template<DWORD fpsm, DWORD zpsm, DWORD ztst, DWORD iip>
void DrawScanlineT(int top, int left, int right, const Vertex& v, const Vertex& dv);
void Init();
void InitEx();
template<DWORD fpsm, DWORD zpsm, DWORD ztst, DWORD iip>
void DrawScanlineT(int top, int left, int right, const Vertex& v);
template<DWORD sel>
void DrawScanlineExT(int top, int left, int right, const Vertex& v, const Vertex& dv);
void DrawScanlineExT(int top, int left, int right, const Vertex& v);
__forceinline GSVector4i Wrap(const GSVector4i& t);
@@ -149,6 +151,8 @@ public:
// IDrawScanline
void SetupDraw(Vertex* vertices, int count, const void* texture);
void DrawScanline(int top, int left, int right, const Vertex& v, const Vertex& dv);
void SetupScanline(const Vertex& dv);
void DrawScanline(int top, int left, int right, const Vertex& v);
void FillRect(const GSVector4i& r, const Vertex& v);
DrawScanlinePtr GetDrawScanlinePtr();
};

View File

@@ -30,6 +30,11 @@ GSRasterizer::GSRasterizer(IDrawScanline* ds, int id, int threads)
{
}
GSRasterizer::~GSRasterizer()
{
delete m_ds;
}
void GSRasterizer::DrawPoint(Vertex* v, const GSVector4i& scissor)
{
// TODO: round to closest for point, prestep for line
@@ -40,7 +45,7 @@ void GSRasterizer::DrawPoint(Vertex* v, const GSVector4i& scissor)
{
if((p.y % m_threads) == m_id)
{
m_ds->DrawScanline(p.y, p.x, p.x + 1, *v, *v);
m_ds->DrawScanline(p.y, p.x, p.x + 1, *v);
m_pixels++;
}
@@ -163,6 +168,8 @@ void GSRasterizer::DrawTriangleTop(Vertex* v, const GSVector4i& scissor)
r += dr * dy;
}
m_ds->SetupScanline(dscan);
DrawTriangleSection(top, bottom, l, dl, r, dr, dscan, scissor);
}
}
@@ -209,6 +216,8 @@ void GSRasterizer::DrawTriangleBottom(Vertex* v, const GSVector4i& scissor)
r += dr * dy;
}
m_ds->SetupScanline(dscan);
DrawTriangleSection(top, bottom, l, dl, r, dr, dscan, scissor);
}
}
@@ -229,6 +238,8 @@ void GSRasterizer::DrawTriangleTopBottom(Vertex* v, const GSVector4i& scissor)
Vertex dscan = longest * longest.p.xxxx().rcp();
m_ds->SetupScanline(dscan);
Vertex& l = v[0];
GSVector4 r = v[0].p;
@@ -312,6 +323,8 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, Vertex& l, const Ver
{
ASSERT(top < bottom);
IDrawScanline::DrawScanlinePtr dsf = m_ds->GetDrawScanlinePtr();
while(1)
{
do
@@ -354,7 +367,7 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, Vertex& l, const Ver
if(px > 0) scan += dscan * px;
m_ds->DrawScanline(top, left, right, scan, dscan);
(m_ds->*dsf)(top, left, right, scan);
}
}
}
@@ -433,11 +446,15 @@ void GSRasterizer::DrawSprite(Vertex* vertices, const GSVector4i& scissor, bool
if(scan.p.y < (float)top) scan.t += dedge.t * ((float)top - scan.p.y);
if(scan.p.x < (float)left) scan.t += dscan.t * ((float)left - scan.p.x);
m_ds->SetupScanline(dscan);
IDrawScanline::DrawScanlinePtr dsf = m_ds->GetDrawScanlinePtr();
for(; top < bottom; top++, scan.t += dedge.t)
{
if((top % m_threads) == m_id)
{
m_ds->DrawScanline(top, left, right, scan, dscan);
(m_ds->*dsf)(top, left, right, scan);
m_pixels += right - left;
}
@@ -472,8 +489,10 @@ GSRasterizerMT::~GSRasterizerMT()
}
}
void GSRasterizerMT::Run()
void GSRasterizerMT::Run(Vertex* vertices, int count, const void* texture)
{
m_ds->SetupDraw(vertices, count, texture);
InterlockedBitTestAndSet(m_sync, m_id);
}

View File

@@ -23,14 +23,19 @@
#include "GSVertexSW.h"
interface IDrawScanline
class IDrawScanline
{
public:
typedef GSVertexSW Vertex;
typedef void (IDrawScanline::*DrawScanlinePtr)(int top, int left, int right, const Vertex& v);
virtual ~IDrawScanline() {}
virtual void SetupDraw(Vertex* vertices, int count, const void* texture) = 0;
virtual void DrawScanline(int top, int left, int right, const Vertex& v, const Vertex& dv) = 0;
virtual void SetupScanline(const Vertex& dv) = 0;
virtual void DrawScanline(int top, int left, int right, const Vertex& v) = 0;
virtual void FillRect(const GSVector4i& r, const Vertex& v) = 0;
virtual DrawScanlinePtr GetDrawScanlinePtr() = 0;
};
class GSRasterizer
@@ -51,12 +56,14 @@ protected:
public:
GSRasterizer(IDrawScanline* ds, int id = 0, int threads = 0);
virtual ~GSRasterizer();
void DrawPoint(Vertex* v, const GSVector4i& scissor);
void DrawLine(Vertex* v, const GSVector4i& scissor);
void DrawTriangle(Vertex* v, const GSVector4i& scissor);
void DrawSprite(Vertex* v, const GSVector4i& scissor, bool solid);
IDrawScanline* GetDrawScanline() {return m_ds;}
int GetPixels() {int pixels = m_pixels; m_pixels = 0; return pixels;}
};
@@ -82,5 +89,5 @@ public:
GSRasterizerMT(IDrawScanline* ds, int id, int threads, IDrawAsync* da, long* sync);
virtual ~GSRasterizerMT();
void Run();
void Run(Vertex* vertices, int count, const void* texture);
};

View File

@@ -402,36 +402,11 @@ public:
//
static const int ar[][2] = {{0, 0}, {4, 3}, {16, 9}};
int arx = ar[m_aspectratio][0];
int ary = ar[m_aspectratio][1];
CRect cr;
CRect r;
m_wnd.GetClientRect(&cr);
m_wnd.GetClientRect(&r);
CRect r = cr;
if(arx > 0 && ary > 0)
{
if(r.Width() * ary > r.Height() * arx)
{
int w = r.Height() * arx / ary;
r.left = r.CenterPoint().x - w / 2;
if(r.left & 1) r.left++;
r.right = r.left + w;
}
else
{
int h = r.Width() * ary / arx;
r.top = r.CenterPoint().y - h / 2;
if(r.top & 1) r.top++;
r.bottom = r.top + h;
}
}
r &= cr;
GSUtil::FitRect(r, m_aspectratio);
m_dev.Present(r);

View File

@@ -36,7 +36,6 @@ protected:
long* m_sync;
long m_threads;
GSTextureCacheSW* m_tc;
GSDrawScanline* m_ds;
GSRasterizer* m_rst;
CAtlList<GSRasterizerMT*> m_rmt;
Texture m_texture[2];
@@ -312,7 +311,7 @@ protected:
//
m_ds->SetupDraw(m_vertices, m_count, texture);
m_rst->GetDrawScanline()->SetupDraw(m_vertices, m_count, texture);
//
@@ -322,7 +321,7 @@ protected:
while(pos)
{
m_rmt.GetNext(pos)->Run();
m_rmt.GetNext(pos)->Run(m_vertices, m_count, texture);
}
// 1st thread is this thread
@@ -478,12 +477,11 @@ public:
m_threads = AfxGetApp()->GetProfileInt(_T("Settings"), _T("swthreads"), 1);
m_tc = new GSTextureCacheSW(this);
m_ds = new GSDrawScanline(this);
m_rst = new GSRasterizer(m_ds, 0, m_threads);
m_rst = new GSRasterizer(new GSDrawScanline(this), 0, m_threads);
for(int i = 1; i < m_threads; i++)
{
m_rmt.AddTail(new GSRasterizerMT(m_ds, i, m_threads, this, m_sync));
m_rmt.AddTail(new GSRasterizerMT(new GSDrawScanline(this), i, m_threads, this, m_sync));
}
m_fpDrawingKickHandlers[GS_POINTLIST] = (DrawingKickHandler)&GSRendererSW::DrawingKickPoint;
@@ -498,7 +496,6 @@ public:
virtual ~GSRendererSW()
{
delete m_tc;
delete m_ds;
delete m_rst;
while(!m_rmt.IsEmpty())

View File

@@ -126,6 +126,41 @@ bool GSUtil::IsRectInRectV(const CRect& inner, const CRect& outer)
return outer.left <= inner.left && inner.right <= outer.right;
}
void GSUtil::FitRect(CRect& r, int aspectratio)
{
static const int ar[][2] = {{0, 0}, {4, 3}, {16, 9}};
if(aspectratio <= 0 || aspectratio >= countof(ar))
{
return;
}
int arx = ar[aspectratio][0];
int ary = ar[aspectratio][1];
CRect r2 = r;
if(arx > 0 && ary > 0)
{
if(r.Width() * ary > r.Height() * arx)
{
int w = r.Height() * arx / ary;
r.left = r.CenterPoint().x - w / 2;
if(r.left & 1) r.left++;
r.right = r.left + w;
}
else
{
int h = r.Width() * ary / arx;
r.top = r.CenterPoint().y - h / 2;
if(r.top & 1) r.top++;
r.bottom = r.top + h;
}
}
r &= r2;
}
bool GSUtil::CheckDirectX()
{
CString str;

View File

@@ -36,6 +36,8 @@ public:
static bool IsRectInRect(const CRect& inner, const CRect& outer);
static bool IsRectInRectH(const CRect& inner, const CRect& outer);
static bool IsRectInRectV(const CRect& inner, const CRect& outer);
static void FitRect(CRect& r, int aspectratio);
static int EncodePSM(int psm)
{

View File

@@ -1075,10 +1075,6 @@
RelativePath=".\GPUState.cpp"
>
</File>
<File
RelativePath=".\GPUTextureCacheSW.cpp"
>
</File>
<File
RelativePath=".\GS.cpp"
>
@@ -1625,18 +1621,10 @@
RelativePath=".\GPUState.h"
>
</File>
<File
RelativePath=".\GPUTextureCacheSW.h"
>
</File>
<File
RelativePath=".\GPUVertex.h"
>
</File>
<File
RelativePath=".\GPUVertexSW.h"
>
</File>
<File
RelativePath=".\GS.h"
>