gl-renderer: Batch paint node's draw calls in fan debug mode
Index vertices from the damage mesh as lines and emit a single draw call in fan debug mode. A new shader path and an additional vertex stream are added in order to filter the color of the solid shader variant per sub-mesh. Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
parent
22d9b9815f
commit
23ae2e7f32
|
@ -75,12 +75,13 @@ precision HIGHPRECISION float;
|
|||
* snippet.
|
||||
*/
|
||||
compile_const int c_variant = DEF_VARIANT;
|
||||
compile_const bool c_input_is_premult = DEF_INPUT_IS_PREMULT;
|
||||
compile_const bool c_green_tint = DEF_GREEN_TINT;
|
||||
compile_const int c_color_pre_curve = DEF_COLOR_PRE_CURVE;
|
||||
compile_const int c_color_mapping = DEF_COLOR_MAPPING;
|
||||
compile_const int c_color_post_curve = DEF_COLOR_POST_CURVE;
|
||||
|
||||
compile_const bool c_input_is_premult = DEF_INPUT_IS_PREMULT;
|
||||
compile_const bool c_green_tint = DEF_GREEN_TINT;
|
||||
compile_const bool c_wireframe = DEF_WIREFRAME;
|
||||
compile_const bool c_need_color_pipeline =
|
||||
c_color_pre_curve != SHADER_COLOR_CURVE_IDENTITY ||
|
||||
c_color_mapping != SHADER_COLOR_MAPPING_IDENTITY ||
|
||||
|
@ -122,6 +123,7 @@ uniform sampler2D tex;
|
|||
#endif
|
||||
|
||||
varying HIGHPRECISION vec2 v_texcoord;
|
||||
varying HIGHPRECISION vec4 v_color;
|
||||
uniform sampler2D tex1;
|
||||
uniform sampler2D tex2;
|
||||
uniform float view_alpha;
|
||||
|
@ -413,6 +415,9 @@ main()
|
|||
/* Electrical (non-linear) RGBA values, may be premult or not */
|
||||
color = sample_input_texture();
|
||||
|
||||
if (c_wireframe)
|
||||
color *= v_color;
|
||||
|
||||
if (c_need_color_pipeline)
|
||||
color = color_pipeline(color); /* Produces straight alpha */
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ struct gl_shader_requirements
|
|||
unsigned variant:4; /* enum gl_shader_texture_variant */
|
||||
bool input_is_premult:1;
|
||||
bool green_tint:1;
|
||||
bool wireframe:1;
|
||||
|
||||
unsigned color_pre_curve:2; /* enum gl_shader_color_curve */
|
||||
unsigned color_mapping:2; /* enum gl_shader_color_mapping */
|
||||
|
@ -96,7 +97,7 @@ struct gl_shader_requirements
|
|||
* The total size of all bitfields plus pad_bits_ must fill up exactly
|
||||
* how many bytes the compiler allocates for them together.
|
||||
*/
|
||||
unsigned pad_bits_:19;
|
||||
unsigned pad_bits_:18;
|
||||
};
|
||||
static_assert(sizeof(struct gl_shader_requirements) ==
|
||||
4 /* total bitfield size in bytes */,
|
||||
|
@ -166,7 +167,8 @@ struct gl_renderer {
|
|||
|
||||
/* Vertex streams. */
|
||||
struct wl_array position_stream;
|
||||
struct wl_array indices;
|
||||
struct wl_array color_stream;
|
||||
struct wl_array indices[2];
|
||||
|
||||
EGLDeviceEXT egl_device;
|
||||
const char *drm_device;
|
||||
|
|
|
@ -1311,6 +1311,66 @@ transform_damage(const struct weston_paint_node *pnode,
|
|||
free(rects);
|
||||
}
|
||||
|
||||
/* Colorise a wireframe sub-mesh. 8 colors (32 bytes) are stored unconditionally
|
||||
* into 'color_stream'.
|
||||
*/
|
||||
static void
|
||||
store_wireframes(uint32_t *color_stream)
|
||||
{
|
||||
static const uint32_t colors[] =
|
||||
{ 0xff0000ff, 0xff00ff00, 0xffff0000, 0xfffffff };
|
||||
static size_t idx = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
color_stream[i] = colors[idx % ARRAY_LENGTH(colors)];
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* Triangulate a wireframe sub-mesh of 'count' vertices as indexed lines. 'bias'
|
||||
* is added to each index. 'count' must be less than or equal to 8. 32 indices
|
||||
* (64 bytes) are stored unconditionally into 'indices'. The return value is the
|
||||
* index count.
|
||||
*/
|
||||
static int
|
||||
store_lines(size_t count,
|
||||
uint16_t bias,
|
||||
uint16_t *indices)
|
||||
{
|
||||
/* Look-up table of triangle lines with last entry storing the index
|
||||
* count. Padded to 32 elements for compilers to emit packed adds. */
|
||||
static const uint16_t lines[][32] = {
|
||||
{}, {}, {}, {
|
||||
2, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
|
||||
},{
|
||||
3, 0, 0, 1, 1, 2, 2, 3, 3, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10
|
||||
},{
|
||||
4, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 1, 1, 3, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14
|
||||
},{
|
||||
5, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 1, 1, 4,
|
||||
4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18
|
||||
},{
|
||||
6, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 1,
|
||||
1, 5, 5, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22
|
||||
},{
|
||||
7, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
|
||||
7, 1, 1, 6, 6, 2, 2, 5, 5, 3, 0, 0, 0, 0, 0, 26
|
||||
},
|
||||
};
|
||||
int i;
|
||||
|
||||
assert(count < ARRAY_LENGTH(lines));
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
indices[i] = lines[count][i] + bias;
|
||||
|
||||
return lines[count][31];
|
||||
}
|
||||
|
||||
/* Triangulate a sub-mesh of 'count' vertices as an indexed triangle strip.
|
||||
* 'bias' is added to each index. In order to chain sub-meshes, the last index
|
||||
* is followed by 2 indices creating 4 degenerate triangles. 'count' must be
|
||||
|
@ -1319,9 +1379,9 @@ transform_damage(const struct weston_paint_node *pnode,
|
|||
* indices.
|
||||
*/
|
||||
static int
|
||||
store_indices(size_t count,
|
||||
uint16_t bias,
|
||||
uint16_t *indices)
|
||||
store_strips(size_t count,
|
||||
uint16_t bias,
|
||||
uint16_t *indices)
|
||||
{
|
||||
/* Look-up table of triangle strips with last entry storing the index
|
||||
* count. Padded to 16 elements for compilers to emit packed adds. */
|
||||
|
@ -1349,9 +1409,15 @@ draw_mesh(struct gl_renderer *gr,
|
|||
struct weston_paint_node *pnode,
|
||||
const struct gl_shader_config *sconf,
|
||||
const struct clipper_vertex *positions,
|
||||
const uint32_t *colors,
|
||||
const uint16_t *strip,
|
||||
int nstrip)
|
||||
int nstrip,
|
||||
const uint16_t *lines,
|
||||
int nlines)
|
||||
{
|
||||
struct gl_shader_config alt;
|
||||
struct weston_color_transform *ctransf;
|
||||
|
||||
assert(nstrip > 0);
|
||||
|
||||
if (!gl_renderer_use_program(gr, sconf))
|
||||
|
@ -1359,6 +1425,35 @@ draw_mesh(struct gl_renderer *gr,
|
|||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, positions);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, nstrip, GL_UNSIGNED_SHORT, strip);
|
||||
|
||||
if (nlines == 0)
|
||||
return;
|
||||
|
||||
/* Fan debugging is rendered as lines colored with the solid shader
|
||||
* variant filtered per sub-mesh using vertex colors. */
|
||||
alt = (struct gl_shader_config) {
|
||||
.req = {
|
||||
.variant = SHADER_VARIANT_SOLID,
|
||||
.input_is_premult = true,
|
||||
.wireframe = true,
|
||||
},
|
||||
.projection = sconf->projection,
|
||||
.view_alpha = 1.0f,
|
||||
.unicolor = { 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
};
|
||||
ctransf = pnode->output->color_outcome->from_sRGB_to_blend;
|
||||
if (!gl_shader_config_set_color_transform(gr, &alt, ctransf)) {
|
||||
weston_log("GL-renderer: %s failed to generate a color "
|
||||
"transformation.\n", __func__);
|
||||
return;
|
||||
}
|
||||
if (!gl_renderer_use_program(gr, &alt))
|
||||
return;
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, colors);
|
||||
glDrawElements(GL_LINES, nlines, GL_UNSIGNED_SHORT, lines);
|
||||
glDisableVertexAttribArray(2);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1371,14 +1466,18 @@ repaint_region(struct gl_renderer *gr,
|
|||
{
|
||||
pixman_box32_t *rects;
|
||||
struct clipper_vertex *positions;
|
||||
uint16_t *indices;
|
||||
int i, j, n, nrects, positions_size, indices_size;
|
||||
int nvtx = 0, nidx = 0;
|
||||
uint32_t *colors = NULL;
|
||||
uint16_t *strips, *lines = NULL;
|
||||
int i, j, n, nrects, positions_size, colors_size, strips_size;
|
||||
int lines_size, nvtx = 0, nstrips = 0, nlines = 0;
|
||||
bool wireframe = gr->fan_debug;
|
||||
|
||||
/* Build-time sub-mesh constants. Clipping emits 8 vertices max.
|
||||
* store_indices() stores at most 10 indices. */
|
||||
* store_strips() and store_lines() respectively store 10 and 26 indices
|
||||
* at most. */
|
||||
const int nvtx_max = 8;
|
||||
const int nidx_max = 10;
|
||||
const int nstrips_max = 10;
|
||||
const int nlines_max = 26;
|
||||
|
||||
rects = pixman_region32_rectangles(region, &nrects);
|
||||
assert((nrects > 0) && (nquads > 0));
|
||||
|
@ -1386,10 +1485,16 @@ repaint_region(struct gl_renderer *gr,
|
|||
/* Worst case allocation sizes per sub-mesh. */
|
||||
n = nquads * nrects;
|
||||
positions_size = n * nvtx_max * sizeof *positions;
|
||||
indices_size = ROUND_UP_N(n * nidx_max * sizeof *indices, 32);
|
||||
colors_size = ROUND_UP_N(n * nvtx_max * sizeof *colors, 32);
|
||||
strips_size = ROUND_UP_N(n * nstrips_max * sizeof *strips, 32);
|
||||
lines_size = ROUND_UP_N(n * nlines_max * sizeof *lines, 64);
|
||||
|
||||
positions = wl_array_add(&gr->position_stream, positions_size);
|
||||
indices = wl_array_add(&gr->indices, indices_size);
|
||||
strips = wl_array_add(&gr->indices[0], strips_size);
|
||||
if (wireframe) {
|
||||
colors = wl_array_add(&gr->color_stream, colors_size);
|
||||
lines = wl_array_add(&gr->indices[1], lines_size);
|
||||
}
|
||||
|
||||
/* A node's damage mesh is created by clipping damage quads to surface
|
||||
* rects and by chaining the resulting sub-meshes into an indexed
|
||||
|
@ -1413,24 +1518,33 @@ repaint_region(struct gl_renderer *gr,
|
|||
for (j = 0; j < nrects; j++) {
|
||||
n = clipper_quad_clip_box32(&quads[i], &rects[j],
|
||||
&positions[nvtx]);
|
||||
nidx += store_indices(n, nvtx, &indices[nidx]);
|
||||
nstrips += store_strips(n, nvtx, &strips[nstrips]);
|
||||
if (wireframe) {
|
||||
store_wireframes(&colors[nvtx]);
|
||||
nlines += store_lines(n, nvtx, &lines[nlines]);
|
||||
}
|
||||
nvtx += n;
|
||||
|
||||
/* Highly unlikely flush to prevent index wraparound.
|
||||
* Subtracting 2 removes the last chaining indices. */
|
||||
if ((nvtx + nvtx_max) > UINT16_MAX) {
|
||||
draw_mesh(gr, pnode, sconf, positions, indices,
|
||||
nidx - 2);
|
||||
nvtx = nidx = 0;
|
||||
draw_mesh(gr, pnode, sconf, positions, colors,
|
||||
strips, nstrips - 2, lines, nlines);
|
||||
nvtx = nstrips = nlines = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nvtx)
|
||||
draw_mesh(gr, pnode, sconf, positions, indices, nidx - 2);
|
||||
draw_mesh(gr, pnode, sconf, positions, colors, strips,
|
||||
nstrips - 2, lines, nlines);
|
||||
|
||||
gr->position_stream.size = 0;
|
||||
gr->indices.size = 0;
|
||||
gr->indices[0].size = 0;
|
||||
if (wireframe) {
|
||||
gr->color_stream.size = 0;
|
||||
gr->indices[1].size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -4010,7 +4124,9 @@ gl_renderer_destroy(struct weston_compositor *ec)
|
|||
eglReleaseThread();
|
||||
|
||||
wl_array_release(&gr->position_stream);
|
||||
wl_array_release(&gr->indices);
|
||||
wl_array_release(&gr->color_stream);
|
||||
wl_array_release(&gr->indices[0]);
|
||||
wl_array_release(&gr->indices[1]);
|
||||
|
||||
if (gr->fragment_binding)
|
||||
weston_binding_destroy(gr->fragment_binding);
|
||||
|
|
|
@ -238,8 +238,11 @@ create_vertex_shader_config_string(const struct gl_shader_requirements *req)
|
|||
char *str;
|
||||
|
||||
size = asprintf(&str,
|
||||
"#define DEF_TEXCOORD_INPUT %s\n",
|
||||
gl_shader_texcoord_input_to_string(req->texcoord_input));
|
||||
"#define DEF_TEXCOORD_INPUT %s\n"
|
||||
"#define DEF_WIREFRAME %s\n",
|
||||
gl_shader_texcoord_input_to_string(req->texcoord_input),
|
||||
req->wireframe ? "true" : "false");
|
||||
|
||||
if (size < 0)
|
||||
return NULL;
|
||||
return str;
|
||||
|
@ -254,12 +257,14 @@ create_fragment_shader_config_string(const struct gl_shader_requirements *req)
|
|||
size = asprintf(&str,
|
||||
"#define DEF_GREEN_TINT %s\n"
|
||||
"#define DEF_INPUT_IS_PREMULT %s\n"
|
||||
"#define DEF_WIREFRAME %s\n"
|
||||
"#define DEF_COLOR_PRE_CURVE %s\n"
|
||||
"#define DEF_COLOR_MAPPING %s\n"
|
||||
"#define DEF_COLOR_POST_CURVE %s\n"
|
||||
"#define DEF_VARIANT %s\n",
|
||||
req->green_tint ? "true" : "false",
|
||||
req->input_is_premult ? "true" : "false",
|
||||
req->wireframe ? "true" : "false",
|
||||
gl_shader_color_curve_to_string(req->color_pre_curve),
|
||||
gl_shader_color_mapping_to_string(req->color_mapping),
|
||||
gl_shader_color_curve_to_string(req->color_post_curve),
|
||||
|
@ -328,6 +333,8 @@ gl_shader_create(struct gl_renderer *gr,
|
|||
glBindAttribLocation(shader->program, 0, "position");
|
||||
if (requirements->texcoord_input == SHADER_TEXCOORD_INPUT_ATTRIB)
|
||||
glBindAttribLocation(shader->program, 1, "texcoord");
|
||||
if (requirements->wireframe)
|
||||
glBindAttribLocation(shader->program, 2, "color");
|
||||
|
||||
glLinkProgram(shader->program);
|
||||
glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
|
||||
|
|
|
@ -46,11 +46,14 @@ uniform mat4 surface_to_buffer;
|
|||
|
||||
attribute vec2 position;
|
||||
attribute vec2 texcoord;
|
||||
attribute vec4 color;
|
||||
|
||||
/* Match the varying precision to the fragment shader */
|
||||
varying FRAG_PRECISION vec2 v_texcoord;
|
||||
varying FRAG_PRECISION vec4 v_color;
|
||||
|
||||
compile_const int c_texcoord_input = DEF_TEXCOORD_INPUT;
|
||||
compile_const bool c_wireframe = DEF_WIREFRAME;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -60,4 +63,7 @@ void main()
|
|||
v_texcoord = texcoord;
|
||||
else if (c_texcoord_input == SHADER_TEXCOORD_INPUT_SURFACE)
|
||||
v_texcoord = vec2(surface_to_buffer * vec4(position, 0.0, 1.0));
|
||||
|
||||
if (c_wireframe)
|
||||
v_color = color;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue