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:
commit
f97283e9bc
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -869,7 +869,7 @@
|
|||
[super handleEmuFrameProcessed];
|
||||
|
||||
NDSFrameInfo frameInfo;
|
||||
frameInfo.render3DFPS = Render3DFramesPerSecond;
|
||||
frameInfo.render3DFPS = GPU->GetFPSRender3D();
|
||||
frameInfo.frameIndex = currFrameCounter;
|
||||
frameInfo.lagFrameCount = TotalLagFrames;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -280,6 +280,7 @@ private:
|
|||
{
|
||||
mPositionCacheEnabled = false;
|
||||
mCondition = eCondition_Clean;
|
||||
mFilePosition = 0;
|
||||
fp = fopen(fname,mode);
|
||||
if(!fp)
|
||||
failbit = true;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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_
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue