Merge branch 'master' into fast-forward-hotkey

This commit is contained in:
Arisotura 2019-06-04 15:53:08 +02:00 committed by GitHub
commit 97f4b5f70b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 5643 additions and 693 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ obj
*.o
melon_grc.c
melon_grc.h
cmake-build

View File

@ -21,11 +21,13 @@ else()
endif()
if(ENABLE_LTO)
add_compile_options(-flto)
add_compile_options(-O3 -flto)
endif()
add_compile_options(-fno-pic)
add_link_options(-no-pie)
option(BUILD_LIBUI "Build libui frontend" ON)
option(BUILD_SDL "Build SDL2 frontend" OFF)
add_subdirectory(src)
@ -33,10 +35,6 @@ if (BUILD_LIBUI)
add_subdirectory(src/libui_sdl)
endif()
if (BUILD_SDL)
add_subdirectory(src/sdl)
endif()
configure_file(
${CMAKE_SOURCE_DIR}/romlist.bin
${CMAKE_BINARY_DIR}/romlist.bin COPYONLY)

View File

@ -2,7 +2,7 @@
<h2 align="center"><b>melonDS</b></h2>
<p align="center">
<a href="http://melonds.kuribo64.net/" alt="melonDS website"><img src="https://img.shields.io/badge/website-melonds.kuribo64.net-%2331352e.svg"></a>
<a href="http://melonds.kuribo64.net/downloads.php" alt="Release: 0.7.4"><img src="https://img.shields.io/badge/release-0.7.4-%235c913b.svg"></a>
<a href="http://melonds.kuribo64.net/downloads.php" alt="Release: 0.8"><img src="https://img.shields.io/badge/release-0.8-%235c913b.svg"></a>
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-%23ff554d.svg"></a>
<a href="https://kiwiirc.com/client/irc.badnik.net/?nick=IRC-Source_?#melonds" alt="IRC channel: #melonds"><img src="https://img.shields.io/badge/IRC%20chat-%23melonds-%23dd2e44.svg"></a>
</p>
@ -78,7 +78,6 @@ If everything went well, melonDS and the libraries it needs should now be in the
## TODO LIST
* improve libui and the emulator UI
* hardware renderer for 3D (w/ upscaling and fancy shit)
* support for rendering screens to separate windows
* emulating some fancy addons
* other non-core shit (debugger, graphics viewers, cheat crapo, etc)

View File

@ -6,8 +6,8 @@
//include version information in .exe, modify these values to match your needs
1 VERSIONINFO
FILEVERSION 0,7,4,0
PRODUCTVERSION 0,7,4,0
FILEVERSION 0,8,0,0
PRODUCTVERSION 0,8,0,0
FILETYPE VFT_APP
{
BLOCK "StringFileInfo"
@ -15,14 +15,14 @@ FILETYPE VFT_APP
BLOCK "040904E4"
{
VALUE "CompanyName", "Melon Factory of Kuribo64"
VALUE "FileVersion", "0.7.4"
VALUE "FileVersion", "0.8"
VALUE "FileDescription", "DS emulator, sorta. also 1st quality melon."
VALUE "InternalName", "SDnolem"
VALUE "LegalCopyright", "2016-2019 Arisotura & co."
VALUE "LegalTrademarks", ""
VALUE "OriginalFilename", "zafkflzdasd.exe"
VALUE "ProductName", "melonDS"
VALUE "ProductVersion", "0.7.4"
VALUE "ProductVersion", "0.8"
}
}
BLOCK "VarFileInfo"

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">
@ -46,27 +30,12 @@
<Compiler>
<Add option="-O3" />
<Add option="-m64" />
<Add option="-flto" />
<Add option="-D_FILE_OFFSET_BITS=64" />
</Compiler>
<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 +51,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 +60,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 +107,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,15 +135,20 @@
<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" />
<Unit filename="src/libui_sdl/LAN_PCap.h" />
<Unit filename="src/libui_sdl/LAN_Socket.cpp" />
<Unit filename="src/libui_sdl/LAN_Socket.h" />
<Unit filename="src/libui_sdl/OSD.cpp" />
<Unit filename="src/libui_sdl/OSD.h" />
<Unit filename="src/libui_sdl/Platform.cpp" />
<Unit filename="src/libui_sdl/PlatformConfig.cpp" />
<Unit filename="src/libui_sdl/PlatformConfig.h" />
<Unit filename="src/libui_sdl/font.h" />
<Unit filename="src/libui_sdl/libui/common/areaevents.c">
<Option compilerVar="CC" />
</Unit>
@ -222,6 +203,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 +235,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

@ -13,9 +13,11 @@ add_library(core STATIC
GPU.cpp
GPU2D.cpp
GPU3D.cpp
GPU3D_OpenGL.cpp
GPU3D_Soft.cpp
NDS.cpp
NDSCart.cpp
OpenGLSupport.cpp
RTC.cpp
Savestate.cpp
SPI.cpp
@ -25,5 +27,7 @@ add_library(core STATIC
)
if (WIN32)
target_link_libraries(core ole32 comctl32 ws2_32)
target_link_libraries(core ole32 comctl32 ws2_32 opengl32)
else()
target_link_libraries(core GL EGL)
endif()

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] __attribute__((aligned (8)));
u32* _3DLine;
u8 WindowMask[256] __attribute__((aligned (8)));
u32 OBJLine[256] __attribute__((aligned (8)));
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

1127
src/GPU3D_OpenGL.cpp Normal file

File diff suppressed because it is too large Load Diff

695
src/GPU3D_OpenGL_shaders.h Normal file
View File

@ -0,0 +1,695 @@
/*
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 vec4 oAttr;
void main()
{
oColor = vec4(uColor).bgra / 31.0;
oAttr.r = float(uOpaquePolyID) / 63.0;
oAttr.g = 0;
oAttr.b = float(uFogFlag);
oAttr.a = 1;
}
)";
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 sampler2D 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);
vec4 attr = 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 vec4 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 = float((fPolygonAttr.x >> 24) & 0x3F) / 63.0;
oAttr.b = float((fPolygonAttr.x >> 15) & 0x1);
oAttr.a = 1;
}
)";
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 = float((fPolygonAttr.x >> 24) & 0x3F) / 63.0;
oAttr.b = float((fPolygonAttr.x >> 15) & 0x1);
oAttr.a = 1;
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 = 0;
oAttr.a = 1;
}
)";
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 = 0;
oAttr.a = 1;
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);

128
src/OpenGLSupport.cpp Normal file
View File

@ -0,0 +1,128 @@
/*
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]);
return true;
}
bool OpenGL_LinkShaderProgram(GLuint* ids)
{
int res;
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 shader program: %s\n", 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]);
}

137
src/OpenGLSupport.h Normal file
View File

@ -0,0 +1,137 @@
/*
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 <string.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
#ifndef __WIN32__
#define DO_PROCLIST_1_3(func)
#else
#define DO_PROCLIST_1_3(func) \
func(GLACTIVETEXTURE, glActiveTexture); \
func(GLBLENDCOLOR, glBlendColor); \
#endif
#define DO_PROCLIST(func) \
DO_PROCLIST_1_3(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(GLUNIFORM2I, glUniform2i); \
func(GLUNIFORM4UI, glUniform4ui); \
func(GLUNIFORMBLOCKBINDING, glUniformBlockBinding); \
func(GLGETUNIFORMLOCATION, glGetUniformLocation); \
func(GLGETUNIFORMBLOCKINDEX, glGetUniformBlockIndex); \
\
func(GLBINDIMAGETEXTURE, glBindImageTexture); \
\
func(GLDRAWBUFFERS, glDrawBuffers); \
\
func(GLBLENDFUNCSEPARATE, glBlendFuncSeparate); \
func(GLBLENDEQUATIONSEPARATE, glBlendEquationSeparate); \
\
func(GLCOLORMASKI, glColorMaski); \
\
func(GLGETSTRINGI, glGetStringi); \
DO_PROCLIST(DECLPROC_EXT);
bool OpenGL_Init();
bool OpenGL_BuildShaderProgram(const char* vs, const char* fs, GLuint* ids, const char* name);
bool OpenGL_LinkShaderProgram(GLuint* ids);
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

@ -130,11 +130,11 @@ void Reset()
// take a backup
const char* firmbkp = "firmware.bin.bak";
f = fopen(firmbkp, "rb");
f = Platform::OpenLocalFile(firmbkp, "rb");
if (f) fclose(f);
else
{
f = fopen(firmbkp, "wb");
f = Platform::OpenLocalFile(firmbkp, "wb");
fwrite(Firmware, 1, FirmwareLength, f);
fclose(f);
}

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

@ -9,7 +9,9 @@ SET(SOURCES_LIBUI
DlgAudioSettings.cpp
DlgEmuSettings.cpp
DlgInputConfig.cpp
DlgVideoSettings.cpp
DlgWifiSettings.cpp
OSD.cpp
)
option(BUILD_SHARED_LIBS "Whether to build libui as a shared library or a static library" ON)

View File

@ -44,8 +44,15 @@ uiEntry* txMicWavPath;
int oldvolume;
void RevertSettings()
{
Config::AudioVolume = oldvolume;
}
int OnCloseWindow(uiWindow* window, void* blarg)
{
RevertSettings();
opened = false;
return 1;
}
@ -69,7 +76,7 @@ void OnMicWavBrowse(uiButton* btn, void* blarg)
void OnCancel(uiButton* btn, void* blarg)
{
Config::AudioVolume = oldvolume;
RevertSettings();
uiControlDestroy(uiControl(win));
opened = false;
@ -180,4 +187,11 @@ void Open()
uiControlShow(uiControl(win));
}
void Close()
{
if (!opened) return;
uiControlDestroy(uiControl(win));
opened = false;
}
}

View File

@ -23,6 +23,7 @@ namespace DlgAudioSettings
{
void Open();
void Close();
}

View File

@ -37,7 +37,6 @@ bool opened;
uiWindow* win;
uiCheckbox* cbDirectBoot;
uiCheckbox* cbThreaded3D;
int OnCloseWindow(uiWindow* window, void* blarg)
@ -55,14 +54,11 @@ void OnCancel(uiButton* btn, void* blarg)
void OnOk(uiButton* btn, void* blarg)
{
Config::DirectBoot = uiCheckboxChecked(cbDirectBoot);
Config::Threaded3D = uiCheckboxChecked(cbThreaded3D);
Config::Save();
uiControlDestroy(uiControl(win));
opened = false;
ApplyNewSettings(0);
}
void Open()
@ -87,9 +83,6 @@ void Open()
cbDirectBoot = uiNewCheckbox("Boot game directly");
uiBoxAppend(in_ctrl, uiControl(cbDirectBoot), 0);
cbThreaded3D = uiNewCheckbox("Threaded 3D renderer");
uiBoxAppend(in_ctrl, uiControl(cbThreaded3D), 0);
}
{
@ -110,9 +103,15 @@ void Open()
}
uiCheckboxSetChecked(cbDirectBoot, Config::DirectBoot);
uiCheckboxSetChecked(cbThreaded3D, Config::Threaded3D);
uiControlShow(uiControl(win));
}
void Close()
{
if (!opened) return;
uiControlDestroy(uiControl(win));
opened = false;
}
}

View File

@ -23,6 +23,7 @@ namespace DlgEmuSettings
{
void Open();
void Close();
}

View File

@ -64,6 +64,21 @@ int openedmask;
InputDlgData inputdlg[2];
void KeyMappingName(int id, char* str)
{
if (id < 0)
{
strcpy(str, "None");
return;
}
char* keyname = uiKeyName(id);
strncpy(str, keyname, 31);
uiFreeText(keyname);
str[31] = '\0';
}
void JoyMappingName(int id, char* str)
{
if (id < 0)
@ -134,7 +149,7 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
return 1;
}
char keyname[16];
char keyname[32];
JoyMappingName(dlg->joymap[id], keyname);
uiButtonSetText(dlg->pollbtn, keyname);
uiControlEnable(uiControl(dlg->pollbtn));
@ -150,12 +165,17 @@ int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
{
// set key.
if (evt->Scancode != 0x1) // ESC
dlg->keymap[dlg->pollid] = evt->Scancode;
{
if (evt->Scancode == 0xE) // backspace
dlg->keymap[dlg->pollid] = -1;
else
dlg->keymap[dlg->pollid] = evt->Scancode;
}
char* keyname = uiKeyName(dlg->keymap[dlg->pollid]);
char keyname[32];
KeyMappingName(dlg->keymap[dlg->pollid], keyname);
uiButtonSetText(dlg->pollbtn, keyname);
uiControlEnable(uiControl(dlg->pollbtn));
uiFreeText(keyname);
dlg->pollid = -1;
@ -170,7 +190,7 @@ void FinishJoyMapping(void* param)
InputDlgData* dlg = (InputDlgData*)param;
int id = dlg->pollid & 0xFF;
char keyname[16];
char keyname[32];
JoyMappingName(dlg->joymap[id], keyname);
uiButtonSetText(dlg->pollbtn, keyname);
uiControlEnable(uiControl(dlg->pollbtn));
@ -386,15 +406,14 @@ void Open(int type)
uiGridAppend(b_key, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter);
uiControlSetMinSize(uiControl(label), width, 1);
char* keyname = uiKeyName(dlg->keymap[j]);
char keyname[32];
KeyMappingName(dlg->keymap[j], keyname);
uiButton* btn = uiNewButton(keyname);
uiControl(btn)->UserData = dlg;
uiGridAppend(b_key, uiControl(btn), 1, i, 1, 1, 1, uiAlignFill, 1, uiAlignCenter);
uiButtonOnClicked(btn, OnKeyStartConfig, (type==0) ? &dskeyorder[i] : &identity[i]);
uiControlSetMinSize(uiControl(btn), width, 1);
uiFreeText(keyname);
}
uiGroup* g_joy = uiNewGroup("Joystick");
@ -410,7 +429,7 @@ void Open(int type)
uiGridAppend(b_joy, uiControl(label), 0, i, 1, 1, 1, uiAlignStart, 1, uiAlignCenter);
uiControlSetMinSize(uiControl(label), width, 1);
char keyname[16];
char keyname[32];
JoyMappingName(dlg->joymap[j], keyname);
uiButton* btn = uiNewButton(keyname);
@ -450,5 +469,13 @@ void Open(int type)
uiControlShow(uiControl(dlg->win));
}
void Close(int type)
{
if (openedmask & (1<<type))
uiControlDestroy(uiControl(inputdlg[type].win));
openedmask &= ~(1<<type);
}
}

View File

@ -23,6 +23,7 @@ namespace DlgInputConfig
{
void Open(int type);
void Close(int type);
}

View File

@ -0,0 +1,324 @@
/*
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));
}
}
void RevertSettings()
{
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);
}
int OnCloseWindow(uiWindow* window, void* blarg)
{
RevertSettings();
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);
uiControlSetFocus(uiControl(win));
}
void OnGLDisplayChanged(uiCheckbox* cb, void* blarg)
{
Config::ScreenUseGL = uiCheckboxChecked(cb);
ApplyNewSettings(2);
uiControlSetFocus(uiControl(win));
}
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)
{
RevertSettings();
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));
}
void Close()
{
if (!opened) return;
uiControlDestroy(uiControl(win));
opened = false;
}
}

View File

@ -0,0 +1,30 @@
/*
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();
void Close();
}
#endif // DLGVIDEOSETTINGS_H

View File

@ -261,4 +261,11 @@ void Open()
uiControlShow(uiControl(win));
}
void Close()
{
if (!opened) return;
uiControlDestroy(uiControl(win));
opened = false;
}
}

View File

@ -23,6 +23,7 @@ namespace DlgWifiSettings
{
void Open();
void Close();
}

423
src/libui_sdl/OSD.cpp Normal file
View File

@ -0,0 +1,423 @@
/*
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 <stdio.h>
#include <string.h>
#include <deque>
#include <SDL2/SDL.h>
#include "../types.h"
#include "libui/ui.h"
#include "../OpenGLSupport.h"
#include "OSD.h"
#include "font.h"
extern int WindowWidth, WindowHeight;
namespace OSD
{
const u32 kOSDMargin = 6;
struct Item
{
Uint32 Timestamp;
char Text[256];
u32 Color;
u32 Width, Height;
u32* Bitmap;
bool DrawBitmapLoaded;
uiDrawBitmap* DrawBitmap;
bool GLTextureLoaded;
GLuint GLTexture;
};
std::deque<Item> ItemQueue;
GLint uOSDPos, uOSDSize;
GLuint OSDVertexArray;
GLuint OSDVertexBuffer;
volatile bool Rendering;
bool Init(bool opengl)
{
if (opengl)
{
GLuint prog; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&prog);
uOSDPos = glGetUniformLocation(prog, "uOSDPos");
uOSDSize = glGetUniformLocation(prog, "uOSDSize");
float vertices[6*2] =
{
0, 0,
1, 1,
1, 0,
0, 0,
0, 1,
1, 1
};
glGenBuffers(1, &OSDVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &OSDVertexArray);
glBindVertexArray(OSDVertexArray);
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)(0));
}
return true;
}
void DeInit(bool opengl)
{
for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
{
Item& item = *it;
if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap);
if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture);
if (item.Bitmap) delete[] item.Bitmap;
it = ItemQueue.erase(it);
}
}
int FindBreakPoint(const char* text, int i)
{
// i = character that went out of bounds
for (int j = i; j >= 0; j--)
{
if (text[j] == ' ')
return j;
}
return i;
}
void LayoutText(const char* text, u32* width, u32* height, int* breaks)
{
u32 w = 0;
u32 h = 14;
u32 totalw = 0;
u32 maxw = WindowWidth - (kOSDMargin*2);
int lastbreak = -1;
int numbrk = 0;
u16* ptr;
memset(breaks, 0, sizeof(int)*64);
for (int i = 0; text[i] != '\0'; )
{
int glyphsize;
if (text[i] == ' ')
{
glyphsize = 6;
}
else
{
u32 ch = text[i];
if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
ptr = &font[(ch-0x10) << 4];
glyphsize = ptr[0];
if (!glyphsize) glyphsize = 6;
else glyphsize += 2; // space around the character
}
w += glyphsize;
if (w > maxw)
{
// wrap shit as needed
if (text[i] == ' ')
{
if (numbrk >= 64) break;
breaks[numbrk++] = i;
i++;
}
else
{
int brk = FindBreakPoint(text, i);
if (brk != lastbreak) i = brk;
if (numbrk >= 64) break;
breaks[numbrk++] = i;
lastbreak = brk;
}
w = 0;
h += 14;
}
else
i++;
if (w > totalw) totalw = w;
}
*width = totalw;
*height = h;
}
u32 RainbowColor(u32 inc)
{
// inspired from Acmlmboard
if (inc < 100) return 0xFFFF9B9B + (inc << 8);
else if (inc < 200) return 0xFFFFFF9B - ((inc-100) << 16);
else if (inc < 300) return 0xFF9BFF9B + (inc-200);
else if (inc < 400) return 0xFF9BFFFF - ((inc-300) << 8);
else if (inc < 500) return 0xFF9B9BFF + ((inc-400) << 16);
else return 0xFFFF9BFF - (inc-500);
}
void RenderText(u32 color, const char* text, Item* item)
{
u32 w, h;
int breaks[64];
bool rainbow = (color == 0);
u32 rainbowinc = (text[0] * 17) % 600;
color |= 0xFF000000;
const u32 shadow = 0xE0000000;
LayoutText(text, &w, &h, breaks);
item->Width = w;
item->Height = h;
item->Bitmap = new u32[w*h];
memset(item->Bitmap, 0, w*h*sizeof(u32));
u32 x = 0, y = 1;
u32 maxw = WindowWidth - (kOSDMargin*2);
int curline = 0;
u16* ptr;
for (int i = 0; text[i] != '\0'; )
{
int glyphsize;
if (text[i] == ' ')
{
x += 6;
}
else
{
u32 ch = text[i];
if (ch < 0x10 || ch > 0x7E) ch = 0x7F;
ptr = &font[(ch-0x10) << 4];
int glyphsize = ptr[0];
if (!glyphsize) x += 6;
else
{
x++;
if (rainbow)
{
color = RainbowColor(rainbowinc);
rainbowinc = (rainbowinc + 30) % 600;
}
// draw character
for (int cy = 0; cy < 12; cy++)
{
u16 val = ptr[4+cy];
for (int cx = 0; cx < glyphsize; cx++)
{
if (val & (1<<cx))
item->Bitmap[((y+cy) * w) + x+cx] = color;
}
}
x += glyphsize;
x++;
}
}
i++;
if (breaks[curline] && i >= breaks[curline])
{
i = breaks[curline++];
if (text[i] == ' ') i++;
x = 0;
y += 14;
}
}
// shadow
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
{
u32 val;
val = item->Bitmap[(y * w) + x];
if ((val >> 24) == 0xFF) continue;
if (x > 0) val = item->Bitmap[(y * w) + x-1];
if (x < w-1) val |= item->Bitmap[(y * w) + x+1];
if (y > 0)
{
if (x > 0) val |= item->Bitmap[((y-1) * w) + x-1];
val |= item->Bitmap[((y-1) * w) + x];
if (x < w-1) val |= item->Bitmap[((y-1) * w) + x+1];
}
if (y < h-1)
{
if (x > 0) val |= item->Bitmap[((y+1) * w) + x-1];
val |= item->Bitmap[((y+1) * w) + x];
if (x < w-1) val |= item->Bitmap[((y+1) * w) + x+1];
}
if ((val >> 24) == 0xFF)
item->Bitmap[(y * w) + x] = shadow;
}
}
}
void AddMessage(u32 color, const char* text)
{
while (Rendering);
Item item;
item.Timestamp = SDL_GetTicks();
strncpy(item.Text, text, 255); item.Text[255] = '\0';
item.Color = color;
item.Bitmap = NULL;
item.DrawBitmapLoaded = false;
item.GLTextureLoaded = false;
ItemQueue.push_back(item);
}
void WindowResized(bool opengl)
{
/*for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
{
Item& item = *it;
if (item->DrawBitmapLoaded && item->DrawBitmap) uiDrawFreeBitmap(item->DrawBitmap);
//if (item->GLTextureLoaded && opengl) glDeleteTextures(1, &item->GLTexture);
item->DrawBitmapLoaded = false;
item->GLTextureLoaded = false;
if (item->Bitmap) delete[] item->Bitmap;
it++;
}*/
}
void Update(bool opengl, uiAreaDrawParams* params)
{
Rendering = true;
Uint32 tick_now = SDL_GetTicks();
Uint32 tick_min = tick_now - 2500;
u32 y = kOSDMargin;
if (opengl)
{
glBindBuffer(GL_ARRAY_BUFFER, OSDVertexBuffer);
glBindVertexArray(OSDVertexArray);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
for (auto it = ItemQueue.begin(); it != ItemQueue.end(); )
{
Item& item = *it;
if (item.Timestamp < tick_min)
{
if (item.DrawBitmapLoaded && item.DrawBitmap) uiDrawFreeBitmap(item.DrawBitmap);
if (item.GLTextureLoaded && opengl) glDeleteTextures(1, &item.GLTexture);
if (item.Bitmap) delete[] item.Bitmap;
it = ItemQueue.erase(it);
continue;
}
if (!item.Bitmap)
{
RenderText(item.Color, item.Text, &item);
}
if (opengl)
{
if (!item.GLTextureLoaded)
{
glGenTextures(1, &item.GLTexture);
glBindTexture(GL_TEXTURE_2D, item.GLTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, item.Width, item.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, item.Bitmap);
item.GLTextureLoaded = true;
}
glBindTexture(GL_TEXTURE_2D, item.GLTexture);
glUniform2i(uOSDPos, kOSDMargin, y);
glUniform2i(uOSDSize, item.Width, item.Height);
glDrawArrays(GL_TRIANGLES, 0, 2*3);
}
else
{
if (!item.DrawBitmapLoaded)
{
item.DrawBitmap = uiDrawNewBitmap(params->Context, item.Width, item.Height, 1);
uiDrawBitmapUpdate(item.DrawBitmap, item.Bitmap);
item.DrawBitmapLoaded = true;
}
uiRect rc_src = {0, 0, item.Width, item.Height};
uiRect rc_dst = {kOSDMargin, y, item.Width, item.Height};
uiDrawBitmapDraw(params->Context, item.DrawBitmap, &rc_src, &rc_dst, 0);
}
y += item.Height;
it++;
}
Rendering = false;
}
}

35
src/libui_sdl/OSD.h Normal file
View File

@ -0,0 +1,35 @@
/*
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 OSD_H
#define OSD_H
namespace OSD
{
bool Init(bool opengl);
void DeInit(bool opengl);
void AddMessage(u32 color, const char* text);
void WindowResized(bool opengl);
void Update(bool opengl, uiAreaDrawParams* params);
}
#endif // OSD_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__
@ -166,7 +167,7 @@ FILE* OpenLocalFile(const char* path, const char* mode)
int len = emudirlen + 1 + pathlen + 1;
emudirpath = new char[len];
strncpy(&emudirpath[0], EmuDirectory, emudirlen);
emudirpath[emudirlen] = '\\';
emudirpath[emudirlen] = '/';
strncpy(&emudirpath[emudirlen+1], path, pathlen);
emudirpath[emudirlen+1+pathlen] = '\0';
}
@ -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;
@ -85,10 +88,10 @@ ConfigEntry PlatformConfigFile[] =
{"Joy_X", 0, &JoyMapping[10], -1, NULL, 0},
{"Joy_Y", 0, &JoyMapping[11], -1, NULL, 0},
{"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0E, NULL, 0},
{"HKKey_Lid", 0, &HKKeyMapping[HK_Lid], 0x0D, NULL, 0},
{"HKKey_Mic", 0, &HKKeyMapping[HK_Mic], 0x35, NULL, 0},
{"HKKey_FastForward", 0, &HKKeyMapping[HK_FastForward], 0x0F, NULL, 0},
{"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0}, // TODO: This doesn't unbind the key, just sets it to some random key
{"HKKey_FastForwardToggle", 0, &HKKeyMapping[HK_FastForwardToggle], -1, NULL, 0},
{"HKJoy_Lid", 0, &HKJoyMapping[HK_Lid], -1, NULL, 0},
{"HKJoy_Mic", 0, &HKJoyMapping[HK_Mic], -1, NULL, 0},
@ -105,6 +108,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

@ -49,6 +49,9 @@ extern int ScreenLayout;
extern int ScreenSizing;
extern int ScreenFilter;
extern int ScreenUseGL;
extern int ScreenRatio;
extern int LimitFPS;
extern int DirectBoot;

135
src/libui_sdl/font.h Normal file
View File

@ -0,0 +1,135 @@
/*
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 FONT_H
#define FONT_H
unsigned short font[] = {
12, 0, 0, 0,0x0C03, 0x0E07, 0x070E, 0x039C, 0x01F8, 0x00F0, 0x00F0, 0x01F8, 0x039C, 0x070E, 0x0E07, 0x0C03,
12, 0, 0, 0,0x01C0, 0x00E0, 0x0060, 0x0860, 0x0C60, 0x0FE0, 0x07F0, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0000, 0x0000,
9, 0, 0, 0,0x01EF, 0x01EF, 0x018C, 0x01CE, 0x00E7, 0x0063, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
10, 0, 0, 0,0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x03FF, 0x03FF, 0x00CC, 0x00CC, 0x0000, 0x0000,
8, 0, 0, 0,0x0018, 0x00FE, 0x00FF, 0x001B, 0x007F, 0x00FE, 0x00D8, 0x00FF, 0x007F, 0x0018, 0x0000, 0x0000,
10, 0, 0, 0,0x0306, 0x038F, 0x01CF, 0x00E6, 0x0070, 0x0038, 0x019C, 0x03CE, 0x03C7, 0x0183, 0x0000, 0x0000,
10, 0, 0, 0,0x007C, 0x00FE, 0x00C6, 0x00EE, 0x007C, 0x037E, 0x03E7, 0x01F3, 0x03BF, 0x031E, 0x0000, 0x0000,
4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
4, 0, 0, 0,0x000C, 0x000E, 0x0007, 0x0003, 0x0003, 0x0003, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000,
4, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x000C, 0x000C, 0x000C, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
10, 0, 0, 0,0x0030, 0x0333, 0x03B7, 0x01FE, 0x00FC, 0x00FC, 0x01FE, 0x03B7, 0x0333, 0x0030, 0x0000, 0x0000,
10, 0, 0, 0,0x0030, 0x0030, 0x0030, 0x0030, 0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000,
4, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000F, 0x000F, 0x000C, 0x000E, 0x0007, 0x0003,
10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
3, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0007, 0x0000, 0x0000,
10, 0, 0, 0,0x0300, 0x0380, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
4, 0, 0, 0,0x0006, 0x0007, 0x0007, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x000F, 0x000F, 0x0000, 0x0000,
8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C0, 0x00FE, 0x007F, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0000, 0x0000,
8, 0, 0, 0,0x007F, 0x00FF, 0x00C0, 0x00C0, 0x007C, 0x00FC, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000,
8, 0, 0, 0,0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x00FF, 0x00FE, 0x0060, 0x0060, 0x0000, 0x0000,
8, 0, 0, 0,0x00FF, 0x00FF, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C0, 0x00C0, 0x00FF, 0x007F, 0x0000, 0x0000,
8, 0, 0, 0,0x007E, 0x007F, 0x0003, 0x0003, 0x007F, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
8, 0, 0, 0,0x00FF, 0x00FF, 0x00C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000C, 0x000C, 0x000C, 0x0000, 0x0000,
8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00FF, 0x00FE, 0x00C0, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000,
3, 0, 0, 0,0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0000, 0x0000, 0x0000,
4, 0, 0, 0,0x0000, 0x0000, 0x000E, 0x000E, 0x0000, 0x0000, 0x000C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
6, 0, 0, 0,0x0030, 0x0038, 0x001C, 0x000E, 0x0007, 0x0007, 0x000E, 0x001C, 0x0038, 0x0030, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x007F, 0x007F, 0x0000, 0x0000, 0x0000,
6, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0038, 0x001C, 0x000E, 0x0007, 0x0003, 0x0000, 0x0000,
8, 0, 0, 0,0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00F0, 0x0078, 0x0018, 0x0000, 0x0018, 0x0018, 0x0000, 0x0000,
10, 0, 0, 0,0x00FC, 0x01FE, 0x0387, 0x0333, 0x037B, 0x03FB, 0x01F3, 0x0007, 0x03FE, 0x03FC, 0x0000, 0x0000,
9, 0, 0, 0,0x00FE, 0x01FF, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000,
9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0000, 0x0000,
8, 0, 0, 0,0x00FE, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x00FF, 0x00FE, 0x0000, 0x0000,
9, 0, 0, 0,0x007F, 0x00FF, 0x01C3, 0x0183, 0x0183, 0x0183, 0x0183, 0x01C3, 0x00FF, 0x007F, 0x0000, 0x0000,
9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x01FF, 0x01FF, 0x0000, 0x0000,
9, 0, 0, 0,0x01FF, 0x01FF, 0x0003, 0x0003, 0x00FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
9, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01F3, 0x01F3, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000,
9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x01FF, 0x0183, 0x0183, 0x0183, 0x0183, 0x0000, 0x0000,
6, 0, 0, 0,0x003F, 0x003F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x003F, 0x003F, 0x0000, 0x0000,
9, 0, 0, 0,0x01F0, 0x01F0, 0x00C0, 0x00C0, 0x00C0, 0x00C0, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
9, 0, 0, 0,0x0183, 0x01C3, 0x00E3, 0x0073, 0x003F, 0x003F, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000,
7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007F, 0x0000, 0x0000,
10, 0, 0, 0,0x0303, 0x0387, 0x03CF, 0x03FF, 0x037B, 0x0333, 0x0303, 0x0303, 0x0303, 0x0303, 0x0000, 0x0000,
10, 0, 0, 0,0x0303, 0x0307, 0x030F, 0x031F, 0x033B, 0x0373, 0x03E3, 0x03C3, 0x0383, 0x0303, 0x0000, 0x0000,
10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x03FF, 0x01FE, 0x0000, 0x0000,
9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
10, 0, 0, 0,0x01FE, 0x03FF, 0x0303, 0x0303, 0x0333, 0x0373, 0x03E3, 0x01C3, 0x03FF, 0x037E, 0x0000, 0x0000,
9, 0, 0, 0,0x00FF, 0x01FF, 0x0183, 0x0183, 0x01FF, 0x00FF, 0x0073, 0x00E3, 0x01C3, 0x0183, 0x0000, 0x0000,
10, 0, 0, 0,0x01FE, 0x01FF, 0x0003, 0x0003, 0x01FF, 0x03FE, 0x0300, 0x0300, 0x03FE, 0x01FE, 0x0000, 0x0000,
10, 0, 0, 0,0x03FF, 0x03FF, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000,
9, 0, 0, 0,0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x0183, 0x01FF, 0x00FE, 0x0000, 0x0000,
10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000,
10, 0, 0, 0,0x0303, 0x0303, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000,
10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0078, 0x00FC, 0x01CE, 0x0387, 0x0303, 0x0000, 0x0000,
10, 0, 0, 0,0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000,
10, 0, 0, 0,0x03FF, 0x03FF, 0x01C0, 0x00E0, 0x0070, 0x0038, 0x001C, 0x000E, 0x03FF, 0x03FF, 0x0000, 0x0000,
4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000F, 0x0000, 0x0000,
10, 0, 0, 0,0x0003, 0x0007, 0x000E, 0x001C, 0x0038, 0x0070, 0x00E0, 0x01C0, 0x0380, 0x0300, 0x0000, 0x0000,
4, 0, 0, 0,0x000F, 0x000F, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000F, 0x000F, 0x0000, 0x0000,
8, 0, 0, 0,0x0018, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03FF, 0x03FF,
4, 0, 0, 0,0x000F, 0x000F, 0x0003, 0x0007, 0x000E, 0x000C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007E, 0x0060, 0x007E, 0x007F, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000,
7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x003F, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x0003, 0x0003, 0x0003, 0x007F, 0x007E, 0x0000, 0x0000,
7, 0, 0, 0,0x0060, 0x0060, 0x0060, 0x007E, 0x007F, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x003E, 0x007F, 0x0063, 0x007F, 0x003F, 0x0003, 0x003F, 0x003E, 0x0000, 0x0000,
6, 0, 0, 0,0x003C, 0x003E, 0x0006, 0x0006, 0x001F, 0x001F, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x007E, 0x003E,
7, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000,
2, 0, 0, 0,0x0003, 0x0003, 0x0000, 0x0000, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
7, 0, 0, 0,0x0060, 0x0060, 0x0000, 0x0000, 0x0060, 0x0060, 0x0060, 0x0060, 0x0060, 0x0063, 0x007F, 0x003E,
8, 0, 0, 0,0x0003, 0x0003, 0x00E3, 0x0073, 0x003B, 0x001F, 0x001F, 0x003B, 0x0073, 0x00E3, 0x0000, 0x0000,
4, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x000F, 0x000E, 0x0000, 0x0000,
10, 0, 0, 0,0x0000, 0x0000, 0x01FF, 0x03FF, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0333, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0000, 0x0000,
8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x00FF, 0x00C3, 0x00C3, 0x00C3, 0x00C3, 0x00FF, 0x007E, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x003F, 0x007F, 0x0063, 0x0063, 0x007F, 0x003F, 0x0003, 0x0003, 0x0003, 0x0003,
7, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0063, 0x0063, 0x007F, 0x007E, 0x0060, 0x0060, 0x0060, 0x0060,
7, 0, 0, 0,0x0000, 0x0000, 0x003B, 0x007F, 0x0067, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
8, 0, 0, 0,0x0000, 0x0000, 0x007E, 0x007F, 0x0003, 0x007F, 0x00FE, 0x00C0, 0x00FE, 0x007E, 0x0000, 0x0000,
6, 0, 0, 0,0x0006, 0x0006, 0x003F, 0x003F, 0x0006, 0x0006, 0x0006, 0x0006, 0x003E, 0x003C, 0x0000, 0x0000,
7, 0, 0, 0,0x0000, 0x0000, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x0063, 0x007F, 0x007E, 0x0000, 0x0000,
10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0303, 0x0387, 0x01CE, 0x00FC, 0x0078, 0x0030, 0x0000, 0x0000,
10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0303, 0x0333, 0x037B, 0x03FF, 0x03CF, 0x0387, 0x0303, 0x0000, 0x0000,
8, 0, 0, 0,0x0000, 0x0000, 0x00C3, 0x00E7, 0x007E, 0x003C, 0x003C, 0x007E, 0x00E7, 0x00C3, 0x0000, 0x0000,
10, 0, 0, 0,0x0000, 0x0000, 0x0303, 0x0307, 0x038E, 0x01DC, 0x00F8, 0x0070, 0x0038, 0x001C, 0x000E, 0x0006,
8, 0, 0, 0,0x0000, 0x0000, 0x00FF, 0x00FF, 0x0070, 0x0038, 0x001C, 0x000E, 0x00FF, 0x00FF, 0x0000, 0x0000,
6, 0, 0, 0,0x0038, 0x003C, 0x000C, 0x000C, 0x000F, 0x000F, 0x000C, 0x000C, 0x003C, 0x0038, 0x0000, 0x0000,
2, 0, 0, 0,0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0000,
6, 0, 0, 0,0x0007, 0x000F, 0x000C, 0x000C, 0x003C, 0x003C, 0x000C, 0x000C, 0x000F, 0x0007, 0x0000, 0x0000,
10, 0, 0, 0,0x0000, 0x0000, 0x0000, 0x031C, 0x03BE, 0x01F7, 0x00E3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
11, 0, 0, 0,0x0555, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0401, 0x0000, 0x0555, 0x0000,
};
#endif

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 {
@ -509,7 +516,7 @@ _UI_EXTERN void uiDrawSave(uiDrawContext *c);
_UI_EXTERN void uiDrawRestore(uiDrawContext *c);
// bitmap API
_UI_EXTERN uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height);
_UI_EXTERN uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha);
_UI_EXTERN void uiDrawBitmapUpdate(uiDrawBitmap* bmp, const void* data);
_UI_EXTERN void uiDrawBitmapDraw(uiDrawContext* c, uiDrawBitmap* bmp, uiRect* srcrect, uiRect* dstrect, int filter);
_UI_EXTERN void uiDrawFreeBitmap(uiDrawBitmap* bmp);
@ -599,6 +606,22 @@ _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 void uiGLBegin(uiGLContext* ctx);
_UI_EXTERN void uiGLEnd(uiGLContext* ctx);
_UI_EXTERN unsigned int uiGLGetVersion(uiGLContext* ctx);
_UI_EXTERN void *uiGLGetProcAddress(const char* proc);
_UI_EXTERN int uiGLGetFramebuffer(uiGLContext* ctx);
_UI_EXTERN float uiGLGetFramebufferScale(uiGLContext* ctx);
_UI_EXTERN void uiGLSwapBuffers(uiGLContext* ctx);
_UI_ENUM(uiModifiers) {
uiModifierCtrl = 1 << 0,
uiModifierAlt = 1 << 1,

View File

@ -43,6 +43,7 @@ list(APPEND _LIBUI_SOURCES
unix/text.c
unix/util.c
unix/window.c
unix/gl.c
)
set(_LIBUI_SOURCES ${_LIBUI_SOURCES} PARENT_SCOPE)
@ -62,6 +63,7 @@ macro(_handle_static)
set(_oname libui-combined.o)
add_custom_command(
OUTPUT ${_oname}
DEPENDS ${_LIBUINAME}
COMMAND
ld -r --whole-archive ${_aname} -o ${_oname}
COMMAND

View File

@ -28,6 +28,8 @@ struct areaWidgetClass {
GtkDrawingAreaClass parent_class;
};
typedef struct uiGLContext uiGLContext;
struct uiArea {
uiUnixControl c;
GtkWidget *widget; // either swidget or areaWidget depending on whether it is scrolling
@ -39,6 +41,10 @@ struct uiArea {
GtkWidget *areaWidget;
GtkDrawingArea *drawingArea;
areaWidget *area;
gboolean opengl;
uiGLContext *glContext;
unsigned int* req_versions;
int bgR, bgG, bgB;
@ -57,6 +63,21 @@ struct uiArea {
G_DEFINE_TYPE(areaWidget, areaWidget, GTK_TYPE_DRAWING_AREA)
int boub(GtkWidget* w) { return isAreaWidget(w); }
void baba(GtkWidget* w)
{
if (!isAreaWidget(w)) return;
areaWidget *aw = areaWidget(w);
uiArea *a = aw->a;
if (!a->opengl) return;
GdkGLContext* oldctx = gdk_gl_context_get_current();
uiGLMakeContextCurrent(a->glContext);
glFinish();
gdk_gl_context_make_current(oldctx);
}
static void areaWidget_init(areaWidget *aw)
{
// for events
@ -133,20 +154,27 @@ static gboolean areaWidget_draw(GtkWidget *w, cairo_t *cr)
loadAreaSize(a, &(dp.AreaWidth), &(dp.AreaHeight));
cairo_clip_extents(cr, &clipX0, &clipY0, &clipX1, &clipY1);
dp.ClipX = clipX0;
dp.ClipY = clipY0;
dp.ClipWidth = clipX1 - clipX0;
dp.ClipHeight = clipY1 - clipY0;
if (a->bgR != -1)
{
cairo_set_source_rgb(cr, a->bgR/255.0, a->bgG/255.0, a->bgB/255.0);
cairo_paint(cr);
}
if (!a->opengl)
{
cairo_clip_extents(cr, &clipX0, &clipY0, &clipX1, &clipY1);
dp.ClipX = clipX0;
dp.ClipY = clipY0;
dp.ClipWidth = clipX1 - clipX0;
dp.ClipHeight = clipY1 - clipY0;
if (a->bgR != -1)
{
cairo_set_source_rgb(cr, a->bgR/255.0, a->bgG/255.0, a->bgB/255.0);
cairo_paint(cr);
}
// no need to save or restore the graphics state to reset transformations; GTK+ does that for us
(*(a->ah->Draw))(a->ah, a, &dp);
// no need to save or restore the graphics state to reset transformations; GTK+ does that for us
(*(a->ah->Draw))(a->ah, a, &dp);
}
else
{
areaDrawGL(w, &dp, cr, a->glContext);
}
freeContext(dp.Context);
return FALSE;
@ -598,7 +626,15 @@ static void areaWidget_class_init(areaWidgetClass *class)
// control implementation
uiUnixControlAllDefaults(uiArea)
uiUnixControlAllDefaultsExceptDestroy(uiArea)
static void uiAreaDestroy(uiControl *c)
{
uiArea* a = uiArea(c);
if (a->opengl && a->glContext) freeGLContext(a->glContext);
g_object_unref(uiArea(c)->widget);
uiFreeControl(c);
}
void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b)
{
@ -716,6 +752,7 @@ uiArea *uiNewArea(uiAreaHandler *ah)
a->ah = ah;
a->scrolling = FALSE;
a->opengl = FALSE;
a->areaWidget = GTK_WIDGET(g_object_new(areaWidgetType,
"libui-area", a,
@ -730,6 +767,58 @@ uiArea *uiNewArea(uiAreaHandler *ah)
return a;
}
void _areaCreateGLContext(GtkWidget* widget, gpointer data)
{
uiArea* a = (uiArea*)data;
uiGLContext* ctx = NULL;
for (int i = 0; a->req_versions[i] && !ctx; i++)
{
int major = uiGLVerMajor(a->req_versions[i]);
int minor = uiGLVerMinor(a->req_versions[i]);
// we cannot support any version older than 3.2 via GDK
if ((major < 3) || (major == 3 && minor < 2))
break;
ctx = createGLContext(widget, major, minor);
}
a->glContext = ctx;
}
uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions)
{
uiArea *a;
uiUnixNewControl(uiArea, a);
a->ah = ah;
a->scrolling = FALSE;
a->opengl = TRUE;
a->glContext = NULL;
a->req_versions = req_versions;
a->areaWidget = GTK_WIDGET(g_object_new(areaWidgetType,
"libui-area", a,
NULL));
a->area = areaWidget(a->areaWidget);
a->widget = a->areaWidget;
g_signal_connect(a->widget, "realize", G_CALLBACK(_areaCreateGLContext), a);
uiAreaSetBackgroundColor(a, -1, -1, -1);
return a;
}
uiGLContext *uiAreaGetGLContext(uiArea* a)
{
if (!a) return NULL;
return a->glContext;
}
uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
{
uiArea *a;
@ -740,6 +829,7 @@ uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
a->scrolling = TRUE;
a->scrollWidth = width;
a->scrollHeight = height;
a->opengl = FALSE;
a->swidget = gtk_scrolled_window_new(NULL, NULL);
a->scontainer = GTK_CONTAINER(a->swidget);

View File

@ -143,13 +143,13 @@ void uiDrawRestore(uiDrawContext *c)
// bitmap API
uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height)
uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha)
{
uiDrawBitmap* bmp;
bmp = uiNew(uiDrawBitmap);
bmp->bmp = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
bmp->bmp = cairo_image_surface_create(alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, width, height);
if (cairo_surface_status(bmp->bmp) != CAIRO_STATUS_SUCCESS)
implbug("error creating bitmap: %s",
cairo_status_to_string(cairo_surface_status(bmp->bmp)));

View File

@ -0,0 +1,246 @@
// 26 may 2019
#include "uipriv_unix.h"
#include <GL/gl.h>
#include <GL/glx.h>
#include <EGL/egl.h>
extern GThread* gtkthread;
extern GMutex glmutex;
struct uiGLContext
{
GtkWidget* widget;
GdkWindow* window;
GdkGLContext *gctx;
int vermaj, vermin;
int width, height;
int scale;
GLuint renderbuffer[2][2];
GLuint framebuffer[2];
int backbuffer;
};
static void areaAllocRenderbuffer(uiGLContext* glctx);
static PFNGLGENRENDERBUFFERSPROC _glGenRenderbuffers;
static PFNGLDELETERENDERBUFFERSPROC _glDeleteRenderbuffers;
static PFNGLBINDRENDERBUFFERPROC _glBindRenderbuffer;
static PFNGLRENDERBUFFERSTORAGEPROC _glRenderbufferStorage;
static PFNGLGETRENDERBUFFERPARAMETERIVPROC _glGetRenderbufferParameteriv;
static PFNGLGENRENDERBUFFERSPROC _glGenFramebuffers;
static PFNGLDELETERENDERBUFFERSPROC _glDeleteFramebuffers;
static PFNGLBINDRENDERBUFFERPROC _glBindFramebuffer;
static PFNGLFRAMEBUFFERTEXTUREPROC _glFramebufferTexture;
static PFNGLFRAMEBUFFERRENDERBUFFERPROC _glFramebufferRenderbuffer;
static PFNGLCHECKFRAMEBUFFERSTATUSPROC _glCheckFramebufferStatus;
static int _procsLoaded = 0;
static void _loadGLProcs(GdkGLContext* glctx)
{
if (_procsLoaded) return;
_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)uiGLGetProcAddress("glGenRenderbuffers");
_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)uiGLGetProcAddress("glDeleteRenderbuffers");
_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)uiGLGetProcAddress("glBindRenderbuffer");
_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)uiGLGetProcAddress("glRenderbufferStorage");
_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)uiGLGetProcAddress("glGetRenderbufferParameteriv");
_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)uiGLGetProcAddress("glGenFramebuffers");
_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)uiGLGetProcAddress("glDeleteFramebuffers");
_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)uiGLGetProcAddress("glBindFramebuffer");
_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)uiGLGetProcAddress("glFramebufferTexture");
_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)uiGLGetProcAddress("glFramebufferRenderbuffer");
_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)uiGLGetProcAddress("glCheckFramebufferStatus");
_procsLoaded = 1;
}
uiGLContext *createGLContext(GtkWidget* widget, int maj, int min)
{
GdkWindow* gdkwin = gtk_widget_get_window(widget);
GError* err = NULL;
GdkGLContext* gctx = gdk_window_create_gl_context(gdkwin, &err);
if (err != NULL || gctx == NULL)
{
return NULL;
}
// TODO: make the set_use_es call conditional (#ifdef or smth) for older versions of gdk?
gdk_gl_context_set_use_es(gctx, FALSE);
gdk_gl_context_set_required_version(gctx, maj, min);
gboolean res = gdk_gl_context_realize(gctx, &err);
if (err != NULL || res == FALSE)
{
return NULL;
}
uiGLContext* ctx = uiNew(uiGLContext);
GtkAllocation allocation;
gtk_widget_get_allocation(widget, &allocation);
int window_scale = gdk_window_get_scale_factor(gdkwin);
ctx->width = allocation.width;
ctx->height = allocation.height;
ctx->scale = window_scale;
gdk_gl_context_make_current(gctx);
_loadGLProcs(gctx);
areaAllocRenderbuffer(ctx);
ctx->backbuffer = 0;
ctx->widget = widget;
ctx->window = gdkwin;
ctx->gctx = gctx;
return ctx;
}
void freeGLContext(uiGLContext* glctx)
{
if (glctx == NULL) return;
gdk_gl_context_make_current(glctx->gctx);
_glDeleteRenderbuffers(4, &glctx->renderbuffer[0][0]);
_glDeleteFramebuffers(2, &glctx->framebuffer[0]);
gdk_gl_context_clear_current();
g_object_unref(glctx->gctx);
uiFree(glctx);
}
static void areaAllocRenderbuffer(uiGLContext* glctx)
{
// TODO: create textures as a fallback if GL_RGB renderbuffer isn't supported?
// they say GL implementations aren't required to support a GL_RGB renderbuffer
// however, a GL_RGBA one would cause gdk_cairo_draw_from_gl() to fall back to glReadPixels()
_glGenRenderbuffers(4, &glctx->renderbuffer[0][0]);
_glGenFramebuffers(2, &glctx->framebuffer[0]);
_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][0]);
_glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
//_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][1]);
//_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
_glBindFramebuffer(GL_FRAMEBUFFER, glctx->framebuffer[0]);
_glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, glctx->renderbuffer[0][0]);
_glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, glctx->renderbuffer[0][1]);
_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][0]);
_glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
//_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][1]);
//_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
_glBindFramebuffer(GL_FRAMEBUFFER, glctx->framebuffer[1]);
_glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, glctx->renderbuffer[1][0]);
_glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, glctx->renderbuffer[1][1]);
//if (_glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
// printf("FRAMEBUFFER IS BAD!! %04X\n", _glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
static void areaReallocRenderbuffer(uiGLContext* glctx)
{
_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][0]);
_glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
//_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[0][1]);
//_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][0]);
_glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, glctx->width*glctx->scale, glctx->height*glctx->scale);
//_glBindRenderbuffer(GL_RENDERBUFFER, glctx->renderbuffer[1][1]);
//_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, glctx->width*glctx->scale, glctx->height*glctx->scale);
}
void areaDrawGL(GtkWidget* widget, uiAreaDrawParams* dp, cairo_t* cr, uiGLContext* glctx)
{
int window_scale = gdk_window_get_scale_factor(glctx->window);
if (glctx->width != dp->AreaWidth || glctx->height != dp->AreaHeight || glctx->scale != window_scale)
{
glctx->width = dp->AreaWidth;
glctx->height = dp->AreaHeight;
glctx->scale = window_scale;
areaReallocRenderbuffer(glctx);
}
else
{
gdk_cairo_draw_from_gl(cr, gtk_widget_get_window(widget),
glctx->renderbuffer[glctx->backbuffer][0], GL_RENDERBUFFER,
1, 0, 0, glctx->width*glctx->scale, glctx->height*glctx->scale);
}
}
int uiGLGetFramebuffer(uiGLContext* ctx)
{
return ctx->framebuffer[ctx->backbuffer];
}
float uiGLGetFramebufferScale(uiGLContext* ctx)
{
return (float)ctx->scale;
}
void uiGLSwapBuffers(uiGLContext* ctx)
{
ctx->backbuffer = ctx->backbuffer ? 0 : 1;
}
void uiGLMakeContextCurrent(uiGLContext* ctx)
{
if (!ctx)
{
gdk_gl_context_clear_current();
return;
}
if (ctx->gctx == gdk_gl_context_get_current()) return;
gdk_gl_context_make_current(ctx->gctx);
}
void uiGLBegin(uiGLContext* ctx)
{
if (g_thread_self() != gtkthread)
{
g_mutex_lock(&glmutex);
}
}
void uiGLEnd(uiGLContext* ctx)
{
if (g_thread_self() != gtkthread)
{
g_mutex_unlock(&glmutex);
}
}
void *uiGLGetProcAddress(const char* proc)
{
// TODO: consider using epoxy or something funny
void* ptr;
ptr = glXGetProcAddressARB((const GLubyte*)proc);
if (ptr) return ptr;
ptr = eglGetProcAddress(proc);
if (ptr) return ptr;
ptr = dlsym(NULL /* RTLD_DEFAULT */, proc);
if (ptr) return ptr;
return NULL;
}
unsigned int uiGLGetVersion(uiGLContext* ctx)
{
if (!ctx) return 0;
return uiGLVersion(ctx->vermaj, ctx->vermin);
}

View File

@ -5,6 +5,25 @@ uiInitOptions options;
// kind of a hack
GThread* gtkthread;
GMutex glmutex;
static void _eventfilter(GdkEvent* evt, gpointer data)
{
if (evt->type == GDK_EXPOSE)
{
g_mutex_lock(&glmutex);
gtk_main_do_event(evt);
g_mutex_unlock(&glmutex);
return;
}
gtk_main_do_event(evt);
}
static void _eventfilterdestroy(gpointer data)
{
printf("DELET\n");
}
const char *uiInit(uiInitOptions *o)
{
@ -21,6 +40,7 @@ const char *uiInit(uiInitOptions *o)
loadFutures();
gtkthread = g_thread_self();
g_mutex_init(&glmutex);
GList* iconlist = NULL;
iconlist = g_list_append(iconlist, gdk_pixbuf_new_from_resource("/org/kuriboland/melonDS/icon/melon_16x16.png", NULL));
@ -31,6 +51,10 @@ const char *uiInit(uiInitOptions *o)
gtk_window_set_default_icon_list(iconlist);
g_mutex_init(&glmutex);
gdk_event_handler_set(_eventfilter, NULL, _eventfilterdestroy);
return NULL;
}

View File

@ -5,7 +5,7 @@
#define GDK_VERSION_MAX_ALLOWED GDK_VERSION_3_10
#include <gtk/gtk.h>
#include <math.h>
#include <dlfcn.h> // see drawtext.c
#include <dlfcn.h> // see drawtext.c, gl.c
#include <langinfo.h>
#include <string.h>
#include <stdlib.h>
@ -63,3 +63,9 @@ extern GtkCellRenderer *newCellRendererButton(void);
extern void loadFutures(void);
extern PangoAttribute *FUTURE_pango_attr_foreground_alpha_new(guint16 alpha);
extern gboolean FUTURE_gtk_widget_path_iter_set_object_name(GtkWidgetPath *path, gint pos, const char *name);
// gl.c
extern uiGLContext *createGLContext(GtkWidget* widget, int maj, int min);
extern void freeGLContext(uiGLContext* glctx);
extern void areaDrawGL(GtkWidget* widget, uiAreaDrawParams* dp, cairo_t* cr, uiGLContext* glctx);

View File

@ -102,6 +102,23 @@ static void uiWindowDestroy(uiControl *c)
uiFreeControl(uiControl(w));
}
void uiWindowSetPosition(uiWindow *w, int x, int y)
{
if (!w) return;
gtk_window_move(w->window, x, y);
}
void uiWindowPosition(uiWindow *w, int *x, int *y)
{
if (!w) return;
int xx, yy;
gtk_window_get_position(w->window, &xx, &yy);
if (x) *x = xx;
if (y) *y = yy;
}
uiUnixControlDefaultHandle(uiWindow)
uiControl *uiWindowParent(uiControl *c)
@ -442,3 +459,4 @@ uiWindow *uiNewWindow(const char *title, int width, int height, int maximized, i
return w;
}

View File

@ -29,6 +29,7 @@ list(APPEND _LIBUI_SOURCES
windows/fontbutton.cpp
windows/fontdialog.cpp
windows/form.cpp
windows/gl.cpp
windows/graphemes.cpp
windows/grid.cpp
windows/group.cpp

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

@ -522,7 +522,7 @@ void uiDrawRestore(uiDrawContext *c)
// bitmap API
uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height)
uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha)
{
uiDrawBitmap* bmp;
HRESULT hr;
@ -532,7 +532,8 @@ uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height)
D2D1_BITMAP_PROPERTIES bp2 = D2D1::BitmapProperties();
bp2.dpiX = 0;
bp2.dpiY = 0;
bp2.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
bp2.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
alpha ? D2D1_ALPHA_MODE_PREMULTIPLIED : D2D1_ALPHA_MODE_IGNORE);
//c->rt->BeginDraw();

View File

@ -0,0 +1,161 @@
// 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 uiGLBegin(uiGLContext* ctx)
{
}
void uiGLEnd(uiGLContext* ctx)
{
}
void uiGLSwapBuffers(uiGLContext* ctx)
{
if (ctx == NULL) return;
SwapBuffers(ctx->dc);
}
int uiGLGetFramebuffer(uiGLContext* ctx)
{
return 0;
}
float uiGLGetFramebufferScale(uiGLContext* ctx)
{
// TODO
return 1;
}

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,250 @@
/*
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 * 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);
}
)";
const char* kScreenVS_OSD = R"(#version 140
layout(std140) uniform uConfig
{
vec2 uScreenSize;
uint u3DScale;
uint uFilterMode;
};
uniform ivec2 uOSDPos;
uniform ivec2 uOSDSize;
in vec2 vPosition;
smooth out vec2 fTexcoord;
void main()
{
vec4 fpos;
vec2 osdpos = (vPosition * vec2(uOSDSize));
fTexcoord = osdpos;
osdpos += uOSDPos;
fpos.xy = ((osdpos * 2.0) / uScreenSize) - 1.0;
fpos.y *= -1;
fpos.z = 0.0;
fpos.w = 1.0;
gl_Position = fpos;
}
)";
const char* kScreenFS_OSD = R"(#version 140
uniform sampler2D OSDTex;
smooth in vec2 fTexcoord;
out vec4 oColor;
void main()
{
vec4 pixel = texelFetch(OSDTex, ivec2(fTexcoord), 0);
oColor = pixel.bgra;
}
)";
#endif // MAIN_SHADERS_H

View File

@ -19,7 +19,7 @@
#ifndef VERSION_H
#define VERSION_H
#define MELONDS_VERSION "0.7.4"
#define MELONDS_VERSION "0.8"
#define MELONDS_URL "http://melonds.kuribo64.net/"