mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Merge branch 'master' into perfqueries.
Conflicts: Source/Core/VideoCommon/Src/VideoConfig.h Source/Core/VideoCommon/VideoCommon.vcxproj.filters Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
This commit is contained in:
@ -26,13 +26,25 @@ if(wxWidgets_FOUND)
|
||||
endif(wxWidgets_FOUND)
|
||||
|
||||
set(LIBS videocommon
|
||||
GLEW
|
||||
SOIL
|
||||
common
|
||||
${OPENGL_LIBRARIES}
|
||||
${X11_LIBRARIES}
|
||||
${wxWidgets_LIBRARIES})
|
||||
if(USE_EGL)
|
||||
set(LIBS ${LIBS}
|
||||
EGL)
|
||||
endif()
|
||||
|
||||
if(USE_GLES)
|
||||
set(SRCS ${SRCS}
|
||||
../Plugin_VideoOGL/Src/GLUtil.cpp)
|
||||
set(LIBS ${LIBS}
|
||||
GLESv2)
|
||||
else()
|
||||
set(LIBS ${LIBS}
|
||||
GLEW
|
||||
${OPENGL_LIBRARIES})
|
||||
endif()
|
||||
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
|
||||
set(LIBS ${LIBS} clrun)
|
||||
endif()
|
||||
|
@ -126,7 +126,46 @@ void SWBPWritten(int address, int newvalue)
|
||||
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case BPMEM_PRELOAD_MODE:
|
||||
if (newvalue != 0)
|
||||
{
|
||||
// TODO: Not quite sure if this is completely correct (likely not)
|
||||
// NOTE: libogc's implementation of GX_PreloadEntireTexture seems flawed, so it's not necessarily a good reference for RE'ing this feature.
|
||||
|
||||
BPS_TmemConfig& tmem_cfg = bpmem.tmem_config;
|
||||
u8* src_ptr = Memory::GetPointer(tmem_cfg.preload_addr << 5); // TODO: Should we add mask here on GC?
|
||||
u32 size = tmem_cfg.preload_tile_info.count * TMEM_LINE_SIZE;
|
||||
u32 tmem_addr_even = tmem_cfg.preload_tmem_even * TMEM_LINE_SIZE;
|
||||
|
||||
if (tmem_cfg.preload_tile_info.type != 3)
|
||||
{
|
||||
if (tmem_addr_even + size > TMEM_SIZE)
|
||||
size = TMEM_SIZE - tmem_addr_even;
|
||||
|
||||
memcpy(texMem + tmem_addr_even, src_ptr, size);
|
||||
}
|
||||
else // RGBA8 tiles (and CI14, but that might just be stupid libogc!)
|
||||
{
|
||||
// AR and GB tiles are stored in separate TMEM banks => can't use a single memcpy for everything
|
||||
u32 tmem_addr_odd = tmem_cfg.preload_tmem_odd * TMEM_LINE_SIZE;
|
||||
|
||||
for (unsigned int i = 0; i < tmem_cfg.preload_tile_info.count; ++i)
|
||||
{
|
||||
if (tmem_addr_even + TMEM_LINE_SIZE > TMEM_SIZE ||
|
||||
tmem_addr_odd + TMEM_LINE_SIZE > TMEM_SIZE)
|
||||
break;
|
||||
|
||||
memcpy(texMem + tmem_addr_even, src_ptr, TMEM_LINE_SIZE);
|
||||
memcpy(texMem + tmem_addr_odd, src_ptr + TMEM_LINE_SIZE, TMEM_LINE_SIZE);
|
||||
tmem_addr_even += TMEM_LINE_SIZE;
|
||||
tmem_addr_odd += TMEM_LINE_SIZE;
|
||||
src_ptr += TMEM_LINE_SIZE * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_TEV_REGISTER_L: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_L+2: // Reg 2
|
||||
case BPMEM_TEV_REGISTER_L+4: // Reg 3
|
||||
|
@ -65,6 +65,13 @@ namespace Clipper
|
||||
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
|
||||
OutputVertexData *Vertices[NUM_INDICES];
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoArray(m_ViewOffset,2);
|
||||
for (int i = 0; i< NUM_CLIPPED_VERTICES; ++i)
|
||||
ClippedVertices[i].DoState(p);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
|
||||
namespace Clipper
|
||||
@ -36,6 +37,8 @@ namespace Clipper
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
|
||||
|
||||
void PerspectiveDivide(OutputVertexData *vertex);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,8 +62,8 @@ void SaveTexture(const char* filename, u32 texmap, s32 mip)
|
||||
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
|
||||
int width = ti0.width + 1;
|
||||
int height = ti0.height + 1;
|
||||
u32 width = ti0.width + 1;
|
||||
u32 height = ti0.height + 1;
|
||||
|
||||
u8 *data = new u8[width * height * 4];
|
||||
|
||||
@ -74,19 +74,23 @@ void SaveTexture(const char* filename, u32 texmap, s32 mip)
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, int width, int height)
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height)
|
||||
{
|
||||
u8 sample[4];
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
for (u32 x = 0; x < width; x++)
|
||||
{
|
||||
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
|
||||
// rgba to bgra
|
||||
|
||||
// RGBA to BGRA
|
||||
*(dst++) = sample[2];
|
||||
*(dst++) = sample[1];
|
||||
*(dst++) = sample[0];
|
||||
*(dst++) = sample[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 GetMaxTextureLod(u32 texmap)
|
||||
|
@ -22,7 +22,7 @@ namespace DebugUtil
|
||||
{
|
||||
void Init();
|
||||
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, int width, int height);
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height);
|
||||
|
||||
void DumpActiveTextures();
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "DebugUtil.h"
|
||||
#include "HwRasterizer.h"
|
||||
#include "SWCommandProcessor.h"
|
||||
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
|
||||
#include "HW/Memmap.h"
|
||||
#include "Core.h"
|
||||
|
||||
@ -33,7 +32,7 @@ namespace EfbCopy
|
||||
{
|
||||
void CopyToXfb()
|
||||
{
|
||||
OpenGL_Update(); // just updates the render window position and the backbuffer size
|
||||
GLInterface->Update(); // just updates the render window position and the backbuffer size
|
||||
|
||||
if (!g_SWVideoConfig.bHwRasterizer)
|
||||
{
|
||||
|
@ -28,6 +28,7 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6];
|
||||
|
||||
namespace EfbInterface
|
||||
{
|
||||
|
||||
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
|
||||
|
||||
inline u32 GetColorOffset(u16 x, u16 y)
|
||||
@ -40,6 +41,12 @@ namespace EfbInterface
|
||||
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoArray(efb, EFB_WIDTH*EFB_HEIGHT*6);
|
||||
p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4);
|
||||
}
|
||||
|
||||
void SetPixelAlphaOnly(u32 offset, u8 a)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
@ -355,7 +362,7 @@ namespace EfbInterface
|
||||
dstClr = (~srcClr) & dstClr;
|
||||
break;
|
||||
case 5: // noop
|
||||
dstClr = dstClr;
|
||||
// Do nothing
|
||||
break;
|
||||
case 6: // xor
|
||||
dstClr = srcClr ^ dstClr;
|
||||
|
@ -47,6 +47,7 @@ namespace EfbInterface
|
||||
|
||||
void UpdateColorTexture();
|
||||
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -29,163 +29,354 @@
|
||||
|
||||
namespace HwRasterizer
|
||||
{
|
||||
float efbHalfWidth;
|
||||
float efbHalfHeight;
|
||||
bool hasTexture;
|
||||
float efbHalfWidth;
|
||||
float efbHalfHeight;
|
||||
bool hasTexture;
|
||||
|
||||
u8 *temp;
|
||||
u8 *temp;
|
||||
|
||||
void Init()
|
||||
{
|
||||
efbHalfWidth = EFB_WIDTH / 2.0f;
|
||||
efbHalfHeight = 480 / 2.0f;
|
||||
// Programs
|
||||
static GLuint colProg, texProg, clearProg;
|
||||
|
||||
temp = (u8*)AllocateMemoryPages(TEMP_SIZE);
|
||||
}
|
||||
// Color
|
||||
static GLint col_apos = -1, col_atex = -1;
|
||||
// Tex
|
||||
static GLint tex_apos = -1, tex_atex = -1, tex_utex = -1;
|
||||
// Clear shader
|
||||
static GLint clear_apos = -1, clear_ucol = -1;
|
||||
|
||||
void LoadTexture()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
u32 imageAddr = texUnit.texImage3[0].image_base;
|
||||
void CreateShaders()
|
||||
{
|
||||
// Color Vertices
|
||||
static const char *fragcolText =
|
||||
"varying " PREC " vec4 TexCoordOut;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = TexCoordOut;\n"
|
||||
"}\n";
|
||||
// Texture Vertices
|
||||
static const char *fragtexText =
|
||||
"varying " PREC " vec4 TexCoordOut;\n"
|
||||
"uniform " TEXTYPE " Texture;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = " TEXFUNC "(Texture, TexCoordOut.xy);\n"
|
||||
"}\n";
|
||||
// Clear shader
|
||||
static const char *fragclearText =
|
||||
"uniform " PREC " vec4 Color;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = Color;\n"
|
||||
"}\n";
|
||||
// Generic passthrough vertice shaders
|
||||
static const char *vertShaderText =
|
||||
"attribute vec4 pos;\n"
|
||||
"attribute vec4 TexCoordIn;\n "
|
||||
"varying vec4 TexCoordOut;\n "
|
||||
"void main() {\n"
|
||||
" gl_Position = pos;\n"
|
||||
" TexCoordOut = TexCoordIn;\n"
|
||||
"}\n";
|
||||
static const char *vertclearText =
|
||||
"attribute vec4 pos;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = pos;\n"
|
||||
"}\n";
|
||||
|
||||
TexCacheEntry &cacheEntry = textures[imageAddr];
|
||||
cacheEntry.Update();
|
||||
// Color Program
|
||||
colProg = OpenGL_CompileProgram(vertShaderText, fragcolText);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, cacheEntry.texture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
}
|
||||
// Texture Program
|
||||
texProg = OpenGL_CompileProgram(vertShaderText, fragtexText);
|
||||
|
||||
void BeginTriangles()
|
||||
{
|
||||
// disabling depth test sometimes allows more things to be visible
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
// Clear Program
|
||||
clearProg = OpenGL_CompileProgram(vertclearText, fragclearText);
|
||||
|
||||
hasTexture = bpmem.tevorders[0].enable0;
|
||||
// Color attributes
|
||||
col_apos = glGetAttribLocation(colProg, "pos");
|
||||
col_atex = glGetAttribLocation(colProg, "TexCoordIn");
|
||||
// Texture attributes
|
||||
tex_apos = glGetAttribLocation(texProg, "pos");
|
||||
tex_atex = glGetAttribLocation(texProg, "TexCoordIn");
|
||||
tex_utex = glGetUniformLocation(texProg, "Texture");
|
||||
// Clear attributes
|
||||
clear_apos = glGetAttribLocation(clearProg, "pos");
|
||||
clear_ucol = glGetUniformLocation(clearProg, "Color");
|
||||
}
|
||||
|
||||
if (hasTexture)
|
||||
LoadTexture();
|
||||
}
|
||||
void Init()
|
||||
{
|
||||
efbHalfWidth = EFB_WIDTH / 2.0f;
|
||||
efbHalfHeight = 480 / 2.0f;
|
||||
|
||||
void EndTriangles()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
temp = (u8*)AllocateMemoryPages(TEMP_SIZE);
|
||||
}
|
||||
void Shutdown()
|
||||
{
|
||||
glDeleteProgram(colProg);
|
||||
glDeleteProgram(texProg);
|
||||
glDeleteProgram(clearProg);
|
||||
}
|
||||
void Prepare()
|
||||
{
|
||||
//legacy multitexturing: select texture channel only.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
|
||||
#ifndef USE_GLES
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glDisable(GL_BLEND);
|
||||
glClearDepth(1.0f);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
#endif
|
||||
// used by hw rasterizer if it enables blending and depth test
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
void DrawColorVertex(OutputVertexData *v)
|
||||
{
|
||||
glColor3ub(v->color[0][OutputVertexData::RED_C], v->color[0][OutputVertexData::GRN_C], v->color[0][OutputVertexData::BLU_C]);
|
||||
glVertex3f(v->screenPosition.x / efbHalfWidth - 1.0f, 1.0f - v->screenPosition.y / efbHalfHeight, v->screenPosition.z / (float)0x00ffffff);
|
||||
}
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
CreateShaders();
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
static float width, height;
|
||||
void LoadTexture()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
u32 imageAddr = texUnit.texImage3[0].image_base;
|
||||
// Texture Rectangle uses pixel coordinates
|
||||
// While GLES uses texture coordinates
|
||||
#ifdef USE_GLES
|
||||
width = texUnit.texImage0[0].width;
|
||||
height = texUnit.texImage0[0].height;
|
||||
#else
|
||||
width = 1;
|
||||
height = 1;
|
||||
#endif
|
||||
TexCacheEntry &cacheEntry = textures[imageAddr];
|
||||
cacheEntry.Update();
|
||||
|
||||
void DrawTextureVertex(OutputVertexData *v)
|
||||
{
|
||||
float s = v->texCoords[0].x;
|
||||
float t = v->texCoords[0].y;
|
||||
glTexCoord2f(s, t);
|
||||
glBindTexture(TEX2D, cacheEntry.texture);
|
||||
glTexParameteri(TEX2D, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(TEX2D, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
float x = (v->screenPosition.x / efbHalfWidth) - 1.0f;
|
||||
float y = 1.0f - (v->screenPosition.y / efbHalfHeight);
|
||||
float z = v->screenPosition.z;
|
||||
glVertex3f(x, y, z);
|
||||
}
|
||||
void BeginTriangles()
|
||||
{
|
||||
// disabling depth test sometimes allows more things to be visible
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
if (hasTexture)
|
||||
{
|
||||
DrawTextureVertex(v0);
|
||||
DrawTextureVertex(v1);
|
||||
DrawTextureVertex(v2);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawColorVertex(v0);
|
||||
DrawColorVertex(v1);
|
||||
DrawColorVertex(v2);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
hasTexture = bpmem.tevorders[0].enable0;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
u8 r = (bpmem.clearcolorAR & 0x00ff);
|
||||
u8 g = (bpmem.clearcolorGB & 0xff00) >> 8;
|
||||
u8 b = (bpmem.clearcolorGB & 0x00ff);
|
||||
u8 a = (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||
if (hasTexture)
|
||||
LoadTexture();
|
||||
}
|
||||
|
||||
GLfloat left = (GLfloat)bpmem.copyTexSrcXY.x / efbHalfWidth - 1.0f;
|
||||
GLfloat top = 1.0f - (GLfloat)bpmem.copyTexSrcXY.y / efbHalfHeight;
|
||||
GLfloat right = (GLfloat)(left + bpmem.copyTexSrcWH.x + 1) / efbHalfWidth - 1.0f;
|
||||
GLfloat bottom = 1.0f - (GLfloat)(top + bpmem.copyTexSrcWH.y + 1) / efbHalfHeight;
|
||||
GLfloat depth = (GLfloat)bpmem.clearZValue / (GLfloat)0x00ffffff;
|
||||
void EndTriangles()
|
||||
{
|
||||
glBindTexture(TEX2D, 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(left, top, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(right, top, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(right, bottom, depth);
|
||||
glColor4ub(r, g, b, a);
|
||||
glVertex3f(left, bottom, depth);
|
||||
glEnd();
|
||||
}
|
||||
void DrawColorVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f;
|
||||
float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight);
|
||||
float z0 = v0->screenPosition.z / (float)0x00ffffff;
|
||||
|
||||
TexCacheEntry::TexCacheEntry()
|
||||
{
|
||||
Create();
|
||||
}
|
||||
float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f;
|
||||
float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight);
|
||||
float z1 = v1->screenPosition.z / (float)0x00ffffff;
|
||||
|
||||
void TexCacheEntry::Create()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f;
|
||||
float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight);
|
||||
float z2 = v2->screenPosition.z / (float)0x00ffffff;
|
||||
|
||||
texImage0.hex = texUnit.texImage0[0].hex;
|
||||
texImage1.hex = texUnit.texImage1[0].hex;
|
||||
texImage2.hex = texUnit.texImage2[0].hex;
|
||||
texImage3.hex = texUnit.texImage3[0].hex;
|
||||
texTlut.hex = texUnit.texTlut[0].hex;
|
||||
float r0 = v0->color[0][OutputVertexData::RED_C] / 255.0f;
|
||||
float g0 = v0->color[0][OutputVertexData::GRN_C] / 255.0f;
|
||||
float b0 = v0->color[0][OutputVertexData::BLU_C] / 255.0f;
|
||||
|
||||
int width = texImage0.width;
|
||||
int height = texImage0.height;
|
||||
float r1 = v1->color[0][OutputVertexData::RED_C] / 255.0f;
|
||||
float g1 = v1->color[0][OutputVertexData::GRN_C] / 255.0f;
|
||||
float b1 = v1->color[0][OutputVertexData::BLU_C] / 255.0f;
|
||||
|
||||
DebugUtil::GetTextureBGRA(temp, 0, 0, width, height);
|
||||
float r2 = v2->color[0][OutputVertexData::RED_C] / 255.0f;
|
||||
float g2 = v2->color[0][OutputVertexData::GRN_C] / 255.0f;
|
||||
float b2 = v2->color[0][OutputVertexData::BLU_C] / 255.0f;
|
||||
|
||||
glGenTextures(1, (GLuint *)&texture);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp);
|
||||
}
|
||||
static const GLfloat verts[3][3] = {
|
||||
{ x0, y0, z0 },
|
||||
{ x1, y1, z1 },
|
||||
{ x2, y2, z2 }
|
||||
};
|
||||
static const GLfloat col[3][4] = {
|
||||
{ r0, g0, b0, 1.0f },
|
||||
{ r1, g1, b1, 1.0f },
|
||||
{ r2, g2, b2, 1.0f }
|
||||
};
|
||||
{
|
||||
glUseProgram(colProg);
|
||||
glEnableVertexAttribArray(col_apos);
|
||||
glEnableVertexAttribArray(col_atex);
|
||||
|
||||
void TexCacheEntry::Destroy()
|
||||
{
|
||||
if (texture == 0)
|
||||
return;
|
||||
glVertexAttribPointer(col_apos, 3, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(col_atex, 4, GL_FLOAT, GL_FALSE, 0, col);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glDisableVertexAttribArray(col_atex);
|
||||
glDisableVertexAttribArray(col_apos);
|
||||
}
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
void DrawTextureVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f;
|
||||
float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight);
|
||||
float z0 = v0->screenPosition.z;
|
||||
|
||||
void TexCacheEntry::Update()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f;
|
||||
float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight);
|
||||
float z1 = v1->screenPosition.z;
|
||||
|
||||
// extra checks cause textures to be reloaded much more
|
||||
if (texUnit.texImage0[0].hex != texImage0.hex ||
|
||||
//texUnit.texImage1[0].hex != texImage1.hex ||
|
||||
//texUnit.texImage2[0].hex != texImage2.hex ||
|
||||
texUnit.texImage3[0].hex != texImage3.hex ||
|
||||
texUnit.texTlut[0].hex != texTlut.hex)
|
||||
{
|
||||
Destroy();
|
||||
Create();
|
||||
}
|
||||
}
|
||||
float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f;
|
||||
float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight);
|
||||
float z2 = v2->screenPosition.z;
|
||||
|
||||
float s0 = v0->texCoords[0].x / width;
|
||||
float t0 = v0->texCoords[0].y / height;
|
||||
|
||||
float s1 = v1->texCoords[0].x / width;
|
||||
float t1 = v1->texCoords[0].y / height;
|
||||
|
||||
float s2 = v2->texCoords[0].x / width;
|
||||
float t2 = v2->texCoords[0].y / height;
|
||||
|
||||
static const GLfloat verts[3][3] = {
|
||||
{ x0, y0, z0 },
|
||||
{ x1, y1, z1 },
|
||||
{ x2, y2, z2 }
|
||||
};
|
||||
static const GLfloat tex[3][2] = {
|
||||
{ s0, t0 },
|
||||
{ s1, t1 },
|
||||
{ s2, t2 }
|
||||
};
|
||||
{
|
||||
glUseProgram(texProg);
|
||||
glEnableVertexAttribArray(tex_apos);
|
||||
glEnableVertexAttribArray(tex_atex);
|
||||
|
||||
glVertexAttribPointer(tex_apos, 3, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(tex_atex, 2, GL_FLOAT, GL_FALSE, 0, tex);
|
||||
glUniform1i(tex_utex, 0);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glDisableVertexAttribArray(tex_atex);
|
||||
glDisableVertexAttribArray(tex_apos);
|
||||
}
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
if (hasTexture)
|
||||
DrawTextureVertex(v0, v1, v2);
|
||||
else
|
||||
DrawColorVertex(v0, v1, v2);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
u8 r = (bpmem.clearcolorAR & 0x00ff);
|
||||
u8 g = (bpmem.clearcolorGB & 0xff00) >> 8;
|
||||
u8 b = (bpmem.clearcolorGB & 0x00ff);
|
||||
u8 a = (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||
|
||||
GLfloat left = (GLfloat)bpmem.copyTexSrcXY.x / efbHalfWidth - 1.0f;
|
||||
GLfloat top = 1.0f - (GLfloat)bpmem.copyTexSrcXY.y / efbHalfHeight;
|
||||
GLfloat right = (GLfloat)(left + bpmem.copyTexSrcWH.x + 1) / efbHalfWidth - 1.0f;
|
||||
GLfloat bottom = 1.0f - (GLfloat)(top + bpmem.copyTexSrcWH.y + 1) / efbHalfHeight;
|
||||
GLfloat depth = (GLfloat)bpmem.clearZValue / (GLfloat)0x00ffffff;
|
||||
static const GLfloat verts[4][3] = {
|
||||
{ left, top, depth },
|
||||
{ right, top, depth },
|
||||
{ right, bottom, depth },
|
||||
{ left, bottom, depth }
|
||||
};
|
||||
{
|
||||
glUseProgram(clearProg);
|
||||
glVertexAttribPointer(clear_apos, 3, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glUniform4f(clear_ucol, r, g, b, a);
|
||||
glEnableVertexAttribArray(col_apos);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableVertexAttribArray(col_apos);
|
||||
}
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
TexCacheEntry::TexCacheEntry()
|
||||
{
|
||||
Create();
|
||||
}
|
||||
|
||||
void TexCacheEntry::Create()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
|
||||
texImage0.hex = texUnit.texImage0[0].hex;
|
||||
texImage1.hex = texUnit.texImage1[0].hex;
|
||||
texImage2.hex = texUnit.texImage2[0].hex;
|
||||
texImage3.hex = texUnit.texImage3[0].hex;
|
||||
texTlut.hex = texUnit.texTlut[0].hex;
|
||||
|
||||
int image_width = texImage0.width;
|
||||
int image_height = texImage0.height;
|
||||
|
||||
DebugUtil::GetTextureBGRA(temp, 0, 0, image_width, image_height);
|
||||
|
||||
glGenTextures(1, (GLuint *)&texture);
|
||||
glBindTexture(TEX2D, texture);
|
||||
#ifdef USE_GLES
|
||||
glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)image_width, (GLsizei)image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
|
||||
#else
|
||||
glTexImage2D(TEX2D, 0, GL_RGBA8, (GLsizei)image_width, (GLsizei)image_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp);
|
||||
#endif
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void TexCacheEntry::Destroy()
|
||||
{
|
||||
if (texture == 0)
|
||||
return;
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
}
|
||||
|
||||
void TexCacheEntry::Update()
|
||||
{
|
||||
FourTexUnits &texUnit = bpmem.tex[0];
|
||||
|
||||
// extra checks cause textures to be reloaded much more
|
||||
if (texUnit.texImage0[0].hex != texImage0.hex ||
|
||||
//texUnit.texImage1[0].hex != texImage1.hex ||
|
||||
//texUnit.texImage2[0].hex != texImage2.hex ||
|
||||
texUnit.texImage3[0].hex != texImage3.hex ||
|
||||
texUnit.texTlut[0].hex != texTlut.hex)
|
||||
{
|
||||
Destroy();
|
||||
Create();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,9 @@ struct OutputVertexData;
|
||||
namespace HwRasterizer
|
||||
{
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void Prepare();
|
||||
|
||||
void BeginTriangles();
|
||||
void EndTriangles();
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define _NATIVEVERTEXFORMAT_H
|
||||
|
||||
#include "Vec3.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define LOADERDECL __cdecl
|
||||
@ -92,6 +93,18 @@ struct OutputVertexData
|
||||
#undef LINTERP
|
||||
#undef LINTERP_INT
|
||||
}
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
mvPosition.DoState(p);
|
||||
p.Do(projectedPosition);
|
||||
screenPosition.DoState(p);
|
||||
for (int i = 0; i < 3;++i)
|
||||
normal[i].DoState(p);
|
||||
p.DoArray(color, sizeof color);
|
||||
for (int i = 0; i < 8;++i)
|
||||
texCoords[i].DoState(p);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -35,7 +35,6 @@ typedef void (*DecodingFunction)(u32);
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
|
||||
static DecodingFunction currentFunction = NULL;
|
||||
static u32 minCommandSize;
|
||||
static u16 streamSize;
|
||||
@ -46,6 +45,20 @@ static bool inObjectStream;
|
||||
static u8 lastPrimCmd;
|
||||
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(minCommandSize);
|
||||
// Not sure what is wrong with this. Something(s) in here is causing dolphin to crash/hang when loading states saved from another run of dolphin. Doesn't seem too important anyway...
|
||||
//vertexLoader.DoState(p);
|
||||
p.Do(readOpcode);
|
||||
p.Do(inObjectStream);
|
||||
p.Do(lastPrimCmd);
|
||||
p.Do(streamSize);
|
||||
p.Do(streamAddress);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void DecodePrimitiveStream(u32 iBufferSize)
|
||||
{
|
||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||
@ -125,7 +138,9 @@ void DecodeStandard(u32 bufferSize)
|
||||
|
||||
if (Cmd == GX_NOP)
|
||||
return;
|
||||
|
||||
// Causes a SIGBUS error on Android
|
||||
// XXX: Investigate
|
||||
#ifndef ANDROID
|
||||
// check if switching in or out of an object
|
||||
// only used for debuggging
|
||||
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
||||
@ -139,7 +154,7 @@ void DecodeStandard(u32 bufferSize)
|
||||
lastPrimCmd = Cmd & 0x87;
|
||||
DebugUtil::OnObjectBegin();
|
||||
}
|
||||
|
||||
#endif
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define _OPCODEDECODER_H_
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
namespace OpcodeDecoder
|
||||
{
|
||||
@ -57,6 +58,8 @@ namespace OpcodeDecoder
|
||||
bool CommandRunnable(u32 iBufferSize);
|
||||
|
||||
void Run(u32 iBufferSize);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -63,6 +63,28 @@ s32 scissorBottom = 0;
|
||||
Tev tev;
|
||||
RasterBlock rasterBlock;
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
ZSlope.DoState(p);
|
||||
WSlope.DoState(p);
|
||||
for (int i=0;i<2;++i)
|
||||
for (int n=0; n<4; ++n)
|
||||
ColorSlopes[i][n].DoState(p);
|
||||
for (int i=0;i<8;++i)
|
||||
for (int n=0; n<3; ++n)
|
||||
TexSlopes[i][n].DoState(p);
|
||||
p.Do(vertex0X);
|
||||
p.Do(vertex0Y);
|
||||
p.Do(vertexOffsetX);
|
||||
p.Do(vertexOffsetY);
|
||||
p.Do(scissorLeft);
|
||||
p.Do(scissorTop);
|
||||
p.Do(scissorRight);
|
||||
p.Do(scissorBottom);
|
||||
tev.DoState(p);
|
||||
p.Do(rasterBlock);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
tev.Init();
|
||||
@ -126,7 +148,7 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||
if (z < 0 || z > 0x00ffffff)
|
||||
return;
|
||||
|
||||
if (bpmem.zcontrol.zcomploc)
|
||||
if (bpmem.zcontrol.early_ztest && bpmem.zmode.testenable && g_SWVideoConfig.bZComploc)
|
||||
{
|
||||
// TODO: Verify that perf regs are being incremented even if test is disabled
|
||||
if (++SWPixelEngine::pereg.perfZcompInputZcomplocLo == 0)
|
||||
@ -379,7 +401,7 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
|
||||
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
|
||||
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
if (!bpmem.genMode.zfreeze)
|
||||
if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze)
|
||||
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define _RASTERIZER_H_
|
||||
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
namespace Rasterizer
|
||||
{
|
||||
@ -37,6 +38,12 @@ namespace Rasterizer
|
||||
float f0;
|
||||
|
||||
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(dfdx);
|
||||
p.Do(dfdy);
|
||||
p.Do(f0);
|
||||
}
|
||||
};
|
||||
|
||||
struct RasterBlockPixel
|
||||
@ -53,6 +60,8 @@ namespace Rasterizer
|
||||
s32 TextureLod[16];
|
||||
bool TextureLinear[16];
|
||||
};
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,15 @@ CPReg cpreg; // shared between gfx and emulator thread
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(cpreg);
|
||||
p.DoArray(commandBuffer, commandBufferSize);
|
||||
p.Do(readPos);
|
||||
p.Do(writePos);
|
||||
p.Do(et_UpdateInterrupts);
|
||||
p.Do(interruptSet);
|
||||
p.Do(interruptWaiting);
|
||||
|
||||
// Is this right?
|
||||
p.DoArray(g_pVideoData,writePos);
|
||||
}
|
||||
|
||||
// does it matter that there is no synchronization between threads during writes?
|
||||
@ -115,15 +124,15 @@ void RunGpu()
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
{
|
||||
// We are going to do FP math on the main thread so have to save the current state
|
||||
SaveSSEState();
|
||||
LoadDefaultSSEState();
|
||||
FPURoundMode::SaveSIMDState();
|
||||
FPURoundMode::LoadDefaultSIMDState();
|
||||
|
||||
// run the opcode decoder
|
||||
do {
|
||||
RunBuffer();
|
||||
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
|
||||
|
||||
LoadSSEState();
|
||||
FPURoundMode::LoadSIMDState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,8 @@ void DoState(PointerWrap &p)
|
||||
p.Do(pereg);
|
||||
p.Do(g_bSignalTokenInterrupt);
|
||||
p.Do(g_bSignalFinishInterrupt);
|
||||
p.Do(et_SetTokenOnMainThread);
|
||||
p.Do(et_SetFinishOnMainThread);
|
||||
}
|
||||
|
||||
void UpdateInterrupts();
|
||||
|
@ -16,17 +16,23 @@
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
|
||||
#include "../../Plugin_VideoOGL/Src/RasterFont.h"
|
||||
#include "SWRenderer.h"
|
||||
#include "SWStatistics.h"
|
||||
#include "../../Plugin_VideoOGL/Src/RasterFont.h"
|
||||
|
||||
#define VSYNC_ENABLED 0
|
||||
|
||||
static GLuint s_RenderTarget = 0;
|
||||
|
||||
static GLint attr_pos = -1, attr_tex = -1;
|
||||
static GLint uni_tex = -1;
|
||||
static GLuint program;
|
||||
|
||||
// Rasterfont isn't compatible with GLES
|
||||
#ifndef USE_GLES
|
||||
RasterFont* s_pfont = NULL;
|
||||
#endif
|
||||
|
||||
void SWRenderer::Init()
|
||||
{
|
||||
@ -34,84 +40,76 @@ void SWRenderer::Init()
|
||||
|
||||
void SWRenderer::Shutdown()
|
||||
{
|
||||
glDeleteTextures(1, &s_RenderTarget);
|
||||
glDeleteProgram(program);
|
||||
glDeleteTextures(1, &s_RenderTarget);
|
||||
#ifndef USE_GLES
|
||||
delete s_pfont;
|
||||
s_pfont = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
delete s_pfont;
|
||||
s_pfont = 0;
|
||||
void CreateShaders()
|
||||
{
|
||||
static const char *fragShaderText =
|
||||
"varying " PREC " vec2 TexCoordOut;\n"
|
||||
"uniform sampler2D Texture;\n"
|
||||
"void main() {\n"
|
||||
" " PREC " vec4 tmpcolor;\n"
|
||||
" tmpcolor = texture2D(Texture, TexCoordOut);\n"
|
||||
" gl_FragColor = tmpcolor;\n"
|
||||
"}\n";
|
||||
static const char *vertShaderText =
|
||||
"attribute vec4 pos;\n"
|
||||
"attribute vec2 TexCoordIn;\n "
|
||||
"varying vec2 TexCoordOut;\n "
|
||||
"void main() {\n"
|
||||
" gl_Position = pos;\n"
|
||||
" TexCoordOut = TexCoordIn;\n"
|
||||
"}\n";
|
||||
|
||||
program = OpenGL_CompileProgram(vertShaderText, fragShaderText);
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
uni_tex = glGetUniformLocation(program, "Texture");
|
||||
attr_pos = glGetAttribLocation(program, "pos");
|
||||
attr_tex = glGetAttribLocation(program, "TexCoordIn");
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SWRenderer::Prepare()
|
||||
{
|
||||
OpenGL_MakeCurrent();
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
|
||||
glGenTextures(1, &s_RenderTarget);
|
||||
|
||||
// Init extension support.
|
||||
if (glewInit() != GLEW_OK) {
|
||||
ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?");
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle VSync on/off
|
||||
#ifdef _WIN32
|
||||
if (WGLEW_EXT_swap_control)
|
||||
wglSwapIntervalEXT(VSYNC_ENABLED);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)Does your video card support OpenGL 2.x?");
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
if (glXSwapIntervalSGI)
|
||||
glXSwapIntervalSGI(VSYNC_ENABLED);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "no support for SwapInterval (framerate clamped to monitor refresh rate)");
|
||||
CreateShaders();
|
||||
// TODO: Enable for GLES once RasterFont supports GLES
|
||||
#ifndef USE_GLES
|
||||
s_pfont = new RasterFont();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
#endif
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
// used by hw rasterizer if it enables blending and depth test
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClearDepth(1.0f);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
//glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
s_pfont = new RasterFont();
|
||||
|
||||
// legacy multitexturing: select texture channel only.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
glGenTextures(1, &s_RenderTarget);
|
||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color)
|
||||
{
|
||||
int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
||||
int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
||||
#ifndef USE_GLES
|
||||
int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
|
||||
int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
|
||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
||||
s_pfont->printMultilineText(pstr,
|
||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||
0, nBackbufferWidth, nBackbufferHeight);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SWRenderer::DrawDebugText()
|
||||
{
|
||||
char debugtext_buffer[8192];
|
||||
char debugtext_buffer[8192];
|
||||
char *p = debugtext_buffer;
|
||||
p[0] = 0;
|
||||
|
||||
@ -139,48 +137,57 @@ void SWRenderer::DrawDebugText()
|
||||
|
||||
void SWRenderer::DrawTexture(u8 *texture, int width, int height)
|
||||
{
|
||||
GLsizei glWidth = (GLsizei)OpenGL_GetBackbufferWidth();
|
||||
GLsizei glHeight = (GLsizei)OpenGL_GetBackbufferHeight();
|
||||
GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth();
|
||||
GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight();
|
||||
|
||||
// Update GLViewPort
|
||||
glViewport(0, 0, glWidth, glHeight);
|
||||
glScissor(0, 0, glWidth, glHeight);
|
||||
glScissor(0, 0, glWidth, glHeight);
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, s_RenderTarget);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glUseProgram(program);
|
||||
static const GLfloat verts[4][2] = {
|
||||
{ -1, -1}, // Left top
|
||||
{ -1, 1}, // left bottom
|
||||
{ 1, 1}, // right bottom
|
||||
{ 1, -1} // right top
|
||||
};
|
||||
static const GLfloat texverts[4][2] = {
|
||||
{0, 1},
|
||||
{0, 0},
|
||||
{1, 0},
|
||||
{1, 1}
|
||||
};
|
||||
|
||||
glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts);
|
||||
glEnableVertexAttribArray(attr_pos);
|
||||
glEnableVertexAttribArray(attr_tex);
|
||||
glUniform1i(uni_tex, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableVertexAttribArray(attr_pos);
|
||||
glDisableVertexAttribArray(attr_tex);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
GLfloat u_max = (GLfloat)width;
|
||||
GLfloat v_max = (GLfloat)glHeight;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, v_max); glVertex2f(-1, -1);
|
||||
glTexCoord2f(0, 0); glVertex2f(-1, 1);
|
||||
glTexCoord2f(u_max, 0); glVertex2f( 1, 1);
|
||||
glTexCoord2f(u_max, v_max); glVertex2f( 1, -1);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
}
|
||||
|
||||
void SWRenderer::SwapBuffer()
|
||||
{
|
||||
DrawDebugText();
|
||||
DrawDebugText();
|
||||
|
||||
glFlush();
|
||||
glFlush();
|
||||
|
||||
OpenGL_SwapBuffers();
|
||||
GLInterface->Swap();
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
swstats.ResetFrame();
|
||||
swstats.ResetFrame();
|
||||
|
||||
// Clear framebuffer
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClearDepth(1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
@ -72,27 +72,27 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
|
||||
|
||||
//TexMtx
|
||||
const int tmDesc[8] = {
|
||||
const u32 tmDesc[8] = {
|
||||
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
|
||||
g_VtxDesc.Tex4MatIdx, g_VtxDesc.Tex5MatIdx, g_VtxDesc.Tex6MatIdx, g_VtxDesc.Tex7MatIdx
|
||||
};
|
||||
// Colors
|
||||
const int colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
|
||||
const u32 colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
|
||||
colElements[0] = m_CurrentVat->g0.Color0Elements;
|
||||
colElements[1] = m_CurrentVat->g0.Color1Elements;
|
||||
const int colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
||||
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
||||
// TextureCoord
|
||||
const int tcDesc[8] = {
|
||||
const u32 tcDesc[8] = {
|
||||
g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord,
|
||||
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const int)((g_VtxDesc.Hex >> 31) & 3)
|
||||
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
|
||||
};
|
||||
const int tcElements[8] = {
|
||||
const u32 tcElements[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
|
||||
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
|
||||
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
|
||||
};
|
||||
|
||||
const int tcFormat[8] = {
|
||||
const u32 tcFormat[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
|
||||
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
|
||||
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
|
||||
@ -328,4 +328,15 @@ void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData
|
||||
vertexLoader->m_texCoordLoader[index]();
|
||||
}
|
||||
|
||||
|
||||
void SWVertexLoader::DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders);
|
||||
p.Do(m_VertexSize);
|
||||
p.Do(*m_CurrentVat);
|
||||
p.Do(m_positionLoader);
|
||||
p.Do(m_normalLoader);
|
||||
p.DoArray(m_colorLoader, sizeof m_colorLoader);
|
||||
p.Do(m_NumAttributeLoaders);
|
||||
m_SetupUnit->DoState(p);
|
||||
p.Do(m_TexGenSpecialCase);
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "CPMemLoader.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
class SetupUnit;
|
||||
|
||||
@ -69,7 +70,7 @@ public:
|
||||
u32 GetVertexSize() { return m_VertexSize; }
|
||||
|
||||
void LoadVertex();
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -35,6 +35,9 @@ SWVideoConfig::SWVideoConfig()
|
||||
bDumpObjects = false;
|
||||
bDumpFrames = false;
|
||||
|
||||
bZComploc = true;
|
||||
bZFreeze = true;
|
||||
|
||||
bDumpTevStages = false;
|
||||
bDumpTevTextureFetches = false;
|
||||
|
||||
@ -52,6 +55,8 @@ void SWVideoConfig::Load(const char* ini_file)
|
||||
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
|
||||
|
||||
iniFile.Get("Rendering", "HwRasterizer", &bHwRasterizer, false);
|
||||
iniFile.Get("Rendering", "ZComploc", &bZComploc, true);
|
||||
iniFile.Get("Rendering", "ZFreeze", &bZFreeze, true);
|
||||
|
||||
iniFile.Get("Info", "ShowStats", &bShowStats, false);
|
||||
|
||||
@ -74,6 +79,8 @@ void SWVideoConfig::Save(const char* ini_file)
|
||||
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
|
||||
|
||||
iniFile.Set("Rendering", "HwRasterizer", bHwRasterizer);
|
||||
iniFile.Set("Rendering", "ZComploc", &bZComploc);
|
||||
iniFile.Set("Rendering", "ZFreeze", &bZFreeze);
|
||||
|
||||
iniFile.Set("Info", "ShowStats", bShowStats);
|
||||
|
||||
|
@ -36,6 +36,10 @@ struct SWVideoConfig : NonCopyable
|
||||
|
||||
bool bHwRasterizer;
|
||||
|
||||
// Emulation features
|
||||
bool bZComploc;
|
||||
bool bZFreeze;
|
||||
|
||||
bool bShowStats;
|
||||
|
||||
bool bDumpTextures;
|
||||
|
@ -39,6 +39,11 @@
|
||||
#include "FileUtil.h"
|
||||
#include "VideoBackend.h"
|
||||
#include "Core.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "SWVertexLoader.h"
|
||||
#include "SWStatistics.h"
|
||||
|
||||
#define VSYNC_ENABLED 0
|
||||
|
||||
namespace SW
|
||||
{
|
||||
@ -68,31 +73,61 @@ void VideoSoftware::ShowConfig(void *_hParent)
|
||||
|
||||
bool VideoSoftware::Initialize(void *&window_handle)
|
||||
{
|
||||
g_SWVideoConfig.Load((File::GetUserPath(D_CONFIG_IDX) + "gfx_software.ini").c_str());
|
||||
g_SWVideoConfig.Load((File::GetUserPath(D_CONFIG_IDX) + "gfx_software.ini").c_str());
|
||||
InitInterface();
|
||||
|
||||
if (!OpenGL_Create(window_handle))
|
||||
if (!GLInterface->Create(window_handle))
|
||||
{
|
||||
INFO_LOG(VIDEO, "%s", "SWRenderer::Create failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
InitBPMemory();
|
||||
InitXFMemory();
|
||||
SWCommandProcessor::Init();
|
||||
SWPixelEngine::Init();
|
||||
OpcodeDecoder::Init();
|
||||
Clipper::Init();
|
||||
Rasterizer::Init();
|
||||
HwRasterizer::Init();
|
||||
SWRenderer::Init();
|
||||
DebugUtil::Init();
|
||||
InitBPMemory();
|
||||
InitXFMemory();
|
||||
SWCommandProcessor::Init();
|
||||
SWPixelEngine::Init();
|
||||
OpcodeDecoder::Init();
|
||||
Clipper::Init();
|
||||
Rasterizer::Init();
|
||||
HwRasterizer::Init();
|
||||
SWRenderer::Init();
|
||||
DebugUtil::Init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VideoSoftware::DoState(PointerWrap&)
|
||||
void VideoSoftware::DoState(PointerWrap& p)
|
||||
{
|
||||
// NYI
|
||||
bool software = true;
|
||||
p.Do(software);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ && software == false)
|
||||
// change mode to abort load of incompatible save state.
|
||||
p.SetMode(PointerWrap::MODE_VERIFY);
|
||||
|
||||
// TODO: incomplete?
|
||||
SWCommandProcessor::DoState(p);
|
||||
SWPixelEngine::DoState(p);
|
||||
EfbInterface::DoState(p);
|
||||
OpcodeDecoder::DoState(p);
|
||||
Clipper::DoState(p);
|
||||
p.Do(swxfregs);
|
||||
p.Do(bpmem);
|
||||
p.Do(swstats);
|
||||
|
||||
// CP Memory
|
||||
p.DoArray(arraybases, 16);
|
||||
p.DoArray(arraystrides, 16);
|
||||
p.Do(MatrixIndexA);
|
||||
p.Do(MatrixIndexB);
|
||||
p.Do(g_VtxDesc.Hex);
|
||||
p.DoArray(g_VtxAttr, 8);
|
||||
p.DoMarker("CP Memory");
|
||||
|
||||
}
|
||||
|
||||
void VideoSoftware::CheckInvalidState()
|
||||
{
|
||||
// there is no state to invalidate
|
||||
}
|
||||
|
||||
void VideoSoftware::PauseAndLock(bool doLock, bool unpauseOnUnlock)
|
||||
@ -124,16 +159,30 @@ void VideoSoftware::EmuStateChange(EMUSTATE_CHANGE newState)
|
||||
|
||||
void VideoSoftware::Shutdown()
|
||||
{
|
||||
HwRasterizer::Shutdown();
|
||||
SWRenderer::Shutdown();
|
||||
OpenGL_Shutdown();
|
||||
GLInterface->Shutdown();
|
||||
}
|
||||
|
||||
// This is called after Video_Initialize() from the Core
|
||||
void VideoSoftware::Video_Prepare()
|
||||
{
|
||||
SWRenderer::Prepare();
|
||||
{
|
||||
GLInterface->MakeCurrent();
|
||||
// Init extension support.
|
||||
// Required for WGL SwapInterval
|
||||
#ifndef USE_GLES
|
||||
if (glewInit() != GLEW_OK) {
|
||||
ERROR_LOG(VIDEO, "glewInit() failed!Does your video card support OpenGL 2.x?");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Handle VSync on/off
|
||||
GLInterface->SwapInterval(VSYNC_ENABLED);
|
||||
|
||||
INFO_LOG(VIDEO, "Video backend initialized.");
|
||||
HwRasterizer::Prepare();
|
||||
SWRenderer::Prepare();
|
||||
|
||||
INFO_LOG(VIDEO, "Video backend initialized.");
|
||||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
@ -279,20 +328,7 @@ writeFn32 VideoSoftware::Video_PEWrite32()
|
||||
// Draw messages on top of the screen
|
||||
unsigned int VideoSoftware::PeekMessages()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// TODO: peekmessage
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return GLInterface->PeekMessages();
|
||||
}
|
||||
|
||||
// Show the current FPS
|
||||
@ -300,7 +336,7 @@ void VideoSoftware::UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
char temp[100];
|
||||
snprintf(temp, sizeof temp, "%s | Software | %s", scm_rev_str, text);
|
||||
OpenGL_SetWindowText(temp);
|
||||
GLInterface->UpdateFPSDisplay(temp);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,13 +25,13 @@
|
||||
|
||||
void SetupUnit::Init(u8 primitiveType)
|
||||
{
|
||||
m_PrimType = primitiveType;
|
||||
m_PrimType = primitiveType;
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertPointer[0] = &m_Vertices[0];
|
||||
m_VertPointer[1] = &m_Vertices[1];
|
||||
m_VertPointer[2] = &m_Vertices[2];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
m_VertexCounter = 0;
|
||||
m_VertPointer[0] = &m_Vertices[0];
|
||||
m_VertPointer[1] = &m_Vertices[1];
|
||||
m_VertPointer[2] = &m_Vertices[2];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupVertex()
|
||||
@ -169,3 +169,21 @@ void SetupUnit::SetupLineStrip()
|
||||
|
||||
void SetupUnit::SetupPoint()
|
||||
{}
|
||||
|
||||
void SetupUnit::DoState(PointerWrap &p)
|
||||
{
|
||||
// TODO: some or all of this is making the save states stop working once dolphin is closed...sometimes (usually)
|
||||
// I have no idea what specifically is wrong, or if this is even important. Disabling it doesn't seem to make any noticible difference...
|
||||
/* p.Do(m_PrimType);
|
||||
p.Do(m_VertexCounter);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
m_Vertices[i].DoState(p);
|
||||
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
{
|
||||
m_VertPointer[0] = &m_Vertices[0];
|
||||
m_VertPointer[1] = &m_Vertices[1];
|
||||
m_VertPointer[2] = &m_Vertices[2];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}*/
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "NativeVertexFormat.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
class SetupUnit
|
||||
{
|
||||
@ -45,6 +46,7 @@ public:
|
||||
OutputVertexData* GetVertex() { return m_VertWritePointer; }
|
||||
|
||||
void SetupVertex();
|
||||
void DoState(PointerWrap &p);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -432,12 +432,12 @@ static bool AlphaCompare(int alpha, int ref, int comp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool AlphaTest(int alpha)
|
||||
static bool TevAlphaTest(int alpha)
|
||||
{
|
||||
bool comp0 = AlphaCompare(alpha, bpmem.alphaFunc.ref0, bpmem.alphaFunc.comp0);
|
||||
bool comp1 = AlphaCompare(alpha, bpmem.alphaFunc.ref1, bpmem.alphaFunc.comp1);
|
||||
bool comp0 = AlphaCompare(alpha, bpmem.alpha_test.ref0, bpmem.alpha_test.comp0);
|
||||
bool comp1 = AlphaCompare(alpha, bpmem.alpha_test.ref1, bpmem.alpha_test.comp1);
|
||||
|
||||
switch (bpmem.alphaFunc.logic) {
|
||||
switch (bpmem.alpha_test.logic) {
|
||||
case 0: return comp0 && comp1; // and
|
||||
case 1: return comp0 || comp1; // or
|
||||
case 2: return comp0 ^ comp1; // xor
|
||||
@ -701,7 +701,7 @@ void Tev::Draw()
|
||||
// convert to 8 bits per component
|
||||
u8 output[4] = {(u8)Reg[0][ALP_C], (u8)Reg[0][BLU_C], (u8)Reg[0][GRN_C], (u8)Reg[0][RED_C]};
|
||||
|
||||
if (!AlphaTest(output[ALP_C]))
|
||||
if (!TevAlphaTest(output[ALP_C]))
|
||||
return;
|
||||
|
||||
// z texture
|
||||
@ -785,15 +785,16 @@ void Tev::Draw()
|
||||
output[BLU_C] = (output[BLU_C] * invFog + fogInt * bpmem.fog.color.b) >> 8;
|
||||
}
|
||||
|
||||
if (!bpmem.zcontrol.zcomploc)
|
||||
bool late_ztest = !bpmem.zcontrol.early_ztest || !g_SWVideoConfig.bZComploc;
|
||||
if (late_ztest && bpmem.zmode.testenable)
|
||||
{
|
||||
// TODO: Check against hw if these values get incremented even if depth testing is disabled
|
||||
if (++SWPixelEngine::pereg.perfZcompInputLo == 0)
|
||||
SWPixelEngine::pereg.perfZcompInputHi++;
|
||||
if (bpmem.zmode.testenable)
|
||||
{
|
||||
if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EfbInterface::ZCompare(Position[0], Position[1], Position[2]))
|
||||
return;
|
||||
|
||||
if (++SWPixelEngine::pereg.perfZcompOutputLo == 0)
|
||||
SWPixelEngine::pereg.perfZcompOutputHi++;
|
||||
}
|
||||
@ -837,3 +838,31 @@ void Tev::SetRegColor(int reg, int comp, bool konst, s16 color)
|
||||
Reg[reg][comp] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void Tev::DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoArray(Reg, sizeof(Reg));
|
||||
|
||||
p.DoArray(KonstantColors, sizeof(KonstantColors));
|
||||
p.DoArray(TexColor,4);
|
||||
p.DoArray(RasColor,4);
|
||||
p.DoArray(StageKonst,4);
|
||||
p.DoArray(Zero16,4);
|
||||
|
||||
p.DoArray(FixedConstants,9);
|
||||
p.Do(AlphaBump);
|
||||
p.DoArray(IndirectTex, sizeof(IndirectTex));
|
||||
p.Do(TexCoord);
|
||||
|
||||
p.DoArray(m_BiasLUT,4);
|
||||
p.DoArray(m_ScaleLShiftLUT,4);
|
||||
p.DoArray(m_ScaleRShiftLUT,4);
|
||||
|
||||
p.DoArray(Position,3);
|
||||
p.DoArray(Color, sizeof(Color));
|
||||
p.DoArray(Uv, 8);
|
||||
p.DoArray(IndirectLod,4);
|
||||
p.DoArray(IndirectLinear,4);
|
||||
p.DoArray(TextureLod,16);
|
||||
p.DoArray(TextureLinear,16);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define _TEV_H_
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
class Tev
|
||||
{
|
||||
@ -96,6 +97,8 @@ public:
|
||||
void SetRegColor(int reg, int comp, bool konst, s16 color);
|
||||
|
||||
enum { ALP_C, BLU_C, GRN_C, RED_C };
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -120,8 +120,18 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
||||
|
||||
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
||||
u8 *imageSrc = Memory::GetPointer(imageBase);
|
||||
u8 *imageSrc, *imageSrcOdd = NULL;
|
||||
if (texUnit.texImage1[subTexmap].image_type)
|
||||
{
|
||||
imageSrc = &texMem[texUnit.texImage1[subTexmap].tmem_even * TMEM_LINE_SIZE];
|
||||
if (ti0.format == GX_TF_RGBA8)
|
||||
imageSrcOdd = &texMem[texUnit.texImage2[subTexmap].tmem_odd * TMEM_LINE_SIZE];
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
||||
imageSrc = Memory::GetPointer(imageBase);
|
||||
}
|
||||
|
||||
int imageWidth = ti0.width;
|
||||
int imageHeight = ti0.height;
|
||||
@ -182,17 +192,34 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
|
||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
{
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
|
||||
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||
}
|
||||
else
|
||||
{
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
|
||||
SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageSPlus1, imageT, imageWidth);
|
||||
AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
|
||||
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageS, imageTPlus1, imageWidth);
|
||||
AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
|
||||
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sampledTex, imageSrc, imageSrcOdd, imageSPlus1, imageTPlus1, imageWidth);
|
||||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||
}
|
||||
|
||||
sample[0] = (u8)(texel[0] >> 14);
|
||||
sample[1] = (u8)(texel[1] >> 14);
|
||||
@ -209,7 +236,10 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
else
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "ChunkFile.h"
|
||||
|
||||
class Vec3
|
||||
{
|
||||
@ -111,6 +112,12 @@ public:
|
||||
{
|
||||
memset((void *)this,0,sizeof(float)*3);
|
||||
}
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(x);
|
||||
p.Do(y);
|
||||
p.Do(z);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -52,6 +52,9 @@ class VideoSoftware : public VideoBackend
|
||||
|
||||
void PauseAndLock(bool doLock, bool unpauseOnUnlock=true);
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
public:
|
||||
void CheckInvalidState();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,8 +21,6 @@
|
||||
#include "FileUtil.h"
|
||||
#include "Core.h"
|
||||
|
||||
#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s)
|
||||
|
||||
template <typename T>
|
||||
IntegerSetting<T>::IntegerSetting(wxWindow* parent, const wxString& label, T& setting, int minVal, int maxVal, long style) :
|
||||
wxSpinCtrl(parent, -1, label, wxDefaultPosition, wxDefaultSize, style),
|
||||
@ -30,7 +28,7 @@ IntegerSetting<T>::IntegerSetting(wxWindow* parent, const wxString& label, T& se
|
||||
{
|
||||
SetRange(minVal, maxVal);
|
||||
SetValue(m_setting);
|
||||
_connect_macro_(this, IntegerSetting::UpdateValue, wxEVT_COMMAND_SPINCTRL_UPDATED, this);
|
||||
Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &IntegerSetting::UpdateValue, this);
|
||||
}
|
||||
|
||||
|
||||
@ -70,7 +68,7 @@ VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title,
|
||||
|
||||
// TODO: How to get the translated plugin name?
|
||||
choice_backend->SetStringSelection(wxString::FromAscii(g_video_backend->GetName().c_str()));
|
||||
_connect_macro_(choice_backend, VideoConfigDialog::Event_Backend, wxEVT_COMMAND_CHOICE_SELECTED, this);
|
||||
choice_backend->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &VideoConfigDialog::Event_Backend, this);
|
||||
|
||||
szr_rendering->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
szr_rendering->Add(choice_backend, 1, 0, 0);
|
||||
|
Reference in New Issue
Block a user