Merge branch 'master' into round-1-start

# Conflicts:
#	desmume/src/frontend/windows/DeSmuME.vcxproj.filters
#	desmume/src/libretro-common/rthreads/rthreads.c
#	desmume/src/texcache.cpp
#	desmume/src/utils/vfat.cpp
This commit is contained in:
zeromus 2016-11-23 21:13:34 -06:00
commit f97283e9bc
38 changed files with 3094 additions and 2269 deletions

View File

@ -18,14 +18,6 @@
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef FASTBUILD
#undef FORCEINLINE
#define FORCEINLINE
//compilation speed hack (cuts time exactly in half by cutting out permutations)
#define DISABLE_MOSAIC
#define DISABLE_COLOREFFECTDISABLEHINT
#endif
#include "GPU.h"
#include <assert.h>
@ -47,7 +39,13 @@
#include "matrix.h"
#include "emufile.h"
u32 Render3DFramesPerSecond;
#ifdef FASTBUILD
#undef FORCEINLINE
#define FORCEINLINE
//compilation speed hack (cuts time exactly in half by cutting out permutations)
#define DISABLE_MOSAIC
#define DISABLE_COLOREFFECTDISABLEHINT
#endif
//instantiate static instance
u16 GPUEngineBase::_brightnessUpTable555[17][0x8000];
@ -6759,6 +6757,11 @@ GPUSubsystem::GPUSubsystem()
_displayTouch = new NDSDisplay(NDSDisplayID_Touch);
_displayTouch->SetEngine(_engineSub);
_videoFrameCount = 0;
_render3DFrameCount = 0;
_frameNeedsFinish = false;
_willAutoApplyMasterBrightness = true;
_willAutoConvertRGB666ToRGB888 = true;
_willAutoResolveToCustomBuffer = true;
//TODO OSD
@ -6853,6 +6856,9 @@ void GPUSubsystem::Reset()
this->SetCustomFramebufferSize(this->_displayInfo.customWidth, this->_displayInfo.customHeight);
}
this->_videoFrameCount = 0;
this->_render3DFrameCount = 0;
this->ClearWithColor(0xFFFF);
this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main] = false;
@ -6883,19 +6889,30 @@ void GPUSubsystem::Reset()
}
void GPUSubsystem::ForceRender3DFinishAndFlush(bool willFlush)
{
bool need3DDisplayFramebuffer;
bool need3DCaptureFramebuffer;
CurrentRenderer->GetFramebufferFlushStates(need3DDisplayFramebuffer, need3DCaptureFramebuffer);
CurrentRenderer->SetFramebufferFlushStates(willFlush, willFlush);
CurrentRenderer->RenderFinish();
CurrentRenderer->SetFramebufferFlushStates(need3DDisplayFramebuffer, need3DCaptureFramebuffer);
}
void GPUSubsystem::ForceFrameStop()
{
if (CurrentRenderer->GetRenderNeedsFinish())
{
bool need3DDisplayFramebuffer;
bool need3DCaptureFramebuffer;
CurrentRenderer->GetFramebufferFlushStates(need3DDisplayFramebuffer, need3DCaptureFramebuffer);
CurrentRenderer->SetFramebufferFlushStates(willFlush, willFlush);
CurrentRenderer->RenderFinish();
CurrentRenderer->SetFramebufferFlushStates(need3DDisplayFramebuffer, need3DCaptureFramebuffer);
this->ForceRender3DFinishAndFlush(true);
CurrentRenderer->SetRenderNeedsFinish(false);
this->_event->DidRender3DEnd();
}
if (this->_frameNeedsFinish)
{
this->_frameNeedsFinish = false;
this->_event->DidFrameEnd(false);
}
}
void GPUSubsystem::UpdateRenderProperties()
@ -6981,6 +6998,11 @@ const NDSDisplayInfo& GPUSubsystem::GetDisplayInfo()
return this->_displayInfo;
}
u32 GPUSubsystem::GetFPSRender3D() const
{
return this->_render3DFrameCount;
}
void GPUSubsystem::SetDisplayDidCustomRender(NDSDisplayID displayID, bool theState)
{
this->_displayInfo.didPerformCustomRender[displayID] = theState;
@ -7023,8 +7045,6 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, void *clientNati
return;
}
GPU->ForceRender3DFinishAndFlush(false);
const float customWidthScale = (float)w / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
const float customHeightScale = (float)h / (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
const float newGpuLargestDstLineCount = (size_t)ceilf(customHeightScale);
@ -7165,8 +7185,6 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h)
void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat, void *clientNativeBuffer, void *clientCustomBuffer)
{
GPU->ForceRender3DFinishAndFlush(false);
this->_displayInfo.colorFormat = outputFormat;
this->_displayInfo.pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor);
@ -7291,6 +7309,26 @@ u16* GPUSubsystem::GetCustomVRAMAddressUsingMappedAddress(const u32 mappedAddr)
return (this->GetEngineMain()->GetCustomVRAMBlockPtr(blockID) + (_gpuCaptureLineIndex[blockLine] * this->_displayInfo.customWidth) + _gpuDstPitchIndex[linePixel]);
}
bool GPUSubsystem::GetWillAutoApplyMasterBrightness() const
{
return this->_willAutoApplyMasterBrightness;
}
void GPUSubsystem::SetWillAutoApplyMasterBrightness(const bool willAutoApply)
{
this->_willAutoApplyMasterBrightness = willAutoApply;
}
bool GPUSubsystem::GetWillAutoConvertRGB666ToRGB888() const
{
return this->_willAutoConvertRGB666ToRGB888;
}
void GPUSubsystem::SetWillAutoConvertRGB666ToRGB888(const bool willAutoConvert)
{
this->_willAutoConvertRGB666ToRGB888 = willAutoConvert;
}
bool GPUSubsystem::GetWillAutoResolveToCustomBuffer() const
{
return this->_willAutoResolveToCustomBuffer;
@ -7305,45 +7343,25 @@ template <NDSColorFormat OUTPUTFORMAT>
void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested)
{
const bool isDisplayCaptureNeeded = this->_engineMain->WillDisplayCapture(l);
const bool isFramebufferRenderNeeded[2] = {(CommonSettings.showGpu.main && !this->_engineMain->GetIsMasterBrightFullIntensity()) || isDisplayCaptureNeeded,
const bool isFramebufferRenderNeeded[2] = { CommonSettings.showGpu.main && !this->_engineMain->GetIsMasterBrightFullIntensity(),
CommonSettings.showGpu.sub && !this->_engineSub->GetIsMasterBrightFullIntensity() };
if (!this->_frameNeedsFinish)
{
this->_event->DidFrameBegin(isFrameSkipRequested);
this->_frameNeedsFinish = true;
}
if (l == 0)
{
this->_event->DidFrameBegin(isFrameSkipRequested);
// Clear displays to black if they are turned off by the user.
if (!isFrameSkipRequested)
{
this->UpdateRenderProperties();
if (!isFramebufferRenderNeeded[GPUEngineID_Main])
{
if (!CommonSettings.showGpu.main)
{
memset(this->_engineMain->renderedBuffer, 0, this->_engineMain->renderedWidth * this->_engineMain->renderedHeight * this->_displayInfo.pixelBytes);
}
else if (this->_engineMain->GetIsMasterBrightFullIntensity())
{
this->_engineMain->ApplyMasterBrightness<OUTPUTFORMAT, true>();
}
}
if (!isFramebufferRenderNeeded[GPUEngineID_Sub])
{
if (!CommonSettings.showGpu.sub)
{
memset(this->_engineSub->renderedBuffer, 0, this->_engineSub->renderedWidth * this->_engineSub->renderedHeight * this->_displayInfo.pixelBytes);
}
else if (this->_engineSub->GetIsMasterBrightFullIntensity())
{
this->_engineSub->ApplyMasterBrightness<OUTPUTFORMAT, true>();
}
}
}
}
if (isFramebufferRenderNeeded[GPUEngineID_Main] && !isFrameSkipRequested)
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || isDisplayCaptureNeeded) && !isFrameSkipRequested )
{
// GPUEngineA:WillRender3DLayer() and GPUEngineA:WillCapture3DLayerDirect() both rely on register
// states that might change on a per-line basis. Therefore, we need to check these states on a
@ -7387,6 +7405,17 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested)
if (l == 191)
{
this->_engineMain->FramebufferPostprocess();
this->_engineSub->FramebufferPostprocess();
this->_videoFrameCount++;
if (this->_videoFrameCount == 60)
{
this->_render3DFrameCount = gfx3d.render3DFrameCount;
gfx3d.render3DFrameCount = 0;
this->_videoFrameCount = 0;
}
if (!isFrameSkipRequested)
{
if (this->_displayInfo.isCustomSizeRequested)
@ -7405,17 +7434,42 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested)
this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedWidth;
this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_displayTouch->GetEngine()->renderedHeight;
if (isFramebufferRenderNeeded[GPUEngineID_Main])
if (this->_willAutoApplyMasterBrightness)
{
this->_engineMain->ApplyMasterBrightness<OUTPUTFORMAT, false>();
if (CommonSettings.showGpu.main)
{
if (this->_engineMain->GetIsMasterBrightFullIntensity())
{
this->_engineMain->ApplyMasterBrightness<OUTPUTFORMAT, true>();
}
else
{
this->_engineMain->ApplyMasterBrightness<OUTPUTFORMAT, false>();
}
}
else
{
memset(this->_engineMain->renderedBuffer, 0, this->_engineMain->renderedWidth * this->_engineMain->renderedHeight * this->_displayInfo.pixelBytes);
}
if (CommonSettings.showGpu.sub)
{
if (this->_engineSub->GetIsMasterBrightFullIntensity())
{
this->_engineSub->ApplyMasterBrightness<OUTPUTFORMAT, true>();
}
else
{
this->_engineSub->ApplyMasterBrightness<OUTPUTFORMAT, false>();
}
}
else
{
memset(this->_engineSub->renderedBuffer, 0, this->_engineSub->renderedWidth * this->_engineSub->renderedHeight * this->_displayInfo.pixelBytes);
}
}
if (isFramebufferRenderNeeded[GPUEngineID_Sub])
{
this->_engineSub->ApplyMasterBrightness<OUTPUTFORMAT, false>();
}
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
if ( (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev) && this->_willAutoConvertRGB666ToRGB888 )
{
this->_engineMain->ResolveRGB666ToRGB888();
this->_engineSub->ResolveRGB666ToRGB888();
@ -7428,18 +7482,11 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested)
}
}
this->_engineMain->FramebufferPostprocess();
this->_engineSub->FramebufferPostprocess();
gfx3d._videoFrameCount++;
if (gfx3d._videoFrameCount == 60)
if (this->_frameNeedsFinish)
{
Render3DFramesPerSecond = gfx3d.render3DFrameCount;
gfx3d.render3DFrameCount = 0;
gfx3d._videoFrameCount = 0;
this->_frameNeedsFinish = false;
this->_event->DidFrameEnd(isFrameSkipRequested);
}
this->_event->DidFrameEnd(isFrameSkipRequested);
}
}

View File

@ -1608,6 +1608,11 @@ private:
NDSDisplay *_displayMain;
NDSDisplay *_displayTouch;
u32 _videoFrameCount; // Internal variable that increments when a video frame is completed. Resets every 60 video frames.
u32 _render3DFrameCount; // The current 3D rendering frame count, saved to this variable once every 60 video frames.
bool _frameNeedsFinish;
bool _willAutoApplyMasterBrightness;
bool _willAutoConvertRGB666ToRGB888;
bool _willAutoResolveToCustomBuffer;
u16 *_customVRAM;
u16 *_customVRAMBlank;
@ -1628,7 +1633,11 @@ public:
void Reset();
void ForceRender3DFinishAndFlush(bool willFlush);
void ForceFrameStop();
const NDSDisplayInfo& GetDisplayInfo(); // Frontends need to call this whenever they need to read the video buffers from the emulator core
u32 GetFPSRender3D() const;
void SetDisplayDidCustomRender(NDSDisplayID displayID, bool theState);
GPUEngineA* GetEngineMain();
@ -1649,6 +1658,26 @@ public:
void UpdateRenderProperties();
// By default, the output framebuffer will have the master brightness applied before
// the DidFrameEnd event. The master brightness is applied using the CPU.
//
// To turn off this behavior, call SetWillAutoApplyMasterBrightness() and pass a value
// of "false". This can be useful if the client wants to apply the master brightness
// itself, for example, if a client applies it on the GPU.
bool GetWillAutoApplyMasterBrightness() const;
void SetWillAutoApplyMasterBrightness(const bool willAutoApply);
// By default, if the output framebuffer is in RGB666 format, then the framebuffers will
// automatically be converted to the much more common RGB888 format. This conversion is
// performed on the CPU.
//
// To turn off this behavior, call SetWillAutoConvertRGB666ToRGB888() and pass a value
// of "false". This can be useful if the client wants to do its own post-processing
// while the color format is still RGB666, or if the client wants to do its own custom
// conversion (such as converting the framebuffer later on the GPU).
bool GetWillAutoConvertRGB666ToRGB888() const;
void SetWillAutoConvertRGB666ToRGB888(const bool willAutoConvert);
// Normally, the GPUs will automatically resolve their native buffers to the master
// custom framebuffer at the end of V-blank so that all rendered graphics are contained
// within a single common buffer. This is necessary for when someone wants to read

View File

@ -88,15 +88,45 @@ libdesmume_a_SOURCES = \
utils/tinyxml/tinyxmlerror.cpp \
utils/tinyxml/tinyxmlparser.cpp \
utils/glcorearb.h \
addons/slot2_auto.cpp addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot2_passme.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1_retail_mcrom_debug.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp addons/slot1comp_protocol.h addons/slot1comp_protocol.cpp \
addons/slot2_auto.cpp \
addons/slot2_mpcf.cpp \
addons/slot2_paddle.cpp \
addons/slot2_gbagame.cpp \
addons/slot2_none.cpp \
addons/slot2_rumblepak.cpp \
addons/slot2_guitarGrip.cpp \
addons/slot2_expMemory.cpp \
addons/slot2_piano.cpp \
addons/slot2_passme.cpp \
addons/slot1_none.cpp \
addons/slot1_r4.cpp \
addons/slot1_retail_nand.cpp \
addons/slot1_retail_auto.cpp \
addons/slot1_retail_mcrom.cpp \
addons/slot1_retail_mcrom_debug.cpp \
addons/slot1comp_mc.cpp \
addons/slot1comp_mc.h \
addons/slot1comp_rom.h \
addons/slot1comp_rom.cpp \
addons/slot1comp_protocol.h \
addons/slot1comp_protocol.cpp \
cheatSystem.cpp cheatSystem.h \
texcache.cpp texcache.h rasterize.cpp rasterize.h \
metaspu/metaspu.cpp metaspu/metaspu.h \
filter/2xsai.cpp filter/bilinear.cpp filter/epx.cpp filter/filter.h \
filter/hq2x.cpp filter/hq2x.h \
filter/hq3x.cpp filter/hq3x.dat \
filter/hq4x.cpp filter/hq4x.dat \
filter/interp.h filter/lq2x.cpp filter/lq2x.h filter/scanline.cpp \
filter/2xsai.cpp \
filter/bilinear.cpp \
filter/deposterize.cpp \
filter/epx.cpp \
filter/filter.h \
filter/hq2x.cpp \
filter/hq2x.h \
filter/hq3x.cpp \
filter/hq3x.dat \
filter/hq4x.cpp \
filter/hq4x.dat \
filter/interp.h \
filter/lq2x.cpp filter/lq2x.h \
filter/scanline.cpp \
filter/videofilter.cpp filter/videofilter.h \
filter/xbrz.cpp filter/xbrz.h \
version.cpp version.h \
@ -110,18 +140,18 @@ libdesmume_a_SOURCES = \
libretro-common/rthreads/async_job.c \
libretro-common/rthreads/rsemaphore.c \
libretro-common/rthreads/rthreads.c
if SUPPORT_SSE2 += \
if SUPPORT_SSE2
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_SSE2.cpp
endif
if SUPPORT_AVX2 += \
if SUPPORT_AVX2
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_AVX2.cpp
endif
if SUPPORT_ALTIVEC += \
if SUPPORT_ALTIVEC
libdesmume_a_SOURCES += \
utils/colorspacehandler/colorspacehandler_AltiVec.cpp
endif

View File

@ -1391,8 +1391,8 @@ static void execHardware_hstart_vblankStart()
triggerDma(EDMAMode_VBlank);
//tracking for arm9 load average
nds.runCycleCollector[0][nds.idleFrameCounter] = 1120380-nds.idleCycles[0];
nds.runCycleCollector[1][nds.idleFrameCounter] = 1120380-nds.idleCycles[1];
nds.runCycleCollector[ARMCPU_ARM9][nds.idleFrameCounter] = 1120380-nds.idleCycles[0];
nds.runCycleCollector[ARMCPU_ARM7][nds.idleFrameCounter] = 1120380-nds.idleCycles[1];
nds.idleFrameCounter++;
nds.idleFrameCounter &= 15;
nds.idleCycles[0] = 0;
@ -2953,9 +2953,12 @@ void NDS_swapScreen()
}
void emu_halt() {
void emu_halt()
{
//printf("halting emu: ARM9 PC=%08X/%08X, ARM7 PC=%08X/%08X\n", NDS_ARM9.R[15], NDS_ARM9.instruct_adr, NDS_ARM7.R[15], NDS_ARM7.instruct_adr);
execute = false;
GPU->ForceFrameStop();
#ifdef LOG_ARM9
if (fp_dis9)
{

View File

@ -636,10 +636,42 @@ static void OGLGetDriverVersion(const char *oglVersionString,
}
}
void texDeleteCallback(TexCacheItem *texItem, void *param1, void *param2)
OpenGLTexture::OpenGLTexture()
{
OpenGLRenderer *oglRenderer = (OpenGLRenderer *)param1;
oglRenderer->DeleteTexture(texItem);
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_32bpp);
_invSizeS = 0.0f;
_invSizeT = 0.0f;
glGenTextures(1, &_texID);
}
OpenGLTexture::OpenGLTexture(u32 texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes)
{
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_32bpp);
_invSizeS = 1.0f / (float)_sizeS;
_invSizeT = 1.0f / (float)_sizeT;
glGenTextures(1, &_texID);
}
OpenGLTexture::~OpenGLTexture()
{
glDeleteTextures(1, &this->_texID);
}
GLuint OpenGLTexture::GetID() const
{
return this->_texID;
}
GLfloat OpenGLTexture::GetInvWidth() const
{
return this->_invSizeS;
}
GLfloat OpenGLTexture::GetInvHeight() const
{
return this->_invSizeT;
}
template<bool require_profile, bool enable_3_2>
@ -871,8 +903,8 @@ OpenGLRenderer::OpenGLRenderer()
ref->fboPostprocessID = 0;
ref->selectedRenderingFBO = 0;
currTexture = NULL;
_mappedFramebuffer = NULL;
_workingTextureUnpackBuffer = (FragmentColor *)malloc_alignedCacheLine(1024 * 1024 * sizeof(FragmentColor));
_pixelReadNeedsFinish = false;
_currentPolyIndex = 0;
_shadowPolyID.reserve(POLYLIST_SIZE);
@ -881,6 +913,7 @@ OpenGLRenderer::OpenGLRenderer()
OpenGLRenderer::~OpenGLRenderer()
{
free_aligned(_framebufferColor);
free_aligned(_workingTextureUnpackBuffer);
// Destroy OpenGL rendering states
delete ref;
@ -1196,14 +1229,7 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2()
DestroyMultisampledFBO();
// Kill the texture cache now before all of our texture IDs disappear.
TexCache_Reset();
while(!ref->freeTextureIDs.empty())
{
GLuint temp = ref->freeTextureIDs.front();
ref->freeTextureIDs.pop();
glDeleteTextures(1, &temp);
}
texCache.Reset();
glFinish();
}
@ -1351,7 +1377,6 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n");
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
@ -2062,13 +2087,6 @@ Render3DError OpenGLRenderer_1_2::InitFinalRenderStates(const std::set<std::stri
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::InitTextures()
{
this->ExpandFreeTextures();
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::InitTables()
{
static bool needTableInit = true;
@ -2227,20 +2245,6 @@ void OpenGLRenderer_1_2::GetExtensionSet(std::set<std::string> *oglExtensionSet)
}
}
Render3DError OpenGLRenderer_1_2::ExpandFreeTextures()
{
static const GLsizei kInitTextures = 128;
GLuint oglTempTextureID[kInitTextures];
glGenTextures(kInitTextures, oglTempTextureID);
for(GLsizei i = 0; i < kInitTextures; i++)
{
this->ref->freeTextureIDs.push(oglTempTextureID[i]);
}
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::EnableVertexAttributes()
{
OGLRenderRef &OGLRef = *this->ref;
@ -2415,17 +2419,6 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::DeleteTexture(const TexCacheItem *item)
{
this->ref->freeTextureIDs.push((GLuint)item->texid);
if(this->currTexture == item)
{
this->currTexture = NULL;
}
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
{
OGLRenderRef &OGLRef = *this->ref;
@ -2694,7 +2687,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount)
{
//needs to happen before endgl because it could free some textureids for expired cache items
TexCache_EvictFrame();
texCache.Evict();
this->ReadBackPixels();
@ -2955,122 +2948,142 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableT
return OGLERROR_NOERR;
}
OpenGLTexture *theTexture = (OpenGLTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
const bool isNewTexture = (theTexture == NULL);
if (isNewTexture)
{
theTexture = new OpenGLTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(theTexture);
}
const NDSTextureFormat packFormat = theTexture->GetPackFormat();
// Enable textures if they weren't already enabled
if (this->isShaderSupported)
{
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (params.texFormat != TEXMODE_A3I5 && params.texFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glUniform2f(OGLRef.uniformPolyTexScale, theTexture->GetInvWidth(), theTexture->GetInvHeight());
}
else
{
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(theTexture->GetInvWidth(), theTexture->GetInvHeight(), 1.0f);
}
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if(newTexture != this->currTexture)
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (theTexture->IsLoadNeeded())
{
this->currTexture = newTexture;
//has the ogl renderer initialized the texture?
if(this->currTexture->GetDeleteCallback() == NULL)
theTexture->Unpack<TexFormat_32bpp>((u32 *)this->_workingTextureUnpackBuffer);
const u32 *textureSrc = (u32 *)this->_workingTextureUnpackBuffer;
size_t texWidth = theTexture->GetWidth();
size_t texHeight = theTexture->GetHeight();
if (this->_textureDeposterizeDstSurface.Surface != NULL)
{
this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
if(OGLRef.freeTextureIDs.empty())
{
this->ExpandFreeTextures();
}
this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = this->currTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->currTexture->decoded;
size_t texWidth = this->currTexture->sizeX;
size_t texHeight = this->currTexture->sizeY;
if (this->_textureDeposterizeBuffer != NULL)
{
this->TextureDeposterize(textureSrc, texWidth, texHeight);
textureSrc = this->_textureDeposterizeBuffer;
}
switch (this->_textureScalingFactor)
{
case 1:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
case 2:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, this->currTexture->sizeX, this->currTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
}
case 4:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
texWidth = this->currTexture->sizeX;
texHeight = this->currTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, this->currTexture->sizeX, this->currTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
}
default:
break;
}
if (this->_textureSmooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (this->_textureScalingFactor > 1) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->_deviceInfo.maxAnisotropy);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
}
else
{
//otherwise, just bind it
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
this->TextureDeposterize(textureSrc, texWidth, texHeight);
textureSrc = (u32 *)this->_textureDeposterizeDstSurface.Surface;
}
if (this->isShaderSupported)
switch (this->_textureScalingFactor)
{
glUniform2f(OGLRef.uniformPolyTexScale, this->currTexture->invSizeX, this->currTexture->invSizeY);
case 1:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
case 2:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
case 4:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
default:
break;
}
if (this->_textureSmooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (this->_textureScalingFactor > 1) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->_deviceInfo.maxAnisotropy);
}
else
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(this->currTexture->invSizeX, this->currTexture->invSizeY, 1.0f);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
}
theTexture->ResetCacheAge();
theTexture->IncreaseCacheUsageCount(1);
return OGLERROR_NOERR;
}
@ -3121,7 +3134,6 @@ Render3DError OpenGLRenderer_1_2::Reset()
memset(OGLRef.vertIndexBuffer, 0, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort));
}
this->currTexture = NULL;
this->_currentPolyIndex = 0;
OGLRef.vtxPtrPosition = (GLvoid *)offsetof(VERT, coord);
@ -3133,7 +3145,7 @@ Render3DError OpenGLRenderer_1_2::Reset()
memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer));
memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer));
TexCache_Reset();
texCache.Reset();
return OGLERROR_NOERR;
}
@ -3838,7 +3850,6 @@ Render3DError OpenGLRenderer_2_0::InitExtensions()
INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n");
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
@ -4615,104 +4626,130 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableT
return OGLERROR_NOERR;
}
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (params.texFormat != TEXMODE_A3I5 && params.texFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
OpenGLTexture *theTexture = (OpenGLTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
const bool isNewTexture = (theTexture == NULL);
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if(newTexture != this->currTexture)
if (isNewTexture)
{
this->currTexture = newTexture;
//has the ogl renderer initialized the texture?
if(this->currTexture->GetDeleteCallback() == NULL)
theTexture = new OpenGLTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(theTexture);
}
const NDSTextureFormat packFormat = theTexture->GetPackFormat();
glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
glUniform1i(OGLRef.uniformTexSingleBitAlpha, (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? GL_TRUE : GL_FALSE);
glUniform2f(OGLRef.uniformPolyTexScale, theTexture->GetInvWidth(), theTexture->GetInvHeight());
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (theTexture->IsLoadNeeded())
{
theTexture->Unpack<TexFormat_32bpp>((u32 *)this->_workingTextureUnpackBuffer);
const u32 *textureSrc = (u32 *)this->_workingTextureUnpackBuffer;
size_t texWidth = theTexture->GetWidth();
size_t texHeight = theTexture->GetHeight();
if (this->_textureDeposterizeDstSurface.Surface != NULL)
{
this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
if(OGLRef.freeTextureIDs.empty())
this->TextureDeposterize(textureSrc, texWidth, texHeight);
textureSrc = (u32 *)this->_textureDeposterizeDstSurface.Surface;
}
switch (this->_textureScalingFactor)
{
case 1:
{
this->ExpandFreeTextures();
}
this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = this->currTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->currTexture->decoded;
size_t texWidth = this->currTexture->sizeX;
size_t texHeight = this->currTexture->sizeY;
if (this->_textureDeposterizeBuffer != NULL)
{
this->TextureDeposterize(textureSrc, texWidth, texHeight);
textureSrc = this->_textureDeposterizeBuffer;
}
switch (this->_textureScalingFactor)
{
case 1:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
case 2:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
if (isNewTexture)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, this->currTexture->sizeX, this->currTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
case 4:
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
texWidth = this->currTexture->sizeX;
texHeight = this->currTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, this->currTexture->sizeX, this->currTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
case 2:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
case 4:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
default:
break;
}
if (this->_textureSmooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (this->_textureScalingFactor > 1) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->_deviceInfo.maxAnisotropy);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
default:
break;
}
if (this->_textureSmooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (this->_textureScalingFactor > 1) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->_deviceInfo.maxAnisotropy);
}
else
{
//otherwise, just bind it
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
glUniform2f(OGLRef.uniformPolyTexScale, this->currTexture->invSizeX, this->currTexture->invSizeY);
}
theTexture->ResetCacheAge();
theTexture->IncreaseCacheUsageCount(1);
return OGLERROR_NOERR;
}

View File

@ -24,6 +24,7 @@
#include <set>
#include <string>
#include "render3D.h"
#include "texcache.h"
#include "types.h"
#ifndef OGLRENDER_3_2_H
@ -491,9 +492,6 @@ struct OGLRenderRef
GLuint vaoGeometryStatesID;
GLuint vaoPostprocessStatesID;
// Textures
std::queue<GLuint> freeTextureIDs;
// Client-side Buffers
GLfloat *color4fBuffer;
GLushort *vertIndexBuffer;
@ -526,8 +524,6 @@ extern CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64];
extern const GLfloat PostprocessVtxBuffer[16];
extern const GLubyte PostprocessElementBuffer[6];
extern void texDeleteCallback(TexCacheItem *texItem, void *param1, void *param2);
//This is called by OGLRender whenever it initializes.
//Platforms, please be sure to set this up.
//return true if you successfully init.
@ -559,6 +555,23 @@ extern void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr);
bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision);
class OpenGLTexture : public TextureStore
{
private:
GLuint _texID;
GLfloat _invSizeS;
GLfloat _invSizeT;
public:
OpenGLTexture();
OpenGLTexture(u32 texAttributes, u32 palAttributes);
virtual ~OpenGLTexture();
GLuint GetID() const;
GLfloat GetInvWidth() const;
GLfloat GetInvHeight() const;
};
#if defined(ENABLE_SSE2)
class OpenGLRenderer : public Render3D_SSE2
#else
@ -587,11 +600,9 @@ protected:
bool isVAOSupported;
bool willFlipFramebufferOnGPU;
bool willConvertFramebufferOnGPU;
// Textures
TexCacheItem *currTexture;
FragmentColor *_mappedFramebuffer;
FragmentColor *_workingTextureUnpackBuffer;
bool _pixelReadNeedsFinish;
size_t _currentPolyIndex;
std::vector<u8> _shadowPolyID;
@ -611,7 +622,6 @@ protected:
virtual void DestroyGeometryProgram() = 0;
virtual Render3DError CreateVAOs() = 0;
virtual void DestroyVAOs() = 0;
virtual Render3DError InitTextures() = 0;
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError InitTables() = 0;
virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader,
@ -637,7 +647,6 @@ protected:
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer) = 0;
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError ExpandFreeTextures() = 0;
virtual Render3DError EnableVertexAttributes() = 0;
virtual Render3DError DisableVertexAttributes() = 0;
virtual Render3DError DownsampleFBO() = 0;
@ -650,7 +659,6 @@ public:
virtual ~OpenGLRenderer();
virtual Render3DError InitExtensions() = 0;
virtual Render3DError DeleteTexture(const TexCacheItem *item) = 0;
bool IsExtensionPresent(const std::set<std::string> *oglExtensionSet, const std::string extensionName) const;
bool ValidateShaderCompile(GLuint theShader) const;
@ -675,7 +683,6 @@ protected:
virtual void DestroyMultisampledFBO();
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError InitTextures();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError InitTables();
@ -704,7 +711,6 @@ protected:
virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError ExpandFreeTextures();
virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes();
virtual Render3DError DownsampleFBO();
@ -731,8 +737,6 @@ public:
virtual Render3DError Reset();
virtual Render3DError RenderFinish();
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
virtual Render3DError DeleteTexture(const TexCacheItem *item);
};
class OpenGLRenderer_1_3 : public OpenGLRenderer_1_2

View File

@ -609,7 +609,6 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
}
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
@ -1686,7 +1685,6 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly)
Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableTexturing)
{
OGLRenderRef &OGLRef = *this->ref;
const PolygonTexParams params = thePoly.getTexParams();
// Check if we need to use textures
@ -1695,99 +1693,125 @@ Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableT
return OGLERROR_NOERR;
}
TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
if(newTexture != this->currTexture)
OpenGLTexture *theTexture = (OpenGLTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
const bool isNewTexture = (theTexture == NULL);
if (isNewTexture)
{
this->currTexture = newTexture;
//has the ogl renderer initialized the texture?
if(this->currTexture->GetDeleteCallback() == NULL)
theTexture = new OpenGLTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(theTexture);
}
glBindTexture(GL_TEXTURE_2D, theTexture->GetID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
if (theTexture->IsLoadNeeded())
{
theTexture->Unpack<TexFormat_32bpp>((u32 *)this->_workingTextureUnpackBuffer);
const u32 *textureSrc = (u32 *)this->_workingTextureUnpackBuffer;
const NDSTextureFormat packFormat = theTexture->GetPackFormat();
size_t texWidth = theTexture->GetWidth();
size_t texHeight = theTexture->GetHeight();
if (this->_textureDeposterizeDstSurface.Surface != NULL)
{
this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
if(OGLRef.freeTextureIDs.empty())
this->TextureDeposterize(textureSrc, texWidth, texHeight);
textureSrc = (u32 *)this->_textureDeposterizeDstSurface.Surface;
}
switch (this->_textureScalingFactor)
{
case 1:
{
this->ExpandFreeTextures();
}
this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
OGLRef.freeTextureIDs.pop();
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
const NDSTextureFormat texFormat = this->currTexture->GetTextureFormat();
const u32 *textureSrc = (u32 *)this->currTexture->decoded;
size_t texWidth = this->currTexture->sizeX;
size_t texHeight = this->currTexture->sizeY;
if (this->_textureDeposterizeBuffer != NULL)
{
this->TextureDeposterize(textureSrc, texWidth, texHeight);
textureSrc = this->_textureDeposterizeBuffer;
}
switch (this->_textureScalingFactor)
{
case 1:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
case 2:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
if (isNewTexture)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, this->currTexture->sizeX, this->currTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
case 4:
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
texWidth = this->currTexture->sizeX;
texHeight = this->currTexture->sizeY;
this->TextureUpscale<2>(texFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, this->currTexture->sizeX, this->currTexture->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
break;
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
case 2:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
case 4:
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 2);
this->TextureUpscale<4>(packFormat, textureSrc, texWidth, texHeight);
if (isNewTexture)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
default:
break;
}
if (this->_textureSmooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (this->_textureScalingFactor > 1) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->_deviceInfo.maxAnisotropy);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, theTexture->GetWidth(), theTexture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
texWidth = theTexture->GetWidth();
texHeight = theTexture->GetHeight();
this->TextureUpscale<2>(packFormat, textureSrc, texWidth, texHeight);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, this->_textureUpscaleBuffer);
glTexSubImage2D(GL_TEXTURE_2D, 2, 0, 0, theTexture->GetWidth(), theTexture->GetHeight(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, textureSrc);
}
break;
}
default:
break;
}
if (this->_textureSmooth)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (this->_textureScalingFactor > 1) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->_deviceInfo.maxAnisotropy);
}
else
{
//otherwise, just bind it
glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
}
}
theTexture->ResetCacheAge();
theTexture->IncreaseCacheUsageCount(1);
return OGLERROR_NOERR;
}

View File

@ -796,8 +796,11 @@ void SPU_struct::WriteByte(u32 addr, u8 val)
regs.ctl_ch1bypass = (val >> 4) & 1;
regs.ctl_ch3bypass = (val >> 5) & 1;
regs.masteren = (val >> 7) & 1;
for(u8 i=0; i<16; i++)
KeyProbe(i);
//from r4925 - after changing 'masteren', we retrigger any sounds? doubtful.
//maybe we STOP sounds here, but we don't enable them (this would retrigger any previous sounds that had finished; glitched AC:WW)
//(probably broken in r3299)
//after commenting this out, I checked bug #1356. seems unrelated.
//for(int i=0; i<16; i++) KeyProbe(i);
break;
//SOUNDBIAS

View File

@ -112,6 +112,10 @@
AB2EE13117D57F5000F68622 /* fsnitro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB2EE13017D57F5000F68622 /* fsnitro.cpp */; };
AB2EE13217D57F5000F68622 /* fsnitro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB2EE13017D57F5000F68622 /* fsnitro.cpp */; };
AB2EE13317D57F5000F68622 /* fsnitro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB2EE13017D57F5000F68622 /* fsnitro.cpp */; };
AB301BDF1D9C8BAC00246A93 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB301BDE1D9C8BAC00246A93 /* deposterize.cpp */; };
AB301BE01D9C8BCD00246A93 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB301BDE1D9C8BAC00246A93 /* deposterize.cpp */; };
AB301BE11D9C8BCE00246A93 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB301BDE1D9C8BAC00246A93 /* deposterize.cpp */; };
AB301BE21D9C8BCF00246A93 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB301BDE1D9C8BAC00246A93 /* deposterize.cpp */; };
AB350BA51478AC96007165AC /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB350BA41478AC96007165AC /* IOKit.framework */; };
AB350D3B147A1D93007165AC /* HID_usage_strings.plist in Resources */ = {isa = PBXBuildFile; fileRef = AB350D3A147A1D93007165AC /* HID_usage_strings.plist */; };
AB3701E5173A3FBF006E573E /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB74EC891738499C0026C41E /* Carbon.framework */; };
@ -1323,6 +1327,7 @@
AB2EE12B17D57ED500F68622 /* slot1_retail_mcrom_debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot1_retail_mcrom_debug.cpp; sourceTree = "<group>"; };
AB2EE12F17D57F5000F68622 /* fsnitro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fsnitro.h; sourceTree = "<group>"; };
AB2EE13017D57F5000F68622 /* fsnitro.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fsnitro.cpp; sourceTree = "<group>"; };
AB301BDE1D9C8BAC00246A93 /* deposterize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = deposterize.cpp; sourceTree = "<group>"; };
AB350BA41478AC96007165AC /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
AB350D38147A1D8D007165AC /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = English; path = translations/English.lproj/HID_usage_strings.plist; sourceTree = "<group>"; };
AB3A655C16CC5416001F5D4A /* EmuControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmuControllerDelegate.h; sourceTree = "<group>"; };
@ -2924,6 +2929,7 @@
children = (
ABFE14FA14C92FF5005D6699 /* 2xsai.cpp */,
ABFE14FB14C92FF5005D6699 /* bilinear.cpp */,
AB301BDE1D9C8BAC00246A93 /* deposterize.cpp */,
ABFE14FC14C92FF5005D6699 /* epx.cpp */,
ABFE14FE14C92FF5005D6699 /* hq2x.cpp */,
AB4C81E31B21676C00ACECD5 /* hq3x.cpp */,
@ -3845,6 +3851,7 @@
ABD1041C1346652500AF11D1 /* cocoa_input.mm in Sources */,
AB3E34C9134AF4500056477A /* cocoa_output.mm in Sources */,
ABFEA8CB1BB4EC1100B08C25 /* smooth.c in Sources */,
AB301BE11D9C8BCE00246A93 /* deposterize.cpp in Sources */,
ABD1041E1346652500AF11D1 /* cocoa_rom.mm in Sources */,
AB80E04D142BC4A800A52038 /* cocoa_util.mm in Sources */,
ABE5DFE5143FB1DA00835AD8 /* cocoa_videofilter.mm in Sources */,
@ -3949,6 +3956,7 @@
AB796CF815CDCBA200C59155 /* cp15.cpp in Sources */,
AB796CF915CDCBA200C59155 /* cpu_detect_x86_gcc.cpp in Sources */,
AB796CFA15CDCBA200C59155 /* crc.cpp in Sources */,
AB301BDF1D9C8BAC00246A93 /* deposterize.cpp in Sources */,
AB796CFB15CDCBA200C59155 /* datetime.cpp in Sources */,
AB796CFC15CDCBA200C59155 /* debug.cpp in Sources */,
ABFEA82E1BB4EC1100B08C25 /* ftlcdfil.c in Sources */,
@ -4155,6 +4163,7 @@
ABFEA8361BB4EC1100B08C25 /* ftmm.c in Sources */,
ABFEA81E1BB4EC1000B08C25 /* ftfstype.c in Sources */,
ABA731601BB51E7000B26147 /* pshinter.c in Sources */,
AB301BE01D9C8BCD00246A93 /* deposterize.cpp in Sources */,
ABFEA8211BB4EC1000B08C25 /* ftgasp.c in Sources */,
ABFEA83C1BB4EC1100B08C25 /* ftotval.c in Sources */,
ABFEA8181BB4EC1000B08C25 /* ftdebug.c in Sources */,
@ -4446,6 +4455,7 @@
ABB3C6B81501C04F00E0C22E /* common.cpp in Sources */,
ABB3C6B91501C04F00E0C22E /* cp15.cpp in Sources */,
AB407F371A6206FB00313213 /* xbrz.cpp in Sources */,
AB301BE21D9C8BCF00246A93 /* deposterize.cpp in Sources */,
ABB3C6BA1501C04F00E0C22E /* debug.cpp in Sources */,
ABB3C6BB1501C04F00E0C22E /* Disassembler.cpp in Sources */,
ABB3C6BC1501C04F00E0C22E /* driver.cpp in Sources */,
@ -4575,13 +4585,13 @@
buildSettings = {
GCC_OPTIMIZATION_LEVEL = fast;
GCC_UNROLL_LOOPS = YES;
LLVM_LTO = YES_THIN;
};
name = Debug;
};
AB796D6F15CDCBA200C59155 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_OPTIMIZATION_LEVEL = fast;
GCC_UNROLL_LOOPS = YES;
LLVM_LTO = YES;
};

View File

@ -1418,6 +1418,11 @@
ABB9212317CEB4110049D4C5 /* slot1comp_protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABB9212017CEB4110049D4C5 /* slot1comp_protocol.cpp */; };
ABB9212417CEB4110049D4C5 /* slot1comp_protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABB9212017CEB4110049D4C5 /* slot1comp_protocol.cpp */; };
ABB9212517CEB4110049D4C5 /* slot1comp_protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABB9212017CEB4110049D4C5 /* slot1comp_protocol.cpp */; };
ABBB4ACD1D9C927C00794E08 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBB4ACC1D9C927C00794E08 /* deposterize.cpp */; };
ABBB4ACE1D9C927C00794E08 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBB4ACC1D9C927C00794E08 /* deposterize.cpp */; };
ABBB4ACF1D9C927C00794E08 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBB4ACC1D9C927C00794E08 /* deposterize.cpp */; };
ABBB4AD01D9C927C00794E08 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBB4ACC1D9C927C00794E08 /* deposterize.cpp */; };
ABBB4AD11D9C927C00794E08 /* deposterize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBB4ACC1D9C927C00794E08 /* deposterize.cpp */; };
ABBCE29715ACB1FF00A2C965 /* arm_jit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBCE29515ACB1FF00A2C965 /* arm_jit.cpp */; };
ABBCE29815ACB1FF00A2C965 /* arm_jit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBCE29515ACB1FF00A2C965 /* arm_jit.cpp */; };
ABBF04A614B515F300E505A0 /* AppIcon_ROMCheats.icns in Resources */ = {isa = PBXBuildFile; fileRef = ABBF04A414B515F300E505A0 /* AppIcon_ROMCheats.icns */; };
@ -1953,6 +1958,7 @@
ABB97873144E89CC00793FA3 /* Icon_ActionReplay_32x32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_ActionReplay_32x32.png; path = Images/Icon_ActionReplay_32x32.png; sourceTree = "<group>"; };
ABB97874144E89CC00793FA3 /* Icon_CodeBreaker_32x32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_CodeBreaker_32x32.png; path = Images/Icon_CodeBreaker_32x32.png; sourceTree = "<group>"; };
ABB97875144E89CC00793FA3 /* Icon_DeSmuME_32x32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_DeSmuME_32x32.png; path = Images/Icon_DeSmuME_32x32.png; sourceTree = "<group>"; };
ABBB4ACC1D9C927C00794E08 /* deposterize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = deposterize.cpp; sourceTree = "<group>"; };
ABBC0F8C1394B1AA0028B6BD /* DefaultUserPrefs.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = DefaultUserPrefs.plist; sourceTree = "<group>"; };
ABBCE29415ACB1E600A2C965 /* arm_jit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = arm_jit.h; path = ../arm_jit.h; sourceTree = SOURCE_ROOT; };
ABBCE29515ACB1FF00A2C965 /* arm_jit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = arm_jit.cpp; path = ../arm_jit.cpp; sourceTree = SOURCE_ROOT; };
@ -3451,6 +3457,7 @@
children = (
ABFE14FA14C92FF5005D6699 /* 2xsai.cpp */,
ABFE14FB14C92FF5005D6699 /* bilinear.cpp */,
ABBB4ACC1D9C927C00794E08 /* deposterize.cpp */,
ABFE14FC14C92FF5005D6699 /* epx.cpp */,
ABFE14FE14C92FF5005D6699 /* hq2x.cpp */,
ABAAEFFE1B22361800E1269D /* hq3x.cpp */,
@ -4538,6 +4545,7 @@
AB50200C1D09E712002FA150 /* retro_stat.c in Sources */,
AB7BB17F1D62C8CC00A7A6E2 /* colorspacehandler.cpp in Sources */,
AB7BB1801D62C8CF00A7A6E2 /* colorspacehandler_AltiVec.cpp in Sources */,
ABBB4AD11D9C927C00794E08 /* deposterize.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4719,6 +4727,7 @@
AB5020181D09E712002FA150 /* retro_stat.c in Sources */,
AB37E3801D6188BC004A2C0D /* colorspacehandler.cpp in Sources */,
AB37E38A1D61895F004A2C0D /* colorspacehandler_AltiVec.cpp in Sources */,
ABBB4AD01D9C927C00794E08 /* deposterize.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -4930,6 +4939,7 @@
AB50200F1D09E712002FA150 /* retro_stat.c in Sources */,
AB37E3741D6188BC004A2C0D /* colorspacehandler.cpp in Sources */,
AB37E3771D6188BC004A2C0D /* colorspacehandler_SSE2.cpp in Sources */,
ABBB4ACD1D9C927C00794E08 /* deposterize.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5141,6 +5151,7 @@
AB5020121D09E712002FA150 /* retro_stat.c in Sources */,
AB37E3781D6188BC004A2C0D /* colorspacehandler.cpp in Sources */,
AB37E37B1D6188BC004A2C0D /* colorspacehandler_SSE2.cpp in Sources */,
ABBB4ACE1D9C927C00794E08 /* deposterize.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -5322,6 +5333,7 @@
AB5020151D09E712002FA150 /* retro_stat.c in Sources */,
AB37E37C1D6188BC004A2C0D /* colorspacehandler.cpp in Sources */,
AB37E37D1D6188BC004A2C0D /* colorspacehandler_AltiVec.cpp in Sources */,
ABBB4ACF1D9C927C00794E08 /* deposterize.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -869,7 +869,7 @@
[super handleEmuFrameProcessed];
NDSFrameInfo frameInfo;
frameInfo.render3DFPS = Render3DFramesPerSecond;
frameInfo.render3DFPS = GPU->GetFPSRender3D();
frameInfo.frameIndex = currFrameCounter;
frameInfo.lagFrameCount = TotalLagFrames;

View File

@ -67,6 +67,7 @@ CommandLine::CommandLine()
, start_paused(FALSE)
, autodetect_method(-1)
, render3d(COMMANDLINE_RENDER3D_DEFAULT)
, language(1) //english by default
{
#ifndef HOST_WINDOWS
disable_sound = 0;
@ -117,6 +118,9 @@ ENDL
" --bios-arm9 BIN_FILE Uses the ARM9 BIOS provided at the specified path" ENDL
" --bios-arm7 BIN_FILE Uses the ARM7 BIOS provided at the specified path" ENDL
" --bios-swi Uses SWI from the provided bios files (else HLE)" ENDL
" --lang N Firmware language (can affect game translations)" ENDL
" 0 = Japanese, 1 = English (default), 2 = French" ENDL
" 3 = German, 4 = Italian, 5 = Spanish" ENDL
ENDL
"Arguments affecting contents of SLOT-1:" ENDL
" --slot1 [RETAIL|RETAILAUTO|R4|RETAILNAND|RETAILMCDROM|RETAILDEBUG]" ENDL
@ -163,6 +167,7 @@ ENDL
#define OPT_CONSOLE_TYPE 200
#define OPT_ARM9 201
#define OPT_ARM7 202
#define OPT_LANGUAGE 203
#define OPT_SLOT1 300
#define OPT_SLOT1_FAT_DIR 301
@ -224,7 +229,8 @@ bool CommandLine::parse(int argc,char **argv)
{ "console-type", required_argument, NULL, OPT_CONSOLE_TYPE },
{ "bios-arm9", required_argument, NULL, OPT_ARM9},
{ "bios-arm7", required_argument, NULL, OPT_ARM7},
{ "bios-swi", required_argument, &_bios_swi, 1},
{ "bios-swi", no_argument, &_bios_swi, 1},
{ "lang", required_argument, NULL, OPT_LANGUAGE},
//slot-1 contents
{ "slot1", required_argument, NULL, OPT_SLOT1},
@ -308,6 +314,7 @@ bool CommandLine::parse(int argc,char **argv)
//utilities
case OPT_ADVANSCENE: CommonSettings.run_advanscene_import = optarg; break;
case OPT_LANGUAGE: language = atoi(optarg); break;
}
} //arg parsing loop
@ -354,10 +361,10 @@ bool CommandLine::parse(int argc,char **argv)
//process 3d renderer
_render3d = strtoupper(_render3d);
if(_render3d == "NONE") render3d = COMMANDLINE_RENDER3D_NONE;
if(_render3d == "SW") render3d = COMMANDLINE_RENDER3D_SW;
if(_render3d == "OLDGL") render3d = COMMANDLINE_RENDER3D_OLDGL;
if(_render3d == "AUTOGL") render3d = COMMANDLINE_RENDER3D_AUTOGL;
if(_render3d == "GL") render3d = COMMANDLINE_RENDER3D_GL;
else if(_render3d == "SW") render3d = COMMANDLINE_RENDER3D_SW;
else if(_render3d == "OLDGL") render3d = COMMANDLINE_RENDER3D_OLDGL;
else if(_render3d == "AUTOGL") render3d = COMMANDLINE_RENDER3D_AUTOGL;
else if(_render3d == "GL") render3d = COMMANDLINE_RENDER3D_GL;
if (autodetect_method != -1)
CommonSettings.autodetectBackupMethod = autodetect_method;

View File

@ -47,6 +47,7 @@ public:
int depth_threshold;
int autodetect_method;
int render3d;
int language;
std::string nds_file;
std::string play_movie_file;
std::string record_movie_file;

View File

@ -280,6 +280,7 @@ private:
{
mPositionCacheEnabled = false;
mCondition = eCondition_Clean;
mFilePosition = 0;
fp = fopen(fname,mode);
if(!fp)
failbit = true;

View File

@ -0,0 +1,188 @@
/*
Copyright (C) 2016 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../types.h"
#include "filter.h"
#define DEPOSTERIZE_THRESHOLD 23 // Possible values are [0-255], where lower a value prevents blending and a higher value allows for more blending
static u32 Deposterize_InterpLTE(const u32 pixA, const u32 pixB)
{
const u32 aB = (pixB & 0xFF000000) >> 24;
if (aB == 0)
{
return pixA;
}
const u32 rA = (pixA & 0x000000FF);
const u32 gA = (pixA & 0x0000FF00) >> 8;
const u32 bA = (pixA & 0x00FF0000) >> 16;
const u32 aA = (pixA & 0xFF000000) >> 24;
const u32 rB = (pixB & 0x000000FF);
const u32 gB = (pixB & 0x0000FF00) >> 8;
const u32 bB = (pixB & 0x00FF0000) >> 16;
const u32 rC = ( (rB - rA <= DEPOSTERIZE_THRESHOLD) || (rA - rB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((rA+rB)>>1) ) : rA;
const u32 gC = ( (gB - gA <= DEPOSTERIZE_THRESHOLD) || (gA - gB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((gA+gB)>>1) ) : gA;
const u32 bC = ( (bB - bA <= DEPOSTERIZE_THRESHOLD) || (bA - bB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((bA+bB)>>1) ) : bA;
const u32 aC = ( (bB - aA <= DEPOSTERIZE_THRESHOLD) || (aA - aB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((aA+aB)>>1) ) : aA;
return (rC | (gC << 8) | (bC << 16) | (aC << 24));
}
static u32 Deposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA, const u32 weightB)
{
const u32 aB = (pixB & 0xFF000000) >> 24;
if (aB == 0)
{
return pixA;
}
const u32 weightSum = weightA + weightB;
const u32 rbA = pixA & 0x00FF00FF;
const u32 gA = pixA & 0x0000FF00;
const u32 aA = (pixA & 0xFF000000) >> 24;
const u32 rbB = pixB & 0x00FF00FF;
const u32 gB = pixB & 0x0000FF00;
const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / weightSum ) & 0x00FF00FF;
const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / weightSum ) & 0x0000FF00;
const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / weightSum ) << 24;
return (rbC | gC | aC);
}
void RenderDeposterize(SSurface Src, SSurface Dst)
{
//---------------------------------------\n\
// Input Pixel Mapping: 06|07|08
// 05|00|01
// 04|03|02
//
// Output Pixel Mapping: 00
const int w = Src.Width;
const int h = Src.Height;
u32 color[9];
u32 blend[9];
u32 *src = (u32 *)Src.Surface;
u32 *workingDst = (u32 *)Dst.workingSurface[0];
u32 *finalDst = (u32 *)Dst.Surface;
int i = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
workingDst[i] = src[i];
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = ((x < w-1) && (y < h-1)) ? src[i+w+1] : src[i];
color[3] = (y < h-1) ? src[i+w] : src[i];
color[4] = ((x > 0) && (y < h-1)) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = ((x > 0) && (y > 0)) ? src[i-w-1] : src[i];
color[7] = (y > 0) ? src[i-w] : src[i];
color[8] = ((x < w-1) && (y > 0)) ? src[i-w+1] : src[i];
blend[0] = color[0];
blend[1] = Deposterize_InterpLTE(color[0], color[1]);
blend[2] = Deposterize_InterpLTE(color[0], color[2]);
blend[3] = Deposterize_InterpLTE(color[0], color[3]);
blend[4] = Deposterize_InterpLTE(color[0], color[4]);
blend[5] = Deposterize_InterpLTE(color[0], color[5]);
blend[6] = Deposterize_InterpLTE(color[0], color[6]);
blend[7] = Deposterize_InterpLTE(color[0], color[7]);
blend[8] = Deposterize_InterpLTE(color[0], color[8]);
workingDst[i] = Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 1, 7),
Deposterize_Blend(blend[0], blend[1], 1, 7),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 1, 7),
Deposterize_Blend(blend[0], blend[3], 1, 7),
1, 1),
1, 1),
Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9),
Deposterize_Blend(blend[0], blend[2], 7, 9),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9),
Deposterize_Blend(blend[0], blend[4], 7, 9),
1, 1),
1, 1),
3, 1);
}
}
i = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
finalDst[i] = src[i];
continue;
}
color[0] = workingDst[i];
color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i];
color[2] = ((x < w-1) && (y < h-1)) ? workingDst[i+w+1] : workingDst[i];
color[3] = (y < h-1) ? workingDst[i+w] : workingDst[i];
color[4] = ((x > 0) && (y < h-1)) ? workingDst[i+w-1] : workingDst[i];
color[5] = (x > 0) ? workingDst[i-1] : workingDst[i];
color[6] = ((x > 0) && (y > 0)) ? workingDst[i-w-1] : workingDst[i];
color[7] = (y > 0) ? workingDst[i-w] : workingDst[i];
color[8] = ((x < w-1) && (y > 0)) ? workingDst[i-w+1] : workingDst[i];
blend[0] = color[0];
blend[1] = Deposterize_InterpLTE(color[0], color[1]);
blend[2] = Deposterize_InterpLTE(color[0], color[2]);
blend[3] = Deposterize_InterpLTE(color[0], color[3]);
blend[4] = Deposterize_InterpLTE(color[0], color[4]);
blend[5] = Deposterize_InterpLTE(color[0], color[5]);
blend[6] = Deposterize_InterpLTE(color[0], color[6]);
blend[7] = Deposterize_InterpLTE(color[0], color[7]);
blend[8] = Deposterize_InterpLTE(color[0], color[8]);
finalDst[i] = Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 1, 7),
Deposterize_Blend(blend[0], blend[1], 1, 7),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 1, 7),
Deposterize_Blend(blend[0], blend[3], 1, 7),
1, 1),
1, 1),
Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9),
Deposterize_Blend(blend[0], blend[2], 7, 9),
1, 1),
Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9),
Deposterize_Blend(blend[0], blend[4], 7, 9),
1, 1),
1, 1),
3, 1);
}
}
}

View File

@ -1,19 +1,22 @@
/*
Copyright (C) 2009-2014 DeSmuME team
Copyright (C) 2009-2016 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IMAGE_FILTER_
#define _IMAGE_FILTER_
#define FILTER_MAX_WORKING_SURFACE_COUNT 8
@ -27,6 +30,8 @@ typedef struct {
void *userData;
} SSurface;
void RenderDeposterize(SSurface Src, SSurface Dst);
void RenderNearest2X (SSurface Src, SSurface Dst);
void RenderLQ2X (SSurface Src, SSurface Dst);
void RenderLQ2XS (SSurface Src, SSurface Dst);
@ -52,3 +57,5 @@ void Render3xBRZ(SSurface Src, SSurface Dst);
void Render4xBRZ(SSurface Src, SSurface Dst);
void Render5xBRZ(SSurface Src, SSurface Dst);
void Render6xBRZ(SSurface Src, SSurface Dst);
#endif // _IMAGE_FILTER_

View File

@ -299,6 +299,15 @@ AS_CASE([$host_cpu],
[AC_DEFINE(HOST_32)]
)
AC_CHECK_DECL([__SSE2__])
AM_CONDITIONAL([SUPPORT_SSE2], [test "x$ac_cv_have_decl___SSE2__" = xyes])
AC_CHECK_DECL([__AVX2__])
AM_CONDITIONAL([SUPPORT_AVX2], [test "x$ac_cv_have_decl___AVX2__" = xyes])
AC_CHECK_DECL([__ALTIVEC__])
AM_CONDITIONAL([SUPPORT_ALTIVEC], [test "x$ac_cv_have_decl___ALTIVEC__" = xyes])
AC_SUBST(UI_DIR)
AC_SUBST(PO_DIR)

View File

@ -1,6 +1,6 @@
/* main.cpp - this file is part of DeSmuME
*
* Copyright (C) 2006-2015 DeSmuME Team
* Copyright (C) 2006-2016 DeSmuME Team
* Copyright (C) 2007 Pascal Giard (evilynux)
*
* This file is free software; you can redistribute it and/or modify
@ -649,24 +649,30 @@ public:
};
static void
init_configured_features( class configured_features *config)
init_configured_features( class configured_features *config )
{
config->engine_3d = 1;
if(config->render3d == COMMANDLINE_RENDER3D_GL || config->render3d == COMMANDLINE_RENDER3D_OLDGL || config->render3d == COMMANDLINE_RENDER3D_AUTOGL)
config->engine_3d = 2;
else
config->engine_3d = 1;
config->savetype = 0;
config->timeout = 0;
/* use the default language */
config->firmware_language = -1;
config->firmware_language = -1;
/* If specified by --lang option the lang will change to choosed one */
config->firmware_language = config->language;
}
static int
fill_configured_features( class configured_features *config,
int argc, char ** argv)
char ** argv)
{
GOptionEntry options[] = {
{ "3d-engine", 0, 0, G_OPTION_ARG_INT, &config->engine_3d, "Select 3d rendering engine. Available engines:\n"
{ "3d-render", 0, 0, G_OPTION_ARG_INT, &config->engine_3d, "Select 3D rendering engine. Available engines:\n"
"\t\t\t\t 0 = 3d disabled\n"
"\t\t\t\t 1 = internal rasterizer (default)\n"
#if defined(HAVE_LIBOSMESA) || defined(HAVE_GL_GLX)
@ -696,7 +702,6 @@ fill_configured_features( class configured_features *config,
//g_option_context_add_main_entries (config->ctx, options, "options");
//g_option_context_add_group (config->ctx, gtk_get_option_group (TRUE));
config->parse(argc,argv);
if(!config->validate())
goto error;
@ -2413,7 +2418,7 @@ gboolean EmuLoop(gpointer data)
// HUD display things (copied from Windows main.cpp)
#ifdef HAVE_LIBAGG
Hud.fps3d = Render3DFramesPerSecond;
Hud.fps3d = GPU->GetFPSRender3D();
if(nds.idleFrameCounter==0 || oneSecond)
{
@ -2446,7 +2451,7 @@ gboolean EmuLoop(gpointer data)
for (i = 0; i < Frameskip; i++) {
NDS_SkipNextFrame();
#ifdef HAVE_LIBAGG
Hud.fps3d = Render3DFramesPerSecond;
Hud.fps3d = GPU->GetFPSRender3D();
#endif
desmume_cycle();
skipped_frames++;
@ -2459,7 +2464,7 @@ gboolean EmuLoop(gpointer data)
for (i = 0; i < Frameskip; i++) {
NDS_SkipNextFrame();
#ifdef HAVE_LIBAGG
Hud.fps3d = Render3DFramesPerSecond;
Hud.fps3d = GPU->GetFPSRender3D();
#endif
desmume_cycle();
skipped_frames++;
@ -2481,7 +2486,7 @@ gboolean EmuLoop(gpointer data)
// Aggressively skip frames to avoid delay
NDS_SkipNextFrame();
#ifdef HAVE_LIBAGG
Hud.fps3d = Render3DFramesPerSecond;
Hud.fps3d = GPU->GetFPSRender3D();
#endif
desmume_cycle();
skipped_frames++;
@ -3252,6 +3257,7 @@ int main (int argc, char *argv[])
// The global menu screws up the window size...
unsetenv("UBUNTU_MENUPROXY");
my_config.parse(argc, argv);
init_configured_features( &my_config);
if (!g_thread_supported())
@ -3259,7 +3265,7 @@ int main (int argc, char *argv[])
gtk_init(&argc, &argv);
if ( !fill_configured_features( &my_config, argc, argv)) {
if ( !fill_configured_features( &my_config, argv)) {
exit(0);
}

View File

@ -621,8 +621,10 @@ static void MyAdjustWindowRectEx(RECT* rect, HWND hwnd)
ZeroMemory(&mbi, sizeof(mbi));
mbi.cbSize = sizeof(mbi);
GetMenuBarInfo(hwnd, OBJID_MENU, 0, &mbi);
//int menuHeight = (mbi.rcBar.bottom - mbi.rcBar.top + 1); //zero 07-aug-2016 - why did I do this? it isn't normal in windows and in the case of no menu bar it was making a 1 instead of a 0 (r3184 in 2009)
//if the menubar exists, its height is off by 1 (frame between bar and client area?)
int menuHeight = (mbi.rcBar.bottom - mbi.rcBar.top);
if(menuHeight != 0) menuHeight++;
rect->bottom -= cymenu;
rect->bottom += menuHeight;

View File

@ -87,6 +87,7 @@
<ClCompile Include="..\FIFO.cpp" />
<ClCompile Include="..\filter\2xsai.cpp" />
<ClCompile Include="..\filter\bilinear.cpp" />
<ClCompile Include="..\filter\deposterize.cpp" />
<ClCompile Include="..\filter\epx.cpp" />
<ClCompile Include="..\filter\hq2x.cpp" />
<ClCompile Include="..\filter\hq4x.cpp" />

View File

@ -975,23 +975,8 @@
<ClCompile Include="..\utils\colorspacehandler\colorspacehandler_SSE2.cpp">
<Filter>Core\utils\colorspacehandler</Filter>
</ClCompile>
<ClCompile Include="..\..\utils\colorspacehandler\colorspacehandler_AVX2.cpp">
<Filter>Core\utils\colorspacehandler</Filter>
</ClCompile>
<ClCompile Include="..\..\utils\colorspacehandler\colorspacehandler_AltiVec.cpp">
<Filter>Core\utils\colorspacehandler</Filter>
</ClCompile>
<ClCompile Include="..\..\utils\colorspacehandler\colorspacehandler_AVX2.cpp">
<Filter>Core\utils\colorspacehandler</Filter>
</ClCompile>
<ClCompile Include="..\..\utils\colorspacehandler\colorspacehandler_AltiVec.cpp">
<Filter>Core\utils\colorspacehandler</Filter>
</ClCompile>
<ClCompile Include="..\..\utils\colorspacehandler\colorspacehandler_AVX2.cpp">
<Filter>Core\utils\colorspacehandler</Filter>
</ClCompile>
<ClCompile Include="..\..\utils\colorspacehandler\colorspacehandler_AltiVec.cpp">
<Filter>Core\utils\colorspacehandler</Filter>
<ClCompile Include="..\filter\deposterize.cpp">
<Filter>Core\filter</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@ -1772,24 +1757,6 @@
<ClInclude Include="..\utils\colorspacehandler\colorspacehandler_SSE2.h">
<Filter>Core\utils\colorspacehandler</Filter>
</ClInclude>
<ClInclude Include="..\..\utils\colorspacehandler\colorspacehandler_AltiVec.h">
<Filter>Core\utils\colorspacehandler</Filter>
</ClInclude>
<ClInclude Include="..\..\utils\colorspacehandler\colorspacehandler_AVX2.h">
<Filter>Core\utils\colorspacehandler</Filter>
</ClInclude>
<ClInclude Include="..\..\utils\colorspacehandler\colorspacehandler_AltiVec.h">
<Filter>Core\utils\colorspacehandler</Filter>
</ClInclude>
<ClInclude Include="..\..\utils\colorspacehandler\colorspacehandler_AVX2.h">
<Filter>Core\utils\colorspacehandler</Filter>
</ClInclude>
<ClInclude Include="..\..\utils\colorspacehandler\colorspacehandler_AltiVec.h">
<Filter>Core\utils\colorspacehandler</Filter>
</ClInclude>
<ClInclude Include="..\..\utils\colorspacehandler\colorspacehandler_AVX2.h">
<Filter>Core\utils\colorspacehandler</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\instruction_tabdef.inc">

View File

@ -2184,7 +2184,7 @@ static void StepRunLoop_User()
const int kFramesPerToolUpdate = 1;
Hud.fps = mainLoopData.fps;
Hud.fps3d = Render3DFramesPerSecond;
Hud.fps3d = GPU->GetFPSRender3D();
Display();
@ -3386,6 +3386,9 @@ int _main()
}
}
//not supported; use the GUI
//if(cmdline.language != -1) CommonSettings.fw_config.language = cmdline.language;
cmdline.process_movieCommands();
if(cmdline.load_slot != -1)

View File

@ -57,15 +57,6 @@ extern bool ShowLagFrameCounter;
#define GPU3D_SWRAST 2
#define GPU3D_OPENGL_OLD 3
static const int LANGUAGE_ENGLISH = 0;
static const int LANGUAGE_FRENCH = 1;
static const int LANGUAGE_CHINESE = 3;
static const int LANGUAGE_ITALIAN = 4;
static const int LANGUAGE_JAPANESE = 5;
static const int LANGUAGE_SPANISH = 6;
static const int LANGUAGE_KOREAN = 7;
static const int LANGUAGE_BRAZILIAN = 8;
extern void Change3DCoreWithFallbackAndSave(int newCore);
extern int backupmemorytype;

View File

@ -184,14 +184,17 @@ BOOL PathSettings_OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lParam)
ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
ti.uId = (UINT_PTR)hwnd;
ti.lpszText =
"The format a screenshot should be saved in.\r\n"
"The string format a screenshot should be saved with (google strftime).\r\n"
"%f\t\tFilename\r\n"
"%r\t\tRandom: 0 ~ RAND_MAX\r\n"
"%t\t\tTick: Reset on startup\r\n"
"%Y\t\tYear:Four Digit\r\n"
"%y\t\tYear:Two Digit\r\n"
"%m\t\tMonth:Two Digit\r\n"
"%D\t\tDay:Two Digit\r\n"
"%H\t\tHour:Two Digit\r\n"
"%d\t\tDay:Two Digit\r\n"
"%H\t\tHour (24):Two Digit\r\n"
"%I\t\tHour (12):Two Digit\r\n"
"%p\t\tAM/PM\r\n"
"%M\t\tMinute: Two Digit\r\n"
"%S\t\tSecond: Two Digit\r\n";
GetClientRect(hwnd, &ti.rect);

View File

@ -503,9 +503,7 @@ void gfx3d_init()
gfx3d.state.fogDensityTable = MMU.ARM9_REG+0x0360;
gfx3d.state.edgeMarkColorTable = (u16 *)(MMU.ARM9_REG+0x0330);
gfx3d._videoFrameCount = 0;
gfx3d.render3DFrameCount = 0;
Render3DFramesPerSecond = 0;
makeTables();
Render3D_Init();
@ -526,7 +524,10 @@ void gfx3d_deinit()
void gfx3d_reset()
{
GPU->ForceRender3DFinishAndFlush(false);
if (CurrentRenderer->GetRenderNeedsFinish())
{
GPU->ForceRender3DFinishAndFlush(false);
}
#ifdef _SHOW_VTX_COUNTERS
max_polys = max_verts = 0;
@ -603,9 +604,7 @@ void gfx3d_reset()
GFX_PIPEclear();
GFX_FIFOclear();
gfx3d._videoFrameCount = 0;
gfx3d.render3DFrameCount = 0;
Render3DFramesPerSecond = 0;
CurrentRenderer->Reset();
}
@ -2299,7 +2298,12 @@ void gfx3d_VBlankSignal()
void gfx3d_VBlankEndSignal(bool skipFrame)
{
GPU->ForceRender3DFinishAndFlush(false);
if (CurrentRenderer->GetRenderNeedsFinish())
{
GPU->ForceRender3DFinishAndFlush(false);
CurrentRenderer->SetRenderNeedsFinish(false);
GPU->GetEventHandler()->DidRender3DEnd();
}
if (!drawPending) return;
if (skipFrame) return;
@ -2307,10 +2311,10 @@ void gfx3d_VBlankEndSignal(bool skipFrame)
drawPending = FALSE;
GPU->GetEventHandler()->DidRender3DBegin();
CurrentRenderer->SetRenderNeedsFinish(true);
if (CommonSettings.showGpu.main)
{
CurrentRenderer->SetRenderNeedsFinish(true);
CurrentRenderer->SetTextureProcessingProperties(CommonSettings.GFX3D_Renderer_TextureScalingFactor,
CommonSettings.GFX3D_Renderer_TextureDeposterize,
CommonSettings.GFX3D_Renderer_TextureSmoothing);
@ -2522,7 +2526,10 @@ void gfx3d_Update3DFramebuffers(FragmentColor *framebufferRGBA6665, u16 *framebu
//-------------savestate
void gfx3d_savestate(EMUFILE* os)
{
GPU->ForceRender3DFinishAndFlush(true);
if (CurrentRenderer->GetRenderNeedsFinish())
{
GPU->ForceRender3DFinishAndFlush(true);
}
//version
write32le(4,os);
@ -2555,6 +2562,10 @@ bool gfx3d_loadstate(EMUFILE* is, int size)
if (read32le(&version,is) != 1) return false;
if (size == 8) version = 0;
if (CurrentRenderer->GetRenderNeedsFinish())
{
GPU->ForceRender3DFinishAndFlush(false);
}
gfx3d_glPolygonAttrib_cache();
gfx3d_glTexImage_cache();

View File

@ -667,7 +667,6 @@ struct GFX3D
GFX3D()
: polylist(0)
, vertlist(0)
, _videoFrameCount(0)
, render3DFrameCount(0) {
}
@ -681,11 +680,9 @@ struct GFX3D
VERTLIST* vertlist;
INDEXLIST indexlist;
u32 _videoFrameCount; // Internal variable that increments when a video frame is completed. Resets every 60 video frames.
u32 render3DFrameCount; // Increments when gfx3d_doFlush() is called. Resets every 60 video frames.
};
extern GFX3D gfx3d;
extern u32 Render3DFramesPerSecond; // save the current 3D rendering frame count to here every 60 video frames
//---------------------

File diff suppressed because it is too large Load Diff

View File

@ -294,7 +294,9 @@ BackupDevice::BackupDevice()
else
{
printf("BackupDevice: Converting old raw .sav file.\n");
sz = trim(buf, sz);
//dont TRIM this! it will wreck the searchFileSaveType below.
//was this intended for egregiously over-sized save files? too bad.
//sz = trim(buf, sz);
}
if (fpOut->fwrite(buf, sz) == sz)
@ -305,6 +307,7 @@ BackupDevice::BackupDevice()
info.type = (res + 1);
addr_size = info.addr_size = save_types[info.type].addr_size;
info.size = fsize = sz;
fpMC = fpOut; //so ensure() works
ensure(sz, fpOut);
fsize = 0;
}
@ -629,6 +632,7 @@ void BackupDevice::reset()
else if(!memcmp(gameInfo.header.gameCode,"AH5", 3)) addr_size = 1; //over the hedge
else if(!memcmp(gameInfo.header.gameCode,"AVH", 3)) addr_size = 1; //over the hedge - Hammy Goes Nuts!
else if(!memcmp(gameInfo.header.gameCode,"AQ3", 3)) addr_size = 1; //spider-man 3
else if(!memcmp(gameInfo.header.gameCode,"BPV", 3)) addr_size = 2; //puzzler world (should be eeprom 64KBits)
//if we found a whitelist match, we dont need to run detection
if(addr_size) state = RUNNING;
@ -1069,8 +1073,10 @@ bool BackupDevice::importData(const char *filename, u32 force_size)
bool res = false;
if (strlen(filename) < 4) return res;
if ((memcmp(filename + strlen(filename) - 4, ".duc", 4) == 0) ||
(memcmp(filename + strlen(filename) - 4, ".dss", 4) == 0))
std::string ext = strright(filename,4);
bool isDuc = strncasecmp(ext.c_str(), ".duc", 4) == 0;
bool isDss = strncasecmp(ext.c_str(), ".dss", 4) == 0;
if(isDuc || isDss)
res = import_duc(filename, force_size);
else
if (import_no_gba(filename, force_size))
@ -1499,26 +1505,49 @@ u32 BackupDevice::get_save_duc_size(const char* fname)
bool BackupDevice::import_duc(const char* filename, u32 force_size)
{
u32 size;
char id[16];
u8 id16[16] = {0}, id4[4] = {0}, id3[3] = {0};
FILE* file = fopen(filename, "rb");
if(!file) return false;
fseek(file, 0, SEEK_END);
size = (u32)ftell(file) - 500;
fseek(file, 0, SEEK_SET);
int version = 0;
// Make sure we really have the right file
fread((void *)id, sizeof(char), 16, file);
//ID version 1
fread(id16, 1, 16, file);
if(!memcmp(id16, "ARDS000000000001", 16)) version = 1;
if (memcmp(id, "ARDS000000000001", 16) != 0)
//ID version 2
fseek(file,0xA1,SEEK_SET);
fread(id3,1,3,file);
if(!memcmp(id16,"\0\0\0\0",4) && id3[2] == 0xC0) version = 2;
if(version == 0)
{
INVALID_DUC:
printf("Not recognized as a valid DUC file\n");
fclose(file);
return false;
}
// Skip the rest of the header since we don't need it
fseek(file, 500, SEEK_SET);
fseek(file, 0, SEEK_END);
size = (u32)ftell(file);
//skip to raw data
if(version == 1)
{
size -= 500;
fseek(file, 500, SEEK_SET);
}
if(version == 2)
{
size -= 0xA4;
fseek(file, 0xA4, SEEK_SET);
//validate size
int specifiedSize = (id3[0]<<8)+(id3[1]<<16);
if(specifiedSize != size)
goto INVALID_DUC;
}
u32 left = 0;
if (force_size > 0)

View File

@ -52,7 +52,6 @@
#include "matrix.h"
#include "render3D.h"
#include "gfx3d.h"
#include "texcache.h"
#include "MMU.h"
#include "NDSSystem.h"
#include "utils/task.h"
@ -329,7 +328,7 @@ class RasterizerUnit
{
protected:
SoftRasterizerRenderer *_softRender;
TexCacheItem *lastTexKey;
SoftRasterizerTexture *lastTexKey;
VERT* verts[MAX_CLIPPED_VERTS];
int polynum;
@ -349,19 +348,16 @@ public:
int width, height;
s32 wmask, hmask;
int wrap;
int wshift;
int texFormat;
void setup(u32 texParam)
void setup(SoftRasterizerTexture *theTexture, u32 texParam)
{
texFormat = (texParam>>26)&7;
wshift = ((texParam>>20)&0x07) + 3;
width=(1 << wshift);
height=(8 << ((texParam>>23)&0x07));
wmask = width-1;
hmask = height-1;
width = theTexture->GetRenderWidth();
height = theTexture->GetRenderHeight();
wmask = theTexture->GetRenderWidthMask();
hmask = theTexture->GetRenderHeightMask();
wrap = (texParam>>16)&0xF;
enabled = gfx3d.renderState.enableTexturing && (texFormat!=0);
enabled = gfx3d.renderState.enableTexturing && (theTexture->GetPackFormat() != TEXMODE_NONE);
}
FORCEINLINE void clamp(s32 &val, const int size, const s32 sizemask)
@ -459,7 +455,10 @@ public:
sampler.dowrap(iu, iv);
FragmentColor color;
color.color = ((u32*)lastTexKey->decoded)[(iv<<sampler.wshift)+iu];
const u32 *textureData = lastTexKey->GetUnpackData();
color.color = textureData[( iv << lastTexKey->GetRenderWidthShift() ) + iu];
return color;
}
@ -1004,15 +1003,15 @@ public:
const size_t dstWidth = this->_softRender->GetFramebufferWidth();
const size_t dstHeight = this->_softRender->GetFramebufferHeight();
lastTexKey = NULL;
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;
u32 lastTexPalette = firstPoly.texPalette;
sampler.setup(firstPoly.texParam);
lastTexKey = this->_softRender->polyTexKeys[0];
sampler.setup(lastTexKey, firstPoly.texParam);
//iterate over polys
for (size_t i = 0; i < polyCount; i++)
@ -1033,13 +1032,15 @@ public:
if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
{
sampler.setup(thePoly.texParam);
lastTexParams = thePoly.texParam;
lastTexPalette = thePoly.texPalette;
lastTexKey = this->_softRender->polyTexKeys[i];
sampler.setup(lastTexKey, thePoly.texParam);
lastTexKey->ResetCacheAge();
lastTexKey->IncreaseCacheUsageCount(1);
}
lastTexKey = this->_softRender->polyTexKeys[i];
for (int j = 0; j < type; j++)
this->verts[j] = &clippedPoly.clipVerts[j];
for (int j = type; j < MAX_CLIPPED_VERTS; j++)
@ -1145,6 +1146,60 @@ static void SoftRasterizerRendererDestroy()
}
}
SoftRasterizerTexture::SoftRasterizerTexture(u32 texAttributes, u32 palAttributes) : TextureStore(texAttributes, palAttributes)
{
_cacheSize = GetUnpackSizeUsingFormat(TexFormat_15bpp);
_unpackData = (u32 *)malloc_alignedCacheLine(_cacheSize);
_renderWidth = _sizeS;
_renderHeight = _sizeT;
_renderWidthMask = _renderWidth - 1;
_renderHeightMask = _renderHeight - 1;
_renderWidthShift = 0;
u32 tempWidth = _renderWidth;
while ( (tempWidth & 1) == 0)
{
tempWidth >>= 1;
_renderWidthShift++;
}
}
SoftRasterizerTexture::~SoftRasterizerTexture()
{
free_aligned(this->_unpackData);
}
u32* SoftRasterizerTexture::GetUnpackData()
{
return this->_unpackData;
}
u32 SoftRasterizerTexture::GetRenderWidth() const
{
return this->_renderWidth;
}
u32 SoftRasterizerTexture::GetRenderHeight() const
{
return this->_renderHeight;
}
u32 SoftRasterizerTexture::GetRenderWidthMask() const
{
return this->_renderWidthMask;
}
u32 SoftRasterizerTexture::GetRenderHeightMask() const
{
return this->_renderHeightMask;
}
u32 SoftRasterizerTexture::GetRenderWidthShift() const
{
return this->_renderWidthShift;
}
GPU3DInterface gpu3DRasterize = {
"SoftRasterizer",
SoftRasterizerRendererCreate,
@ -1371,7 +1426,18 @@ void SoftRasterizerRenderer::setupTextures()
const POLY &firstPoly = *firstClippedPoly.poly;
u32 lastTexParams = firstPoly.texParam;
u32 lastTexPalette = firstPoly.texPalette;
TexCacheItem *lastTexKey = TexCache_SetTexture(TexFormat_15bpp, firstPoly.texParam, firstPoly.texPalette);
SoftRasterizerTexture *lastTexItem = (SoftRasterizerTexture *)texCache.GetTexture(firstPoly.texParam, firstPoly.texPalette);
if (lastTexItem == NULL)
{
lastTexItem = new SoftRasterizerTexture(firstPoly.texParam, firstPoly.texPalette);
texCache.Add(lastTexItem);
}
if (lastTexItem->IsLoadNeeded())
{
lastTexItem->Unpack<TexFormat_15bpp>(lastTexItem->GetUnpackData());
}
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
@ -1384,13 +1450,24 @@ void SoftRasterizerRenderer::setupTextures()
//and then it won't be safe.
if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
{
lastTexKey = TexCache_SetTexture(TexFormat_15bpp, thePoly.texParam, thePoly.texPalette);
lastTexItem = (SoftRasterizerTexture *)texCache.GetTexture(thePoly.texParam, thePoly.texPalette);
if (lastTexItem == NULL)
{
lastTexItem = new SoftRasterizerTexture(thePoly.texParam, thePoly.texPalette);
texCache.Add(lastTexItem);
}
if (lastTexItem->IsLoadNeeded())
{
lastTexItem->Unpack<TexFormat_15bpp>(lastTexItem->GetUnpackData());
}
lastTexParams = thePoly.texParam;
lastTexPalette = thePoly.texPalette;
}
//printf("%08X %d\n",poly->texParam,rasterizerUnit[0].textures.currentNum);
polyTexKeys[i] = lastTexKey;
polyTexKeys[i] = lastTexItem;
}
}
@ -1535,7 +1612,7 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt
{
rasterizerUnit[0].mainLoop<false>();
this->_renderGeometryNeedsFinish = false;
TexCache_EvictFrame(); // Since we're finishing geometry rendering here and now, also check the texture cache now.
texCache.Evict(); // Since we're finishing geometry rendering here and now, also check the texture cache now.
}
// printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count);
@ -1886,7 +1963,7 @@ Render3DError SoftRasterizerRenderer::Reset()
memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer));
memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer));
TexCache_Reset();
texCache.Reset();
return RENDER3DERROR_NOERR;
}
@ -1945,7 +2022,7 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
}
// Now that geometry rendering is finished on all threads, check the texture cache.
TexCache_EvictFrame();
texCache.Evict();
// Do multithreaded post-processing.
if (this->currentRenderState->enableEdgeMarking || this->currentRenderState->enableFog)

View File

@ -20,6 +20,7 @@
#include "render3D.h"
#include "gfx3d.h"
#include "texcache.h"
#define SOFTRASTERIZER_DEPTH_EQUAL_TEST_TOLERANCE 0x200
@ -39,6 +40,28 @@ struct SoftRasterizerPostProcessParams
bool fogAlphaOnly;
};
class SoftRasterizerTexture : public TextureStore
{
protected:
u32 *_unpackData;
u32 _renderWidth;
u32 _renderHeight;
u32 _renderWidthMask;
u32 _renderHeightMask;
u32 _renderWidthShift;
public:
SoftRasterizerTexture(u32 texAttributes, u32 palAttributes);
virtual ~SoftRasterizerTexture();
u32* GetUnpackData();
u32 GetRenderWidth() const;
u32 GetRenderHeight() const;
u32 GetRenderWidthMask() const;
u32 GetRenderHeightMask() const;
u32 GetRenderWidthShift() const;
};
#if defined(ENABLE_SSE2)
class SoftRasterizerRenderer : public Render3D_SSE2
#else
@ -75,7 +98,7 @@ public:
FragmentColor toonColor32LUT[32];
GFX3D_Clipper::TClippedPoly *clippedPolys;
FragmentAttributesBuffer *_framebufferAttributes;
TexCacheItem *polyTexKeys[POLYLIST_SIZE];
SoftRasterizerTexture *polyTexKeys[POLYLIST_SIZE];
bool polyVisible[POLYLIST_SIZE];
bool polyBackfacing[POLYLIST_SIZE];
GFX3D_State *currentRenderState;

View File

@ -28,9 +28,9 @@
#include "gfx3d.h"
#include "MMU.h"
#include "texcache.h"
#include "./filter/filter.h"
#include "./filter/xbrz.h"
#define TEXTURE_DEPOSTERIZE_THRESHOLD 21 // Possible values are [0-255], where lower a value prevents blending and a higher value allows for more blending
int cur3DCore = GPU3D_NULL;
@ -126,55 +126,6 @@ void Render3DBaseDestroy()
}
}
static u32 TextureDeposterize_InterpLTE(const u32 pixA, const u32 pixB, const u32 threshold)
{
const u32 aB = (pixB & 0xFF000000) >> 24;
if (aB == 0)
{
return pixA;
}
const u32 rA = (pixA & 0x000000FF);
const u32 gA = (pixA & 0x0000FF00) >> 8;
const u32 bA = (pixA & 0x00FF0000) >> 16;
const u32 aA = (pixA & 0xFF000000) >> 24;
const u32 rB = (pixB & 0x000000FF);
const u32 gB = (pixB & 0x0000FF00) >> 8;
const u32 bB = (pixB & 0x00FF0000) >> 16;
const u32 rC = ( (rB - rA <= threshold) || (rA - rB <= threshold) ) ? ( ((rA+rB)>>1) ) : rA;
const u32 gC = ( (gB - gA <= threshold) || (gA - gB <= threshold) ) ? ( ((gA+gB)>>1) ) : gA;
const u32 bC = ( (bB - bA <= threshold) || (bA - bB <= threshold) ) ? ( ((bA+bB)>>1) ) : bA;
const u32 aC = ( (bB - aA <= threshold) || (aA - aB <= threshold) ) ? ( ((aA+aB)>>1) ) : aA;
return (rC | (gC << 8) | (bC << 16) | (aC << 24));
}
static u32 TextureDeposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA, const u32 weightB)
{
const u32 aB = (pixB & 0xFF000000) >> 24;
if (aB == 0)
{
return pixA;
}
const u32 weightSum = weightA + weightB;
const u32 rbA = pixA & 0x00FF00FF;
const u32 gA = pixA & 0x0000FF00;
const u32 aA = (pixA & 0xFF000000) >> 24;
const u32 rbB = pixB & 0x00FF00FF;
const u32 gB = pixB & 0x0000FF00;
const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / weightSum ) & 0x00FF00FF;
const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / weightSum ) & 0x0000FF00;
const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / weightSum ) << 24;
return (rbC | gC | aC);
}
FragmentAttributesBuffer::FragmentAttributesBuffer(size_t newCount)
{
count = newCount;
@ -284,15 +235,26 @@ Render3D::Render3D()
_textureScalingFactor = 1;
_textureSmooth = false;
_textureDeposterizeBuffer = NULL;
_textureUpscaleBuffer = NULL;
memset(&_textureDeposterizeSrcSurface, 0, sizeof(_textureDeposterizeSrcSurface));
memset(&_textureDeposterizeDstSurface, 0, sizeof(_textureDeposterizeDstSurface));
_textureDeposterizeSrcSurface.Width = _textureDeposterizeDstSurface.Width = 1;
_textureDeposterizeSrcSurface.Height = _textureDeposterizeDstSurface.Height = 1;
_textureDeposterizeSrcSurface.Pitch = _textureDeposterizeDstSurface.Pitch = 1;
Reset();
}
Render3D::~Render3D()
{
// Do nothing.
if (this->_textureDeposterizeDstSurface.Surface != NULL)
{
free_aligned(this->_textureDeposterizeDstSurface.Surface);
this->_textureDeposterizeDstSurface.Surface = NULL;
this->_textureDeposterizeDstSurface.workingSurface[0] = NULL;
}
}
const Render3DDeviceInfo& Render3D::GetDeviceInfo()
@ -384,20 +346,24 @@ void Render3D::SetTextureProcessingProperties(size_t scalingFactor, bool willDep
const size_t newScalingFactor = (isScaleValid) ? scalingFactor : 1;
bool needTexCacheReset = false;
if ( willDeposterize && (this->_textureDeposterizeBuffer == NULL) )
if ( willDeposterize && (this->_textureDeposterizeDstSurface.Surface == NULL) )
{
// 1024x1024 texels is the largest possible texture size.
// We need two buffers, one for each deposterize stage.
const size_t bufferSize = 1024 * 1024 * 2 * sizeof(u32);
this->_textureDeposterizeBuffer = (u32 *)malloc_alignedCacheLine(bufferSize);
memset(this->_textureDeposterizeBuffer, 0, bufferSize);
this->_textureDeposterizeDstSurface.Surface = (unsigned char *)malloc_alignedCacheLine(bufferSize);
this->_textureDeposterizeDstSurface.workingSurface[0] = (unsigned char *)((u32 *)this->_textureDeposterizeDstSurface.Surface + (1024 * 1024));
memset(this->_textureDeposterizeDstSurface.Surface, 0, bufferSize);
needTexCacheReset = true;
}
else if ( !willDeposterize && (this->_textureDeposterizeBuffer != NULL) )
else if ( !willDeposterize && (this->_textureDeposterizeDstSurface.Surface != NULL) )
{
free_aligned(this->_textureDeposterizeBuffer);
this->_textureDeposterizeBuffer = NULL;
free_aligned(this->_textureDeposterizeDstSurface.Surface);
this->_textureDeposterizeDstSurface.Surface = NULL;
this->_textureDeposterizeDstSurface.workingSurface[0] = NULL;
needTexCacheReset = true;
}
@ -422,124 +388,17 @@ void Render3D::SetTextureProcessingProperties(size_t scalingFactor, bool willDep
if (needTexCacheReset)
{
TexCache_Reset();
texCache.Reset();
}
}
Render3DError Render3D::TextureDeposterize(const u32 *src, const size_t srcTexWidth, const size_t srcTexHeight)
{
//---------------------------------------\n\
// Input Pixel Mapping: 06|07|08
// 05|00|01
// 04|03|02
//
// Output Pixel Mapping: 00
this->_textureDeposterizeSrcSurface.Width = this->_textureDeposterizeDstSurface.Width = srcTexWidth;
this->_textureDeposterizeSrcSurface.Height = this->_textureDeposterizeDstSurface.Height = srcTexHeight;
this->_textureDeposterizeSrcSurface.Surface = (unsigned char *)src;
const int w = srcTexWidth;
const int h = srcTexHeight;
u32 color[9];
u32 blend[9];
u32 *dst = this->_textureDeposterizeBuffer + (1024 * 1024);
u32 *finalDst = this->_textureDeposterizeBuffer;
size_t i = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
dst[i] = src[i];
continue;
}
color[0] = src[i];
color[1] = (x < w-1) ? src[i+1] : src[i];
color[2] = ((x < w-1) && (y < h-1)) ? src[i+w+1] : src[i];
color[3] = (y < h-1) ? src[i+w] : src[i];
color[4] = ((x > 0) && (y < h-1)) ? src[i+w-1] : src[i];
color[5] = (x > 0) ? src[i-1] : src[i];
color[6] = ((x > 0) && (y > 0)) ? src[i-w-1] : src[i];
color[7] = (y > 0) ? src[i-w] : src[i];
color[8] = ((x < w-1) && (y > 0)) ? src[i-w+1] : src[i];
blend[0] = color[0];
blend[1] = TextureDeposterize_InterpLTE(color[0], color[1], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[2] = TextureDeposterize_InterpLTE(color[0], color[2], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[3] = TextureDeposterize_InterpLTE(color[0], color[3], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[4] = TextureDeposterize_InterpLTE(color[0], color[4], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[5] = TextureDeposterize_InterpLTE(color[0], color[5], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[6] = TextureDeposterize_InterpLTE(color[0], color[6], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[7] = TextureDeposterize_InterpLTE(color[0], color[7], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[8] = TextureDeposterize_InterpLTE(color[0], color[8], TEXTURE_DEPOSTERIZE_THRESHOLD);
dst[i] = TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[5], 1, 7),
TextureDeposterize_Blend(blend[0], blend[1], 1, 7),
1, 1),
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[7], 1, 7),
TextureDeposterize_Blend(blend[0], blend[3], 1, 7),
1, 1),
1, 1),
TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[6], 7, 9),
TextureDeposterize_Blend(blend[0], blend[2], 7, 9),
1, 1),
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[8], 7, 9),
TextureDeposterize_Blend(blend[0], blend[4], 7, 9),
1, 1),
1, 1),
3, 1);
}
}
i = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++, i++)
{
if ((src[i] & 0xFF000000) == 0)
{
finalDst[i] = src[i];
continue;
}
color[0] = dst[i];
color[1] = (x < w-1) ? dst[i+1] : dst[i];
color[2] = ((x < w-1) && (y < h-1)) ? dst[i+w+1] : dst[i];
color[3] = (y < h-1) ? dst[i+w] : dst[i];
color[4] = ((x > 0) && (y < h-1)) ? dst[i+w-1] : dst[i];
color[5] = (x > 0) ? dst[i-1] : dst[i];
color[6] = ((x > 0) && (y > 0)) ? dst[i-w-1] : dst[i];
color[7] = (y > 0) ? dst[i-w] : dst[i];
color[8] = ((x < w-1) && (y > 0)) ? dst[i-w+1] : dst[i];
blend[0] = color[0];
blend[1] = TextureDeposterize_InterpLTE(color[0], color[1], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[2] = TextureDeposterize_InterpLTE(color[0], color[2], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[3] = TextureDeposterize_InterpLTE(color[0], color[3], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[4] = TextureDeposterize_InterpLTE(color[0], color[4], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[5] = TextureDeposterize_InterpLTE(color[0], color[5], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[6] = TextureDeposterize_InterpLTE(color[0], color[6], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[7] = TextureDeposterize_InterpLTE(color[0], color[7], TEXTURE_DEPOSTERIZE_THRESHOLD);
blend[8] = TextureDeposterize_InterpLTE(color[0], color[8], TEXTURE_DEPOSTERIZE_THRESHOLD);
finalDst[i] = TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[5], 1, 7),
TextureDeposterize_Blend(blend[0], blend[1], 1, 7),
1, 1),
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[7], 1, 7),
TextureDeposterize_Blend(blend[0], blend[3], 1, 7),
1, 1),
1, 1),
TextureDeposterize_Blend(TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[6], 7, 9),
TextureDeposterize_Blend(blend[0], blend[2], 7, 9),
1, 1),
TextureDeposterize_Blend(TextureDeposterize_Blend(blend[0], blend[8], 7, 9),
TextureDeposterize_Blend(blend[0], blend[4], 7, 9),
1, 1),
1, 1),
3, 1);
}
}
RenderDeposterize(this->_textureDeposterizeSrcSurface, this->_textureDeposterizeDstSurface);
return RENDER3DERROR_NOERR;
}
@ -756,7 +615,7 @@ Render3DError Render3D::Reset()
this->_willFlushFramebufferRGBA6665 = true;
this->_willFlushFramebufferRGBA5551 = true;
TexCache_Reset();
texCache.Reset();
return RENDER3DERROR_NOERR;
}
@ -798,7 +657,7 @@ Render3DError Render3D::RenderFinish()
Render3DError Render3D::VramReconfigureSignal()
{
TexCache_Invalidate();
texCache.Invalidate();
return RENDER3DERROR_NOERR;
}

View File

@ -21,6 +21,7 @@
#include "gfx3d.h"
#include "types.h"
#include "./filter/filter.h"
#define kUnsetTranslucentPolyID 255
@ -130,7 +131,10 @@ protected:
size_t _textureScalingFactor;
bool _textureSmooth;
u32 *_textureDeposterizeBuffer;
SSurface _textureDeposterizeSrcSurface;
SSurface _textureDeposterizeDstSurface;
u32 *_textureUpscaleBuffer;
CACHE_ALIGN u16 clearImageColor16Buffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];

File diff suppressed because it is too large Load Diff

View File

@ -21,90 +21,169 @@
#define _TEXCACHE_H_
#include <map>
#include <vector>
#include "types.h"
#include "common.h"
#include "gfx3d.h"
enum TexCache_TexFormat
//this ought to be enough for anyone
//#define TEXCACHE_DEFAULT_THRESHOLD (64*1024*1024)
//changed by zeromus on 15-dec. I couldnt find any games that were getting anywhere NEAR 64
//metal slug burns through sprites so fast, it can test it pretty quickly though
//#define TEXCACHE_DEFAULT_THRESHOLD (16*1024*1024)
// rogerman, 2016-11-02: Increase this to 32MB for games that use many large textures, such
// as Umihara Kawase Shun, which can cache over 20MB in the first level.
#define TEXCACHE_DEFAULT_THRESHOLD (32*1024*1024)
#define PALETTE_DUMP_SIZE ((64+16+16)*1024)
enum TextureStoreUnpackFormat
{
TexFormat_None = 0, //used when nothing yet is cached
TexFormat_32bpp, //used by ogl renderer
TexFormat_15bpp //used by rasterizer
};
class TexCacheItem;
class MemSpan;
class TextureStore;
typedef std::multimap<u32,TexCacheItem*> TTexCacheItemMultimap;
typedef void (*TexCacheItemDeleteCallback)(TexCacheItem *texItem, void *param1, void *param2);
typedef u64 TextureCacheKey;
typedef std::map<TextureCacheKey, TextureStore *> TextureCacheMap; // Key = A TextureCacheKey that includes a combination of the texture's NDS texture attributes and palette attributes; Value = Pointer to the texture item
typedef std::vector<TextureStore *> TextureCacheList;
//typedef u32 TextureFingerprint;
class TexCacheItem
class TextureCache
{
private:
TexCacheItemDeleteCallback _deleteCallback;
void *_deleteCallbackParam1;
void *_deleteCallbackParam2;
protected:
TextureCacheMap _texCacheMap; // Used to quickly find a texture item by using a key of type TextureCacheKey
TextureCacheList _texCacheList; // Used to sort existing texture items for various operations
size_t _actualCacheSize;
size_t _cacheSizeThreshold;
u8 _paletteDump[PALETTE_DUMP_SIZE];
public:
TexCacheItem()
: decode_len(0)
, decoded(NULL)
, suspectedInvalid(false)
, assumedInvalid(false)
, _deleteCallback(NULL)
, _deleteCallbackParam1(NULL)
, _deleteCallbackParam2(NULL)
, cacheFormat(TexFormat_None)
{}
TextureCache();
~TexCacheItem()
{
free_aligned(this->decoded);
if (this->_deleteCallback != NULL) this->_deleteCallback(this, this->_deleteCallbackParam1, this->_deleteCallbackParam2);
}
u32 decode_len;
NDSTextureFormat format;
u8* decoded; //decoded texture data
bool suspectedInvalid;
bool assumedInvalid;
TTexCacheItemMultimap::iterator iterator;
NDSTextureFormat GetTextureFormat() const { return this->format; }
u32 texformat, texpal;
u32 sizeX, sizeY;
float invSizeX, invSizeY;
u32 texid; //used by ogl renderer for the texid
TexCache_TexFormat cacheFormat;
struct Dump {
~Dump() {
delete[] texture;
}
int textureSize, indexSize;
static const int maxTextureSize=128*1024;
u8* texture;
u8 palette[256*2];
} dump;
size_t GetActualCacheSize() const;
size_t GetCacheSizeThreshold() const;
void SetCacheSizeThreshold(size_t newThreshold);
TexCacheItemDeleteCallback GetDeleteCallback()
{
return this->_deleteCallback;
}
void Invalidate();
void Evict();
void Reset();
void SetDeleteCallback(TexCacheItemDeleteCallback callbackFunc, void *inParam1, void *inParam2)
{
this->_deleteCallback = callbackFunc;
this->_deleteCallbackParam1 = inParam1;
this->_deleteCallbackParam2 = inParam2;
}
TextureStore* GetTexture(u32 texAttributes, u32 palAttributes);
void Add(TextureStore *texItem);
void Remove(TextureStore *texItem);
static TextureCacheKey GenerateKey(const u32 texAttributes, const u32 palAttributes);
};
void TexCache_Invalidate();
void TexCache_Reset();
void TexCache_EvictFrame();
class TextureStore
{
protected:
u32 _textureAttributes;
u32 _paletteAttributes;
u32 _sizeS;
u32 _sizeT;
bool _isPalZeroTransparent;
NDSTextureFormat _packFormat;
u32 _packAddress;
u32 _packSize;
u8 *_packData;
u32 _paletteAddress;
u32 _paletteSize;
u16 *_paletteColorTable;
// Only used by 4x4 formatted textures
u32 _packIndexAddress;
u32 _packIndexSize;
u8 *_packIndexData;
u32 _packSizeFirstSlot;
bool _suspectedInvalid;
bool _assumedInvalid;
bool _isLoadNeeded;
TextureCacheKey _cacheKey;
size_t _cacheSize;
size_t _cacheAge; // A value of 0 means the texture was just used. The higher this value, the older the texture.
size_t _cacheUsageCount;
public:
TextureStore();
TextureStore(const u32 texAttributes, const u32 palAttributes);
virtual ~TextureStore();
u32 GetTextureAttributes() const;
u32 GetPaletteAttributes() const;
u32 GetWidth() const;
u32 GetHeight() const;
bool IsPalZeroTransparent() const;
NDSTextureFormat GetPackFormat() const;
u32 GetPackAddress() const;
u32 GetPackSize() const;
u8* GetPackData();
u32 GetPaletteAddress() const;
u32 GetPaletteSize() const;
u16* GetPaletteColorTable() const;
u32 GetPackIndexAddress() const;
u32 GetPackIndexSize() const;
u8* GetPackIndexData();
void SetTextureData(const MemSpan &packedData, const MemSpan &packedIndexData);
void SetTexturePalette(const MemSpan &packedPalette);
void SetTexturePalette(const u16 *paletteBuffer);
size_t GetUnpackSizeUsingFormat(const TextureStoreUnpackFormat texCacheFormat) const;
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void Unpack(u32 *unpackBuffer);
bool IsSuspectedInvalid() const;
void SetSuspectedInvalid();
bool IsAssumedInvalid() const;
void SetAssumedInvalid();
void SetLoadNeeded();
bool IsLoadNeeded() const;
TextureCacheKey GetCacheKey() const;
size_t GetCacheSize() const;
void SetCacheSize(size_t cacheSize);
size_t GetCacheAge() const;
void IncreaseCacheAge(const size_t ageAmount);
void ResetCacheAge();
size_t GetCacheUseCount() const;
void IncreaseCacheUsageCount(const size_t usageCount);
void ResetCacheUsageCount();
void Update();
void VRAMCompareAndUpdate();
void DebugDump();
};
TexCacheItem* TexCache_SetTexture(TexCache_TexFormat TEXFORMAT, u32 format, u32 texpal);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI2(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI4(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackI8(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, const bool isPalZeroTransparent, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackA3I5(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackA5I3(const size_t srcSize, const u8 *__restrict srcData, const u16 *__restrict srcPal, u32 *__restrict dstBuffer);
template<TextureStoreUnpackFormat TEXCACHEFORMAT> 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<TextureStoreUnpackFormat TEXCACHEFORMAT> void NDSTextureUnpackDirect16Bit(const size_t srcSize, const u16 *__restrict srcData, u32 *__restrict dstBuffer);
extern TextureCache texCache;
#endif

View File

@ -142,90 +142,6 @@ void ColorspaceHandlerInit()
}
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert555To8888Opaque(const u16 src)
{
return (SWAP_RB) ? COLOR555TO8888_OPAQUE_SWAP_RB(src & 0x7FFF) : COLOR555TO8888_OPAQUE(src & 0x7FFF);
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert555To6665Opaque(const u16 src)
{
return (SWAP_RB) ? COLOR555TO6665_OPAQUE_SWAP_RB(src & 0x7FFF) : COLOR555TO6665_OPAQUE(src & 0x7FFF);
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert8888To6665(FragmentColor srcColor)
{
FragmentColor outColor;
outColor.r = ((SWAP_RB) ? srcColor.b : srcColor.r) >> 2;
outColor.g = srcColor.g >> 2;
outColor.b = ((SWAP_RB) ? srcColor.r : srcColor.b) >> 2;
outColor.a = srcColor.a >> 3;
return outColor.color;
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert8888To6665(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert8888To6665<SWAP_RB>(srcColorComponent);
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert6665To8888(FragmentColor srcColor)
{
FragmentColor outColor;
outColor.r = material_6bit_to_8bit[((SWAP_RB) ? srcColor.b : srcColor.r)];
outColor.g = material_6bit_to_8bit[srcColor.g];
outColor.b = material_6bit_to_8bit[((SWAP_RB) ? srcColor.r : srcColor.b)];
outColor.a = material_5bit_to_8bit[srcColor.a];
return outColor.color;
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert6665To8888(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert6665To8888<SWAP_RB>(srcColorComponent);
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert8888To5551(FragmentColor srcColor)
{
return R5G5B5TORGB15( ((SWAP_RB) ? srcColor.b : srcColor.r) >> 3, srcColor.g >> 3, ((SWAP_RB) ? srcColor.r : srcColor.b) >> 3) | ((srcColor.a == 0) ? 0x0000 : 0x8000 );
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert8888To5551(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert8888To5551<SWAP_RB>(srcColorComponent);
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert6665To5551(FragmentColor srcColor)
{
return R6G6B6TORGB15( ((SWAP_RB) ? srcColor.b : srcColor.r), srcColor.g, ((SWAP_RB) ? srcColor.r : srcColor.b)) | ((srcColor.a == 0) ? 0x0000 : 0x8000);
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert6665To5551(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert6665To5551<SWAP_RB>(srcColorComponent);
}
template <bool SWAP_RB, bool IS_UNALIGNED>
void ColorspaceConvertBuffer555To8888Opaque(const u16 *__restrict src, u32 *__restrict dst, size_t pixCount)
{
@ -718,36 +634,6 @@ size_t ColorspaceHandler::ConvertBuffer6665To5551_SwapRB_IsUnaligned(const u32 *
return this->ColorspaceHandler::ConvertBuffer6665To5551_SwapRB(src, dst, pixCount);
}
template u32 ColorspaceConvert555To8888Opaque<true>(const u16 src);
template u32 ColorspaceConvert555To8888Opaque<false>(const u16 src);
template u32 ColorspaceConvert555To6665Opaque<true>(const u16 src);
template u32 ColorspaceConvert555To6665Opaque<false>(const u16 src);
template u32 ColorspaceConvert8888To6665<true>(FragmentColor srcColor);
template u32 ColorspaceConvert8888To6665<false>(FragmentColor srcColor);
template u32 ColorspaceConvert8888To6665<true>(u32 srcColor);
template u32 ColorspaceConvert8888To6665<false>(u32 srcColor);
template u32 ColorspaceConvert6665To8888<true>(FragmentColor srcColor);
template u32 ColorspaceConvert6665To8888<false>(FragmentColor srcColor);
template u32 ColorspaceConvert6665To8888<true>(u32 srcColor);
template u32 ColorspaceConvert6665To8888<false>(u32 srcColor);
template u16 ColorspaceConvert8888To5551<true>(FragmentColor srcColor);
template u16 ColorspaceConvert8888To5551<false>(FragmentColor srcColor);
template u16 ColorspaceConvert8888To5551<true>(u32 srcColor);
template u16 ColorspaceConvert8888To5551<false>(u32 srcColor);
template u16 ColorspaceConvert6665To5551<true>(FragmentColor srcColor);
template u16 ColorspaceConvert6665To5551<false>(FragmentColor srcColor);
template u16 ColorspaceConvert6665To5551<true>(u32 srcColor);
template u16 ColorspaceConvert6665To5551<false>(u32 srcColor);
template void ColorspaceConvertBuffer555To8888Opaque<true, true>(const u16 *__restrict src, u32 *__restrict dst, size_t pixCount);
template void ColorspaceConvertBuffer555To8888Opaque<true, false>(const u16 *__restrict src, u32 *__restrict dst, size_t pixCount);
template void ColorspaceConvertBuffer555To8888Opaque<false, true>(const u16 *__restrict src, u32 *__restrict dst, size_t pixCount);

View File

@ -130,16 +130,89 @@ extern CACHE_ALIGN u32 color_555_to_888[32768];
void ColorspaceHandlerInit();
template<bool SWAP_RB> u32 ColorspaceConvert555To8888Opaque(const u16 src);
template<bool SWAP_RB> u32 ColorspaceConvert555To6665Opaque(const u16 src);
template<bool SWAP_RB> u32 ColorspaceConvert8888To6665(FragmentColor srcColor);
template<bool SWAP_RB> u32 ColorspaceConvert8888To6665(u32 srcColor);
template<bool SWAP_RB> u32 ColorspaceConvert6665To8888(FragmentColor srcColor);
template<bool SWAP_RB> u32 ColorspaceConvert6665To8888(u32 srcColor);
template<bool SWAP_RB> u16 ColorspaceConvert8888To5551(FragmentColor srcColor);
template<bool SWAP_RB> u16 ColorspaceConvert8888To5551(u32 srcColor);
template<bool SWAP_RB> u16 ColorspaceConvert6665To5551(FragmentColor srcColor);
template<bool SWAP_RB> u16 ColorspaceConvert6665To5551(u32 srcColor);
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert555To8888Opaque(const u16 src)
{
return (SWAP_RB) ? COLOR555TO8888_OPAQUE_SWAP_RB(src & 0x7FFF) : COLOR555TO8888_OPAQUE(src & 0x7FFF);
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert555To6665Opaque(const u16 src)
{
return (SWAP_RB) ? COLOR555TO6665_OPAQUE_SWAP_RB(src & 0x7FFF) : COLOR555TO6665_OPAQUE(src & 0x7FFF);
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert8888To6665(FragmentColor srcColor)
{
FragmentColor outColor;
outColor.r = ((SWAP_RB) ? srcColor.b : srcColor.r) >> 2;
outColor.g = srcColor.g >> 2;
outColor.b = ((SWAP_RB) ? srcColor.r : srcColor.b) >> 2;
outColor.a = srcColor.a >> 3;
return outColor.color;
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert8888To6665(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert8888To6665<SWAP_RB>(srcColorComponent);
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert6665To8888(FragmentColor srcColor)
{
FragmentColor outColor;
outColor.r = material_6bit_to_8bit[((SWAP_RB) ? srcColor.b : srcColor.r)];
outColor.g = material_6bit_to_8bit[srcColor.g];
outColor.b = material_6bit_to_8bit[((SWAP_RB) ? srcColor.r : srcColor.b)];
outColor.a = material_5bit_to_8bit[srcColor.a];
return outColor.color;
}
template <bool SWAP_RB>
FORCEINLINE u32 ColorspaceConvert6665To8888(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert6665To8888<SWAP_RB>(srcColorComponent);
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert8888To5551(FragmentColor srcColor)
{
return R5G5B5TORGB15( ((SWAP_RB) ? srcColor.b : srcColor.r) >> 3, srcColor.g >> 3, ((SWAP_RB) ? srcColor.r : srcColor.b) >> 3) | ((srcColor.a == 0) ? 0x0000 : 0x8000 );
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert8888To5551(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert8888To5551<SWAP_RB>(srcColorComponent);
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert6665To5551(FragmentColor srcColor)
{
return R6G6B6TORGB15( ((SWAP_RB) ? srcColor.b : srcColor.r), srcColor.g, ((SWAP_RB) ? srcColor.r : srcColor.b)) | ((srcColor.a == 0) ? 0x0000 : 0x8000);
}
template <bool SWAP_RB>
FORCEINLINE u16 ColorspaceConvert6665To5551(u32 srcColor)
{
FragmentColor srcColorComponent;
srcColorComponent.color = srcColor;
return ColorspaceConvert6665To5551<SWAP_RB>(srcColorComponent);
}
template<bool SWAP_RB, bool IS_UNALIGNED> void ColorspaceConvertBuffer555To8888Opaque(const u16 *__restrict src, u32 *__restrict dst, size_t pixCount);
template<bool SWAP_RB, bool IS_UNALIGNED> void ColorspaceConvertBuffer555To6665Opaque(const u16 *__restrict src, u32 *__restrict dst, size_t pixCount);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2009-2015 DeSmuME team
Copyright (C) 2009-2016 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -110,7 +110,8 @@ void Task::Impl::execute(const TWork &work, void *param)
{
slock_lock(this->mutex);
if (work == NULL || !this->_isThreadRunning) {
if ((work == NULL) || (this->workFunc != NULL) || !this->_isThreadRunning)
{
slock_unlock(this->mutex);
return;
}
@ -128,12 +129,13 @@ void* Task::Impl::finish()
slock_lock(this->mutex);
if (!this->_isThreadRunning) {
if ((this->workFunc == NULL) || !this->_isThreadRunning) {
slock_unlock(this->mutex);
return returnValue;
}
while (this->workFunc != NULL) {
while (this->workFunc != NULL)
{
scond_wait(this->condWork, this->mutex);
}

View File

@ -27,82 +27,79 @@
#include "../types.h"
#include "../debug.h"
#include "../emufile.h"
#include "retro_dirent.h"
#include "retro_stat.h"
#include "file/file_path.h"
#include "emufat.h"
#include "vfat.h"
#include "libfat/libfat_public_api.h"
#include <retro_dirent.h>
#include <retro_stat.h>
#include <file/file_path.h>
static char retro_dir[PATH_MAX_LENGTH];
enum EListCallbackArg {
EListCallbackArg_Item, EListCallbackArg_Pop
};
typedef void (*ListCallback)(RDIR *rdir, EListCallbackArg);
typedef void (*ListCallback)(RDIR* rdir, EListCallbackArg);
// List all files and subdirectories recursively
//TODO: clunky architecture. we've combined the callbacks into one handler.
//we could merge the callback and list_files function, or refactor the callback into one for each enum which receives a unit of work after
//the more detailed recursing logic (caused by libretro-common integration) is handled in the lister
static void list_files(const char *filepath, ListCallback list_callback)
{
void * hFind;
char *fname;
u32 dwError;
RDIR *rdir = retro_opendir(filepath);
if (!rdir)
return;
strcpy(retro_dir, filepath);
if (retro_dirent_error(rdir))
goto end;
RDIR* rdir = retro_opendir(filepath);
if(!rdir) return;
if(retro_dirent_error(rdir))
{
retro_closedir(rdir);
return;
}
for (;;)
{
const char *name = NULL;
if (!retro_readdir(rdir))
break;
for(;;)
{
if(!retro_readdir(rdir))
break;
const char *fname = retro_dirent_get_name(rdir);
list_callback(rdir,EListCallbackArg_Item);
const char* fname = retro_dirent_get_name(rdir);
list_callback(rdir,EListCallbackArg_Item);
printf("cflash added %s\n",fname);
if (retro_dirent_is_dir(rdir, filepath) && (strcmp(fname, ".")) && strcmp(fname, ".."))
{
std::string subdir = (std::string)filepath + path_default_slash() + fname;
list_files(subdir.c_str(), list_callback);
list_callback(rdir, EListCallbackArg_Pop);
if(retro_dirent_is_dir(rdir) && (strcmp(fname, ".")) && (strcmp(fname, "..")))
{
std::string subdir = (std::string)filepath + path_default_slash() + fname;
list_files(subdir.c_str(), list_callback);
list_callback(rdir, EListCallbackArg_Pop);
}
}
end:
retro_closedir(rdir);
retro_closedir(rdir);
}
static unsigned long dataSectors = 0;
void count_ListCallback(RDIR *rdir, EListCallbackArg arg)
enum eCallbackType
{
if(arg == EListCallbackArg_Pop)
return;
u32 sectors = 1;
if (!retro_dirent_is_dir(rdir, retro_dir))
{
const char *path = retro_dirent_get_name(rdir);
/* allocate sectors for file */
int32_t fileSize = path_get_size(path);
sectors += (fileSize+511)/512 + 1;
}
eCallbackType_Count, eCallbackType_Build
};
dataSectors += sectors;
}
static eCallbackType callbackType;
//for eCallbackType_Count:
static bool count_failed = false;
static u64 dataSectors = 0;
//recursing related.. really ought to be merged with list_files functionality
static std::string currPath;
static std::stack<std::string> pathStack;
static std::stack<std::string> virtPathStack;
static std::string currVirtPath;
void build_ListCallback(RDIR *rdir, EListCallbackArg arg)
static void DirectoryListCallback(RDIR* rdir, EListCallbackArg arg)
{
const char *fname = retro_dirent_get_name(rdir);
const char* fname = retro_dirent_get_name(rdir);
if(arg == EListCallbackArg_Pop)
{
@ -113,7 +110,7 @@ void build_ListCallback(RDIR *rdir, EListCallbackArg arg)
return;
}
if (retro_dirent_is_dir(rdir, retro_dir))
if(retro_dirent_is_dir(rdir))
{
if(!strcmp(fname,".")) return;
if(!strcmp(fname,"..")) return;
@ -122,10 +119,18 @@ void build_ListCallback(RDIR *rdir, EListCallbackArg arg)
virtPathStack.push(currVirtPath);
currVirtPath = currVirtPath + "/" + fname;
bool ok = LIBFAT::MkDir(currVirtPath.c_str());
if(!ok)
printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str());
if(callbackType == eCallbackType_Build)
{
bool ok = LIBFAT::MkDir(currVirtPath.c_str());
if(!ok)
printf("ERROR adding dir %s via libfat\n",currVirtPath.c_str());
}
else
{
dataSectors++; //directories take one sector
}
currPath = currPath + path_default_slash() + fname;
return;
@ -134,47 +139,56 @@ void build_ListCallback(RDIR *rdir, EListCallbackArg arg)
{
std::string path = currPath + path_default_slash() + fname;
FILE* inf = fopen(path.c_str(),"rb");
if(inf)
if(callbackType == eCallbackType_Build)
{
u8 * buf;
size_t elements_read;
long len;
FILE* inf = fopen(path.c_str(),"rb");
if(inf)
{
fseek(inf,0,SEEK_END);
long len = ftell(inf);
fseek(inf,0,SEEK_SET);
u8 *buf = new u8[len];
fread(buf,1,len,inf);
fclose(inf);
fseek(inf, 0, SEEK_END);
len = ftell(inf);
fseek(inf, 0, SEEK_SET);
buf = new u8[len];
elements_read = fread(buf, 1, len, inf);
if (elements_read != len)
printf(
"libfat: %lu bytes read instead of %l.\n",
elements_read,
len
);
fclose(inf);
std::string path = currVirtPath + "/" + fname;
printf("FAT + (%10.2f KB) %s \n",len/1024.f,path.c_str());
bool ok = LIBFAT::WriteFile(path.c_str(),buf,len);
if(!ok)
printf("ERROR adding file to fat\n");
delete[] buf;
} else printf("ERROR opening file for fat\n");
std::string path = currVirtPath + "/" + fname;
printf("FAT + (%10.2f KB) %s \n",len/1024.f,path.c_str());
bool ok = LIBFAT::WriteFile(path.c_str(),buf,len);
if(!ok)
printf("ERROR adding file to fat\n");
delete[] buf;
} else printf("ERROR opening file for fat\n");
}
else
{
//allocate sectors for file
int32_t fileSize = path_get_size(path.c_str());
if(fileSize == -1) { count_failed = true; dataSectors = 0; }
else dataSectors += (fileSize+511)/512 + 1;
}
}
}
bool VFAT::build(const char* path, int extra_MB)
{
dataSectors = 0;
currVirtPath = "";
currPath = path;
list_files(path, count_ListCallback);
count_failed = false;
callbackType = eCallbackType_Count;
list_files(path, DirectoryListCallback);
if(count_failed)
{
printf("FAILED enumerating files for fat\n");
return false;
}
dataSectors += 8; //a few for reserved sectors, etc.
dataSectors += extra_MB*1024*1024/512; //add extra write space
//dataSectors += 16*1024*1024/512; //add 16MB worth of write space. this is probably enough for anyone, but maybe it should be configurable.
//we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded)
@ -185,10 +199,7 @@ bool VFAT::build(const char* path, int extra_MB)
if(dataSectors>=(0x80000000>>9))
{
printf(
"error allocating memory for fat (%lu KBytes)\n",
(dataSectors*512) / 1024
);
printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024);
printf("total fat sizes > 2GB are never going to work\n");
}
@ -199,10 +210,7 @@ bool VFAT::build(const char* path, int extra_MB)
}
catch(std::bad_alloc)
{
printf(
"error allocating memory for fat (%lu KBytes)\n",
(dataSectors*512) / 1024
);
printf("error allocating memory for fat (%d KBytes)\n",(dataSectors*512)/1024);
printf("(out of memory)\n");
return false;
}
@ -225,7 +233,8 @@ bool VFAT::build(const char* path, int extra_MB)
//setup libfat and write all the files through it
LIBFAT::Init(memf->buf(),memf->size());
list_files(path, build_ListCallback);
callbackType = eCallbackType_Build;
list_files(path, DirectoryListCallback);
LIBFAT::Shutdown();
return true;
@ -246,4 +255,4 @@ EMUFILE* VFAT::detach()
EMUFILE* ret = file;
file = NULL;
return ret;
}
}