1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-24 21:39:35 +00:00

Add Drawer class to replace OGLRender WIP

This commit is contained in:
Sergey Lipskiy 2017-01-10 22:22:32 +07:00
parent 4cbb2d0189
commit dd57479838
22 changed files with 1381 additions and 161 deletions

View File

@ -348,6 +348,9 @@
<ClCompile Include="..\..\src\Performance.cpp" />
<ClCompile Include="..\..\src\PostProcessor.cpp" />
<ClCompile Include="..\..\src\RDP.CPP" />
<ClCompile Include="..\..\src\Drawer.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug_mupenplus|Win32'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\RSP.cpp" />
<ClCompile Include="..\..\src\ShaderUtils.cpp" />
<ClCompile Include="..\..\src\SoftwareRender.cpp" />
@ -471,6 +474,7 @@
<ClInclude Include="..\..\src\PluginAPI.h" />
<ClInclude Include="..\..\src\PostProcessor.h" />
<ClInclude Include="..\..\src\RDP.h" />
<ClInclude Include="..\..\src\Drawer.h" />
<ClInclude Include="..\..\src\RSP.h" />
<ClInclude Include="..\..\src\ShaderUtils.h" />
<ClInclude Include="..\..\src\SoftwareRender.h" />

View File

@ -341,6 +341,9 @@
<ClCompile Include="..\..\src\Graphics\OpenGLContext\mupen64plus\mupen64plus_DisplayWindow.cpp">
<Filter>Source Files\Graphics\OpenGL\mupen64plus</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Drawer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\3DMath.h">
@ -622,5 +625,8 @@
<ClInclude Include="..\..\src\DisplayWindow.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Drawer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -14,60 +14,60 @@
static int saRGBExpanded[] =
{
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
SHADE, ENVIRONMENT, ONE, NOISE,
ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO
G_GCI_COMBINED, G_GCI_TEXEL0, G_GCI_TEXEL1, G_GCI_PRIMITIVE,
G_GCI_SHADE, G_GCI_ENVIRONMENT, G_GCI_ONE, G_GCI_NOISE,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO
};
static int sbRGBExpanded[] =
{
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
SHADE, ENVIRONMENT, CENTER, K4,
ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO
G_GCI_COMBINED, G_GCI_TEXEL0, G_GCI_TEXEL1, G_GCI_PRIMITIVE,
G_GCI_SHADE, G_GCI_ENVIRONMENT, G_GCI_CENTER, G_GCI_K4,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO
};
static int mRGBExpanded[] =
{
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
SHADE, ENVIRONMENT, SCALE, COMBINED_ALPHA,
TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA, SHADE_ALPHA,
ENV_ALPHA, LOD_FRACTION, PRIM_LOD_FRAC, K5,
ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO
G_GCI_COMBINED, G_GCI_TEXEL0, G_GCI_TEXEL1, G_GCI_PRIMITIVE,
G_GCI_SHADE, G_GCI_ENVIRONMENT, G_GCI_SCALE, G_GCI_COMBINED_ALPHA,
G_GCI_TEXEL0_ALPHA, G_GCI_TEXEL1_ALPHA, G_GCI_PRIMITIVE_ALPHA, G_GCI_SHADE_ALPHA,
G_GCI_ENV_ALPHA, G_GCI_LOD_FRACTION, G_GCI_PRIM_LOD_FRAC, G_GCI_K5,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO,
G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO, G_GCI_ZERO
};
static int aRGBExpanded[] =
{
COMBINED, TEXEL0, TEXEL1, PRIMITIVE,
SHADE, ENVIRONMENT, ONE, ZERO
G_GCI_COMBINED, G_GCI_TEXEL0, G_GCI_TEXEL1, G_GCI_PRIMITIVE,
G_GCI_SHADE, G_GCI_ENVIRONMENT, G_GCI_ONE, G_GCI_ZERO
};
static int saAExpanded[] =
{
COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
G_GCI_COMBINED, G_GCI_TEXEL0_ALPHA, G_GCI_TEXEL1_ALPHA, G_GCI_PRIMITIVE_ALPHA,
G_GCI_SHADE_ALPHA, G_GCI_ENV_ALPHA, G_GCI_ONE, G_GCI_ZERO
};
static int sbAExpanded[] =
{
COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
G_GCI_COMBINED, G_GCI_TEXEL0_ALPHA, G_GCI_TEXEL1_ALPHA, G_GCI_PRIMITIVE_ALPHA,
G_GCI_SHADE_ALPHA, G_GCI_ENV_ALPHA, G_GCI_ONE, G_GCI_ZERO
};
static int mAExpanded[] =
{
LOD_FRACTION, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
SHADE_ALPHA, ENV_ALPHA, PRIM_LOD_FRAC, ZERO,
G_GCI_LOD_FRACTION, G_GCI_TEXEL0_ALPHA, G_GCI_TEXEL1_ALPHA, G_GCI_PRIMITIVE_ALPHA,
G_GCI_SHADE_ALPHA, G_GCI_ENV_ALPHA, G_GCI_PRIM_LOD_FRAC, G_GCI_ZERO,
};
static int aAExpanded[] =
{
COMBINED, TEXEL0_ALPHA, TEXEL1_ALPHA, PRIMITIVE_ALPHA,
SHADE_ALPHA, ENV_ALPHA, ONE, ZERO
G_GCI_COMBINED, G_GCI_TEXEL0_ALPHA, G_GCI_TEXEL1_ALPHA, G_GCI_PRIMITIVE_ALPHA,
G_GCI_SHADE_ALPHA, G_GCI_ENV_ALPHA, G_GCI_ONE, G_GCI_ZERO
};
void Combiner_Init() {
@ -142,10 +142,10 @@ void SimplifyCycle( CombineCycle *cc, CombinerStage *stage )
stage->numOps = 1;
// If we're just subtracting zero, skip it
if (cc->sb != ZERO) {
if (cc->sb != G_GCI_ZERO) {
// Subtracting a number from itself is zero
if (cc->sb == stage->op[0].param1)
stage->op[0].param1 = ZERO;
stage->op[0].param1 = G_GCI_ZERO;
else {
stage->op[1].op = SUB;
stage->op[1].param1 = cc->sb;
@ -154,15 +154,15 @@ void SimplifyCycle( CombineCycle *cc, CombinerStage *stage )
}
// If we either subtracted, or didn't load a zero
if ((stage->numOps > 1) || (stage->op[0].param1 != ZERO)) {
if ((stage->numOps > 1) || (stage->op[0].param1 != G_GCI_ZERO)) {
// Multiplying by zero is zero
if (cc->m == ZERO) {
if (cc->m == G_GCI_ZERO) {
stage->numOps = 1;
stage->op[0].op = LOAD;
stage->op[0].param1 = ZERO;
stage->op[0].param1 = G_GCI_ZERO;
} else {
// Multiplying by one, so just do a load
if ((stage->numOps == 1) && (stage->op[0].param1 == ONE))
if ((stage->numOps == 1) && (stage->op[0].param1 == G_GCI_ONE))
stage->op[0].param1 = cc->m;
else {
stage->op[stage->numOps].op = MUL;
@ -173,9 +173,9 @@ void SimplifyCycle( CombineCycle *cc, CombinerStage *stage )
}
// Don't bother adding zero
if (cc->a != ZERO) {
if (cc->a != G_GCI_ZERO) {
// If all we have so far is zero, then load this instead
if ((stage->numOps == 1) && (stage->op[0].param1 == ZERO))
if ((stage->numOps == 1) && (stage->op[0].param1 == G_GCI_ZERO))
stage->op[0].param1 = cc->a;
else {
stage->op[stage->numOps].op = ADD;
@ -313,6 +313,19 @@ void CombinerInfo::setPolygonMode(OGLRender::RENDER_STATE _renderState)
}
}
void CombinerInfo::setPolygonMode(DrawingState _drawingState)
{
switch (_drawingState) {
case DrawingState::Rect:
case DrawingState::TexRect:
m_rectMode = true;
break;
default:
m_rectMode = false;
break;
}
}
void CombinerInfo::_saveShadersStorage() const
{
if (m_shadersLoaded >= m_combiners.size())

View File

@ -6,6 +6,7 @@
#include "GLideN64.h"
#include "OpenGL.h"
#include "Drawer.h"
#include "gDP.h"
#include "CombinerKey.h"
#include "Graphics/CombinerProgram.h"
@ -68,29 +69,28 @@
#define INTER 4
// Internal generalized combiner inputs
#define COMBINED 0
#define TEXEL0 1
#define TEXEL1 2
#define PRIMITIVE 3
#define SHADE 4
#define ENVIRONMENT 5
#define CENTER 6
#define SCALE 7
#define COMBINED_ALPHA 8
#define TEXEL0_ALPHA 9
#define TEXEL1_ALPHA 10
#define PRIMITIVE_ALPHA 11
#define SHADE_ALPHA 12
#define ENV_ALPHA 13
#define LOD_FRACTION 14
#define PRIM_LOD_FRAC 15
#define NOISE 16
#define K4 17
#define K5 18
#define ONE 19
#define ZERO 20
#define LIGHT 21
#define HW_LIGHT 22
#define G_GCI_COMBINED 0
#define G_GCI_TEXEL0 1
#define G_GCI_TEXEL1 2
#define G_GCI_PRIMITIVE 3
#define G_GCI_SHADE 4
#define G_GCI_ENVIRONMENT 5
#define G_GCI_CENTER 6
#define G_GCI_SCALE 7
#define G_GCI_COMBINED_ALPHA 8
#define G_GCI_TEXEL0_ALPHA 9
#define G_GCI_TEXEL1_ALPHA 10
#define G_GCI_PRIMITIVE_ALPHA 11
#define G_GCI_SHADE_ALPHA 12
#define G_GCI_ENV_ALPHA 13
#define G_GCI_LOD_FRACTION 14
#define G_GCI_PRIM_LOD_FRAC 15
#define G_GCI_NOISE 16
#define G_GCI_K4 17
#define G_GCI_K5 18
#define G_GCI_ONE 19
#define G_GCI_ZERO 20
#define G_GCI_HW_LIGHT 22
struct CombinerOp
{
@ -137,6 +137,7 @@ public:
static CombinerInfo & get();
void setPolygonMode(OGLRender::RENDER_STATE _renderState);
void setPolygonMode(DrawingState _drawingState);
bool isRectMode() const { return m_rectMode; }
private:

656
src/Drawer.cpp Normal file
View File

@ -0,0 +1,656 @@
#include <algorithm>
#include <assert.h>
#include "Graphics/Context.h"
#include "Graphics/Parameters.h"
#include "Config.h"
#include "RSP.h"
#include "VI.h"
#include "FrameBuffer.h"
#include "DepthBuffer.h"
#include "DisplayWindow.h"
#include "SoftwareRender.h"
#include "Drawer.h"
using namespace graphics;
void Drawer::addTriangle(int _v0, int _v1, int _v2)
{
const u32 firstIndex = triangles.num;
triangles.elements[triangles.num++] = _v0;
triangles.elements[triangles.num++] = _v1;
triangles.elements[triangles.num++] = _v2;
triangles.maxElement = std::max(triangles.maxElement, _v0);
triangles.maxElement = std::max(triangles.maxElement, _v1);
triangles.maxElement = std::max(triangles.maxElement, _v2);
m_modifyVertices |= triangles.vertices[_v0].modify |
triangles.vertices[_v1].modify |
triangles.vertices[_v2].modify;
if ((gSP.geometryMode & G_LIGHTING) == 0) {
if ((gSP.geometryMode & G_SHADE) == 0) {
// Prim shading
for (u32 i = firstIndex; i < triangles.num; ++i) {
SPVertex & vtx = triangles.vertices[triangles.elements[i]];
vtx.flat_r = gDP.primColor.r;
vtx.flat_g = gDP.primColor.g;
vtx.flat_b = gDP.primColor.b;
vtx.flat_a = gDP.primColor.a;
}
}
else if ((gSP.geometryMode & G_SHADING_SMOOTH) == 0) {
// Flat shading
SPVertex & vtx0 = triangles.vertices[triangles.elements[firstIndex + ((RSP.w1 >> 24) & 3)]];
for (u32 i = firstIndex; i < triangles.num; ++i) {
SPVertex & vtx = triangles.vertices[triangles.elements[i]];
vtx.r = vtx.flat_r = vtx0.r;
vtx.g = vtx.flat_g = vtx0.g;
vtx.b = vtx.flat_b = vtx0.b;
vtx.a = vtx.flat_a = vtx0.a;
}
}
}
if (gDP.otherMode.depthSource == G_ZS_PRIM) {
for (u32 i = firstIndex; i < triangles.num; ++i) {
SPVertex & vtx = triangles.vertices[triangles.elements[i]];
vtx.z = gDP.primDepth.z * vtx.w;
}
}
if (!gfxContext.isSupported(SpecialFeatures::NearPlaneClipping)) {
if (GBI.isNoN() && gDP.otherMode.depthCompare == 0 && gDP.otherMode.depthUpdate == 0) {
for (u32 i = firstIndex; i < triangles.num; ++i) {
SPVertex & vtx = triangles.vertices[triangles.elements[i]];
vtx.z = 0.0f;
}
}
}
}
void Drawer::_updateCullFace() const
{
if (gSP.geometryMode & G_CULL_BOTH) {
gfxContext.enable(enable::CULL_FACE, true);
if (gSP.geometryMode & G_CULL_BACK)
gfxContext.cullFace(cullMode::BACK);
else
gfxContext.cullFace(cullMode::FRONT);
} else
gfxContext.enable(enable::CULL_FACE, false);
}
void Drawer::_updateDepthUpdate() const
{
gfxContext.enableDepthWrite(gDP.otherMode.depthUpdate != 0);
}
void Drawer::_updateDepthCompare() const
{
if (config.frameBufferEmulation.N64DepthCompare != 0) {
gfxContext.enable(enable::DEPTH_TEST, false);
gfxContext.enableDepthWrite(false);
}
else if ((gDP.changed & (CHANGED_RENDERMODE | CHANGED_CYCLETYPE)) != 0) {
if (((gSP.geometryMode & G_ZBUFFER) || gDP.otherMode.depthSource == G_ZS_PRIM) && gDP.otherMode.cycleType <= G_CYC_2CYCLE) {
if (gDP.otherMode.depthCompare != 0) {
switch (gDP.otherMode.depthMode) {
case ZMODE_INTER:
gfxContext.enable(enable::POLYGON_OFFSET_FILL, false);
gfxContext.setDepthCompare(compare::LEQUAL);
break;
case ZMODE_OPA:
case ZMODE_XLU:
// Max || Infront;
gfxContext.enable(enable::POLYGON_OFFSET_FILL, false);
if (gDP.otherMode.depthSource == G_ZS_PRIM && gDP.primDepth.z == 1.0f)
// Max
gfxContext.setDepthCompare(compare::LEQUAL);
else
// Infront
gfxContext.setDepthCompare(compare::LESS);
break;
case ZMODE_DEC:
gfxContext.enable(enable::POLYGON_OFFSET_FILL, true);
gfxContext.setDepthCompare(compare::LEQUAL);
break;
}
} else {
gfxContext.enable(enable::POLYGON_OFFSET_FILL, false);
gfxContext.setDepthCompare(compare::ALWAYS);
}
_updateDepthUpdate();
gfxContext.enable(enable::DEPTH_TEST, true);
if (!GBI.isNoN())
gfxContext.enable(enable::DEPTH_CLAMP, false);
} else {
gfxContext.enable(enable::DEPTH_TEST, false);
if (!GBI.isNoN())
gfxContext.enable(enable::DEPTH_CLAMP, true);
}
}
}
inline
bool _needAdjustCoordinate(DisplayWindow & _wnd)
{
return _wnd.isAdjustScreen() &&
gSP.viewport.width < gDP.colorImage.width &&
u32(gSP.viewport.width + gSP.viewport.x * 2.0f) != gDP.colorImage.width &&
gDP.colorImage.width > VI.width * 98 / 100;
}
inline
void _adjustScissorX(f32 & _X0, f32 & _X1, float _scale)
{
const float halfX = gDP.colorImage.width / 2.0f;
_X0 = (_X0 - halfX) * _scale + halfX;
_X1 = (_X1 - halfX) * _scale + halfX;
}
void Drawer::updateScissor(FrameBuffer * _pBuffer) const
{
DisplayWindow & wnd = DisplayWindow::get();
f32 scaleX, scaleY;
u32 heightOffset, screenHeight;
if (_pBuffer == nullptr) {
scaleX = wnd.getScaleX();
scaleY = wnd.getScaleY();
heightOffset = wnd.getHeightOffset();
screenHeight = VI.height;
} else {
scaleX = _pBuffer->m_scaleX;
scaleY = _pBuffer->m_scaleY;
heightOffset = 0;
screenHeight = (_pBuffer->m_height == 0) ? VI.height : _pBuffer->m_height;
}
f32 SX0 = gDP.scissor.ulx;
f32 SX1 = gDP.scissor.lrx;
if (_needAdjustCoordinate(wnd))
_adjustScissorX(SX0, SX1, wnd.getAdjustScale());
gfxContext.setScissor((s32)(SX0 * scaleX), (s32)((screenHeight - gDP.scissor.lry) * scaleY + heightOffset),
std::max((s32)((SX1 - SX0) * scaleX), 0), std::max((s32)((gDP.scissor.lry - gDP.scissor.uly) * scaleY), 0));
gDP.changed &= ~CHANGED_SCISSOR;
}
inline
float _adjustViewportX(f32 _X0)
{
const f32 halfX = gDP.colorImage.width / 2.0f;
const f32 halfVP = gSP.viewport.width / 2.0f;
return (_X0 + halfVP - halfX) * video().getAdjustScale() + halfX - halfVP;
}
void Drawer::_updateViewport() const
{
DisplayWindow & wnd = DisplayWindow::get();
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
if (pCurrentBuffer == nullptr) {
const f32 scaleX = wnd.getScaleX();
const f32 scaleY = wnd.getScaleY();
float Xf = gSP.viewport.vscale[0] < 0 ? (gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) : gSP.viewport.x;
if (_needAdjustCoordinate(wnd))
Xf = _adjustViewportX(Xf);
const s32 X = (s32)(Xf * scaleX);
const s32 Y = gSP.viewport.vscale[1] < 0 ? (s32)((gSP.viewport.y + gSP.viewport.vscale[1] * 2.0f) * scaleY) : (s32)((VI.height - (gSP.viewport.y + gSP.viewport.height)) * scaleY);
gfxContext.setViewport(X, Y + wnd.getHeightOffset(),
std::max((s32)(gSP.viewport.width * scaleX), 0), std::max((s32)(gSP.viewport.height * scaleY), 0));
} else {
const f32 scaleX = pCurrentBuffer->m_scaleX;
const f32 scaleY = pCurrentBuffer->m_scaleY;
float Xf = gSP.viewport.vscale[0] < 0 ? (gSP.viewport.x + gSP.viewport.vscale[0] * 2.0f) : gSP.viewport.x;
if (_needAdjustCoordinate(wnd))
Xf = _adjustViewportX(Xf);
const s32 X = (s32)(Xf * scaleX);
const s32 Y = gSP.viewport.vscale[1] < 0 ? (s32)((gSP.viewport.y + gSP.viewport.vscale[1] * 2.0f) * scaleY) : (s32)((pCurrentBuffer->m_height - (gSP.viewport.y + gSP.viewport.height)) * scaleY);
gfxContext.setViewport(X, Y,
std::max((s32)(gSP.viewport.width * scaleX), 0), std::max((s32)(gSP.viewport.height * scaleY), 0));
}
gSP.changed &= ~CHANGED_VIEWPORT;
}
void Drawer::_updateScreenCoordsViewport() const
{
DisplayWindow & wnd = DisplayWindow::get();
FrameBuffer * pCurrentBuffer = frameBufferList().getCurrent();
if (pCurrentBuffer == nullptr)
gfxContext.setViewport(0, wnd.getHeightOffset(), wnd.getScreenWidth(), wnd.getScreenHeight());
else
gfxContext.setViewport(0, 0, s32(pCurrentBuffer->m_width*pCurrentBuffer->m_scaleX), s32(pCurrentBuffer->m_height*pCurrentBuffer->m_scaleY));
gSP.changed |= CHANGED_VIEWPORT;
}
void Drawer::_legacySetBlendMode() const
{
const u32 blendmode = gDP.otherMode.l >> 16;
// 0x7000 = CVG_X_ALPHA|ALPHA_CVG_SEL|FORCE_BL
if (gDP.otherMode.alphaCvgSel != 0 && (gDP.otherMode.l & 0x7000) != 0x7000) {
switch (blendmode) {
case 0x4055: // Mario Golf
case 0x5055: // Paper Mario intro clr_mem * a_in + clr_mem * a_mem
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
break;
default:
gfxContext.enable(enable::BLEND, false);
}
return;
}
if (gDP.otherMode.forceBlender != 0 && gDP.otherMode.cycleType < G_CYC_COPY) {
Parameter sfactor, dfactor;
switch (blendmode)
{
// Mace objects
case 0x0382:
// Mace special blend mode, see GLSLCombiner.cpp
case 0x0091:
// 1080 Sky
case 0x0C08:
// Used LOTS of places
case 0x0F0A:
//DK64 blue prints
case 0x0302:
// Bomberman 2 special blend mode, see GLSLCombiner.cpp
case 0xA500:
//Sin and Punishment
case 0xCB02:
// Battlezone
// clr_in * a + clr_in * (1-a)
case 0xC800:
// Conker BFD
// clr_in * a_fog + clr_fog * (1-a)
// clr_in * 0 + clr_in * 1
case 0x07C2:
case 0x00C0:
//ISS64
case 0xC302:
// Donald Duck
case 0xC702:
sfactor = blend::ONE;
dfactor = blend::ZERO;
break;
case 0x55f0:
// Bust-A-Move 3 DX
// CLR_MEM * A_FOG + CLR_FOG * 1MA
sfactor = blend::ONE;
dfactor = blend::SRC_ALPHA;
break;
case 0x0F1A:
if (gDP.otherMode.cycleType == G_CYC_1CYCLE) {
sfactor = blend::ONE;
dfactor = blend::ZERO;
}
else {
sfactor = blend::ZERO;
dfactor = blend::ONE;
}
break;
//Space Invaders
case 0x0448: // Add
case 0x055A:
sfactor = blend::ONE;
dfactor = blend::ONE;
break;
case 0xc712: // Pokemon Stadium?
case 0xAF50: // LOT in Zelda: MM
case 0x0F5A: // LOT in Zelda: MM
case 0x0FA5: // Seems to be doing just blend color - maybe combiner can be used for this?
case 0x5055: // Used in Paper Mario intro, I'm not sure if this is right...
//clr_in * 0 + clr_mem * 1
sfactor = blend::ZERO;
dfactor = blend::ONE;
break;
case 0x5F50: //clr_mem * 0 + clr_mem * (1-a)
sfactor = blend::ZERO;
dfactor = blend::ONE_MINUS_SRC_ALPHA;
break;
case 0xF550: //clr_fog * a_fog + clr_mem * (1-a)
case 0x0150: // spiderman
case 0x0550: // bomberman 64
case 0x0D18: //clr_in * a_fog + clr_mem * (1-a)
sfactor = blend::SRC_ALPHA;
dfactor = blend::ONE_MINUS_SRC_ALPHA;
break;
case 0xC912: //40 winks, clr_in * a_fog + clr_mem * 1
sfactor = blend::SRC_ALPHA;
dfactor = blend::ONE;
break;
case 0x0040: // Fzero
case 0xC810: // Blends fog
case 0x0C18: // Standard interpolated blend
case 0x0050: // Standard interpolated blend
case 0x0051: // Standard interpolated blend
case 0x0055: // Used for antialiasing
sfactor = blend::SRC_ALPHA;
dfactor = blend::ONE_MINUS_SRC_ALPHA;
break;
case 0x0C19: // Used for antialiasing
case 0xC811: // Blends fog
sfactor = blend::SRC_ALPHA;
dfactor = blend::DST_ALPHA;
break;
case 0x5000: // V8 explosions
sfactor = blend::ONE_MINUS_SRC_ALPHA;
dfactor = blend::SRC_ALPHA;
break;
case 0xFA00: // Bomberman second attack
sfactor = blend::ONE;
dfactor = blend::ZERO;
break;
default:
//LOG(LOG_VERBOSE, "Unhandled blend mode=%x", gDP.otherMode.l >> 16);
sfactor = blend::SRC_ALPHA;
dfactor = blend::ONE_MINUS_SRC_ALPHA;
break;
}
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(sfactor, dfactor);
} else if ((config.generalEmulation.hacks & hack_pilotWings) != 0 && (gDP.otherMode.l & 0x80) != 0) { //CLR_ON_CVG without FORCE_BL
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
} else if ((config.generalEmulation.hacks & hack_blastCorps) != 0 && gDP.otherMode.cycleType < G_CYC_COPY && gSP.texture.on == 0 && currentCombiner()->usesTexture()) { // Blast Corps
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
} else {
gfxContext.enable(enable::BLEND, false);
}
}
void Drawer::_setBlendMode() const
{
if (config.generalEmulation.enableLegacyBlending != 0) {
_legacySetBlendMode();
return;
}
if (gDP.otherMode.forceBlender != 0 && gDP.otherMode.cycleType < G_CYC_COPY) {
Parameter srcFactor = blend::ONE;
Parameter dstFactor = blend::ZERO;
u32 memFactorSource = 2, muxA, muxB;
if (gDP.otherMode.cycleType == G_CYC_2CYCLE) {
muxA = gDP.otherMode.c2_m1b;
muxB = gDP.otherMode.c2_m2b;
if (gDP.otherMode.c2_m1a == 1) {
if (gDP.otherMode.c2_m2a == 1) {
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
return;
}
memFactorSource = 0;
} else if (gDP.otherMode.c2_m2a == 1) {
memFactorSource = 1;
}
if (gDP.otherMode.c2_m2a == 0 && gDP.otherMode.c2_m2b == 1) {
// c_in * a_mem
srcFactor = blend::DST_ALPHA;
}
} else {
muxA = gDP.otherMode.c1_m1b;
muxB = gDP.otherMode.c1_m2b;
if (gDP.otherMode.c1_m1a == 1) {
if (gDP.otherMode.c1_m2a == 1) {
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
return;
}
memFactorSource = 0;
}
else if (gDP.otherMode.c1_m2a == 1) {
memFactorSource = 1;
}
if (gDP.otherMode.c1_m2a == 0 && gDP.otherMode.c1_m2b == 1) {
// c_pixel * a_mem
srcFactor = blend::DST_ALPHA;
}
}
switch (memFactorSource) {
case 0:
switch (muxA) {
case 0:
dstFactor = blend::SRC_ALPHA;
break;
case 1:
gfxContext.setBlendColor(gDP.fogColor.r, gDP.fogColor.g, gDP.fogColor.b, gDP.fogColor.a);
dstFactor = blend::CONSTANT_ALPHA;
break;
case 2:
assert(false); // shade alpha
dstFactor = blend::SRC_ALPHA;
break;
case 3:
dstFactor = blend::ZERO;
break;
}
break;
case 1:
switch (muxB) {
case 0:
// 1.0 - muxA
switch (muxA) {
case 0:
dstFactor = blend::ONE_MINUS_SRC_ALPHA;
break;
case 1:
gfxContext.setBlendColor(gDP.fogColor.r, gDP.fogColor.g, gDP.fogColor.b, gDP.fogColor.a);
dstFactor = blend::ONE_MINUS_CONSTANT_ALPHA;
break;
case 2:
assert(false); // shade alpha
dstFactor = blend::ONE_MINUS_SRC_ALPHA;
break;
case 3:
dstFactor = blend::ONE;
break;
}
break;
case 1:
dstFactor = blend::DST_ALPHA;
break;
case 2:
dstFactor = blend::ONE;
break;
case 3:
dstFactor = blend::ZERO;
break;
}
break;
default:
dstFactor = blend::ZERO;
}
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(srcFactor, dstFactor);
}
else if ((config.generalEmulation.hacks & hack_pilotWings) != 0 && gDP.otherMode.clearOnCvg != 0) { //CLR_ON_CVG without FORCE_BL
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
}
else if ((config.generalEmulation.hacks & hack_blastCorps) != 0 && gDP.otherMode.cycleType < G_CYC_COPY && gSP.texture.on == 0 && currentCombiner()->usesTexture()) { // Blast Corps
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
} else if ((gDP.otherMode.forceBlender == 0 && gDP.otherMode.cycleType < G_CYC_COPY)) {
if (gDP.otherMode.c1_m1a == 1 && gDP.otherMode.c1_m2a == 1) {
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
} else {
gfxContext.enable(enable::BLEND, false);
}
}
else {
gfxContext.enable(enable::BLEND, false);
}
}
void Drawer::_updateTextures() const
{
//For some reason updating the texture cache on the first frame of LOZ:OOT causes a nullptr Pointer exception...
CombinerInfo & cmbInfo = CombinerInfo::get();
CombinerProgram * pCurrentCombiner = cmbInfo.getCurrent();
if (pCurrentCombiner != nullptr) {
for (u32 t = 0; t < 2; ++t) {
if (pCurrentCombiner->usesTile(t))
textureCache().update(t);
else
textureCache().activateDummy(t);
}
}
gDP.changed &= ~(CHANGED_TILE | CHANGED_TMEM);
gSP.changed &= ~(CHANGED_TEXTURE);
}
void Drawer::_updateStates(DrawingState _drawingState) const
{
// DisplayWindow & ogl = DisplayWindow::get();
CombinerInfo & cmbInfo = CombinerInfo::get();
cmbInfo.setPolygonMode(_drawingState);
cmbInfo.update();
if (gSP.changed & CHANGED_GEOMETRYMODE) {
_updateCullFace();
gSP.changed &= ~CHANGED_GEOMETRYMODE;
}
_updateDepthCompare();
if (gDP.changed & CHANGED_SCISSOR)
updateScissor(frameBufferList().getCurrent());
if (gSP.changed & CHANGED_VIEWPORT)
_updateViewport();
if ((gSP.changed & CHANGED_TEXTURE) ||
(gDP.changed & (CHANGED_TILE | CHANGED_TMEM)) ||
cmbInfo.isChanged() ||
_drawingState == DrawingState::TexRect) {
_updateTextures();
}
if ((gDP.changed & (CHANGED_RENDERMODE | CHANGED_CYCLETYPE))) {
_setBlendMode();
gDP.changed &= ~(CHANGED_RENDERMODE | CHANGED_CYCLETYPE);
}
cmbInfo.updateParameters();
if (!gfxContext.isSupported(SpecialFeatures::FragmentDepthWrite))
return;
if (gDP.colorImage.address == gDP.depthImageAddress &&
config.generalEmulation.enableFragmentDepthWrite != 0 &&
config.frameBufferEmulation.N64DepthCompare == 0 &&
(config.generalEmulation.hacks & hack_ZeldaMM) == 0
) {
// Current render target is depth buffer.
// Shader will set gl_FragDepth to shader color, see ShaderCombiner ctor
// Here we enable depth buffer write.
if (gDP.otherMode.depthCompare != 0) {
// Render to depth buffer with depth compare. Need to get copy of current depth buffer.
FrameBuffer * pCurBuf = frameBufferList().getCurrent();
if (pCurBuf != nullptr && pCurBuf->m_pDepthBuffer != nullptr) {
CachedTexture * pDepthTexture = pCurBuf->m_pDepthBuffer->copyDepthBufferTexture(pCurBuf);
if (pDepthTexture == nullptr)
return;
Context::TexParameters params;
params.handle = graphics::ObjectHandle(pDepthTexture->glName);
params.target = graphics::target::TEXTURE_2D;
params.textureUnitIndex = graphics::textureIndices::DepthTex;
params.maxMipmapLevel = 0;
params.minFilter = graphics::textureParameters::FILTER_NEAREST;
params.magFilter = graphics::textureParameters::FILTER_NEAREST;
gfxContext.setTextureParameters(params);
}
}
else if (frameBufferList().getCurrent() == nullptr) {
gfxContext.enable(enable::BLEND, true);
gfxContext.setBlending(blend::ZERO, blend::ONE);
}
gfxContext.enable(enable::DEPTH_TEST, true);
gfxContext.setDepthCompare(compare::ALWAYS);
gfxContext.enableDepthWrite(true);
gDP.changed |= CHANGED_RENDERMODE;
}
}
void Drawer::_prepareDrawTriangle(bool _dma)
{
#ifdef GL_IMAGE_TEXTURES_SUPPORT
if (m_bImageTexture && config.frameBufferEmulation.N64DepthCompare != 0)
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
#endif // GL_IMAGE_TEXTURES_SUPPORT
if ((m_modifyVertices & MODIFY_XY) != 0)
gSP.changed &= ~CHANGED_VIEWPORT;
if (gSP.changed || gDP.changed)
_updateStates(DrawingState::Triangle);
m_drawingState = DrawingState::Triangle;
m_bDmaVertices = _dma;
bool bFlatColors = false;
if (!RSP.bLLE && (gSP.geometryMode & G_LIGHTING) == 0) {
bFlatColors = (gSP.geometryMode & G_SHADE) == 0;
bFlatColors |= (gSP.geometryMode & G_SHADING_SMOOTH) == 0;
}
m_bFlatColors = bFlatColors;
if ((m_modifyVertices & MODIFY_XY) != 0)
_updateScreenCoordsViewport();
m_modifyVertices = 0;
}
bool Drawer::_canDraw() const
{
return config.frameBufferEmulation.enable == 0 || frameBufferList().getCurrent() != nullptr;
}
void Drawer::drawTriangles()
{
if (triangles.num == 0 || !_canDraw()) {
triangles.num = 0;
triangles.maxElement = 0;
return;
}
_prepareDrawTriangle(false);
/*
const u32 count = static_cast<u32>(triangles.maxElement) + 1;
m_vbo.setTrianglesBuffers(m_bFlatColors, count, triangles.vertices);
const VerticesBuffers::BufferType bufferType = VerticesBuffers::BufferType::triangles;
glDrawElementsBaseVertex(GL_TRIANGLES, triangles.num, GL_UNSIGNED_BYTE, triangles.elements, m_vbo.getPos(bufferType) - count);
*/
if (config.frameBufferEmulation.enable != 0 &&
config.frameBufferEmulation.copyDepthToRDRAM == Config::cdSoftwareRender &&
gDP.otherMode.depthUpdate != 0) {
renderTriangles(triangles.vertices.data(), triangles.elements.data(), triangles.num);
FrameBuffer * pCurrentDepthBuffer = frameBufferList().findBuffer(gDP.depthImageAddress);
if (pCurrentDepthBuffer != nullptr)
pCurrentDepthBuffer->m_cleared = false;
}
triangles.num = 0;
triangles.maxElement = 0;
}

163
src/Drawer.h Normal file
View File

@ -0,0 +1,163 @@
#pragma once
#include <array>
#include <vector>
#include "gSP.h"
#include "Graphics/Parameter.h"
struct CachedTexture;
struct FrameBuffer;
#define VERTBUFF_SIZE 256U
#define ELEMBUFF_SIZE 1024U
enum class DrawingState
{
None = 0,
Line = 1,
Triangle = 2,
Rect = 3,
TexRect = 4,
};
class Drawer
{
public:
void addTriangle(int _v0, int _v1, int _v2);
void drawTriangles();
void drawScreenSpaceTriangle(u32 _numVtx);
void drawDMATriangles(u32 _numVtx);
void drawLine(int _v0, int _v1, float _width);
void drawRect(int _ulx, int _uly, int _lrx, int _lry, float * _pColor);
struct TexturedRectParams
{
float ulx, uly, lrx, lry;
float uls, ult, lrs, lrt;
float dsdx, dtdy;
bool flip, forceAjustScale, texrectCmd;
const FrameBuffer * pBuffer;
const CachedTexture * pInputTexture;
const CachedTexture * pOutputTexture;
TexturedRectParams(float _ulx, float _uly, float _lrx, float _lry,
float _uls, float _ult, float _lrs, float _lrt,
float _dsdx, float _dtdy,
bool _flip, bool _forceAjustScale, bool _texrectCmd,
const FrameBuffer * _pBuffer,
const CachedTexture * _pInputTexture = 0,
const CachedTexture * _pOutputTexture = 0
) :
ulx(_ulx), uly(_uly), lrx(_lrx), lry(_lry),
uls(_uls), ult(_ult), lrs(_lrs), lrt(_lrt),
dsdx(_dsdx), dtdy(_dtdy),
flip(_flip), forceAjustScale(_forceAjustScale), texrectCmd(_texrectCmd),
pBuffer(_pBuffer), pInputTexture(_pInputTexture), pOutputTexture(_pOutputTexture)
{}
private:
friend class Drawer;
TexturedRectParams() :
ulx(0), uly(0), lrx(0), lry(0)
{};
};
void correctTexturedRectParams(TexturedRectParams & _params);
void drawTexturedRect(const TexturedRectParams & _params);
void copyTexturedRect(u32 _srcX0, u32 _srcY0, u32 _srcX1, u32 _srcY1,
u32 _srcWidth, u32 _srcHeight, u32 _srcTex,
s32 _dstX0, s32 _dstY0, s32 _dstX1, s32 _dstY1,
u32 _dstWidth, u32 _dstHeight, graphics::Parameter _filter);
void drawText(const char *_pText, float x, float y);
void drawOSD();
void clearDepthBuffer(u32 _ulx, u32 _uly, u32 _lrx, u32 _lry);
void clearColorBuffer(float * _pColor);
int getTrianglesCount() const { return triangles.num; }
bool isClipped(s32 _v0, s32 _v1, s32 _v2) const
{
return (triangles.vertices[_v0].clip & triangles.vertices[_v1].clip & triangles.vertices[_v2].clip) != 0;
}
bool isImageTexturesSupported() const { return m_bImageTexture; }
SPVertex & getVertex(u32 _v) { return triangles.vertices[_v]; }
void setDMAVerticesSize(u32 _size) { if (m_dmaVertices.size() < _size) m_dmaVertices.resize(_size); }
SPVertex * getDMAVerticesData() { return m_dmaVertices.data(); }
void updateScissor(FrameBuffer * _pBuffer) const;
DrawingState getDrawingState() const { return m_drawingState; }
void dropRenderState() { m_drawingState = DrawingState::None; }
private:
Drawer()
: m_modifyVertices(0)
, m_bImageTexture(false)
, m_bFlatColors(false) {
}
Drawer(const Drawer &);
void _initExtensions();
void _initStates();
void _initData();
void _destroyData();
void _setSpecialTexrect() const;
void _setBlendMode() const;
void _legacySetBlendMode() const;
void _updateCullFace() const;
void _updateViewport() const;
void _updateScreenCoordsViewport() const;
void _updateDepthUpdate() const;
void _updateDepthCompare() const;
void _updateTextures() const;
void _updateStates(DrawingState _drawingState) const;
void _prepareDrawTriangle(bool _dma);
bool _canDraw() const;
void _drawThickLine(int _v0, int _v1, float _width);
void _getTextSize(const char *_pText, float & _w, float & _h) const;
void _drawOSD(const char *_pText, float _x, float & _y);
struct RectVertex
{
float x, y, z, w;
float s0, t0, s1, t1;
};
DrawingState m_drawingState;
TexturedRectParams m_texrectParams;
struct {
std::array<SPVertex, VERTBUFF_SIZE> vertices;
std::array<u8, ELEMBUFF_SIZE> elements;
u32 num;
int maxElement;
} triangles;
std::vector<SPVertex> m_dmaVertices;
RectVertex m_rect[4];
u32 m_modifyVertices;
f32 m_maxLineWidth;
bool m_bImageTexture;
bool m_bFlatColors;
bool m_bDmaVertices;
//GLuint m_programCopyTex;
};

View File

@ -23,6 +23,46 @@ void Context::destroy()
m_impl.reset();
}
void Context::enable(Parameter _parameter, bool _enable)
{
m_impl->enable(_parameter, _enable);
}
void Context::cullFace(Parameter _parameter)
{
m_impl->cullFace(_parameter);
}
void Context::enableDepthWrite(bool _enable)
{
m_impl->enableDepthWrite(_enable);
}
void Context::setDepthCompare(Parameter _mode)
{
m_impl->setDepthCompare(_mode);
}
void Context::setViewport(s32 _x, s32 _y, s32 _width, s32 _height)
{
m_impl->setViewport(_x, _y, _width, _height);
}
void Context::setScissor(s32 _x, s32 _y, s32 _width, s32 _height)
{
m_impl->setScissor(_x, _y, _width, _height);
}
void Context::setBlending(Parameter _sfactor, Parameter _dfactor)
{
m_impl->setBlending(_sfactor, _dfactor);
}
void Context::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
{
m_impl->setBlendColor(_red, _green, _blue, _alpha);
}
ObjectHandle Context::createTexture(Parameter _target)
{
return m_impl->createTexture(_target);
@ -118,8 +158,8 @@ ShaderProgram * Context::createTexrectCopyShader()
return m_impl->createTexrectCopyShader();
}
bool Context::isMultisamplingSupported() const
bool Context::isSupported(SpecialFeatures _feature) const
{
// TODO
return true;
}
}

View File

@ -12,6 +12,12 @@
namespace graphics {
enum class SpecialFeatures {
Multisampling,
NearPlaneClipping,
FragmentDepthWrite
};
class ContextImpl;
class Context
@ -24,6 +30,22 @@ namespace graphics {
void destroy();
void enable(Parameter _parameter, bool _enable);
void cullFace(Parameter _mode);
void enableDepthWrite(bool _enable);
void setDepthCompare(Parameter _mode);
void setViewport(s32 _x, s32 _y, s32 _width, s32 _height);
void setScissor(s32 _x, s32 _y, s32 _width, s32 _height);
void setBlending(Parameter _sfactor, Parameter _dfactor);
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha);
ObjectHandle createTexture(Parameter _target);
void deleteTexture(ObjectHandle _name);
@ -119,7 +141,7 @@ namespace graphics {
ShaderProgram * createTexrectCopyShader();
bool isMultisamplingSupported() const;
bool isSupported(SpecialFeatures _feature) const;
private:
std::unique_ptr<ContextImpl> m_impl;

View File

@ -12,6 +12,14 @@ namespace graphics {
virtual ~ContextImpl() {}
virtual void init() = 0;
virtual void destroy() = 0;
virtual void enable(Parameter _parameter, bool _enable) = 0;
virtual void cullFace(Parameter _mode) = 0;
virtual void enableDepthWrite(bool _enable) = 0;
virtual void setDepthCompare(Parameter _mode) = 0;
virtual void setViewport(s32 _x, s32 _y, s32 _width, s32 _height) = 0;
virtual void setScissor(s32 _x, s32 _y, s32 _width, s32 _height) = 0;
virtual void setBlending(Parameter _sfactor, Parameter _dfactor) = 0;
virtual void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) = 0;
virtual ObjectHandle createTexture(Parameter _target) = 0;
virtual void deleteTexture(ObjectHandle _name) = 0;
virtual void init2DTexture(const Context::InitTextureParams & _params) = 0;

View File

@ -12,6 +12,8 @@ namespace graphics {
bool operator==(const ObjectHandle & _other) const { return m_name == _other.m_name; }
bool operator!=(const ObjectHandle & _other) const { return m_name != _other.m_name; }
void reset() { m_name = 0; }
private:
u32 m_name;
};

View File

@ -6,38 +6,38 @@ using namespace glsl;
bool CombinerInputs::usesTile(u32 _t) const
{
if (_t == 0)
return (m_inputs & ((1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0;
return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA))) != 0;
return (m_inputs & ((1 << G_GCI_TEXEL0) | (1 << G_GCI_TEXEL0_ALPHA))) != 0;
return (m_inputs & ((1 << G_GCI_TEXEL1) | (1 << G_GCI_TEXEL1_ALPHA))) != 0;
}
bool CombinerInputs::usesTexture() const
{
return (m_inputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA) | (1 << TEXEL0) | (1 << TEXEL0_ALPHA))) != 0;
return (m_inputs & ((1 << G_GCI_TEXEL1) | (1 << G_GCI_TEXEL1_ALPHA) | (1 << G_GCI_TEXEL0) | (1 << G_GCI_TEXEL0_ALPHA))) != 0;
}
bool CombinerInputs::usesLOD() const
{
return (m_inputs & (1 << LOD_FRACTION)) != 0;
return (m_inputs & (1 << G_GCI_LOD_FRACTION)) != 0;
}
bool CombinerInputs::usesNoise() const
{
return (m_inputs & (1 << NOISE)) != 0;
return (m_inputs & (1 << G_GCI_NOISE)) != 0;
}
bool CombinerInputs::usesShade() const
{
return (m_inputs & ((1 << SHADE) | (1 << SHADE_ALPHA))) != 0;
return (m_inputs & ((1 << G_GCI_SHADE) | (1 << G_GCI_SHADE_ALPHA))) != 0;
}
bool CombinerInputs::usesShadeColor() const
{
return (m_inputs & (1 << SHADE)) != 0;
return (m_inputs & (1 << G_GCI_SHADE)) != 0;
}
bool CombinerInputs::usesHwLighting() const
{
return (m_inputs & (1 << HW_LIGHT)) != 0;
return (m_inputs & (1 << G_GCI_HW_LIGHT)) != 0;
}
void CombinerInputs::addInput(int _input)

View File

@ -66,10 +66,10 @@ inline
int correctFirstStageParam(int _param)
{
switch (_param) {
case TEXEL1:
return TEXEL0;
case TEXEL1_ALPHA:
return TEXEL0_ALPHA;
case G_GCI_TEXEL1:
return G_GCI_TEXEL0;
case G_GCI_TEXEL1_ALPHA:
return G_GCI_TEXEL0_ALPHA;
}
return _param;
}
@ -88,14 +88,14 @@ inline
int correctSecondStageParam(int _param)
{
switch (_param) {
case TEXEL0:
return TEXEL1;
case TEXEL1:
return TEXEL0;
case TEXEL0_ALPHA:
return TEXEL1_ALPHA;
case TEXEL1_ALPHA:
return TEXEL0_ALPHA;
case G_GCI_TEXEL0:
return G_GCI_TEXEL1;
case G_GCI_TEXEL1:
return G_GCI_TEXEL0;
case G_GCI_TEXEL0_ALPHA:
return G_GCI_TEXEL1_ALPHA;
case G_GCI_TEXEL1_ALPHA:
return G_GCI_TEXEL0_ALPHA;
}
return _param;
}
@ -1748,7 +1748,7 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
config.generalEmulation.enableHWLighting != 0 && GBI.isHWLSupported() && combinerInputs.usesShadeColor();
if (bUseHWLight)
combinerInputs.addInput(HW_LIGHT);
combinerInputs.addInput(G_GCI_HW_LIGHT);
std::stringstream ssShader;

View File

@ -1,30 +1,25 @@
#include "GLFunctions.h"
#include "opengl_GLInfo.h"
#include "opengl_CachedFunctions.h"
using namespace graphics;
using namespace opengl;
/*---------------CachedEnable-------------*/
CachedEnable::CachedEnable(graphics::Parameter _parameter)
CachedEnable::CachedEnable(Parameter _parameter)
: m_parameter(_parameter)
, m_enabled(false)
{
}
CachedEnable::CachedEnable()
: m_parameter(0U)
, m_enabled(false)
{
}
void CachedEnable::reset()
{
m_enabled = false;
}
void CachedEnable::enable(bool _enable)
{
if (!m_parameter.isValid())
return;
// TODO make cacheable
if (!update(u32(_enable)))
return;
if (_enable) {
glEnable(GLenum(m_parameter));
} else {
@ -34,62 +29,111 @@ void CachedEnable::enable(bool _enable)
/*---------------CachedBindTexture-------------*/
CachedBindTexture::CachedBindTexture()
: m_name(0U) {
}
void CachedBindTexture::reset()
void CachedBindTexture::bind(Parameter _target, ObjectHandle _name)
{
m_name = graphics::ObjectHandle(0U);
}
void CachedBindTexture::bind(graphics::Parameter _target, graphics::ObjectHandle _name)
{
m_name = _name;
// TODO make cacheable
glBindTexture(GLenum(_target), GLuint(_name));
if (update(_name))
glBindTexture(GLenum(_target), GLuint(_name));
}
/*---------------CachedActiveTexture-------------*/
const graphics::Parameter CachedActiveTexture::m_invalidIndex(0xFFFFFFFF);
CachedActiveTexture::CachedActiveTexture()
: m_index(m_invalidIndex) {
void CachedActiveTexture::setActiveTexture(Parameter _index) {
if (update(_index))
glActiveTexture(GL_TEXTURE0 + GLuint(_index));
}
void CachedActiveTexture::reset() {
m_index = m_invalidIndex;
/*---------------CachedCullFace-------------*/
void CachedCullFace::setCullFace(Parameter _mode)
{
if (update(_mode))
glCullFace(GLenum(_mode));
}
void CachedActiveTexture::setActiveTexture(graphics::Parameter _index) {
// TODO make cacheable
m_index = _index;
glActiveTexture(GL_TEXTURE0 + GLuint(_index));
/*---------------CachedDepthMask-------------*/
void CachedDepthMask::setDepthMask(bool _enable)
{
if (update(Parameter(u32(_enable))))
glDepthMask(GLboolean(_enable));
}
/*---------------CachedDepthMask-------------*/
void CachedDepthCompare::setDepthCompare(Parameter _mode)
{
if (update(_mode))
glDepthFunc(GLenum(_mode));
}
/*---------------CachedViewport-------------*/
void CachedViewport::setViewport(s32 _x, s32 _y, s32 _width, s32 _height)
{
if (update(Parameter(_x), Parameter(_y), Parameter(_width), Parameter(_height)))
glViewport(_x, _y, _width, _height);
}
/*---------------CachedScissor-------------*/
void CachedScissor::setScissor(s32 _x, s32 _y, s32 _width, s32 _height)
{
if (update(Parameter(_x), Parameter(_y), Parameter(_width), Parameter(_height)))
glScissor(_x, _y, _width, _height);
}
/*---------------CachedBlending-------------*/
void CachedBlending::setBlending(Parameter _sfactor, Parameter _dfactor)
{
if (update(_sfactor, _dfactor))
glBlendFunc(GLenum(_sfactor), GLenum(_dfactor));
}
/*---------------CachedBlendColor-------------*/
void CachedBlendColor::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
{
if (update(Parameter(_red), Parameter(_green), Parameter(_blue), Parameter(_alpha)))
glBlendColor(_red, _green, _blue, _alpha);
}
/*---------------CachedFunctions-------------*/
CachedFunctions::CachedFunctions()
CachedFunctions::CachedFunctions(const GLInfo & _glinfo)
: m_bindFramebuffer(glBindFramebuffer)
, m_bindRenderbuffer(glBindRenderbuffer)
, m_bindBuffer(glBindBuffer) {
if (_glinfo.isGLESX) {
// Disable parameters, not avalible for GLESX
m_enables.emplace(GL_DEPTH_CLAMP, Parameter());
}
}
CachedFunctions::~CachedFunctions()
{
}
void CachedFunctions::reset() {
void CachedFunctions::reset()
{
for (auto it : m_enables)
it.second.reset();
m_activeTexture.reset();
m_bindTexture.reset();
m_bindFramebuffer.reset();
m_bindRenderbuffer.reset();
m_bindBuffer.reset();
m_cullFace.reset();
m_depthMask.reset();
m_depthCompare.reset();
m_viewport.reset();
m_scissor.reset();
m_blending.reset();
m_blendColor.reset();
}
CachedEnable * CachedFunctions::getCachedEnable(graphics::Parameter _parameter)
CachedEnable * CachedFunctions::getCachedEnable(Parameter _parameter)
{
const u32 key(_parameter);
auto it = m_enables.find(key);
@ -122,6 +166,42 @@ CachedBindRenderbuffer * CachedFunctions::geCachedBindRenderbuffer()
return &m_bindRenderbuffer;
}
CachedBindBuffer * CachedFunctions::geCachedBindBuffer() {
CachedBindBuffer * CachedFunctions::geCachedBindBuffer()
{
return &m_bindBuffer;
}
CachedCullFace * CachedFunctions::getCachedCullFace()
{
return &m_cullFace;
}
CachedDepthMask * CachedFunctions::getCachedDepthMask()
{
return &m_depthMask;
}
CachedDepthCompare * CachedFunctions::getCachedDepthCompare()
{
return &m_depthCompare;
}
CachedViewport * CachedFunctions::getCachedViewport()
{
return &m_viewport;
}
CachedScissor * CachedFunctions::getCachedScissor()
{
return &m_scissor;
}
CachedBlending * CachedFunctions::getCachedBlending()
{
return &m_blending;
}
CachedBlendColor * CachedFunctions::getCachedBlendColor()
{
return &m_blendColor;
}

View File

@ -5,40 +5,55 @@
namespace opengl {
class CachedEnable
//#define CACHED_USE_CACHE
template<class T>
class Cached1
{
public:
CachedEnable();
CachedEnable(graphics::Parameter _parameter);
bool update(T _param)
{
#ifdef CACHED_USE_CACHE
if (_param == m_cached)
return false;
#endif
m_cached = _param;
return true;
}
void reset();
void reset()
{
m_cached.reset();
}
protected:
T m_cached;
};
class CachedEnable : public Cached1<graphics::Parameter>
{
public:
CachedEnable(graphics::Parameter _parameter);
void enable(bool _enable);
private:
const graphics::Parameter m_parameter;
bool m_enabled;
};
template<typename Bind>
class CachedBind
class CachedBind : public Cached1<graphics::ObjectHandle>
{
public:
CachedBind(Bind _bind) : m_bind(_bind), m_name(0U) {}
CachedBind(Bind _bind) : m_bind(_bind) {}
void bind(graphics::Parameter _target, graphics::ObjectHandle _name) {
// TODO make cacheble
m_bind(GLenum(_target), GLuint(_name));
}
void reset()
{
m_name = graphics::ObjectHandle(0U);
if (update(_name))
m_bind(GLenum(_target), GLuint(_name));
}
private:
graphics::ObjectHandle m_name;
Bind m_bind;
};
@ -48,37 +63,126 @@ namespace opengl {
typedef CachedBind<decltype(glBindBuffer)> CachedBindBuffer;
class CachedBindTexture
class CachedBindTexture : public Cached1<graphics::ObjectHandle>
{
public:
CachedBindTexture();
void reset();
void bind(graphics::Parameter _target, graphics::ObjectHandle _name);
private:
graphics::ObjectHandle m_name;
};
class CachedActiveTexture
class CachedActiveTexture : public Cached1<graphics::Parameter>
{
public:
CachedActiveTexture();
void reset();
void setActiveTexture(graphics::Parameter _index);
private:
static const graphics::Parameter m_invalidIndex;
graphics::Parameter m_index;
};
class CachedCullFace : public Cached1<graphics::Parameter>
{
public:
void setCullFace(graphics::Parameter _mode);
};
class CachedDepthMask : public Cached1<graphics::Parameter>
{
public:
void setDepthMask(bool _enable);
};
class CachedDepthCompare : public Cached1<graphics::Parameter>
{
public:
void setDepthCompare(graphics::Parameter m_mode);
};
class Cached2
{
public:
bool update(graphics::Parameter _p1,
graphics::Parameter _p2)
{
#ifdef CACHED_USE_CACHE
if (_p1 == m_p1 &&
_p2 == m_p2)
return false;
#endif
m_p1 = _p1;
m_p2 = _p2;
return true;
}
void reset()
{
m_p1.reset();
m_p2.reset();
}
protected:
graphics::Parameter m_p1, m_p2;
};
class Cached4
{
public:
bool update(graphics::Parameter _p1,
graphics::Parameter _p2,
graphics::Parameter _p3,
graphics::Parameter _p4)
{
#ifdef CACHED_USE_CACHE
if (_p1 == m_p1 &&
_p2 == m_p2 &&
_p3 == m_p3 &&
_p4 == m_p4)
return false;
#endif
m_p1 = _p1;
m_p2 = _p2;
m_p3 = _p3;
m_p4 = _p4;
return true;
}
void reset()
{
m_p1.reset();
m_p2.reset();
m_p3.reset();
m_p4.reset();
}
protected:
graphics::Parameter m_p1, m_p2, m_p3, m_p4;
};
class CachedViewport : public Cached4
{
public:
void setViewport(s32 _x, s32 _y, s32 _width, s32 _height);
};
class CachedScissor : public Cached4
{
public:
void setScissor(s32 _x, s32 _y, s32 _width, s32 _height);
};
class CachedBlending : public Cached2
{
public:
void setBlending(graphics::Parameter _sfactor, graphics::Parameter _dfactor);
};
class CachedBlendColor : public Cached4
{
public:
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha);
};
/*---------------CachedFunctions-------------*/
class CachedFunctions
{
public:
CachedFunctions();
CachedFunctions(const GLInfo & _glinfo);
~CachedFunctions();
void reset();
@ -95,6 +199,20 @@ namespace opengl {
CachedBindBuffer * geCachedBindBuffer();
CachedCullFace * getCachedCullFace();
CachedDepthMask * getCachedDepthMask();
CachedDepthCompare * getCachedDepthCompare();
CachedViewport * getCachedViewport();
CachedScissor * getCachedScissor();
CachedBlending * getCachedBlending();
CachedBlendColor * getCachedBlendColor();
private:
typedef std::unordered_map<u32, CachedEnable> EnableParameters;
@ -104,6 +222,13 @@ namespace opengl {
CachedBindFramebuffer m_bindFramebuffer;
CachedBindRenderbuffer m_bindRenderbuffer;
CachedBindBuffer m_bindBuffer;
CachedCullFace m_cullFace;
CachedDepthMask m_depthMask;
CachedDepthCompare m_depthCompare;
CachedViewport m_viewport;
CachedScissor m_scissor;
CachedBlending m_blending;
CachedBlendColor m_blendColor;
};
}

View File

@ -22,7 +22,7 @@ void ContextImpl::init()
m_glInfo.init();
if (!m_cachedFunctions)
m_cachedFunctions.reset(new CachedFunctions);
m_cachedFunctions.reset(new CachedFunctions(m_glInfo));
{
TextureManipulationObjectFactory textureObjectsFactory(m_glInfo, *m_cachedFunctions.get());
@ -60,6 +60,46 @@ void ContextImpl::destroy()
m_combinerProgramBuilder.reset(nullptr);
}
void ContextImpl::enable(graphics::Parameter _parameter, bool _enable)
{
m_cachedFunctions->getCachedEnable(_parameter)->enable(_enable);
}
void ContextImpl::cullFace(graphics::Parameter _mode)
{
m_cachedFunctions->getCachedCullFace()->setCullFace(_mode);
}
void ContextImpl::enableDepthWrite(bool _enable)
{
m_cachedFunctions->getCachedDepthMask()->setDepthMask(_enable);
}
void ContextImpl::setDepthCompare(graphics::Parameter _mode)
{
m_cachedFunctions->getCachedDepthCompare()->setDepthCompare(_mode);
}
void ContextImpl::setViewport(s32 _x, s32 _y, s32 _width, s32 _height)
{
m_cachedFunctions->getCachedViewport()->setViewport(_x, _y, _width, _height);
}
void ContextImpl::setScissor(s32 _x, s32 _y, s32 _width, s32 _height)
{
m_cachedFunctions->getCachedScissor()->setScissor(_x, _y, _width, _height);
}
void ContextImpl::setBlending(graphics::Parameter _sfactor, graphics::Parameter _dfactor)
{
m_cachedFunctions->getCachedBlending()->setBlending(_sfactor, _dfactor);
}
void ContextImpl::setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha)
{
}
graphics::ObjectHandle ContextImpl::createTexture(graphics::Parameter _target)
{
return m_createTexture->createTexture(_target);

View File

@ -22,6 +22,22 @@ namespace opengl {
void destroy() override;
void enable(graphics::Parameter _parameter, bool _enable) override;
void cullFace(graphics::Parameter _mode) override;
void enableDepthWrite(bool _enable) override;
void setDepthCompare(graphics::Parameter _mode) override;
void setViewport(s32 _x, s32 _y, s32 _width, s32 _height) override;
void setScissor(s32 _x, s32 _y, s32 _width, s32 _height) override;
void setBlending(graphics::Parameter _sfactor, graphics::Parameter _dfactor) override;
void setBlendColor(f32 _red, f32 _green, f32 _blue, f32 _alpha) override;
graphics::ObjectHandle createTexture(graphics::Parameter _target) override;
void deleteTexture(graphics::ObjectHandle _name) override;

View File

@ -77,4 +77,25 @@ namespace graphics {
Parameter WRAP_REPEAT(GL_REPEAT);
Parameter WRAP_MIRRORED_REPEAT(GL_MIRRORED_REPEAT);
}
namespace cullMode {
Parameter FRONT(GL_FRONT);
Parameter BACK(GL_BACK);
}
namespace compare {
Parameter LEQUAL(GL_LEQUAL);
Parameter LESS(GL_LESS);
Parameter ALWAYS(GL_ALWAYS);
}
namespace blend {
Parameter ZERO(GL_ZERO);
Parameter ONE(GL_ONE);
Parameter SRC_ALPHA(GL_SRC_ALPHA);
Parameter DST_ALPHA(GL_DST_ALPHA);
Parameter ONE_MINUS_SRC_ALPHA(GL_ONE_MINUS_SRC_ALPHA);
Parameter CONSTANT_ALPHA(GL_CONSTANT_ALPHA);
Parameter ONE_MINUS_CONSTANT_ALPHA(GL_ONE_MINUS_CONSTANT_ALPHA);
}
}

View File

@ -19,6 +19,8 @@ namespace graphics {
bool isValid() const { return m_iparameter != INVALID_PARAMETER; }
void reset() { m_iparameter = INVALID_PARAMETER; }
bool operator==(const Parameter & _other) const { return m_iparameter == _other.m_iparameter; }
private:

View File

@ -77,4 +77,25 @@ namespace graphics {
extern Parameter WRAP_REPEAT;
extern Parameter WRAP_MIRRORED_REPEAT;
}
namespace cullMode {
extern Parameter FRONT;
extern Parameter BACK;
}
namespace compare {
extern Parameter LEQUAL;
extern Parameter LESS;
extern Parameter ALWAYS;
}
namespace blend {
extern Parameter ZERO;
extern Parameter ONE;
extern Parameter SRC_ALPHA;
extern Parameter DST_ALPHA;
extern Parameter ONE_MINUS_SRC_ALPHA;
extern Parameter CONSTANT_ALPHA;
extern Parameter ONE_MINUS_CONSTANT_ALPHA;
}
}

View File

@ -1,9 +1,9 @@
#include <Graphics/Context.h>
#include <Graphics/Parameters.h>
#include "FrameBuffer.h"
#include "Config.h""
#include "Config.h"
#include "GBI.h"
#include "VI.h""
#include "VI.h"
#include "Textures.h"
#include "NoiseTexture.h"

View File

@ -496,7 +496,7 @@ void TextureCache::init()
m_pMSDummy = nullptr;
if (config.video.multisampling != 0 && gfxContext.isMultisamplingSupported()) {
if (config.video.multisampling != 0 && gfxContext.isSupported(graphics::SpecialFeatures::Multisampling)) {
m_pMSDummy = addFrameBufferTexture(true); // we don't want to remove dummy texture
_initDummyTexture(m_pMSDummy);

View File

@ -2,7 +2,7 @@
#include "Graphics/Parameters.h"
#include "FBOTextureFormats.h"
#include "DepthBuffer.h"
#include "Config.h""
#include "Config.h"
#include "Textures.h"
#include "ZlutTexture.h"