21 Commits

Author SHA1 Message Date
andromeda
f09e348de8 add example 2026-02-27 22:27:15 +01:00
andromeda
d9d14bdc94 example except it just churns and doesn't actually paint a window 2026-02-12 23:25:32 +01:00
andromeda
2d299d4ced Merge branch 'hs-bindgen-fixes' into dev 2026-02-12 22:28:47 +01:00
andromeda
cea8ba3354 it finally compiles :) 2026-02-12 22:20:30 +01:00
andromeda
66b9e70c8c bump flake, change -D to -optc-D in .cabal file 2026-02-12 21:15:51 +01:00
andromeda
472eb1c70d bump rgfw 2026-01-31 14:10:41 +01:00
andromeda
2b84809d84 build error 2026-01-31 13:18:14 +01:00
andromeda
4858c3ee2e bump hs-bindgen 2026-01-24 19:26:30 +01:00
andromeda
8583f117cc fix error in README.md 2026-01-24 18:57:13 +01:00
andromeda
3d72958712 Merge branch 'master' into nix-err-date-not-found 2026-01-24 18:55:00 +01:00
andromeda
371d2b7f97 builds! 2026-01-24 18:49:56 +01:00
mtgmonkey
93bee37b83 key callbacks, tidy 2025-12-16 11:14:40 +01:00
mtgmonkey
d36bbad5a8 tidy up, submodule RGFW 2025-12-16 01:12:02 +01:00
mtgmonkey
5a701a3632 [feat] unify with example, actually win for once 2025-12-16 00:24:10 +01:00
mtgmonkey
170685f6c8 remove extra files 2025-12-11 23:03:15 +01:00
mtgmonkey
82961432f9 remove Wayland; couldn't figure out 2025-12-11 22:49:07 +01:00
mtgmonkey
15c587d65a remove assertion of Semantic Versioning - Cabal is annoying 2025-12-11 18:19:51 +01:00
mtgmonkey
7cfdb25174 fix typo in CHANGELOG.md 2025-12-11 18:17:08 +01:00
mtgmonkey
8a16c6695e basic functionality on Wayland and X11 2025-12-11 18:15:32 +01:00
mtgmonkey
ab69702910 add library as git submodule, wayland, window shows 2025-12-10 21:12:56 +01:00
mtgmonkey
5e2d2b89c8 init 2025-12-09 22:18:41 +01:00
10 changed files with 289 additions and 85 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
lib
include
result*
dist-newstyle

View File

@@ -1,2 +1,3 @@
`nix build` or `nix run` to build lib or run the example
to do it manually, run `./generate.sh` to generate `lib/` before `cabal build` or `cabal run`

View File

@@ -4,10 +4,10 @@ packages:
source-repository-package
type: git
location: https://github.com/well-typed/hs-bindgen.git
tag: 933d11d771ff13b6a3b851cb0ec9bc3632626f2f
tag: f99ed4ddfc7808b3eb28bbf089612b6a52983685
subdir: hs-bindgen-runtime
source-repository-package
type: git
location: https://github.com/well-typed/hs-bindgen.git
tag: 933d11d771ff13b6a3b851cb0ec9bc3632626f2f
tag: f99ed4ddfc7808b3eb28bbf089612b6a52983685
subdir: c-expr-runtime

38
flake.lock generated
View File

@@ -5,11 +5,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1763759067,
"narHash": "sha256-LlLt2Jo/gMNYAwOgdRQBrsRoOz7BPRkzvNaI/fzXi2Q=",
"lastModified": 1769996383,
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "2cccadc7357c0ba201788ae99c4dfa90728ef5e0",
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
"type": "github"
},
"original": {
@@ -25,43 +25,43 @@
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1765888948,
"narHash": "sha256-rgGAUQVfJ0sKXm9bzh7XIJUHh/JkEsz/LX6k8aCKeD4=",
"lastModified": 1770911191,
"narHash": "sha256-fePV3+4uHg1tQH83rUO/7gQOGexHdaxyVkO2X3HkOA0=",
"owner": "well-typed",
"repo": "hs-bindgen",
"rev": "fd74e8fa4216eccd67069ec9d8637b57000ffc83",
"rev": "087884c110948e7bd67bec0ae8004e5396f63241",
"type": "github"
},
"original": {
"owner": "well-typed",
"repo": "hs-bindgen",
"rev": "fd74e8fa4216eccd67069ec9d8637b57000ffc83",
"type": "github"
}
},
"libclang-bindings-src": {
"flake": false,
"locked": {
"lastModified": 1765293798,
"narHash": "sha256-fZvyZo5emD1W5LwrIg2zTUYE9StRh3xF8TcuXjzKIAk=",
"lastModified": 1770274896,
"narHash": "sha256-JnxJBo2L4URFD8JbpjnPG/ej/xKFe7y5ZpjnvIztwAM=",
"owner": "well-typed",
"repo": "libclang",
"rev": "b8305bd9c3e8e8f63d6f415553388be7f233ef45",
"rev": "155642a4a4a9f0414a058a8f08f39aa6c7bb57ed",
"type": "github"
},
"original": {
"owner": "well-typed",
"repo": "libclang",
"rev": "155642a4a4a9f0414a058a8f08f39aa6c7bb57ed",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1764947035,
"narHash": "sha256-EYHSjVM4Ox4lvCXUMiKKs2vETUSL5mx+J2FfutM7T9w=",
"lastModified": 1770169770,
"narHash": "sha256-awR8qIwJxJJiOmcEGgP2KUqYmHG4v/z8XpL9z8FnT1A=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a672be65651c80d3f592a89b3945466584a22069",
"rev": "aa290c9891fa4ebe88f8889e59633d20cc06a5f2",
"type": "github"
},
"original": {
@@ -73,11 +73,11 @@
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1761765539,
"narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=",
"lastModified": 1769909678,
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "719359f4562934ae99f5443f20aa06c2ffff91fc",
"rev": "72716169fe93074c333e8d0173151350670b824c",
"type": "github"
},
"original": {
@@ -88,11 +88,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1765772535,
"narHash": "sha256-aq+dQoaPONOSjtFIBnAXseDm9TUhIbe215TPmkfMYww=",
"lastModified": 1770843696,
"narHash": "sha256-LovWTGDwXhkfCOmbgLVA10bvsi/P8eDDpRudgk68HA8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "09b8fda8959d761445f12b55f380d90375a1d6bb",
"rev": "2343bbb58f99267223bc2aac4fc9ea301a155a16",
"type": "github"
},
"original": {

View File

@@ -1,7 +1,7 @@
{
inputs = {
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
hs-bindgen.url = "github:well-typed/hs-bindgen/fd74e8fa4216eccd67069ec9d8637b57000ffc83";
hs-bindgen.url = "github:well-typed/hs-bindgen";
self.submodules = true;
};
outputs = {
@@ -10,50 +10,6 @@
self,
...
}: let
version = "0.1.0";
package = {
# nix stuff
mkDerivation,
lib,
# haskell deps
base,
c-expr-runtime,
hs-bindgen-runtime,
# pkgconfig deps
libGL,
libX11,
libXcursor,
libXi,
xrandr,
# shell deps
hs-bindgen-cli,
}:
mkDerivation {
pname = "hs-rgfw";
inherit version;
src = ./.;
libraryHaskellDepends = [
base
c-expr-runtime
hs-bindgen-runtime
];
libraryPkgconfigDepends = [
libGL
libX11
libXcursor
libXi
xrandr
];
preBuild = ''
set -x
export PATH=${hs-bindgen-cli}/bin:\$PATH
./generate.sh
set +x
'';
homepage = "https://git.mtgmonkey.net/Andromeda/hs-rgfw";
license = lib.licenses.gpl3Only;
platforms = ["x86_64-linux"];
};
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
@@ -67,6 +23,8 @@
default = pkgs.mkShell {
stdenv = pkgs.clangStdenv;
packages = [
pkgs.haskellPackages.ghcide
pkgs.haskellPackages.ormolu
pkgs.clang
pkgs.cabal-install
pkgs.hs-bindgen-cli
@@ -78,7 +36,18 @@
};
};
packages.${system} = {
default = pkgs.haskellPackages.callPackage package {};
default =
(pkgs.haskell.packages.ghc912.callCabal2nix "hs-rgfw" ./. {
xi = pkgs.libxi;
gl = pkgs.libGL;
xcursor = pkgs.libxcursor;
xrandr = pkgs.xrandr;
}).overrideAttrs {
preConfigure = ''
export PATH=${pkgs.clang}/bin:${pkgs.hs-bindgen-cli}/bin:${pkgs.tree}/bin:$PATH
./generate.sh
'';
};
};
};
}

View File

@@ -1,8 +1,49 @@
echo "# copying header..."
mkdir -p lib/include
cp rgfw/RGFW.h lib/include/RGFW.h
echo "# creating flags for hs-bindgen-cli..."
export CFLAGS=$(pkg-config --cflags x11 xcursor xrandr xi gl xrender xext xfixes)
HBC_ARGS=""
for token in $CFLAGS; do
case "$token" in
-I* ) HBC_ARGS="$HBC_ARGS $token" ;;
-D* ) HBC_ARGS="$HBC_ARGS --define-macro ${token#-D}" ;;
* ) HBC_ARGS="$HBC_ARGS --clang-option $token" ;;
esac
done
echo "# creating c file from header..."
# other macro definitions should be defined with ghc-options: -copt-D in *.cabal
cat > lib/RGFW.c <<EOF
#define RGFW_IMPLEMENTATION
#include "RGFW.h"
EOF
echo "# generating library RGFW.Generated..."
# --unsafe _unsafe \
# --pointer _pointer \
set -x
hs-bindgen-cli preprocess \
-Irgfw \
-Ilib/include \
--unique-id andromeda.hs-rgfw \
--create-output-dirs \
--overwrite-files \
--single-file \
--safe _safe \
--hs-output-dir lib \
--module RGFW.Generated \
--clang-option=-DRGFW_OPENGL \
--define-macro=RGFW_OPENGL \
--define-macro=RGFW_EXPORT \
$HBC_ARGS \
RGFW.h
set +x
echo "# generated filetree:"
tree lib

View File

@@ -12,22 +12,11 @@ common warnings
library
import: warnings
-- hs-bindgen-cli uses --single-file flag, so no other modules
exposed-modules: RGFW.Generated
build-depends:
, base
, c-expr-runtime
, hs-bindgen-runtime
include-dirs: rgfw
hs-source-dirs: lib
default-language: Haskell2010
default-extensions: FlexibleInstances
executable hs-rgfw
import: warnings
main-is: Main.hs
build-depends:
, base
, hs-rgfw
, primitive
, c-expr-runtime
, hs-bindgen-runtime
pkgconfig-depends:
@@ -36,6 +25,32 @@ executable hs-rgfw
, xcursor
, xrandr
, xi
include-dirs: rgfw
include-dirs: lib/include
hs-source-dirs: lib
default-language: Haskell2010
default-extensions: FlexibleInstances
-- options for RGFW passed here
ghc-options:
-optc-DRGFW_OPENGL
-optc-DRGFW_EXPORT
c-sources: lib/RGFW.c
executable hs-rgfw
import: warnings
main-is: Main.hs
build-depends:
, base
, bytestring
, c-expr-runtime
, hs-bindgen-runtime
, hs-rgfw
, OpenGL
pkgconfig-depends:
, gl
, x11
, xcursor
, xrandr
, xi
include-dirs: lib/include
hs-source-dirs: src
default-language: Haskell2010

2
rgfw

Submodule rgfw updated: 83d945ae89...a971541830

91
src/LoadShaders.hs Normal file
View File

@@ -0,0 +1,91 @@
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- |
-- Module : LoadShaders
-- Copyright : (c) Sven Panne 2013
-- License : BSD3
--
-- Maintainer : Sven Panne <svenpanne@gmail.com>
-- Stability : stable
-- Portability : portable
--
-- Utilities for shader handling, adapted from LoadShaders.cpp which is (c) The
-- Red Book Authors.
module LoadShaders
( ShaderSource (..),
ShaderInfo (..),
loadShaders,
)
where
import Control.Exception
import Control.Monad
import qualified Data.ByteString as B
import Graphics.Rendering.OpenGL
--------------------------------------------------------------------------------
-- | The source of the shader source code.
data ShaderSource
= -- | The shader source code is directly given as a 'B.ByteString'.
ByteStringSource B.ByteString
| -- | The shader source code is directly given as a 'String'.
StringSource String
| -- | The shader source code is located in the file at the given 'FilePath'.
FileSource FilePath
deriving (Eq, Ord, Show)
getSource :: ShaderSource -> IO B.ByteString
getSource (ByteStringSource bs) = return bs
getSource (StringSource str) = return $ packUtf8 str
getSource (FileSource path) = B.readFile path
--------------------------------------------------------------------------------
-- | A description of a shader: The type of the shader plus its source code.
data ShaderInfo
= ShaderInfo ShaderType ShaderSource
deriving (Eq, Ord, Show)
--------------------------------------------------------------------------------
-- | Create a new program object from the given shaders, throwing an
-- 'IOException' if something goes wrong.
loadShaders :: [ShaderInfo] -> IO Program
loadShaders infos =
createProgram `bracketOnError` deleteObjectName $ \program -> do
loadCompileAttach program infos
linkAndCheck program
return program
linkAndCheck :: Program -> IO ()
linkAndCheck = checked linkProgram linkStatus programInfoLog "link"
loadCompileAttach :: Program -> [ShaderInfo] -> IO ()
loadCompileAttach _ [] = return ()
loadCompileAttach program (ShaderInfo shType source : infos) =
createShader shType `bracketOnError` deleteObjectName $ \shader -> do
src <- getSource source
shaderSourceBS shader $= src
compileAndCheck shader
attachShader program shader
loadCompileAttach program infos
compileAndCheck :: Shader -> IO ()
compileAndCheck = checked compileShader compileStatus shaderInfoLog "compile"
checked ::
(t -> IO ()) ->
(t -> GettableStateVar Bool) ->
(t -> GettableStateVar String) ->
String ->
t ->
IO ()
checked action getStatus getInfoLog message object = do
action object
ok <- get (getStatus object)
unless ok $ do
infoLog <- get (getInfoLog object)
fail (message ++ " log: " ++ infoLog)

View File

@@ -1,3 +1,89 @@
{-# LANGUAGE MultilineStrings #-}
module Main where
import Data.Bits ((.|.))
import Foreign.C.ConstPtr
import Foreign.C.String (newCString)
import Foreign.C.Types (CChar)
import Foreign.Ptr (Ptr)
import Graphics.Rendering.OpenGL (($=))
import qualified Graphics.Rendering.OpenGL as GL
import LoadShaders
import RGFW.Generated
main :: IO ()
main = putStrLn "Hello World"
main = do
putStrInfo "creating window"
-- string not freed; window remains open
windowTitle_cstr <- newCString "window"
let windowTitle_ptr = ConstPtr windowTitle_cstr
windowFlags = RGFW_windowFlags $ fromIntegral $ RGFW_windowCenter .|. RGFW_windowNoResize .|. RGFW_windowOpenGL
window <-
rGFW_createWindow_safe
windowTitle_ptr -- name
0 -- x
0 -- y
300 -- w
300 -- h
windowFlags -- flags
putStrDebug $ "windowFlags: " ++ (show $ unwrapU32 $ unwrapRGFW_windowFlags windowFlags)
putStrDebug $ "window: " ++ (show $ window)
putStrInfo "initialising shaders"
_ <- initResources
putStrInfo "entering loop"
loop window 0
loop :: Ptr RGFW_window -> Int -> IO ()
loop window i = do
view
rGFW_window_swapBuffers_OpenGL_safe window
loop window $ i + 1
putStrDebug :: String -> IO ()
putStrDebug a = putStrLn $ "[debug]:" ++ a
putStrInfo :: String -> IO ()
putStrInfo a = putStrLn $ "[info]:" ++ a
initResources :: IO GL.Program
initResources = do
program <-
loadShaders
[ ShaderInfo GL.VertexShader $ StringSource vertShader,
ShaderInfo GL.FragmentShader $ StringSource fragShader
]
GL.currentProgram $= Just program
return program
where
vertShader =
"""
#version 330 core
layout (location = 0) in vec3 aPos;
out vec4 vertexColor;
void main()
{
gl_Position = vec4(aPos, 1.0);
vertexColor = vec4(0.5, 0.0, 0.0, 1.0);
}
"""
fragShader =
"""
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
void main()
{
FragColor = vertexColor;
}
"""
view :: IO ()
view = do
GL.clearColor $= GL.Color4 1 0 1 1
GL.clear [GL.ColorBuffer, GL.DepthBuffer]