~sircmpwn/casa

32cdc838a65719c269079f652ea2e5157d52a96e — Drew DeVault a month ago 0587e73
Render icons with OpenGL :D
5 files changed, 193 insertions(+), 10 deletions(-)

A include/matrix.h
M meson.build
D src/icons.c
A src/matrix.c
M src/render.c
A include/matrix.h => include/matrix.h +19 -0
@@ 0,0 1,19 @@
#ifndef CASA_MATRIX_H
#define CASA_MATRIX_H

struct box {
	int x, y, width, height;
};

void matrix_identity(float mat[static 9]);
void matrix_multiply(float mat[static 9],
		const float a[static 9], const float b[static 9]);
void matrix_transpose(float mat[static 9], const float a[static 9]);
void matrix_translate(float mat[static 9], float x, float y);
void matrix_scale(float mat[static 9], float x, float y);
void matrix_rotate(float mat[static 9], float rad);
void matrix_projection(float mat[static 9], int width, int height);
void matrix_project_box(float mat[static 9], const struct box *box,
		float rotation, const float projection[static 9]);

#endif

M meson.build => meson.build +5 -1
@@ 40,6 40,8 @@ gbm = dependency('gbm')
wayland_client = dependency('wayland-client')
wayland_protocols = dependency('wayland-protocols')

math = cc.find_library('m')

subdir('protocols')

casa = executable('casa',


@@ 47,6 49,7 @@ casa = executable('casa',
		'src/buffers.c',
		'src/input.c',
		'src/main.c',
		'src/matrix.c',
		'src/output.c',
		'src/prerender.c',
		'src/render.c',


@@ 58,9 61,10 @@ casa = executable('casa',
		client_protos,
		drm,
		egl,
		fdicons,
		gbm,
		gles2,
		fdicons,
		math,
		wayland_client,
	],
	include_directories: include_directories('include'),

D src/icons.c => src/icons.c +0 -1
@@ 1,1 0,0 @@
#include <cairo/cairo.h>

A src/matrix.c => src/matrix.c +114 -0
@@ 0,0 1,114 @@
#include <math.h>
#include <string.h>
#include "matrix.h"

void matrix_identity(float mat[static 9]) {
	static const float identity[9] = {
		1.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 1.0f,
	};
	memcpy(mat, identity, sizeof(identity));
}

void matrix_multiply(float mat[static 9], const float a[static 9],
		const float b[static 9]) {
	float product[9];

	product[0] = a[0]*b[0] + a[1]*b[3] + a[2]*b[6];
	product[1] = a[0]*b[1] + a[1]*b[4] + a[2]*b[7];
	product[2] = a[0]*b[2] + a[1]*b[5] + a[2]*b[8];

	product[3] = a[3]*b[0] + a[4]*b[3] + a[5]*b[6];
	product[4] = a[3]*b[1] + a[4]*b[4] + a[5]*b[7];
	product[5] = a[3]*b[2] + a[4]*b[5] + a[5]*b[8];

	product[6] = a[6]*b[0] + a[7]*b[3] + a[8]*b[6];
	product[7] = a[6]*b[1] + a[7]*b[4] + a[8]*b[7];
	product[8] = a[6]*b[2] + a[7]*b[5] + a[8]*b[8];

	memcpy(mat, product, sizeof(product));
}

void matrix_transpose(float mat[static 9], const float a[static 9]) {
	float transposition[9] = {
		a[0], a[3], a[6],
		a[1], a[4], a[7],
		a[2], a[5], a[8],
	};
	memcpy(mat, transposition, sizeof(transposition));
}

void matrix_translate(float mat[static 9], float x, float y) {
	float translate[9] = {
		1.0f, 0.0f, x,
		0.0f, 1.0f, y,
		0.0f, 0.0f, 1.0f,
	};
	matrix_multiply(mat, mat, translate);
}

void matrix_scale(float mat[static 9], float x, float y) {
	float scale[9] = {
		x,    0.0f, 0.0f,
		0.0f, y,    0.0f,
		0.0f, 0.0f, 1.0f,
	};
	matrix_multiply(mat, mat, scale);
}

void matrix_rotate(float mat[static 9], float rad) {
	float rotate[9] = {
		cos(rad), -sin(rad), 0.0f,
		sin(rad),  cos(rad), 0.0f,
		0.0f,      0.0f,     1.0f,
	};
	matrix_multiply(mat, mat, rotate);
}

static const float transform[] = {
	1.0f, 0.0f, 0.0f,
	0.0f, 1.0f, 0.0f,
	0.0f, 0.0f, 1.0f,
};

void matrix_projection(float mat[static 9], int width, int height) {
	memset(mat, 0, sizeof(*mat) * 9);

	const float *t = transform;
	float x = 2.0f / width;
	float y = 2.0f / height;

	// Rotation + reflection
	mat[0] = x * t[0];
	mat[1] = x * t[1];
	mat[3] = y * -t[3];
	mat[4] = y * -t[4];

	// Translation
	mat[2] = -copysign(1.0f, mat[0] + mat[1]);
	mat[5] = -copysign(1.0f, mat[3] + mat[4]);

	// Identity
	mat[8] = 1.0f;
}

void matrix_project_box(float mat[static 9], const struct box *box,
		float rotation, const float projection[static 9]) {
	int x = box->x;
	int y = box->y;
	int width = box->width;
	int height = box->height;

	matrix_identity(mat);
	matrix_translate(mat, x, y);

	if (rotation != 0) {
		matrix_translate(mat, width/2, height/2);
		matrix_rotate(mat, rotation);
		matrix_translate(mat, -width/2, -height/2);
	}

	matrix_scale(mat, width, height);
	matrix_multiply(mat, projection, mat);
}

M src/render.c => src/render.c +55 -8
@@ 1,8 1,11 @@
#include <GLES2/gl2.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include "buffers.h"
#include "casa.h"
#include "matrix.h"
#include "shaders.h"
#include "surface.h"

/*


@@ 14,7 17,8 @@
 * - Implement inertia in scrolling motion
 */
static void
render_icons(struct casa_buffer *buffer, double progress, int y_offs)
render_icons(struct casa_surface *surface,
		struct casa_buffer *buffer, double progress, int y_offs)
{
	const int width = 128, height = 128;
	const int nrows = 16, ncols = 4;


@@ 22,17 26,60 @@ render_icons(struct casa_buffer *buffer, double progress, int y_offs)
	int x_margin = (((buffer->width - gutter * 2) / ncols) - width) / 2;
	int y_margin = 32;

	glEnable(GL_SCISSOR_TEST);
	glClearColor(1.0f * progress, 0.0f, 0.0f, progress);
	float projection[9], matrix[9], transposition[9];
	const struct casa_shaders *shaders = &surface->casa->shaders;
	GLuint tex = surface->casa->test_icon;
	glUseProgram(shaders->textured_quad.program);
	glUniform1i(shaders->textured_quad.tex, 0);
	glUniform1f(shaders->textured_quad.alpha, progress > 1.0 ? 1.0 : progress);
	glUniform1i(shaders->textured_quad.invert_y, 0);

	matrix_projection(projection, buffer->width, buffer->height);
	GLfloat verts[] = {
		1, 0, // top right
		0, 0, // top left
		1, 1, // bottom right
		0, 1, // bottom left
	};
	GLfloat texcoord[] = {
		1, 0, // top right
		0, 0, // top left
		1, 1, // bottom right
		0, 1, // bottom left
	};

	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);

	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);

	for (int row = 0; row < nrows; ++row) {
		for (int col = 0; col < ncols; ++col) {
			int x = gutter + x_margin + col * (width + x_margin * 2);
			int y = gutter * 2 + row * (height + y_margin);
			glScissor(x, y + y_offs, width, height);
			glClear(GL_COLOR_BUFFER_BIT);
			(void)x; (void)y;

			struct box box = {
				.x = x,
				.y = buffer->height - height - (y + y_offs),
				.width = width,
				.height = height,
			};
			matrix_project_box(matrix, &box, 0, projection);
			matrix_transpose(transposition, matrix);

			glUniformMatrix3fv(shaders->textured_quad.proj,
					1, GL_FALSE, transposition);
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, tex);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
		}
	}
	glScissor(0, 0, buffer->width, buffer->height);

	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
}

static void


@@ 45,7 92,7 @@ casa_render_idle(struct casa_surface *surface,

	const int height = 128;
	int y_offs = (int)((1.0 - progress) * (height / 0.5));
	render_icons(buffer, progress, y_offs);
	render_icons(surface, buffer, progress, y_offs);
}

static void


@@ 62,7 109,7 @@ casa_render_browse(struct casa_surface *surface,
		height /= 0.5;
	}
	int y_offs = (int)((1.0 - progress) * height);
	render_icons(buffer, progress, y_offs);
	render_icons(surface, buffer, progress, y_offs);
}

struct wl_buffer *