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:
parent
4cbb2d0189
commit
dd57479838
|
@ -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" />
|
||||
|
|
|
@ -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>
|
|
@ -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())
|
||||
|
|
|
@ -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
656
src/Drawer.cpp
Normal 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
163
src/Drawer.h
Normal 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;
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user