mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-28 12:40:12 +00:00
include clearing
This commit is contained in:
parent
0d15fc35d7
commit
efa538f9d7
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "AutoPause.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Emu/SysCalls/ErrorCodes.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Utilities/Log.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Emu/SysCalls/ErrorCodes.h"
|
||||
|
@ -1,8 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "GLBuffers.h"
|
||||
#include "GLGSRender.h"
|
||||
|
||||
GLBufferObject::GLBufferObject()
|
||||
{
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "GLGSRender.h"
|
||||
#include "Emu/Cell/PPCInstrTable.h"
|
||||
|
||||
#define CMD_DEBUG 0
|
||||
#define DUMP_VERTEX_DATA 0
|
||||
@ -35,6 +35,731 @@ void printGlError(GLenum err, const std::string& situation)
|
||||
#define checkForGlError(x) /*x*/
|
||||
#endif
|
||||
|
||||
void GLTexture::Create()
|
||||
{
|
||||
if (m_id)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
if (!m_id)
|
||||
{
|
||||
glGenTextures(1, &m_id);
|
||||
checkForGlError("GLTexture::Init() -> glGenTextures");
|
||||
Bind();
|
||||
}
|
||||
}
|
||||
|
||||
int GLTexture::GetGlWrap(int wrap)
|
||||
{
|
||||
switch (wrap)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_WRAP: return GL_REPEAT;
|
||||
case CELL_GCM_TEXTURE_MIRROR: return GL_MIRRORED_REPEAT;
|
||||
case CELL_GCM_TEXTURE_CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE;
|
||||
case CELL_GCM_TEXTURE_BORDER: return GL_CLAMP_TO_BORDER;
|
||||
case CELL_GCM_TEXTURE_CLAMP: return GL_CLAMP_TO_EDGE;
|
||||
case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP_TO_EDGE: return GL_MIRROR_CLAMP_TO_EDGE_EXT;
|
||||
case CELL_GCM_TEXTURE_MIRROR_ONCE_BORDER: return GL_MIRROR_CLAMP_TO_BORDER_EXT;
|
||||
case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP: return GL_MIRROR_CLAMP_EXT;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture wrap error: bad wrap (%d).", wrap);
|
||||
return GL_REPEAT;
|
||||
}
|
||||
|
||||
float GLTexture::GetMaxAniso(int aniso)
|
||||
{
|
||||
switch (aniso)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_1: return 1.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_2: return 2.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_4: return 4.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_6: return 6.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_8: return 8.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_10: return 10.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_12: return 12.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_16: return 16.0f;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture anisotropy error: bad max aniso (%d).", aniso);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
void GLTexture::Init(RSXTexture& tex)
|
||||
{
|
||||
if (tex.GetLocation() > 1)
|
||||
return;
|
||||
|
||||
Bind();
|
||||
|
||||
const u64 texaddr = GetAddress(tex.GetOffset(), tex.GetLocation());
|
||||
if (!Memory.IsGoodAddr(texaddr))
|
||||
{
|
||||
LOG_ERROR(RSX, "Bad texture address=0x%x", texaddr);
|
||||
return;
|
||||
}
|
||||
//ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
|
||||
// m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod);
|
||||
//TODO: safe init
|
||||
checkForGlError("GLTexture::Init() -> glBindTexture");
|
||||
|
||||
int format = tex.GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
bool is_swizzled = !(tex.GetFormat() & CELL_GCM_TEXTURE_LN);
|
||||
|
||||
const u8 *pixels = const_cast<const u8 *>(Memory.GetMemFromAddr(texaddr));
|
||||
u8 *unswizzledPixels;
|
||||
static const GLint glRemapStandard[4] = { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
|
||||
// NOTE: This must be in ARGB order in all forms below.
|
||||
const GLint *glRemap = glRemapStandard;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8: // One 8-bit fixed-point number
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_B8)");
|
||||
|
||||
static const GLint swizzleMaskB8[] = { GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE };
|
||||
glRemap = swizzleMaskB8;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei");
|
||||
|
||||
// TODO: texture swizzling
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_A1R5G5B5)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_A1R5G5B5)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_A4R4G4B4)");
|
||||
|
||||
// We read it in as R4G4B4A4, so we need to remap each component.
|
||||
static const GLint swizzleMaskA4R4G4B4[] = { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN };
|
||||
glRemap = swizzleMaskA4R4G4B4;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G6B5)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.GetWidth(), tex.GetHeight(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_R5G6B5)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G6B5)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
if (is_swizzled)
|
||||
{
|
||||
u32 *src, *dst;
|
||||
u32 log2width, log2height;
|
||||
|
||||
unswizzledPixels = (u8*)malloc(tex.GetWidth() * tex.GetHeight() * 4);
|
||||
src = (u32*)pixels;
|
||||
dst = (u32*)unswizzledPixels;
|
||||
|
||||
log2width = log(tex.GetWidth()) / log(2);
|
||||
log2height = log(tex.GetHeight()) / log(2);
|
||||
|
||||
for (int i = 0; i<tex.GetHeight(); i++)
|
||||
{
|
||||
for (int j = 0; j<tex.GetWidth(); j++)
|
||||
{
|
||||
dst[(i*tex.GetHeight()) + j] = src[LinearToSwizzleAddress(j, i, 0, log2width, log2height, 0)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, is_swizzled ? unswizzledPixels : pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_A8R8G8B8)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: // Compressed 4x4 pixels into 8 bytes
|
||||
{
|
||||
u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 8;
|
||||
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT1)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: // Compressed 4x4 pixels into 16 bytes
|
||||
{
|
||||
u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 16;
|
||||
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT23)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: // Compressed 4x4 pixels into 16 bytes
|
||||
{
|
||||
u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 16;
|
||||
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT45)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_G8B8:
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_UNSIGNED_BYTE, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_G8B8)");
|
||||
|
||||
static const GLint swizzleMaskG8B8[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN };
|
||||
glRemap = swizzleMaskG8B8;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_R6G5B5:
|
||||
{
|
||||
// TODO: Probably need to actually unswizzle if is_swizzled.
|
||||
const u32 numPixels = tex.GetWidth() * tex.GetHeight();
|
||||
unswizzledPixels = (u8 *)malloc(numPixels * 4);
|
||||
// TODO: Speed.
|
||||
for (u32 i = 0; i < numPixels; ++i) {
|
||||
u16 c = reinterpret_cast<const be_t<u16> *>(pixels)[i];
|
||||
unswizzledPixels[i * 4 + 0] = Convert6To8((c >> 10) & 0x3F);
|
||||
unswizzledPixels[i * 4 + 1] = Convert5To8((c >> 5) & 0x1F);
|
||||
unswizzledPixels[i * 4 + 2] = Convert5To8((c >> 0) & 0x1F);
|
||||
unswizzledPixels[i * 4 + 3] = 255;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_R6G5B5)");
|
||||
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8: // 24-bit unsigned fixed-point number and 8 bits of garbage
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH24_D8)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // 24-bit unsigned float and 8 bits of garbage
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH16: // 16-bit unsigned fixed-point number
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_SHORT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH16)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // 16-bit unsigned float
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH16_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_X16)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_UNSIGNED_SHORT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_X16)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_X16)");
|
||||
|
||||
static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE };
|
||||
glRemap = swizzleMaskX16;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_UNSIGNED_SHORT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_Y16_X16)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16)");
|
||||
|
||||
static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED };
|
||||
glRemap = swizzleMaskX32_Y16_X16;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_R5G5B5A1:
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G5B5A1)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_R5G5B5A1)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G5B5A1)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_HALF_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT: // One 32-bit floating-point number
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_X32_FLOAT)");
|
||||
|
||||
static const GLint swizzleMaskX32_FLOAT[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE };
|
||||
glRemap = swizzleMaskX32_FLOAT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_D1R5G5B5)");
|
||||
|
||||
// TODO: Texture swizzling
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_D1R5G5B5)");
|
||||
|
||||
static const GLint swizzleMaskX32_D1R5G5B5[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
|
||||
glRemap = swizzleMaskX32_D1R5G5B5;
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_D1R5G5B5)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8: // 8 bits of garbage and three unsigned 8-bit fixed-point numbers
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_D8R8G8B8)");
|
||||
|
||||
static const GLint swizzleMaskX32_D8R8G8B8[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
|
||||
glRemap = swizzleMaskX32_D8R8G8B8;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16_FLOAT)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_HALF_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_Y16_X16_FLOAT)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16_FLOAT)");
|
||||
|
||||
static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN };
|
||||
glRemap = swizzleMaskX32_Y16_X16_FLOAT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) :
|
||||
{
|
||||
const u32 numPixels = tex.GetWidth() * tex.GetHeight();
|
||||
unswizzledPixels = (u8 *)malloc(numPixels * 4);
|
||||
// TODO: Speed.
|
||||
for (u32 i = 0; i < numPixels; i += 2) {
|
||||
unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 3];
|
||||
unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 2];
|
||||
unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 0];
|
||||
unswizzledPixels[i * 4 + 0 + 3] = 255;
|
||||
|
||||
// The second pixel is the same, except for red.
|
||||
unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 1];
|
||||
unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 2];
|
||||
unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 0];
|
||||
unswizzledPixels[i * 4 + 4 + 3] = 255;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN)");
|
||||
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) :
|
||||
{
|
||||
const u32 numPixels = tex.GetWidth() * tex.GetHeight();
|
||||
unswizzledPixels = (u8 *)malloc(numPixels * 4);
|
||||
// TODO: Speed.
|
||||
for (u32 i = 0; i < numPixels; i += 2) {
|
||||
unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 2];
|
||||
unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 3];
|
||||
unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 1];
|
||||
unswizzledPixels[i * 4 + 0 + 3] = 255;
|
||||
|
||||
// The second pixel is the same, except for red.
|
||||
unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 0];
|
||||
unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 3];
|
||||
unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 1];
|
||||
unswizzledPixels[i * 4 + 4 + 3] = 255;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN)");
|
||||
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
break;
|
||||
|
||||
default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format,
|
||||
(is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40); break;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.GetMipmap() - 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.GetMipmap() > 1);
|
||||
|
||||
if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT)
|
||||
{
|
||||
u8 remap_a = tex.GetRemap() & 0x3;
|
||||
u8 remap_r = (tex.GetRemap() >> 2) & 0x3;
|
||||
u8 remap_g = (tex.GetRemap() >> 4) & 0x3;
|
||||
u8 remap_b = (tex.GetRemap() >> 6) & 0x3;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
|
||||
}
|
||||
|
||||
checkForGlError("GLTexture::Init() -> remap");
|
||||
|
||||
static const int gl_tex_zfunc[] =
|
||||
{
|
||||
GL_NEVER,
|
||||
GL_LESS,
|
||||
GL_EQUAL,
|
||||
GL_LEQUAL,
|
||||
GL_GREATER,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_ALWAYS,
|
||||
};
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(tex.GetWrapS()));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(tex.GetWrapT()));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(tex.GetWrapR()));
|
||||
|
||||
checkForGlError("GLTexture::Init() -> wrap");
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.GetZfunc()]);
|
||||
|
||||
checkForGlError("GLTexture::Init() -> compare");
|
||||
|
||||
glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.GetBias());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, (tex.GetMinLOD() >> 8));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (tex.GetMaxLOD() >> 8));
|
||||
|
||||
checkForGlError("GLTexture::Init() -> lod");
|
||||
|
||||
static const int gl_tex_min_filter[] =
|
||||
{
|
||||
GL_NEAREST, // unused
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_NEAREST, // CELL_GCM_TEXTURE_CONVOLUTION_MIN
|
||||
};
|
||||
|
||||
static const int gl_tex_mag_filter[] = {
|
||||
GL_NEAREST, // unused
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_NEAREST, // unused
|
||||
GL_LINEAR // CELL_GCM_TEXTURE_CONVOLUTION_MAG
|
||||
};
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_min_filter[tex.GetMinFilter()]);
|
||||
|
||||
checkForGlError("GLTexture::Init() -> min filters");
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter[tex.GetMagFilter()]);
|
||||
|
||||
checkForGlError("GLTexture::Init() -> mag filters");
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GetMaxAniso(tex.GetMaxAniso()));
|
||||
|
||||
checkForGlError("GLTexture::Init() -> max anisotropy");
|
||||
|
||||
//Unbind();
|
||||
|
||||
if (is_swizzled && format == CELL_GCM_TEXTURE_A8R8G8B8)
|
||||
{
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
}
|
||||
|
||||
void GLTexture::Save(RSXTexture& tex, const std::string& name)
|
||||
{
|
||||
if (!m_id || !tex.GetOffset() || !tex.GetWidth() || !tex.GetHeight()) return;
|
||||
|
||||
const u32 texPixelCount = tex.GetWidth() * tex.GetHeight();
|
||||
|
||||
u32* alldata = new u32[texPixelCount];
|
||||
|
||||
Bind();
|
||||
|
||||
switch (tex.GetFormat() & ~(0x20 | 0x40))
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8:
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata);
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, alldata);
|
||||
break;
|
||||
|
||||
default:
|
||||
delete[] alldata;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
rFile f(name + ".raw", rFile::write);
|
||||
f.Write(alldata, texPixelCount * 4);
|
||||
}
|
||||
u8* data = new u8[texPixelCount * 3];
|
||||
u8* alpha = new u8[texPixelCount];
|
||||
|
||||
u8* src = (u8*)alldata;
|
||||
u8* dst_d = data;
|
||||
u8* dst_a = alpha;
|
||||
for (u32 i = 0; i < texPixelCount; i++)
|
||||
{
|
||||
*dst_d++ = *src++;
|
||||
*dst_d++ = *src++;
|
||||
*dst_d++ = *src++;
|
||||
*dst_a++ = *src++;
|
||||
}
|
||||
|
||||
rImage out;
|
||||
out.Create(tex.GetWidth(), tex.GetHeight(), data, alpha);
|
||||
out.SaveFile(name, rBITMAP_TYPE_PNG);
|
||||
|
||||
delete[] alldata;
|
||||
//free(data);
|
||||
//free(alpha);
|
||||
}
|
||||
|
||||
void GLTexture::Save(RSXTexture& tex)
|
||||
{
|
||||
static const std::string& dir_path = "textures";
|
||||
static const std::string& file_fmt = dir_path + "/" + "tex[%d].png";
|
||||
|
||||
if (!rExists(dir_path)) rMkdir(dir_path);
|
||||
|
||||
u32 count = 0;
|
||||
while (rExists(fmt::Format(file_fmt, count))) count++;
|
||||
Save(tex, fmt::Format(file_fmt, count));
|
||||
}
|
||||
|
||||
void GLTexture::Bind()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
}
|
||||
|
||||
void GLTexture::Unbind()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void GLTexture::Delete()
|
||||
{
|
||||
if (m_id)
|
||||
{
|
||||
glDeleteTextures(1, &m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PostDrawObj::Draw()
|
||||
{
|
||||
static bool s_is_initialized = false;
|
||||
|
||||
if (!s_is_initialized)
|
||||
{
|
||||
s_is_initialized = true;
|
||||
Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_program.Use();
|
||||
}
|
||||
}
|
||||
|
||||
void PostDrawObj::Initialize()
|
||||
{
|
||||
InitializeShaders();
|
||||
m_fp.Compile();
|
||||
m_vp.Compile();
|
||||
m_program.Create(m_vp.id, m_fp.GetId());
|
||||
m_program.Use();
|
||||
InitializeLocations();
|
||||
}
|
||||
|
||||
void DrawCursorObj::Draw()
|
||||
{
|
||||
checkForGlError("PostDrawObj : Unknown error.");
|
||||
|
||||
PostDrawObj::Draw();
|
||||
checkForGlError("PostDrawObj::Draw");
|
||||
|
||||
if (!m_fbo.IsCreated())
|
||||
{
|
||||
m_fbo.Create();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Create");
|
||||
m_fbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind");
|
||||
|
||||
m_rbo.Create();
|
||||
checkForGlError("DrawCursorObj : m_rbo.Create");
|
||||
m_rbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_rbo.Bind");
|
||||
m_rbo.Storage(GL_RGBA, m_width, m_height);
|
||||
checkForGlError("DrawCursorObj : m_rbo.Storage");
|
||||
|
||||
m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0, m_rbo.GetId());
|
||||
checkForGlError("DrawCursorObj : m_fbo.Renderbuffer");
|
||||
}
|
||||
|
||||
m_fbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind");
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
checkForGlError("DrawCursorObj : glDrawBuffer");
|
||||
|
||||
m_program.Use();
|
||||
checkForGlError("DrawCursorObj : m_program.Use");
|
||||
|
||||
if (m_update_texture)
|
||||
{
|
||||
//m_update_texture = false;
|
||||
|
||||
glUniform2f(m_program.GetLocation("in_tc"), m_width, m_height);
|
||||
checkForGlError("DrawCursorObj : glUniform2f");
|
||||
if (!m_tex_id)
|
||||
{
|
||||
glGenTextures(1, &m_tex_id);
|
||||
checkForGlError("DrawCursorObj : glGenTextures");
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
checkForGlError("DrawCursorObj : glActiveTexture");
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex_id);
|
||||
checkForGlError("DrawCursorObj : glBindTexture");
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
|
||||
checkForGlError("DrawCursorObj : glTexImage2D");
|
||||
m_program.SetTex(0);
|
||||
}
|
||||
|
||||
if (m_update_pos)
|
||||
{
|
||||
//m_update_pos = false;
|
||||
|
||||
glUniform4f(m_program.GetLocation("in_pos"), m_pos_x, m_pos_y, m_pos_z, 1.0f);
|
||||
checkForGlError("DrawCursorObj : glUniform4f");
|
||||
}
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
checkForGlError("DrawCursorObj : glDrawArrays");
|
||||
|
||||
m_fbo.Bind(GL_READ_FRAMEBUFFER);
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind(GL_READ_FRAMEBUFFER)");
|
||||
GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
|
||||
checkForGlError("DrawCursorObj : GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0)");
|
||||
GLfbo::Blit(
|
||||
0, 0, m_width, m_height,
|
||||
0, 0, m_width, m_height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
checkForGlError("DrawCursorObj : GLfbo::Blit");
|
||||
m_fbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind");
|
||||
}
|
||||
|
||||
void DrawCursorObj::InitializeShaders()
|
||||
{
|
||||
m_vp.shader =
|
||||
"#version 330\n"
|
||||
"\n"
|
||||
"uniform vec4 in_pos;\n"
|
||||
"uniform vec2 in_tc;\n"
|
||||
"out vec2 tc;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" tc = in_tc;\n"
|
||||
" gl_Position = in_pos;\n"
|
||||
"}\n";
|
||||
|
||||
m_fp.SetShaderText(
|
||||
"#version 330\n"
|
||||
"\n"
|
||||
"in vec2 tc;\n"
|
||||
"uniform sampler2D tex0;\n"
|
||||
"layout (location = 0) out vec4 res;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" res = texture(tex0, tc);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void DrawCursorObj::SetTexture(void* pixels, int width, int height)
|
||||
{
|
||||
m_pixels = pixels;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
m_update_texture = true;
|
||||
}
|
||||
|
||||
void DrawCursorObj::SetPosition(float x, float y, float z)
|
||||
{
|
||||
m_pos_x = x;
|
||||
m_pos_y = y;
|
||||
m_pos_z = z;
|
||||
m_update_pos = true;
|
||||
}
|
||||
|
||||
void DrawCursorObj::InitializeLocations()
|
||||
{
|
||||
//ConLog.Warning("tex0 location = 0x%x", m_program.GetLocation("tex0"));
|
||||
}
|
||||
|
||||
GLGSRender::GLGSRender()
|
||||
: GSRender()
|
||||
, m_frame(nullptr)
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "Utilities/rPlatform.h"
|
||||
#include "GLBuffers.h"
|
||||
#include "GLProgramBuffer.h"
|
||||
@ -29,56 +28,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void Create()
|
||||
{
|
||||
if(m_id)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
void Create();
|
||||
|
||||
if(!m_id)
|
||||
{
|
||||
glGenTextures(1, &m_id);
|
||||
checkForGlError("GLTexture::Init() -> glGenTextures");
|
||||
Bind();
|
||||
}
|
||||
}
|
||||
int GetGlWrap(int wrap);
|
||||
|
||||
int GetGlWrap(int wrap)
|
||||
{
|
||||
switch(wrap)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_WRAP: return GL_REPEAT;
|
||||
case CELL_GCM_TEXTURE_MIRROR: return GL_MIRRORED_REPEAT;
|
||||
case CELL_GCM_TEXTURE_CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE;
|
||||
case CELL_GCM_TEXTURE_BORDER: return GL_CLAMP_TO_BORDER;
|
||||
case CELL_GCM_TEXTURE_CLAMP: return GL_CLAMP_TO_EDGE;
|
||||
case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP_TO_EDGE: return GL_MIRROR_CLAMP_TO_EDGE_EXT;
|
||||
case CELL_GCM_TEXTURE_MIRROR_ONCE_BORDER: return GL_MIRROR_CLAMP_TO_BORDER_EXT;
|
||||
case CELL_GCM_TEXTURE_MIRROR_ONCE_CLAMP: return GL_MIRROR_CLAMP_EXT;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture wrap error: bad wrap (%d).", wrap);
|
||||
return GL_REPEAT;
|
||||
}
|
||||
|
||||
float GetMaxAniso(int aniso)
|
||||
{
|
||||
switch (aniso)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_1: return 1.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_2: return 2.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_4: return 4.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_6: return 6.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_8: return 8.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_10: return 10.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_12: return 12.0f;
|
||||
case CELL_GCM_TEXTURE_MAX_ANISO_16: return 16.0f;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture anisotropy error: bad max aniso (%d).", aniso);
|
||||
return 1.0f;
|
||||
}
|
||||
float GetMaxAniso(int aniso);
|
||||
|
||||
inline static u8 Convert4To8(u8 v)
|
||||
{
|
||||
@ -98,526 +52,17 @@ public:
|
||||
return (v << 2) | (v >> 4);
|
||||
}
|
||||
|
||||
void Init(RSXTexture& tex)
|
||||
{
|
||||
if (tex.GetLocation() > 1)
|
||||
return;
|
||||
void Init(RSXTexture& tex);
|
||||
|
||||
Bind();
|
||||
void Save(RSXTexture& tex, const std::string& name);
|
||||
|
||||
const u64 texaddr = GetAddress(tex.GetOffset(), tex.GetLocation());
|
||||
if (!Memory.IsGoodAddr(texaddr))
|
||||
{
|
||||
LOG_ERROR(RSX, "Bad texture address=0x%x", texaddr);
|
||||
return;
|
||||
}
|
||||
//ConLog.Warning("texture addr = 0x%x, width = %d, height = %d, max_aniso=%d, mipmap=%d, remap=0x%x, zfunc=0x%x, wraps=0x%x, wrapt=0x%x, wrapr=0x%x, minlod=0x%x, maxlod=0x%x",
|
||||
// m_offset, m_width, m_height, m_maxaniso, m_mipmap, m_remap, m_zfunc, m_wraps, m_wrapt, m_wrapr, m_minlod, m_maxlod);
|
||||
//TODO: safe init
|
||||
checkForGlError("GLTexture::Init() -> glBindTexture");
|
||||
void Save(RSXTexture& tex);
|
||||
|
||||
int format = tex.GetFormat() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
bool is_swizzled = !(tex.GetFormat() & CELL_GCM_TEXTURE_LN);
|
||||
void Bind();
|
||||
|
||||
const u8 *pixels = const_cast<const u8 *>(Memory.GetMemFromAddr(texaddr));
|
||||
u8 *unswizzledPixels;
|
||||
static const GLint glRemapStandard[4] = {GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE};
|
||||
// NOTE: This must be in ARGB order in all forms below.
|
||||
const GLint *glRemap = glRemapStandard;
|
||||
void Unbind();
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8: // One 8-bit fixed-point number
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_B8)");
|
||||
|
||||
static const GLint swizzleMaskB8[] = { GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE };
|
||||
glRemap = swizzleMaskB8;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei");
|
||||
|
||||
// TODO: texture swizzling
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_A1R5G5B5)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_A1R5G5B5)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_A4R4G4B4)");
|
||||
|
||||
// We read it in as R4G4B4A4, so we need to remap each component.
|
||||
static const GLint swizzleMaskA4R4G4B4[] = { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN };
|
||||
glRemap = swizzleMaskA4R4G4B4;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G6B5)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.GetWidth(), tex.GetHeight(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_R5G6B5)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G6B5)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
if(is_swizzled)
|
||||
{
|
||||
u32 *src, *dst;
|
||||
u32 log2width, log2height;
|
||||
|
||||
unswizzledPixels = (u8*)malloc(tex.GetWidth() * tex.GetHeight() * 4);
|
||||
src = (u32*)pixels;
|
||||
dst = (u32*)unswizzledPixels;
|
||||
|
||||
log2width = log(tex.GetWidth())/log(2);
|
||||
log2height = log(tex.GetHeight())/log(2);
|
||||
|
||||
for(int i=0; i<tex.GetHeight(); i++)
|
||||
{
|
||||
for(int j=0; j<tex.GetWidth(); j++)
|
||||
{
|
||||
dst[(i*tex.GetHeight()) + j] = src[LinearToSwizzleAddress(j, i, 0, log2width, log2height, 0)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, is_swizzled ? unswizzledPixels : pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_A8R8G8B8)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: // Compressed 4x4 pixels into 8 bytes
|
||||
{
|
||||
u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 8;
|
||||
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT1)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: // Compressed 4x4 pixels into 16 bytes
|
||||
{
|
||||
u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 16;
|
||||
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT23)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: // Compressed 4x4 pixels into 16 bytes
|
||||
{
|
||||
u32 size = ((tex.GetWidth() + 3) / 4) * ((tex.GetHeight() + 3) / 4) * 16;
|
||||
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.GetWidth(), tex.GetHeight(), 0, size, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glCompressedTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_DXT45)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_G8B8:
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_UNSIGNED_BYTE, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_G8B8)");
|
||||
|
||||
static const GLint swizzleMaskG8B8[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN };
|
||||
glRemap = swizzleMaskG8B8;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_R6G5B5:
|
||||
{
|
||||
// TODO: Probably need to actually unswizzle if is_swizzled.
|
||||
const u32 numPixels = tex.GetWidth() * tex.GetHeight();
|
||||
unswizzledPixels = (u8 *)malloc(numPixels * 4);
|
||||
// TODO: Speed.
|
||||
for (u32 i = 0; i < numPixels; ++i) {
|
||||
u16 c = reinterpret_cast<const be_t<u16> *>(pixels)[i];
|
||||
unswizzledPixels[i * 4 + 0] = Convert6To8((c >> 10) & 0x3F);
|
||||
unswizzledPixels[i * 4 + 1] = Convert5To8((c >> 5) & 0x1F);
|
||||
unswizzledPixels[i * 4 + 2] = Convert5To8((c >> 0) & 0x1F);
|
||||
unswizzledPixels[i * 4 + 3] = 255;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_R6G5B5)");
|
||||
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8: // 24-bit unsigned fixed-point number and 8 bits of garbage
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH24_D8)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // 24-bit unsigned float and 8 bits of garbage
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH16: // 16-bit unsigned fixed-point number
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_SHORT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH16)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // 16-bit unsigned float
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.GetWidth(), tex.GetHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_DEPTH16_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_X16)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_UNSIGNED_SHORT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_X16)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_X16)");
|
||||
|
||||
static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE };
|
||||
glRemap = swizzleMaskX16;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_UNSIGNED_SHORT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_Y16_X16)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16)");
|
||||
|
||||
static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED };
|
||||
glRemap = swizzleMaskX32_Y16_X16;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_R5G5B5A1:
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G5B5A1)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_R5G5B5A1)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_R5G5B5A1)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_HALF_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT)");
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_X32_FLOAT: // One 32-bit floating-point number
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RED, GL_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_X32_FLOAT)");
|
||||
|
||||
static const GLint swizzleMaskX32_FLOAT[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE };
|
||||
glRemap = swizzleMaskX32_FLOAT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_D1R5G5B5:
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_D1R5G5B5)");
|
||||
|
||||
// TODO: Texture swizzling
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_D1R5G5B5)");
|
||||
|
||||
static const GLint swizzleMaskX32_D1R5G5B5[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
|
||||
glRemap = swizzleMaskX32_D1R5G5B5;
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_D1R5G5B5)");
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8: // 8 bits of garbage and three unsigned 8-bit fixed-point numbers
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_D8R8G8B8)");
|
||||
|
||||
static const GLint swizzleMaskX32_D8R8G8B8[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
|
||||
glRemap = swizzleMaskX32_D8R8G8B8;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16_FLOAT)");
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RG, GL_HALF_FLOAT, pixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_Y16_X16_FLOAT)");
|
||||
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
|
||||
checkForGlError("GLTexture::Init() -> glPixelStorei(CELL_GCM_TEXTURE_Y16_X16_FLOAT)");
|
||||
|
||||
static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN };
|
||||
glRemap = swizzleMaskX32_Y16_X16_FLOAT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN):
|
||||
{
|
||||
const u32 numPixels = tex.GetWidth() * tex.GetHeight();
|
||||
unswizzledPixels = (u8 *)malloc(numPixels * 4);
|
||||
// TODO: Speed.
|
||||
for (u32 i = 0; i < numPixels; i += 2) {
|
||||
unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 3];
|
||||
unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 2];
|
||||
unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 0];
|
||||
unswizzledPixels[i * 4 + 0 + 3] = 255;
|
||||
|
||||
// The second pixel is the same, except for red.
|
||||
unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 1];
|
||||
unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 2];
|
||||
unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 0];
|
||||
unswizzledPixels[i * 4 + 4 + 3] = 255;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN)");
|
||||
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN):
|
||||
{
|
||||
const u32 numPixels = tex.GetWidth() * tex.GetHeight();
|
||||
unswizzledPixels = (u8 *)malloc(numPixels * 4);
|
||||
// TODO: Speed.
|
||||
for (u32 i = 0; i < numPixels; i += 2) {
|
||||
unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 2];
|
||||
unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 3];
|
||||
unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 1];
|
||||
unswizzledPixels[i * 4 + 0 + 3] = 255;
|
||||
|
||||
// The second pixel is the same, except for red.
|
||||
unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 0];
|
||||
unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 3];
|
||||
unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 1];
|
||||
unswizzledPixels[i * 4 + 4 + 3] = 255;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.GetWidth(), tex.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
|
||||
checkForGlError("GLTexture::Init() -> glTexImage2D(CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8 & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN)");
|
||||
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
break;
|
||||
|
||||
default: LOG_ERROR(RSX, "Init tex error: Bad tex format (0x%x | %s | 0x%x)", format,
|
||||
(is_swizzled ? "swizzled" : "linear"), tex.GetFormat() & 0x40); break;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.GetMipmap() - 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.GetMipmap() > 1);
|
||||
|
||||
if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT)
|
||||
{
|
||||
u8 remap_a = tex.GetRemap() & 0x3;
|
||||
u8 remap_r = (tex.GetRemap() >> 2) & 0x3;
|
||||
u8 remap_g = (tex.GetRemap() >> 4) & 0x3;
|
||||
u8 remap_b = (tex.GetRemap() >> 6) & 0x3;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
|
||||
}
|
||||
|
||||
checkForGlError("GLTexture::Init() -> remap");
|
||||
|
||||
static const int gl_tex_zfunc[] =
|
||||
{
|
||||
GL_NEVER,
|
||||
GL_LESS,
|
||||
GL_EQUAL,
|
||||
GL_LEQUAL,
|
||||
GL_GREATER,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_ALWAYS,
|
||||
};
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetGlWrap(tex.GetWrapS()));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetGlWrap(tex.GetWrapT()));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GetGlWrap(tex.GetWrapR()));
|
||||
|
||||
checkForGlError("GLTexture::Init() -> wrap");
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.GetZfunc()]);
|
||||
|
||||
checkForGlError("GLTexture::Init() -> compare");
|
||||
|
||||
glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, tex.GetBias());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, (tex.GetMinLOD() >> 8));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (tex.GetMaxLOD() >> 8));
|
||||
|
||||
checkForGlError("GLTexture::Init() -> lod");
|
||||
|
||||
static const int gl_tex_min_filter[] =
|
||||
{
|
||||
GL_NEAREST, // unused
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_NEAREST, // CELL_GCM_TEXTURE_CONVOLUTION_MIN
|
||||
};
|
||||
|
||||
static const int gl_tex_mag_filter[] = {
|
||||
GL_NEAREST, // unused
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_NEAREST, // unused
|
||||
GL_LINEAR // CELL_GCM_TEXTURE_CONVOLUTION_MAG
|
||||
};
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_min_filter[tex.GetMinFilter()]);
|
||||
|
||||
checkForGlError("GLTexture::Init() -> min filters");
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter[tex.GetMagFilter()]);
|
||||
|
||||
checkForGlError("GLTexture::Init() -> mag filters");
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GetMaxAniso(tex.GetMaxAniso()));
|
||||
|
||||
checkForGlError("GLTexture::Init() -> max anisotropy");
|
||||
|
||||
//Unbind();
|
||||
|
||||
if(is_swizzled && format == CELL_GCM_TEXTURE_A8R8G8B8)
|
||||
{
|
||||
free(unswizzledPixels);
|
||||
}
|
||||
}
|
||||
|
||||
void Save(RSXTexture& tex, const std::string& name)
|
||||
{
|
||||
if(!m_id || !tex.GetOffset() || !tex.GetWidth() || !tex.GetHeight()) return;
|
||||
|
||||
const u32 texPixelCount = tex.GetWidth() * tex.GetHeight();
|
||||
|
||||
u32* alldata = new u32[texPixelCount];
|
||||
|
||||
Bind();
|
||||
|
||||
switch(tex.GetFormat() & ~(0x20 | 0x40))
|
||||
{
|
||||
case CELL_GCM_TEXTURE_B8:
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, alldata);
|
||||
break;
|
||||
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, alldata);
|
||||
break;
|
||||
|
||||
default:
|
||||
delete[] alldata;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
rFile f(name + ".raw", rFile::write);
|
||||
f.Write(alldata, texPixelCount * 4);
|
||||
}
|
||||
u8* data = new u8[texPixelCount * 3];
|
||||
u8* alpha = new u8[texPixelCount];
|
||||
|
||||
u8* src = (u8*)alldata;
|
||||
u8* dst_d = data;
|
||||
u8* dst_a = alpha;
|
||||
for (u32 i = 0; i < texPixelCount; i++)
|
||||
{
|
||||
*dst_d++ = *src++;
|
||||
*dst_d++ = *src++;
|
||||
*dst_d++ = *src++;
|
||||
*dst_a++ = *src++;
|
||||
}
|
||||
|
||||
rImage out;
|
||||
out.Create(tex.GetWidth(), tex.GetHeight(), data, alpha);
|
||||
out.SaveFile(name, rBITMAP_TYPE_PNG);
|
||||
|
||||
delete[] alldata;
|
||||
//free(data);
|
||||
//free(alpha);
|
||||
}
|
||||
|
||||
void Save(RSXTexture& tex)
|
||||
{
|
||||
static const std::string& dir_path = "textures";
|
||||
static const std::string& file_fmt = dir_path + "/" + "tex[%d].png";
|
||||
|
||||
if(!rExists(dir_path)) rMkdir(dir_path);
|
||||
|
||||
u32 count = 0;
|
||||
while(rExists(fmt::Format(file_fmt, count))) count++;
|
||||
Save(tex, fmt::Format(file_fmt, count));
|
||||
}
|
||||
|
||||
void Bind()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
}
|
||||
|
||||
void Unbind()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void Delete()
|
||||
{
|
||||
if(m_id)
|
||||
{
|
||||
glDeleteTextures(1, &m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
void Delete();
|
||||
};
|
||||
|
||||
class PostDrawObj
|
||||
@ -630,33 +75,12 @@ protected:
|
||||
GLrbo m_rbo;
|
||||
|
||||
public:
|
||||
virtual void Draw()
|
||||
{
|
||||
static bool s_is_initialized = false;
|
||||
|
||||
if(!s_is_initialized)
|
||||
{
|
||||
s_is_initialized = true;
|
||||
Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_program.Use();
|
||||
}
|
||||
}
|
||||
virtual void Draw();
|
||||
|
||||
virtual void InitializeShaders() = 0;
|
||||
virtual void InitializeLocations() = 0;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
InitializeShaders();
|
||||
m_fp.Compile();
|
||||
m_vp.Compile();
|
||||
m_program.Create(m_vp.id, m_fp.GetId());
|
||||
m_program.Use();
|
||||
InitializeLocations();
|
||||
}
|
||||
void Initialize();
|
||||
};
|
||||
|
||||
class DrawCursorObj : public PostDrawObj
|
||||
@ -675,133 +99,15 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Draw()
|
||||
{
|
||||
checkForGlError("PostDrawObj : Unknown error.");
|
||||
virtual void Draw();
|
||||
|
||||
PostDrawObj::Draw();
|
||||
checkForGlError("PostDrawObj::Draw");
|
||||
virtual void InitializeShaders();
|
||||
|
||||
if(!m_fbo.IsCreated())
|
||||
{
|
||||
m_fbo.Create();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Create");
|
||||
m_fbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind");
|
||||
void SetTexture(void* pixels, int width, int height);
|
||||
|
||||
m_rbo.Create();
|
||||
checkForGlError("DrawCursorObj : m_rbo.Create");
|
||||
m_rbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_rbo.Bind");
|
||||
m_rbo.Storage(GL_RGBA, m_width, m_height);
|
||||
checkForGlError("DrawCursorObj : m_rbo.Storage");
|
||||
void SetPosition(float x, float y, float z = 0.0f);
|
||||
|
||||
m_fbo.Renderbuffer(GL_COLOR_ATTACHMENT0, m_rbo.GetId());
|
||||
checkForGlError("DrawCursorObj : m_fbo.Renderbuffer");
|
||||
}
|
||||
|
||||
m_fbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind");
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
checkForGlError("DrawCursorObj : glDrawBuffer");
|
||||
|
||||
m_program.Use();
|
||||
checkForGlError("DrawCursorObj : m_program.Use");
|
||||
|
||||
if(m_update_texture)
|
||||
{
|
||||
//m_update_texture = false;
|
||||
|
||||
glUniform2f(m_program.GetLocation("in_tc"), m_width, m_height);
|
||||
checkForGlError("DrawCursorObj : glUniform2f");
|
||||
if(!m_tex_id)
|
||||
{
|
||||
glGenTextures(1, &m_tex_id);
|
||||
checkForGlError("DrawCursorObj : glGenTextures");
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
checkForGlError("DrawCursorObj : glActiveTexture");
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex_id);
|
||||
checkForGlError("DrawCursorObj : glBindTexture");
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
|
||||
checkForGlError("DrawCursorObj : glTexImage2D");
|
||||
m_program.SetTex(0);
|
||||
}
|
||||
|
||||
if(m_update_pos)
|
||||
{
|
||||
//m_update_pos = false;
|
||||
|
||||
glUniform4f(m_program.GetLocation("in_pos"), m_pos_x, m_pos_y, m_pos_z, 1.0f);
|
||||
checkForGlError("DrawCursorObj : glUniform4f");
|
||||
}
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
checkForGlError("DrawCursorObj : glDrawArrays");
|
||||
|
||||
m_fbo.Bind(GL_READ_FRAMEBUFFER);
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind(GL_READ_FRAMEBUFFER)");
|
||||
GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0);
|
||||
checkForGlError("DrawCursorObj : GLfbo::Bind(GL_DRAW_FRAMEBUFFER, 0)");
|
||||
GLfbo::Blit(
|
||||
0, 0, m_width, m_height,
|
||||
0, 0, m_width, m_height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
checkForGlError("DrawCursorObj : GLfbo::Blit");
|
||||
m_fbo.Bind();
|
||||
checkForGlError("DrawCursorObj : m_fbo.Bind");
|
||||
}
|
||||
|
||||
virtual void InitializeShaders()
|
||||
{
|
||||
m_vp.shader =
|
||||
"#version 330\n"
|
||||
"\n"
|
||||
"uniform vec4 in_pos;\n"
|
||||
"uniform vec2 in_tc;\n"
|
||||
"out vec2 tc;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" tc = in_tc;\n"
|
||||
" gl_Position = in_pos;\n"
|
||||
"}\n";
|
||||
|
||||
m_fp.SetShaderText(
|
||||
"#version 330\n"
|
||||
"\n"
|
||||
"in vec2 tc;\n"
|
||||
"uniform sampler2D tex0;\n"
|
||||
"layout (location = 0) out vec4 res;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" res = texture(tex0, tc);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void SetTexture(void* pixels, int width, int height)
|
||||
{
|
||||
m_pixels = pixels;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
m_update_texture = true;
|
||||
}
|
||||
|
||||
void SetPosition(float x, float y, float z = 0.0f)
|
||||
{
|
||||
m_pos_x = x;
|
||||
m_pos_y = y;
|
||||
m_pos_z = z;
|
||||
m_update_pos = true;
|
||||
}
|
||||
|
||||
void InitializeLocations()
|
||||
{
|
||||
//ConLog.Warning("tex0 location = 0x%x", m_program.GetLocation("tex0"));
|
||||
}
|
||||
void InitializeLocations();
|
||||
};
|
||||
|
||||
class GLGSRender //TODO: find out why this used to inherit from wxWindow
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "GLProgram.h"
|
||||
#include "GLGSRender.h"
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "GLVertexProgram.h"
|
||||
|
@ -1,12 +1,23 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
|
||||
#include "sysutil_video.h"
|
||||
|
||||
#include "GSManager.h"
|
||||
#include "Null/NullGSRender.h"
|
||||
#include "GL/GLGSRender.h"
|
||||
|
||||
void GSInfo::Init()
|
||||
{
|
||||
mode.resolutionId = Ini.GSResolution.GetValue();
|
||||
mode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_INTERLACE;
|
||||
mode.conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE;
|
||||
mode.aspect = Ini.GSAspectRatio.GetValue();
|
||||
mode.refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_50HZ;
|
||||
mode.format = CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8;
|
||||
mode.pitch = 4;
|
||||
}
|
||||
|
||||
GSManager::GSManager() : m_render(nullptr)
|
||||
{
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
#include "sysutil_video.h"
|
||||
#include "GSRender.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
|
||||
struct GSInfo
|
||||
{
|
||||
@ -21,16 +19,7 @@ struct GSInfo
|
||||
{
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
mode.resolutionId = Ini.GSResolution.GetValue();
|
||||
mode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_INTERLACE;
|
||||
mode.conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE;
|
||||
mode.aspect = Ini.GSAspectRatio.GetValue();
|
||||
mode.refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_50HZ;
|
||||
mode.format = CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8;
|
||||
mode.pitch = 4;
|
||||
}
|
||||
void Init();
|
||||
};
|
||||
|
||||
class GSManager
|
||||
|
@ -1,10 +1,30 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "GSRender.h"
|
||||
|
||||
GSLock::GSLock(GSRender& renderer, GSLockType type)
|
||||
: m_renderer(renderer)
|
||||
, m_type(type)
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.lock(); break;
|
||||
case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.wait(); break;
|
||||
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.wait(); break;
|
||||
}
|
||||
}
|
||||
|
||||
GSLock::~GSLock()
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.unlock(); break;
|
||||
case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.post(); break;
|
||||
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.post(); break;
|
||||
}
|
||||
}
|
||||
|
||||
GSLockCurrent::GSLockCurrent(GSLockType type) : GSLock(Emu.GetGSManager().GetRender(), type)
|
||||
{
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "Emu/RSX/GCM.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
|
||||
struct GSRender : public RSXThread
|
||||
@ -25,27 +24,9 @@ private:
|
||||
GSLockType m_type;
|
||||
|
||||
public:
|
||||
GSLock(GSRender& renderer, GSLockType type)
|
||||
: m_renderer(renderer)
|
||||
, m_type(type)
|
||||
{
|
||||
switch(m_type)
|
||||
{
|
||||
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.lock(); break;
|
||||
case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.wait(); break;
|
||||
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.wait(); break;
|
||||
}
|
||||
}
|
||||
GSLock(GSRender& renderer, GSLockType type);
|
||||
|
||||
~GSLock()
|
||||
{
|
||||
switch(m_type)
|
||||
{
|
||||
case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.unlock(); break;
|
||||
case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.post(); break;
|
||||
case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.post(); break;
|
||||
}
|
||||
}
|
||||
~GSLock();
|
||||
};
|
||||
|
||||
struct GSLockCurrent : GSLock
|
||||
|
@ -1,7 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "RSXThread.h"
|
||||
#include "RSXThread.h"
|
||||
#include "RSXTexture.h"
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "RSXThread.h"
|
||||
#include "Emu/SysCalls/lv2/sys_time.h"
|
||||
|
||||
#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args) : args[x].ToLE())
|
||||
#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args.GetAddr()) : args[x].ToLE())
|
||||
|
||||
u32 methodRegisters[0xffff];
|
||||
|
||||
@ -139,8 +140,9 @@ u32 RSXVertexData::GetTypeSize()
|
||||
#define CMD_LOG(...)
|
||||
#endif
|
||||
|
||||
u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, mem32_ptr_t args)
|
||||
u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr)
|
||||
{
|
||||
mem32_ptr_t args(args_addr);
|
||||
std::string debug = GetMethodName(cmd);
|
||||
debug += "(";
|
||||
for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i));
|
||||
@ -205,8 +207,10 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, mem3
|
||||
index = (cmd - a) / m; \
|
||||
case a \
|
||||
|
||||
void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t args, const u32 count)
|
||||
void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count)
|
||||
{
|
||||
mem32_ptr_t args(args_addr);
|
||||
|
||||
#if CMD_DEBUG
|
||||
std::string debug = GetMethodName(cmd);
|
||||
debug += "(";
|
||||
@ -2237,7 +2241,7 @@ void RSXThread::Task()
|
||||
methodRegisters[(cmd & 0xffff) + (i*4*inc)] = ARGS(i);
|
||||
}
|
||||
|
||||
DoCmd(cmd, cmd & 0x3ffff, args, count);
|
||||
DoCmd(cmd, cmd & 0x3ffff, args.GetAddr(), count);
|
||||
|
||||
m_ctrl->get = get + (count + 1) * 4;
|
||||
//memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4);
|
||||
@ -2252,3 +2256,33 @@ void RSXThread::Task()
|
||||
|
||||
OnExitThread();
|
||||
}
|
||||
|
||||
void RSXThread::Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
|
||||
{
|
||||
m_ctrl = (CellGcmControl*)&Memory[ctrlAddress];
|
||||
m_ioAddress = ioAddress;
|
||||
m_ioSize = ioSize;
|
||||
m_ctrlAddress = ctrlAddress;
|
||||
m_local_mem_addr = localAddress;
|
||||
|
||||
m_cur_vertex_prog = nullptr;
|
||||
m_cur_shader_prog = nullptr;
|
||||
m_cur_shader_prog_num = 0;
|
||||
|
||||
m_used_gcm_commands.clear();
|
||||
|
||||
OnInit();
|
||||
ThreadBase::Start();
|
||||
}
|
||||
|
||||
u32 RSXThread::ReadIO32(u32 addr)
|
||||
{
|
||||
u32 value;
|
||||
Memory.RSXIOMem.Read32(Memory.RSXIOMem.GetStartAddr() + addr, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void RSXThread::WriteIO32(u32 addr, u32 value)
|
||||
{
|
||||
Memory.RSXIOMem.Write32(Memory.RSXIOMem.GetStartAddr() + addr, value);
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
#include "RSXVertexProgram.h"
|
||||
#include "RSXFragmentProgram.h"
|
||||
#include "Emu/SysCalls/Callback.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
||||
#include <stack>
|
||||
#include <set> // For tracking a list of used gcm commands
|
||||
@ -611,8 +610,8 @@ protected:
|
||||
void Begin(u32 draw_mode);
|
||||
void End();
|
||||
|
||||
u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, mem32_ptr_t args);
|
||||
void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t args, const u32 count);
|
||||
u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr);
|
||||
void DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count);
|
||||
void nativeRescale(float width, float height);
|
||||
|
||||
virtual void OnInit() = 0;
|
||||
@ -636,33 +635,9 @@ protected:
|
||||
virtual void Task();
|
||||
|
||||
public:
|
||||
void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
|
||||
{
|
||||
m_ctrl = (CellGcmControl*)&Memory[ctrlAddress];
|
||||
m_ioAddress = ioAddress;
|
||||
m_ioSize = ioSize;
|
||||
m_ctrlAddress = ctrlAddress;
|
||||
m_local_mem_addr = localAddress;
|
||||
void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);
|
||||
|
||||
m_cur_vertex_prog = nullptr;
|
||||
m_cur_shader_prog = nullptr;
|
||||
m_cur_shader_prog_num = 0;
|
||||
u32 ReadIO32(u32 addr);
|
||||
|
||||
m_used_gcm_commands.clear();
|
||||
|
||||
OnInit();
|
||||
ThreadBase::Start();
|
||||
}
|
||||
|
||||
u32 ReadIO32(u32 addr)
|
||||
{
|
||||
u32 value;
|
||||
Memory.RSXIOMem.Read32(Memory.RSXIOMem.GetStartAddr() + addr, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void WriteIO32(u32 addr, u32 value)
|
||||
{
|
||||
Memory.RSXIOMem.Write32(Memory.RSXIOMem.GetStartAddr() + addr, value);
|
||||
}
|
||||
void WriteIO32(u32 addr, u32 value);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "LogBase.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/Modules.h"
|
||||
#include "cellSysutil.h"
|
||||
#include "Emu/RSX/sysutil_video.h"
|
||||
#include "cellResc.h"
|
||||
|
||||
Module *cellResc = nullptr;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
@ -9,6 +10,7 @@
|
||||
|
||||
#include "cellSysutil.h"
|
||||
#include "cellSysutil_SaveData.h"
|
||||
#include "Emu/RSX/sysutil_video.h"
|
||||
#include "cellMsgDialog.h"
|
||||
#include "cellGame.h"
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Utilities/rXml.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Utilities/AutoPause.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "lv2/sys_tty.h"
|
||||
#include "lv2/sys_vm.h"
|
||||
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "LogBase.h"
|
||||
|
||||
//#define SYSCALLS_DEBUG
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
|
||||
#include "Emu/Event.h"
|
||||
#include "sys_event.h"
|
||||
|
||||
SysCallBase sys_event("sys_event");
|
||||
|
@ -10,6 +10,34 @@
|
||||
|
||||
SysCallBase sys_event_flag("sys_event_flag");
|
||||
|
||||
u32 EventFlag::check()
|
||||
{
|
||||
SleepQueue sq; // TODO: implement without SleepQueue
|
||||
|
||||
u32 target = 0;
|
||||
|
||||
for (u32 i = 0; i < waiters.size(); i++)
|
||||
{
|
||||
if (((waiters[i].mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & waiters[i].bitptn) == waiters[i].bitptn) ||
|
||||
((waiters[i].mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & waiters[i].bitptn)))
|
||||
{
|
||||
if (m_protocol == SYS_SYNC_FIFO)
|
||||
{
|
||||
target = waiters[i].tid;
|
||||
break;
|
||||
}
|
||||
sq.list.push_back(waiters[i].tid);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
target = sq.pop_prio();
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
s32 sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr, u64 init)
|
||||
{
|
||||
sys_event_flag.Warning("sys_event_flag_create(eflag_id_addr=0x%x, attr_addr=0x%x, init=0x%llx)",
|
||||
|
@ -47,33 +47,7 @@ struct EventFlag
|
||||
{
|
||||
}
|
||||
|
||||
u32 check()
|
||||
{
|
||||
SleepQueue sq; // TODO: implement without SleepQueue
|
||||
|
||||
u32 target = 0;
|
||||
|
||||
for (u32 i = 0; i < waiters.size(); i++)
|
||||
{
|
||||
if (((waiters[i].mode & SYS_EVENT_FLAG_WAIT_AND) && (flags & waiters[i].bitptn) == waiters[i].bitptn) ||
|
||||
((waiters[i].mode & SYS_EVENT_FLAG_WAIT_OR) && (flags & waiters[i].bitptn)))
|
||||
{
|
||||
if (m_protocol == SYS_SYNC_FIFO)
|
||||
{
|
||||
target = waiters[i].tid;
|
||||
break;
|
||||
}
|
||||
sq.list.push_back(waiters[i].tid);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_protocol == SYS_SYNC_PRIORITY)
|
||||
{
|
||||
target = sq.pop_prio();
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
u32 check();
|
||||
};
|
||||
|
||||
s32 sys_event_flag_create(mem32_t eflag_id, mem_ptr_t<sys_event_flag_attr> attr, u64 init);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/FS/vfsFile.h"
|
||||
#include "sys_spu.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "Emu/RSX/GSManager.h"
|
||||
#include "Emu/Audio/AudioManager.h"
|
||||
#include "Emu/FS/VFS.h"
|
||||
#include "Emu/Event.h"
|
||||
#include "Loader/Loader.h"
|
||||
|
||||
enum Status
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
|
||||
#include "Emu/SysCalls/lv2/sys_event.h"
|
||||
#include "DisAsmFrame.h"
|
||||
#include "Emu/FS/vfsLocalFile.h"
|
||||
#include "Emu/Cell/PPCThread.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "GSFrame.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/RSX/sysutil_video.h"
|
||||
#include "rpcs3.h"
|
||||
|
||||
BEGIN_EVENT_TABLE(GSFrame, wxFrame)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <wx/listctrl.h>
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Emu/GameInfo.h"
|
||||
|
||||
struct Column
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "rpcs3.h"
|
||||
#include "Emu/SysCalls/lv2/sys_lwmutex.h"
|
||||
#include "Emu/SysCalls/lv2/sys_event.h"
|
||||
#include "InterpreterDisAsm.h"
|
||||
#include "Emu/Cell/PPUDecoder.h"
|
||||
#include "Emu/Cell/PPUDisAsm.h"
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user