Browse Source

Added OpenGL module

This proved to be more involved than I thought it would be, thanks to
my distaste in OpenGL loaders. I decided on galogen, which is now
built and executed during comptime in order to generate the GL
headers.

It doesn't yet pull the latest Khronos spec. I can add that once I add
a CURL module, which I thought I was going to need anyways.

The OpenGL code itself isn't yet doing much.
windows-imgui
Macoy Madson 6 months ago
parent
commit
753e2a0fbe
  1. 1
      .gitignore
  2. 152
      src/OpenGL.cake
  3. 62
      test/src/GameLibTests.cake

1
.gitignore

@ -42,6 +42,7 @@ test/ogreApp
test/output/
test/autoTest
test/VocalGame
test/galogen
*.blend1

152
src/OpenGL.cake

@ -0,0 +1,152 @@
;; Windowing and OpenGL access are provided by SDL
(import "SDL.cake")
(c-import "stdio.h"
"SDL.h"
"SDL_syswm.h"
;; Use galogen-generated header. See (generate-gl-header)
"gl46.h") ;; "GL/gl.h"
(comptime-cond
('auto-test
(defun test--opengl (&return int)
(var window (* SDL_Window) null)
(unless (sdl-initialize-for-3d (addr window) "OpenGL" 640 480) (return 1))
(SDL_GL_SetSwapInterval 1) ;; Enable vsync
;; TODO: Support resizing with window resize callback
(glViewport 0 0 640 480)
(scope ;; Make our triangle vertex array object
(var vertex-buffer-id (unsigned int))
(glGenBuffers 1 (addr vertex-buffer-id))
(glBindBuffer GL_ARRAY_BUFFER vertex-buffer-id)
(var vertices ([] float)
(array
0.25f 0.25f 0.25f
0.5f 0.5f 0.5f
0.75f 0.75f 0.75f))
(glBufferData GL_ARRAY_BUFFER (sizeof vertices) vertices GL_STATIC_DRAW))
(var exit-reason (* (const char)) null)
(while (not exit-reason)
(var event SDL_Event)
(while (SDL_PollEvent (addr event))
(when (= (field event type) SDL_QUIT)
(set exit-reason "Window event")))
(var currentKeyStates (* (const Uint8)) (SDL_GetKeyboardState null))
(when (at SDL_SCANCODE_ESCAPE currentKeyStates)
(set exit-reason "Escape pressed"))
(glClearColor 0.2f 0.3f 0.3f 1.f)
(glClear GL_COLOR_BUFFER_BIT)
(SDL_GL_SwapWindow window))
(when exit-reason
(printf "Exiting. Reason: %s\n" exit-reason))
(sdl-shutdown window)
(return 0))))
;;
;; Building
;;
(module-use-sdl-build-options)
(comptime-cond
('Unix
(add-library-dependency "GL" "dl"))
('Windows
(add-linker-options "opengl32.lib")))
;; Most OpenGL loading libraries were not to my tastes. I decided on galogen
;; (http://galogen.gpfault.net/) because it's only two C++ files (not python or something else) and
;; reads directly from the Khronos spec (and I don't have to use my web browser for *****-sake)
;; See https://www.khronos.org/opengl/wiki/OpenGL_Loading_Library
(add-dependency-git-submodule clone-galogen "https://github.com/google/galogen" "Dependencies/galogen")
(defun-comptime generate-gl-header (manager (& ModuleManager) module (* Module) &return bool)
(var galogen-source-file (* (const char)) "Dependencies/galogen/galogen.cpp")
(var galogen-executable (* (const char))
(comptime-cond ('Unix "galogen") ('Windows "galogen.exe")))
;; Build galogen (GL header code generator)
(when (fileIsMoreRecentlyModified galogen-source-file galogen-executable)
(comptime-cond
('Unix
(run-process-sequential-or
((call-on c_str (field manager environment compileTimeBuildCommand fileToExecute))
galogen-source-file "Dependencies/galogen/third_party/tinyxml2.cpp"
"--std=c++11" "-O3"
"-o" galogen-executable)
(Log "error: failed to build galogen. This uses the compile-time build command\n")
(return false))
(addExecutablePermission galogen-executable))
('Windows
(run-process-sequential-or
((call-on c_str (field manager environment compileTimeBuildCommand fileToExecute))
galogen-source-file "Dependencies/galogen/third_party/tinyxml2.cpp"
"/Ox" "/EHsc")
(Log "error: failed to build galogen. This uses the compile-time build command\n")
(return false)))))
;; Use galogen to generate gl headers/source
;; TODO Use CURL or something to download the latest version from
;; https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/master/xml/gl.xml
(var gl-specification (* (const char)) "Dependencies/galogen/third_party/gl.xml")
;; TODO: Generate the version header name to match the version SDL.cake specifies
(var gl-generated-output-path ([] 256 char) (array 0))
(unless (outputFilenameFromSourceFilename
(call-on c_str (field manager buildOutputDir))
"gl46"
null gl-generated-output-path (sizeof gl-generated-output-path))
(Log "error: failed to generate gl output filename\n")
(return false))
(var gl-generated-source-name ([] 256 char) (array 0))
(PrintfBuffer gl-generated-source-name "%s.c" gl-generated-output-path)
(when (or (fileIsMoreRecentlyModified galogen-executable
gl-generated-source-name)
(fileIsMoreRecentlyModified gl-specification
gl-generated-source-name))
(var galogen-executable-path ([] 256 char) (array 0))
(comptime-cond ('Unix (PrintfBuffer galogen-executable-path "./%s" galogen-executable))
('Windows (PrintfBuffer galogen-executable-path "%s" galogen-executable)))
(run-process-sequential-or
(galogen-executable-path
gl-specification
"--api" "gl" "--ver" "4.6" "--profile" "core"
"--filename" gl-generated-output-path)
(Log "error: failed to generate gl headers via galogen\n")
(return false)))
(scope ;; Add the generated file as a dependency
;; TODO: This needs to be cleaned up
(var gl-dependency ModuleDependency (array))
(set (field gl-dependency type) ModuleDependency_CFile)
(set (field gl-dependency name) "gl46.c")
(scope ;; Use this function as the blame token
;; TODO: Add __function__ for this
(var this-definition-name (* (const char)) "generate-gl-header")
(var this-definition (* ObjectDefinition)
(findObjectDefinition (field manager environment) this-definition-name))
(unless this-definition
(Logf "error: failed to find definition of %s to create blame token. Was it
renamed? Search for %s and replace it with the new name of the function it is defined in\n"
this-definition-name this-definition-name)
(return false))
(set (field gl-dependency blameToken) (path this-definition > definitionInvocation)))
(call-on push_back (path module > dependencies) gl-dependency))
(scope ;; Search paths for new dependency
;; Make sure Cakelisp can resolve to the file in the cache
(call-on push_back (path module > cSearchDirectories) (call-on c_str (field manager buildOutputDir)))
;; Make sure the source file can find its header
(call-on push_back (path module > cSearchDirectories) "."))
(return true))
(add-compile-time-hook-module pre-build generate-gl-header)

62
test/src/GameLibTests.cake

@ -40,32 +40,42 @@
;; (var test-minimal bool true)
(var test-minimal bool false)
(if test-minimal
(gamelib-run-test
"Auto Test (data structures only)"
(array platform-config
"../src/AutoTest.cake" "../src/Dictionary.cake"
"../src/DynamicArray.cake"))
(scope ;; Test everything, which requires user input and takes a while
(gamelib-run-test
"Auto Test"
(array platform-config
"../src/AutoTest.cake" "../src/SDL.cake" "../src/Math.cake"
"../src/Aubio.cake" "../src/ImGui.cake" "../src/Dictionary.cake"
"../src/DynamicArray.cake"))
(gamelib-run-test "Ogre" (array platform-config "src/OgreApp.cake"))
(gamelib-run-test "SDL Ogre" (array platform-config "src/SDLOgreApp.cake"))
(gamelib-build "Vocal Game (hot reload)"
(array platform-config "src/MakeHotReload.cake" "src/VocalGame.cake"))
(gamelib-run-test "Hot-loader"
(array platform-config "src/Loader.cake"))
(gamelib-run-test "Vocal Game (no reload)"
(array platform-config "src/NoHotReload.cake" "src/VocalGame.cake"))))
;; (var test-opengl-only bool true)
(var test-opengl-only bool false)
(cond
(test-minimal
(gamelib-run-test
"Auto Test (data structures only)"
(array platform-config
"../src/AutoTest.cake" "../src/Dictionary.cake"
"../src/DynamicArray.cake")))
(test-opengl-only
(gamelib-run-test
"Auto Test (OpenGL only)"
(array platform-config
"../src/AutoTest.cake" "../src/OpenGL.cake")))
(true ;; Test everything, which requires user input and takes a while
(gamelib-run-test
"Auto Test"
(array platform-config
"../src/AutoTest.cake" "../src/SDL.cake" "../src/Math.cake"
"../src/Aubio.cake" "../src/ImGui.cake" "../src/Dictionary.cake"
"../src/DynamicArray.cake" "../src/OpenGL.cake"))
(gamelib-run-test "Ogre" (array platform-config "src/OgreApp.cake"))
(gamelib-run-test "SDL Ogre" (array platform-config "src/SDLOgreApp.cake"))
(gamelib-build "Vocal Game (hot reload)"
(array platform-config "src/MakeHotReload.cake" "src/VocalGame.cake"))
(gamelib-run-test "Hot-loader"
(array platform-config "src/Loader.cake"))
(gamelib-run-test "Vocal Game (no reload)"
(array platform-config "src/NoHotReload.cake" "src/VocalGame.cake"))))
(Log "\nGameLibTests: All tests succeeded!\n")
(return true))

Loading…
Cancel
Save