Initial Cross Platform Work
This commit is contained in:
18
backends/3ds/CMakeLists.txt
Normal file
18
backends/3ds/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
# Make sure to use 3ds toolschain for 3ds build :)
|
||||
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
if(DEFINED ENV{DEVKITPRO})
|
||||
set(CMAKE_TOOLCHAIN_FILE "$ENV{DEVKITPRO}/cmake/3DS.cmake" CACHE PATH "toolchain file")
|
||||
else()
|
||||
message(FATAL_ERROR "Please define DEVKITPRO to point to your SDK path!")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-psabi -O3")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions")
|
||||
|
||||
add_library(pd-backend-3ds STATIC
|
||||
source/li_backend_c3d.cpp
|
||||
source/pd_hid_3ds.cpp)
|
||||
target_include_directories(pd-backend-3ds PUBLIC include)
|
||||
target_link_libraries(pd-backend-3ds PUBLIC palladium)
|
83
backends/3ds/include/li_backend_c3d.hpp
Normal file
83
backends/3ds/include/li_backend_c3d.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 - 2025 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <3ds.h>
|
||||
#include <citro3d.h>
|
||||
|
||||
#include <pd/core/core.hpp>
|
||||
#include <pd/lithium/backend.hpp>
|
||||
|
||||
namespace PD {
|
||||
template <typename T>
|
||||
class LinearAlloc : public Allocator<T> {
|
||||
public:
|
||||
LinearAlloc() = default;
|
||||
~LinearAlloc() = default;
|
||||
|
||||
T* Allocate(size_t n) override { return (T*)linearAlloc(n); }
|
||||
void Deallocate(T* ptr) { linearFree(ptr); }
|
||||
};
|
||||
namespace LI {
|
||||
class Backend_C3D : public PD::LI::Backend {
|
||||
public:
|
||||
Backend_C3D() : LI::Backend("Citro3D") {}
|
||||
~Backend_C3D() {}
|
||||
PD_SMART_CTOR(Backend_C3D)
|
||||
|
||||
void Init() override;
|
||||
|
||||
void Deinit() override;
|
||||
|
||||
void NewFrame() override;
|
||||
|
||||
void BindTexture(PD::LI::TexAddress addr) override;
|
||||
|
||||
void RenderDrawData(const PD::Vec<PD::LI::Command::Ref>& Commands) override;
|
||||
|
||||
PD::LI::Texture::Ref LoadTexture(
|
||||
const std::vector<PD::u8>& pixels, int w, int h,
|
||||
PD::LI::Texture::Type type = PD::LI::Texture::Type::RGBA32,
|
||||
PD::LI::Texture::Filter filter =
|
||||
PD::LI::Texture::Filter::LINEAR) override;
|
||||
|
||||
private:
|
||||
Vec<Vertex, LinearAlloc<Vertex>> VertexBuffer;
|
||||
Vec<u16, LinearAlloc<u16>> IndexBuffer;
|
||||
size_t CurrentVertex = 0;
|
||||
size_t CurrentIndex = 0;
|
||||
Mat4 Projection;
|
||||
int pLocProjection = 0;
|
||||
DVLB_s* ShaderCode;
|
||||
shaderProgram_s Shader;
|
||||
C3D_AttrInfo ShaderInfo;
|
||||
// For Stats
|
||||
PD::u32 num_vtx = 0;
|
||||
PD::u32 num_idx = 0;
|
||||
};
|
||||
} // namespace LI
|
||||
} // namespace PD
|
43
backends/3ds/include/pd_hid_3ds.hpp
Normal file
43
backends/3ds/include/pd_hid_3ds.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2025 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/core/hid_driver.hpp>
|
||||
|
||||
namespace PD {
|
||||
class Hid3DS : public Hid {
|
||||
public:
|
||||
/**
|
||||
* Constructor to setup Key binds
|
||||
*/
|
||||
Hid3DS();
|
||||
~Hid3DS() = default;
|
||||
PD_SMART_CTOR(Hid3DS)
|
||||
|
||||
/**
|
||||
* Overrideing the Update Function for Input Checking etc
|
||||
*/
|
||||
void Update() override;
|
||||
};
|
||||
} // namespace PD
|
103
backends/3ds/include/pd_net_3ds.hpp
Normal file
103
backends/3ds/include/pd_net_3ds.hpp
Normal file
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2025 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <malloc.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <pd/net/backend.hpp>
|
||||
|
||||
namespace PD {
|
||||
class NetBackend3DS : public Net::Backend {
|
||||
public:
|
||||
NetBackend3DS() : Net::Backend("3DS") {}
|
||||
~NetBackend3DS() = default;
|
||||
PD_SMART_CTOR(NetBackend3DS)
|
||||
|
||||
bool Init() override {
|
||||
pSocBuffer = (uint32_t*)memalign(pSocAlign, pSocBufferSize);
|
||||
Result ret = 0;
|
||||
if (pSocBuffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ret = socInit(pSocBuffer, pSocBufferSize)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Deinit() override { socExit(); }
|
||||
int NewSocket() override { return socket(AF_INET, SOCK_STREAM, 0); }
|
||||
void Close(int sock_id) override { close(sock_id); }
|
||||
int GetInvalidRef() const override { return -1; }
|
||||
|
||||
bool Bind(int sock_id, u16 port) {
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
return bind(sock_id, (sockaddr*)&addr, sizeof(addr)) != -1;
|
||||
}
|
||||
bool Listen(int sock_id, int backlog = 5) {
|
||||
return listen(sock_id, backlog) != -1;
|
||||
}
|
||||
bool Accept(int sock_id, Net::Socket::Ref client) {
|
||||
int client_soc = accept(sock_id, nullptr, nullptr);
|
||||
if (client_soc == -1) {
|
||||
return false;
|
||||
}
|
||||
client->pSocket = client_soc;
|
||||
return true;
|
||||
}
|
||||
bool Connect(int sock_id, const std::string& ip, u16 port) {
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);
|
||||
return connect(sock_id, (sockaddr*)&addr, sizeof(addr)) != -1;
|
||||
}
|
||||
int Send(int sock_id, const std::string& data) {
|
||||
return send(sock_id, data.c_str(), static_cast<int>(data.size()), 0);
|
||||
}
|
||||
int Receive(int sock_id, std::string& data, int size = 1024) {
|
||||
char* tmp = new char[size];
|
||||
int res = recv(sock_id, tmp, size, 0);
|
||||
if (res > 0) {
|
||||
data.assign(tmp, res);
|
||||
}
|
||||
delete[] tmp;
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
/** using libctru u32 here */
|
||||
const uint32_t pSocAlign = 0x1000;
|
||||
const uint32_t pSocBufferSize = 0x100000;
|
||||
uint32_t* pSocBuffer = nullptr;
|
||||
};
|
||||
} // namespace PD
|
229
backends/3ds/source/li_backend_c3d.cpp
Normal file
229
backends/3ds/source/li_backend_c3d.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
#include <li_backend_c3d.hpp>
|
||||
|
||||
/// @brief Shader Code (Unused as i dont want to use libpicasso here (yet))
|
||||
const char* LIShaderCTR = R"(
|
||||
; LI7 Shader
|
||||
; Constants
|
||||
.constf myconst(0.0, 1.0, 0.00392156862745, 0.0)
|
||||
.alias ones myconst.yyyy ; Vector full of ones
|
||||
|
||||
; Uniforms
|
||||
.fvec projection[4]
|
||||
|
||||
; Outputs
|
||||
.out out_position position
|
||||
.out out_color color
|
||||
.out out_uv texcoord0
|
||||
|
||||
; Inputs
|
||||
.alias in_xy v0
|
||||
.alias in_uvc v1
|
||||
.alias in_col v2
|
||||
|
||||
.entry vmain
|
||||
.proc vmain
|
||||
mov r0.xy, in_xy.xy
|
||||
mov r0.w, ones
|
||||
|
||||
dp4 out_position.x, projection[0], r0
|
||||
dp4 out_position.y, projection[1], r0
|
||||
dp4 out_position.z, projection[2], r0
|
||||
dp4 out_position.w, projection[3], r0
|
||||
|
||||
mov out_uv, in_uvc.xy
|
||||
|
||||
mul r1, myconst.zzzz, in_col
|
||||
mov out_color, r1
|
||||
end
|
||||
.end
|
||||
)";
|
||||
|
||||
// clang-format off
|
||||
unsigned char li_shader[] = {
|
||||
0x44, 0x56, 0x4c, 0x42, 0x1, 0x0, 0x0, 0x0, 0xa4, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x50, 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x1, 0xf0, 0x7, 0x4e, 0x2, 0x8, 0x2, 0x8, 0x3, 0x18, 0x2, 0x8, 0x4, 0x28, 0x2, 0x8, 0x5, 0x38, 0x2, 0x8, 0x6, 0x10, 0x40, 0x4c, 0x7, 0xf1, 0x27, 0x22, 0x8, 0x10, 0x21, 0x4c, 0x0, 0x0, 0x0, 0x88, 0xac, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa1, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xd5, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x45, 0x2, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x74, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x2, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x1, 0x1, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1, 0x0, 0xf, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x13, 0x0, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0, 0x0,
|
||||
};
|
||||
// clang-format on
|
||||
size_t li_shader_size = 0x124;
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
GPU_TEXCOLOR GetTexFmt(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return GPU_RGBA8;
|
||||
else if (type == Texture::RGB24)
|
||||
return GPU_RGB8;
|
||||
else if (type == Texture::A8)
|
||||
return GPU_A8;
|
||||
return GPU_RGBA8; // Default
|
||||
}
|
||||
int GetBPP(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return 4;
|
||||
else if (type == Texture::RGB24)
|
||||
return 3;
|
||||
else if (type == Texture::A8)
|
||||
return 1;
|
||||
return 0; // Error
|
||||
}
|
||||
void Backend_C3D::Init() {
|
||||
std::cout << "[BACKEND_C3D]: Setting up Buffers" << std::endl;
|
||||
VertexBuffer.Resize(4 * 8192);
|
||||
IndexBuffer.Resize(6 * 8192);
|
||||
|
||||
Flags |= LIBackendFlags_FlipUV_Y;
|
||||
|
||||
std::cout << "[BACKEND_C3D]: Loading shader..." << std::endl;
|
||||
ShaderCode = DVLB_ParseFile((uint32_t*)li_shader, li_shader_size);
|
||||
shaderProgramInit(&Shader);
|
||||
shaderProgramSetVsh(&Shader, &ShaderCode->DVLE[0]);
|
||||
pLocProjection =
|
||||
shaderInstanceGetUniformLocation(Shader.vertexShader, "projection");
|
||||
|
||||
std::cout << "[BACKEND_C3D]: Setting up Attr Info" << std::endl;
|
||||
AttrInfo_Init(&ShaderInfo);
|
||||
AttrInfo_AddLoader(&ShaderInfo, 0, GPU_FLOAT, 2);
|
||||
AttrInfo_AddLoader(&ShaderInfo, 1, GPU_FLOAT, 2);
|
||||
AttrInfo_AddLoader(&ShaderInfo, 2, GPU_UNSIGNED_BYTE, 4);
|
||||
std::cout << "[BACKEND_C3D]: Backend init done!" << std::endl;
|
||||
}
|
||||
|
||||
void Backend_C3D::Deinit() {
|
||||
shaderProgramFree(&Shader);
|
||||
DVLB_Free(ShaderCode);
|
||||
}
|
||||
|
||||
void Backend_C3D::NewFrame() {
|
||||
C3D_BindProgram(&Shader);
|
||||
C3D_SetAttrInfo(&ShaderInfo);
|
||||
CurrentIndex = 0;
|
||||
CurrentVertex = 0;
|
||||
FrameCounter++;
|
||||
VertexCounter = num_vtx;
|
||||
IndexCounter = num_idx;
|
||||
num_vtx = 0;
|
||||
num_idx = 0;
|
||||
}
|
||||
|
||||
void Backend_C3D::BindTexture(PD::LI::TexAddress addr) {
|
||||
C3D_TexBind(0, reinterpret_cast<C3D_Tex*>(addr));
|
||||
}
|
||||
|
||||
void Backend_C3D::RenderDrawData(
|
||||
const PD::Vec<PD::LI::Command::Ref>& Commands) {
|
||||
C3D_BindProgram(&Shader);
|
||||
C3D_SetAttrInfo(&ShaderInfo);
|
||||
C3D_Mtx proj;
|
||||
Mtx_OrthoTilt(&proj, 0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f, false);
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, &proj);
|
||||
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||
size_t index = 0;
|
||||
while (index < Commands.Size()) {
|
||||
PD::LI::Texture::Ref Tex = Commands[index]->Tex;
|
||||
if (!Tex) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
bool ScissorEnabled = Commands[index]->ScissorEnabled;
|
||||
ivec4 ScissorRect = Commands[index]->ScissorRect;
|
||||
size_t StartIndex = CurrentIndex;
|
||||
|
||||
while (index < Commands.Size() && Commands[index]->Tex == Tex &&
|
||||
Commands[index]->ScissorEnabled == ScissorEnabled &&
|
||||
Commands[index]->ScissorRect == ScissorRect) {
|
||||
auto c = Commands[index];
|
||||
for (size_t i = 0; i < c->IndexBuffer.Size(); i++) {
|
||||
num_idx++;
|
||||
IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.At(i);
|
||||
}
|
||||
for (size_t i = 0; i < c->VertexBuffer.Size(); i++) {
|
||||
num_vtx++;
|
||||
VertexBuffer[CurrentVertex++] = c->VertexBuffer.At(i);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (ScissorEnabled) {
|
||||
// Figure out this setup was pain
|
||||
C3D_SetScissor(GPU_SCISSOR_NORMAL,
|
||||
ViewPort.y - (ScissorRect.y + ScissorRect.w),
|
||||
ViewPort.x - (ScissorRect.x + ScissorRect.z),
|
||||
ViewPort.y - ScissorRect.y, ViewPort.x - ScissorRect.x);
|
||||
} else {
|
||||
C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0);
|
||||
}
|
||||
BindTexture(Tex->Address);
|
||||
auto bufInfo = C3D_GetBufInfo();
|
||||
BufInfo_Init(bufInfo);
|
||||
BufInfo_Add(bufInfo, VertexBuffer.Data(), sizeof(Vertex), 3, 0x210);
|
||||
|
||||
C3D_DrawElements(GPU_TRIANGLES, CurrentIndex - StartIndex,
|
||||
C3D_UNSIGNED_SHORT, IndexBuffer.Data() + StartIndex);
|
||||
}
|
||||
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
|
||||
}
|
||||
|
||||
PD::LI::Texture::Ref Backend_C3D::LoadTexture(const std::vector<PD::u8>& pixels,
|
||||
int w, int h,
|
||||
PD::LI::Texture::Type type,
|
||||
PD::LI::Texture::Filter filter) {
|
||||
std::cout << "Loading Tex " << std::format("[{}, {}]", w, h) << std::endl;
|
||||
// Don't check here as check done before
|
||||
PD::LI::Texture::Ref res = PD::LI::Texture::New();
|
||||
int bpp = GetBPP(type);
|
||||
ivec2 tex_size(w, h);
|
||||
// Pow2
|
||||
if (!PD::BitUtil::IsSingleBit(w)) {
|
||||
tex_size.x = PD::BitUtil::GetPow2((unsigned int)w);
|
||||
}
|
||||
if (!PD::BitUtil::IsSingleBit(h)) {
|
||||
tex_size.y = PD::BitUtil::GetPow2((unsigned int)h);
|
||||
}
|
||||
res->Size.x = w;
|
||||
res->Size.y = h;
|
||||
res->UV = fvec4(0.f, 1.f, ((float)w / (float)tex_size.x),
|
||||
1.0 - ((float)h / (float)tex_size.y));
|
||||
|
||||
// Texture Setup
|
||||
auto fltr = (filter == Texture::NEAREST ? GPU_NEAREST : GPU_LINEAR);
|
||||
auto tex_fmt = GetTexFmt(type);
|
||||
auto tex = new C3D_Tex;
|
||||
C3D_TexInit(tex, (u16)tex_size.x, (u16)tex_size.y, tex_fmt);
|
||||
C3D_TexSetFilter(tex, fltr, fltr);
|
||||
|
||||
// Using std::fill_n instead cause i hate this error lines
|
||||
// under the memset func in my editor
|
||||
std::fill_n((PD::u8*)tex->data, tex->size, 0);
|
||||
// memset(tex->data, 0, tex->size);s
|
||||
|
||||
/// Probably Remove this if statement in future
|
||||
/// This are the things confirmed as working
|
||||
if (bpp == 3 || bpp == 4 || bpp == 1) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int dst_pos = ((((y >> 3) * ((int)tex_size.x >> 3) + (x >> 3)) << 6) +
|
||||
((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) |
|
||||
((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) *
|
||||
bpp;
|
||||
int src_pos = (y * w + x) * bpp;
|
||||
/// Best idea i had
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
((u8*)tex->data)[dst_pos + bpp - 1 - i] = pixels[src_pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
C3D_TexFlush(tex);
|
||||
}
|
||||
|
||||
tex->border = 0x00000000;
|
||||
C3D_TexSetWrap(tex, GPU_REPEAT, GPU_REPEAT);
|
||||
res->Address = (TexAddress)tex;
|
||||
std::cout << std::format("Tex {:#08x} Addr {:#08X}", (TexAddress)res.get(),
|
||||
res->Address)
|
||||
<< std::endl;
|
||||
return res;
|
||||
}
|
||||
} // namespace LI
|
||||
} // namespace PD
|
60
backends/3ds/source/pd_hid_3ds.cpp
Normal file
60
backends/3ds/source/pd_hid_3ds.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd_hid_3ds.hpp>
|
||||
|
||||
namespace PD {
|
||||
Hid3DS::Hid3DS() : Hid("3DS") {
|
||||
binds[KEY_A] = A;
|
||||
binds[KEY_B] = B;
|
||||
binds[KEY_X] = X;
|
||||
binds[KEY_Y] = Y;
|
||||
binds[KEY_START] = Start;
|
||||
binds[KEY_SELECT] = Select;
|
||||
binds[KEY_L] = L;
|
||||
binds[KEY_R] = R;
|
||||
binds[KEY_DUP] = DUp;
|
||||
binds[KEY_DDOWN] = DDown;
|
||||
binds[KEY_DLEFT] = DLeft;
|
||||
binds[KEY_DRIGHT] = DRight;
|
||||
binds[KEY_CPAD_UP] = CPUp;
|
||||
binds[KEY_CPAD_DOWN] = CPDown;
|
||||
binds[KEY_CPAD_LEFT] = CPLeft;
|
||||
binds[KEY_CPAD_RIGHT] = CPRight;
|
||||
binds[KEY_CSTICK_UP] = CSUp;
|
||||
binds[KEY_CSTICK_DOWN] = CSDown;
|
||||
binds[KEY_CSTICK_LEFT] = CSLeft;
|
||||
binds[KEY_CSTICK_RIGHT] = CSRight;
|
||||
binds[KEY_ZL] = ZL;
|
||||
binds[KEY_ZR] = ZR;
|
||||
binds[KEY_TOUCH] = Touch;
|
||||
}
|
||||
void Hid3DS::Update() {
|
||||
hidScanInput();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
key_events[i][Event_Down] = 0;
|
||||
key_events[i][Event_Held] = 0;
|
||||
key_events[i][Event_Up] = 0;
|
||||
}
|
||||
u32 kd = hidKeysDown();
|
||||
u32 kh = hidKeysHeld();
|
||||
u32 ku = hidKeysUp();
|
||||
for (auto &b : binds) {
|
||||
if (b.first & kd) {
|
||||
key_events[0][Event_Down] |= b.second;
|
||||
}
|
||||
if (b.first & kh) {
|
||||
key_events[0][Event_Held] |= b.second;
|
||||
}
|
||||
if (b.first & ku) {
|
||||
key_events[0][Event_Up] |= b.second;
|
||||
}
|
||||
}
|
||||
if (locked) {
|
||||
SwappyTable();
|
||||
}
|
||||
touchPosition t;
|
||||
hidTouchRead(&t);
|
||||
touch[1] = touch[0]; // Cycle touch pos
|
||||
touch[0] = fvec2(t.px, t.py);
|
||||
}
|
||||
} // namespace PD
|
27
backends/desktop/CMakeLists.txt
Normal file
27
backends/desktop/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
if(WIN32)
|
||||
set(EXTRA_LIBS ws2_32)
|
||||
else()
|
||||
set(EXTRA_LIBS)
|
||||
endif()
|
||||
|
||||
add_subdirectory(glfw)
|
||||
add_subdirectory(glad)
|
||||
|
||||
# if(PD_BUILD_SHARED)
|
||||
# add_library(pd-backend-desktop SHARED
|
||||
# source/li_backend_gl2.cpp
|
||||
# source/pd_hid_glfw.cpp)
|
||||
# target_compile_definitions(pd-backend-desktop PUBLIC
|
||||
# -DPD_BKND_DESKTOP_BUILD_SHARED=1)
|
||||
# else()
|
||||
add_library(pd-backend-desktop STATIC
|
||||
source/li_backend_gl2.cpp
|
||||
source/pd_hid_glfw.cpp)
|
||||
#endif()
|
||||
|
||||
target_compile_definitions(pd-backend-desktop PUBLIC
|
||||
-DPD_BKND_DESKTOP_STATIC=1)
|
||||
target_include_directories(pd-backend-desktop PUBLIC include)
|
||||
target_link_libraries(pd-backend-desktop PUBLIC glad glfw palladium ${EXTRA_LIBS})
|
4
backends/desktop/glad/CMakeLists.txt
Normal file
4
backends/desktop/glad/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
add_library(glad source/glad.c)
|
||||
target_include_directories(glad PUBLIC include)
|
311
backends/desktop/glad/include/KHR/khrplatform.h
Normal file
311
backends/desktop/glad/include/KHR/khrplatform.h
Normal file
@ -0,0 +1,311 @@
|
||||
#ifndef __khrplatform_h_
|
||||
#define __khrplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/* Khronos platform-specific types and definitions.
|
||||
*
|
||||
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||
* The last semantic modification to khrplatform.h was at commit ID:
|
||||
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||
*
|
||||
* Adopters may modify this file to suit their platform. Adopters are
|
||||
* encouraged to submit platform specific modifications to the Khronos
|
||||
* group so that they can be included in future versions of this file.
|
||||
* Please submit changes by filing pull requests or issues on
|
||||
* the EGL Registry repository linked above.
|
||||
*
|
||||
*
|
||||
* See the Implementer's Guidelines for information about where this file
|
||||
* should be located on your system and for more details of its use:
|
||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||
*
|
||||
* This file should be included as
|
||||
* #include <KHR/khrplatform.h>
|
||||
* by Khronos client API header files that use its types and defines.
|
||||
*
|
||||
* The types in khrplatform.h should only be used to define API-specific types.
|
||||
*
|
||||
* Types defined in khrplatform.h:
|
||||
* khronos_int8_t signed 8 bit
|
||||
* khronos_uint8_t unsigned 8 bit
|
||||
* khronos_int16_t signed 16 bit
|
||||
* khronos_uint16_t unsigned 16 bit
|
||||
* khronos_int32_t signed 32 bit
|
||||
* khronos_uint32_t unsigned 32 bit
|
||||
* khronos_int64_t signed 64 bit
|
||||
* khronos_uint64_t unsigned 64 bit
|
||||
* khronos_intptr_t signed same number of bits as a pointer
|
||||
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||
* khronos_ssize_t signed size
|
||||
* khronos_usize_t unsigned size
|
||||
* khronos_float_t signed 32 bit floating point
|
||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||
* nanoseconds
|
||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||
* only be used as a base type when a client API's boolean type is
|
||||
* an enum. Client APIs which use an integer or other type for
|
||||
* booleans cannot use this as the base type for their boolean.
|
||||
*
|
||||
* Tokens defined in khrplatform.h:
|
||||
*
|
||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||
*
|
||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||
*
|
||||
* Calling convention macros defined in this file:
|
||||
* KHRONOS_APICALL
|
||||
* KHRONOS_APIENTRY
|
||||
* KHRONOS_APIATTRIBUTES
|
||||
*
|
||||
* These may be used in function prototypes as:
|
||||
*
|
||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||
* int arg1,
|
||||
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||
*/
|
||||
|
||||
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||
# define KHRONOS_STATIC 1
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APICALL
|
||||
*-------------------------------------------------------------------------
|
||||
* This precedes the return type of the function in the function prototype.
|
||||
*/
|
||||
#if defined(KHRONOS_STATIC)
|
||||
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||
* header compatible with static linking. */
|
||||
# define KHRONOS_APICALL
|
||||
#elif defined(_WIN32)
|
||||
# define KHRONOS_APICALL __declspec(dllimport)
|
||||
#elif defined (__SYMBIAN32__)
|
||||
# define KHRONOS_APICALL IMPORT_C
|
||||
#elif defined(__ANDROID__)
|
||||
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||
#else
|
||||
# define KHRONOS_APICALL
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIENTRY
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the return type of the function and precedes the function
|
||||
* name in the function prototype.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||
/* Win32 but not WinCE */
|
||||
# define KHRONOS_APIENTRY __stdcall
|
||||
#else
|
||||
# define KHRONOS_APIENTRY
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIATTRIBUTES
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the closing parenthesis of the function prototype arguments.
|
||||
*/
|
||||
#if defined (__ARMCC_2__)
|
||||
#define KHRONOS_APIATTRIBUTES __softfp
|
||||
#else
|
||||
#define KHRONOS_APIATTRIBUTES
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* basic type definitions
|
||||
*-----------------------------------------------------------------------*/
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||
|
||||
|
||||
/*
|
||||
* Using <stdint.h>
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
/*
|
||||
* To support platform where unsigned long cannot be used interchangeably with
|
||||
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
||||
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
||||
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
||||
* unsigned long long or similar (this results in different C++ name mangling).
|
||||
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
||||
* platforms where the size of a pointer is larger than the size of long.
|
||||
*/
|
||||
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
||||
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
||||
#define KHRONOS_USE_INTPTR_T
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(__VMS ) || defined(__sgi)
|
||||
|
||||
/*
|
||||
* Using <inttypes.h>
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||
|
||||
/*
|
||||
* Win32
|
||||
*/
|
||||
typedef __int32 khronos_int32_t;
|
||||
typedef unsigned __int32 khronos_uint32_t;
|
||||
typedef __int64 khronos_int64_t;
|
||||
typedef unsigned __int64 khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(__sun__) || defined(__digital__)
|
||||
|
||||
/*
|
||||
* Sun or Digital
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#if defined(__arch64__) || defined(_LP64)
|
||||
typedef long int khronos_int64_t;
|
||||
typedef unsigned long int khronos_uint64_t;
|
||||
#else
|
||||
typedef long long int khronos_int64_t;
|
||||
typedef unsigned long long int khronos_uint64_t;
|
||||
#endif /* __arch64__ */
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif 0
|
||||
|
||||
/*
|
||||
* Hypothetical platform with no float or int64 support
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#define KHRONOS_SUPPORT_INT64 0
|
||||
#define KHRONOS_SUPPORT_FLOAT 0
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Generic fallback
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Types that are (so far) the same on all platforms
|
||||
*/
|
||||
typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
|
||||
/*
|
||||
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||
* to be the only LLP64 architecture in current use.
|
||||
*/
|
||||
#ifdef KHRONOS_USE_INTPTR_T
|
||||
typedef intptr_t khronos_intptr_t;
|
||||
typedef uintptr_t khronos_uintptr_t;
|
||||
#elif defined(_WIN64)
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef unsigned long long int khronos_uintptr_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef unsigned long int khronos_uintptr_t;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
typedef unsigned long long int khronos_usize_t;
|
||||
#else
|
||||
typedef signed long int khronos_ssize_t;
|
||||
typedef unsigned long int khronos_usize_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_FLOAT
|
||||
/*
|
||||
* Float type
|
||||
*/
|
||||
typedef float khronos_float_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64
|
||||
/* Time types
|
||||
*
|
||||
* These types can be used to represent a time interval in nanoseconds or
|
||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||
* time the system booted). The Unadjusted System Time is an unsigned
|
||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||
* may be either signed or unsigned.
|
||||
*/
|
||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dummy value used to pad enum types to 32 bits.
|
||||
*/
|
||||
#ifndef KHRONOS_MAX_ENUM
|
||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enumerated boolean type
|
||||
*
|
||||
* Values other than zero should be considered to be true. Therefore
|
||||
* comparisons should not be made against KHRONOS_TRUE.
|
||||
*/
|
||||
typedef enum {
|
||||
KHRONOS_FALSE = 0,
|
||||
KHRONOS_TRUE = 1,
|
||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||
} khronos_boolean_enum_t;
|
||||
|
||||
#endif /* __khrplatform_h_ */
|
5169
backends/desktop/glad/include/glad/glad.h
Normal file
5169
backends/desktop/glad/include/glad/glad.h
Normal file
File diff suppressed because it is too large
Load Diff
2532
backends/desktop/glad/source/glad.c
Normal file
2532
backends/desktop/glad/source/glad.c
Normal file
File diff suppressed because it is too large
Load Diff
1
backends/desktop/glfw
Submodule
1
backends/desktop/glfw
Submodule
Submodule backends/desktop/glfw added at e7ea71be03
46
backends/desktop/include/li_backend_gl2.hpp
Normal file
46
backends/desktop/include/li_backend_gl2.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include <glad/glad.h>
|
||||
|
||||
/** SEPARATOR */
|
||||
#include <GLFW/glfw3.h>
|
||||
/** SEPARATOR */
|
||||
#include <pd/core/core.hpp>
|
||||
#include <pd/lithium/backend.hpp>
|
||||
#include <pd_p_bknd_api.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
class PD_BKND_DESKTOP_API Backend_GL2 : public PD::LI::Backend {
|
||||
public:
|
||||
Backend_GL2() : LI::Backend("OpenGL2") {}
|
||||
~Backend_GL2() {}
|
||||
|
||||
PD_SMART_CTOR(Backend_GL2)
|
||||
|
||||
void Init() override;
|
||||
void Deinit() override;
|
||||
void NewFrame() override;
|
||||
void BindTexture(PD::LI::TexAddress addr) override;
|
||||
void RenderDrawData(const PD::Vec<PD::LI::Command::Ref>& Commands) override;
|
||||
PD::LI::Texture::Ref LoadTexture(
|
||||
const std::vector<PD::u8>& pixels, int w, int h,
|
||||
PD::LI::Texture::Type type = PD::LI::Texture::Type::RGBA32,
|
||||
PD::LI::Texture::Filter filter =
|
||||
PD::LI::Texture::Filter::LINEAR) override;
|
||||
|
||||
private:
|
||||
PD::Vec<PD::LI::Vertex> VertexBuffer;
|
||||
PD::Vec<PD::u16> IndexBuffer;
|
||||
size_t CurrentVertex = 0;
|
||||
size_t CurrentIndex = 0;
|
||||
GLuint Shader;
|
||||
GLuint pLocProjection;
|
||||
GLuint pLocTex;
|
||||
Mat4 Projection;
|
||||
GLuint VBO, IBO;
|
||||
// For Stats
|
||||
PD::u32 num_vtx = 0;
|
||||
PD::u32 num_idx = 0;
|
||||
};
|
||||
|
||||
} // namespace LI
|
||||
} // namespace PD
|
50
backends/desktop/include/pd_hid_glfw.hpp
Normal file
50
backends/desktop/include/pd_hid_glfw.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2025 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <pd/core/hid_driver.hpp>
|
||||
#include <pd_p_bknd_api.hpp>
|
||||
|
||||
namespace PD {
|
||||
class PD_BKND_DESKTOP_API HidGLFW : public Hid {
|
||||
public:
|
||||
/**
|
||||
* Constructor to setup Key binds
|
||||
*/
|
||||
HidGLFW(GLFWwindow* win);
|
||||
~HidGLFW() = default;
|
||||
PD_SMART_CTOR(HidGLFW)
|
||||
|
||||
/**
|
||||
* Overrideing the Update Function for Input Checking etc
|
||||
*/
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
GLFWwindow* Window;
|
||||
int PrevState;
|
||||
};
|
||||
} // namespace PD
|
117
backends/desktop/include/pd_net_desktop.hpp
Normal file
117
backends/desktop/include/pd_net_desktop.hpp
Normal file
@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
Copyright (c) 2024 - 2025 René Amthor (tobid7)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#ifdef _MSVC
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#endif
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <pd/net/backend.hpp>
|
||||
namespace PD {
|
||||
class NetBackendDesktop : public PD::Net::Backend {
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
NetBackendDesktop() : Net::Backend("Desktop (Windows)") {
|
||||
#else
|
||||
NetBackendDesktop() : Net::Backend("Desktop (Unix)") {
|
||||
#endif
|
||||
}
|
||||
~NetBackendDesktop() = default;
|
||||
PD_SMART_CTOR(NetBackendDesktop)
|
||||
bool Init() override {
|
||||
#ifdef _WIN32
|
||||
WSADATA wsa_data;
|
||||
return (WSAStartup(MAKEWORD(2, 2), &wsa_data) == 0);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
void Deinit() override {
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
int NewSocket() override { return socket(AF_INET, SOCK_STREAM, 0); }
|
||||
void Close(int sock_id) override {
|
||||
#ifdef _WIN32
|
||||
closesocket(sock_id);
|
||||
#else
|
||||
close(sock_id);
|
||||
#endif
|
||||
}
|
||||
int GetInvalidRef() const override {
|
||||
#ifdef _WIN32
|
||||
return INVALID_SOCKET;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Bind(int sock_id, u16 port) {
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
return bind(sock_id, (sockaddr*)&addr, sizeof(addr)) != -1;
|
||||
}
|
||||
bool Listen(int sock_id, int backlog = 5) {
|
||||
return listen(sock_id, backlog) != -1;
|
||||
}
|
||||
bool Accept(int sock_id, Net::Socket::Ref client) {
|
||||
int client_soc = accept(sock_id, nullptr, nullptr);
|
||||
if (client_soc == GetInvalidRef()) {
|
||||
return false;
|
||||
}
|
||||
client->pSocket = client_soc;
|
||||
return true;
|
||||
}
|
||||
bool Connect(int sock_id, const std::string& ip, u16 port) {
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);
|
||||
return connect(sock_id, (sockaddr*)&addr, sizeof(addr)) != -1;
|
||||
}
|
||||
int Send(int sock_id, const std::string& data) {
|
||||
return send(sock_id, data.c_str(), static_cast<int>(data.size()), 0);
|
||||
}
|
||||
int Receive(int sock_id, std::string& data, int size = 1024) {
|
||||
char* tmp = new char[size];
|
||||
int res = recv(sock_id, tmp, size, 0);
|
||||
if (res > 0) {
|
||||
data.assign(tmp, res);
|
||||
}
|
||||
delete[] tmp;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
} // namespace PD
|
58
backends/desktop/include/pd_p_bknd_api.hpp
Normal file
58
backends/desktop/include/pd_p_bknd_api.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 - 2025 tobid7
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef PD_BKND_DESKTOP_STATIC
|
||||
#if defined(__3DS__) // 3ds Specific
|
||||
#error "Desktop backend is not supported on the 3ds!"
|
||||
#endif
|
||||
#define PD_BKND_DESKTOP_API
|
||||
#else
|
||||
#ifdef _WIN32 // Windows (MSVC Tested)
|
||||
#ifdef PD_BKND_DESKTOP_BUILD_SHARED
|
||||
#define PD_BKND_DESKTOP_API __declspec(dllexport)
|
||||
#else
|
||||
#define PD_BKND_DESKTOP_API __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(__APPLE__) // macOS (untested yet)
|
||||
#ifdef PD_BKND_DESKTOP_BUILD_SHARED
|
||||
#define PD_BKND_DESKTOP_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define PD_BKND_DESKTOP_API
|
||||
#endif
|
||||
#elif defined(__linux__) // Linux (untested yet)
|
||||
#ifdef PD_BKND_DESKTOP_BUILD_SHARED
|
||||
#define PD_BKND_DESKTOP_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define PD_BKND_DESKTOP_API
|
||||
#endif
|
||||
#elif defined(__3DS__) // 3ds Specific
|
||||
#error "Desktop backend is not supported on the 3ds!"
|
||||
#else
|
||||
#define PD_BKND_DESKTOP_API
|
||||
#endif
|
||||
#endif
|
230
backends/desktop/source/li_backend_gl2.cpp
Normal file
230
backends/desktop/source/li_backend_gl2.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
#include <li_backend_gl2.hpp>
|
||||
|
||||
const char* vertex_shader = R"(
|
||||
#version 120
|
||||
|
||||
attribute vec2 pos;
|
||||
attribute vec2 uv;
|
||||
attribute vec4 color;
|
||||
|
||||
varying vec2 oUV;
|
||||
varying vec4 oColor;
|
||||
|
||||
// Probably forgot about this matric and
|
||||
// searched hours for why the rendering isn't working :/
|
||||
uniform mat4 projection;
|
||||
|
||||
void main() {
|
||||
gl_Position = projection*vec4(pos, 0.0, 1.0);
|
||||
oUV = uv;
|
||||
oColor = color;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* frag_shader = R"(
|
||||
#version 120
|
||||
|
||||
varying vec2 oUV;
|
||||
varying vec4 oColor;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void main() {
|
||||
vec4 tc = texture2D(tex, oUV);
|
||||
gl_FragColor = tc*oColor;
|
||||
}
|
||||
)";
|
||||
|
||||
GLuint compileShader(const std::string& source,
|
||||
GLenum type) {
|
||||
GLuint shader = glCreateShader(type);
|
||||
const char* src = source.c_str();
|
||||
glShaderSource(shader, 1, &src, nullptr);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
char infoLog[512];
|
||||
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
|
||||
std::cerr << "Shader Compilation Error: " << infoLog << std::endl;
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint
|
||||
createShaderProgram(const std::string& vertexShaderSource,
|
||||
const std::string& fragmentShaderSource) {
|
||||
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader =
|
||||
compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
|
||||
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
glLinkProgram(shaderProgram);
|
||||
|
||||
GLint success;
|
||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
char infoLog[512];
|
||||
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
|
||||
std::cerr << "Shader Program Linking Error: " << infoLog << std::endl;
|
||||
}
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
PD_BKND_DESKTOP_API void Backend_GL2::Init() {
|
||||
VertexBuffer.Resize(4 * 8192);
|
||||
IndexBuffer.Resize(6 * 8192);
|
||||
Shader = createShaderProgram(vertex_shader, frag_shader);
|
||||
glUseProgram(Shader);
|
||||
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
|
||||
GLint _pos = glGetAttribLocation(Shader, "pos");
|
||||
GLint _uv = glGetAttribLocation(Shader, "uv");
|
||||
GLint _color = glGetAttribLocation(Shader, "color");
|
||||
glVertexAttribPointer(_pos, 2, GL_FLOAT, GL_FALSE, sizeof(PD::LI::Vertex),
|
||||
(void*)offsetof(PD::LI::Vertex, Pos));
|
||||
glEnableVertexAttribArray(_pos);
|
||||
|
||||
glVertexAttribPointer(_uv, 2, GL_FLOAT, GL_FALSE, sizeof(PD::LI::Vertex),
|
||||
(void*)offsetof(PD::LI::Vertex, UV));
|
||||
glEnableVertexAttribArray(_uv);
|
||||
|
||||
glVertexAttribPointer(_color, 4, GL_UNSIGNED_BYTE, GL_TRUE,
|
||||
sizeof(PD::LI::Vertex),
|
||||
(void*)offsetof(PD::LI::Vertex, Color));
|
||||
glEnableVertexAttribArray(_color);
|
||||
|
||||
glGenBuffers(1, &IBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
|
||||
pLocTex = glGetUniformLocation(Shader, "tex");
|
||||
pLocProjection = glGetUniformLocation(Shader, "projection");
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
PD_BKND_DESKTOP_API void Backend_GL2::Deinit() {
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteBuffers(1, &IBO);
|
||||
}
|
||||
|
||||
PD_BKND_DESKTOP_API void Backend_GL2::NewFrame() {
|
||||
glViewport(0, 0, ViewPort.x, ViewPort.y);
|
||||
glClearColor(ClearColor.x, ClearColor.y, ClearColor.z, ClearColor.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
Projection.Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, -1.f, 1.f);
|
||||
glUniformMatrix4fv(pLocProjection, 1, GL_TRUE, Projection.m);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
CurrentIndex = 0;
|
||||
CurrentVertex = 0;
|
||||
FrameCounter++;
|
||||
VertexCounter = num_vtx;
|
||||
IndexCounter = num_idx;
|
||||
num_vtx = 0;
|
||||
num_idx = 0;
|
||||
}
|
||||
|
||||
PD_BKND_DESKTOP_API void Backend_GL2::BindTexture(PD::LI::TexAddress addr) {
|
||||
// Actually not using the Address as Address
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)addr);
|
||||
glUniform1i(pLocTex, 0);
|
||||
}
|
||||
|
||||
PD_BKND_DESKTOP_API void Backend_GL2::RenderDrawData(
|
||||
const PD::Vec<PD::LI::Command::Ref>& Commands) {
|
||||
glUseProgram(Shader);
|
||||
size_t index = 0;
|
||||
while (index < Commands.Size()) {
|
||||
PD::LI::Texture::Ref Tex = Commands[index]->Tex;
|
||||
if (!Tex) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
size_t StartIndex = CurrentIndex;
|
||||
bool ScissorEnabled = Commands[index]->ScissorEnabled;
|
||||
ivec4 ScissorRect = Commands[index]->ScissorRect;
|
||||
|
||||
while (index < Commands.Size() && Commands[index]->Tex == Tex &&
|
||||
Commands[index]->ScissorEnabled == ScissorEnabled &&
|
||||
Commands[index]->ScissorRect == ScissorRect) {
|
||||
auto c = Commands[index];
|
||||
for (size_t i = 0; i < c->IndexBuffer.Size(); i++) {
|
||||
num_idx++;
|
||||
IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.At(i);
|
||||
}
|
||||
for (size_t i = 0; i < c->VertexBuffer.Size(); i++) {
|
||||
num_vtx++;
|
||||
VertexBuffer[CurrentVertex++] = c->VertexBuffer.At(i);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (ScissorEnabled) {
|
||||
glScissor(ScissorRect.x, ViewPort.y - (ScissorRect.y + ScissorRect.w),
|
||||
ScissorRect.z, ScissorRect.w);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
BindTexture(Tex->Address);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, CurrentVertex * sizeof(PD::LI::Vertex),
|
||||
&VertexBuffer[0], GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, CurrentIndex * sizeof(PD::u16),
|
||||
&IndexBuffer[0], GL_DYNAMIC_DRAW);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, CurrentIndex - StartIndex, GL_UNSIGNED_SHORT,
|
||||
(void*)(StartIndex * sizeof(PD::u16)));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
BindTexture(0);
|
||||
}
|
||||
}
|
||||
|
||||
PD_BKND_DESKTOP_API PD::LI::Texture::Ref Backend_GL2::LoadTexture(
|
||||
const std::vector<PD::u8>& pixels, int w, int h, PD::LI::Texture::Type type,
|
||||
PD::LI::Texture::Filter filter) {
|
||||
GLuint texID;
|
||||
glGenTextures(1, &texID);
|
||||
glBindTexture(GL_TEXTURE_2D, texID);
|
||||
|
||||
// Set base format (Always using RGBA as base)
|
||||
GLenum fmt = GL_RGBA;
|
||||
if (type == PD::LI::Texture::Type::RGB24) {
|
||||
fmt = GL_RGB;
|
||||
} else if (type == PD::LI::Texture::Type::A8) {
|
||||
fmt = GL_ALPHA;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE,
|
||||
pixels.data());
|
||||
if (filter == PD::LI::Texture::Filter::LINEAR) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
} else if (filter == PD::LI::Texture::Filter::NEAREST) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
auto res = PD::LI::Texture::New(texID, PD::ivec2(w, h));
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace LI
|
||||
} // namespace PD
|
33
backends/desktop/source/pd_hid_glfw.cpp
Normal file
33
backends/desktop/source/pd_hid_glfw.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include <pd_hid_glfw.hpp>
|
||||
|
||||
namespace PD {
|
||||
PD_BKND_DESKTOP_API HidGLFW::HidGLFW(GLFWwindow* win) : Hid("GLFW") {
|
||||
Window = win;
|
||||
binds[GLFW_MOUSE_BUTTON_LEFT] = Touch;
|
||||
}
|
||||
PD_BKND_DESKTOP_API void HidGLFW::Update() {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
key_events[i][Event_Down] = 0;
|
||||
key_events[i][Event_Held] = 0;
|
||||
key_events[i][Event_Up] = 0;
|
||||
}
|
||||
int state = glfwGetMouseButton(Window, GLFW_MOUSE_BUTTON_LEFT);
|
||||
if (state == GLFW_PRESS) {
|
||||
if (PrevState == GLFW_RELEASE) {
|
||||
key_events[0][Event_Down] |= Touch;
|
||||
}
|
||||
key_events[0][Event_Held] |= Touch;
|
||||
} else if (state == GLFW_RELEASE && PrevState == GLFW_PRESS) {
|
||||
key_events[0][Event_Up] |= Touch;
|
||||
}
|
||||
|
||||
PrevState = state;
|
||||
if (locked) {
|
||||
SwappyTable();
|
||||
}
|
||||
double x, y;
|
||||
glfwGetCursorPos(Window, &x, &y);
|
||||
touch[1] = touch[0]; // Cycle touch pos
|
||||
touch[0] = fvec2(x, y);
|
||||
}
|
||||
} // namespace PD
|
Reference in New Issue
Block a user