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:
parent
6ff0facae6
commit
0a2dd8aa72
|
@ -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;
|
||||
|
|
|
@ -43,7 +43,7 @@ typedef struct {
|
|||
/// @brief Wrapper of a binded GLX texture.
|
||||
typedef struct gl_texture {
|
||||
double opacity;
|
||||
int refcount;
|
||||
int *refcount;
|
||||
GLuint texture;
|
||||
GLenum target;
|
||||
unsigned width;
|
||||
|
@ -89,12 +89,7 @@ GLuint gl_create_program_from_str(const char *vert_shader_str, const char *frag_
|
|||
void gl_compose(backend_t *, void *ptex, int dst_x, int dst_y, const region_t *reg_tgt,
|
||||
const region_t *reg_visible);
|
||||
|
||||
bool gl_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str,
|
||||
gl_win_shader_t *pprogram);
|
||||
|
||||
unsigned char *gl_take_screenshot(session_t *ps, int *out_length);
|
||||
void gl_resize(struct gl_data *, int width, int height);
|
||||
//bool gl_create_blur_filters(session_t *ps, gl_blur_shader_t *passes, const gl_cap_t *cap);
|
||||
|
||||
GLuint glGetUniformLocationChecked(GLuint p, const char *name);
|
||||
|
||||
|
@ -106,8 +101,6 @@ GLuint gl_new_texture(GLenum target);
|
|||
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);
|
||||
|
||||
void *gl_copy(backend_t *base, const void *image_data, const region_t *reg_visible);
|
||||
|
||||
bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
|
||||
const region_t *reg_visible);
|
||||
|
||||
|
|
|
@ -161,8 +161,8 @@ struct glx_fbconfig_info *glx_find_fbconfig(Display *dpy, int screen, struct xvi
|
|||
void glx_release_image(backend_t *base, void *image_data) {
|
||||
struct _glx_image_data *wd = image_data;
|
||||
struct _glx_data *gd = (void *)base;
|
||||
wd->texture.refcount--;
|
||||
if (wd->texture.refcount != 0) {
|
||||
(*wd->texture.refcount)--;
|
||||
if (*wd->texture.refcount != 0) {
|
||||
return;
|
||||
}
|
||||
// Release binding
|
||||
|
@ -300,8 +300,8 @@ end:
|
|||
return &gd->gl.base;
|
||||
}
|
||||
|
||||
static void *glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap,
|
||||
struct xvisual_info fmt, bool owned) {
|
||||
static void *
|
||||
glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) {
|
||||
struct _glx_data *gd = (void *)base;
|
||||
// Retrieve pixmap parameters, if they aren't provided
|
||||
if (fmt.visual_depth > OPENGL_MAX_DEPTH) {
|
||||
|
@ -370,7 +370,8 @@ static void *glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap,
|
|||
wd->texture.depth = fmt.visual_depth;
|
||||
wd->texture.color_inverted = false;
|
||||
wd->texture.has_alpha = fmt.alpha_size != 0;
|
||||
wd->texture.refcount = 1;
|
||||
wd->texture.refcount = ccalloc(1, int);
|
||||
*wd->texture.refcount = 1;
|
||||
glBindTexture(wd->texture.target, wd->texture.texture);
|
||||
glXBindTexImageEXT(gd->display, wd->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
|
||||
glBindTexture(wd->texture.target, 0);
|
||||
|
@ -404,6 +405,14 @@ static int glx_buffer_age(backend_t *base) {
|
|||
return (int)val ?: -1;
|
||||
}
|
||||
|
||||
static void *glx_copy(backend_t *base, const void *image_data, const region_t *reg_visible) {
|
||||
const struct _glx_image_data *img = image_data;
|
||||
auto new_img = ccalloc(1, struct _glx_image_data);
|
||||
*new_img = *img;
|
||||
(*new_img->texture.refcount)++;
|
||||
return new_img;
|
||||
}
|
||||
|
||||
struct backend_operations glx_ops = {
|
||||
.init = glx_init,
|
||||
.deinit = glx_deinit,
|
||||
|
@ -411,13 +420,13 @@ struct backend_operations glx_ops = {
|
|||
.release_image = glx_release_image,
|
||||
.compose = gl_compose,
|
||||
.image_op = gl_image_op,
|
||||
.copy = gl_copy,
|
||||
.copy = glx_copy,
|
||||
.blur = gl_blur,
|
||||
.is_image_transparent = gl_is_image_transparent,
|
||||
.present = glx_present,
|
||||
.buffer_age = glx_buffer_age,
|
||||
.render_shadow = default_backend_render_shadow,
|
||||
.max_buffer_age = 5, // Why?
|
||||
.max_buffer_age = 5, // Why?
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue