mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 21:37:42 -07:00
Merge branch 'master' into fast-forward-hotkey
This commit is contained in:
commit
97f4b5f70b
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ obj
|
||||
*.o
|
||||
melon_grc.c
|
||||
melon_grc.h
|
||||
cmake-build
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
8
melon.rc
8
melon.rc
@ -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"
|
||||
|
79
melonDS.cbp
79
melonDS.cbp
@ -19,22 +19,6 @@
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add library="SDL2" />
|
||||
<Add library="shell32" />
|
||||
<Add library="comctl32" />
|
||||
<Add library="comdlg32" />
|
||||
<Add library="advapi32" />
|
||||
<Add library="wsock32" />
|
||||
<Add library="oleacc" />
|
||||
<Add library="ole32" />
|
||||
<Add library="usp10" />
|
||||
<Add library="gdi32" />
|
||||
<Add library="d2d1" />
|
||||
<Add library="dwrite" />
|
||||
<Add library="uxtheme" />
|
||||
<Add library="iphlpapi" />
|
||||
<Add library="user32" />
|
||||
<Add library="ws2_32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release Windows">
|
||||
@ -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" />
|
||||
|
14
src/ARM.cpp
14
src/ARM.cpp
@ -159,7 +159,7 @@ void ARM::SetupCodeMem(u32 addr)
|
||||
//NDS::ARM7GetMemRegion(addr, false, &CodeMem);
|
||||
}
|
||||
}
|
||||
|
||||
extern u64 vbltime;
|
||||
void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
||||
{
|
||||
if (restorecpsr)
|
||||
@ -180,6 +180,16 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
||||
if (R[15]==0x0204BE5E) printf("recvfrom() ret:%d errno:%d %08X\n", R[0], NDS::ARM9Read32(0x217F398), addr);
|
||||
if (R[15]==0x0205038A) printf("sgrecvfrom() ret:%d errno:%d %08X\n", R[0], NDS::ARM9Read32(0x217F398), addr);
|
||||
if (addr==0x02050379 || addr==0x0205036D) printf("morp %08X->%08X, %d\n", R[15], addr, R[7]);*/
|
||||
/*if (addr==0x020B5F14) printf("VRAM UNMAP %02X %08X\n", R[0], R[15]);
|
||||
if (addr==0x020B5FAC) printf("VRAM MAP %2X %08X\n", R[0], R[15]);
|
||||
if (addr==0x0209F860) printf("VRAM BLORP %02X %08X\n", R[0], R[15]);
|
||||
if (addr==0x02005A34) printf("VAZAVAZORP %08X. VCOUNT=%d\n", R[15], NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x0209FBEC) printf("COUILLON. %08X %08X\n", R[0], R[1]);
|
||||
if (addr==0x02004AA8) printf("ANEBATE 1 %d\n", NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x020058C8) printf("ANEBATE 2 %d\n", NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x02005398) printf("ANEBATE 3 %d %d\n", NDS::ARM9Read16(0x04000006), (u32)(NDS::ARM9Timestamp-vbltime));
|
||||
if (addr==0x02005A5C) printf("PLAFORP %d\n", NDS::ARM9Read16(0x04000006));
|
||||
if (addr==0x209FBDC) printf("ROLOLORP\n");*/
|
||||
|
||||
u32 oldregion = R[15] >> 24;
|
||||
u32 newregion = addr >> 24;
|
||||
@ -508,6 +518,8 @@ void ARMv5::Execute()
|
||||
}
|
||||
else
|
||||
AddCycles_C();
|
||||
|
||||
//if (R[15]>=0x02005A5C && R[15]<=0x02005A84) printf("NORP %08X %d\n", R[15]-8, NDS::ARM9Read16(0x04000006));
|
||||
}
|
||||
|
||||
// TODO optimize this shit!!!
|
||||
|
@ -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()
|
||||
|
@ -28,12 +28,20 @@ namespace Config
|
||||
|
||||
const char* kConfigFile = "melonDS.ini";
|
||||
|
||||
int _3DRenderer;
|
||||
int Threaded3D;
|
||||
|
||||
int GL_ScaleFactor;
|
||||
int GL_Antialias;
|
||||
|
||||
ConfigEntry ConfigFile[] =
|
||||
{
|
||||
{"3DRenderer", 0, &_3DRenderer, 1, NULL, 0},
|
||||
{"Threaded3D", 0, &Threaded3D, 1, NULL, 0},
|
||||
|
||||
{"GL_ScaleFactor", 0, &GL_ScaleFactor, 1, NULL, 0},
|
||||
{"GL_Antialias", 0, &GL_Antialias, 0, NULL, 0},
|
||||
|
||||
{"", -1, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -40,8 +40,12 @@ bool HasConfigFile(const char* fileName);
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
extern int _3DRenderer;
|
||||
extern int Threaded3D;
|
||||
|
||||
extern int GL_ScaleFactor;
|
||||
extern int GL_Antialias;
|
||||
|
||||
}
|
||||
|
||||
#endif // CONFIG_H
|
||||
|
101
src/GPU.cpp
101
src/GPU.cpp
@ -20,7 +20,7 @@
|
||||
#include <string.h>
|
||||
#include "NDS.h"
|
||||
#include "GPU.h"
|
||||
|
||||
u64 vbltime;
|
||||
|
||||
namespace GPU
|
||||
{
|
||||
@ -71,7 +71,9 @@ u32 VRAMMap_TexPal[8];
|
||||
|
||||
u32 VRAMMap_ARM7[2];
|
||||
|
||||
u32 Framebuffer[256*192*2];
|
||||
int FrontBuffer;
|
||||
u32* Framebuffer[2][2];
|
||||
bool Accelerated;
|
||||
|
||||
GPU2D* GPU2D_A;
|
||||
GPU2D* GPU2D_B;
|
||||
@ -83,6 +85,12 @@ bool Init()
|
||||
GPU2D_B = new GPU2D(1);
|
||||
if (!GPU3D::Init()) return false;
|
||||
|
||||
FrontBuffer = 0;
|
||||
Framebuffer[0][0] = NULL; Framebuffer[0][1] = NULL;
|
||||
Framebuffer[1][0] = NULL; Framebuffer[1][1] = NULL;
|
||||
Accelerated = false;
|
||||
SetDisplaySettings(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -91,6 +99,11 @@ void DeInit()
|
||||
delete GPU2D_A;
|
||||
delete GPU2D_B;
|
||||
GPU3D::DeInit();
|
||||
|
||||
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
|
||||
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
||||
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
||||
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
|
||||
}
|
||||
|
||||
void Reset()
|
||||
@ -137,23 +150,39 @@ void Reset()
|
||||
|
||||
VRAMMap_ARM7[0] = 0;
|
||||
VRAMMap_ARM7[1] = 0;
|
||||
|
||||
for (int i = 0; i < 256*192*2; i++)
|
||||
printf("RESET: ACCEL=%d FRAMEBUFFER=%p\n", Accelerated, Framebuffer[0][0]);
|
||||
int fbsize;
|
||||
if (Accelerated) fbsize = (256*3 + 1) * 192;
|
||||
else fbsize = 256 * 192;
|
||||
for (int i = 0; i < fbsize; i++)
|
||||
{
|
||||
Framebuffer[i] = 0xFFFFFFFF;
|
||||
Framebuffer[0][0][i] = 0xFFFFFFFF;
|
||||
Framebuffer[1][0][i] = 0xFFFFFFFF;
|
||||
}
|
||||
for (int i = 0; i < fbsize; i++)
|
||||
{
|
||||
Framebuffer[0][1][i] = 0xFFFFFFFF;
|
||||
Framebuffer[1][1][i] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
GPU2D_A->Reset();
|
||||
GPU2D_B->Reset();
|
||||
GPU3D::Reset();
|
||||
|
||||
GPU2D_A->SetFramebuffer(&Framebuffer[256*192]);
|
||||
GPU2D_B->SetFramebuffer(&Framebuffer[256*0]);
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
|
||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
memset(Framebuffer, 0, 256*192*2*4);
|
||||
int fbsize;
|
||||
if (Accelerated) fbsize = (256*3 + 1) * 192;
|
||||
else fbsize = 256 * 192;
|
||||
memset(Framebuffer[0][0], 0, fbsize*4);
|
||||
memset(Framebuffer[0][1], 0, fbsize*4);
|
||||
memset(Framebuffer[1][0], 0, fbsize*4);
|
||||
memset(Framebuffer[1][1], 0, fbsize*4);
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
@ -208,6 +237,48 @@ void DoSavestate(Savestate* file)
|
||||
GPU3D::DoSavestate(file);
|
||||
}
|
||||
|
||||
void AssignFramebuffers()
|
||||
{
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
if (NDS::PowerControl9 & (1<<15))
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][0]);
|
||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(Framebuffer[backbuf][1]);
|
||||
GPU2D_B->SetFramebuffer(Framebuffer[backbuf][0]);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDisplaySettings(bool accel)
|
||||
{
|
||||
int fbsize;
|
||||
if (accel) fbsize = (256*3 + 1) * 192;
|
||||
else fbsize = 256 * 192;
|
||||
if (Framebuffer[0][0]) delete[] Framebuffer[0][0];
|
||||
if (Framebuffer[1][0]) delete[] Framebuffer[1][0];
|
||||
if (Framebuffer[0][1]) delete[] Framebuffer[0][1];
|
||||
if (Framebuffer[1][1]) delete[] Framebuffer[1][1];
|
||||
Framebuffer[0][0] = new u32[fbsize];
|
||||
Framebuffer[1][0] = new u32[fbsize];
|
||||
Framebuffer[0][1] = new u32[fbsize];
|
||||
Framebuffer[1][1] = new u32[fbsize];
|
||||
|
||||
memset(Framebuffer[0][0], 0, fbsize*4);
|
||||
memset(Framebuffer[1][0], 0, fbsize*4);
|
||||
memset(Framebuffer[0][1], 0, fbsize*4);
|
||||
memset(Framebuffer[1][1], 0, fbsize*4);
|
||||
|
||||
AssignFramebuffers();
|
||||
|
||||
GPU2D_A->SetDisplaySettings(accel);
|
||||
GPU2D_B->SetDisplaySettings(accel);
|
||||
|
||||
Accelerated = accel;
|
||||
}
|
||||
|
||||
|
||||
// VRAM mapping notes
|
||||
//
|
||||
@ -666,16 +737,7 @@ void SetPowerCnt(u32 val)
|
||||
GPU2D_B->SetEnabled(val & (1<<9));
|
||||
GPU3D::SetEnabled(val & (1<<3), val & (1<<2));
|
||||
|
||||
if (val & (1<<15))
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(&Framebuffer[256*0]);
|
||||
GPU2D_B->SetFramebuffer(&Framebuffer[256*192]);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPU2D_A->SetFramebuffer(&Framebuffer[256*192]);
|
||||
GPU2D_B->SetFramebuffer(&Framebuffer[256*0]);
|
||||
}
|
||||
AssignFramebuffers();
|
||||
}
|
||||
|
||||
|
||||
@ -746,6 +808,9 @@ void StartHBlank(u32 line)
|
||||
|
||||
void FinishFrame(u32 lines)
|
||||
{
|
||||
FrontBuffer = FrontBuffer ? 0 : 1;
|
||||
AssignFramebuffers();
|
||||
|
||||
TotalScanlines = lines;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,8 @@ extern u32 VRAMMap_Texture[4];
|
||||
extern u32 VRAMMap_TexPal[8];
|
||||
extern u32 VRAMMap_ARM7[2];
|
||||
|
||||
extern u32 Framebuffer[256*192*2];
|
||||
extern int FrontBuffer;
|
||||
extern u32* Framebuffer[2][2];
|
||||
|
||||
extern GPU2D* GPU2D_A;
|
||||
extern GPU2D* GPU2D_B;
|
||||
@ -74,6 +75,8 @@ void Stop();
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
|
||||
void SetDisplaySettings(bool accel);
|
||||
|
||||
|
||||
void MapVRAM_AB(u32 bank, u8 cnt);
|
||||
void MapVRAM_CD(u32 bank, u8 cnt);
|
||||
|
740
src/GPU2D.cpp
740
src/GPU2D.cpp
File diff suppressed because it is too large
Load Diff
49
src/GPU2D.h
49
src/GPU2D.h
@ -31,6 +31,7 @@ public:
|
||||
|
||||
void SetEnabled(bool enable) { Enabled = enable; }
|
||||
void SetFramebuffer(u32* buf);
|
||||
void SetDisplaySettings(bool accel);
|
||||
|
||||
u8 Read8(u32 addr);
|
||||
u16 Read16(u32 addr);
|
||||
@ -68,6 +69,14 @@ private:
|
||||
bool Enabled;
|
||||
u32* Framebuffer;
|
||||
|
||||
bool Accelerated;
|
||||
|
||||
u32 BGOBJLine[256*3] __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
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "NDS.h"
|
||||
#include "GPU.h"
|
||||
#include "FIFO.h"
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
// 3D engine notes
|
||||
@ -156,6 +157,8 @@ u32 NumCommands, CurCommand, ParamCount, TotalParams;
|
||||
bool GeometryEnabled;
|
||||
bool RenderingEnabled;
|
||||
|
||||
int Renderer;
|
||||
|
||||
u32 DispCnt;
|
||||
u8 AlphaRefVal, AlphaRef;
|
||||
|
||||
@ -275,14 +278,16 @@ bool Init()
|
||||
|
||||
CmdStallQueue = new FIFO<CmdFIFOEntry>(64);
|
||||
|
||||
if (!SoftRenderer::Init()) return false;
|
||||
Renderer = -1;
|
||||
// SetRenderer() will be called to set it up later
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
SoftRenderer::DeInit();
|
||||
if (Renderer == 0) SoftRenderer::DeInit();
|
||||
else GLRenderer::DeInit();
|
||||
|
||||
delete CmdFIFO;
|
||||
delete CmdPIPE;
|
||||
@ -382,7 +387,8 @@ void Reset()
|
||||
FlushAttributes = 0;
|
||||
|
||||
ResetRenderingState();
|
||||
SoftRenderer::Reset();
|
||||
if (Renderer == 0) SoftRenderer::Reset();
|
||||
else GLRenderer::Reset();
|
||||
}
|
||||
|
||||
void DoSavestate(Savestate* file)
|
||||
@ -605,6 +611,43 @@ void SetEnabled(bool geometry, bool rendering)
|
||||
}
|
||||
|
||||
|
||||
int InitRenderer(bool hasGL)
|
||||
{
|
||||
int renderer = hasGL ? Config::_3DRenderer : 0;
|
||||
|
||||
if (renderer == 1)
|
||||
{
|
||||
if (!GLRenderer::Init())
|
||||
renderer = 0;
|
||||
}
|
||||
|
||||
if (renderer == 0) SoftRenderer::Init();
|
||||
|
||||
Renderer = renderer;
|
||||
UpdateRendererConfig();
|
||||
GPU::SetDisplaySettings(Renderer != 0);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void DeInitRenderer()
|
||||
{
|
||||
if (Renderer == 0) SoftRenderer::DeInit();
|
||||
else GLRenderer::DeInit();
|
||||
}
|
||||
|
||||
void UpdateRendererConfig()
|
||||
{
|
||||
if (Renderer == 0)
|
||||
{
|
||||
SoftRenderer::SetupRenderThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
GLRenderer::UpdateDisplaySettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MatrixLoadIdentity(s32* m)
|
||||
{
|
||||
@ -1191,6 +1234,16 @@ void SubmitPolygon()
|
||||
vtx->FinalPosition[0] = posX & 0x1FF;
|
||||
vtx->FinalPosition[1] = posY & 0xFF;
|
||||
|
||||
// hi-res positions
|
||||
if (w != 0)
|
||||
{
|
||||
posX = ((((s64)(vtx->Position[0] + w) * Viewport[4]) << 4) / (((s64)w) << 1)) + (Viewport[0] << 4);
|
||||
posY = ((((s64)(-vtx->Position[1] + w) * Viewport[5]) << 4) / (((s64)w) << 1)) + (Viewport[3] << 4);
|
||||
|
||||
vtx->HiresPosition[0] = posX & 0x1FFF;
|
||||
vtx->HiresPosition[1] = posY & 0xFFF;
|
||||
}
|
||||
|
||||
vtx->FinalColor[0] = vtx->Color[0] >> 12;
|
||||
if (vtx->FinalColor[0]) vtx->FinalColor[0] = ((vtx->FinalColor[0] << 4) + 0xF);
|
||||
vtx->FinalColor[1] = vtx->Color[1] >> 12;
|
||||
@ -2331,7 +2384,7 @@ void CheckFIFODMA()
|
||||
|
||||
void VCount144()
|
||||
{
|
||||
SoftRenderer::VCount144();
|
||||
if (Renderer == 0) SoftRenderer::VCount144();
|
||||
}
|
||||
|
||||
|
||||
@ -2413,17 +2466,14 @@ void VBlank()
|
||||
|
||||
void VCount215()
|
||||
{
|
||||
SoftRenderer::RenderFrame();
|
||||
}
|
||||
|
||||
void RequestLine(int line)
|
||||
{
|
||||
return SoftRenderer::RequestLine(line);
|
||||
if (Renderer == 0) SoftRenderer::RenderFrame();
|
||||
else GLRenderer::RenderFrame();
|
||||
}
|
||||
|
||||
u32* GetLine(int line)
|
||||
{
|
||||
return SoftRenderer::GetLine(line);
|
||||
if (Renderer == 0) return SoftRenderer::GetLine(line);
|
||||
else return GLRenderer::GetLine(line);
|
||||
}
|
||||
|
||||
|
||||
|
28
src/GPU3D.h
28
src/GPU3D.h
@ -39,6 +39,10 @@ typedef struct
|
||||
s32 FinalPosition[2];
|
||||
s32 FinalColor[3];
|
||||
|
||||
// hi-res position (4-bit fractional part)
|
||||
// TODO maybe: hi-res color? (that survives clipping)
|
||||
s32 HiresPosition[2];
|
||||
|
||||
} Vertex;
|
||||
|
||||
typedef struct
|
||||
@ -86,6 +90,8 @@ extern u32 RenderNumPolygons;
|
||||
|
||||
extern u64 Timestamp;
|
||||
|
||||
extern int Renderer;
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
@ -94,6 +100,10 @@ void DoSavestate(Savestate* file);
|
||||
|
||||
void SetEnabled(bool geometry, bool rendering);
|
||||
|
||||
int InitRenderer(bool hasGL);
|
||||
void DeInitRenderer();
|
||||
void UpdateRendererConfig();
|
||||
|
||||
void ExecuteCommand();
|
||||
|
||||
s32 CyclesToRunFor();
|
||||
@ -104,7 +114,6 @@ void CheckFIFODMA();
|
||||
void VCount144();
|
||||
void VBlank();
|
||||
void VCount215();
|
||||
void RequestLine(int line);
|
||||
u32* GetLine(int line);
|
||||
|
||||
void WriteToGXFIFO(u32 val);
|
||||
@ -127,11 +136,26 @@ void SetupRenderThread();
|
||||
|
||||
void VCount144();
|
||||
void RenderFrame();
|
||||
void RequestLine(int line);
|
||||
u32* GetLine(int line);
|
||||
|
||||
}
|
||||
|
||||
namespace GLRenderer
|
||||
{
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
|
||||
void UpdateDisplaySettings();
|
||||
|
||||
void RenderFrame();
|
||||
void PrepareCaptureFrame();
|
||||
u32* GetLine(int line);
|
||||
void SetupAccelFrame();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
1127
src/GPU3D_OpenGL.cpp
Normal file
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
695
src/GPU3D_OpenGL_shaders.h
Normal 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
|
@ -129,9 +129,9 @@ void DeInit()
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(ColorBuffer, 0, 256*192 * 4);
|
||||
memset(DepthBuffer, 0, 256*192 * 4);
|
||||
memset(AttrBuffer, 0, 256*192 * 4);
|
||||
memset(ColorBuffer, 0, BufferSize * 2 * 4);
|
||||
memset(DepthBuffer, 0, BufferSize * 2 * 4);
|
||||
memset(AttrBuffer, 0, BufferSize * 2 * 4);
|
||||
|
||||
PrevIsShadowMask = false;
|
||||
|
||||
@ -2106,17 +2106,14 @@ void RenderThreadFunc()
|
||||
}
|
||||
}
|
||||
|
||||
void RequestLine(int line)
|
||||
u32* GetLine(int line)
|
||||
{
|
||||
if (RenderThreadRunning)
|
||||
{
|
||||
if (line < 192)
|
||||
Platform::Semaphore_Wait(Sema_ScanlineCount);
|
||||
}
|
||||
}
|
||||
|
||||
u32* GetLine(int line)
|
||||
{
|
||||
return &ColorBuffer[(line * ScanlineWidth) + FirstPixelOffset];
|
||||
}
|
||||
|
||||
|
@ -1532,7 +1532,7 @@ void debug(u32 param)
|
||||
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
|
||||
|
||||
FILE*
|
||||
shit = fopen("debug/lmnts.bin", "wb");
|
||||
shit = fopen("debug/card.bin", "wb");
|
||||
for (u32 i = 0x02000000; i < 0x02400000; i+=4)
|
||||
{
|
||||
u32 val = ARM7Read32(i);
|
||||
|
128
src/OpenGLSupport.cpp
Normal file
128
src/OpenGLSupport.cpp
Normal 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
137
src/OpenGLSupport.h
Normal 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
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ namespace DlgAudioSettings
|
||||
{
|
||||
|
||||
void Open();
|
||||
void Close();
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ namespace DlgEmuSettings
|
||||
{
|
||||
|
||||
void Open();
|
||||
void Close();
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ namespace DlgInputConfig
|
||||
{
|
||||
|
||||
void Open(int type);
|
||||
void Close(int type);
|
||||
|
||||
}
|
||||
|
||||
|
324
src/libui_sdl/DlgVideoSettings.cpp
Normal file
324
src/libui_sdl/DlgVideoSettings.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
30
src/libui_sdl/DlgVideoSettings.h
Normal file
30
src/libui_sdl/DlgVideoSettings.h
Normal 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
|
@ -261,4 +261,11 @@ void Open()
|
||||
uiControlShow(uiControl(win));
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
if (!opened) return;
|
||||
uiControlDestroy(uiControl(win));
|
||||
opened = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ namespace DlgWifiSettings
|
||||
{
|
||||
|
||||
void Open();
|
||||
void Close();
|
||||
|
||||
}
|
||||
|
||||
|
423
src/libui_sdl/OSD.cpp
Normal file
423
src/libui_sdl/OSD.cpp
Normal 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
35
src/libui_sdl/OSD.h
Normal 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
|
@ -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;
|
||||
|
@ -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},
|
||||
|
@ -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
135
src/libui_sdl/font.h
Normal 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
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
|
246
src/libui_sdl/libui/unix/gl.c
Normal file
246
src/libui_sdl/libui/unix/gl.c
Normal 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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -25,8 +25,11 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
||||
}
|
||||
|
||||
// always recreate the render target if necessary
|
||||
if (a->rt == NULL)
|
||||
a->rt = makeHWNDRenderTarget(a->hwnd);
|
||||
if (!a->openGL)
|
||||
{
|
||||
if (a->rt == NULL)
|
||||
a->rt = makeHWNDRenderTarget(a->hwnd);
|
||||
}
|
||||
|
||||
if (areaDoDraw(a, uMsg, wParam, lParam, &lResult) != FALSE)
|
||||
return lResult;
|
||||
@ -34,12 +37,14 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
||||
if (uMsg == WM_WINDOWPOSCHANGED) {
|
||||
if ((wp->flags & SWP_NOSIZE) != 0)
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
uiWindowsEnsureGetClientRect(a->hwnd, &client);
|
||||
areaDrawOnResize(a, &client);
|
||||
areaScrollOnResize(a, &client);
|
||||
{
|
||||
double w, h;
|
||||
loadAreaSize(a, a->rt, &w, &h);
|
||||
loadAreaSize(a, &w, &h);
|
||||
a->ah->Resize(a->ah, a, (int)w, (int)h);
|
||||
}
|
||||
return 0;
|
||||
@ -56,7 +61,15 @@ static LRESULT CALLBACK areaWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
||||
|
||||
// control implementation
|
||||
|
||||
uiWindowsControlAllDefaults(uiArea)
|
||||
uiWindowsControlAllDefaultsExceptDestroy(uiArea)
|
||||
|
||||
static void uiAreaDestroy(uiControl *c)
|
||||
{
|
||||
uiArea* a = uiArea(c);
|
||||
if (a->openGL && a->glcontext) freeGLContext(a->glcontext);
|
||||
uiWindowsEnsureDestroyWindow(a->hwnd);
|
||||
uiFreeControl(c);
|
||||
}
|
||||
|
||||
static void uiAreaMinimumSize(uiWindowsControl *c, int *width, int *height)
|
||||
{
|
||||
@ -182,6 +195,9 @@ uiArea *uiNewArea(uiAreaHandler *ah)
|
||||
|
||||
uiWindowsNewControl(uiArea, a);
|
||||
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
|
||||
a->ah = ah;
|
||||
a->scrolling = FALSE;
|
||||
clickCounterReset(&(a->cc));
|
||||
@ -195,6 +211,50 @@ uiArea *uiNewArea(uiAreaHandler *ah)
|
||||
|
||||
uiAreaSetBackgroundColor(a, -1, -1, -1);
|
||||
|
||||
a->openGL = 0;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
uiGLContext *uiAreaGetGLContext(uiArea* a)
|
||||
{
|
||||
if (!a->openGL) userbug("trying to get GL context from non-GL area");
|
||||
|
||||
return a->glcontext;
|
||||
}
|
||||
|
||||
uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions)
|
||||
{
|
||||
uiArea *a;
|
||||
|
||||
uiWindowsNewControl(uiArea, a);
|
||||
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
|
||||
a->ah = ah;
|
||||
a->scrolling = FALSE;
|
||||
clickCounterReset(&(a->cc));
|
||||
|
||||
// a->hwnd is assigned in areaWndProc()
|
||||
uiWindowsEnsureCreateControlHWND(0,
|
||||
areaClass, L"",
|
||||
0,
|
||||
hInstance, a,
|
||||
FALSE);
|
||||
|
||||
uiAreaSetBackgroundColor(a, -1, -1, -1);
|
||||
|
||||
a->openGL = 1;
|
||||
|
||||
for (int i = 0; req_versions[i]; i++)
|
||||
{
|
||||
int major = uiGLVerMajor(req_versions[i]);
|
||||
int minor = uiGLVerMinor(req_versions[i]);
|
||||
a->glcontext = createGLContext(a, major, minor);
|
||||
if (a->glcontext) break;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
@ -204,6 +264,9 @@ uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
|
||||
|
||||
uiWindowsNewControl(uiArea, a);
|
||||
|
||||
a->width = -1;
|
||||
a->height = -1;
|
||||
|
||||
a->ah = ah;
|
||||
a->scrolling = TRUE;
|
||||
a->scrollWidth = width;
|
||||
@ -219,6 +282,8 @@ uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height)
|
||||
|
||||
uiAreaSetBackgroundColor(a, -1, -1, -1);
|
||||
|
||||
a->openGL = 0; // TODO, eventually???
|
||||
|
||||
// set initial scrolling parameters
|
||||
areaUpdateScroll(a);
|
||||
|
||||
|
@ -10,6 +10,8 @@ struct uiArea {
|
||||
HWND hwnd;
|
||||
uiAreaHandler *ah;
|
||||
|
||||
int width, height;
|
||||
|
||||
BOOL scrolling;
|
||||
int scrollWidth;
|
||||
int scrollHeight;
|
||||
@ -26,6 +28,9 @@ struct uiArea {
|
||||
|
||||
int bgR, bgG, bgB;
|
||||
|
||||
int openGL;
|
||||
uiGLContext* glcontext;
|
||||
|
||||
ID2D1HwndRenderTarget *rt;
|
||||
};
|
||||
|
||||
@ -42,6 +47,10 @@ extern void areaUpdateScroll(uiArea *a);
|
||||
extern BOOL areaDoEvents(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
|
||||
|
||||
// areautil.cpp
|
||||
extern void loadAreaSize(uiArea *a, ID2D1RenderTarget *rt, double *width, double *height);
|
||||
extern void loadAreaSize(uiArea *a, double *width, double *height);
|
||||
extern void pixelsToDIP(uiArea *a, double *x, double *y);
|
||||
extern void dipToPixels(uiArea *a, double *x, double *y);
|
||||
|
||||
// gl.cpp
|
||||
extern uiGLContext* createGLContext(uiArea* a, int vermajor, int verminor);
|
||||
extern void freeGLContext(uiGLContext* c);
|
||||
|
@ -6,6 +6,13 @@ static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip)
|
||||
{
|
||||
uiAreaHandler *ah = a->ah;
|
||||
uiAreaDrawParams dp;
|
||||
|
||||
if (a->openGL)
|
||||
{
|
||||
//(*(ah->Draw))(ah, a, &dp);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
COLORREF bgcolorref;
|
||||
D2D1_COLOR_F bgcolor;
|
||||
D2D1_MATRIX_3X2_F scrollTransform;
|
||||
@ -13,7 +20,7 @@ static HRESULT doPaint(uiArea *a, ID2D1RenderTarget *rt, RECT *clip)
|
||||
// no need to save or restore the graphics state to reset transformations; it's handled by resetTarget() in draw.c, called during the following
|
||||
dp.Context = newContext(rt);
|
||||
|
||||
loadAreaSize(a, rt, &(dp.AreaWidth), &(dp.AreaHeight));
|
||||
loadAreaSize(a, &(dp.AreaWidth), &(dp.AreaHeight));
|
||||
|
||||
dp.ClipX = clip->left;
|
||||
dp.ClipY = clip->top;
|
||||
@ -113,6 +120,9 @@ static void onWM_PAINT(uiArea *a)
|
||||
|
||||
static void onWM_PRINTCLIENT(uiArea *a, HDC dc)
|
||||
{
|
||||
// TODO????
|
||||
if (a->openGL) return;
|
||||
|
||||
ID2D1DCRenderTarget *rt;
|
||||
RECT client;
|
||||
HRESULT hr;
|
||||
@ -143,13 +153,16 @@ BOOL areaDoDraw(uiArea *a, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lRe
|
||||
// TODO only if the render target wasn't just created?
|
||||
void areaDrawOnResize(uiArea *a, RECT *newClient)
|
||||
{
|
||||
D2D1_SIZE_U size;
|
||||
if (!a->openGL)
|
||||
{
|
||||
D2D1_SIZE_U size;
|
||||
|
||||
size.width = newClient->right - newClient->left;
|
||||
size.height = newClient->bottom - newClient->top;
|
||||
// don't track the error; we'll get that in EndDraw()
|
||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx
|
||||
a->rt->Resize(&size);
|
||||
size.width = newClient->right - newClient->left;
|
||||
size.height = newClient->bottom - newClient->top;
|
||||
// don't track the error; we'll get that in EndDraw()
|
||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/dd370994%28v=vs.85%29.aspx
|
||||
a->rt->Resize(&size);
|
||||
}
|
||||
|
||||
// according to Rick Brewster, we must always redraw the entire client area after calling ID2D1RenderTarget::Resize() (see http://stackoverflow.com/a/33222983/3408572)
|
||||
// we used to have a uiAreaHandler.RedrawOnResize() method to decide this; now you know why we don't anymore
|
||||
|
@ -109,7 +109,7 @@ static void areaMouseEvent(uiArea *a, int down, int up, WPARAM wParam, LPARAM l
|
||||
me.Y += a->vscrollpos;
|
||||
}
|
||||
|
||||
loadAreaSize(a, NULL, &(me.AreaWidth), &(me.AreaHeight));
|
||||
loadAreaSize(a, &(me.AreaWidth), &(me.AreaHeight));
|
||||
|
||||
me.Down = down;
|
||||
me.Up = up;
|
||||
|
@ -2,20 +2,35 @@
|
||||
#include "uipriv_windows.hpp"
|
||||
#include "area.hpp"
|
||||
|
||||
void loadAreaSize(uiArea *a, ID2D1RenderTarget *rt, double *width, double *height)
|
||||
// TODO: make those int rather than double
|
||||
void loadAreaSize(uiArea *a, double *width, double *height)
|
||||
{
|
||||
D2D1_SIZE_F size;
|
||||
|
||||
if (a->width != -1)
|
||||
{
|
||||
*width = (double)a->width;
|
||||
*height = (double)a->height;
|
||||
return;
|
||||
}
|
||||
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
if (!a->scrolling) {
|
||||
if (rt == NULL)
|
||||
/*if (rt == NULL)
|
||||
rt = a->rt;
|
||||
size = realGetSize(rt);
|
||||
*width = size.width;
|
||||
*height = size.height;
|
||||
dipToPixels(a, width, height);
|
||||
dipToPixels(a, width, height);*/
|
||||
RECT rect;
|
||||
GetWindowRect(a->hwnd, &rect);
|
||||
*width = (double)(rect.right - rect.left);
|
||||
*height = (double)(rect.bottom - rect.top);
|
||||
}
|
||||
|
||||
a->width = (int)*width;
|
||||
a->height = (int)*height;
|
||||
}
|
||||
|
||||
void pixelsToDIP(uiArea *a, double *x, double *y)
|
||||
|
@ -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();
|
||||
|
||||
|
161
src/libui_sdl/libui/windows/gl.cpp
Normal file
161
src/libui_sdl/libui/windows/gl.cpp
Normal 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;
|
||||
}
|
@ -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
250
src/libui_sdl/main_shaders.h
Normal file
250
src/libui_sdl/main_shaders.h
Normal 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
|
@ -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/"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user