diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index a60853926..fff2e49bb 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -53,3 +53,15 @@ target_link_libraries(touch wlr-render ${XKBCOMMON_LIBRARIES} ) + +add_executable(tablet + tablet.c + shared.c +) + +target_link_libraries(tablet + wlr-backend + wlr-session + wlr-render + ${XKBCOMMON_LIBRARIES} +) diff --git a/example/tablet.c b/example/tablet.c new file mode 100644 index 000000000..9a4984380 --- /dev/null +++ b/example/tablet.c @@ -0,0 +1,63 @@ +#define _POSIX_C_SOURCE 199309L +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shared.h" +#include "cat.h" + +struct sample_state { + struct wlr_renderer *renderer; +}; + +static void handle_output_frame(struct output_state *output, struct timespec *ts) { + struct compositor_state *state = output->compositor; + struct sample_state *sample = state->data; + struct wlr_output *wlr_output = output->output; + + wlr_renderer_begin(sample->renderer, wlr_output); + + float matrix[16]; + float color[4] = { 0, 1.0, 0, 1.0 }; + wlr_matrix_scale(&matrix, 128, 128, 1); + wlr_matrix_mul(&wlr_output->transform_matrix, &matrix, &matrix); + wlr_render_colored_ellipse(sample->renderer, &color, &matrix); + + wlr_renderer_end(sample->renderer); +} + +static void handle_keyboard_key(struct keyboard_state *kbstate, + xkb_keysym_t sym, enum wlr_key_state key_state) { + if (sym == XKB_KEY_Escape) { + kbstate->compositor->exit = true; + } +} + +int main(int argc, char *argv[]) { + struct sample_state state = { 0 }; + struct compositor_state compositor; + + compositor_init(&compositor); + compositor.output_frame_cb = handle_output_frame; + compositor.keyboard_key_cb = handle_keyboard_key; + + state.renderer = wlr_gles3_renderer_init(); + + compositor.data = &state; + compositor_run(&compositor); + + wlr_renderer_destroy(state.renderer); +} diff --git a/include/render/gles3.h b/include/render/gles3.h index 5efb197e2..9acc10881 100644 --- a/include/render/gles3.h +++ b/include/render/gles3.h @@ -13,6 +13,9 @@ struct wlr_surface_state { struct wlr_surface *gles3_surface_init(); +extern const GLchar quad_vertex_src[]; +extern const GLchar quad_fragment_src[]; +extern const GLchar ellipse_fragment_src[]; extern const GLchar vertex_src[]; extern const GLchar fragment_src_RGB[]; extern const GLchar fragment_src_RGBA[]; diff --git a/include/wlr/render.h b/include/wlr/render.h index 88aa615e1..3c0bd04b6 100644 --- a/include/wlr/render.h +++ b/include/wlr/render.h @@ -28,6 +28,16 @@ struct wlr_surface *wlr_render_surface_init(struct wlr_renderer *r); */ bool wlr_render_with_matrix(struct wlr_renderer *r, struct wlr_surface *surface, const float (*matrix)[16]); +/** + * Renders a solid quad in the specified color. + */ +void wlr_render_colored_quad(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]); +/** + * Renders a solid ellipse in the specified color. + */ +void wlr_render_colored_ellipse(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]); /** * Destroys this wlr_renderer. Surfaces must be destroyed separately. */ diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 80471ac8c..a934f49e7 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -19,6 +19,10 @@ struct wlr_renderer_impl { struct wlr_surface *(*surface_init)(struct wlr_renderer_state *state); bool (*render_with_matrix)(struct wlr_renderer_state *state, struct wlr_surface *surface, const float (*matrix)[16]); + void (*render_quad)(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]); + void (*render_ellipse)(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]); void (*destroy)(struct wlr_renderer_state *state); }; diff --git a/render/gles3/renderer.c b/render/gles3/renderer.c index 74754d1b3..b00561934 100644 --- a/render/gles3/renderer.c +++ b/render/gles3/renderer.c @@ -13,6 +13,8 @@ static struct { bool initialized; GLuint rgb, rgba; + GLuint quad; + GLuint ellipse; } shaders; static GLuint vao, vbo, ebo; @@ -28,6 +30,9 @@ static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) { GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen)); GLchar msg[loglen]; GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg)); + wlr_log(L_ERROR, "Shader compilation failed"); + wlr_log(L_ERROR, "%s", msg); + exit(1); return false; } return true; @@ -60,6 +65,12 @@ static void init_default_shaders() { if (!compile_program(vertex_src, fragment_src_RGBA, &shaders.rgba)) { goto error; } + if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) { + goto error; + } + if (!compile_program(quad_vertex_src, ellipse_fragment_src, &shaders.ellipse)) { + goto error; + } return; error: wlr_log(L_ERROR, "Failed to set up default shaders!"); @@ -141,6 +152,28 @@ static bool wlr_gles3_render_surface(struct wlr_renderer_state *state, return true; } +static void wlr_gles3_render_quad(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]) { + GL_CALL(glUseProgram(shaders.quad)); + GL_CALL(glBindVertexArray(vao)); + GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo)); + GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)); + GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix)); + GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3])); + GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)); +} + +static void wlr_gles3_render_ellipse(struct wlr_renderer_state *state, + const float (*color)[4], const float (*matrix)[16]) { + GL_CALL(glUseProgram(shaders.ellipse)); + GL_CALL(glBindVertexArray(vao)); + GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, vbo)); + GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo)); + GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix)); + GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3])); + GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)); +} + static void wlr_gles3_destroy(struct wlr_renderer_state *state) { // no-op } @@ -150,6 +183,8 @@ static struct wlr_renderer_impl wlr_renderer_impl = { .end = wlr_gles3_end, .surface_init = wlr_gles3_surface_init, .render_with_matrix = wlr_gles3_render_surface, + .render_quad = wlr_gles3_render_quad, + .render_ellipse = wlr_gles3_render_ellipse, .destroy = wlr_gles3_destroy }; diff --git a/render/gles3/shaders.c b/render/gles3/shaders.c index f53ef385c..dd7f790fe 100644 --- a/render/gles3/shaders.c +++ b/render/gles3/shaders.c @@ -1,28 +1,63 @@ #include "render/gles3.h" #include +// Colored quads +const GLchar quad_vertex_src[] = +"uniform mat4 proj;" +"uniform vec4 color;" +"attribute vec2 pos;" +"attribute vec2 texcoord;" +"varying vec4 v_color;" +"varying vec2 v_texcoord;" +"void main() {" +" gl_Position = proj * vec4(pos, 0.0, 1.0);" +" v_color = color;" +" v_texcoord = texcoord;" +"}"; + +const GLchar quad_fragment_src[] = +"precision mediump float;" +"varying vec4 v_color;" +"varying vec2 v_texcoord;" +"void main() {" +" gl_FragColor = v_color;" +"}"; + +// Colored ellipses (TODO) + +const GLchar ellipse_fragment_src[] = +"precision mediump float;" +"varying vec4 v_color;" +"varying vec2 v_texcoord;" +"void main() {" +" float l = length(v_texcoord - vec2(0.5, 0.5));" +" if (l > 0.5) discard;" +" gl_FragColor = v_color;" +"}"; + +// Textured quads const GLchar vertex_src[] = -"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" -"}\n"; +"uniform mat4 proj;" +"attribute vec2 pos;" +"attribute vec2 texcoord;" +"varying vec2 v_texcoord;" +"void main() {" +" gl_Position = proj * vec4(pos, 0.0, 1.0);" +" v_texcoord = texcoord;" +"}"; const GLchar fragment_src_RGB[] = -"precision mediump float;\n" -"varying vec2 v_texcoord;\n" -"uniform sampler2D tex;\n" -"void main() {\n" -" gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);\n" -"}\n"; +"precision mediump float;" +"varying vec2 v_texcoord;" +"uniform sampler2D tex;" +"void main() {" +" gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);" +"}"; const GLchar fragment_src_RGBA[] = -"precision mediump float;\n" -"varying vec2 v_texcoord;\n" -"uniform sampler2D tex;\n" -"void main() {\n" -" gl_FragColor = texture2D(tex, v_texcoord);\n" -"}\n"; +"precision mediump float;" +"varying vec2 v_texcoord;" +"uniform sampler2D tex;" +"void main() {" +" gl_FragColor = texture2D(tex, v_texcoord);" +"}"; diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 2fd2fd31e..f48bb3eb2 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -31,3 +31,13 @@ bool wlr_render_with_matrix(struct wlr_renderer *r, struct wlr_surface *surface, const float (*matrix)[16]) { return r->impl->render_with_matrix(r->state, surface, matrix); } + +void wlr_render_colored_quad(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]) { + r->impl->render_quad(r->state, color, matrix); +} + +void wlr_render_colored_ellipse(struct wlr_renderer *r, + const float (*color)[4], const float (*matrix)[16]) { + r->impl->render_ellipse(r->state, color, matrix); +}