new backend: glx: reduce code duplication

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-05-07 00:31:54 +01:00
parent 45ead409b5
commit 18b1fc95ff
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
1 changed files with 66 additions and 84 deletions

View File

@ -158,17 +158,10 @@ static void gl_free_prog_main(gl_win_shader_t *pprogram) {
* @param reg_tgt the clip region, in Xorg coordinate system * @param reg_tgt the clip region, in Xorg coordinate system
* @param reg_visible ignored * @param reg_visible ignored
*/ */
static void _gl_compose(backend_t *base, struct gl_image *img, GLuint target, int dst_x, static void _gl_compose(backend_t *base, struct gl_image *img, GLuint target,
int dst_y, GLfloat *coord, GLuint *indices, int nrects) { GLfloat *coord, GLuint *indices, int nrects) {
struct gl_data *gd = (void *)base; struct gl_data *gd = (void *)base;
// Until we start to use glClipControl, reg_tgt, dst_x and dst_y and
// in a different coordinate system than the one OpenGL uses.
// OpenGL window coordinate (or NDC) has the origin at the lower left of the
// screen, with y axis pointing up; Xorg has the origin at the upper left of the
// screen, with y axis pointing down. We have to do some coordinate conversion in
// this function
if (!img || !img->inner->texture) { if (!img || !img->inner->texture) {
log_error("Missing texture."); log_error("Missing texture.");
return; return;
@ -247,28 +240,27 @@ static void _gl_compose(backend_t *base, struct gl_image *img, GLuint target, in
return; return;
} }
void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, /// Convert rectangles in X coordinates to OpenGL vertex and texture coordinates
const region_t *reg_tgt, const region_t *reg_visible) { /// @param[in] nrects, rects rectangles
struct gl_data *gd = (void *)base; /// @param[in] dst_x, dst_y origin of the OpenGL texture, affect the calculated texture
struct gl_image *img = image_data; /// coordinates
/// @param[in] width, height size of the OpenGL texture
// Painting /// @param[in] root_height height of the back buffer
int nrects; /// @param[in] y_inverted whether the texture is y inverted
const rect_t *rects; /// @param[out] coord, indices output
rects = pixman_region32_rectangles((region_t *)reg_tgt, &nrects); static void x_rect_to_coords(int nrects, const rect_t *rects, int dst_x, int dst_y,
if (!nrects) { int width, int height, int root_height, bool y_inverted,
// Nothing to paint GLfloat *coord, GLuint *indices) {
return; dst_y = root_height - dst_y;
if (y_inverted) {
dst_y -= height;
} }
auto coord = ccalloc(nrects * 16, GLfloat); for (int i = 0; i < nrects; i++) {
auto indices = ccalloc(nrects * 6, GLuint);
dst_y = gd->height - dst_y - img->inner->height;
for (int i = 0; i < nrects; ++i) {
// Y-flip. Note after this, crect.y1 > crect.y2 // Y-flip. Note after this, crect.y1 > crect.y2
rect_t crect = rects[i]; rect_t crect = rects[i];
crect.y1 = gd->height - crect.y1; crect.y1 = root_height - crect.y1;
crect.y2 = gd->height - crect.y2; crect.y2 = root_height - crect.y2;
// Calculate texture coordinates // Calculate texture coordinates
// (texture_x1, texture_y1), texture coord for the _bottom left_ corner // (texture_x1, texture_y1), texture coord for the _bottom left_ corner
@ -278,17 +270,17 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2); auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2);
// X pixmaps might be Y inverted, invert the texture coordinates // X pixmaps might be Y inverted, invert the texture coordinates
if (img->inner->y_inverted) { if (y_inverted) {
texture_y1 = (GLfloat)img->inner->height - texture_y1; texture_y1 = (GLfloat)height - texture_y1;
texture_y2 = (GLfloat)img->inner->height - texture_y2; texture_y2 = (GLfloat)height - texture_y2;
} }
// GL_TEXTURE_2D coordinates are normalized // GL_TEXTURE_2D coordinates are normalized
// TODO use texelFetch // TODO use texelFetch
texture_x1 /= (GLfloat)img->inner->width; texture_x1 /= (GLfloat)width;
texture_y1 /= (GLfloat)img->inner->height; texture_y1 /= (GLfloat)height;
texture_x2 /= (GLfloat)img->inner->width; texture_x2 /= (GLfloat)width;
texture_y2 /= (GLfloat)img->inner->height; texture_y2 /= (GLfloat)height;
// Vertex coordinates // Vertex coordinates
auto vx1 = (GLfloat)crect.x1; auto vx1 = (GLfloat)crect.x1;
@ -316,7 +308,34 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
memcpy(&indices[i * 6], (GLuint[]){u + 0, u + 1, u + 2, u + 2, u + 3, u + 0}, memcpy(&indices[i * 6], (GLuint[]){u + 0, u + 1, u + 2, u + 2, u + 3, u + 0},
sizeof(GLuint) * 6); sizeof(GLuint) * 6);
} }
_gl_compose(base, img, 0, dst_x, dst_y, coord, indices, nrects); }
void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y,
const region_t *reg_tgt, const region_t *reg_visible) {
struct gl_data *gd = (void *)base;
struct gl_image *img = image_data;
// Painting
int nrects;
const rect_t *rects;
rects = pixman_region32_rectangles((region_t *)reg_tgt, &nrects);
if (!nrects) {
// Nothing to paint
return;
}
// Until we start to use glClipControl, reg_tgt, dst_x and dst_y and
// in a different coordinate system than the one OpenGL uses.
// OpenGL window coordinate (or NDC) has the origin at the lower left of the
// screen, with y axis pointing up; Xorg has the origin at the upper left of the
// screen, with y axis pointing down. We have to do some coordinate conversion in
// this function
auto coord = ccalloc(nrects * 16, GLfloat);
auto indices = ccalloc(nrects * 6, GLuint);
x_rect_to_coords(nrects, rects, dst_x, dst_y, img->inner->width, img->inner->height,
gd->height, img->inner->y_inverted, coord, indices);
_gl_compose(base, img, 0, coord, indices, nrects);
free(indices); free(indices);
free(coord); free(coord);
@ -340,56 +359,15 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
bool ret = false; bool ret = false;
int nrects; int nrects;
const rect_t *rect = pixman_region32_rectangles((region_t *)reg_blur, &nrects); const rect_t *rects = pixman_region32_rectangles((region_t *)reg_blur, &nrects);
if (!nrects) { if (!nrects) {
return true; return true;
} }
auto coord = ccalloc(nrects * 16, GLfloat); auto coord = ccalloc(nrects * 16, GLfloat);
auto indices = ccalloc(nrects * 6, GLuint); auto indices = ccalloc(nrects * 6, GLuint);
for (int i = 0; i < nrects; i++) { x_rect_to_coords(nrects, rects, extent->x1, extent->y2, gd->width, gd->height,
rect_t crect = rect[i]; gd->height, false, coord, indices);
// flip y axis, because the regions are in Xorg's coordinates,
// which is y-flipped from OpenGL's.
crect.y1 = gd->height - crect.y1;
crect.y2 = gd->height - crect.y2;
// Texture coordinates
auto texture_x1 = (GLfloat)(crect.x1 - extent->x1);
auto texture_y1 = (GLfloat)(crect.y2 - dst_y);
auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1);
auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2);
texture_x1 /= (GLfloat)gd->width;
texture_x2 /= (GLfloat)gd->width;
texture_y1 /= (GLfloat)gd->height;
texture_y2 /= (GLfloat)gd->height;
// Vertex coordinates
// For passes before the last one, we are drawing into a buffer,
// so (dx, dy) from source maps to (0, 0)
auto vx1 = (GLfloat)(crect.x1 - extent->x1);
auto vy1 = (GLfloat)(crect.y2 - dst_y);
auto vx2 = vx1 + (GLfloat)(crect.x2 - crect.x1);
auto vy2 = vy1 + (GLfloat)(crect.y1 - crect.y2);
memcpy(&coord[i * 16],
(GLfloat[][2]){
{vx1, vy1},
{texture_x1, texture_y1},
{vx2, vy1},
{texture_x2, texture_y1},
{vx2, vy2},
{texture_x2, texture_y2},
{vx1, vy2},
{texture_x1, texture_y2},
},
sizeof(GLfloat[2]) * 8);
GLuint u = (GLuint)(i * 4);
memcpy(&indices[i * 6], (GLuint[]){u + 0, u + 1, u + 2, u + 2, u + 3, u + 0},
sizeof(GLuint) * 6);
}
GLuint vao; GLuint vao;
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
@ -437,11 +415,11 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur,
glUniform1f(p->unifm_opacity, (float)opacity); glUniform1f(p->unifm_opacity, (float)opacity);
} }
if (i == gd->npasses - 1) { if (i == gd->npasses - 1) {
// For last pass, we are drawing back to source, so we need to
// translate the render region
glUniform2f(p->orig_loc, (GLfloat)extent->x1, (GLfloat)dst_y);
} else {
glUniform2f(p->orig_loc, 0, 0); glUniform2f(p->orig_loc, 0, 0);
} else {
// For other than last pass, we are drawing to a texture, we
// translate the render origin so we don't need a big texture
glUniform2f(p->orig_loc, -(GLfloat)extent->x1, -(GLfloat)dst_y);
} }
glUniform1f(p->unifm_offset_x, 1.0f / (GLfloat)gd->width); glUniform1f(p->unifm_offset_x, 1.0f / (GLfloat)gd->width);
@ -976,7 +954,7 @@ static inline void gl_image_decouple(backend_t *base, struct gl_image *img) {
}; };
// clang-format on // clang-format on
_gl_compose(base, img, fbo, 0, 0, coord, (GLuint[]){0, 1, 2, 2, 3, 0}, 1); _gl_compose(base, img, fbo, coord, (GLuint[]){0, 1, 2, 2, 3, 0}, 1);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo); glDeleteFramebuffers(1, &fbo);
@ -989,6 +967,9 @@ static inline void gl_image_decouple(backend_t *base, struct gl_image *img) {
img->opacity = 1; img->opacity = 1;
} }
static void gl_image_apply_alpha(struct gl_image *img, const region_t *reg_op, double alpha) {
}
/// stub for backend_operations::image_op /// stub for backend_operations::image_op
bool gl_image_op(backend_t *base, enum image_operations op, void *image_data, 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) { const region_t *reg_op, const region_t *reg_visible, void *arg) {
@ -1002,6 +983,7 @@ bool gl_image_op(backend_t *base, enum image_operations op, void *image_data,
case IMAGE_OP_APPLY_ALPHA_ALL: tex->opacity *= *(double *)arg; break; case IMAGE_OP_APPLY_ALPHA_ALL: tex->opacity *= *(double *)arg; break;
case IMAGE_OP_APPLY_ALPHA: case IMAGE_OP_APPLY_ALPHA:
gl_image_decouple(base, tex); gl_image_decouple(base, tex);
gl_image_apply_alpha(tex, reg_op, *(double *)arg);
log_warn("IMAGE_OP_APPLY_ALPHA not implemented yet"); log_warn("IMAGE_OP_APPLY_ALPHA not implemented yet");
break; break;
case IMAGE_OP_RESIZE_TILE: case IMAGE_OP_RESIZE_TILE: