Compare commits

...

4 Commits

5 changed files with 190 additions and 45 deletions

View File

@ -1,11 +1,30 @@
SOURCES = cpp/opengl/render_context_glx.cpp cpp/opengl/render_opengles.cpp cpp/math.cpp # Copyright (C) 2022 RozK
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
SOURCES = \
cpp/opengl/render_context_glx.cpp \
cpp/opengl/render_opengles.cpp \
cpp/events/events_x11.cpp \
cpp/math.cpp
OUTPUTFILE = engine.so OUTPUTFILE = engine.so
CXXFLAGS = -fpic -Wall -Werror -O2 -flto -fomit-frame-pointer -ffast-math -funroll-loops -fno-rtti -fno-exceptions CXXFLAGS = -fpic -Wall -Werror -O2 -flto -fomit-frame-pointer -ffast-math -funroll-loops -fno-rtti -fno-exceptions
.PHONY: all .PHONY: all
all: clean $(OUTPUTFILE) all: clean $(OUTPUTFILE)
find . -name "*.o" -type f -delete
.PHONY: clean .PHONY: clean
clean: clean:

View File

@ -17,7 +17,7 @@ import ctypes
from array import array from array import array
from pathlib import Path from pathlib import Path
_lib = ctypes.cdll.LoadLibrary(Path(__file__).parent / "engine.so") _engine = ctypes.cdll.LoadLibrary(Path(__file__).parent / "engine.so")
class vec3(ctypes.Structure): class vec3(ctypes.Structure):
_fields_ = ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float) _fields_ = ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float)
@ -85,6 +85,9 @@ INSTANCE_FLAG_VISIBLE = _flag(1)
BATCH_MAX_SIZE = 65536 BATCH_MAX_SIZE = 65536
def buffer(type, size):
return (type * size)()
_vec3p = ctypes.POINTER(vec3) _vec3p = ctypes.POINTER(vec3)
_vec4p = ctypes.POINTER(vec4) _vec4p = ctypes.POINTER(vec4)
_mat3p = ctypes.POINTER(mat3) _mat3p = ctypes.POINTER(mat3)
@ -105,7 +108,7 @@ def _floatp(x):
assert x.typecode == 'f' assert x.typecode == 'f'
return x.buffer_info()[0] return x.buffer_info()[0]
vec3_rotate = _lib.rk_vec3_rotate vec3_rotate = _engine.rk_vec3_rotate
vec3_rotate.argtypes = ( vec3_rotate.argtypes = (
_vec3p, # ret _vec3p, # ret
_vec3p, # vec3 _vec3p, # vec3
@ -113,31 +116,31 @@ vec3_rotate.argtypes = (
ctypes.c_float) # angle ctypes.c_float) # angle
vec3_mul_vec3 = _lib.rk_vec3_mul_vec3 vec3_mul_vec3 = _engine.rk_vec3_mul_vec3
vec3_mul_vec3.argtypes = ( vec3_mul_vec3.argtypes = (
_vec3p, # ret _vec3p, # ret
_vec3p, # a _vec3p, # a
_vec3p) # b _vec3p) # b
mat3_rotation = _lib.rk_mat3_rotation mat3_rotation = _engine.rk_mat3_rotation
mat3_rotation.argtypes = ( mat3_rotation.argtypes = (
_mat3p, # ret _mat3p, # ret
_vec3p, # axis _vec3p, # axis
ctypes.c_float) # angle ctypes.c_float) # angle
mat3_mul_vec3 = _lib.rk_mat3_mul_vec3 mat3_mul_vec3 = _engine.rk_mat3_mul_vec3
mat3_mul_vec3.argtypes = ( mat3_mul_vec3.argtypes = (
_vec3p, # ret _vec3p, # ret
_mat3p, # a _mat3p, # a
_vec3p) # b _vec3p) # b
mat3_mul_mat3 = _lib.rk_mat3_mul_mat3 mat3_mul_mat3 = _engine.rk_mat3_mul_mat3
mat3_mul_mat3.argtypes = ( mat3_mul_mat3.argtypes = (
_mat3p, # ret _mat3p, # ret
_mat3p, # a _mat3p, # a
_mat3p) # b _mat3p) # b
mat4_projection = _lib.rk_mat4_projection mat4_projection = _engine.rk_mat4_projection
mat4_projection.argtypes = ( mat4_projection.argtypes = (
_mat4p, # ret _mat4p, # ret
ctypes.c_float, # hfov ctypes.c_float, # hfov
@ -145,39 +148,39 @@ mat4_projection.argtypes = (
ctypes.c_float, # near ctypes.c_float, # near
ctypes.c_float) # far ctypes.c_float) # far
mat4_lookat = _lib.rk_mat4_lookat mat4_lookat = _engine.rk_mat4_lookat
mat4_lookat.argtypes = ( mat4_lookat.argtypes = (
_mat4p, # ret _mat4p, # ret
_vec3p, # position _vec3p, # position
_vec3p) # lookat _vec3p) # lookat
mat4_mul_vec3 = _lib.rk_mat4_mul_vec3 mat4_mul_vec3 = _engine.rk_mat4_mul_vec3
mat4_mul_vec3.argtypes = ( mat4_mul_vec3.argtypes = (
_vec3p, # ret _vec3p, # ret
_mat4p, # a _mat4p, # a
_vec3p, # b _vec3p, # b
ctypes.c_float) # w ctypes.c_float) # w
mat4_mul_vec4 = _lib.rk_mat4_mul_vec4 mat4_mul_vec4 = _engine.rk_mat4_mul_vec4
mat4_mul_vec4.argtypes = ( mat4_mul_vec4.argtypes = (
_vec4p, # ret _vec4p, # ret
_mat4p, # a _mat4p, # a
_vec4p) # b _vec4p) # b
mat4_mul_mat4 = _lib.rk_mat4_mul_mat4 mat4_mul_mat4 = _engine.rk_mat4_mul_mat4
mat4_mul_mat4.argtypes = ( mat4_mul_mat4.argtypes = (
_mat4p, # ret _mat4p, # ret
_mat4p, # a _mat4p, # a
_mat4p) # b _mat4p) # b
initialize = _lib.rk_initialize initialize = _engine.rk_initialize
initialize.restype = ctypes.c_void_p initialize.restype = ctypes.c_void_p
initialize.argtypes = ( initialize.argtypes = (
ctypes.c_char_p, # name ctypes.c_char_p, # name
ctypes.c_uint, # width ctypes.c_uint, # width
ctypes.c_uint) # height ctypes.c_uint) # height
_load_shader = _lib.rk_load_shader _load_shader = _engine.rk_load_shader
_load_shader.restype = ctypes.c_void_p _load_shader.restype = ctypes.c_void_p
_load_shader.argtypes = ( _load_shader.argtypes = (
ctypes.c_uint, # vert_nlines ctypes.c_uint, # vert_nlines
@ -196,19 +199,19 @@ def load_shader(vert_lines, frag_lines):
vert_nlines, ctypes.addressof(vert_lines), vert_nlines, ctypes.addressof(vert_lines),
frag_nlines, ctypes.addressof(frag_lines)) frag_nlines, ctypes.addressof(frag_lines))
resolve_input = _lib.rk_resolve_input resolve_input = _engine.rk_resolve_input
resolve_input.restype = ctypes.c_void_p resolve_input.restype = ctypes.c_void_p
resolve_input.argtypes = ( resolve_input.argtypes = (
ctypes.c_void_p, # shader ctypes.c_void_p, # shader
ctypes.c_char_p) # name ctypes.c_char_p) # name
resolve_param = _lib.rk_resolve_param resolve_param = _engine.rk_resolve_param
resolve_param.restype = ctypes.c_void_p resolve_param.restype = ctypes.c_void_p
resolve_param.argtypes = ( resolve_param.argtypes = (
ctypes.c_void_p, # shader ctypes.c_void_p, # shader
ctypes.c_char_p) # name ctypes.c_char_p) # name
_create_texture = _lib.rk_create_texture _create_texture = _engine.rk_create_texture
_create_texture.restype = ctypes.c_void_p _create_texture.restype = ctypes.c_void_p
_create_texture.argtypes = ( _create_texture.argtypes = (
ctypes.c_uint, # format ctypes.c_uint, # format
@ -223,7 +226,7 @@ def create_texture(format, width, height, nlevels, flags, pixels):
assert len(pixels) == width * height * max(1, nlevels) * TEXTURE_FORMAT_NELEMS[format] assert len(pixels) == width * height * max(1, nlevels) * TEXTURE_FORMAT_NELEMS[format]
return _create_texture(format, width, height, nlevels, flags, _voidp(pixels)) return _create_texture(format, width, height, nlevels, flags, _voidp(pixels))
_create_triangles = _lib.rk_create_triangles _create_triangles = _engine.rk_create_triangles
_create_triangles.restype = ctypes.c_void_p _create_triangles.restype = ctypes.c_void_p
_create_triangles.argtypes = ( _create_triangles.argtypes = (
ctypes.c_uint, # nvertices ctypes.c_uint, # nvertices
@ -233,7 +236,7 @@ def create_triangles(vertices):
assert len(vertices) % 9 == 0 assert len(vertices) % 9 == 0
return _create_triangles(len(vertices) // 3, _floatp(vertices)) return _create_triangles(len(vertices) // 3, _floatp(vertices))
_create_vertices = _lib.rk_create_vertices _create_vertices = _engine.rk_create_vertices
_create_vertices.restype = ctypes.c_void_p _create_vertices.restype = ctypes.c_void_p
_create_vertices.argtypes = ( _create_vertices.argtypes = (
ctypes.c_char_p, # format ctypes.c_char_p, # format
@ -245,59 +248,59 @@ _create_vertices.argtypes = (
def create_vertices(format, nvertices, vertices, indices): def create_vertices(format, nvertices, vertices, indices):
return _create_vertices(format, nvertices, _ubytep(vertices), len(indices), _ushortp(indices)) return _create_vertices(format, nvertices, _ubytep(vertices), len(indices), _ushortp(indices))
create_batch = _lib.rk_create_batch create_batch = _engine.rk_create_batch
create_batch.restype = ctypes.c_void_p create_batch.restype = ctypes.c_void_p
create_batch.argtypes = ( create_batch.argtypes = (
ctypes.c_void_p, # vertices ctypes.c_void_p, # vertices
ctypes.c_uint, # max_size ctypes.c_uint, # max_size
ctypes.c_char_p) # params_format ctypes.c_char_p) # params_format
begin_frame = _lib.rk_begin_frame begin_frame = _engine.rk_begin_frame
select_shader = _lib.rk_select_shader select_shader = _engine.rk_select_shader
select_shader.argtypes = ( select_shader.argtypes = (
ctypes.c_void_p,) # shader ctypes.c_void_p,) # shader
set_input_float = _lib.rk_set_input_float set_input_float = _engine.rk_set_input_float
set_input_float.argtypes = ( set_input_float.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
ctypes.c_float) # value ctypes.c_float) # value
set_input_vec3 = _lib.rk_set_input_vec3 set_input_vec3 = _engine.rk_set_input_vec3
set_input_vec3.argtypes = ( set_input_vec3.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
_vec3p) # value _vec3p) # value
set_input_mat3 = _lib.rk_set_input_mat3 set_input_mat3 = _engine.rk_set_input_mat3
set_input_mat3.argtypes = ( set_input_mat3.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
_mat3p) # value _mat3p) # value
set_input_mat4 = _lib.rk_set_input_mat4 set_input_mat4 = _engine.rk_set_input_mat4
set_input_mat4.argtypes = ( set_input_mat4.argtypes = (
ctypes.c_void_p, # input ctypes.c_void_p, # input
_mat4p) # value _mat4p) # value
set_param_vec3 = _lib.rk_set_param_vec3 set_param_vec3 = _engine.rk_set_param_vec3
set_param_vec3.argtypes = ( set_param_vec3.argtypes = (
ctypes.c_uint, # layout ctypes.c_uint, # layout
_vec3p) # value _vec3p) # value
select_texture = _lib.rk_select_texture select_texture = _engine.rk_select_texture
select_texture.argtypes = ( select_texture.argtypes = (
ctypes.c_uint, # slot ctypes.c_uint, # slot
ctypes.c_void_p, # texture ctypes.c_void_p, # texture
ctypes.c_void_p) # sampler ctypes.c_void_p) # sampler
draw_triangles = _lib.rk_draw_triangles draw_triangles = _engine.rk_draw_triangles
draw_triangles.argtypes = ( draw_triangles.argtypes = (
ctypes.c_void_p,) # triangles ctypes.c_void_p,) # triangles
select_vertices = _lib.rk_select_vertices select_vertices = _engine.rk_select_vertices
select_vertices.argtypes = ( select_vertices.argtypes = (
ctypes.c_void_p,) # vertices ctypes.c_void_p,) # vertices
draw_batch = _lib.rk_draw_batch draw_batch = _engine.rk_draw_batch
draw_batch.argtypes = ( draw_batch.argtypes = (
ctypes.c_void_p, # batch ctypes.c_void_p, # batch
ctypes.c_uint, # size ctypes.c_uint, # size
@ -305,39 +308,63 @@ draw_batch.argtypes = (
ctypes.POINTER(ctypes.c_uint), # meshes ctypes.POINTER(ctypes.c_uint), # meshes
ctypes.c_void_p) # params ctypes.c_void_p) # params
unselect_vertices = _lib.rk_unselect_vertices unselect_vertices = _engine.rk_unselect_vertices
unselect_vertices.argtypes = ( unselect_vertices.argtypes = (
ctypes.c_void_p,) # vertices ctypes.c_void_p,) # vertices
unselect_texture = _lib.rk_unselect_texture unselect_texture = _engine.rk_unselect_texture
unselect_texture.argtypes = ( unselect_texture.argtypes = (
ctypes.c_uint, # slot ctypes.c_uint, # slot
ctypes.c_void_p) # texture ctypes.c_void_p) # texture
unselect_shader = _lib.rk_unselect_shader unselect_shader = _engine.rk_unselect_shader
unselect_shader.argtypes = ( unselect_shader.argtypes = (
ctypes.c_void_p,) # shader ctypes.c_void_p,) # shader
end_frame = _lib.rk_end_frame end_frame = _engine.rk_end_frame
destroy_batch = _lib.rk_destroy_batch destroy_batch = _engine.rk_destroy_batch
destroy_batch.argtypes = ( destroy_batch.argtypes = (
ctypes.c_void_p,) # batch ctypes.c_void_p,) # batch
destroy_triangles = _lib.rk_destroy_triangles destroy_triangles = _engine.rk_destroy_triangles
destroy_triangles.argtypes = ( destroy_triangles.argtypes = (
ctypes.c_void_p,) # triangles ctypes.c_void_p,) # triangles
destroy_vertices = _lib.rk_destroy_vertices destroy_vertices = _engine.rk_destroy_vertices
destroy_vertices.argtypes = ( destroy_vertices.argtypes = (
ctypes.c_void_p,) # vertices ctypes.c_void_p,) # vertices
destroy_texture = _lib.rk_destroy_texture destroy_texture = _engine.rk_destroy_texture
destroy_texture.argtypes = ( destroy_texture.argtypes = (
ctypes.c_void_p,) # texture ctypes.c_void_p,) # texture
destroy_shader = _lib.rk_destroy_shader destroy_shader = _engine.rk_destroy_shader
destroy_shader.argtypes = ( destroy_shader.argtypes = (
ctypes.c_void_p,) # shader ctypes.c_void_p,) # shader
terminate = _lib.rk_terminate terminate = _engine.rk_terminate
EVENT_KEY_PRESS = 0
EVENT_KEY_RELEASE = 1
class _EventKey(ctypes.Structure):
_fields_ = (
('keycode', ctypes.c_uint),
)
class _AllEvents(ctypes.Union):
_fields_ = (
('key', _EventKey),
)
class Event(ctypes.Structure):
_fields_ = ('type', ctypes.c_uint), ('data', _AllEvents)
consume_events = _engine.rk_consume_events
consume_events.restype = ctypes.c_uint
consume_events.argtypes = (
ctypes.POINTER(Event), # events
ctypes.c_uint) # max_events
flush_events = _engine.rk_flush_events

43
cpp/events.hpp Normal file
View File

@ -0,0 +1,43 @@
// Copyright (C) 2022 RozK
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _RK_ENGINE_EVENTS_H
#define _RK_ENGINE_EVENTS_H
#include "types.hpp"
enum rk_event_type : rk_uint {
RK_EVENT_KEY_PRESS = 0,
RK_EVENT_KEY_RELEASE = 1
};
struct rk_event_key {
rk_uint keycode;
};
struct rk_event {
rk_event_type type;
union {
rk_event_key key;
};
};
RK_EXPORT rk_uint rk_consume_events(
rk_event * events,
rk_uint max_events);
RK_EXPORT void rk_flush_events();
#endif // _RK_ENGINE_EVENTS_H

55
cpp/events/events_x11.cpp Normal file
View File

@ -0,0 +1,55 @@
// Copyright (C) 2022 RozK
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "../events.hpp"
#include <X11/Xlib.h>
unsigned rk_events_mask = KeyPressMask | KeyReleaseMask;
extern Display * rk_display;
extern Window rk_window;
rk_uint rk_consume_events(
rk_event * events,
rk_uint max_events) {
if (!events || !max_events) {
return 0;
}
XEvent x11_event;
unsigned nevents = 0;
for ( ; nevents < max_events ; ++nevents) {
if (XCheckWindowEvent(rk_display, rk_window, rk_events_mask, &x11_event)) {
rk_event & event = events[nevents];
switch (x11_event.type) {
case KeyPress:
event.type = RK_EVENT_KEY_PRESS;
event.key.keycode = x11_event.xkey.keycode;
break;
case KeyRelease:
event.type = RK_EVENT_KEY_RELEASE;
event.key.keycode = x11_event.xkey.keycode;
break;
}
} else {
break;
}
}
return nevents;
}
void rk_flush_events() {
XEvent x11_event;
while (XCheckWindowEvent(rk_display, rk_window, rk_events_mask, &x11_event)) {
}
}

View File

@ -21,9 +21,10 @@
#include <GLES3/gl32.h> #include <GLES3/gl32.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
static Display * rk_display = nullptr; Display * rk_display = nullptr;
Window rk_window = 0;
extern unsigned rk_events_mask;
static Colormap rk_colormap = 0; static Colormap rk_colormap = 0;
static Window rk_window = 0;
static GLXContext rk_context = nullptr; static GLXContext rk_context = nullptr;
static bool rk_error_occured = false; static bool rk_error_occured = false;
@ -146,7 +147,7 @@ rk_window_t rk_create_context(
swa.colormap = rk_colormap; swa.colormap = rk_colormap;
swa.background_pixmap = None; swa.background_pixmap = None;
swa.border_pixel = 0; swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask; swa.event_mask = rk_events_mask;
rk_window = XCreateWindow(rk_display, RootWindow(rk_display, vi->screen), rk_window = XCreateWindow(rk_display, RootWindow(rk_display, vi->screen),
0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &swa); CWBorderPixel | CWColormap | CWEventMask, &swa);