diff --git a/CMakeLists.txt b/CMakeLists.txt index 2570b3c0..fbd63e05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,5 +63,6 @@ add_subdirectory(backend) add_subdirectory(common) add_subdirectory(types) add_subdirectory(session) +add_subdirectory(render) add_subdirectory(example) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index b4d63eb0..e8f7ec72 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -20,4 +20,5 @@ add_executable(rotation target_link_libraries(rotation wlr-backend wlr-session + wlr-render ) diff --git a/example/rotation.c b/example/rotation.c index c7b253be..361cfb8c 100644 --- a/example/rotation.c +++ b/example/rotation.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -15,29 +16,24 @@ #include "cat.h" static const GLchar vert_src[] = -"#version 310 es\n" -"precision mediump float;\n" -"layout(location = 0) uniform mat4 transform;\n" -"layout(location = 0) in vec2 pos;\n" -"layout(location = 1) in vec2 texcoord;\n" -"out vec2 v_texcoord;\n" +"uniform mat4 proj;\n" +"attribute vec2 pos;\n" +"attribute vec2 texcoord;\n" +"varying vec2 v_texcoord;\n" "void main() {\n" +" gl_Position = proj * vec4(pos, 0.0, 1.0);\n" " v_texcoord = texcoord;\n" -" gl_Position = transform * vec4(pos, 0.0, 1.0);\n" "}\n"; static const GLchar frag_src[] = -"#version 310 es\n" "precision mediump float;\n" -"in vec2 v_texcoord;\n" -"out vec4 color;\n" -"uniform sampler2D texture0;\n" +"varying vec2 v_texcoord;\n" +"uniform sampler2D tex;\n" "void main() {\n" -" color = texture(texture0, v_texcoord);\n" +" gl_FragColor = texture2D(tex, v_texcoord);\n" "}\n"; struct state { - struct timespec last_frame; struct wl_listener output_add; struct wl_listener output_remove; struct wl_list outputs; @@ -53,10 +49,13 @@ struct state { }; struct output_state { + struct timespec last_frame; struct wl_list link; struct wlr_output *output; struct state *state; struct wl_listener frame; + float x, y; + float vel_x, vel_y; }; struct output_config { @@ -120,14 +119,6 @@ static void init_gl(struct gl *gl) { 0, 0, 0, 0, // top left 0, 1, 0, 1, // bottom left }; - // Temporary - for (size_t i = 0; i < sizeof(verticies) / sizeof(verticies[0]); i += 4) { - verticies[i] *= 128.0f; - verticies[i + 1] *= 128.0f; - verticies[i] += 128; - verticies[i + 1] += 128; - } - // End temp GLuint indicies[] = { 0, 1, 3, 1, 2, 3, @@ -164,14 +155,16 @@ static void cleanup_gl(struct gl *gl) { static void output_frame(struct wl_listener *listener, void *data) { struct output_state *ostate = wl_container_of(listener, ostate, frame); + struct wlr_output *output = ostate->output; struct state *s = ostate->state; - glClearColor(0, 0, 0, 1); + glClearColor(0.25f, 0.25f, 0.25f, 1); glClear(GL_COLOR_BUFFER_BIT); - int32_t width = ostate->output->width; - int32_t height = ostate->output->height; + int32_t width = output->width; + int32_t height = output->height; glViewport(0, 0, width, height); + wlr_output_effective_resolution(output, &width, &height); glUseProgram(s->gl.prog); @@ -183,13 +176,33 @@ static void output_frame(struct wl_listener *listener, void *data) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glUniformMatrix4fv(0, 1, GL_TRUE, ostate->output->transform_matrix); + float world[16], final[16]; + wlr_matrix_identity(&final); + wlr_matrix_translate(&world, ostate->x, ostate->y, 0); + wlr_matrix_mul(&final, &world, &final); + wlr_matrix_scale(&world, 128, 128, 1); + wlr_matrix_mul(&final, &world, &final); + wlr_matrix_mul(&output->transform_matrix, &final, &final); + glUniformMatrix4fv(0, 1, GL_TRUE, final); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - s->last_frame = now; + long ms = (now.tv_sec - ostate->last_frame.tv_sec) * 1000 + + (now.tv_nsec - ostate->last_frame.tv_nsec) / 1000000; + float seconds = ms / 1000.0f; + ostate->x += ostate->vel_x * seconds; + ostate->y += ostate->vel_y * seconds; + if (ostate->y > height - 128) { + ostate->vel_y = -ostate->vel_y; + } else { + ostate->vel_y += 50 * seconds; + } + if (ostate->x > width - 128 || ostate->x < 0) { + ostate->vel_x = -ostate->vel_x; + } + ostate->last_frame = now; } static void output_add(struct wl_listener *listener, void *data) { @@ -201,9 +214,13 @@ static void output_add(struct wl_listener *listener, void *data) { struct output_state *ostate = calloc(1, sizeof(struct output_state)); + clock_gettime(CLOCK_MONOTONIC, &ostate->last_frame); ostate->output = output; ostate->state = state; ostate->frame.notify = output_frame; + ostate->x = ostate->y = 0; + ostate->vel_x = 100; + ostate->vel_y = 0; struct output_config *conf; wl_list_for_each(conf, &state->config, link) { @@ -314,7 +331,6 @@ int main(int argc, char *argv[]) { wl_list_init(&state.config); wl_list_init(&state.output_add.link); wl_list_init(&state.output_remove.link); - clock_gettime(CLOCK_MONOTONIC, &state.last_frame); parse_args(argc, argv, &state.config); @@ -344,7 +360,7 @@ int main(int argc, char *argv[]) { struct wl_event_source *timer = wl_event_loop_add_timer(event_loop, timer_done, &done); - wl_event_source_timer_update(timer, 10000); + wl_event_source_timer_update(timer, 30000); while (!done) { wl_event_loop_dispatch(event_loop, 0); diff --git a/include/wlr/render/matrix.h b/include/wlr/render/matrix.h new file mode 100644 index 00000000..a1053b00 --- /dev/null +++ b/include/wlr/render/matrix.h @@ -0,0 +1,10 @@ +#ifndef _WLR_RENDER_MATRIX_H +#define _WLR_RENDER_MATRIX_H + +void wlr_matrix_identity(float (*output)[16]); +void wlr_matrix_translate(float (*output)[16], float x, float y, float z); +void wlr_matrix_scale(float (*output)[16], float x, float y, float z); +void wlr_matrix_rotate(float (*output)[16], float radians); +void wlr_matrix_mul(float (*x)[16], float (*y)[16], float (*product)[16]); + +#endif diff --git a/include/wlr/types.h b/include/wlr/types.h index a3afb258..51ea45cf 100644 --- a/include/wlr/types.h +++ b/include/wlr/types.h @@ -47,5 +47,7 @@ bool wlr_output_set_mode(struct wlr_output *output, void wlr_output_transform(struct wlr_output *output, enum wl_output_transform transform); void wlr_output_destroy(struct wlr_output *output); +void wlr_output_effective_resolution(struct wlr_output *output, + int *width, int *height); #endif diff --git a/render/CMakeLists.txt b/render/CMakeLists.txt new file mode 100644 index 00000000..16d9e8d2 --- /dev/null +++ b/render/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(wlr-render STATIC + matrix.c +) diff --git a/render/matrix.c b/render/matrix.c new file mode 100644 index 00000000..7d111c38 --- /dev/null +++ b/render/matrix.c @@ -0,0 +1,83 @@ +#include +#include +#include + +/* Obtains the index for the given row/column */ +static inline int mind(int row, int col) { + return (row - 1) * 4 + col - 1; +} + +void wlr_matrix_identity(float (*output)[16]) { + static const float identity[16] = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + memcpy(*output, identity, sizeof(identity)); +} + +void wlr_matrix_translate(float (*output)[16], float x, float y, float z) { + wlr_matrix_identity(output); + (*output)[mind(1, 4)] = x; + (*output)[mind(2, 4)] = y; + (*output)[mind(3, 4)] = z; +} + +void wlr_matrix_scale(float (*output)[16], float x, float y, float z) { + wlr_matrix_identity(output); + (*output)[mind(1, 1)] = x; + (*output)[mind(2, 2)] = y; + (*output)[mind(3, 3)] = z; +} + +void wlr_matrix_rotate(float (*output)[16], float radians) { + wlr_matrix_identity(output); + float _cos = cosf(radians); + float _sin = sinf(radians); + (*output)[mind(1, 1)] = _cos; + (*output)[mind(1, 2)] = _sin; + (*output)[mind(2, 1)] = -_sin; + (*output)[mind(2, 2)] = _cos; +} + +void wlr_matrix_mul(float (*x)[16], float (*y)[16], float (*product)[16]) { + float _product[16] = { + (*x)[mind(1, 1)] * (*y)[mind(1, 1)] + (*x)[mind(1, 2)] * (*y)[mind(2, 1)] + + (*x)[mind(1, 3)] * (*y)[mind(3, 1)] + (*x)[mind(1, 4)] * (*y)[mind(4, 1)], + (*x)[mind(1, 1)] * (*y)[mind(1, 2)] + (*x)[mind(1, 2)] * (*y)[mind(2, 2)] + + (*x)[mind(1, 3)] * (*y)[mind(3, 2)] + (*x)[mind(1, 4)] * (*y)[mind(4, 2)], + (*x)[mind(1, 1)] * (*y)[mind(1, 3)] + (*x)[mind(1, 2)] * (*y)[mind(2, 3)] + + (*x)[mind(1, 3)] * (*y)[mind(3, 3)] + (*x)[mind(1, 4)] * (*y)[mind(4, 3)], + (*x)[mind(1, 1)] * (*y)[mind(1, 4)] + (*x)[mind(1, 2)] * (*y)[mind(2, 4)] + + (*x)[mind(1, 4)] * (*y)[mind(3, 4)] + (*x)[mind(1, 4)] * (*y)[mind(4, 4)], + + (*x)[mind(2, 1)] * (*y)[mind(1, 1)] + (*x)[mind(2, 2)] * (*y)[mind(2, 1)] + + (*x)[mind(2, 3)] * (*y)[mind(3, 1)] + (*x)[mind(2, 4)] * (*y)[mind(4, 1)], + (*x)[mind(2, 1)] * (*y)[mind(1, 2)] + (*x)[mind(2, 2)] * (*y)[mind(2, 2)] + + (*x)[mind(2, 3)] * (*y)[mind(3, 2)] + (*x)[mind(2, 4)] * (*y)[mind(4, 2)], + (*x)[mind(2, 1)] * (*y)[mind(1, 3)] + (*x)[mind(2, 2)] * (*y)[mind(2, 3)] + + (*x)[mind(2, 3)] * (*y)[mind(3, 3)] + (*x)[mind(2, 4)] * (*y)[mind(4, 3)], + (*x)[mind(2, 1)] * (*y)[mind(1, 4)] + (*x)[mind(2, 2)] * (*y)[mind(2, 4)] + + (*x)[mind(2, 4)] * (*y)[mind(3, 4)] + (*x)[mind(2, 4)] * (*y)[mind(4, 4)], + + (*x)[mind(3, 1)] * (*y)[mind(1, 1)] + (*x)[mind(3, 2)] * (*y)[mind(2, 1)] + + (*x)[mind(3, 3)] * (*y)[mind(3, 1)] + (*x)[mind(3, 4)] * (*y)[mind(4, 1)], + (*x)[mind(3, 1)] * (*y)[mind(1, 2)] + (*x)[mind(3, 2)] * (*y)[mind(2, 2)] + + (*x)[mind(3, 3)] * (*y)[mind(3, 2)] + (*x)[mind(3, 4)] * (*y)[mind(4, 2)], + (*x)[mind(3, 1)] * (*y)[mind(1, 3)] + (*x)[mind(3, 2)] * (*y)[mind(2, 3)] + + (*x)[mind(3, 3)] * (*y)[mind(3, 3)] + (*x)[mind(3, 4)] * (*y)[mind(4, 3)], + (*x)[mind(3, 1)] * (*y)[mind(1, 4)] + (*x)[mind(3, 2)] * (*y)[mind(2, 4)] + + (*x)[mind(3, 4)] * (*y)[mind(3, 4)] + (*x)[mind(3, 4)] * (*y)[mind(4, 4)], + + (*x)[mind(4, 1)] * (*y)[mind(1, 1)] + (*x)[mind(4, 2)] * (*y)[mind(2, 1)] + + (*x)[mind(4, 3)] * (*y)[mind(3, 1)] + (*x)[mind(4, 4)] * (*y)[mind(4, 1)], + (*x)[mind(4, 1)] * (*y)[mind(1, 2)] + (*x)[mind(4, 2)] * (*y)[mind(2, 2)] + + (*x)[mind(4, 3)] * (*y)[mind(3, 2)] + (*x)[mind(4, 4)] * (*y)[mind(4, 2)], + (*x)[mind(4, 1)] * (*y)[mind(1, 3)] + (*x)[mind(4, 2)] * (*y)[mind(2, 3)] + + (*x)[mind(4, 3)] * (*y)[mind(3, 3)] + (*x)[mind(4, 4)] * (*y)[mind(4, 3)], + (*x)[mind(4, 1)] * (*y)[mind(1, 4)] + (*x)[mind(4, 2)] * (*y)[mind(2, 4)] + + (*x)[mind(4, 4)] * (*y)[mind(3, 4)] + (*x)[mind(4, 4)] * (*y)[mind(4, 4)], + }; + memcpy(*product, _product, sizeof(_product)); +} diff --git a/types/wlr_output.c b/types/wlr_output.c index 0cf5c718..20503030 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -100,3 +100,15 @@ void wlr_output_destroy(struct wlr_output *output) { list_free(output->modes); free(output); } + +void wlr_output_effective_resolution(struct wlr_output *output, + int *width, int *height) { + // TODO: Scale factor + if (output->transform % 2 == 1) { + *width = output->height; + *height = output->width; + } else { + *width = output->width; + *height = output->height; + } +}