Merge branch 'blackmagic'
BAHAHAHHAHAHAHAAHAHAHAHHH HARK HARK HARK HARK HA-*~
This commit is contained in:
commit
94f5ecb647
75
melonDS.cbp
75
melonDS.cbp
|
@ -19,22 +19,6 @@
|
|||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add library="SDL2" />
|
||||
<Add library="shell32" />
|
||||
<Add library="comctl32" />
|
||||
<Add library="comdlg32" />
|
||||
<Add library="advapi32" />
|
||||
<Add library="wsock32" />
|
||||
<Add library="oleacc" />
|
||||
<Add library="ole32" />
|
||||
<Add library="usp10" />
|
||||
<Add library="gdi32" />
|
||||
<Add library="d2d1" />
|
||||
<Add library="dwrite" />
|
||||
<Add library="uxtheme" />
|
||||
<Add library="iphlpapi" />
|
||||
<Add library="user32" />
|
||||
<Add library="ws2_32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release Windows">
|
||||
|
@ -51,22 +35,6 @@
|
|||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m64" />
|
||||
<Add library="SDL2" />
|
||||
<Add library="shell32" />
|
||||
<Add library="comctl32" />
|
||||
<Add library="comdlg32" />
|
||||
<Add library="advapi32" />
|
||||
<Add library="wsock32" />
|
||||
<Add library="oleacc" />
|
||||
<Add library="ole32" />
|
||||
<Add library="usp10" />
|
||||
<Add library="gdi32" />
|
||||
<Add library="d2d1" />
|
||||
<Add library="dwrite" />
|
||||
<Add library="uxtheme" />
|
||||
<Add library="iphlpapi" />
|
||||
<Add library="user32" />
|
||||
<Add library="ws2_32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="DebugFast Windows">
|
||||
|
@ -82,22 +50,6 @@
|
|||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add library="SDL2" />
|
||||
<Add library="shell32" />
|
||||
<Add library="comctl32" />
|
||||
<Add library="comdlg32" />
|
||||
<Add library="advapi32" />
|
||||
<Add library="wsock32" />
|
||||
<Add library="oleacc" />
|
||||
<Add library="ole32" />
|
||||
<Add library="usp10" />
|
||||
<Add library="gdi32" />
|
||||
<Add library="d2d1" />
|
||||
<Add library="dwrite" />
|
||||
<Add library="uxtheme" />
|
||||
<Add library="iphlpapi" />
|
||||
<Add library="user32" />
|
||||
<Add library="ws2_32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
|
@ -107,6 +59,25 @@
|
|||
<Add option="-pipe" />
|
||||
<Add directory="src" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add library="SDL2" />
|
||||
<Add library="shell32" />
|
||||
<Add library="comctl32" />
|
||||
<Add library="comdlg32" />
|
||||
<Add library="advapi32" />
|
||||
<Add library="wsock32" />
|
||||
<Add library="oleacc" />
|
||||
<Add library="ole32" />
|
||||
<Add library="usp10" />
|
||||
<Add library="gdi32" />
|
||||
<Add library="d2d1" />
|
||||
<Add library="dwrite" />
|
||||
<Add library="uxtheme" />
|
||||
<Add library="iphlpapi" />
|
||||
<Add library="user32" />
|
||||
<Add library="ws2_32" />
|
||||
<Add library="opengl32" />
|
||||
</Linker>
|
||||
<Unit filename="melon.rc">
|
||||
<Option compilerVar="WINDRES" />
|
||||
</Unit>
|
||||
|
@ -135,11 +106,15 @@
|
|||
<Unit filename="src/GPU2D.h" />
|
||||
<Unit filename="src/GPU3D.cpp" />
|
||||
<Unit filename="src/GPU3D.h" />
|
||||
<Unit filename="src/GPU3D_OpenGL.cpp" />
|
||||
<Unit filename="src/GPU3D_OpenGL_shaders.h" />
|
||||
<Unit filename="src/GPU3D_Soft.cpp" />
|
||||
<Unit filename="src/NDS.cpp" />
|
||||
<Unit filename="src/NDS.h" />
|
||||
<Unit filename="src/NDSCart.cpp" />
|
||||
<Unit filename="src/NDSCart.h" />
|
||||
<Unit filename="src/OpenGLSupport.cpp" />
|
||||
<Unit filename="src/OpenGLSupport.h" />
|
||||
<Unit filename="src/Platform.h" />
|
||||
<Unit filename="src/RTC.cpp" />
|
||||
<Unit filename="src/RTC.h" />
|
||||
|
@ -159,6 +134,8 @@
|
|||
<Unit filename="src/libui_sdl/DlgEmuSettings.h" />
|
||||
<Unit filename="src/libui_sdl/DlgInputConfig.cpp" />
|
||||
<Unit filename="src/libui_sdl/DlgInputConfig.h" />
|
||||
<Unit filename="src/libui_sdl/DlgVideoSettings.cpp" />
|
||||
<Unit filename="src/libui_sdl/DlgVideoSettings.h" />
|
||||
<Unit filename="src/libui_sdl/DlgWifiSettings.cpp" />
|
||||
<Unit filename="src/libui_sdl/DlgWifiSettings.h" />
|
||||
<Unit filename="src/libui_sdl/LAN_PCap.cpp" />
|
||||
|
@ -222,6 +199,7 @@
|
|||
<Unit filename="src/libui_sdl/libui/windows/fontbutton.cpp" />
|
||||
<Unit filename="src/libui_sdl/libui/windows/fontdialog.cpp" />
|
||||
<Unit filename="src/libui_sdl/libui/windows/form.cpp" />
|
||||
<Unit filename="src/libui_sdl/libui/windows/gl.cpp" />
|
||||
<Unit filename="src/libui_sdl/libui/windows/graphemes.cpp" />
|
||||
<Unit filename="src/libui_sdl/libui/windows/grid.cpp" />
|
||||
<Unit filename="src/libui_sdl/libui/windows/group.cpp" />
|
||||
|
@ -253,6 +231,7 @@
|
|||
<Unit filename="src/libui_sdl/libui/windows/winpublic.cpp" />
|
||||
<Unit filename="src/libui_sdl/libui/windows/winutil.cpp" />
|
||||
<Unit filename="src/libui_sdl/main.cpp" />
|
||||
<Unit filename="src/libui_sdl/main_shaders.h" />
|
||||
<Unit filename="src/pcap/bluetooth.h" />
|
||||
<Unit filename="src/pcap/bpf.h" />
|
||||
<Unit filename="src/pcap/can_socketcan.h" />
|
||||
|
|
14
src/ARM.cpp
14
src/ARM.cpp
|
@ -159,7 +159,7 @@ void ARM::SetupCodeMem(u32 addr)
|
|||
//NDS::ARM7GetMemRegion(addr, false, &CodeMem);
|
||||
}
|
||||
}
|
||||
|
||||
extern u64 vbltime;
|
||||
void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
||||
{
|
||||
if (restorecpsr)
|
||||
|
@ -180,6 +180,16 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||
if (R[15]==0x0204BE5E) printf("recvfrom() ret:%d errno:%d %08X\n", R[0], NDS::ARM9Read32(0x217F398), addr);
|
||||
if (R[15]==0x0205038A) printf("sgrecvfrom() ret:%d errno:%d %08X\n", R[0], NDS::ARM9Read32(0x217F398), addr);
|
||||
if (addr==0x02050379 || addr==0x0205036D) printf("morp %08X->%08X, %d\n", R[15], addr, R[7]);*/
|
||||
/*if (addr==0x020B5F14) printf("VRAM UNMAP %02X %08X\n", R[0], R[15]);
|
||||
if (addr==0x020B5FAC) printf("VRAM MAP %2X %08X\n", R[0], R[15]);
|
||||
if (addr==0x0209F860) printf("VRAM BLORP %02X %08X\n", R[0], R[15]);
|
||||
if (addr==0x02005A34) printf("VAZAVAZORP %08X. VCOUNT=%d\n", R[15], NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x0209FBEC) printf("COUILLON. %08X %08X\n", R[0], R[1]);
|
||||
if (addr==0x02004AA8) printf("ANEBATE 1 %d\n", NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x020058C8) printf("ANEBATE 2 %d\n", NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x02005398) printf("ANEBATE 3 %d %d\n", NDS::ARM9Read16(0x04000006), (u32)(NDS::ARM9Timestamp-vbltime));
|
||||
if (addr==0x02005A5C) printf("PLAFORP %d\n", NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x209FBDC) printf("ROLOLORP\n");*/
|
||||
|
||||
u32 oldregion = R[15] >> 24;
|
||||
u32 newregion = addr >> 24;
|
||||
|
@ -508,6 +518,8 @@ void ARMv5::Execute()
|
|||
}
|
||||
else
|
||||
AddCycles_C();
|
||||
|
||||
//if (R[15]>=0x02005A5C && R[15]<=0x02005A84) printf("NORP %08X %d\n", R[15]-8, NDS::ARM9Read16(0x04000006));
|
||||
}
|
||||
|
||||
// TODO optimize this shit!!!
|
||||
|
|
|
@ -28,12 +28,20 @@ namespace Config
|
|||
|
||||
const char* kConfigFile = "melonDS.ini";
|
||||
|
||||
int _3DRenderer;
|
||||
int Threaded3D;
|
||||
|
||||
int GL_ScaleFactor;
|
||||
int GL_Antialias;
|
||||
|
||||
ConfigEntry ConfigFile[] =
|
||||
{
|
||||
{"3DRenderer", 0, &_3DRenderer, 1, NULL, 0},
|
||||
{"Threaded3D", 0, &Threaded3D, 1, NULL, 0},
|
||||
|
||||
{"GL_ScaleFactor", 0, &GL_ScaleFactor, 1, NULL, 0},
|
||||
{"GL_Antialias", 0, &GL_Antialias, 0, NULL, 0},
|
||||
|
||||
{"", -1, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
|
|
@ -40,8 +40,12 @@ bool HasConfigFile(const char* fileName);
|
|||
void Load();
|
||||
void Save();
|
||||
|
||||
extern int _3DRenderer;
|
||||
extern int Threaded3D;
|
||||
|
||||
extern int GL_ScaleFactor;
|
||||
extern int GL_Antialias;
|
||||
|
||||
}
|
||||
|
||||
#endif // CONFIG_H
|
||||
|
|
101
src/GPU.cpp
101
src/GPU.cpp
|
@ -20,7 +20,7 @@
|
|||
#include <string.h>
|
||||
#include "NDS.h"
|
||||
#include "GPU.h"
|
||||
|
||||
u64 vbltime;
|
||||
|
||||
namespace GPU
|
||||
{
|
||||
|
@ -71,7 +71,9 @@ u32 VRAMMap_TexPal[8];
|
|||
|
||||
u32 VRAMMap_ARM7[2];
|
||||
|
||||
u32 Framebuffer[256*192*2];
|
||||
int FrontBuffer;
|
||||
u32* Framebuffer[2][2];
|
||||
bool Accelerated;
|
||||
|
||||
GPU2D* GPU2D_A;
|
||||
GPU2D* GPU2D_B;
|
||||
|
@ -83,6 +85,12 @@ bool Init()
|
|||
GPU2D_B = new GPU2D(1);
|
||||
if (!GPU3D::Init()) return false;
|
||||
|
||||
FrontBuffer = 0;
|
||||
Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL;
|
||||
Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL;
|
||||
Accelerated = false;
|
||||
SetDisplaySettings(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -91,6 +99,11 @@ void DeInit()
|
|||
delete GPU2D_A;
|
||||
delete GPU2D_B;
|
||||
GPU3D::DeInit();
|
||||
|
||||
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
|
||||
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
||||
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
||||
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
|
||||
}
|
||||
|
||||
void Reset()
|
||||
|
@ -137,23 +150,39 @@ void Reset()
|
|||
|
||||
VRAMMap_ARM7[0] = 0;
|
||||
VRAMMap_ARM7[1] = 0;
|
||||
|
||||
for (int i = 0; i < 256*192*2; i++)
|
||||
printf("RESET: ACCEL=%d FRAMEBUFFER=%p\n", Accelerated, Framebuffer[0][0]);
|
||||
int fbsize;
|
||||
if (Accelerated) fbsize = (256*3 + 1) * 192;
|
||||
else fbsize = 256 * 192;
|
||||
for (int i = 0; i < fbsize; i++)
|
||||
{
|
||||
Framebuffer[i] = 0xFFFFFFFF;
|
||||
Framebuffer[0][0][i] = 0xFFFFFFFF;
|
||||
Framebuffer[1][0][i] = 0xFFFFFFFF;
|
||||
}
|
||||
for (int i = 0; i < fbsize; i++)
|
||||
{
|
||||
Framebuffer[0][1][i] = 0xFFFFFFFF;
|
||||
Framebuffer[1][1][i] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
GPU2D_A->Reset();
|
||||
GPU2D_B->Reset();
|
||||
GPU3D::Reset();
|
||||
|
||||
GPU2D_A->SetFramebuffer(&Framebuffer[256*192]);
|
||||
GPU2D_B->SetFramebuffer(&Framebuffer[256*0]);
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
|
||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
memset(Framebuffer, 0, 256*192*2*4);
|
||||
int fbsize;
|
||||
if (Accelerated) fbsize = (256*3 + 1) * 192;
|
||||
else fbsize = 256 * 192;
|
||||
memset(Framebuffer[0][0], 0, fbsize*4);
|
||||
memset(Framebuffer[0][1], 0, fbsize*4);
|
||||
memset(Framebuffer[1][0], 0, fbsize*4);
|
||||
memset(Framebuffer[1][1], 0, fbsize*4);
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
|
@ -208,6 +237,48 @@ void DoSavestate(Savestate* file)
|
|||
GPU3D::DoSavestate(file);
|
||||
}
|
||||
|
||||
void AssignFramebuffers()
|
||||
{
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
if (NDS::PowerControl9 & (1<<15))
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][0]);
|
||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
|
||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDisplaySettings(bool accel)
|
||||
{
|
||||
int fbsize;
|
||||
if (accel) fbsize = (256*3 + 1) * 192;
|
||||
else fbsize = 256 * 192;
|
||||
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
|
||||
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
||||
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
||||
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
|
||||
Framebuffer[0][0] = new u32[fbsize];
|
||||
Framebuffer[1][0] = new u32[fbsize];
|
||||
Framebuffer[0][1] = new u32[fbsize];
|
||||
Framebuffer[1][1] = new u32[fbsize];
|
||||
|
||||
memset(Framebuffer[0][0], 0, fbsize*4);
|
||||
memset(Framebuffer[1][0], 0, fbsize*4);
|
||||
memset(Framebuffer[0][1], 0, fbsize*4);
|
||||
memset(Framebuffer[1][1], 0, fbsize*4);
|
||||
|
||||
AssignFramebuffers();
|
||||
|
||||
GPU2D_A->SetDisplaySettings(accel);
|
||||
GPU2D_B->SetDisplaySettings(accel);
|
||||
|
||||
Accelerated = accel;
|
||||
}
|
||||
|
||||
|
||||
// VRAM mapping notes
|
||||
//
|
||||
|
@ -666,16 +737,7 @@ void SetPowerCnt(u32 val)
|
|||
GPU2D_B->SetEnabled(val & (1<<9));
|
||||
GPU3D::SetEnabled(val & (1<<3), val & (1<<2));
|
||||
|
||||
if (val & (1<<15))
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(&Framebuffer[256*0]);
|
||||
GPU2D_B->SetFramebuffer(&Framebuffer[256*192]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(&Framebuffer[256*192]);
|
||||
GPU2D_B->SetFramebuffer(&Framebuffer[256*0]);
|
||||
}
|
||||
AssignFramebuffers();
|
||||
}
|
||||
|
||||
|
||||
|
@ -746,6 +808,9 @@ void StartHBlank(u32 line)
|
|||
|
||||
void FinishFrame(u32 lines)
|
||||
{
|
||||
FrontBuffer = FrontBuffer ? 0 : 1;
|
||||
AssignFramebuffers();
|
||||
|
||||
TotalScanlines = lines;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ extern u32 VRAMMap_Texture[4];
|
|||
extern u32 VRAMMap_TexPal[8];
|
||||
extern u32 VRAMMap_ARM7[2];
|
||||
|
||||
extern u32 Framebuffer[256*192*2];
|
||||
extern int FrontBuffer;
|
||||
extern u32* Framebuffer[2][2];
|
||||
|
||||
extern GPU2D* GPU2D_A;
|
||||
extern GPU2D* GPU2D_B;
|
||||
|
@ -74,6 +75,8 @@ void Stop();
|
|||
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
void SetDisplaySettings(bool accel);
|
||||
|
||||
|
||||
void MapVRAM_AB(u32 bank, u8 cnt);
|
||||
void MapVRAM_CD(u32 bank, u8 cnt);
|
||||
|
|
737
src/GPU2D.cpp
737
src/GPU2D.cpp
File diff suppressed because it is too large
Load Diff
49
src/GPU2D.h
49
src/GPU2D.h
|
@ -31,6 +31,7 @@ public:
|
|||
|
||||
void SetEnabled(bool enable) { Enabled = enable; }
|
||||
void SetFramebuffer(u32* buf);
|
||||
void SetDisplaySettings(bool accel);
|
||||
|
||||
u8 Read8(u32 addr);
|
||||
u16 Read16(u32 addr);
|
||||
|
@ -68,6 +69,14 @@ private:
|
|||
bool Enabled;
|
||||
u32* Framebuffer;
|
||||
|
||||
bool Accelerated;
|
||||
|
||||
u32 BGOBJLine[256*3];
|
||||
u32* _3DLine;
|
||||
|
||||
u8 WindowMask[256];
|
||||
u32 OBJLine[256];
|
||||
|
||||
u16 DispFIFO[16];
|
||||
u32 DispFIFOReadPtr;
|
||||
u32 DispFIFOWritePtr;
|
||||
|
@ -114,27 +123,35 @@ private:
|
|||
u32 BGExtPalStatus[4];
|
||||
u32 OBJExtPalStatus;
|
||||
|
||||
template<u32 bgmode> void DrawScanlineBGMode(u32 line, u32 nsprites, u32* spritebuf, u32* dst);
|
||||
void DrawScanlineBGMode6(u32 line, u32 nsprites, u32* spritebuf, u32* dst);
|
||||
void DrawScanline_Mode1(u32 line, u32* dst);
|
||||
u32 ColorBlend4(u32 val1, u32 val2, u32 eva, u32 evb);
|
||||
u32 ColorBlend5(u32 val1, u32 val2);
|
||||
u32 ColorBrightnessUp(u32 val, u32 factor);
|
||||
u32 ColorBrightnessDown(u32 val, u32 factor);
|
||||
u32 ColorComposite(int i, u32 val1, u32 val2);
|
||||
|
||||
void DrawPixel(u32* dst, u16 color, u32 flag);
|
||||
template<u32 bgmode> void DrawScanlineBGMode(u32 line, u32 nsprites);
|
||||
void DrawScanlineBGMode6(u32 line, u32 nsprites);
|
||||
void DrawScanline_BGOBJ(u32 line);
|
||||
|
||||
void DrawBG_3D(u32 line, u32* dst);
|
||||
void DrawBG_Text(u32 line, u32* dst, u32 bgnum);
|
||||
void DrawBG_Affine(u32 line, u32* dst, u32 bgnum);
|
||||
void DrawBG_Extended(u32 line, u32* dst, u32 bgnum);
|
||||
void DrawBG_Large(u32 line, u32* dst);
|
||||
static void DrawPixel_Normal(u32* dst, u16 color, u32 flag);
|
||||
static void DrawPixel_Accel(u32* dst, u16 color, u32 flag);
|
||||
void (*DrawPixel)(u32* dst, u16 color, u32 flag);
|
||||
|
||||
void InterleaveSprites(u32* buf, u32 prio, u32* dst);
|
||||
u32 DrawSprites(u32 line, u32* dst);
|
||||
void DrawSpritesWindow(u32 line, u8* dst);
|
||||
template<bool window> void DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos, u32* dst);
|
||||
template<bool window> void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos, u32* dst);
|
||||
void DrawBG_3D();
|
||||
void DrawBG_Text(u32 line, u32 bgnum);
|
||||
void DrawBG_Affine(u32 line, u32 bgnum);
|
||||
void DrawBG_Extended(u32 line, u32 bgnum);
|
||||
void DrawBG_Large(u32 line);
|
||||
|
||||
void DoCapture(u32 line, u32 width, u32* src);
|
||||
void InterleaveSprites(u32 prio);
|
||||
u32 DrawSprites(u32 line);
|
||||
void DrawSpritesWindow(u32 line);
|
||||
template<bool window> void DrawSprite_Rotscale(u16* attrib, u16* rotparams, u32 boundwidth, u32 boundheight, u32 width, u32 height, s32 xpos, s32 ypos);
|
||||
template<bool window> void DrawSprite_Normal(u16* attrib, u32 width, s32 xpos, s32 ypos);
|
||||
|
||||
void CalculateWindowMask(u32 line, u8* mask);
|
||||
void DoCapture(u32 line, u32 width);
|
||||
|
||||
void CalculateWindowMask(u32 line);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "NDS.h"
|
||||
#include "GPU.h"
|
||||
#include "FIFO.h"
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
// 3D engine notes
|
||||
|
@ -156,6 +157,8 @@ u32 NumCommands, CurCommand, ParamCount, TotalParams;
|
|||
bool GeometryEnabled;
|
||||
bool RenderingEnabled;
|
||||
|
||||
int Renderer;
|
||||
|
||||
u32 DispCnt;
|
||||
u8 AlphaRefVal, AlphaRef;
|
||||
|
||||
|
@ -275,14 +278,16 @@ bool Init()
|
|||
|
||||
CmdStallQueue = new FIFO<CmdFIFOEntry>(64);
|
||||
|
||||
if (!SoftRenderer::Init()) return false;
|
||||
Renderer = -1;
|
||||
// SetRenderer() will be called to set it up later
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
SoftRenderer::DeInit();
|
||||
if (Renderer == 0) SoftRenderer::DeInit();
|
||||
else GLRenderer::DeInit();
|
||||
|
||||
delete CmdFIFO;
|
||||
delete CmdPIPE;
|
||||
|
@ -382,7 +387,8 @@ void Reset()
|
|||
FlushAttributes = 0;
|
||||
|
||||
ResetRenderingState();
|
||||
SoftRenderer::Reset();
|
||||
if (Renderer == 0) SoftRenderer::Reset();
|
||||
else GLRenderer::Reset();
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
|
@ -605,6 +611,43 @@ void SetEnabled(bool geometry, bool rendering)
|
|||
}
|
||||
|
||||
|
||||
int InitRenderer(bool hasGL)
|
||||
{
|
||||
int renderer = hasGL ? Config::_3DRenderer : 0;
|
||||
|
||||
if (renderer == 1)
|
||||
{
|
||||
if (!GLRenderer::Init())
|
||||
renderer = 0;
|
||||
}
|
||||
|
||||
if (renderer == 0) SoftRenderer::Init();
|
||||
|
||||
Renderer = renderer;
|
||||
UpdateRendererConfig();
|
||||
GPU::SetDisplaySettings(Renderer != 0);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void DeInitRenderer()
|
||||
{
|
||||
if (Renderer == 0) SoftRenderer::DeInit();
|
||||
else GLRenderer::DeInit();
|
||||
}
|
||||
|
||||
void UpdateRendererConfig()
|
||||
{
|
||||
if (Renderer == 0)
|
||||
{
|
||||
SoftRenderer::SetupRenderThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLRenderer::UpdateDisplaySettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MatrixLoadIdentity(s32* m)
|
||||
{
|
||||
|
@ -1191,6 +1234,16 @@ void SubmitPolygon()
|
|||
vtx->FinalPosition[0] = posX & 0x1FF;
|
||||
vtx->FinalPosition[1] = posY & 0xFF;
|
||||
|
||||
// hi-res positions
|
||||
if (w != 0)
|
||||
{
|
||||
posX = ((((s64)(vtx->Position[0] + w) * Viewport[4]) << 4) / (((s64)w) << 1)) + (Viewport[0] << 4);
|
||||
posY = ((((s64)(-vtx->Position[1] + w) * Viewport[5]) << 4) / (((s64)w) << 1)) + (Viewport[3] << 4);
|
||||
|
||||
vtx->HiresPosition[0] = posX & 0x1FFF;
|
||||
vtx->HiresPosition[1] = posY & 0xFFF;
|
||||
}
|
||||
|
||||
vtx->FinalColor[0] = vtx->Color[0] >> 12;
|
||||
if (vtx->FinalColor[0]) vtx->FinalColor[0] = ((vtx->FinalColor[0] << 4) + 0xF);
|
||||
vtx->FinalColor[1] = vtx->Color[1] >> 12;
|
||||
|
@ -2331,7 +2384,7 @@ void CheckFIFODMA()
|
|||
|
||||
void VCount144()
|
||||
{
|
||||
SoftRenderer::VCount144();
|
||||
if (Renderer == 0) SoftRenderer::VCount144();
|
||||
}
|
||||
|
||||
|
||||
|
@ -2413,17 +2466,14 @@ void VBlank()
|
|||
|
||||
void VCount215()
|
||||
{
|
||||
SoftRenderer::RenderFrame();
|
||||
}
|
||||
|
||||
void RequestLine(int line)
|
||||
{
|
||||
return SoftRenderer::RequestLine(line);
|
||||
if (Renderer == 0) SoftRenderer::RenderFrame();
|
||||
else GLRenderer::RenderFrame();
|
||||
}
|
||||
|
||||
u32* GetLine(int line)
|
||||
{
|
||||
return SoftRenderer::GetLine(line);
|
||||
if (Renderer == 0) return SoftRenderer::GetLine(line);
|
||||
else return GLRenderer::GetLine(line);
|
||||
}
|
||||
|
||||
|
||||
|
|
28
src/GPU3D.h
28
src/GPU3D.h
|
@ -39,6 +39,10 @@ typedef struct
|
|||
s32 FinalPosition[2];
|
||||
s32 FinalColor[3];
|
||||
|
||||
// hi-res position (4-bit fractional part)
|
||||
// TODO maybe: hi-res color? (that survives clipping)
|
||||
s32 HiresPosition[2];
|
||||
|
||||
} Vertex;
|
||||
|
||||
typedef struct
|
||||
|
@ -86,6 +90,8 @@ extern u32 RenderNumPolygons;
|
|||
|
||||
extern u64 Timestamp;
|
||||
|
||||
extern int Renderer;
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
|
@ -94,6 +100,10 @@ void DoSavestate(Savestate* file);
|
|||
|
||||
void SetEnabled(bool geometry, bool rendering);
|
||||
|
||||
int InitRenderer(bool hasGL);
|
||||
void DeInitRenderer();
|
||||
void UpdateRendererConfig();
|
||||
|
||||
void ExecuteCommand();
|
||||
|
||||
s32 CyclesToRunFor();
|
||||
|
@ -104,7 +114,6 @@ void CheckFIFODMA();
|
|||
void VCount144();
|
||||
void VBlank();
|
||||
void VCount215();
|
||||
void RequestLine(int line);
|
||||
u32* GetLine(int line);
|
||||
|
||||
void WriteToGXFIFO(u32 val);
|
||||
|
@ -127,11 +136,26 @@ void SetupRenderThread();
|
|||
|
||||
void VCount144();
|
||||
void RenderFrame();
|
||||
void RequestLine(int line);
|
||||
u32* GetLine(int line);
|
||||
|
||||
}
|
||||
|
||||
namespace GLRenderer
|
||||
{
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
|
||||
void UpdateDisplaySettings();
|
||||
|
||||
void RenderFrame();
|
||||
void PrepareCaptureFrame();
|
||||
u32* GetLine(int line);
|
||||
void SetupAccelFrame();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,690 @@
|
|||
/*
|
||||
Copyright 2016-2019 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef GPU3D_OPENGL_SHADERS_H
|
||||
#define GPU3D_OPENGL_SHADERS_H
|
||||
|
||||
#define kShaderHeader "#version 140"
|
||||
|
||||
|
||||
const char* kClearVS = kShaderHeader R"(
|
||||
|
||||
in vec2 vPosition;
|
||||
|
||||
uniform uint uDepth;
|
||||
|
||||
void main()
|
||||
{
|
||||
float fdepth = (float(uDepth) / 8388608.0) - 1.0;
|
||||
gl_Position = vec4(vPosition, fdepth, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kClearFS = kShaderHeader R"(
|
||||
|
||||
uniform uvec4 uColor;
|
||||
uniform uint uOpaquePolyID;
|
||||
uniform uint uFogFlag;
|
||||
|
||||
out vec4 oColor;
|
||||
out uvec3 oAttr;
|
||||
|
||||
void main()
|
||||
{
|
||||
oColor = vec4(uColor).bgra / 31.0;
|
||||
oAttr.r = uOpaquePolyID;
|
||||
oAttr.g = uint(0);
|
||||
oAttr.b = uFogFlag;
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
|
||||
const char* kFinalPassVS = kShaderHeader R"(
|
||||
|
||||
in vec2 vPosition;
|
||||
|
||||
void main()
|
||||
{
|
||||
// heh
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kFinalPassFS = kShaderHeader R"(
|
||||
|
||||
uniform sampler2D DepthBuffer;
|
||||
uniform usampler2D AttrBuffer;
|
||||
|
||||
layout(std140) uniform uConfig
|
||||
{
|
||||
vec2 uScreenSize;
|
||||
int uDispCnt;
|
||||
vec4 uToonColors[32];
|
||||
vec4 uEdgeColors[8];
|
||||
vec4 uFogColor;
|
||||
float uFogDensity[34];
|
||||
int uFogOffset;
|
||||
int uFogShift;
|
||||
};
|
||||
|
||||
out vec4 oColor;
|
||||
|
||||
vec4 CalculateFog(float depth)
|
||||
{
|
||||
int idepth = int(depth * 16777216.0);
|
||||
int densityid, densityfrac;
|
||||
|
||||
if (idepth < uFogOffset)
|
||||
{
|
||||
densityid = 0;
|
||||
densityfrac = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint udepth = uint(idepth);
|
||||
udepth -= uint(uFogOffset);
|
||||
udepth = (udepth >> 2) << uint(uFogShift);
|
||||
|
||||
densityid = int(udepth >> 17);
|
||||
if (densityid >= 32)
|
||||
{
|
||||
densityid = 32;
|
||||
densityfrac = 0;
|
||||
}
|
||||
else
|
||||
densityfrac = int(udepth & uint(0x1FFFF));
|
||||
}
|
||||
|
||||
float density = mix(uFogDensity[densityid], uFogDensity[densityid+1], float(densityfrac)/131072.0);
|
||||
|
||||
return vec4(density, density, density, density);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
|
||||
vec4 ret = vec4(0,0,0,0);
|
||||
vec4 depth = texelFetch(DepthBuffer, coord, 0);
|
||||
ivec4 attr = ivec4(texelFetch(AttrBuffer, coord, 0));
|
||||
|
||||
if (attr.b != 0) ret = CalculateFog(depth.r);
|
||||
|
||||
oColor = ret;
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
|
||||
const char* kRenderVSCommon = R"(
|
||||
|
||||
layout(std140) uniform uConfig
|
||||
{
|
||||
vec2 uScreenSize;
|
||||
int uDispCnt;
|
||||
vec4 uToonColors[32];
|
||||
vec4 uEdgeColors[8];
|
||||
vec4 uFogColor;
|
||||
float uFogDensity[34];
|
||||
int uFogOffset;
|
||||
int uFogShift;
|
||||
};
|
||||
|
||||
in uvec4 vPosition;
|
||||
in uvec4 vColor;
|
||||
in ivec2 vTexcoord;
|
||||
in ivec3 vPolygonAttr;
|
||||
|
||||
smooth out vec4 fColor;
|
||||
smooth out vec2 fTexcoord;
|
||||
flat out ivec3 fPolygonAttr;
|
||||
)";
|
||||
|
||||
const char* kRenderFSCommon = R"(
|
||||
|
||||
uniform usampler2D TexMem;
|
||||
uniform sampler2D TexPalMem;
|
||||
|
||||
layout(std140) uniform uConfig
|
||||
{
|
||||
vec2 uScreenSize;
|
||||
int uDispCnt;
|
||||
vec4 uToonColors[32];
|
||||
vec4 uEdgeColors[8];
|
||||
vec4 uFogColor;
|
||||
float uFogDensity[34];
|
||||
int uFogOffset;
|
||||
int uFogShift;
|
||||
};
|
||||
|
||||
smooth in vec4 fColor;
|
||||
smooth in vec2 fTexcoord;
|
||||
flat in ivec3 fPolygonAttr;
|
||||
|
||||
out vec4 oColor;
|
||||
out uvec3 oAttr;
|
||||
|
||||
int TexcoordWrap(int c, int maxc, int mode)
|
||||
{
|
||||
if ((mode & (1<<0)) != 0)
|
||||
{
|
||||
if ((mode & (1<<2)) != 0 && (c & maxc) != 0)
|
||||
return (maxc-1) - (c & (maxc-1));
|
||||
else
|
||||
return (c & (maxc-1));
|
||||
}
|
||||
else
|
||||
return clamp(c, 0, maxc-1);
|
||||
}
|
||||
|
||||
vec4 TextureFetch_A3I5(ivec2 addr, ivec4 st, int wrapmode)
|
||||
{
|
||||
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
|
||||
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
|
||||
|
||||
addr.x += ((st.y * st.z) + st.x);
|
||||
ivec4 pixel = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
|
||||
pixel.a = (pixel.r & 0xE0);
|
||||
pixel.a = (pixel.a >> 3) + (pixel.a >> 6);
|
||||
pixel.r &= 0x1F;
|
||||
|
||||
addr.y = (addr.y << 3) + pixel.r;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
|
||||
return vec4(color.rgb, float(pixel.a)/31.0);
|
||||
}
|
||||
|
||||
vec4 TextureFetch_I2(ivec2 addr, ivec4 st, int wrapmode, float alpha0)
|
||||
{
|
||||
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
|
||||
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
|
||||
|
||||
addr.x += ((st.y * st.z) + st.x) >> 2;
|
||||
ivec4 pixel = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
pixel.r >>= (2 * (st.x & 3));
|
||||
pixel.r &= 0x03;
|
||||
|
||||
addr.y = (addr.y << 2) + pixel.r;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
|
||||
return vec4(color.rgb, (pixel.r>0)?1:alpha0);
|
||||
}
|
||||
|
||||
vec4 TextureFetch_I4(ivec2 addr, ivec4 st, int wrapmode, float alpha0)
|
||||
{
|
||||
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
|
||||
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
|
||||
|
||||
addr.x += ((st.y * st.z) + st.x) >> 1;
|
||||
ivec4 pixel = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
if ((st.x & 1) != 0) pixel.r >>= 4;
|
||||
else pixel.r &= 0x0F;
|
||||
|
||||
addr.y = (addr.y << 3) + pixel.r;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
|
||||
return vec4(color.rgb, (pixel.r>0)?1:alpha0);
|
||||
}
|
||||
|
||||
vec4 TextureFetch_I8(ivec2 addr, ivec4 st, int wrapmode, float alpha0)
|
||||
{
|
||||
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
|
||||
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
|
||||
|
||||
addr.x += ((st.y * st.z) + st.x);
|
||||
ivec4 pixel = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
|
||||
addr.y = (addr.y << 3) + pixel.r;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
|
||||
return vec4(color.rgb, (pixel.r>0)?1:alpha0);
|
||||
}
|
||||
|
||||
vec4 TextureFetch_Compressed(ivec2 addr, ivec4 st, int wrapmode)
|
||||
{
|
||||
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
|
||||
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
|
||||
|
||||
addr.x += ((st.y & 0x3FC) * (st.z>>2)) + (st.x & 0x3FC) + (st.y & 0x3);
|
||||
ivec4 p = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
int val = (p.r >> (2 * (st.x & 0x3))) & 0x3;
|
||||
|
||||
int slot1addr = 0x20000 + ((addr.x & 0x1FFFC) >> 1);
|
||||
if (addr.x >= 0x40000) slot1addr += 0x10000;
|
||||
|
||||
int palinfo;
|
||||
p = ivec4(texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0));
|
||||
palinfo = p.r;
|
||||
slot1addr++;
|
||||
p = ivec4(texelFetch(TexMem, ivec2(slot1addr&0x3FF, slot1addr>>10), 0));
|
||||
palinfo |= (p.r << 8);
|
||||
|
||||
addr.y = (addr.y << 3) + ((palinfo & 0x3FFF) << 1);
|
||||
palinfo >>= 14;
|
||||
|
||||
if (val == 0)
|
||||
{
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
return vec4(color.rgb, 1.0);
|
||||
}
|
||||
else if (val == 1)
|
||||
{
|
||||
addr.y++;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
return vec4(color.rgb, 1.0);
|
||||
}
|
||||
else if (val == 2)
|
||||
{
|
||||
if (palinfo == 1)
|
||||
{
|
||||
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
addr.y++;
|
||||
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
return vec4((color0.rgb + color1.rgb) / 2.0, 1.0);
|
||||
}
|
||||
else if (palinfo == 3)
|
||||
{
|
||||
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
addr.y++;
|
||||
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
return vec4((color0.rgb*5.0 + color1.rgb*3.0) / 8.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr.y += 2;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
return vec4(color.rgb, 1.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (palinfo == 2)
|
||||
{
|
||||
addr.y += 3;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
return vec4(color.rgb, 1.0);
|
||||
}
|
||||
else if (palinfo == 3)
|
||||
{
|
||||
vec4 color0 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
addr.y++;
|
||||
vec4 color1 = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
return vec4((color0.rgb*3.0 + color1.rgb*5.0) / 8.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return vec4(0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec4 TextureFetch_A5I3(ivec2 addr, ivec4 st, int wrapmode)
|
||||
{
|
||||
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
|
||||
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
|
||||
|
||||
addr.x += ((st.y * st.z) + st.x);
|
||||
ivec4 pixel = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
|
||||
pixel.a = (pixel.r & 0xF8) >> 3;
|
||||
pixel.r &= 0x07;
|
||||
|
||||
addr.y = (addr.y << 3) + pixel.r;
|
||||
vec4 color = texelFetch(TexPalMem, ivec2(addr.y&0x3FF, addr.y>>10), 0);
|
||||
|
||||
return vec4(color.rgb, float(pixel.a)/31.0);
|
||||
}
|
||||
|
||||
vec4 TextureFetch_Direct(ivec2 addr, ivec4 st, int wrapmode)
|
||||
{
|
||||
st.x = TexcoordWrap(st.x, st.z, wrapmode>>0);
|
||||
st.y = TexcoordWrap(st.y, st.w, wrapmode>>1);
|
||||
|
||||
addr.x += ((st.y * st.z) + st.x) << 1;
|
||||
ivec4 pixelL = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
addr.x++;
|
||||
ivec4 pixelH = ivec4(texelFetch(TexMem, ivec2(addr.x&0x3FF, addr.x>>10), 0));
|
||||
|
||||
vec4 color;
|
||||
color.r = float(pixelL.r & 0x1F) / 31.0;
|
||||
color.g = float((pixelL.r >> 5) | ((pixelH.r & 0x03) << 3)) / 31.0;
|
||||
color.b = float((pixelH.r & 0x7C) >> 2) / 31.0;
|
||||
color.a = float(pixelH.r >> 7);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4 TextureLookup_Nearest(vec2 st)
|
||||
{
|
||||
int attr = int(fPolygonAttr.y);
|
||||
int paladdr = int(fPolygonAttr.z);
|
||||
|
||||
float alpha0;
|
||||
if ((attr & (1<<29)) != 0) alpha0 = 0.0;
|
||||
else alpha0 = 1.0;
|
||||
|
||||
int tw = 8 << ((attr >> 20) & 0x7);
|
||||
int th = 8 << ((attr >> 23) & 0x7);
|
||||
ivec4 st_full = ivec4(ivec2(st), tw, th);
|
||||
|
||||
ivec2 vramaddr = ivec2((attr & 0xFFFF) << 3, paladdr);
|
||||
int wrapmode = (attr >> 16);
|
||||
|
||||
int type = (attr >> 26) & 0x7;
|
||||
if (type == 5) return TextureFetch_Compressed(vramaddr, st_full, wrapmode);
|
||||
else if (type == 2) return TextureFetch_I2 (vramaddr, st_full, wrapmode, alpha0);
|
||||
else if (type == 3) return TextureFetch_I4 (vramaddr, st_full, wrapmode, alpha0);
|
||||
else if (type == 4) return TextureFetch_I8 (vramaddr, st_full, wrapmode, alpha0);
|
||||
else if (type == 1) return TextureFetch_A3I5 (vramaddr, st_full, wrapmode);
|
||||
else if (type == 6) return TextureFetch_A5I3 (vramaddr, st_full, wrapmode);
|
||||
else return TextureFetch_Direct (vramaddr, st_full, wrapmode);
|
||||
}
|
||||
|
||||
vec4 TextureLookup_Linear(vec2 texcoord)
|
||||
{
|
||||
ivec2 intpart = ivec2(texcoord);
|
||||
vec2 fracpart = fract(texcoord);
|
||||
|
||||
int attr = int(fPolygonAttr.y);
|
||||
int paladdr = int(fPolygonAttr.z);
|
||||
|
||||
float alpha0;
|
||||
if ((attr & (1<<29)) != 0) alpha0 = 0.0;
|
||||
else alpha0 = 1.0;
|
||||
|
||||
int tw = 8 << ((attr >> 20) & 0x7);
|
||||
int th = 8 << ((attr >> 23) & 0x7);
|
||||
ivec4 st_full = ivec4(intpart, tw, th);
|
||||
|
||||
ivec2 vramaddr = ivec2((attr & 0xFFFF) << 3, paladdr);
|
||||
int wrapmode = (attr >> 16);
|
||||
|
||||
vec4 A, B, C, D;
|
||||
int type = (attr >> 26) & 0x7;
|
||||
if (type == 5)
|
||||
{
|
||||
A = TextureFetch_Compressed(vramaddr, st_full , wrapmode);
|
||||
B = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
|
||||
C = TextureFetch_Compressed(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
|
||||
D = TextureFetch_Compressed(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
|
||||
}
|
||||
else if (type == 2)
|
||||
{
|
||||
A = TextureFetch_I2(vramaddr, st_full , wrapmode, alpha0);
|
||||
B = TextureFetch_I2(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
|
||||
C = TextureFetch_I2(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
|
||||
D = TextureFetch_I2(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
|
||||
}
|
||||
else if (type == 3)
|
||||
{
|
||||
A = TextureFetch_I4(vramaddr, st_full , wrapmode, alpha0);
|
||||
B = TextureFetch_I4(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
|
||||
C = TextureFetch_I4(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
|
||||
D = TextureFetch_I4(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
|
||||
}
|
||||
else if (type == 4)
|
||||
{
|
||||
A = TextureFetch_I8(vramaddr, st_full , wrapmode, alpha0);
|
||||
B = TextureFetch_I8(vramaddr, st_full + ivec4(1,0,0,0), wrapmode, alpha0);
|
||||
C = TextureFetch_I8(vramaddr, st_full + ivec4(0,1,0,0), wrapmode, alpha0);
|
||||
D = TextureFetch_I8(vramaddr, st_full + ivec4(1,1,0,0), wrapmode, alpha0);
|
||||
}
|
||||
else if (type == 1)
|
||||
{
|
||||
A = TextureFetch_A3I5(vramaddr, st_full , wrapmode);
|
||||
B = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
|
||||
C = TextureFetch_A3I5(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
|
||||
D = TextureFetch_A3I5(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
|
||||
}
|
||||
else if (type == 6)
|
||||
{
|
||||
A = TextureFetch_A5I3(vramaddr, st_full , wrapmode);
|
||||
B = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
|
||||
C = TextureFetch_A5I3(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
|
||||
D = TextureFetch_A5I3(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
|
||||
}
|
||||
else
|
||||
{
|
||||
A = TextureFetch_Direct(vramaddr, st_full , wrapmode);
|
||||
B = TextureFetch_Direct(vramaddr, st_full + ivec4(1,0,0,0), wrapmode);
|
||||
C = TextureFetch_Direct(vramaddr, st_full + ivec4(0,1,0,0), wrapmode);
|
||||
D = TextureFetch_Direct(vramaddr, st_full + ivec4(1,1,0,0), wrapmode);
|
||||
}
|
||||
|
||||
float fx = fracpart.x;
|
||||
vec4 AB;
|
||||
if (A.a < (0.5/31.0) && B.a < (0.5/31.0))
|
||||
AB = vec4(0);
|
||||
else
|
||||
{
|
||||
//if (A.a < (0.5/31.0) || B.a < (0.5/31.0))
|
||||
// fx = step(0.5, fx);
|
||||
|
||||
AB = mix(A, B, fx);
|
||||
}
|
||||
|
||||
fx = fracpart.x;
|
||||
vec4 CD;
|
||||
if (C.a < (0.5/31.0) && D.a < (0.5/31.0))
|
||||
CD = vec4(0);
|
||||
else
|
||||
{
|
||||
//if (C.a < (0.5/31.0) || D.a < (0.5/31.0))
|
||||
// fx = step(0.5, fx);
|
||||
|
||||
CD = mix(C, D, fx);
|
||||
}
|
||||
|
||||
fx = fracpart.y;
|
||||
vec4 ret;
|
||||
if (AB.a < (0.5/31.0) && CD.a < (0.5/31.0))
|
||||
ret = vec4(0);
|
||||
else
|
||||
{
|
||||
//if (AB.a < (0.5/31.0) || CD.a < (0.5/31.0))
|
||||
// fx = step(0.5, fx);
|
||||
|
||||
ret = mix(AB, CD, fx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 FinalColor()
|
||||
{
|
||||
vec4 col;
|
||||
vec4 vcol = fColor;
|
||||
int blendmode = (fPolygonAttr.x >> 4) & 0x3;
|
||||
|
||||
if (blendmode == 2)
|
||||
{
|
||||
if ((uDispCnt & (1<<1)) == 0)
|
||||
{
|
||||
// toon
|
||||
vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
|
||||
vcol.rgb = tooncolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// highlight
|
||||
vcol.rgb = vcol.rrr;
|
||||
}
|
||||
}
|
||||
|
||||
if ((((fPolygonAttr.y >> 26) & 0x7) == 0) || ((uDispCnt & (1<<0)) == 0))
|
||||
{
|
||||
// no texture
|
||||
col = vcol;
|
||||
}
|
||||
else
|
||||
{
|
||||
vec4 tcol = TextureLookup_Nearest(fTexcoord);
|
||||
//vec4 tcol = TextureLookup_Linear(fTexcoord);
|
||||
|
||||
if ((blendmode & 1) != 0)
|
||||
{
|
||||
// decal
|
||||
col.rgb = (tcol.rgb * tcol.a) + (vcol.rgb * (1.0-tcol.a));
|
||||
col.a = vcol.a;
|
||||
}
|
||||
else
|
||||
{
|
||||
// modulate
|
||||
col = vcol * tcol;
|
||||
}
|
||||
}
|
||||
|
||||
if (blendmode == 2)
|
||||
{
|
||||
if ((uDispCnt & (1<<1)) != 0)
|
||||
{
|
||||
vec3 tooncolor = uToonColors[int(vcol.r * 31)].rgb;
|
||||
col.rgb = min(col.rgb + tooncolor, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
return col.bgra;
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
const char* kRenderVS_Z = R"(
|
||||
|
||||
void main()
|
||||
{
|
||||
int attr = vPolygonAttr.x;
|
||||
int zshift = (attr >> 16) & 0x1F;
|
||||
|
||||
vec4 fpos;
|
||||
fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
|
||||
fpos.z = (float(vPosition.z << zshift) / 8388608.0) - 1.0;
|
||||
fpos.w = float(vPosition.w) / 65536.0f;
|
||||
fpos.xyz *= fpos.w;
|
||||
|
||||
fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
|
||||
fTexcoord = vec2(vTexcoord) / 16.0;
|
||||
fPolygonAttr = vPolygonAttr;
|
||||
|
||||
gl_Position = fpos;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kRenderVS_W = R"(
|
||||
|
||||
smooth out float fZ;
|
||||
|
||||
void main()
|
||||
{
|
||||
int attr = vPolygonAttr.x;
|
||||
int zshift = (attr >> 16) & 0x1F;
|
||||
|
||||
vec4 fpos;
|
||||
fpos.xy = ((vec2(vPosition.xy) * 2.0) / uScreenSize) - 1.0;
|
||||
fZ = float(vPosition.z << zshift) / 16777216.0;
|
||||
fpos.w = float(vPosition.w) / 65536.0f;
|
||||
fpos.xy *= fpos.w;
|
||||
|
||||
fColor = vec4(vColor) / vec4(255.0,255.0,255.0,31.0);
|
||||
fTexcoord = vec2(vTexcoord) / 16.0;
|
||||
fPolygonAttr = vPolygonAttr;
|
||||
|
||||
gl_Position = fpos;
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
const char* kRenderFS_ZO = R"(
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col = FinalColor();
|
||||
if (col.a < 30.5/31) discard;
|
||||
|
||||
oColor = col;
|
||||
oAttr.r = uint((fPolygonAttr.x >> 24) & 0x3F);
|
||||
oAttr.b = uint((fPolygonAttr.x >> 15) & 0x1);
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kRenderFS_WO = R"(
|
||||
|
||||
smooth in float fZ;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col = FinalColor();
|
||||
if (col.a < 30.5/31) discard;
|
||||
|
||||
oColor = col;
|
||||
oAttr.r = uint((fPolygonAttr.x >> 24) & 0x3F);
|
||||
oAttr.b = uint((fPolygonAttr.x >> 15) & 0x1);
|
||||
gl_FragDepth = fZ;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kRenderFS_ZT = R"(
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col = FinalColor();
|
||||
if (col.a < 0.5/31) discard;
|
||||
if (col.a >= 30.5/31) discard;
|
||||
|
||||
oColor = col;
|
||||
oAttr.b = uint(0);
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kRenderFS_WT = R"(
|
||||
|
||||
smooth in float fZ;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col = FinalColor();
|
||||
if (col.a < 0.5/31) discard;
|
||||
if (col.a >= 30.5/31) discard;
|
||||
|
||||
oColor = col;
|
||||
oAttr.b = uint(0);
|
||||
gl_FragDepth = fZ;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kRenderFS_ZSM = R"(
|
||||
|
||||
void main()
|
||||
{
|
||||
oColor = vec4(0,0,0,1);
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kRenderFS_WSM = R"(
|
||||
|
||||
smooth in float fZ;
|
||||
|
||||
void main()
|
||||
{
|
||||
oColor = vec4(0,0,0,1);
|
||||
gl_FragDepth = fZ;
|
||||
}
|
||||
)";
|
||||
|
||||
#endif // GPU3D_OPENGL_SHADERS_H
|
|
@ -129,9 +129,9 @@ void DeInit()
|
|||
|
||||
void Reset()
|
||||
{
|
||||
memset(ColorBuffer, 0, 256*192 * 4);
|
||||
memset(DepthBuffer, 0, 256*192 * 4);
|
||||
memset(AttrBuffer, 0, 256*192 * 4);
|
||||
memset(ColorBuffer, 0, BufferSize * 2 * 4);
|
||||
memset(DepthBuffer, 0, BufferSize * 2 * 4);
|
||||
memset(AttrBuffer, 0, BufferSize * 2 * 4);
|
||||
|
||||
PrevIsShadowMask = false;
|
||||
|
||||
|
@ -2106,17 +2106,14 @@ void RenderThreadFunc()
|
|||
}
|
||||
}
|
||||
|
||||
void RequestLine(int line)
|
||||
u32* GetLine(int line)
|
||||
{
|
||||
if (RenderThreadRunning)
|
||||
{
|
||||
if (line < 192)
|
||||
Platform::Semaphore_Wait(Sema_ScanlineCount);
|
||||
}
|
||||
}
|
||||
|
||||
u32* GetLine(int line)
|
||||
{
|
||||
return &ColorBuffer[(line * ScanlineWidth) + FirstPixelOffset];
|
||||
}
|
||||
|
||||
|
|
|
@ -1532,7 +1532,7 @@ void debug(u32 param)
|
|||
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
||||
|
||||
FILE*
|
||||
shit = fopen("debug/lmnts.bin", "wb");
|
||||
shit = fopen("debug/card.bin", "wb");
|
||||
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
||||
{
|
||||
u32 val = ARM7Read32(i);
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
Copyright 2016-2019 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "OpenGLSupport.h"
|
||||
|
||||
|
||||
DO_PROCLIST(DECLPROC);
|
||||
|
||||
|
||||
bool OpenGL_Init()
|
||||
{
|
||||
DO_PROCLIST(LOADPROC);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name)
|
||||
{
|
||||
int len;
|
||||
int res;
|
||||
|
||||
ids[0] = glCreateShader(GL_VERTEX_SHADER);
|
||||
len = strlen(vs);
|
||||
glShaderSource(ids[0], 1, &vs, &len);
|
||||
glCompileShader(ids[0]);
|
||||
|
||||
glGetShaderiv(ids[0], GL_COMPILE_STATUS, &res);
|
||||
if (res != GL_TRUE)
|
||||
{
|
||||
glGetShaderiv(ids[0], GL_INFO_LOG_LENGTH, &res);
|
||||
if (res < 1) res = 1024;
|
||||
char* log = new char[res+1];
|
||||
glGetShaderInfoLog(ids[0], res+1, NULL, log);
|
||||
printf("OpenGL: failed to compile vertex shader %s: %s\n", name, log);
|
||||
printf("shader source:\n--\n%s\n--\n", vs);
|
||||
delete[] log;
|
||||
|
||||
glDeleteShader(ids[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ids[1] = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
len = strlen(fs);
|
||||
glShaderSource(ids[1], 1, &fs, &len);
|
||||
glCompileShader(ids[1]);
|
||||
|
||||
glGetShaderiv(ids[1], GL_COMPILE_STATUS, &res);
|
||||
if (res != GL_TRUE)
|
||||
{
|
||||
glGetShaderiv(ids[1], GL_INFO_LOG_LENGTH, &res);
|
||||
if (res < 1) res = 1024;
|
||||
char* log = new char[res+1];
|
||||
glGetShaderInfoLog(ids[1], res+1, NULL, log);
|
||||
printf("OpenGL: failed to compile fragment shader %s: %s\n", name, log);
|
||||
//printf("shader source:\n--\n%s\n--\n", fs);
|
||||
delete[] log;
|
||||
|
||||
FILE* logf = fopen("shaderfail.log", "w");
|
||||
fwrite(fs, len+1, 1, logf);
|
||||
fclose(logf);
|
||||
|
||||
glDeleteShader(ids[0]);
|
||||
glDeleteShader(ids[1]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ids[2] = glCreateProgram();
|
||||
glAttachShader(ids[2], ids[0]);
|
||||
glAttachShader(ids[2], ids[1]);
|
||||
glLinkProgram(ids[2]);
|
||||
|
||||
glGetProgramiv(ids[2], GL_LINK_STATUS, &res);
|
||||
if (res != GL_TRUE)
|
||||
{
|
||||
glGetProgramiv(ids[2], GL_INFO_LOG_LENGTH, &res);
|
||||
if (res < 1) res = 1024;
|
||||
char* log = new char[res+1];
|
||||
glGetProgramInfoLog(ids[2], res+1, NULL, log);
|
||||
printf("OpenGL: failed to link program %s: %s\n", name, log);
|
||||
delete[] log;
|
||||
|
||||
glDeleteShader(ids[0]);
|
||||
glDeleteShader(ids[1]);
|
||||
glDeleteProgram(ids[2]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGL_DeleteShaderProgram(GLuint* ids)
|
||||
{
|
||||
glDeleteShader(ids[0]);
|
||||
glDeleteShader(ids[1]);
|
||||
glDeleteProgram(ids[2]);
|
||||
}
|
||||
|
||||
void OpenGL_UseShaderProgram(GLuint* ids)
|
||||
{
|
||||
glUseProgram(ids[2]);
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
Copyright 2016-2019 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef OPENGLSUPPORT_H
|
||||
#define OPENGLSUPPORT_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
|
||||
// here, have some macro magic
|
||||
// we at the melonDS company really love macro magic
|
||||
// also, suggestion to the fine folks who write the OpenGL headers:
|
||||
// pls make the type names follow the same capitalization as their
|
||||
// matching function names, so this is more convenient to deal with
|
||||
|
||||
#define DECLPROC(type, name) \
|
||||
PFN##type##PROC name ;
|
||||
|
||||
#define DECLPROC_EXT(type, name) \
|
||||
extern PFN##type##PROC name ;
|
||||
|
||||
#define LOADPROC(type, name) \
|
||||
name = (PFN##type##PROC)Platform::GL_GetProcAddress(#name); \
|
||||
if (!name) { printf("OpenGL: " #name " not found\n"); return false; }
|
||||
|
||||
|
||||
// if you need more OpenGL functions, add them to the macronator here
|
||||
// TODO: handle conditionally loading certain functions for different GL versions
|
||||
|
||||
#define DO_PROCLIST(func) \
|
||||
func(GLGENFRAMEBUFFERS, glGenFramebuffers); \
|
||||
func(GLDELETEFRAMEBUFFERS, glDeleteFramebuffers); \
|
||||
func(GLBINDFRAMEBUFFER, glBindFramebuffer); \
|
||||
func(GLFRAMEBUFFERTEXTURE, glFramebufferTexture); \
|
||||
func(GLBLITFRAMEBUFFER, glBlitFramebuffer); \
|
||||
func(GLCHECKFRAMEBUFFERSTATUS, glCheckFramebufferStatus); \
|
||||
\
|
||||
func(GLGENBUFFERS, glGenBuffers); \
|
||||
func(GLDELETEBUFFERS, glDeleteBuffers); \
|
||||
func(GLBINDBUFFER, glBindBuffer); \
|
||||
func(GLMAPBUFFER, glMapBuffer); \
|
||||
func(GLMAPBUFFERRANGE, glMapBufferRange); \
|
||||
func(GLUNMAPBUFFER, glUnmapBuffer); \
|
||||
func(GLBUFFERDATA, glBufferData); \
|
||||
func(GLBUFFERSUBDATA, glBufferSubData); \
|
||||
func(GLBINDBUFFERBASE, glBindBufferBase); \
|
||||
\
|
||||
func(GLGENVERTEXARRAYS, glGenVertexArrays); \
|
||||
func(GLDELETEVERTEXARRAYS, glDeleteVertexArrays); \
|
||||
func(GLBINDVERTEXARRAY, glBindVertexArray); \
|
||||
func(GLENABLEVERTEXATTRIBARRAY, glEnableVertexAttribArray); \
|
||||
func(GLDISABLEVERTEXATTRIBARRAY, glDisableVertexAttribArray); \
|
||||
func(GLVERTEXATTRIBPOINTER, glVertexAttribPointer); \
|
||||
func(GLVERTEXATTRIBIPOINTER, glVertexAttribIPointer); \
|
||||
func(GLBINDATTRIBLOCATION, glBindAttribLocation); \
|
||||
func(GLBINDFRAGDATALOCATION, glBindFragDataLocation); \
|
||||
\
|
||||
func(GLCREATESHADER, glCreateShader); \
|
||||
func(GLSHADERSOURCE, glShaderSource); \
|
||||
func(GLCOMPILESHADER, glCompileShader); \
|
||||
func(GLCREATEPROGRAM, glCreateProgram); \
|
||||
func(GLATTACHSHADER, glAttachShader); \
|
||||
func(GLLINKPROGRAM, glLinkProgram); \
|
||||
func(GLUSEPROGRAM, glUseProgram); \
|
||||
func(GLGETSHADERIV, glGetShaderiv); \
|
||||
func(GLGETSHADERINFOLOG, glGetShaderInfoLog); \
|
||||
func(GLGETPROGRAMIV, glGetProgramiv); \
|
||||
func(GLGETPROGRAMINFOLOG, glGetProgramInfoLog); \
|
||||
func(GLDELETESHADER, glDeleteShader); \
|
||||
func(GLDELETEPROGRAM, glDeleteProgram); \
|
||||
\
|
||||
func(GLUNIFORM1I, glUniform1i); \
|
||||
func(GLUNIFORM1UI, glUniform1ui); \
|
||||
func(GLUNIFORM4UI, glUniform4ui); \
|
||||
func(GLUNIFORMBLOCKBINDING, glUniformBlockBinding); \
|
||||
func(GLGETUNIFORMLOCATION, glGetUniformLocation); \
|
||||
func(GLGETUNIFORMBLOCKINDEX, glGetUniformBlockIndex); \
|
||||
\
|
||||
func(GLACTIVETEXTURE, glActiveTexture); \
|
||||
func(GLBINDIMAGETEXTURE, glBindImageTexture); \
|
||||
\
|
||||
func(GLDRAWBUFFERS, glDrawBuffers); \
|
||||
\
|
||||
func(GLBLENDFUNCSEPARATE, glBlendFuncSeparate); \
|
||||
func(GLBLENDEQUATIONSEPARATE, glBlendEquationSeparate); \
|
||||
func(GLBLENDCOLOR, glBlendColor); \
|
||||
\
|
||||
func(GLCOLORMASKI, glColorMaski); \
|
||||
\
|
||||
func(GLMEMORYBARRIER, glMemoryBarrier); \
|
||||
\
|
||||
func(GLGETSTRINGI, glGetStringi); \
|
||||
|
||||
|
||||
DO_PROCLIST(DECLPROC_EXT);
|
||||
|
||||
|
||||
bool OpenGL_Init();
|
||||
|
||||
bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name);
|
||||
void OpenGL_DeleteShaderProgram(GLuint* ids);
|
||||
void OpenGL_UseShaderProgram(GLuint* ids);
|
||||
|
||||
#endif // OPENGLSUPPORT_H
|
|
@ -68,6 +68,8 @@ void Semaphore_Reset(void* sema);
|
|||
void Semaphore_Wait(void* sema);
|
||||
void Semaphore_Post(void* sema);
|
||||
|
||||
void* GL_GetProcAddress(const char* proc);
|
||||
|
||||
// local multiplayer comm interface
|
||||
// packet type: DS-style TX header (12 bytes) + original 802.11 frame
|
||||
bool MP_Init();
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
|
||||
|
||||
// SPU TODO
|
||||
// * loop mode 3, what does it do?
|
||||
// * capture addition modes, overflow bugs
|
||||
// * channel hold
|
||||
// * 'length less than 4' glitch
|
||||
|
||||
|
||||
namespace SPU
|
||||
|
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
Copyright 2016-2019 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libui/ui.h"
|
||||
|
||||
#include "../types.h"
|
||||
#include "PlatformConfig.h"
|
||||
|
||||
#include "DlgVideoSettings.h"
|
||||
|
||||
|
||||
void ApplyNewSettings(int type);
|
||||
|
||||
|
||||
namespace DlgVideoSettings
|
||||
{
|
||||
|
||||
bool opened;
|
||||
uiWindow* win;
|
||||
|
||||
uiRadioButtons* rbRenderer;
|
||||
uiCheckbox* cbGLDisplay;
|
||||
uiCheckbox* cbThreaded3D;
|
||||
uiCombobox* cbResolution;
|
||||
uiCheckbox* cbAntialias;
|
||||
|
||||
int old_renderer;
|
||||
int old_gldisplay;
|
||||
int old_threaded3D;
|
||||
int old_resolution;
|
||||
int old_antialias;
|
||||
|
||||
|
||||
void UpdateControls()
|
||||
{
|
||||
int renderer = uiRadioButtonsSelected(rbRenderer);
|
||||
|
||||
if (renderer == 0)
|
||||
{
|
||||
uiControlEnable(uiControl(cbGLDisplay));
|
||||
uiControlEnable(uiControl(cbThreaded3D));
|
||||
uiControlDisable(uiControl(cbResolution));
|
||||
uiControlDisable(uiControl(cbAntialias));
|
||||
}
|
||||
else
|
||||
{
|
||||
uiControlDisable(uiControl(cbGLDisplay));
|
||||
uiControlDisable(uiControl(cbThreaded3D));
|
||||
uiControlEnable(uiControl(cbResolution));
|
||||
uiControlEnable(uiControl(cbAntialias));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int OnCloseWindow(uiWindow* window, void* blarg)
|
||||
{
|
||||
opened = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void OnRendererChanged(uiRadioButtons* rb, void* blarg)
|
||||
{
|
||||
int id = uiRadioButtonsSelected(rb);
|
||||
bool old_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
||||
|
||||
Config::_3DRenderer = id;
|
||||
UpdateControls();
|
||||
|
||||
bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
||||
if (new_usegl != old_usegl)
|
||||
ApplyNewSettings(2);
|
||||
else
|
||||
ApplyNewSettings(3);
|
||||
}
|
||||
|
||||
void OnGLDisplayChanged(uiCheckbox* cb, void* blarg)
|
||||
{
|
||||
Config::ScreenUseGL = uiCheckboxChecked(cb);
|
||||
ApplyNewSettings(2);
|
||||
uiControlSetFocus(uiControl(cb));
|
||||
}
|
||||
|
||||
void OnThreaded3DChanged(uiCheckbox* cb, void* blarg)
|
||||
{
|
||||
Config::Threaded3D = uiCheckboxChecked(cb);
|
||||
ApplyNewSettings(0);
|
||||
}
|
||||
|
||||
void OnResolutionChanged(uiCombobox* cb, void* blarg)
|
||||
{
|
||||
int id = uiComboboxSelected(cb);
|
||||
|
||||
Config::GL_ScaleFactor = id+1;
|
||||
ApplyNewSettings(0);
|
||||
}
|
||||
|
||||
void OnAntialiasChanged(uiCheckbox* cb, void* blarg)
|
||||
{
|
||||
Config::GL_Antialias = uiCheckboxChecked(cb);
|
||||
ApplyNewSettings(0);
|
||||
}
|
||||
|
||||
void OnCancel(uiButton* btn, void* blarg)
|
||||
{
|
||||
bool apply0 = false;
|
||||
bool apply2 = false;
|
||||
bool apply3 = false;
|
||||
|
||||
bool old_usegl = (old_gldisplay != 0) || (old_renderer != 0);
|
||||
bool new_usegl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0);
|
||||
|
||||
if (old_renderer != Config::_3DRenderer)
|
||||
{
|
||||
Config::_3DRenderer = old_renderer;
|
||||
apply3 = true;
|
||||
}
|
||||
|
||||
if (old_gldisplay != Config::ScreenUseGL)
|
||||
{
|
||||
Config::ScreenUseGL = old_gldisplay;
|
||||
}
|
||||
if (old_usegl != new_usegl)
|
||||
{
|
||||
apply2 = true;
|
||||
}
|
||||
|
||||
if (old_threaded3D != Config::Threaded3D)
|
||||
{
|
||||
Config::Threaded3D = old_threaded3D;
|
||||
apply0 = true;
|
||||
}
|
||||
|
||||
if (old_resolution != Config::GL_ScaleFactor ||
|
||||
old_antialias != Config::GL_Antialias)
|
||||
{
|
||||
Config::GL_ScaleFactor = old_resolution;
|
||||
Config::GL_Antialias = old_antialias;
|
||||
apply0 = true;
|
||||
}
|
||||
|
||||
if (apply2) ApplyNewSettings(2);
|
||||
else if (apply3) ApplyNewSettings(3);
|
||||
if (apply0) ApplyNewSettings(0);
|
||||
|
||||
uiControlDestroy(uiControl(win));
|
||||
opened = false;
|
||||
}
|
||||
|
||||
void OnOk(uiButton* btn, void* blarg)
|
||||
{
|
||||
Config::Save();
|
||||
|
||||
uiControlDestroy(uiControl(win));
|
||||
opened = false;
|
||||
}
|
||||
|
||||
void Open()
|
||||
{
|
||||
if (opened)
|
||||
{
|
||||
uiControlSetFocus(uiControl(win));
|
||||
return;
|
||||
}
|
||||
|
||||
opened = true;
|
||||
win = uiNewWindow("Video settings - melonDS", 400, 100, 0, 0, 0);
|
||||
uiWindowSetMargined(win, 1);
|
||||
uiWindowOnClosing(win, OnCloseWindow, NULL);
|
||||
|
||||
uiBox* top = uiNewVerticalBox();
|
||||
uiWindowSetChild(win, uiControl(top));
|
||||
uiBoxSetPadded(top, 1);
|
||||
|
||||
uiBox* splitter = uiNewHorizontalBox();
|
||||
uiBoxAppend(top, uiControl(splitter), 0);
|
||||
uiBoxSetPadded(splitter, 1);
|
||||
|
||||
uiBox* left = uiNewVerticalBox();
|
||||
uiBoxAppend(splitter, uiControl(left), 1);
|
||||
uiBoxSetPadded(left, 1);
|
||||
uiBox* right = uiNewVerticalBox();
|
||||
uiBoxAppend(splitter, uiControl(right), 1);
|
||||
uiBoxSetPadded(right, 1);
|
||||
|
||||
{
|
||||
uiGroup* grp = uiNewGroup("Display settings");
|
||||
uiBoxAppend(left, uiControl(grp), 0);
|
||||
uiGroupSetMargined(grp, 1);
|
||||
|
||||
uiBox* in_ctrl = uiNewVerticalBox();
|
||||
uiGroupSetChild(grp, uiControl(in_ctrl));
|
||||
|
||||
uiLabel* lbl = uiNewLabel("3D renderer:");
|
||||
uiBoxAppend(in_ctrl, uiControl(lbl), 0);
|
||||
|
||||
rbRenderer = uiNewRadioButtons();
|
||||
uiRadioButtonsAppend(rbRenderer, "Software");
|
||||
uiRadioButtonsAppend(rbRenderer, "OpenGL");
|
||||
uiRadioButtonsOnSelected(rbRenderer, OnRendererChanged, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(rbRenderer), 0);
|
||||
|
||||
lbl = uiNewLabel("");
|
||||
uiBoxAppend(in_ctrl, uiControl(lbl), 0);
|
||||
|
||||
cbGLDisplay = uiNewCheckbox("OpenGL display");
|
||||
uiCheckboxOnToggled(cbGLDisplay, OnGLDisplayChanged, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(cbGLDisplay), 0);
|
||||
}
|
||||
|
||||
{
|
||||
uiGroup* grp = uiNewGroup("Software renderer");
|
||||
uiBoxAppend(right, uiControl(grp), 0);
|
||||
uiGroupSetMargined(grp, 1);
|
||||
|
||||
uiBox* in_ctrl = uiNewVerticalBox();
|
||||
uiGroupSetChild(grp, uiControl(in_ctrl));
|
||||
|
||||
cbThreaded3D = uiNewCheckbox("Threaded");
|
||||
uiCheckboxOnToggled(cbThreaded3D, OnThreaded3DChanged, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(cbThreaded3D), 0);
|
||||
}
|
||||
|
||||
{
|
||||
uiGroup* grp = uiNewGroup("OpenGL renderer");
|
||||
uiBoxAppend(right, uiControl(grp), 0);
|
||||
uiGroupSetMargined(grp, 1);
|
||||
|
||||
uiBox* in_ctrl = uiNewVerticalBox();
|
||||
uiGroupSetChild(grp, uiControl(in_ctrl));
|
||||
|
||||
uiLabel* lbl = uiNewLabel("Internal resolution:");
|
||||
uiBoxAppend(in_ctrl, uiControl(lbl), 0);
|
||||
|
||||
cbResolution = uiNewCombobox();
|
||||
uiComboboxOnSelected(cbResolution, OnResolutionChanged, NULL);
|
||||
for (int i = 1; i <= 8; i++)
|
||||
{
|
||||
char txt[64];
|
||||
sprintf(txt, "%dx native (%dx%d)", i, 256*i, 192*i);
|
||||
uiComboboxAppend(cbResolution, txt);
|
||||
}
|
||||
uiBoxAppend(in_ctrl, uiControl(cbResolution), 0);
|
||||
|
||||
lbl = uiNewLabel("");
|
||||
uiBoxAppend(in_ctrl, uiControl(lbl), 0);
|
||||
|
||||
cbAntialias = uiNewCheckbox("Antialiasing");
|
||||
uiCheckboxOnToggled(cbAntialias, OnAntialiasChanged, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(cbAntialias), 0);
|
||||
}
|
||||
|
||||
{
|
||||
uiBox* in_ctrl = uiNewHorizontalBox();
|
||||
uiBoxSetPadded(in_ctrl, 1);
|
||||
uiBoxAppend(top, uiControl(in_ctrl), 0);
|
||||
|
||||
uiLabel* dummy = uiNewLabel("");
|
||||
uiBoxAppend(in_ctrl, uiControl(dummy), 1);
|
||||
|
||||
uiButton* btncancel = uiNewButton("Cancel");
|
||||
uiButtonOnClicked(btncancel, OnCancel, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(btncancel), 0);
|
||||
|
||||
uiButton* btnok = uiNewButton("Ok");
|
||||
uiButtonOnClicked(btnok, OnOk, NULL);
|
||||
uiBoxAppend(in_ctrl, uiControl(btnok), 0);
|
||||
}
|
||||
|
||||
Config::_3DRenderer = Config::_3DRenderer ? 1 : 0;
|
||||
|
||||
if (Config::GL_ScaleFactor < 1) Config::GL_ScaleFactor = 1;
|
||||
else if (Config::GL_ScaleFactor > 8) Config::GL_ScaleFactor = 8;
|
||||
|
||||
old_renderer = Config::_3DRenderer;
|
||||
old_gldisplay = Config::ScreenUseGL;
|
||||
old_threaded3D = Config::Threaded3D;
|
||||
old_resolution = Config::GL_ScaleFactor;
|
||||
old_antialias = Config::GL_Antialias;
|
||||
|
||||
uiCheckboxSetChecked(cbGLDisplay, Config::ScreenUseGL);
|
||||
uiCheckboxSetChecked(cbThreaded3D, Config::Threaded3D);
|
||||
uiComboboxSetSelected(cbResolution, Config::GL_ScaleFactor-1);
|
||||
uiCheckboxSetChecked(cbAntialias, Config::GL_Antialias);
|
||||
uiRadioButtonsSetSelected(rbRenderer, Config::_3DRenderer);
|
||||
UpdateControls();
|
||||
|
||||
uiControlShow(uiControl(win));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2016-2019 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef DLGVIDEOSETTINGS_H
|
||||
#define DLGVIDEOSETTINGS_H
|
||||
|
||||
namespace DlgVideoSettings
|
||||
{
|
||||
|
||||
void Open();
|
||||
|
||||
}
|
||||
|
||||
#endif // DLGVIDEOSETTINGS_H
|
|
@ -24,6 +24,7 @@
|
|||
#include "PlatformConfig.h"
|
||||
#include "LAN_Socket.h"
|
||||
#include "LAN_PCap.h"
|
||||
#include "libui/ui.h"
|
||||
#include <string>
|
||||
|
||||
#ifdef __WIN32__
|
||||
|
@ -302,6 +303,12 @@ void Semaphore_Post(void* sema)
|
|||
}
|
||||
|
||||
|
||||
void* GL_GetProcAddress(const char* proc)
|
||||
{
|
||||
return uiGLGetProcAddress(proc);
|
||||
}
|
||||
|
||||
|
||||
bool MP_Init()
|
||||
{
|
||||
int opt_true = 1;
|
||||
|
|
|
@ -40,6 +40,9 @@ int ScreenLayout;
|
|||
int ScreenSizing;
|
||||
int ScreenFilter;
|
||||
|
||||
int ScreenUseGL;
|
||||
int ScreenRatio;
|
||||
|
||||
int LimitFPS;
|
||||
|
||||
int DirectBoot;
|
||||
|
@ -101,6 +104,9 @@ ConfigEntry PlatformConfigFile[] =
|
|||
{"ScreenSizing", 0, &ScreenSizing, 0, NULL, 0},
|
||||
{"ScreenFilter", 0, &ScreenFilter, 1, NULL, 0},
|
||||
|
||||
{"ScreenUseGL", 0, &ScreenUseGL, 1, NULL, 0},
|
||||
{"ScreenRatio", 0, &ScreenRatio, 0, NULL, 0},
|
||||
|
||||
{"LimitFPS", 0, &LimitFPS, 1, NULL, 0},
|
||||
|
||||
{"DirectBoot", 0, &DirectBoot, 1, NULL, 0},
|
||||
|
|
|
@ -48,6 +48,9 @@ extern int ScreenLayout;
|
|||
extern int ScreenSizing;
|
||||
extern int ScreenFilter;
|
||||
|
||||
extern int ScreenUseGL;
|
||||
extern int ScreenRatio;
|
||||
|
||||
extern int LimitFPS;
|
||||
|
||||
extern int DirectBoot;
|
||||
|
|
|
@ -108,6 +108,8 @@ typedef struct uiWindow uiWindow;
|
|||
#define uiWindow(this) ((uiWindow *) (this))
|
||||
_UI_EXTERN char *uiWindowTitle(uiWindow *w);
|
||||
_UI_EXTERN void uiWindowSetTitle(uiWindow *w, const char *title);
|
||||
_UI_EXTERN void uiWindowPosition(uiWindow *w, int *x, int *y);
|
||||
_UI_EXTERN void uiWindowSetPosition(uiWindow *w, int x, int y);
|
||||
_UI_EXTERN void uiWindowContentSize(uiWindow *w, int *width, int *height);
|
||||
_UI_EXTERN void uiWindowSetContentSize(uiWindow *w, int width, int height);
|
||||
_UI_EXTERN int uiWindowMinimized(uiWindow *w);
|
||||
|
@ -326,6 +328,10 @@ _UI_ENUM(uiWindowResizeEdge) {
|
|||
// TODO way to bring up the system menu instead?
|
||||
};
|
||||
|
||||
#define uiGLVersion(major, minor) ((major) | ((minor)<<16))
|
||||
#define uiGLVerMajor(ver) ((ver) & 0xFFFF)
|
||||
#define uiGLVerMinor(ver) ((ver) >> 16)
|
||||
|
||||
#define uiArea(this) ((uiArea *) (this))
|
||||
// TODO give a better name
|
||||
// TODO document the types of width and height
|
||||
|
@ -342,6 +348,7 @@ _UI_EXTERN void uiAreaBeginUserWindowMove(uiArea *a);
|
|||
_UI_EXTERN void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge);
|
||||
_UI_EXTERN void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b);
|
||||
_UI_EXTERN uiArea *uiNewArea(uiAreaHandler *ah);
|
||||
_UI_EXTERN uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions);
|
||||
_UI_EXTERN uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height);
|
||||
|
||||
struct uiAreaDrawParams {
|
||||
|
@ -599,6 +606,18 @@ _UI_EXTERN void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, int startChar
|
|||
|
||||
_UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout);
|
||||
|
||||
|
||||
// OpenGL support
|
||||
|
||||
typedef struct uiGLContext uiGLContext;
|
||||
|
||||
_UI_EXTERN uiGLContext *uiAreaGetGLContext(uiArea* a);
|
||||
_UI_EXTERN void uiGLMakeContextCurrent(uiGLContext* ctx);
|
||||
_UI_EXTERN unsigned int uiGLGetVersion(uiGLContext* ctx);
|
||||
_UI_EXTERN void *uiGLGetProcAddress(const char* proc);
|
||||
_UI_EXTERN void uiGLSwapBuffers(uiGLContext* ctx);
|
||||
|
||||
|
||||
_UI_ENUM(uiModifiers) {
|
||||
uiModifierCtrl = 1 << 0,
|
||||
uiModifierAlt = 1 << 1,
|
||||
|
|
|
@ -25,8 +25,11 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|||
}
|
||||
|
||||
// always recreate the render target if necessary
|
||||
if (a->rt == NULL)
|
||||
a->rt = makeHWNDRenderTarget(a->hwnd);
|
||||
if (!a->openGL)
|
||||
{
|
||||
if (a->rt == NULL)
|
||||
a->rt = makeHWNDRenderTarget(a->hwnd);
|
||||
}
|
||||
|
||||
if (areaDoDraw(a, uMsg, wParam, lParam, &lResult) != FALSE)
|
||||
return lResult;
|
||||
|
@ -34,12 +37,14 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|||
if (uMsg == WM_WINDOWPOSCHANGED) {
|
||||
if ((wp->flags & SWP_NOSIZE) != 0)
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
uiWindowsEnsureGetClientRect(a->hwnd, &client);
|
||||
areaDrawOnResize(a, &client);
|
||||
areaScrollOnResize(a, &client);
|
||||
{
|
||||
double w, h;
|
||||
loadAreaSize(a, a->rt, &w, &h);
|
||||
loadAreaSize(a, &w, &h);
|
||||
a->ah->Resize(a->ah, a, (int)w, (int)h);
|
||||
}
|
||||
return 0;
|
||||
|
@ -56,7 +61,15 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|||
|
||||
// control implementation
|
||||
|
||||
uiWindowsControlAllDefaults(uiArea)
|
||||
uiWindowsControlAllDefaultsExceptDestroy(uiArea)
|
||||
|
||||
static void uiAreaDestroy(uiControl *c)
|
||||
{
|
||||
uiArea* a = uiArea(c);
|
||||
if (a->openGL && a->glcontext) freeGLContext(a->glcontext);
|
||||
uiWindowsEnsureDestroyWindow(a->hwnd);
|
||||
uiFreeControl(c);
|
||||
}
|
||||
|
||||
static void uiAreaMinimumSize(uiWindowsControl *c, int *width, int *height)
|
||||
{
|
||||
|
@ -182,6 +195,9 @@ uiArea *uiNewArea(uiAreaHandler *ah)
|
|||
|
||||
uiWindowsNewControl(uiArea, a);
|
||||
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
|
||||
a->ah = ah;
|
||||
a->scrolling = FALSE;
|
||||
clickCounterReset(&(a->cc));
|
||||
|
@ -195,6 +211,50 @@ uiArea *uiNewArea(uiAreaHandler *ah)
|
|||
|
||||
uiAreaSetBackgroundColor(a, -1, -1, -1);
|
||||
|
||||
a->openGL = 0;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
uiGLContext *uiAreaGetGLContext(uiArea* a)
|
||||
{
|
||||
if (!a->openGL) userbug("trying to get GL context from non-GL area");
|
||||
|
||||
return a->glcontext;
|
||||
}
|
||||
|
||||
uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions)
|
||||
{
|
||||
uiArea *a;
|
||||
|
||||
uiWindowsNewControl(uiArea, a);
|
||||
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
|
||||
a->ah = ah;
|
||||
a->scrolling = FALSE;
|
||||
clickCounterReset(&(a->cc));
|
||||
|
||||
// a->hwnd is assigned in areaWndProc()
|
||||
uiWindowsEnsureCreateControlHWND(0,
|
||||
areaClass, L"",
|
||||
0,
|
||||
hInstance, a,
|
||||
FALSE);
|
||||
|
||||
uiAreaSetBackgroundColor(a, -1, -1, -1);
|
||||
|
||||
a->openGL = 1;
|
||||
|
||||
for (int i = 0; req_versions[i]; i++)
|
||||
{
|
||||
int major = uiGLVerMajor(req_versions[i]);
|
||||
int minor = uiGLVerMinor(req_versions[i]);
|
||||
a->glcontext = createGLContext(a, major, minor);
|
||||
if (a->glcontext) break;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
@ -204,6 +264,9 @@ uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
|
|||
|
||||
uiWindowsNewControl(uiArea, a);
|
||||
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
|
||||
a->ah = ah;
|
||||
a->scrolling = TRUE;
|
||||
a->scrollWidth = width;
|
||||
|
@ -219,6 +282,8 @@ uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
|
|||
|
||||
uiAreaSetBackgroundColor(a, -1, -1, -1);
|
||||
|
||||
a->openGL = 0; // TODO, eventually???
|
||||
|
||||
// set initial scrolling parameters
|
||||
areaUpdateScroll(a);
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ struct uiArea {
|
|||
HWND hwnd;
|
||||
uiAreaHandler *ah;
|
||||
|
||||
int width, height;
|
||||
|
||||
BOOL scrolling;
|
||||
int scrollWidth;
|
||||
int scrollHeight;
|
||||
|
@ -26,6 +28,9 @@ struct uiArea {
|
|||
|
||||
int bgR, bgG, bgB;
|
||||
|
||||
int openGL;
|
||||
uiGLContext* glcontext;
|
||||
|
||||
ID2D1HwndRenderTarget *rt;
|
||||
};
|
||||
|
||||
|
@ -42,6 +47,10 @@ extern void areaUpdateScroll(uiArea *a);
|
|||
extern BOOL areaDoEvents(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
|
||||
|
||||
// areautil.cpp
|
||||
extern void loadAreaSize(uiArea *a, ID2D1RenderTarget *rt, double *width, double *height);
|
||||
extern void loadAreaSize(uiArea *a, double *width, double *height);
|
||||
extern void pixelsToDIP(uiArea *a, double *x, double *y);
|
||||
extern void dipToPixels(uiArea *a, double *x, double *y);
|
||||
|
||||
// gl.cpp
|
||||
extern uiGLContext* createGLContext(uiArea* a, int vermajor, int verminor);
|
||||
extern void freeGLContext(uiGLContext* c);
|
||||
|
|
|
@ -6,6 +6,13 @@ static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip)
|
|||
{
|
||||
uiAreaHandler *ah = a->ah;
|
||||
uiAreaDrawParams dp;
|
||||
|
||||
if (a->openGL)
|
||||
{
|
||||
//(*(ah->Draw))(ah, a, &dp);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
COLORREF bgcolorref;
|
||||
D2D1_COLOR_F bgcolor;
|
||||
D2D1_MATRIX_3X2_F scrollTransform;
|
||||
|
@ -13,7 +20,7 @@ static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip)
|
|||
// no need to save or restore the graphics state to reset transformations; it's handled by resetTarget() in draw.c, called during the following
|
||||
dp.Context = newContext(rt);
|
||||
|
||||
loadAreaSize(a, rt, &(dp.AreaWidth), &(dp.AreaHeight));
|
||||
loadAreaSize(a, &(dp.AreaWidth), &(dp.AreaHeight));
|
||||
|
||||
dp.ClipX = clip->left;
|
||||
dp.ClipY = clip->top;
|
||||
|
@ -113,6 +120,9 @@ static void onWM_PAINT(uiArea *a)
|
|||
|
||||
static void onWM_PRINTCLIENT(uiArea *a, HDC dc)
|
||||
{
|
||||
// TODO????
|
||||
if (a->openGL) return;
|
||||
|
||||
ID2D1DCRenderTarget *rt;
|
||||
RECT client;
|
||||
HRESULT hr;
|
||||
|
@ -143,13 +153,16 @@ BOOL areaDoDraw(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lRe
|
|||
// TODO only if the render target wasn't just created?
|
||||
void areaDrawOnResize(uiArea *a, RECT *newClient)
|
||||
{
|
||||
D2D1_SIZE_U size;
|
||||
if (!a->openGL)
|
||||
{
|
||||
D2D1_SIZE_U size;
|
||||
|
||||
size.width = newClient->right - newClient->left;
|
||||
size.height = newClient->bottom - newClient->top;
|
||||
// don't track the error; we'll get that in EndDraw()
|
||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx
|
||||
a->rt->Resize(&size);
|
||||
size.width = newClient->right - newClient->left;
|
||||
size.height = newClient->bottom - newClient->top;
|
||||
// don't track the error; we'll get that in EndDraw()
|
||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx
|
||||
a->rt->Resize(&size);
|
||||
}
|
||||
|
||||
// according to Rick Brewster, we must always redraw the entire client area after calling ID2D1RenderTarget::Resize() (see http://stackoverflow.com/a/33222983/3408572)
|
||||
// we used to have a uiAreaHandler.RedrawOnResize() method to decide this; now you know why we don't anymore
|
||||
|
|
|
@ -109,7 +109,7 @@ static void areaMouseEvent(uiArea *a, int down, int up, WPARAM wParam, LPARAM l
|
|||
me.Y += a->vscrollpos;
|
||||
}
|
||||
|
||||
loadAreaSize(a, NULL, &(me.AreaWidth), &(me.AreaHeight));
|
||||
loadAreaSize(a, &(me.AreaWidth), &(me.AreaHeight));
|
||||
|
||||
me.Down = down;
|
||||
me.Up = up;
|
||||
|
|
|
@ -2,20 +2,35 @@
|
|||
#include "uipriv_windows.hpp"
|
||||
#include "area.hpp"
|
||||
|
||||
void loadAreaSize(uiArea *a, ID2D1RenderTarget *rt, double *width, double *height)
|
||||
// TODO: make those int rather than double
|
||||
void loadAreaSize(uiArea *a, double *width, double *height)
|
||||
{
|
||||
D2D1_SIZE_F size;
|
||||
|
||||
if (a->width != -1)
|
||||
{
|
||||
*width = (double)a->width;
|
||||
*height = (double)a->height;
|
||||
return;
|
||||
}
|
||||
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
if (!a->scrolling) {
|
||||
if (rt == NULL)
|
||||
/*if (rt == NULL)
|
||||
rt = a->rt;
|
||||
size = realGetSize(rt);
|
||||
*width = size.width;
|
||||
*height = size.height;
|
||||
dipToPixels(a, width, height);
|
||||
dipToPixels(a, width, height);*/
|
||||
RECT rect;
|
||||
GetWindowRect(a->hwnd, &rect);
|
||||
*width = (double)(rect.right - rect.left);
|
||||
*height = (double)(rect.bottom - rect.top);
|
||||
}
|
||||
|
||||
a->width = (int)*width;
|
||||
a->height = (int)*height;
|
||||
}
|
||||
|
||||
void pixelsToDIP(uiArea *a, double *x, double *y)
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
// 31 march 2019
|
||||
#include "uipriv_windows.hpp"
|
||||
#include "area.hpp"
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/wglext.h>
|
||||
|
||||
struct uiGLContext
|
||||
{
|
||||
uiArea* a;
|
||||
|
||||
HWND hwnd;
|
||||
HDC dc;
|
||||
HGLRC rc;
|
||||
|
||||
unsigned int version;
|
||||
};
|
||||
|
||||
|
||||
uiGLContext* createGLContext(uiArea* a, int vermajor, int verminor)
|
||||
{
|
||||
uiGLContext* ctx;
|
||||
BOOL res;
|
||||
|
||||
ctx = uiNew(uiGLContext);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->hwnd = a->hwnd;
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
pfd.cAlphaBits = 8;
|
||||
pfd.cDepthBits = 24;
|
||||
pfd.cStencilBits = 8;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
ctx->dc = GetDC(ctx->hwnd);
|
||||
if (!ctx->dc)
|
||||
{
|
||||
uiFree(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pixelformat = ChoosePixelFormat(ctx->dc, &pfd);
|
||||
res = SetPixelFormat(ctx->dc, pixelformat, &pfd);
|
||||
if (!res)
|
||||
{
|
||||
ReleaseDC(ctx->hwnd, ctx->dc);
|
||||
uiFree(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->rc = wglCreateContext(ctx->dc);
|
||||
if (!ctx->rc)
|
||||
{
|
||||
ReleaseDC(ctx->hwnd, ctx->dc);
|
||||
uiFree(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wglMakeCurrent(ctx->dc, ctx->rc);
|
||||
|
||||
if (vermajor >= 3)
|
||||
{
|
||||
HGLRC (*wglCreateContextAttribsARB)(HDC,HGLRC,const int*);
|
||||
HGLRC rc_better = NULL;
|
||||
|
||||
wglCreateContextAttribsARB = (HGLRC(*)(HDC,HGLRC,const int*))wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
if (wglCreateContextAttribsARB)
|
||||
{
|
||||
int attribs[15];
|
||||
int i = 0;
|
||||
|
||||
attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
|
||||
attribs[i++] = vermajor;
|
||||
attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||
attribs[i++] = verminor;
|
||||
|
||||
attribs[i] = 0;
|
||||
rc_better = wglCreateContextAttribsARB(ctx->dc, NULL, attribs);
|
||||
}
|
||||
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(ctx->rc);
|
||||
|
||||
if (!rc_better)
|
||||
{
|
||||
ReleaseDC(ctx->hwnd, ctx->dc);
|
||||
uiFree(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->version = uiGLVersion(vermajor, verminor);
|
||||
ctx->rc = rc_better;
|
||||
wglMakeCurrent(ctx->dc, ctx->rc);
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void freeGLContext(uiGLContext* ctx)
|
||||
{
|
||||
if (ctx == NULL) return;
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(ctx->rc);
|
||||
ReleaseDC(ctx->hwnd, ctx->dc);
|
||||
uiFree(ctx);
|
||||
}
|
||||
|
||||
void uiGLMakeContextCurrent(uiGLContext* ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
{
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wglGetCurrentContext() == ctx->rc) return;
|
||||
int res = wglMakeCurrent(ctx->dc, ctx->rc);
|
||||
}
|
||||
|
||||
unsigned int uiGLGetVersion(uiGLContext* ctx)
|
||||
{
|
||||
if (ctx == NULL) return 0;
|
||||
return ctx->version;
|
||||
}
|
||||
|
||||
void *uiGLGetProcAddress(const char* proc)
|
||||
{
|
||||
return (void*)wglGetProcAddress(proc);
|
||||
}
|
||||
|
||||
void uiGLSwapBuffers(uiGLContext* ctx)
|
||||
{
|
||||
if (ctx == NULL) return;
|
||||
SwapBuffers(ctx->dc);
|
||||
}
|
|
@ -363,6 +363,21 @@ static void windowMonitorRect(HWND hwnd, RECT *r)
|
|||
*r = mi.rcMonitor;
|
||||
}
|
||||
|
||||
void uiWindowPosition(uiWindow *w, int *x, int *y)
|
||||
{
|
||||
RECT rect;
|
||||
if (GetWindowRect(w->hwnd, &rect) == 0)
|
||||
logLastError(L"error getting window position");
|
||||
*x = rect.left;
|
||||
*y = rect.top;
|
||||
}
|
||||
|
||||
void uiWindowSetPosition(uiWindow *w, int x, int y)
|
||||
{
|
||||
if (SetWindowPos(w->hwnd, NULL, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER | SWP_NOZORDER) == 0)
|
||||
logLastError(L"error moving window");
|
||||
}
|
||||
|
||||
void uiWindowContentSize(uiWindow *w, int *width, int *height)
|
||||
{
|
||||
RECT r;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
Copyright 2016-2019 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef MAIN_SHADERS_H
|
||||
#define MAIN_SHADERS_H
|
||||
|
||||
const char* kScreenVS = R"(#version 140
|
||||
|
||||
layout(std140) uniform uConfig
|
||||
{
|
||||
vec2 uScreenSize;
|
||||
uint u3DScale;
|
||||
uint uFilterMode;
|
||||
};
|
||||
|
||||
in vec2 vPosition;
|
||||
in vec2 vTexcoord;
|
||||
|
||||
smooth out vec2 fTexcoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 fpos;
|
||||
fpos.xy = ((vPosition.xy * 2.0) / uScreenSize) - 1.0;
|
||||
fpos.y *= -1;
|
||||
fpos.z = 0.0;
|
||||
fpos.w = 1.0;
|
||||
|
||||
gl_Position = fpos;
|
||||
fTexcoord = vTexcoord;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kScreenFS = R"(#version 140
|
||||
|
||||
layout(std140) uniform uConfig
|
||||
{
|
||||
vec2 uScreenSize;
|
||||
uint u3DScale;
|
||||
uint uFilterMode;
|
||||
};
|
||||
|
||||
uniform usampler2D ScreenTex;
|
||||
|
||||
smooth in vec2 fTexcoord;
|
||||
|
||||
out vec4 oColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0));
|
||||
|
||||
// TODO: filters
|
||||
|
||||
oColor = vec4(vec3(pixel.bgr) / 255.0, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
const char* kScreenFS_Accel = R"(#version 140
|
||||
|
||||
layout(std140) uniform uConfig
|
||||
{
|
||||
vec2 uScreenSize;
|
||||
uint u3DScale;
|
||||
uint uFilterMode;
|
||||
};
|
||||
|
||||
uniform usampler2D ScreenTex;
|
||||
uniform sampler2D _3DTex;
|
||||
|
||||
smooth in vec2 fTexcoord;
|
||||
|
||||
out vec4 oColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec4 pixel = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord), 0));
|
||||
|
||||
ivec4 mbright = ivec4(texelFetch(ScreenTex, ivec2(256*3, int(fTexcoord.y)), 0));
|
||||
int dispmode = mbright.b & 0x3;
|
||||
|
||||
if (dispmode == 1)
|
||||
{
|
||||
ivec4 val1 = pixel;
|
||||
ivec4 val2 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(256,0), 0));
|
||||
ivec4 val3 = ivec4(texelFetch(ScreenTex, ivec2(fTexcoord) + ivec2(512,0), 0));
|
||||
|
||||
int compmode = val3.a & 0xF;
|
||||
int eva, evb, evy;
|
||||
|
||||
if (compmode == 4)
|
||||
{
|
||||
// 3D on top, blending
|
||||
|
||||
float xpos = val3.r + fract(fTexcoord.x);
|
||||
float ypos = mod(fTexcoord.y, 192);
|
||||
ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra
|
||||
* vec4(63,63,63,31));
|
||||
|
||||
if (_3dpix.a > 0)
|
||||
{
|
||||
eva = (_3dpix.a & 0x1F) + 1;
|
||||
evb = 32 - eva;
|
||||
|
||||
val1 = ((_3dpix * eva) + (val1 * evb)) >> 5;
|
||||
if (eva <= 16) val1 += ivec4(1,1,1,0);
|
||||
val1 = min(val1, 0x3F);
|
||||
}
|
||||
else
|
||||
val1 = val2;
|
||||
}
|
||||
else if (compmode == 1)
|
||||
{
|
||||
// 3D on bottom, blending
|
||||
|
||||
float xpos = val3.r + fract(fTexcoord.x);
|
||||
float ypos = mod(fTexcoord.y, 192);
|
||||
ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra
|
||||
* vec4(63,63,63,31));
|
||||
|
||||
if (_3dpix.a > 0)
|
||||
{
|
||||
eva = val3.g;
|
||||
evb = val3.b;
|
||||
|
||||
val1 = ((val1 * eva) + (_3dpix * evb)) >> 4;
|
||||
val1 = min(val1, 0x3F);
|
||||
}
|
||||
else
|
||||
val1 = val2;
|
||||
}
|
||||
else if (compmode <= 3)
|
||||
{
|
||||
// 3D on top, normal/fade
|
||||
|
||||
float xpos = val3.r + fract(fTexcoord.x);
|
||||
float ypos = mod(fTexcoord.y, 192);
|
||||
ivec4 _3dpix = ivec4(texelFetch(_3DTex, ivec2(vec2(xpos, ypos)*u3DScale), 0).bgra
|
||||
* vec4(63,63,63,31));
|
||||
|
||||
if (_3dpix.a > 0)
|
||||
{
|
||||
evy = val3.g;
|
||||
|
||||
val1 = _3dpix;
|
||||
if (compmode == 2) val1 += ((ivec4(0x3F,0x3F,0x3F,0) - val1) * evy) >> 4;
|
||||
else if (compmode == 3) val1 -= (val1 * evy) >> 4;
|
||||
}
|
||||
else
|
||||
val1 = val2;
|
||||
}
|
||||
|
||||
pixel = val1;
|
||||
}
|
||||
|
||||
if (dispmode != 0)
|
||||
{
|
||||
int brightmode = mbright.g >> 6;
|
||||
if (brightmode == 1)
|
||||
{
|
||||
// up
|
||||
int evy = mbright.r & 0x1F;
|
||||
if (evy > 16) evy = 16;
|
||||
|
||||
pixel += ((ivec4(0x3F,0x3F,0x3F,0) - pixel) * evy) >> 4;
|
||||
}
|
||||
else if (brightmode == 2)
|
||||
{
|
||||
// down
|
||||
int evy = mbright.r & 0x1F;
|
||||
if (evy > 16) evy = 16;
|
||||
|
||||
pixel -= (pixel * evy) >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
pixel.rgb <<= 2;
|
||||
pixel.rgb |= (pixel.rgb >> 6);
|
||||
|
||||
// TODO: filters
|
||||
|
||||
oColor = vec4(vec3(pixel.rgb) / 255.0, 1.0);
|
||||
}
|
||||
)";
|
||||
|
||||
#endif // MAIN_SHADERS_H
|
Loading…
Reference in New Issue