Merge branch 'blackmagic'

BAHAHAHHAHAHAHAAHAHAHAHHH

HARK HARK HARK HARK HA-*~
This commit is contained in:
Arisotura 2019-05-25 20:42:27 +02:00
commit 94f5ecb647
33 changed files with 4296 additions and 631 deletions

View File

@ -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" />

View File

@ -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!!!

View File

@ -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}
};

View File

@ -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

View File

@ -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;
}

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);
}

View File

@ -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

1124
src/GPU3D_OpenGL.cpp Normal file

File diff suppressed because it is too large Load Diff

690
src/GPU3D_OpenGL_shaders.h Normal file
View File

@ -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

View File

@ -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];
}

View File

@ -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);

119
src/OpenGLSupport.cpp Normal file
View File

@ -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]);
}

123
src/OpenGLSupport.h Normal file
View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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));
}
}

View File

@ -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

View File

@ -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;

View File

@ -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},

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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

View File

@ -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