From c6a5740665a4998f669e4193337c6952bb086a9b Mon Sep 17 00:00:00 2001 From: rogerman Date: Fri, 6 Oct 2017 17:13:08 -0700 Subject: [PATCH] =?UTF-8?q?GFX3D:=20Rework=20polygon=20attributes=20and=20?= =?UTF-8?q?texture=20parameters=20using=20the=20latest=20coding=20style.?= =?UTF-8?q?=20Also=20improve=20the=20performance=20of=20SoftRasterizer=20w?= =?UTF-8?q?hile=20we=E2=80=99re=20at=20it.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- desmume/src/OGLRender.cpp | 94 ++++--- desmume/src/OGLRender.h | 6 +- desmume/src/OGLRender_3_2.cpp | 54 ++-- desmume/src/OGLRender_3_2.h | 2 +- desmume/src/gfx3d.cpp | 71 +++--- desmume/src/gfx3d.h | 456 +++++++++++++--------------------- desmume/src/rasterize.cpp | 230 +++++++++++------ desmume/src/rasterize.h | 2 +- desmume/src/render3D.cpp | 2 +- desmume/src/render3D.h | 2 +- desmume/src/texcache.cpp | 30 +-- desmume/src/texcache.h | 12 +- 12 files changed, 449 insertions(+), 512 deletions(-) diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 6c2b2760e..314f4035f 100755 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -693,7 +693,7 @@ static void OGLGetDriverVersion(const char *oglVersionString, } } -OpenGLTexture::OpenGLTexture(u32 texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes) +OpenGLTexture::OpenGLTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes) { _cacheSize = GetUnpackSizeUsingFormat(TexFormat_32bpp); _invSizeS = 1.0f / (float)_sizeS; @@ -1523,7 +1523,7 @@ OpenGLTexture* OpenGLRenderer::GetLoadedTextureFromPolygon(const POLY &thePoly, } template -size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr) +size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr) { OGLRenderRef &OGLRef = *this->ref; @@ -1550,7 +1550,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const // Set up the initial polygon const POLY &initialPoly = polyList->list[indexList->list[firstIndex]]; - u32 lastTexParams = initialPoly.texParam; + TEXIMAGE_PARAM lastTexParams = initialPoly.texParam; u32 lastTexPalette = initialPoly.texPalette; u32 lastViewport = initialPoly.viewport; @@ -1566,14 +1566,14 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const const POLY &thePoly = polyList->list[indexList->list[i]]; // Set up the polygon if it changed - if (lastPolyAttr != thePoly.polyAttr) + if (lastPolyAttr.value != thePoly.attribute.value) { - lastPolyAttr = thePoly.polyAttr; + lastPolyAttr = thePoly.attribute; this->SetupPolygon(thePoly, (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys), (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass)); } // Set up the texture if it changed - if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette) + if (lastTexParams.value != thePoly.texParam.value || lastTexPalette != thePoly.texPalette) { lastTexParams = thePoly.texParam; lastTexPalette = thePoly.texPalette; @@ -1602,17 +1602,17 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const // the same and we're not drawing a line loop or line strip. if (i+1 <= lastIndex) { - const POLY *nextPoly = &polyList->list[indexList->list[i+1]]; + const POLY &nextPoly = polyList->list[indexList->list[i+1]]; - if (lastPolyAttr == nextPoly->polyAttr && - lastTexParams == nextPoly->texParam && - lastTexPalette == nextPoly->texPalette && - lastViewport == nextPoly->viewport && - polyPrimitive == oglPrimitiveType[nextPoly->vtxFormat] && + if (lastPolyAttr.value == nextPoly.attribute.value && + lastTexParams.value == nextPoly.texParam.value && + lastTexPalette == nextPoly.texPalette && + lastViewport == nextPoly.viewport && + polyPrimitive == oglPrimitiveType[nextPoly.vtxFormat] && polyPrimitive != GL_LINE_LOOP && polyPrimitive != GL_LINE_STRIP && - oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_LOOP && - oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_STRIP) + oglPrimitiveType[nextPoly.vtxFormat] != GL_LINE_LOOP && + oglPrimitiveType[nextPoly.vtxFormat] != GL_LINE_STRIP) { continue; } @@ -1621,22 +1621,22 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const // Render the polygons this->SetPolygonIndex(i); - if (thePoly.getAttributePolygonMode() == POLYGON_MODE_SHADOW) + if (thePoly.attribute.Mode == POLYGON_MODE_SHADOW) { if (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass) { - this->DrawShadowPolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.getAttributeEnableAlphaDepthWrite(), thePoly.isTranslucent(), thePoly.getAttributePolygonID()); + this->DrawShadowPolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.attribute.TranslucentDepthWrite_Enable, thePoly.isTranslucent(), thePoly.attribute.PolygonID); } } - else if ( (thePoly.getTexParamTexFormat() == TEXMODE_A3I5) || (thePoly.getTexParamTexFormat() == TEXMODE_A5I3) ) + else if ( (thePoly.texParam.PackedFormat == TEXMODE_A3I5) || (thePoly.texParam.PackedFormat == TEXMODE_A5I3) ) { if (DRAWMODE == OGLPolyDrawMode_ZeroAlphaPass) { - this->DrawAlphaTexturePolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.getAttributeEnableAlphaDepthWrite(), thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque()); + this->DrawAlphaTexturePolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.attribute.TranslucentDepthWrite_Enable, thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque()); } else { - this->DrawAlphaTexturePolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.getAttributeEnableAlphaDepthWrite(), thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque()); + this->DrawAlphaTexturePolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.attribute.TranslucentDepthWrite_Enable, thePoly.isTranslucent(), thePoly.isWireframe() || thePoly.isOpaque()); } } else @@ -3265,7 +3265,7 @@ Render3DError OpenGLRenderer_1_2::DisableVertexAttributes() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr) +Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr) { OGLRenderRef &OGLRef = *this->ref; @@ -3618,7 +3618,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) } else { - const GLfloat thePolyAlpha = (thePoly->isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly->getAttributeAlpha()]; + const GLfloat thePolyAlpha = (thePoly->isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly->attribute.Alpha]; for (size_t j = 0; j < polyType; j++) { @@ -3692,7 +3692,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, size_t indexOffset = 0; const POLY &firstPoly = polyList->list[indexList->list[0]]; - u32 lastPolyAttr = firstPoly.polyAttr; + POLYGON_ATTR lastPolyAttr = firstPoly.attribute; if (polyList->opaqueCount > 0) { @@ -3714,7 +3714,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, if (polyList->opaqueCount > 0) { const POLY &lastOpaquePoly = polyList->list[indexList->list[polyList->opaqueCount - 1]]; - lastPolyAttr = lastOpaquePoly.polyAttr; + lastPolyAttr = lastOpaquePoly.attribute; this->SetupPolygon(lastOpaquePoly, false, true); } } @@ -4098,15 +4098,13 @@ void OpenGLRenderer_1_2::SetPolygonIndex(const size_t index) Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer) { - const PolygonAttributes attr = thePoly.getAttributes(); - // Set up depth test mode static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL}; - glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); + glDepthFunc(oglDepthFunc[thePoly.attribute.DepthEqualTest_Enable]); // Set up culling mode static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; - GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + GLenum cullingMode = oglCullingMode[thePoly.attribute.SurfaceCullingMode]; if (cullingMode == 0) { @@ -4121,13 +4119,13 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs if (willChangeStencilBuffer) { // Handle drawing states for the polygon - if (attr.polygonMode == POLYGON_MODE_SHADOW) + if (thePoly.attribute.Mode == POLYGON_MODE_SHADOW) { // Set up shadow polygon states. // // See comments in DrawShadowPolygon() for more information about // how this 4-pass process works in OpenGL. - if (attr.polygonID == 0) + if (thePoly.attribute.PolygonID == 0) { // 1st pass: Mark stencil buffer bits (0x40) with the shadow polygon volume. // Bits are only marked on depth-fail. @@ -4140,7 +4138,7 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs // 2nd pass: Mark stencil buffer bits (0x80) with the result of the polygon ID // check. Bits are marked if the polygon ID of this polygon differs from the // one in the stencil buffer. - glStencilFunc(GL_NOTEQUAL, 0x80 | attr.polygonID, 0x3F); + glStencilFunc(GL_NOTEQUAL, 0x80 | thePoly.attribute.PolygonID, 0x3F); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilMask(0x80); } @@ -4150,12 +4148,12 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs } else { - glStencilFunc(GL_ALWAYS, attr.polygonID, 0x3F); + glStencilFunc(GL_ALWAYS, thePoly.attribute.PolygonID, 0x3F); glStencilOp(GL_KEEP, GL_KEEP, (treatAsTranslucent) ? GL_KEEP : GL_REPLACE); glStencilMask(0xFF); // Drawing non-shadow polygons will implicitly reset the stencil buffer bits glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask((!treatAsTranslucent || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); + glDepthMask((!treatAsTranslucent || thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE); } } @@ -4163,18 +4161,18 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs if (this->isShaderSupported) { OGLRenderRef &OGLRef = *this->ref; - glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); - glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE); - glUniform1f(OGLRef.uniformPolyAlpha, (attr.isWireframe) ? 1.0f : divide5bitBy31_LUT[attr.alpha]); - glUniform1i(OGLRef.uniformPolyID, attr.polygonID); - glUniform1i(OGLRef.uniformPolyIsWireframe, (attr.isWireframe) ? GL_TRUE : GL_FALSE); - glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformPolyMode, thePoly.attribute.Mode); + glUniform1i(OGLRef.uniformPolyEnableFog, (thePoly.attribute.Fog_Enable) ? GL_TRUE : GL_FALSE); + glUniform1f(OGLRef.uniformPolyAlpha, (thePoly.isWireframe()) ? 1.0f : divide5bitBy31_LUT[thePoly.attribute.Alpha]); + glUniform1i(OGLRef.uniformPolyID, thePoly.attribute.PolygonID); + glUniform1i(OGLRef.uniformPolyIsWireframe, (thePoly.isWireframe()) ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE); } else { // Set the texture blending mode static const GLint oglTexBlendMode[4] = {GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE}; - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[attr.polygonMode]); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[thePoly.attribute.Mode]); } return OGLERROR_NOERR; @@ -4202,8 +4200,6 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, size_t polyR return OGLERROR_NOERR; } - - const PolygonTexParams texParams = thePoly.getTexParams(); // Enable textures if they weren't already enabled if (this->isShaderSupported) @@ -4221,8 +4217,8 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, size_t polyR } glBindTexture(GL_TEXTURE_2D, theTexture->GetID()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (texParams.enableRepeatS ? (texParams.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (texParams.enableRepeatT ? (texParams.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ((thePoly.texParam.RepeatS_Enable) ? ((thePoly.texParam.MirroredRepeatS_Enable) ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ((thePoly.texParam.RepeatT_Enable) ? ((thePoly.texParam.MirroredRepeatT_Enable) ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE)); if (this->_textureSmooth) { @@ -4687,14 +4683,12 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, size_t polyR return OGLERROR_NOERR; } - const PolygonTexParams texParams = thePoly.getTexParams(); - glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); glUniform1i(OGLRef.uniformTexSingleBitAlpha, (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE); glBindTexture(GL_TEXTURE_2D, theTexture->GetID()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (texParams.enableRepeatS ? (texParams.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (texParams.enableRepeatT ? (texParams.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ((thePoly.texParam.RepeatS_Enable) ? ((thePoly.texParam.MirroredRepeatS_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ((thePoly.texParam.RepeatT_Enable) ? ((thePoly.texParam.MirroredRepeatT_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); if (this->_textureSmooth) { @@ -4748,6 +4742,6 @@ Render3DError OpenGLRenderer_2_1::RenderFlush(bool willFlushBuffer32, bool willF return RENDER3DERROR_NOERR; } -template size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr); -template size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr); -template size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr); +template size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); +template size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); +template size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index d3fdc9414..0efcb412d 100755 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -601,7 +601,7 @@ protected: u32 *_upscaleBuffer; public: - OpenGLTexture(u32 texAttributes, u32 palAttributes); + OpenGLTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes); virtual ~OpenGLTexture(); virtual void Load(bool isNewTexture); @@ -657,7 +657,7 @@ protected: Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16); OpenGLTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing); - template size_t DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, u32 &lastPolyAttr); + template size_t DrawPolygonsForIndexRange(const POLYLIST *polyList, const INDEXLIST *indexList, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); template Render3DError DrawAlphaTexturePolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool enableAlphaDepthWrite, const bool isTranslucent, const bool canHaveOpaqueFragments); // OpenGL-specific methods @@ -773,7 +773,7 @@ protected: virtual void GetExtensionSet(std::set *oglExtensionSet); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); - virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr); + virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); virtual Render3DError DownsampleFBO(); virtual Render3DError ReadBackPixels(); diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 2476e9e4f..5d606e3b5 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -1350,7 +1350,7 @@ Render3DError OpenGLRenderer_3_2::DisableVertexAttributes() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr) +Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr) { OGLRenderRef &OGLRef = *this->ref; @@ -1612,19 +1612,19 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) for (size_t i = 0; i < engine.polylist->count; i++) { - const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]]; - const size_t polyType = thePoly->type; + const POLY &thePoly = engine.polylist->list[engine.indexlist.list[i]]; + const size_t polyType = thePoly.type; for (size_t j = 0; j < polyType; j++) { - const GLushort vertIndex = thePoly->vertIndexes[j]; + const GLushort vertIndex = thePoly.vertIndexes[j]; // While we're looping through our vertices, add each vertex index to // a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; - if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP) + if (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP) { if (j == 2) { @@ -1632,26 +1632,24 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) } else if (j == 3) { - indexPtr[vertIndexCount++] = thePoly->vertIndexes[0]; + indexPtr[vertIndexCount++] = thePoly.vertIndexes[0]; } } } - this->_textureList[i] = this->GetLoadedTextureFromPolygon(*thePoly, engine.renderState.enableTexturing); + this->_textureList[i] = this->GetLoadedTextureFromPolygon(thePoly, engine.renderState.enableTexturing); const NDSTextureFormat packFormat = this->_textureList[i]->GetPackFormat(); - const PolygonAttributes polyAttr = thePoly->getAttributes(); - const PolygonTexParams texParams = thePoly->getTexParams(); polyStates[i].enableTexture = (this->_textureList[i]->IsSamplingEnabled()) ? GL_TRUE : GL_FALSE; - polyStates[i].enableFog = (polyAttr.enableRenderFog) ? GL_TRUE : GL_FALSE; - polyStates[i].isWireframe = (polyAttr.isWireframe) ? GL_TRUE : GL_FALSE; - polyStates[i].setNewDepthForTranslucent = (polyAttr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; - polyStates[i].polyAlpha = (polyAttr.isWireframe) ? 0x1F : polyAttr.alpha; - polyStates[i].polyMode = polyAttr.polygonMode; - polyStates[i].polyID = polyAttr.polygonID; - polyStates[i].texSizeS = texParams.sizeS; // Note that we are using the packed version of sizeS - polyStates[i].texSizeT = texParams.sizeT; // Note that we are using the packed version of sizeT + polyStates[i].enableFog = (thePoly.attribute.Fog_Enable) ? GL_TRUE : GL_FALSE; + polyStates[i].isWireframe = (thePoly.isWireframe()) ? GL_TRUE : GL_FALSE; + polyStates[i].setNewDepthForTranslucent = (thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE; + polyStates[i].polyAlpha = (thePoly.isWireframe()) ? 0x1F : thePoly.attribute.Alpha; + polyStates[i].polyMode = thePoly.attribute.Mode; + polyStates[i].polyID = thePoly.attribute.PolygonID; + polyStates[i].texSizeS = thePoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S + polyStates[i].texSizeT = thePoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T polyStates[i].texSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE; } @@ -1860,15 +1858,13 @@ void OpenGLRenderer_3_2::SetPolygonIndex(const size_t index) Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer) { - const PolygonAttributes attr = thePoly.getAttributes(); - // Set up depth test mode static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL}; - glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); + glDepthFunc(oglDepthFunc[thePoly.attribute.DepthEqualTest_Enable]); // Set up culling mode static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; - GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + GLenum cullingMode = oglCullingMode[thePoly.attribute.SurfaceCullingMode]; if (cullingMode == 0) { @@ -1883,13 +1879,13 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAs if (willChangeStencilBuffer) { // Handle drawing states for the polygon - if (attr.polygonMode == POLYGON_MODE_SHADOW) + if (thePoly.attribute.Mode == POLYGON_MODE_SHADOW) { // Set up shadow polygon states. // // See comments in DrawShadowPolygon() for more information about // how this 4-pass process works in OpenGL. - if (attr.polygonID == 0) + if (thePoly.attribute.PolygonID == 0) { // 1st pass: Mark stencil buffer bits (0x40) with the shadow polygon volume. // Bits are only marked on depth-fail. @@ -1902,7 +1898,7 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAs // 2nd pass: Mark stencil buffer bits (0x80) with the result of the polygon ID // check. Bits are marked if the polygon ID of this polygon differs from the // one in the stencil buffer. - glStencilFunc(GL_NOTEQUAL, 0x80 | attr.polygonID, 0x3F); + glStencilFunc(GL_NOTEQUAL, 0x80 | thePoly.attribute.PolygonID, 0x3F); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilMask(0x80); } @@ -1912,12 +1908,12 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAs } else { - glStencilFunc(GL_ALWAYS, attr.polygonID, 0x3F); + glStencilFunc(GL_ALWAYS, thePoly.attribute.PolygonID, 0x3F); glStencilOp(GL_KEEP, GL_KEEP, (treatAsTranslucent) ? GL_KEEP : GL_REPLACE); glStencilMask(0xFF); // Drawing non-shadow polygons will implicitly reset the stencil buffer bits glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask((!treatAsTranslucent || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); + glDepthMask((!treatAsTranslucent || thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE); } } @@ -1934,11 +1930,9 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, size_t polyR return OGLERROR_NOERR; } - PolygonTexParams texParams = thePoly.getTexParams(); - glBindTexture(GL_TEXTURE_2D, theTexture->GetID()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (texParams.enableRepeatS ? (texParams.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (texParams.enableRepeatT ? (texParams.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ((thePoly.texParam.RepeatS_Enable) ? ((thePoly.texParam.MirroredRepeatS_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ((thePoly.texParam.RepeatT_Enable) ? ((thePoly.texParam.MirroredRepeatT_Enable) ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); if (this->_textureSmooth) { diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index b2d711e6d..d556d93ff 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -85,7 +85,7 @@ protected: virtual void GetExtensionSet(std::set *oglExtensionSet); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); - virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, u32 lastPolyAttr); + virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); virtual Render3DError DownsampleFBO(); virtual Render3DError ReadBackPixels(); virtual Render3DError BeginRender(const GFX3D &engine); diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index eff866171..91e93cfed 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -334,7 +334,10 @@ static CACHE_ALIGN u16 BTcoords[6] = {0, 0, 0, 0, 0, 0}; static CACHE_ALIGN float PTcoords[4] = {0.0, 0.0, 0.0, 1.0}; //raw ds format poly attributes -static u32 polyAttr=0,textureFormat=0, texturePalette=0, polyAttrPending=0; +static POLYGON_ATTR polyAttrInProcess; +static POLYGON_ATTR currentPolyAttr; +static TEXIMAGE_PARAM currentPolyTexParam; +static u32 currentPolyTexPalette = 0; //the current vertex color, 5bit values static u8 colorRGB[4] = { 31,31,31,31 }; @@ -351,11 +354,9 @@ static u8 shininessInd = 0; //-----------cached things: //these dont need to go into the savestate. they can be regenerated from HW registers //from polygonattr: -static unsigned int cullingMask=0; -static u32 envMode=0; static u32 lightMask=0; //other things: -static int texCoordinateTransform = 0; +static TextureTransformationMode texCoordTransformMode = TextureTransformationMode_None; static CACHE_ALIGN s32 cacheLightDirection[4][4]; static CACHE_ALIGN s32 cacheHalfVector[4][4]; //------------------ @@ -438,8 +439,8 @@ void POLY::save(EMUFILE &os) os.write_16LE(vertIndexes[1]); os.write_16LE(vertIndexes[2]); os.write_16LE(vertIndexes[3]); - os.write_32LE(polyAttr); - os.write_32LE(texParam); + os.write_32LE(attribute.value); + os.write_32LE(texParam.value); os.write_32LE(texPalette); os.write_32LE(viewport); os.write_floatLE(miny); @@ -456,8 +457,8 @@ void POLY::load(EMUFILE &is) is.read_16LE(vertIndexes[1]); is.read_16LE(vertIndexes[2]); is.read_16LE(vertIndexes[3]); - is.read_32LE(polyAttr); - is.read_32LE(texParam); + is.read_32LE(attribute.value); + is.read_32LE(texParam.value); is.read_32LE(texPalette); is.read_32LE(viewport); is.read_floatLE(miny); @@ -497,6 +498,10 @@ void VERT::load(EMUFILE &is) void gfx3d_init() { + polyAttrInProcess.value = 0; + currentPolyAttr.value = 0; + currentPolyTexParam.value = 0; + gxf_hardware.reset(); //gxf_hardware.test(); int zzz=9; @@ -584,10 +589,10 @@ void gfx3d_reset() gfx3d.vertList = vertList; gfx3d.vertListCount = vertListCount[listTwiddle]; - polyAttr = 0; - textureFormat = 0; - texturePalette = 0; - polyAttrPending = 0; + polyAttrInProcess.value = 0; + currentPolyAttr.value = 0; + currentPolyTexParam.value = 0; + currentPolyTexPalette = 0; mode = MATRIXMODE_PROJECTION; s16coord[0] = s16coord[1] = s16coord[2] = s16coord[3] = 0; coordind = 0; @@ -717,7 +722,7 @@ static void SetVertex() DS_ALIGN(16) s32 coordTransformed[4] = { coord[0], coord[1], coord[2], (1<<12) }; - if (texCoordinateTransform == 3) + if (texCoordTransformMode == TextureTransformationMode_VertexSource) { //Tested by: Eledees The Adventures of Kai and Zero (E) [title screen and frontend menus] last_s = (s32)(((s64)s16coord[0] * mtxCurrent[3][0] + @@ -869,7 +874,7 @@ static void SetVertex() // Line segment detect // Tested" Castlevania POR - warp stone, trajectory of ricochet, "Eye of Decay" - if (!(textureFormat & (7 << 26))) // no texture + if (currentPolyTexParam.PackedFormat == TEXMODE_NONE) { bool duplicated = false; const VERT &vert0 = vertList[poly.vertIndexes[0]]; @@ -889,9 +894,9 @@ static void SetVertex() } } - poly.polyAttr = polyAttr; - poly.texParam = textureFormat; - poly.texPalette = texturePalette; + poly.attribute = polyAttrInProcess; + poly.texParam = currentPolyTexParam; + poly.texPalette = currentPolyTexPalette; poly.viewport = viewport; polylist->count++; } @@ -901,18 +906,12 @@ static void SetVertex() static void gfx3d_glPolygonAttrib_cache() { // Light enable/disable - lightMask = (polyAttr&0xF); - - // texture environment - envMode = (polyAttr&0x30)>>4; - - // back face culling - cullingMask = (polyAttr>>6)&3; + lightMask = polyAttrInProcess.LightMask; } static void gfx3d_glTexImage_cache() { - texCoordinateTransform = (textureFormat>>30); + texCoordTransformMode = (TextureTransformationMode)currentPolyTexParam.TexCoordTransformMode; } static void gfx3d_glLightDirection_cache(const size_t index) @@ -1292,7 +1291,7 @@ static void gfx3d_glNormal(s32 v) CACHE_ALIGN s32 normal[4] = { nx,ny,nz,(1<<12) }; - if (texCoordinateTransform == 2) + if (texCoordTransformMode == TextureTransformationMode_NormalSource) { //SM64 highlight rendered star in main menu tests this //also smackdown 2010 player textures tested this (needed cast on _s and _t) @@ -1391,13 +1390,13 @@ static void gfx3d_glTexCoord(s32 val) _s = ((val<<16)>>16); _t = (val>>16); - if (texCoordinateTransform == 1) + if (texCoordTransformMode == TextureTransformationMode_TexCoordSource) { //dragon quest 4 overworld will test this last_s = (s32) (( (s64)_s * mtxCurrent[3][0] + (s64)_t * mtxCurrent[3][4] + (s64)mtxCurrent[3][8] + (s64)mtxCurrent[3][12])>>12); last_t = (s32) (( (s64)_s * mtxCurrent[3][1] + (s64)_t * mtxCurrent[3][5] + (s64)mtxCurrent[3][9] + (s64)mtxCurrent[3][13])>>12); } - else if(texCoordinateTransform == 0) + else if (texCoordTransformMode == TextureTransformationMode_None) { last_s=_s; last_t=_t; @@ -1469,20 +1468,20 @@ static void gfx3d_glPolygonAttrib (u32 val) //PROGINFO("Set polyattr in the middle of a begin/end pair.\n (This won't be activated until the next begin)\n"); //TODO - we need some some similar checking for teximageparam etc. } - polyAttrPending = val; + currentPolyAttr.value = val; GFX_DELAY(1); } static void gfx3d_glTexImage(u32 val) { - textureFormat = val; + currentPolyTexParam.value = val; gfx3d_glTexImage_cache(); GFX_DELAY(1); } static void gfx3d_glTexPalette(u32 val) { - texturePalette = val; + currentPolyTexPalette = val; GFX_DELAY(1); } @@ -1558,7 +1557,7 @@ static void gfx3d_glBegin(u32 v) triStripToggle = 0; tempVertInfo.count = 0; tempVertInfo.first = true; - polyAttr = polyAttrPending; + polyAttrInProcess = currentPolyAttr; gfx3d_glPolygonAttrib_cache(); GFX_DELAY(1); } @@ -2529,11 +2528,11 @@ void gfx3d_glGetLightColor(const size_t index, u32 &dst) SFORMAT SF_GFX3D[]={ { "GCTL", 4, 1, &gfx3d.state.savedDISP3DCNT}, - { "GPAT", 4, 1, &polyAttr}, - { "GPAP", 4, 1, &polyAttrPending}, + { "GPAT", 4, 1, &polyAttrInProcess.value}, + { "GPAP", 4, 1, ¤tPolyAttr.value}, { "GINB", 4, 1, &inBegin}, - { "GTFM", 4, 1, &textureFormat}, - { "GTPA", 4, 1, &texturePalette}, + { "GTFM", 4, 1, ¤tPolyTexParam.value}, + { "GTPA", 4, 1, ¤tPolyTexPalette}, { "GMOD", 4, 1, &mode}, { "GMTM", 4,16, mtxTemporal}, { "GMCU", 4,64, mtxCurrent}, diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index be0dec9be..afac5ed61 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -114,77 +114,6 @@ enum PolygonType POLYGON_TYPE_QUAD = 4 }; -// POLYGON ATTRIBUTES - BIT LOCATIONS -enum -{ - POLYGON_ATTR_ENABLE_LIGHT0_BIT = 0, - POLYGON_ATTR_ENABLE_LIGHT1_BIT = 1, - POLYGON_ATTR_ENABLE_LIGHT2_BIT = 2, - POLYGON_ATTR_ENABLE_LIGHT3_BIT = 3, - POLYGON_ATTR_MODE_BIT = 4, // Bits 4 - 5 - POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT = 6, - POLYGON_ATTR_ENABLE_FRONT_SURFACE_BIT = 7, - // Bits 8 - 10 unused - POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_BIT = 11, - POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_BIT = 12, - POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_BIT = 13, - POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_BIT = 14, - POLYGON_ATTR_ENABLE_FOG_BIT = 15, - POLYGON_ATTR_ALPHA_BIT = 16, // Bits 16 - 20 - // Bits 21 - 23 unused - POLYGON_ATTR_POLYGON_ID_BIT = 24 // Bits 24 - 29 - // Bits 30 - 31 unused -}; - -// POLYGON ATTRIBUTES - BIT MASKS -enum -{ - POLYGON_ATTR_ENABLE_LIGHT0_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT0_BIT, - POLYGON_ATTR_ENABLE_LIGHT1_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT1_BIT, - POLYGON_ATTR_ENABLE_LIGHT2_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT2_BIT, - POLYGON_ATTR_ENABLE_LIGHT3_MASK = 0x01 << POLYGON_ATTR_ENABLE_LIGHT3_BIT, - POLYGON_ATTR_MODE_MASK = 0x03 << POLYGON_ATTR_MODE_BIT, - POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK = 0x01 << POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT, - POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK = 0x01 << POLYGON_ATTR_ENABLE_FRONT_SURFACE_BIT, - POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_MASK= 0x01 << POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_BIT, - POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_MASK = 0x01 << POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_BIT, - POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_MASK = 0x01 << POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_BIT, - POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_MASK = 0x01 << POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_BIT, - POLYGON_ATTR_ENABLE_FOG_MASK = 0x01 << POLYGON_ATTR_ENABLE_FOG_BIT, - POLYGON_ATTR_ALPHA_MASK = 0x1F << POLYGON_ATTR_ALPHA_BIT, - POLYGON_ATTR_POLYGON_ID_MASK = 0x3F << POLYGON_ATTR_POLYGON_ID_BIT -}; - -// TEXTURE PARAMETERS - BIT LOCATIONS -enum -{ - TEXTURE_PARAM_VRAM_OFFSET_BIT = 0, // Bits 0 - 15 - TEXTURE_PARAM_ENABLE_REPEAT_S_BIT = 16, - TEXTURE_PARAM_ENABLE_REPEAT_T_BIT = 17, - TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_BIT = 18, - TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_BIT = 19, - TEXTURE_PARAM_SIZE_S_BIT = 20, // Bits 20 - 22 - TEXTURE_PARAM_SIZE_T_BIT = 23, // Bits 23 - 25 - TEXTURE_PARAM_FORMAT_BIT = 26, // Bits 26 - 28 - TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_BIT = 29, - TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT = 30 // Bits 30 - 31 -}; - -// TEXTURE PARAMETERS - BIT MASKS -enum -{ - TEXTURE_PARAM_VRAM_OFFSET_MASK = 0xFFFF << TEXTURE_PARAM_VRAM_OFFSET_BIT, - TEXTURE_PARAM_ENABLE_REPEAT_S_MASK = 0x01 << TEXTURE_PARAM_ENABLE_REPEAT_S_BIT, - TEXTURE_PARAM_ENABLE_REPEAT_T_MASK = 0x01 << TEXTURE_PARAM_ENABLE_REPEAT_T_BIT, - TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_MASK = 0x01 << TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_BIT, - TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_MASK = 0x01 << TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_BIT, - TEXTURE_PARAM_SIZE_S_MASK = 0x07 << TEXTURE_PARAM_SIZE_S_BIT, - TEXTURE_PARAM_SIZE_T_MASK = 0x07 << TEXTURE_PARAM_SIZE_T_BIT, - TEXTURE_PARAM_FORMAT_MASK = 0x07 << TEXTURE_PARAM_FORMAT_BIT, - TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_MASK = 0x01 << TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_BIT, - TEXTURE_PARAM_COORD_TRANSFORM_MODE_MASK = 0x03 << TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT -}; - // TEXTURE PARAMETERS - FORMAT ID enum NDSTextureFormat { @@ -198,6 +127,14 @@ enum NDSTextureFormat TEXMODE_16BPP = 7 }; +enum TextureTransformationMode +{ + TextureTransformationMode_None = 0, + TextureTransformationMode_TexCoordSource = 1, + TextureTransformationMode_NormalSource = 2, + TextureTransformationMode_VertexSource = 3 +}; + enum PolygonShadingMode { PolygonShadingMode_Toon = 0, @@ -208,48 +145,170 @@ void gfx3d_init(); void gfx3d_deinit(); void gfx3d_reset(); -typedef struct +typedef union { - u8 enableLightFlags; - bool enableLight0; - bool enableLight1; - bool enableLight2; - bool enableLight3; - PolygonMode polygonMode; - u8 surfaceCullingMode; - bool enableRenderBackSurface; - bool enableRenderFrontSurface; - bool enableAlphaDepthWrite; - bool enableRenderOnFarPlaneIntersect; - bool enableRenderOneDot; - bool enableDepthEqualTest; - bool enableRenderFog; - bool isWireframe; - bool isOpaque; - bool isTranslucent; - u8 alpha; - u8 polygonID; -} PolygonAttributes; + u32 value; + + struct + { +#ifndef MSB_FIRST + u8 Light0:1; // 0: Light 0; 0=Disable, 1=Enable + u8 Light1:1; // 1: Light 1; 0=Disable, 1=Enable + u8 Light2:1; // 2: Light 2; 0=Disable, 1=Enable + u8 Light3:1; // 3: Light 3; 0=Disable, 1=Enable + u8 Mode:2; // 4- 5: Polygon mode; + // 0=Low + // 1=Medium + // 2=High + // 3=Maximum + u8 BackSurface:1; // 6: Back surface; 0=Hide, 1=Render + u8 FrontSurface:1; // 7: Front surface; 0=Hide, 1=Render + + u8 :3; // 8-10: Unused bits + u8 TranslucentDepthWrite_Enable:1; // 11: Translucent depth write; 0=Keep 1=Replace + u8 FarPlaneIntersect_Enable:1; // 12: Far-plane intersecting polygons; 0=Hide, 1=Render/clipped + u8 OneDotPolygons_Enable:1; // 13: One-dot polygons; 0=Hide, 1=Render + u8 DepthEqualTest_Enable:1; // 14: Depth test mode; 0=Less, 1=Equal + u8 Fog_Enable:1; // 15: Fog; 0=Disable, 1=Enable + + u8 Alpha:5; // 16-20: Alpha value + u8 :3; // 21-23: Unused bits + + u8 PolygonID:6; // 24-29: Polygon ID + u8 :2; // 30-31: Unused bits +#else + u8 FrontSurface:1; // 7: Front surface; 0=Hide, 1=Render + u8 BackSurface:1; // 6: Back surface; 0=Hide, 1=Render + u8 Mode:2; // 4- 5: Polygon mode; + // 0=Low + // 1=Medium + // 2=High + // 3=Maximum + u8 Light3:1; // 3: Light 3; 0=Disable, 1=Enable + u8 Light2:1; // 2: Light 2; 0=Disable, 1=Enable + u8 Light1:1; // 1: Light 1; 0=Disable, 1=Enable + u8 Light0:1; // 0: Light 0; 0=Disable, 1=Enable + + u8 Fog_Enable:1; // 15: Fog; 0=Disable, 1=Enable + u8 DepthEqualTest_Enable:1; // 14: Depth test mode; 0=Less, 1=Equal + u8 OneDotPolygons_Enable:1; // 13: One-dot polygons; 0=Hide, 1=Render + u8 FarPlaneIntersect_Enable:1; // 12: Far-plane intersecting polygons; 0=Hide, 1=Render/clipped + u8 TranslucentDepthWrite_Enable:1; // 11: Translucent depth write; 0=Keep 1=Replace + u8 :3; // 8-10: Unused bits + + u8 :3; // 21-23: Unused bits + u8 Alpha:5; // 16-20: Alpha value + + u8 :2; // 30-31: Unused bits + u8 PolygonID:6; // 24-29: Polygon ID +#endif + }; + + struct + { +#ifndef MSB_FIRST + u8 LightMask:4; // 0- 3: Light enable mask + u8 :2; + u8 SurfaceCullingMode:2; // 6- 7: Surface culling mode; + // 0=Cull front and back + // 1=Cull front + // 2=Cull back + // 3=No culling + u8 :8; + u8 :8; + u8 :8; +#else + u8 SurfaceCullingMode:2; // 6- 7: Surface culling mode; + // 0=Cull front and back + // 1=Cull front + // 2=Cull back + // 3=No culling + u8 :2; + u8 LightMask:4; // 0- 3: Light enable mask + + u8 :8; + u8 :8; + u8 :8; +#endif + }; +} POLYGON_ATTR; -typedef struct +typedef union { - u16 VRAMOffset; - bool enableRepeatS; - bool enableRepeatT; - bool enableMirroredRepeatS; - bool enableMirroredRepeatT; - u8 sizeS; - u8 sizeT; - u8 texFormat; - bool enableTransparentColor0; - u8 coordTransformMode; -} PolygonTexParams; + u32 value; + + struct + { + u16 VRAMOffset:16; // 0-15: VRAM offset address + +#ifndef MSB_FIRST + u16 RepeatS_Enable:1; // 16: Repeat for S-coordinate; 0=Clamp 1=Repeat + u16 RepeatT_Enable:1; // 17: Repeat for T-coordinate; 0=Clamp 1=Repeat + u16 MirroredRepeatS_Enable:1; // 18: Mirrored repeat for S-coordinate, interacts with bit 16; 0=Disable 1=Enable + u16 MirroredRepeatT_Enable:1; // 19: Mirrored repeat for T-coordinate, interacts with bit 17; 0=Disable 1=Enable + u16 SizeShiftS:3; // 20-22: Texel size shift for S-coordinate; 0...7, where the actual texel size is (8 << N) + u16 SizeShiftT:3; // 23-25: Texel size shift for T-coordinate; 0...7, where the actual texel size is (8 << N) + u16 PackedFormat:3; // 26-28: Packed texture format; + // 0=None + // 1=A3I5, 5-bit indexed color with 3-bit alpha + // 2=I2, 2-bit indexed color (4-color palette) + // 3=I4, 4-bit indexed color (16-color palette) + // 4=I8, 8-bit indexed color (256-color palette) + // 5=4x4-texel compressed + // 6=A5I3, 3-bit indexed color with 5-bit alpha + // 7=Direct 16-bit color + u16 KeyColor0_Enable:1; // 29: Use palette color 0 as transparent; 0=Displayed 1=Transparent + u16 TexCoordTransformMode:2; // 30-31: Texture coordinate transformation mode; + // 0=No transformation + // 1=TexCoord source + // 2=Normal source + // 3=Vertex source +#else + u16 TexCoordTransformMode:2; // 30-31: Texture coordinate transformation mode; + // 0=No transformation + // 1=TexCoord source + // 2=Normal source + // 3=Vertex source + u16 KeyColor0_Enable:1; // 29: Use palette color 0 as transparent; 0=Displayed 1=Transparent + u16 PackedFormat:3; // 26-28: Packed texture format; + // 0=None + // 1=A3I5, 5-bit indexed color (32-color palette) with 3-bit alpha (0...7, where 0=Fully Transparent and 7=Opaque) + // 2=I2, 2-bit indexed color (4-color palette) + // 3=I4, 4-bit indexed color (16-color palette) + // 4=I8, 8-bit indexed color (256-color palette) + // 5=4x4-texel compressed + // 6=A5I3, 3-bit indexed color (8-color palette) with 5-bit alpha (0...31, where 0=Fully Transparent and 31=Opaque) + // 7=Direct 16-bit color + u16 SizeShiftT:3; // 23-25: Texel size shift for T-coordinate; 0...7, where the actual texel size is (8 << N) + u16 SizeShiftS:3; // 20-22: Texel size shift for S-coordinate; 0...7, where the actual texel size is (8 << N) + u16 MirroredRepeatT_Enable:1; // 19: Mirrored repeat for T-coordinate, interacts with bit 17; 0=Disable 1=Enable + u16 MirroredRepeatS_Enable:1; // 18: Mirrored repeat for S-coordinate, interacts with bit 16; 0=Disable 1=Enable + u16 RepeatT_Enable:1; // 17: Repeat for T-coordinate; 0=Clamp 1=Repeat + u16 RepeatS_Enable:1; // 16: Repeat for S-coordinate; 0=Clamp 1=Repeat +#endif + }; + + struct + { + u16 :16; + +#ifndef MSB_FIRST + u16 TextureWrapMode:4; // 16-19: Texture wrap mode for repeat and mirrored repeat + u16 :12; +#else + u16 :12; + u16 TextureWrapMode:4; // 16-19: Texture wrap mode for repeat and mirrored repeat +#endif + }; +} TEXIMAGE_PARAM; struct POLY { PolygonType type; //tri or quad PolygonPrimitiveType vtxFormat; u16 vertIndexes[4]; //up to four verts can be referenced by this poly - u32 polyAttr, texParam, texPalette; //the hardware rendering params + POLYGON_ATTR attribute; + TEXIMAGE_PARAM texParam; + u32 texPalette; //the hardware rendering params u32 viewport; float miny, maxy; @@ -262,193 +321,14 @@ struct POLY { else type = POLYGON_TYPE_TRIANGLE; } - u8 getAttributeEnableLightFlags() const - { - return ((polyAttr & (POLYGON_ATTR_ENABLE_LIGHT0_MASK | - POLYGON_ATTR_ENABLE_LIGHT1_MASK | - POLYGON_ATTR_ENABLE_LIGHT2_MASK | - POLYGON_ATTR_ENABLE_LIGHT3_MASK)) >> POLYGON_ATTR_ENABLE_LIGHT0_BIT); - } - - bool getAttributeEnableLight0() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT0_MASK) > 0); - } - - bool getAttributeEnableLight1() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT1_MASK) > 0); - } - - bool getAttributeEnableLight2() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT2_MASK) > 0); - } - - bool getAttributeEnableLight3() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_LIGHT3_MASK) > 0); - } - - PolygonMode getAttributePolygonMode() const - { - return (PolygonMode)((polyAttr & POLYGON_ATTR_MODE_MASK) >> POLYGON_ATTR_MODE_BIT); - } - - u8 getAttributeEnableFaceCullingFlags() const - { - return ((polyAttr & (POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK | - POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK)) >> POLYGON_ATTR_ENABLE_BACK_SURFACE_BIT); - } - - bool getAttributeEnableBackSurface() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_BACK_SURFACE_MASK) > 0); - } - - bool getAttributeEnableFrontSurface() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_FRONT_SURFACE_MASK) > 0); - } - - bool getAttributeEnableAlphaDepthWrite() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_ALPHA_DEPTH_WRITE_MASK) > 0); - } - - bool getAttributeEnableRenderOnFarPlaneIntersect() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_RENDER_ON_FAR_PLANE_INTERSECT_MASK) > 0); - } - - bool getAttributeEnableOneDotRender() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_ONE_DOT_RENDER_MASK) > 0); - } - - bool getAttributeEnableDepthEqualTest() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_DEPTH_EQUAL_TEST_MASK) > 0); - } - - bool getAttributeEnableFog() const - { - return ((polyAttr & POLYGON_ATTR_ENABLE_FOG_MASK) > 0); - } - - u8 getAttributeAlpha() const - { - return ((polyAttr & POLYGON_ATTR_ALPHA_MASK) >> POLYGON_ATTR_ALPHA_BIT); - } - - u8 getAttributePolygonID() const - { - return ((polyAttr & POLYGON_ATTR_POLYGON_ID_MASK) >> POLYGON_ATTR_POLYGON_ID_BIT); - } - - PolygonAttributes getAttributes() const - { - PolygonAttributes theAttr; - - theAttr.enableLightFlags = this->getAttributeEnableLightFlags(); - theAttr.enableLight0 = this->getAttributeEnableLight0(); - theAttr.enableLight1 = this->getAttributeEnableLight1(); - theAttr.enableLight2 = this->getAttributeEnableLight2(); - theAttr.enableLight3 = this->getAttributeEnableLight3(); - theAttr.polygonMode = this->getAttributePolygonMode(); - theAttr.surfaceCullingMode = this->getAttributeEnableFaceCullingFlags(); - theAttr.enableRenderBackSurface = this->getAttributeEnableBackSurface(); - theAttr.enableRenderFrontSurface = this->getAttributeEnableFrontSurface(); - theAttr.enableAlphaDepthWrite = this->getAttributeEnableAlphaDepthWrite(); - theAttr.enableRenderOnFarPlaneIntersect = this->getAttributeEnableRenderOnFarPlaneIntersect(); - theAttr.enableRenderOneDot = this->getAttributeEnableOneDotRender(); - theAttr.enableDepthEqualTest = this->getAttributeEnableDepthEqualTest(); - theAttr.enableRenderFog = this->getAttributeEnableFog(); - theAttr.alpha = this->getAttributeAlpha(); - theAttr.isWireframe = this->isWireframe(); - theAttr.isOpaque = this->isOpaque(); - theAttr.isTranslucent = this->isTranslucent(); - theAttr.polygonID = this->getAttributePolygonID(); - - return theAttr; - } - - u16 getTexParamVRAMOffset() const - { - return ((texParam & TEXTURE_PARAM_VRAM_OFFSET_MASK) >> TEXTURE_PARAM_VRAM_OFFSET_BIT); - } - - bool getTexParamEnableRepeatS() const - { - return ((texParam & TEXTURE_PARAM_ENABLE_REPEAT_S_MASK) > 0); - } - - bool getTexParamEnableRepeatT() const - { - return ((texParam & TEXTURE_PARAM_ENABLE_REPEAT_T_MASK) > 0); - } - - bool getTexParamEnableMirroredRepeatS() const - { - return ((texParam & TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_S_MASK) > 0); - } - - bool getTexParamEnableMirroredRepeatT() const - { - return ((texParam & TEXTURE_PARAM_ENABLE_MIRRORED_REPEAT_T_MASK) > 0); - } - - u8 getTexParamSizeS() const - { - return ((texParam & TEXTURE_PARAM_SIZE_S_MASK) >> TEXTURE_PARAM_SIZE_S_BIT); - } - - u8 getTexParamSizeT() const - { - return ((texParam & TEXTURE_PARAM_SIZE_T_MASK) >> TEXTURE_PARAM_SIZE_T_BIT); - } - - u8 getTexParamTexFormat() const - { - return ((texParam & TEXTURE_PARAM_FORMAT_MASK) >> TEXTURE_PARAM_FORMAT_BIT); - } - - bool getTexParamEnableTransparentColor0() const - { - return ((texParam & TEXTURE_PARAM_ENABLE_TRANSPARENT_COLOR0_MASK) > 0); - } - - u8 getTexParamCoordTransformMode() const - { - return ((texParam & TEXTURE_PARAM_COORD_TRANSFORM_MODE_MASK) >> TEXTURE_PARAM_COORD_TRANSFORM_MODE_BIT); - } - - PolygonTexParams getTexParams() const - { - PolygonTexParams theTexParams; - - theTexParams.VRAMOffset = this->getTexParamVRAMOffset(); - theTexParams.enableRepeatS = this->getTexParamEnableRepeatS(); - theTexParams.enableRepeatT = this->getTexParamEnableRepeatT(); - theTexParams.enableMirroredRepeatS = this->getTexParamEnableMirroredRepeatS(); - theTexParams.enableMirroredRepeatT = this->getTexParamEnableMirroredRepeatT(); - theTexParams.sizeS = this->getTexParamSizeS(); - theTexParams.sizeT = this->getTexParamSizeT(); - theTexParams.texFormat = this->getTexParamTexFormat(); - theTexParams.enableTransparentColor0 = this->getTexParamEnableTransparentColor0(); - theTexParams.coordTransformMode = this->getTexParamCoordTransformMode(); - - return theTexParams; - } - bool isWireframe() const { - return (this->getAttributeAlpha() == 0); + return (this->attribute.Alpha == 0); } bool isOpaque() const { - return (this->getAttributeAlpha() == 31); + return (this->attribute.Alpha == 31); } bool isTranslucent() const @@ -461,8 +341,8 @@ struct POLY { } // Also check for translucent texture format. - const u8 texFormat = this->getTexParamTexFormat(); - const PolygonMode mode = this->getAttributePolygonMode(); + const NDSTextureFormat texFormat = (NDSTextureFormat)this->texParam.PackedFormat; + const PolygonMode mode = (PolygonMode)this->attribute.Mode; //a5i3 or a3i5 -> translucent if ( (texFormat == TEXMODE_A3I5 || texFormat == TEXMODE_A5I3) && (mode != POLYGON_MODE_DECAL && mode != POLYGON_MODE_SHADOW) ) diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 5da48ad2b..c4e9b2aa2 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -380,7 +380,7 @@ public: return RENDER3DERROR_NOERR; } - this->_textureWrapMode = (thePoly.texParam >> 16) & 0x0F; + this->_textureWrapMode = thePoly.texParam.TextureWrapMode; theTexture->ResetCacheAge(); theTexture->IncreaseCacheUsageCount(1); @@ -508,7 +508,7 @@ public: } template - FORCEINLINE void pixel(const PolygonAttributes &polyAttr, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z) + FORCEINLINE void pixel(const POLYGON_ATTR polyAttr, const bool isTranslucent, const size_t fragmentIndex, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z) { FragmentColor srcColor; FragmentColor shaderOutput; @@ -530,7 +530,7 @@ public: // run the depth test bool depthFail = false; - if (polyAttr.enableDepthEqualTest) + if (polyAttr.DepthEqualTest_Enable) { const u32 minDepth = max(0x00000000, dstAttributeDepth - SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE); const u32 maxDepth = min(0x00FFFFFF, dstAttributeDepth + SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE); @@ -548,10 +548,10 @@ public: } } - if(depthFail) + if (depthFail) { //shadow mask polygons set stencil bit here - if (ISSHADOWPOLYGON && polyAttr.polygonID == 0) + if (ISSHADOWPOLYGON && polyAttr.PolygonID == 0) dstAttributeStencil=1; return; } @@ -559,7 +559,7 @@ public: //handle shadow polys if (ISSHADOWPOLYGON) { - if (polyAttr.polygonID == 0) + if (polyAttr.PolygonID == 0) { //shadow mask polygons only affect the stencil buffer, and then only when they fail depth test //if we made it here, the shadow mask polygon fragment needs to be trashed @@ -573,7 +573,7 @@ public: //draw only where stencil bit is set return; } - if (dstAttributeOpaquePolyID == polyAttr.polygonID) + if (dstAttributeOpaquePolyID == polyAttr.PolygonID) { //draw only when polygon ID differs //TODO: are we using the right dst polyID? @@ -596,10 +596,10 @@ public: srcColor = MakeFragmentColor(max(0x00, min(0x3F,u32floor(r))), max(0x00, min(0x3F,u32floor(g))), max(0x00, min(0x3F,u32floor(b))), - polyAttr.alpha); + polyAttr.Alpha); //pixel shader - shade(polyAttr.polygonMode, srcColor, shaderOutput, invu * w, invv * w); + shade((PolygonMode)polyAttr.Mode, srcColor, shaderOutput, invu * w, invv * w); // handle alpha test if ( shaderOutput.a == 0 || @@ -612,42 +612,42 @@ public: isOpaquePixel = (shaderOutput.a == 0x1F); if (isOpaquePixel) { - dstAttributeOpaquePolyID = polyAttr.polygonID; - dstAttributeIsTranslucentPoly = polyAttr.isTranslucent; - dstAttributeIsFogged = polyAttr.enableRenderFog; + dstAttributeOpaquePolyID = polyAttr.PolygonID; + dstAttributeIsTranslucentPoly = isTranslucent; + dstAttributeIsFogged = polyAttr.Fog_Enable; dstColor = shaderOutput; } else { //dont overwrite pixels on translucent polys with the same polyids - if (dstAttributeTranslucentPolyID == polyAttr.polygonID) + if (dstAttributeTranslucentPolyID == polyAttr.PolygonID) return; //originally we were using a test case of shadows-behind-trees in sm64ds //but, it looks bad in that game. this is actually correct //if this isnt correct, then complex shape cart shadows in mario kart don't work right - dstAttributeTranslucentPolyID = polyAttr.polygonID; + dstAttributeTranslucentPolyID = polyAttr.PolygonID; //alpha blending and write color alphaBlend(dstColor, shaderOutput); - dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.enableRenderFog); + dstAttributeIsFogged = (dstAttributeIsFogged && polyAttr.Fog_Enable); } //depth writing - if (isOpaquePixel || polyAttr.enableAlphaDepthWrite) + if (isOpaquePixel || polyAttr.TranslucentDepthWrite_Enable) dstAttributeDepth = newDepth; } //draws a single scanline - template - FORCEINLINE void drawscanline(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack) + template + FORCEINLINE void drawscanline(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight) { int XStart = pLeft->X; int width = pRight->X - XStart; // HACK: workaround for vertical/slant line poly - if (lineHack && width == 0) + if (USELINEHACK && width == 0) { int leftWidth = pLeft->XStep; if (pLeft->ErrorTerm + pLeft->Numerator >= pLeft->Denominator) @@ -699,7 +699,7 @@ public: if (x < 0) { - if (RENDERER && !lineHack) + if (RENDERER && !USELINEHACK) { printf("rasterizer rendering at x=%d! oops!\n",x); return; @@ -717,7 +717,7 @@ public: } if (x+width > framebufferWidth) { - if (RENDERER && !lineHack && framebufferWidth == GPU_FRAMEBUFFER_NATIVE_WIDTH) + if (RENDERER && !USELINEHACK && framebufferWidth == GPU_FRAMEBUFFER_NATIVE_WIDTH) { printf("rasterizer rendering at x=%d! oops!\n",x+width-1); return; @@ -727,7 +727,7 @@ public: while (width-- > 0) { - pixel(polyAttr, adr, dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z); + pixel(polyAttr, isTranslucent, adr, dstColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z); adr++; x++; @@ -742,44 +742,44 @@ public: } //runs several scanlines, until an edge is finished - template - void runscanlines(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack) + template + void runscanlines(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right) { //oh lord, hack city for edge drawing //do not overstep either of the edges int Height = min(left->Height,right->Height); - bool first=true; + bool first = true; //HACK: special handling for horizontal line poly - if (lineHack && left->Height == 0 && right->Height == 0 && left->YY>=0) + if (USELINEHACK && left->Height == 0 && right->Height == 0 && left->YY>=0) { bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); - if(draw) drawscanline(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack); + if (draw) drawscanline(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right); } - while(Height--) + while (Height--) { bool draw = (!SLI || (left->Y & SLI_MASK) == SLI_VALUE); - if(draw) drawscanline(polyAttr, dstColor, framebufferWidth, framebufferHeight, left,right,lineHack); + if (draw) drawscanline(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, left, right); const int xl = left->X; const int xr = right->X; const int y = left->Y; left->Step(); right->Step(); - if(!RENDERER && _debug_thisPoly) + if (!RENDERER && _debug_thisPoly) { //debug drawing - bool top = (horizontal&&first); - bool bottom = (!Height&&horizontal); - if(Height || top || bottom) + bool top = (ISHORIZONTAL && first); + bool bottom = (!Height && ISHORIZONTAL); + if (Height || top || bottom) { - if(draw) + if (draw) { int nxl = left->X; int nxr = right->X; - if(top) + if (top) { int xs = min(xl,xr); int xe = max(xl,xr); @@ -791,7 +791,7 @@ public: dstColor[adr].b = 0; } } - else if(bottom) + else if (bottom) { int xs = min(xl,xr); int xe = max(xl,xr); @@ -844,11 +844,11 @@ public: //rotate verts until vert0.y is minimum, and then vert0.x is minimum in case of ties //this is a necessary precondition for our shape engine - template - void sort_verts(bool backwards) + template + void sort_verts() { //if the verts are backwards, reorder them first - if (backwards) + if (ISBACKWARDS) for (size_t i = 0; i < TYPE/2; i++) swap(verts[i],verts[TYPE-i-1]); @@ -881,22 +881,22 @@ public: //verts must be clockwise. //I didnt reference anything for this algorithm but it seems like I've seen it somewhere before. //Maybe it is like crow's algorithm - template - void shape_engine(const PolygonAttributes &polyAttr, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type, const bool backwards, bool lineHack) + template + void shape_engine(const POLYGON_ATTR polyAttr, const bool isTranslucent, FragmentColor *dstColor, const size_t framebufferWidth, const size_t framebufferHeight, int type) { bool failure = false; - switch(type) + switch (type) { - case 3: sort_verts<3>(backwards); break; - case 4: sort_verts<4>(backwards); break; - case 5: sort_verts<5>(backwards); break; - case 6: sort_verts<6>(backwards); break; - case 7: sort_verts<7>(backwards); break; - case 8: sort_verts<8>(backwards); break; - case 9: sort_verts<9>(backwards); break; - case 10: sort_verts<10>(backwards); break; - default: printf("skipping type %d\n",type); return; + case 3: sort_verts(); break; + case 4: sort_verts(); break; + case 5: sort_verts(); break; + case 6: sort_verts(); break; + case 7: sort_verts(); break; + case 8: sort_verts(); break; + case 9: sort_verts(); break; + case 10: sort_verts(); break; + default: printf("skipping type %d\n", type); return; } //we are going to step around the polygon in both directions starting from vert 0. @@ -912,18 +912,25 @@ public: //generate new edges if necessary. we must avoid regenerating edges when they are incomplete //so that they can be continued on down the shape assert(rv != type); - int _lv = lv==type?0:lv; //make sure that we ask for vert 0 when the variable contains the starting value + int _lv = (lv == type) ? 0 : lv; //make sure that we ask for vert 0 when the variable contains the starting value if (step_left) left = edge_fx_fl(_lv,lv-1,(VERT**)&verts, failure); if (step_right) right = edge_fx_fl(rv,rv+1,(VERT**)&verts, failure); step_left = step_right = false; //handle a failure in the edge setup due to nutty polys - if(failure) + if (failure) return; - bool horizontal = left.Y == right.Y; - runscanlines(polyAttr, dstColor, framebufferWidth, framebufferHeight, &left, &right, horizontal, lineHack); - + const bool horizontal = (left.Y == right.Y); + if (horizontal) + { + runscanlines(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right); + } + else + { + runscanlines(polyAttr, isTranslucent, dstColor, framebufferWidth, framebufferHeight, &left, &right); + } + //if we ran out of an edge, step to the next one if (right.Height == 0) { @@ -937,11 +944,11 @@ public: } //this is our completion condition: when our stepped edges meet in the middle - if (lv<=rv+1) break; + if (lv <= rv+1) break; } } - template + template FORCEINLINE void mainLoop() { const size_t polyCount = this->_softRender->_clippedPolyCount; @@ -956,9 +963,8 @@ public: const GFX3D_Clipper::TClippedPoly &firstClippedPoly = this->_softRender->clippedPolys[0]; const POLY &firstPoly = *firstClippedPoly.poly; - PolygonAttributes polyAttr = firstPoly.getAttributes(); - u32 lastPolyAttr = firstPoly.polyAttr; - u32 lastTexParams = firstPoly.texParam; + POLYGON_ATTR polyAttr = firstPoly.attribute; + TEXIMAGE_PARAM lastTexParams = firstPoly.texParam; u32 lastTexPalette = firstPoly.texPalette; this->SetupTexture(firstPoly, 0); @@ -972,38 +978,78 @@ public: GFX3D_Clipper::TClippedPoly &clippedPoly = this->_softRender->clippedPolys[i]; const POLY &thePoly = *clippedPoly.poly; - const PolygonType type = clippedPoly.type; + const int vertCount = clippedPoly.type; + const bool useLineHack = USELINEHACK && (thePoly.vtxFormat & 4); - if (lastPolyAttr != thePoly.polyAttr) - { - polyAttr = thePoly.getAttributes(); - lastPolyAttr = thePoly.polyAttr; - } + polyAttr = thePoly.attribute; + const bool isTranslucent = thePoly.isTranslucent(); - if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette) + if (lastTexParams.value != thePoly.texParam.value || lastTexPalette != thePoly.texPalette) { lastTexParams = thePoly.texParam; lastTexPalette = thePoly.texPalette; this->SetupTexture(thePoly, i); } - for (int j = 0; j < type; j++) + for (int j = 0; j < vertCount; j++) this->verts[j] = &clippedPoly.clipVerts[j]; - for (int j = type; j < MAX_CLIPPED_VERTS; j++) + for (int j = vertCount; j < MAX_CLIPPED_VERTS; j++) this->verts[j] = NULL; - if (polyAttr.polygonMode == POLYGON_MODE_SHADOW) + if (!this->_softRender->polyBackfacing[i]) { - shape_engine(polyAttr, dstColor, dstWidth, dstHeight, type, !this->_softRender->polyBackfacing[i], (thePoly.vtxFormat & 4) && CommonSettings.GFX3D_LineHack); + if (polyAttr.Mode == POLYGON_MODE_SHADOW) + { + if (useLineHack) + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + else + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + } + else + { + if (useLineHack) + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + else + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + } } else { - shape_engine(polyAttr, dstColor, dstWidth, dstHeight, type, !this->_softRender->polyBackfacing[i], (thePoly.vtxFormat & 4) && CommonSettings.GFX3D_LineHack); + if (polyAttr.Mode == POLYGON_MODE_SHADOW) + { + if (useLineHack) + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + else + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + } + else + { + if (useLineHack) + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + else + { + shape_engine(polyAttr, isTranslucent, dstColor, dstWidth, dstHeight, vertCount); + } + } } } } - - + + }; //rasterizerUnit #define _MAX_CORES 16 @@ -1016,7 +1062,16 @@ static bool rasterizerUnitTasksInited = false; static void* execRasterizerUnit(void *arg) { intptr_t which = (intptr_t)arg; - rasterizerUnit[which].mainLoop(); + + if (CommonSettings.GFX3D_LineHack) + { + rasterizerUnit[which].mainLoop(); + } + else + { + rasterizerUnit[which].mainLoop(); + } + return 0; } @@ -1066,7 +1121,14 @@ static void* SoftRasterizer_RunRenderEdgeMarkAndFog(void *arg) void _HACK_Viewer_ExecUnit() { - _HACK_viewer_rasterizerUnit.mainLoop(); + if (CommonSettings.GFX3D_LineHack) + { + _HACK_viewer_rasterizerUnit.mainLoop(); + } + else + { + _HACK_viewer_rasterizerUnit.mainLoop(); + } } static Render3D* SoftRasterizerRendererCreate() @@ -1092,7 +1154,7 @@ static void SoftRasterizerRendererDestroy() } } -SoftRasterizerTexture::SoftRasterizerTexture(u32 texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes) +SoftRasterizerTexture::SoftRasterizerTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : Render3DTexture(texAttributes, palAttributes) { _cacheSize = GetUnpackSizeUsingFormat(TexFormat_15bpp); _unpackData = (u32 *)malloc_alignedCacheLine(_cacheSize); @@ -1599,7 +1661,7 @@ void SoftRasterizerRenderer::performBackfaceTests() const POLY &thePoly = *clippedPoly.poly; const PolygonType type = clippedPoly.type; const VERT *verts = &clippedPoly.clipVerts[0]; - const u8 cullingMode = thePoly.getAttributeEnableFaceCullingFlags(); + const u8 cullingMode = thePoly.attribute.SurfaceCullingMode; //HACK: backface culling //this should be moved to gfx3d, but first we need to redo the way the lists are built @@ -1714,7 +1776,15 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt } else { - rasterizerUnit[0].mainLoop(); + if (CommonSettings.GFX3D_LineHack) + { + rasterizerUnit[0].mainLoop(); + } + else + { + rasterizerUnit[0].mainLoop(); + } + this->_renderGeometryNeedsFinish = false; texCache.Evict(); // Since we're finishing geometry rendering here and now, also check the texture cache now. } diff --git a/desmume/src/rasterize.h b/desmume/src/rasterize.h index 6c197a7ea..52862de5e 100644 --- a/desmume/src/rasterize.h +++ b/desmume/src/rasterize.h @@ -63,7 +63,7 @@ protected: u32 _renderWidthShift; public: - SoftRasterizerTexture(u32 texAttributes, u32 palAttributes); + SoftRasterizerTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes); virtual ~SoftRasterizerTexture(); virtual void Load(); diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index 12154c21d..62fe429d0 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -193,7 +193,7 @@ void FragmentAttributesBuffer::SetAll(const FragmentAttributes &attr) } } -Render3DTexture::Render3DTexture(u32 texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes) +Render3DTexture::Render3DTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes) { _isSamplingEnabled = true; _useDeposterize = false; diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index 4f413042c..75096d97a 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -126,7 +126,7 @@ protected: template void _Upscale(const u32 *__restrict src, u32 *__restrict dst); public: - Render3DTexture(u32 texAttributes, u32 palAttributes); + Render3DTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes); bool IsSamplingEnabled() const; void SetSamplingEnabled(bool isEnabled); diff --git a/desmume/src/texcache.cpp b/desmume/src/texcache.cpp index 551e46a54..14ca0e34c 100644 --- a/desmume/src/texcache.cpp +++ b/desmume/src/texcache.cpp @@ -321,7 +321,7 @@ void TextureCache::ForceReloadAllTextures() } } -TextureStore* TextureCache::GetTexture(u32 texAttributes, u32 palAttributes) +TextureStore* TextureCache::GetTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes) { TextureStore *theTexture = NULL; const TextureCacheKey key = TextureCache::GenerateKey(texAttributes, palAttributes); @@ -364,16 +364,16 @@ void TextureCache::Remove(TextureStore *texItem) this->_actualCacheSize -= texItem->GetCacheSize(); } -TextureCacheKey TextureCache::GenerateKey(const u32 texAttributes, const u32 palAttributes) +TextureCacheKey TextureCache::GenerateKey(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes) { // Since the repeat, flip, and coordinate transformation modes are render settings // and not data settings, we can mask out those bits to help reduce duplicate entries. - return (TextureCacheKey)( ((u64)palAttributes << 32) | (u64)(texAttributes & 0x3FF0FFFF) ); + return (TextureCacheKey)( ((u64)palAttributes << 32) | (u64)(texAttributes.value & 0x3FF0FFFF) ); } TextureStore::TextureStore() { - _textureAttributes = 0; + _textureAttributes.value = 0; _paletteAttributes = 0; _cacheKey = 0; @@ -406,7 +406,7 @@ TextureStore::TextureStore() _cacheUsageCount = 0; } -TextureStore::TextureStore(const u32 texAttributes, const u32 palAttributes) +TextureStore::TextureStore(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes) { //for each texformat, multiplier from numtexels to numbytes (fixed point 30.2) static const u32 texSizes[] = {0, 4, 1, 2, 4, 1, 4, 8}; @@ -418,16 +418,16 @@ TextureStore::TextureStore(const u32 texAttributes, const u32 palAttributes) _paletteAttributes = palAttributes; _cacheKey = TextureCache::GenerateKey(texAttributes, palAttributes); - _sizeS = (8 << ((texAttributes >> 20) & 0x07)); - _sizeT = (8 << ((texAttributes >> 23) & 0x07)); + _sizeS = (8 << texAttributes.SizeShiftS); + _sizeT = (8 << texAttributes.SizeShiftT); - _packFormat = (NDSTextureFormat)((texAttributes >> 26) & 0x07); - _packAddress = (texAttributes & 0xFFFF) << 3; + _packFormat = (NDSTextureFormat)(texAttributes.PackedFormat); + _packAddress = texAttributes.VRAMOffset << 3; _packSize = (_sizeS * _sizeT * texSizes[_packFormat]) >> 2; //shifted because the texSizes multiplier is fixed point if ( (_packFormat == TEXMODE_I2) || (_packFormat == TEXMODE_I4) || (_packFormat == TEXMODE_I8) ) { - _isPalZeroTransparent = ( ((texAttributes >> 29) & 1) != 0 ); + _isPalZeroTransparent = (texAttributes.KeyColor0_Enable != 0); } else { @@ -439,8 +439,8 @@ TextureStore::TextureStore(const u32 texAttributes, const u32 palAttributes) if (_packFormat == TEXMODE_4X4) { - const u32 indexBase = ((texAttributes & 0xC000) == 0x8000) ? 0x30000 : 0x20000; - const u32 indexOffset = (texAttributes & 0x3FFF) << 2; + const u32 indexBase = ((texAttributes.VRAMOffset & 0xC000) == 0x8000) ? 0x30000 : 0x20000; + const u32 indexOffset = (texAttributes.VRAMOffset & 0x3FFF) << 2; _packIndexAddress = indexBase + indexOffset; _packIndexSize = (_sizeS * _sizeT) >> 3; @@ -502,7 +502,7 @@ TextureStore::~TextureStore() free_aligned(this->_packData); } -u32 TextureStore::GetTextureAttributes() const +TEXIMAGE_PARAM TextureStore::GetTextureAttributes() const { return this->_textureAttributes; } @@ -647,7 +647,7 @@ void TextureStore::Unpack(u32 *unpackBuffer) PROGINFO("Your 4x4 texture has overrun its texture slot.\n"); } - NDSTextureUnpack4x4(this->_packSizeFirstSlot, (u32 *)this->_packData, (u16 *)this->_packIndexData, this->_paletteAddress, this->_textureAttributes, this->_sizeS, this->_sizeT, unpackBuffer); + NDSTextureUnpack4x4(this->_packSizeFirstSlot, (u32 *)this->_packData, (u16 *)this->_packIndexData, this->_paletteAddress, this->_sizeS, this->_sizeT, unpackBuffer); break; } @@ -1164,7 +1164,7 @@ void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *__restrict srcData, co #define PAL4X4(offset) ( LE_TO_LOCAL_16( *(u16*)( MMU.texInfo.texPalSlot[((palAddress + (offset)*2)>>14)&0x7] + ((palAddress + (offset)*2)&0x3FFF) ) ) & 0x7FFF ) template -void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer) +void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer) { const u32 limit = srcSize * sizeof(u32); const u16 xTmpSize = sizeX >> 2; diff --git a/desmume/src/texcache.h b/desmume/src/texcache.h index 8978c6fdf..5cbf0338c 100644 --- a/desmume/src/texcache.h +++ b/desmume/src/texcache.h @@ -76,18 +76,18 @@ public: void Reset(); void ForceReloadAllTextures(); - TextureStore* GetTexture(u32 texAttributes, u32 palAttributes); + TextureStore* GetTexture(TEXIMAGE_PARAM texAttributes, u32 palAttributes); void Add(TextureStore *texItem); void Remove(TextureStore *texItem); - static TextureCacheKey GenerateKey(const u32 texAttributes, const u32 palAttributes); + static TextureCacheKey GenerateKey(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes); }; class TextureStore { protected: - u32 _textureAttributes; + TEXIMAGE_PARAM _textureAttributes; u32 _paletteAttributes; u32 _sizeS; @@ -123,10 +123,10 @@ protected: public: TextureStore(); - TextureStore(const u32 texAttributes, const u32 palAttributes); + TextureStore(const TEXIMAGE_PARAM texAttributes, const u32 palAttributes); virtual ~TextureStore(); - u32 GetTextureAttributes() const; + TEXIMAGE_PARAM GetTextureAttributes() const; u32 GetPaletteAttributes() const; u32 GetWidth() const; @@ -187,7 +187,7 @@ template void NDSTextureUnpackI4(const template void NDSTextureUnpackI8(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer); template void NDSTextureUnpackA3I5(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer); template void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer); -template void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 texAttributes, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer); +template void NDSTextureUnpack4x4(const size_t srcSize, const u32 *__restrict srcData, const u16 *__restrict srcIndex, const u32 palAddress, const u32 sizeX, const u32 sizeY, u32 *__restrict dstBuffer); template void NDSTextureUnpackDirect16Bit(const size_t srcSize, const u16 *__restrict srcData, u32 *__restrict dstBuffer); extern TextureCache texCache;