Reuse some code from the new gl backend
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
290ec7fb04
commit
061dd8e52e
|
@ -16,6 +16,26 @@
|
||||||
|
|
||||||
#include "backend/gl/gl_common.h"
|
#include "backend/gl/gl_common.h"
|
||||||
|
|
||||||
|
#define P_PAINTREG_START(var) \
|
||||||
|
do { \
|
||||||
|
region_t reg_new; \
|
||||||
|
int nrects; \
|
||||||
|
const rect_t *rects; \
|
||||||
|
pixman_region32_init_rect(®_new, dx, dy, width, height); \
|
||||||
|
pixman_region32_intersect(®_new, ®_new, (region_t *)reg_tgt); \
|
||||||
|
rects = pixman_region32_rectangles(®_new, &nrects); \
|
||||||
|
glBegin(GL_QUADS); \
|
||||||
|
\
|
||||||
|
for (int ri = 0; ri < nrects; ++ri) { \
|
||||||
|
rect_t var = rects[ri];
|
||||||
|
|
||||||
|
#define P_PAINTREG_END() \
|
||||||
|
} \
|
||||||
|
glEnd(); \
|
||||||
|
pixman_region32_fini(®_new); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
struct gl_data {};
|
struct gl_data {};
|
||||||
|
|
||||||
GLuint gl_create_shader(GLenum shader_type, const char *shader_str) {
|
GLuint gl_create_shader(GLenum shader_type, const char *shader_str) {
|
||||||
|
|
|
@ -144,23 +144,3 @@ static inline void gl_free_blur_shader(gl_blur_shader_t *shader) {
|
||||||
shader->prog = 0;
|
shader->prog = 0;
|
||||||
shader->frag_shader = 0;
|
shader->frag_shader = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define P_PAINTREG_START(var) \
|
|
||||||
do { \
|
|
||||||
region_t reg_new; \
|
|
||||||
int nrects; \
|
|
||||||
const rect_t *rects; \
|
|
||||||
pixman_region32_init_rect(®_new, dx, dy, width, height); \
|
|
||||||
pixman_region32_intersect(®_new, ®_new, (region_t *)reg_tgt); \
|
|
||||||
rects = pixman_region32_rectangles(®_new, &nrects); \
|
|
||||||
glBegin(GL_QUADS); \
|
|
||||||
\
|
|
||||||
for (int ri = 0; ri < nrects; ++ri) { \
|
|
||||||
rect_t var = rects[ri];
|
|
||||||
|
|
||||||
#define P_PAINTREG_END() \
|
|
||||||
} \
|
|
||||||
glEnd(); \
|
|
||||||
pixman_region32_fini(®_new); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
|
@ -6,7 +6,9 @@ if get_option('new_backends')
|
||||||
# enable opengl
|
# enable opengl
|
||||||
if get_option('opengl')
|
if get_option('opengl')
|
||||||
srcs += [ files('gl/gl_common.c', 'gl/glx.c') ]
|
srcs += [ files('gl/gl_common.c', 'gl/glx.c') ]
|
||||||
deps += [ dependency('gl', required: true) ]
|
|
||||||
cflags += [ '-DGL_GLEXT_PROTOTYPES' ]
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if get_option('opengl')
|
||||||
|
srcs += [ files('gl/gl_common.c') ]
|
||||||
|
endif
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
#include "opengl.h"
|
#include "backend/gl/gl_common.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
@ -328,7 +328,7 @@ static const struct log_ops glx_string_marker_logger_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct log_target *glx_string_marker_logger_new(void) {
|
struct log_target *glx_string_marker_logger_new(void) {
|
||||||
if (!glx_hasglext("GL_GREMEDY_string_marker")) {
|
if (!gl_has_extension("GL_GREMEDY_string_marker")) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
169
src/opengl.c
169
src/opengl.c
|
@ -24,6 +24,7 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
#include "region.h"
|
#include "region.h"
|
||||||
|
#include "backend/gl/gl_common.h"
|
||||||
|
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
|
||||||
|
@ -359,7 +360,7 @@ glx_init(session_t *ps, bool need_render) {
|
||||||
// Check GL_ARB_texture_non_power_of_two, requires a GLX context and
|
// Check GL_ARB_texture_non_power_of_two, requires a GLX context and
|
||||||
// must precede FBConfig fetching
|
// must precede FBConfig fetching
|
||||||
if (need_render)
|
if (need_render)
|
||||||
psglx->has_texture_non_power_of_two = glx_hasglext(
|
psglx->has_texture_non_power_of_two = gl_has_extension(
|
||||||
"GL_ARB_texture_non_power_of_two");
|
"GL_ARB_texture_non_power_of_two");
|
||||||
|
|
||||||
// Acquire function addresses
|
// Acquire function addresses
|
||||||
|
@ -455,7 +456,7 @@ glx_destroy(session_t *ps) {
|
||||||
|
|
||||||
glx_free_prog_main(ps, &ps->glx_prog_win);
|
glx_free_prog_main(ps, &ps->glx_prog_win);
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
// Free FBConfigs
|
// Free FBConfigs
|
||||||
for (int i = 0; i <= OPENGL_MAX_DEPTH; ++i) {
|
for (int i = 0; i <= OPENGL_MAX_DEPTH; ++i) {
|
||||||
|
@ -609,7 +610,7 @@ glx_init_blur(session_t *ps) {
|
||||||
|
|
||||||
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
||||||
assert(strlen(shader_str) < len);
|
assert(strlen(shader_str) < len);
|
||||||
ppass->frag_shader = glx_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
ppass->frag_shader = gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
||||||
free(shader_str);
|
free(shader_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,7 +620,7 @@ glx_init_blur(session_t *ps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build program
|
// Build program
|
||||||
ppass->prog = glx_create_program(&ppass->frag_shader, 1);
|
ppass->prog = gl_create_program(&ppass->frag_shader, 1);
|
||||||
if (!ppass->prog) {
|
if (!ppass->prog) {
|
||||||
log_error("Failed to create GLSL program.");
|
log_error("Failed to create GLSL program.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -649,7 +650,7 @@ glx_init_blur(session_t *ps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -664,7 +665,7 @@ glx_load_prog_main(session_t *ps,
|
||||||
assert(pprogram);
|
assert(pprogram);
|
||||||
|
|
||||||
// Build program
|
// Build program
|
||||||
pprogram->prog = glx_create_program_from_str(vshader_str, fshader_str);
|
pprogram->prog = gl_create_program_from_str(vshader_str, fshader_str);
|
||||||
if (!pprogram->prog) {
|
if (!pprogram->prog) {
|
||||||
log_error("Failed to create GLSL program.");
|
log_error("Failed to create GLSL program.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -682,7 +683,7 @@ glx_load_prog_main(session_t *ps,
|
||||||
P_GET_UNIFM_LOC("tex", unifm_tex);
|
P_GET_UNIFM_LOC("tex", unifm_tex);
|
||||||
#undef P_GET_UNIFM_LOC
|
#undef P_GET_UNIFM_LOC
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -831,7 +832,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
glBindTexture(ptex->target, 0);
|
glBindTexture(ptex->target, 0);
|
||||||
glDisable(ptex->target);
|
glDisable(ptex->target);
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -854,7 +855,7 @@ glx_release_pixmap(session_t *ps, glx_texture_t *ptex) {
|
||||||
ptex->glpixmap = 0;
|
ptex->glpixmap = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -881,7 +882,7 @@ glx_set_clip(session_t *ps, const region_t *reg) {
|
||||||
rects[0].x2-rects[0].x1, rects[0].y2-rects[0].y1);
|
rects[0].x2-rects[0].x1, rects[0].y2-rects[0].y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define P_PAINTREG_START(var) \
|
#define P_PAINTREG_START(var) \
|
||||||
|
@ -1134,7 +1135,7 @@ glx_blur_dst_end:
|
||||||
free_glx_bc(ps, pbc);
|
free_glx_bc(ps, pbc);
|
||||||
}
|
}
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1169,7 +1170,7 @@ glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
|
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1379,149 +1380,7 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
if (has_prog)
|
if (has_prog)
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
|
||||||
glx_check_err(ps);
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get tightly packed RGB888 data from GL front buffer.
|
|
||||||
*
|
|
||||||
* Don't expect any sort of decent performance.
|
|
||||||
*
|
|
||||||
* @returns tightly packed RGB888 data of the size of the screen,
|
|
||||||
* to be freed with `free()`
|
|
||||||
*/
|
|
||||||
unsigned char *
|
|
||||||
glx_take_screenshot(session_t *ps, int *out_length) {
|
|
||||||
int length = 3 * ps->root_width * ps->root_height;
|
|
||||||
GLint unpack_align_old = 0;
|
|
||||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_align_old);
|
|
||||||
assert(unpack_align_old > 0);
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
auto buf = ccalloc(length, unsigned char);
|
|
||||||
glReadBuffer(GL_FRONT);
|
|
||||||
glReadPixels(0, 0, ps->root_width, ps->root_height, GL_RGB,
|
|
||||||
GL_UNSIGNED_BYTE, buf);
|
|
||||||
glReadBuffer(GL_BACK);
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_align_old);
|
|
||||||
if (out_length)
|
|
||||||
*out_length = sizeof(unsigned char) * length;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint
|
|
||||||
glx_create_shader(GLenum shader_type, const char *shader_str) {
|
|
||||||
log_trace("glx_create_shader(): ===\n%s\n===", shader_str);
|
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
GLuint shader = glCreateShader(shader_type);
|
|
||||||
if (!shader) {
|
|
||||||
log_error("Failed to create shader with type %#x.", shader_type);
|
|
||||||
goto glx_create_shader_end;
|
|
||||||
}
|
|
||||||
glShaderSource(shader, 1, &shader_str, NULL);
|
|
||||||
glCompileShader(shader);
|
|
||||||
|
|
||||||
// Get shader status
|
|
||||||
{
|
|
||||||
GLint status = GL_FALSE;
|
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
|
||||||
if (GL_FALSE == status) {
|
|
||||||
GLint log_len = 0;
|
|
||||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len);
|
|
||||||
if (log_len) {
|
|
||||||
char log[log_len + 1];
|
|
||||||
glGetShaderInfoLog(shader, log_len, NULL, log);
|
|
||||||
log_error("Failed to compile shader with type %d: %s", shader_type, log);
|
|
||||||
}
|
|
||||||
goto glx_create_shader_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
success = true;
|
|
||||||
|
|
||||||
glx_create_shader_end:
|
|
||||||
if (shader && !success) {
|
|
||||||
glDeleteShader(shader);
|
|
||||||
shader = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint
|
|
||||||
glx_create_program(const GLuint * const shaders, int nshaders) {
|
|
||||||
bool success = false;
|
|
||||||
GLuint program = glCreateProgram();
|
|
||||||
if (!program) {
|
|
||||||
log_error("Failed to create program.");
|
|
||||||
goto glx_create_program_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < nshaders; ++i)
|
|
||||||
glAttachShader(program, shaders[i]);
|
|
||||||
glLinkProgram(program);
|
|
||||||
|
|
||||||
// Get program status
|
|
||||||
{
|
|
||||||
GLint status = GL_FALSE;
|
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
|
||||||
if (GL_FALSE == status) {
|
|
||||||
GLint log_len = 0;
|
|
||||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len);
|
|
||||||
if (log_len) {
|
|
||||||
char log[log_len + 1];
|
|
||||||
glGetProgramInfoLog(program, log_len, NULL, log);
|
|
||||||
log_error("Failed to link program: %s", log);
|
|
||||||
}
|
|
||||||
goto glx_create_program_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
success = true;
|
|
||||||
|
|
||||||
glx_create_program_end:
|
|
||||||
if (program) {
|
|
||||||
for (int i = 0; i < nshaders; ++i)
|
|
||||||
glDetachShader(program, shaders[i]);
|
|
||||||
}
|
|
||||||
if (program && !success) {
|
|
||||||
glDeleteProgram(program);
|
|
||||||
program = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a program from vertex and fragment shader strings.
|
|
||||||
*/
|
|
||||||
GLuint
|
|
||||||
glx_create_program_from_str(const char *vert_shader_str,
|
|
||||||
const char *frag_shader_str) {
|
|
||||||
GLuint vert_shader = 0;
|
|
||||||
GLuint frag_shader = 0;
|
|
||||||
GLuint prog = 0;
|
|
||||||
|
|
||||||
if (vert_shader_str)
|
|
||||||
vert_shader = glx_create_shader(GL_VERTEX_SHADER, vert_shader_str);
|
|
||||||
if (frag_shader_str)
|
|
||||||
frag_shader = glx_create_shader(GL_FRAGMENT_SHADER, frag_shader_str);
|
|
||||||
|
|
||||||
GLuint shaders[2];
|
|
||||||
unsigned int count = 0;
|
|
||||||
if (vert_shader)
|
|
||||||
shaders[count++] = vert_shader;
|
|
||||||
if (frag_shader)
|
|
||||||
shaders[count++] = frag_shader;
|
|
||||||
assert(count <= sizeof(shaders) / sizeof(shaders[0]));
|
|
||||||
if (count)
|
|
||||||
prog = glx_create_program(shaders, count);
|
|
||||||
|
|
||||||
if (vert_shader)
|
|
||||||
glDeleteShader(vert_shader);
|
|
||||||
if (frag_shader)
|
|
||||||
glDeleteShader(frag_shader);
|
|
||||||
|
|
||||||
return prog;
|
|
||||||
}
|
|
||||||
|
|
68
src/opengl.h
68
src/opengl.h
|
@ -33,56 +33,6 @@ typedef struct glx_fbconfig {
|
||||||
bool y_inverted;
|
bool y_inverted;
|
||||||
} glx_fbconfig_t;
|
} glx_fbconfig_t;
|
||||||
|
|
||||||
#ifdef DEBUG_GLX_ERR
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a textual representation of an OpenGL error.
|
|
||||||
*/
|
|
||||||
static inline const char *
|
|
||||||
glx_dump_err_str(GLenum err) {
|
|
||||||
switch (err) {
|
|
||||||
CASESTRRET(GL_NO_ERROR);
|
|
||||||
CASESTRRET(GL_INVALID_ENUM);
|
|
||||||
CASESTRRET(GL_INVALID_VALUE);
|
|
||||||
CASESTRRET(GL_INVALID_OPERATION);
|
|
||||||
CASESTRRET(GL_INVALID_FRAMEBUFFER_OPERATION);
|
|
||||||
CASESTRRET(GL_OUT_OF_MEMORY);
|
|
||||||
CASESTRRET(GL_STACK_UNDERFLOW);
|
|
||||||
CASESTRRET(GL_STACK_OVERFLOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for GLX error.
|
|
||||||
*
|
|
||||||
* http://blog.nobel-joergensen.com/2013/01/29/debugging-opengl-using-glgeterror/
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
glx_check_err_(session_t *ps, const char *func, int line) {
|
|
||||||
if (!ps->psglx->context) return;
|
|
||||||
|
|
||||||
GLenum err = GL_NO_ERROR;
|
|
||||||
|
|
||||||
while (GL_NO_ERROR != (err = glGetError())) {
|
|
||||||
const char *errtext = glx_dump_err_str(err);
|
|
||||||
if (errtext) {
|
|
||||||
log_printf(tls_logger, LOG_LEVEL_ERROR, func, "GLX error at line %d: %s", line,
|
|
||||||
errtext);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
log_printf(tls_logger, LOG_LEVEL_ERROR, func, "GLX error at line %d: %d", line,
|
|
||||||
err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define glx_check_err(ps) glx_check_err_(ps, __func__, __LINE__)
|
|
||||||
#else
|
|
||||||
#define glx_check_err(ps) ((void) 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a word is in string.
|
* Check if a word is in string.
|
||||||
*/
|
*/
|
||||||
|
@ -123,24 +73,6 @@ glx_hasglxext(session_t *ps, const char *ext) {
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a GLX extension exists.
|
|
||||||
*/
|
|
||||||
static inline bool
|
|
||||||
glx_hasglext(const char *ext) {
|
|
||||||
const char *gl_exts = (const char *) glGetString(GL_EXTENSIONS);
|
|
||||||
if (!gl_exts) {
|
|
||||||
log_error("Failed get GL extension list.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found = wd_is_in_str(gl_exts, ext);
|
|
||||||
if (!found)
|
|
||||||
log_info("Missing GL extension %s.", ext);
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
GLfloat factor, const region_t *reg_tgt);
|
GLfloat factor, const region_t *reg_tgt);
|
||||||
|
|
Loading…
Reference in New Issue