throw all gl functions in global namespace, that'll show them

main
eater 2 years ago
parent 1f3881bdc4
commit 112b26a4b5
Signed by: eater
GPG Key ID: AD2560A0F84F0759

@ -4,6 +4,58 @@ if ( ! file_exists(__DIR__ . "/../resources/gl.xml")) {
copy("https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/gl.xml", __DIR__ . "/../resources/gl.xml"); copy("https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/gl.xml", __DIR__ . "/../resources/gl.xml");
} }
$types = [
"int" => [
"char",
"unsigned char",
"int",
"unsigned int",
"short",
"unsigned short",
"long",
"unsigned long",
"long long",
"unsigned long long",
"GLsizeiptr",
"GLintptr",
"GLenum",
"GLboolean",
"GLbitfield",
"GLvoid",
"GLbyte",
"GLshort",
"GLint",
"GLubyte",
"GLushort",
"GLuint",
"GLsizei",
"GLchar",
"GLsizeiptr",
"GLintptr",
"GLsync",
"GLeglImageOES",
"GLeglClientBufferEXT",
"GLuint64",
"GLint64",
"GLuint64EXT",
"GLint64EXT",
"GLfixed",
"GLhalfNV",
"GLhandleARB",
"GLcharARB",
"GLintptrARB",
"GLsizeiptrARB",
"GLclampx",
],
"float" => [
'GLfloat',
'GLdouble',
'float',
'double',
],
];
$xml = new DOMDocument(); $xml = new DOMDocument();
$xml->loadXML(file_get_contents(__DIR__ . "/../resources/gl.xml")); $xml->loadXML(file_get_contents(__DIR__ . "/../resources/gl.xml"));
@ -13,6 +65,8 @@ $data = file_get_contents(__DIR__ . "/../headers/gl.h");
$data .= "// GENERATED DATA START\n\n"; $data .= "// GENERATED DATA START\n\n";
$php = "<?php\n\nuse Cijber\GraphicsToolkit\GL;\nuse FFI\Cdata;\n\n// generated gl functions\n\n";
/** @var DOMNode $node */ /** @var DOMNode $node */
foreach ($commands->childNodes as $node) { foreach ($commands->childNodes as $node) {
if ($node->nodeName !== "command") { if ($node->nodeName !== "command") {
@ -26,15 +80,47 @@ foreach ($commands->childNodes as $node) {
$name = $proto->getElementsByTagName("name")[0]; $name = $proto->getElementsByTagName("name")[0];
$name->remove(); $name->remove();
$returnType = trim($proto->textContent); $returnType = trim($proto->textContent);
$functionName = trim($name->textContent); $functionName = trim($name->textContent);
$args = []; $args = [];
$names = [];
$phpArgs = [];
foreach ($node->getElementsByTagName("param") as $param) { foreach ($node->getElementsByTagName("param") as $param) {
$args[] = trim($param->textContent); $name = $param->getElementsByTagName('name')->item(0);
$name->remove();
$type = trim($param->textContent);;
if (($type === 'void *' || $type === 'const void *') && $functionName === 'glVertexAttribPointer' || $functionName === 'glDrawElements') {
$type = 'unsigned long long';
}
$phpType = "";
foreach ($types as $foundPhpType => $cTypes) {
if (false !== array_search($type, $cTypes)) {
$phpType = $foundPhpType;
break;
}
}
if ($phpType !== "") {
$phpArgs[] = $phpType . ' $' . $name->textContent;
} else {
$phpArgs[] = '$' . $name->textContent;
}
$names[] = '$' . $name->textContent;
$args[] = $type;
} }
$data .= "typedef $returnType (* FUNC_$functionName) (" . implode(", ", $args) . ");\n"; $data .= "typedef $returnType (* FUNC_$functionName) (" . implode(", ", $args) . ");\n";
$functionBody = "(" . implode(", ", $phpArgs) . ") {\n static \$proc;\n return (\$proc ??= GL::getProcAddress('" . strtolower($functionName[2]) . substr($functionName, 3) . "'))(" . implode(", ", $names) . ");\n}\n\n";;
$php .= "function $functionName$functionBody";
} }
file_put_contents(__DIR__ . "/../headers/gl_generated.h", $data); file_put_contents(__DIR__ . "/../headers/gl_generated.h", $data);
file_put_contents(__DIR__ . "/../src/gl_functions.php", $php);

@ -6,7 +6,14 @@ use Cijber\GraphicsToolkit\GLFW;
use Cijber\GraphicsToolkit\Utils; use Cijber\GraphicsToolkit\Utils;
set_error_handler(function($severity, $message, $file, $line) {
global $error;
$error = new RuntimeException("$severity: $message [$file($line)]");
Fiber::suspend();
});
include(__DIR__ . "/../vendor/autoload.php"); include(__DIR__ . "/../vendor/autoload.php");
function main() { function main() {
GL::init(); GL::init();
@ -31,63 +38,66 @@ function main() {
$window, $window,
function($window, $width, $height) use (&$viewportHeight, &$viewportWidth) { function($window, $width, $height) use (&$viewportHeight, &$viewportWidth) {
echo "Size: $width x $height\n"; echo "Size: $width x $height\n";
GL::viewport(0, 0, $viewportWidth = $width, $viewportHeight = $height); glViewport(0, 0, $viewportWidth = $width, $viewportHeight = $height);
} }
); );
GL::viewport(0, 0, 800, 600); glViewport(0, 0, 800, 600);
GL::debugMessageCallback(function($source, $type, $id, $severity, $length, $message, $user) { glDebugMessageCallback(function($source, $type, $id, $severity, $length, $message, $user) {
$message = substr($message, 0, $length); $message = substr($message, 0, $length);
var_dump(["source" => $source, "type" => $type, "id" => $id, "severity" => $severity, "message" => $message, "gl" => GL::$lastCall]); var_dump(["source" => $source, "type" => $type, "id" => $id, "severity" => $severity, "message" => $message, "call" => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)[2]]);
}, null); }, null);
// GL::debugMessageCallback($callback, null); // glDebugMessageCallback($callback, null);
GL::enable(GL::DEBUG_OUTPUT); glEnable(GL::DEBUG_OUTPUT);
GL::enable(GL::DEBUG_OUTPUT_SYNCHRONOUS); glEnable(GL::DEBUG_OUTPUT_SYNCHRONOUS);
GL::enable(GL::BLEND);
GL::blendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA);
$vertexShader = GL::createShader(GL::VERTEX_SHADER); glEnable(GL::BLEND);
$vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/vertex.glsl");
// glEnable(GL::BLEND);
glBlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA);
GL::shaderSource($vertexShader, 1, $vertexShaderSource, null); $vertexShader = \glCreateShader(GL::VERTEX_SHADER);
$vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/vertex.glsl");
GL::shaderSource($vertexShader, [$vertexShaderSource]);
GL::compileShader($vertexShader); glCompileShader($vertexShader);
GL::getShaderiv($vertexShader, GL::COMPILE_STATUS, $success); glGetShaderiv($vertexShader, GL::COMPILE_STATUS, Utils::pointer($success, "int32_t"));
if ( ! $success) { if ( ! $success->cdata) {
GL::getShaderiv($vertexShader, GL::INFO_LOG_LENGTH, $logLength); glGetShaderiv($vertexShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
GL::getShaderInfoLog($vertexShader, $infoLog, $logLength); glGetShaderInfoLog($vertexShader, $logLength, Utils::null(), Utils::stringBuffer($infoLog, $logLength->cdata));
die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog"); die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog");
} }
$fragmentShader = GL::createShader(GL::FRAGMENT_SHADER); $fragmentShader = glCreateShader(GL::FRAGMENT_SHADER);
$fragmentShaderSource = file_get_contents( $fragmentShaderSource = file_get_contents(
__DIR__ . "/../shaders/fragment.glsl" __DIR__ . "/../shaders/fragment.glsl"
); );
GL::shaderSource($fragmentShader, 1, $fragmentShaderSource, null); GL::shaderSource($fragmentShader, [$fragmentShaderSource]);
GL::compileShader($fragmentShader); glCompileShader($fragmentShader);
GL::getShaderiv($fragmentShader, GL::COMPILE_STATUS, $success); glGetShaderiv($fragmentShader, GL::COMPILE_STATUS, FFI::addr($success));
if ( ! $success) { if ( ! $success->cdata) {
GL::getShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, $logLength); glGetShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
GL::GetShaderInfoLog($fragmentShader, $infoLog, $logLength); glGetShaderInfoLog($fragmentShader, $logLength->cdata, Utils::pointer($result, 'int32_t'), Utils::stringBuffer($infoLog, $logLength->cdata));
die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t$infoLog"); $infoLog = FFI::string($infoLog, $result->cdata);
die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t{$infoLog}");
} }
$shaderProgram = GL::createProgram(); $shaderProgram = glCreateProgram();
GL::attachShader($shaderProgram, $vertexShader); glAttachShader($shaderProgram, $vertexShader);
GL::attachShader($shaderProgram, $fragmentShader); glAttachShader($shaderProgram, $fragmentShader);
GL::linkProgram($shaderProgram); glLinkProgram($shaderProgram);
GL::deleteShader($vertexShader); glDeleteShader($vertexShader);
GL::deleteShader($fragmentShader); glDeleteShader($fragmentShader);
$vertices = [ $vertices = [
-0.5, -0.5,
@ -102,20 +112,21 @@ function main() {
]; ];
$float = Utils::arrayOf('float', $vertices); $float = Utils::arrayOf('float', $vertices);
GL::genVertexArrays(1, $VAO); glGenVertexArrays(1, Utils::pointer($VAO, 'uint32_t'));
GL::genBuffers(1, $VBO); glGenBuffers(1, Utils::pointer($VBO, 'uint32_t'));
$VAO = $VAO->cdata;
GL::bindVertexArray($VAO); $VBO = $VBO->cdata;
GL::bindBuffer(GL::ARRAY_BUFFER, $VBO); glBindVertexArray($VAO);
GL::bufferData( glBindBuffer(GL::ARRAY_BUFFER, $VBO);
glBufferData(
GL::ARRAY_BUFFER, GL::ARRAY_BUFFER,
FFI::sizeof($float), FFI::sizeof($float),
$float, $float,
GL::STATIC_DRAW GL::STATIC_DRAW
); );
GL::vertexAttribPointer( glVertexAttribPointer(
0, 0,
3, 3,
GL::FLOAT, GL::FLOAT,
@ -124,10 +135,10 @@ function main() {
0 0
); );
GL::enableVertexAttribArray(0); glEnableVertexAttribArray(0);
GL::bindBuffer(GL::ARRAY_BUFFER, 0); glBindBuffer(GL::ARRAY_BUFFER, 0);
GL::bindVertexArray(0); glBindVertexArray(0);
$textureRow = Cairo::format_stride_for_width(Cairo::FORMAT_RGB24, 400); $textureRow = Cairo::format_stride_for_width(Cairo::FORMAT_RGB24, 400);
$textureData = FFI::new(FFI::arrayType(FFI::type("unsigned char"), [$textureRow * 400])); $textureData = FFI::new(FFI::arrayType(FFI::type("unsigned char"), [$textureRow * 400]));
@ -142,65 +153,57 @@ function main() {
Cairo::fill($cairo); Cairo::fill($cairo);
Cairo::surface_flush($surface); Cairo::surface_flush($surface);
Gl::genTextures(1, $texture); glGenTextures(1, Utils::pointer($texture, "uint32_t"));
GL::bindTexture(GL::TEXTURE_2D, $texture); $texture = $texture->cdata;
glBindTexture(GL::TEXTURE_2D, $texture);
gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_WRAP_S, GL::REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) glTexParameteri(GL::TEXTURE_2D, GL::TEXTURE_WRAP_S, GL::REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_WRAP_T, GL::REPEAT); glTexParameteri(GL::TEXTURE_2D, GL::TEXTURE_WRAP_T, GL::REPEAT);
// set texture filtering parameters // set texture filtering parameters
gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_MIN_FILTER, GL::LINEAR); glTexParameteri(GL::TEXTURE_2D, GL::TEXTURE_MIN_FILTER, GL::LINEAR);
gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_MAG_FILTER, GL::LINEAR); glTexParameteri(GL::TEXTURE_2D, GL::TEXTURE_MAG_FILTER, GL::LINEAR);
GL::texImage2D(GL::TEXTURE_2D, 0, GL::RGBA, 400, 400, 0, GL::BGRA, GL::UNSIGNED_BYTE, $textureData); glTexImage2D(GL::TEXTURE_2D, 0, GL::RGBA, 400, 400, 0, GL::BGRA, GL::UNSIGNED_BYTE, $textureData);
$vertexShader = GL::createShader(GL::VERTEX_SHADER); $vertexShader = glCreateShader(GL::VERTEX_SHADER);
$vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/sq_vertex_shader.glsl"); $vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/sq_vertex_shader.glsl");
GL::shaderSource( GL::shaderSource($vertexShader, [$vertexShaderSource]);
$vertexShader,
1,
$vertexShaderSource,
null
);
glCompileShader($vertexShader);
glGetShaderiv($vertexShader, GL::COMPILE_STATUS, Utils::pointer($success, 'int32_t'));
GL::compileShader($vertexShader); if ( ! $success->cdata) {
GL::getShaderiv($vertexShader, GL::COMPILE_STATUS, $success); glGetShaderiv($vertexShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
glGetShaderInfoLog($vertexShader, $logLength, Utils::null(), Utils::stringBuffer($infoLog, $logLength->cdata));
if ( ! $success) {
GL::getShaderiv($vertexShader, GL::INFO_LOG_LENGTH, $logLength);
GL::getShaderInfoLog($vertexShader, $infoLog, $logLength);
die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog"); die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog");
} }
$fragmentShader = GL::createShader(GL::FRAGMENT_SHADER); $fragmentShader = glCreateShader(GL::FRAGMENT_SHADER);
$fragmentShaderSource = file_get_contents( $fragmentShaderSource = file_get_contents(
__DIR__ . "/../shaders/sq_fragment_shader.glsl" __DIR__ . "/../shaders/sq_fragment_shader.glsl"
); );
GL::shaderSource( GL::shaderSource($fragmentShader, [$fragmentShaderSource]);
$fragmentShader, glCompileShader($fragmentShader);
1, glGetShaderiv($fragmentShader, GL::COMPILE_STATUS, FFI::addr($success));
$fragmentShaderSource,
null
);
GL::compileShader($fragmentShader);
GL::getShaderiv($fragmentShader, GL::COMPILE_STATUS, $success);
if ( ! $success) {
GL::getShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, $logLength); if ( ! $success->cdata) {
GL::GetShaderInfoLog($fragmentShader, $infoLog, $logLength); glGetShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t$infoLog"); glGetShaderInfoLog($fragmentShader, $logLength->cdata, Utils::pointer($result, 'int32_t'), Utils::stringBuffer($infoLog, $logLength->cdata));
$infoLog = FFI::string($infoLog, $result->cdata);
die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t{$infoLog}");
} }
$squareProgram = GL::createProgram(); $squareProgram = glCreateProgram();
GL::attachShader($squareProgram, $vertexShader); glAttachShader($squareProgram, $vertexShader);
GL::attachShader($squareProgram, $fragmentShader); glAttachShader($squareProgram, $fragmentShader);
GL::linkProgram($squareProgram); glLinkProgram($squareProgram);
GL::deleteShader($vertexShader); glDeleteShader($vertexShader);
GL::deleteShader($fragmentShader); glDeleteShader($fragmentShader);
$sq = [ $sq = [
@ -240,15 +243,18 @@ function main() {
]; ];
$float = Utils::arrayOf('float', $sq); $float = Utils::arrayOf('float', $sq);
GL::genVertexArrays(1, $SQUARE_VAO); glGenVertexArrays(1, Utils::pointer($SQUARE_VAO, 'uint32_t'));
GL::genBuffers(1, $VBO); $SQUARE_VAO = $SQUARE_VAO->cdata;
GL::genBuffers(1, $EBO); glGenBuffers(1, Utils::pointer($VBO, 'uint32_t'));
$VBO = $VBO->cdata;
glGenBuffers(1, Utils::pointer($EBO, 'uint32_t'));
$EBO = $EBO->cdata;
GL::bindVertexArray($SQUARE_VAO); glBindVertexArray($SQUARE_VAO);
GL::bindBuffer(GL::ARRAY_BUFFER, $VBO); glBindBuffer(GL::ARRAY_BUFFER, $VBO);
GL::bufferData( glBufferData(
GL::ARRAY_BUFFER, GL::ARRAY_BUFFER,
FFI::sizeof($float), FFI::sizeof($float),
$float, $float,
@ -256,46 +262,48 @@ function main() {
); );
$indices = Utils::arrayOf("unsigned int", [0, 1, 3, 1, 2, 3]); $indices = Utils::arrayOf("unsigned int", [0, 1, 3, 1, 2, 3]);
GL::bindBuffer(GL::ELEMENT_ARRAY_BUFFER, $EBO); glBindBuffer(GL::ELEMENT_ARRAY_BUFFER, $EBO);
GL::bufferData( glBufferData(
GL::ELEMENT_ARRAY_BUFFER, GL::ELEMENT_ARRAY_BUFFER,
FFI::sizeof($indices), FFI::sizeof($indices),
$indices, $indices,
GL::STATIC_DRAW, GL::STATIC_DRAW,
); );
GL::vertexAttribPointer(0, 3, GL::FLOAT, false, 8 * 4, 0); glVertexAttribPointer(0, 3, GL::FLOAT, 0, 8 * 4, 0);
GL::enableVertexAttribArray(0); glEnableVertexAttribArray(0);
GL::vertexAttribPointer(1, 3, GL::FLOAT, false, 8 * 4, 3 * 4); glVertexAttribPointer(1, 3, GL::FLOAT, 0, 8 * 4, 3 * 4);
GL::enableVertexAttribArray(1); glEnableVertexAttribArray(1);
GL::vertexAttribPointer(2, 2, GL::FLOAT, false, 8 * 4, 6 * 4); glVertexAttribPointer(2, 2, GL::FLOAT, 0, 8 * 4, 6 * 4);
GL::enableVertexAttribArray(2); glEnableVertexAttribArray(2);
GL::useProgram($squareProgram); glUseProgram($squareProgram);
$location = GL::getUniformLocation($squareProgram, "ourTexture"); $location = glGetUniformLocation($squareProgram, "ourTexture");
GL::uniform1i($location, 0); glUniform1i($location, 0);
$viewportSizeLocation = GL::getUniformLocation($squareProgram, "viewportSize"); $viewportSizeLocation = glGetUniformLocation($squareProgram, "viewportSize");
while ( ! GLFW::windowShouldClose($window)) { while ( ! GLFW::windowShouldClose($window)) {
processInput($window); processInput($window);
GL::clearColor(0.2, 0.3, 0.3, 1.0); glClearColor(0.2, 0.3, 0.3, 1.0);
GL::clear(GL::COLOR_BUFFER_BIT); glClear(GL::COLOR_BUFFER_BIT);
glUseProgram($squareProgram);
GL::useProgram($shaderProgram); glActiveTexture(GL::TEXTURE0);
GL::bindVertexArray($VAO); glBindTexture(GL::TEXTURE_2D, $texture);
GL::drawArrays(GL::TRIANGLES, 0, 3);
GL::activeTexture(GL::TEXTURE0); glBindVertexArray($VAO);
GL::bindTexture(GL::TEXTURE_2D, $texture); glDrawArrays(GL::TRIANGLES, 0, 3);
GL::useProgram($squareProgram); glActiveTexture(GL::TEXTURE0);
GL::uniform2i($viewportSizeLocation, $viewportWidth, $viewportHeight); glBindTexture(GL::TEXTURE_2D, $texture);
GL::bindVertexArray($SQUARE_VAO);
$f = FFI::new("long long"); glUseProgram($squareProgram);
$f->cdata = 0; glUniform2i($viewportSizeLocation, $viewportWidth, $viewportHeight);
GL::drawElements(GL::TRIANGLES, 6, GL::UNSIGNED_INT, FFI::cast('void *', $f)); glBindVertexArray($SQUARE_VAO);
glDrawElements(GL::TRIANGLES, 6, GL::UNSIGNED_INT, 0);
GLFW::pollEvents(); GLFW::pollEvents();
GLFW::swapBuffers($window); GLFW::swapBuffers($window);
@ -310,4 +318,11 @@ function processInput($window) {
} }
} }
main(); global $error;
$error = null;
$fiber = new Fiber(fn() => main());
$fiber->start();
if ($error !== null) {
throw $error;
}

File diff suppressed because it is too large Load Diff

@ -10,7 +10,7 @@ uniform ivec2 viewportSize;
void main() void main()
{ {
ivec2 txtSize = textureSize(ourTexture, 0); ivec2 txtSize = textureSize(ourTexture, 0);
vec2 coord = vec2(gl_FragCoord.x / txtSize.x, -gl_FragCoord.y / txtSize.y); vec2 coord = vec2(gl_FragCoord.x / txtSize.x, (viewportSize.y - gl_FragCoord.y) / txtSize.y);
float rest = coord.y - floor(coord.y); float rest = coord.y - floor(coord.y);
FragColor = texture(ourTexture, coord); FragColor = texture(ourTexture, coord);

@ -6,33 +6,9 @@ namespace Cijber\GraphicsToolkit;
use Cijber\GraphicsToolkit\Consts\GLConsts; use Cijber\GraphicsToolkit\Consts\GLConsts;
use FFI; use FFI;
use FFI\CData; use FFI\CData;
use ReflectionClass;
use ReflectionMethod;
use RuntimeException; use RuntimeException;
/**
* @method static void bindVertexArray(int $VAO)
* @method static void bindBuffer(int $type, int $VBO)
* @method static void bufferData(int $type, int $size, $data, int $management)
* @method static void viewport(int $x, int $y, int $width, int $height)
* @method static void enableVertexAttribArray(int $VAO)
* @method static void drawArrays(int $type, int $index, int $count)
* @method static void useProgram($shaderProgram)
* @method static void clear(int $type)
* @method static void clearColor(float $red, float $green, float $blue, float $alpha)
* @method static int createShader(int $type)
* @method static void compileShader(int $shader)
* @method static void attachShader(int $program, int $shader)
* @method static int createProgram()
* @method static void linkProgram(int $program)
* @method static void deleteShader(int $shader)
* @method static int getError()
* @method static void enable(int $flag)
* @method static void debugMessageCallback(callable $callback, $userParam)
* @method static void debugMessageControl(int $source, int $type, int $severity, int $count, $null, bool $enabled)
* @method static void blendFunc(int $sfactor, int $bfactor)
*/
class GL extends GLConsts { class GL extends GLConsts {
public static string $lastCall; public static string $lastCall;
public static FFI $ffi; public static FFI $ffi;
@ -47,36 +23,13 @@ class GL extends GLConsts {
*/ */
public static function init() { public static function init() {
static::$ffi = FFI::load(__DIR__ . "/../headers/gl_generated.h"); static::$ffi = FFI::load(__DIR__ . "/../headers/gl_generated.h");
include_once __DIR__ . "/gl_functions.php";
$reflection = new ReflectionClass(__CLASS__);
$methods = $reflection->getMethods(
ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_STATIC
);
foreach ($methods as $method) {
if (str_contains($method->getDocComment() ?: "", "@GLIgnore")) {
continue;
}
static::$calls[$method->name] = static::getProcAddress(
$method->name
);
}
preg_match_all(
":@method static [a-zA-Z]+ ([a-zA-Z0-9]+):",
$reflection->getDocComment(),
$matches
);
foreach ($matches[1] as $match) {
static::$calls[$match] = static::getProcAddress($match);
}
} }
/** /**
* @GLIgnore * @GLIgnore
*/ */
private static function getProcAddress($name): CData { public static function getProcAddress($name): CData {
$funcname = 'gl' . ucfirst($name); $funcname = 'gl' . ucfirst($name);
$typename = 'FUNC_' . $funcname; $typename = 'FUNC_' . $funcname;
@ -98,211 +51,17 @@ class GL extends GLConsts {
return static::$ffi->cast($typename, $proc); return static::$ffi->cast($typename, $proc);
} }
public static function genBuffers(int $amount, &$ids) { public static function shaderSource(int $shader, array $sources) {
if ($amount > 1) { $lens = [];
$ids = array_fill(0, $amount, 0); $strings = [];
} foreach ($sources as $source) {
$strings[] = Utils::string($source, false);
if (is_array($ids)) { $lens[] = strlen($source);
$arr = &$ids;
} else {
$arr = [&$ids];
}
$items = static::$ffi->new("GLuint[$amount]");
(static::$calls['genBuffers'])($amount, $items);
for ($i = 0; $i < $amount; $i++) {
$arr[$i] = $items[$i];
}
}
public static function genVertexArrays(int $amount, &$ids) {
if ($amount > 1) {
$ids = array_fill(0, $amount, 0);
}
if (is_array($ids)) {
$arr = &$ids;
} else {
$arr = [&$ids];
}
$items = static::$ffi->new("GLuint[$amount]");
(static::$calls['genVertexArrays'])($amount, $items);
for ($i = 0; $i < $amount; $i++) {
$arr[$i] = $items[$i];
}
}
public static function genTextures(int $amount, &$ids) {
if ($amount > 1) {
$ids = array_fill(0, $amount, 0);
}
if (is_array($ids)) {
$arr = &$ids;
} else {
$arr = [&$ids];
}
$items = static::$ffi->new("GLuint[$amount]");
(static::$calls['genTextures'])($amount, $items);
for ($i = 0; $i < $amount; $i++) {
$arr[$i] = $items[$i];
}
}
/**
* @GLIgnore
*/
public static function __callStatic($name, $arguments) {
if ( ! isset(static::$calls[$name])) {
static::$calls[$name] = static::getProcAddress($name);
}
static::$lastCall = $name;
return (static::$calls[$name])(...$arguments);
}
public static function vertexAttribPointer(
int $index,
int $size,
int $type,
bool $normalized,
int $stride,
int $pointer
) {
$pointerC = static::$ffi->new('long long');
$pointerC->cdata = $pointer;
$p = static::$ffi->cast(
'void*',
$pointerC
);
(static::$calls['vertexAttribPointer'])(
$index,
$size,
$type,
$normalized ? 1 : 0,
$stride,
$p,
);
}
public static function getShaderiv(
int $shader,
int $type,
&$params
) {
$paramsC = static::$ffi->new('GLint');
(static::$calls['getShaderiv'])(
$shader,
$type,
FFI::addr($paramsC)
);
$params = $paramsC->cdata;
}
public static function getProgramiv(
int $program,
int $type,
&$params
) {
$paramsC = static::$ffi->new('GLint');
(static::$calls['getProgramiv'])(
$program,
$type,
FFI::addr($paramsC)
);
$params = $paramsC->cdata;
}
public static function getProgramInfoLog(
int $program,
&$log,
int $maxLength = 512
) {
$logC = static::$ffi->new("char[$maxLength]");
$actualLength = static::$ffi->new("GLsizei");
(static::$calls['getProgramInfoLog'])(
$program,
$maxLength,
FFI::addr($actualLength),
$logC,
);
$log = FFI::string($logC, $actualLength->cdata);
}
public static function getShaderInfoLog(
int $shader,
null|string &$log = null,
int $maxLength = 512
) {
$logC = static::$ffi->new(FFI::arrayType(FFI::type("char"), [$maxLength]));
$actualLength = static::$ffi->new("GLsizei");
(static::$calls['getShaderInfoLog'])(
$shader,
$maxLength,
FFI::addr($actualLength),
$logC,
);
$log = FFI::string($logC, $actualLength->cdata);
}
public static function shaderSource(
int $shader,
int $count,
string $source,
?array $offsets
) {
$item = null;
if (is_array($offsets) && count($offsets) > 0) {
$item = static::$ffi->new('GLint[' . count($offsets) . ']');
for ($i = 0; $i < count($offsets); $i++) {
$item[$i] = $offsets[$i];
}
} }
$sourceConst = Utils::constString($source . "\0"); $arrays = Utils::arrayOf('char*', $strings);
$lengths = Utils::arrayOf('int32_t', $lens);
(static::$calls['shaderSource'])(
$shader,
$count,
FFI::addr($sourceConst),
$item,
);
}
/**
* @GLIgnore
*/
public static function getInteger(int $item): int {
return static::getIntegerv($item)[0];
}
public static function getIntegerv(int $item, int $values = 1): array {
$t = static::$ffi->new(FFI::arrayType(static::$ffi->type("GLint"), [$values]));
(static::$calls['getIntegerv'])($item, $t);
$arr = [];
for ($i = 0; $i < $values; $i++) {
$arr[$i] = $t[$i];
}
return $arr; glShaderSource($shader, count($sources), $arrays, $lengths);
} }
} }

@ -14,7 +14,7 @@ class Utils {
static function ffi(): FFI { static function ffi(): FFI {
if (static::$ffi === null) { if (static::$ffi === null) {
static::$ffi = FFI::cdef(""); static::$ffi = FFI::cdef("extern size_t malloc (size_t);");
} }
return static::$ffi; return static::$ffi;
@ -38,12 +38,10 @@ class Utils {
return $arr; return $arr;
} }
public static function string(string $input): FFI\CData { public static function string(string $input, bool $owned = true): FFI\CData {
$ffi = static::ffi(); $ffi = static::ffi();
$data = $ffi->new('char[' . strlen($input) . ']'); $data = $ffi->new('char[' . strlen($input) . ']', $owned);
for ($i = 0; $i < strlen($input); $i++) { FFI::memcpy($data, $input, strlen($input));
$data[$i] = $input[$i];
}
return $data; return $data;
} }
@ -68,13 +66,32 @@ class Utils {
return FFI::sizeof($type); return FFI::sizeof($type);
} }
public static function ptr(int $offset): FFI\CData {
$val = GL::$ffi->new("long long", false);
$val->cdata = $offset;
return GL::$ffi->cast('void*', $val);
}
public static function null(): FFI\CData { public static function null(): FFI\CData {
if (static::$null === null) { if ( ! isset(static::$null)) {
$val = FFI::new("usize"); static::$null = self::ptr(0);
$val->cdata = 0;
static::$null = FFI::cast('void *', $val);
} }
return static::$null; return static::$null;
} }
public static function pointer(&$data = null, $type = null): FFI\CData {
if ($type === null) {
$type = "void*";
}
$data = self::$ffi->new($type);
return FFI::addr($data);
}
public static function stringBuffer(&$infoLog, int $bufSize = 4096) {
return $infoLog = self::$ffi->new('char[' . $bufSize . ']');
}
} }

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save