gl_common: implement image_op

Implement image processing in gl_compose using a frag shader.
gl_image_op is used to set flags corresponds to what processing is
needed for a texture.

Also implement proper reference counting for textures.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2019-03-09 14:12:53 +00:00
parent 6ff0facae6
commit 0a2dd8aa72
3 changed files with 48 additions and 40 deletions

View File

@@ -39,6 +39,8 @@
} \
while (0)
#define GLSL(version, ...) "#version " #version "\n" #__VA_ARGS__
GLuint gl_create_shader(GLenum shader_type, const char *shader_str) {
log_trace("===\n%s\n===", shader_str);
@@ -366,22 +368,6 @@ bool gl_dim_reg(session_t *ps, int dx, int dy, int width, int height, float z,
return true;
}
static inline int gl_gen_texture(GLenum tex_tgt, int width, int height, GLuint *tex) {
glGenTextures(1, tex);
if (!*tex)
return -1;
glEnable(tex_tgt);
glBindTexture(tex_tgt, *tex);
glTexParameteri(tex_tgt, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tex_tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(tex_tgt, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(tex_tgt, 0);
return 0;
}
#if 0
/**
* Blur contents in a particular region.
@@ -606,8 +592,8 @@ GLuint glGetUniformLocationChecked(GLuint p, const char *name) {
/**
* Load a GLSL main program from shader strings.
*/
int gl_win_shader_from_string(session_t *ps, const char *vshader_str,
const char *fshader_str, gl_win_shader_t *ret) {
static int gl_win_shader_from_string(const char *vshader_str, const char *fshader_str,
gl_win_shader_t *ret) {
// Build program
ret->prog = gl_create_program_from_str(vshader_str, fshader_str);
if (!ret->prog) {
@@ -798,6 +784,22 @@ err:
}
#endif
// clang-format off
const char *win_shader_glsl = GLSL(110,
uniform float opacity;
uniform bool invert_color;
uniform sampler2D tex;
void main() {
vec4 c = texture2D(tex, gl_TexCoord[0].xy);
if (invert_color)
c = vec4(c.aaa - c.rgb, c.a);
c *= opacity;
gl_FragColor = c;
}
);
// clang-format on
bool gl_init(struct gl_data *gd, session_t *ps) {
// Initialize GLX data structure
for (int i = 0; i < MAX_BLUR_PASS; ++i) {
@@ -846,6 +848,7 @@ bool gl_init(struct gl_data *gd, session_t *ps) {
// Initialize blur filters
// gl_create_blur_filters(ps, gd->blur_shader, &gd->cap);
gl_win_shader_from_string(NULL, win_shader_glsl, &gd->win_shader);
return true;
}
@@ -881,6 +884,7 @@ GLuint gl_new_texture(GLenum target) {
return 0;
}
glEnable(target);
glBindTexture(target, texture);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -894,16 +898,18 @@ GLuint gl_new_texture(GLenum target) {
/// stub for backend_operations::image_op
bool gl_image_op(backend_t *base, enum image_operations op, void *image_data,
const region_t *reg_op, const region_t *reg_visible, void *arg) {
struct gl_texture *tex = image_data;
switch (op) {
case IMAGE_OP_INVERT_COLOR_ALL: tex->color_inverted = true; break;
case IMAGE_OP_DIM_ALL: log_warn("IMAGE_OP_DIM_ALL not implemented yet"); break;
case IMAGE_OP_APPLY_ALPHA_ALL: tex->opacity *= *(double *)arg; break;
case IMAGE_OP_APPLY_ALPHA:
log_warn("IMAGE_OP_APPLY_ALPHA not implemented yet");
break;
}
return true;
}
/// stub for backend_operations::copy
void *gl_copy(backend_t *base, const void *image_data, const region_t *reg_visible) {
struct gl_texture *t = (void *)image_data;
t->refcount++;
return (void *)image_data;
}
bool gl_is_image_transparent(backend_t *base, void *image_data) {
gl_texture_t *img = image_data;
return img->has_alpha;