1#include <fastuidraw/gl_backend/gl_get.hpp>
2#include <fastuidraw/text/glyph_generate_params.hpp>
3#include <fastuidraw/text/glyph_render_data_restricted_rays.hpp>
4#include "sdl_painter_demo.hpp"
5#include "text_helper.hpp"
6
7namespace
8{
9 template<typename T>
10 class enum_wrapper
11 {
12 public:
13 explicit
14 enum_wrapper(T v):
15 m_v(v)
16 {}
17
18 T m_v;
19 };
20
21 template<typename T>
22 enum_wrapper<T>
23 make_enum_wrapper(T v)
24 {
25 return enum_wrapper<T>(v);
26 }
27
28 std::ostream&
29 operator<<(std::ostream &str, enum_wrapper<bool> b)
30 {
31 if (b.m_v)
32 {
33 str << "true";
34 }
35 else
36 {
37 str << "false";
38 }
39 return str;
40 }
41
42 std::ostream&
43 operator<<(std::ostream &str,
44 enum_wrapper<enum fastuidraw::gl::PainterEngineGL::data_store_backing_t> v)
45 {
46 switch(v.m_v)
47 {
48 case fastuidraw::gl::PainterEngineGL::data_store_tbo:
49 str << "tbo";
50 break;
51
52 case fastuidraw::gl::PainterEngineGL::data_store_ubo:
53 str << "ubo";
54 break;
55
56 case fastuidraw::gl::PainterEngineGL::data_store_ssbo:
57 str << "ssbo";
58 break;
59
60 default:
61 str << "invalid value";
62 }
63
64 return str;
65 }
66
67 std::ostream&
68 operator<<(std::ostream &str,
69 enum_wrapper<enum fastuidraw::gl::PainterEngineGL::clipping_type_t> v)
70 {
71 switch(v.m_v)
72 {
73 case fastuidraw::gl::PainterEngineGL::clipping_via_gl_clip_distance:
74 str << "on";
75 break;
76
77 case fastuidraw::gl::PainterEngineGL::clipping_via_discard:
78 str << "off";
79 break;
80
81 case fastuidraw::gl::PainterEngineGL::clipping_via_skip_color_write:
82 str << "emulate_skip_color_write";
83 break;
84
85 default:
86 str << "invalid value";
87 }
88
89 return str;
90 }
91
92 std::ostream&
93 operator<<(std::ostream &str,
94 enum_wrapper<enum fastuidraw::glsl::PainterShaderRegistrarGLSL::fbf_blending_type_t> v)
95 {
96 switch(v.m_v)
97 {
98 case fastuidraw::glsl::PainterShaderRegistrarGLSL::fbf_blending_framebuffer_fetch:
99 str << "framebuffer_fetch";
100 break;
101
102 case fastuidraw::glsl::PainterShaderRegistrarGLSL::fbf_blending_interlock:
103 str << "interlock";
104 break;
105
106 case fastuidraw::glsl::PainterShaderRegistrarGLSL::fbf_blending_not_supported:
107 str << "none";
108 break;
109
110 default:
111 str << "invalid value";
112 }
113
114 return str;
115 }
116
117 std::ostream&
118 operator<<(std::ostream &str,
119 enum_wrapper<enum fastuidraw::PainterBlendShader::shader_type> v)
120 {
121 switch (v.m_v)
122 {
123 case fastuidraw::PainterBlendShader::single_src:
124 str << "single_src";
125 break;
126
127 case fastuidraw::PainterBlendShader::dual_src:
128 str << "dual_src";
129 break;
130
131 case fastuidraw::PainterBlendShader::framebuffer_fetch:
132 str << "framebuffer_fetch";
133 break;
134
135 default:
136 str << "invalid value";
137 }
138 return str;
139 }
140
141 std::ostream&
142 operator<<(std::ostream &ostr, const fastuidraw::PainterShader::Tag &tag)
143 {
144 ostr << "(ID=" << tag.m_ID << ", group=" << tag.m_group << ")";
145 return ostr;
146 }
147
148 void
149 print_glyph_shader_ids(const fastuidraw::PainterShaderRegistrar &rp,
150 const fastuidraw::PainterGlyphShader &sh)
151 {
152 for(unsigned int i = 0; i < sh.shader_count(); ++i)
153 {
154 enum fastuidraw::glyph_type tp;
155 tp = static_cast<enum fastuidraw::glyph_type>(i);
156 std::cout << "\t\t#" << i << ": " << sh.shader(tp)->tag(rp) << "\n";
157 }
158 }
159
160 void
161 print_stroke_shader_ids(const fastuidraw::PainterShaderRegistrar &rp,
162 const fastuidraw::PainterStrokeShader &shader,
163 const std::string &prefix = "\t\t")
164 {
165 using namespace fastuidraw;
166 vecN<c_string, PainterStrokeShader::number_shader_types> shader_type_labels;
167
168 shader_type_labels[PainterStrokeShader::non_aa_shader] = "non_aa_shader";
169 shader_type_labels[PainterStrokeShader::aa_shader] = "aa_shader";
170
171 for (unsigned int tp = 0; tp < PainterEnums::stroking_method_number_precise_choices; ++tp)
172 {
173 enum PainterEnums::stroking_method_t e_tp;
174
175 e_tp = static_cast<enum PainterEnums::stroking_method_t>(tp);
176 for (unsigned int sh = 0; sh < PainterStrokeShader::number_shader_types; ++sh)
177 {
178 enum PainterStrokeShader::shader_type_t e_sh;
179
180 e_sh = static_cast<enum PainterStrokeShader::shader_type_t>(sh);
181 std::cout << prefix << "(" << PainterEnums::label(e_tp)
182 << ", " << shader_type_labels[e_sh] << "): ";
183
184 if (shader.shader(e_tp, e_sh))
185 {
186 std::cout << shader.shader(e_tp, e_sh)->tag(rp);
187 }
188 else
189 {
190 std::cout << "null-shader";
191 }
192 std::cout << "\n";
193 }
194 }
195 }
196
197 void
198 print_dashed_stroke_shader_ids(const fastuidraw::PainterShaderRegistrar &rp,
199 const fastuidraw::PainterDashedStrokeShaderSet &sh)
200 {
201 std::cout << "\t\tflat_caps:\n";
202 print_stroke_shader_ids(rp, sh.shader(fastuidraw::Painter::flat_caps), "\t\t\t");
203
204 std::cout << "\t\trounded_caps:\n";
205 print_stroke_shader_ids(rp, sh.shader(fastuidraw::Painter::rounded_caps), "\t\t\t");
206
207 std::cout << "\t\tsquare_caps:\n";
208 print_stroke_shader_ids(rp, sh.shader(fastuidraw::Painter::square_caps), "\t\t\t");
209 }
210
211 GLuint
212 ready_pixel_counter_ssbo(unsigned int binding_index)
213 {
214 GLuint return_value(0);
215 uint32_t zero[2] = {0, 0};
216
217 fastuidraw_glGenBuffers(1, &return_value);
218 fastuidraw_glBindBuffer(GL_SHADER_STORAGE_BUFFER, return_value);
219 fastuidraw_glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(uint32_t), zero, GL_STREAM_READ);
220 fastuidraw_glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
221 fastuidraw_glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding_index, return_value);
222
223 return return_value;
224 }
225
226 void
227 update_pixel_counts(GLuint bo, fastuidraw::vecN<uint64_t, 4> &dst)
228 {
229 const uint32_t *p;
230
231 fastuidraw_glBindBuffer(GL_SHADER_STORAGE_BUFFER, bo);
232 p = (const uint32_t*)fastuidraw_glMapBufferRange(GL_SHADER_STORAGE_BUFFER,
233 0, 2 * sizeof(uint32_t), GL_MAP_READ_BIT);
234 dst[sdl_painter_demo::frame_number_pixels] = p[0];
235 dst[sdl_painter_demo::frame_number_pixels_that_neighbor_helper] = p[1];
236 fastuidraw_glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
237 fastuidraw_glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
238 fastuidraw_glDeleteBuffers(1, &bo);
239
240 dst[sdl_painter_demo::total_number_pixels] += dst[sdl_painter_demo::frame_number_pixels];
241 dst[sdl_painter_demo::total_number_pixels_that_neighbor_helper] += dst[sdl_painter_demo::frame_number_pixels_that_neighbor_helper];
242 }
243}
244
245sdl_painter_demo::
246sdl_painter_demo(const std::string &about_text,
247 bool default_value_for_print_painter):
248 sdl_demo(about_text),
249
250 m_image_atlas_options("Image Atlas Options", *this),
251 m_log2_color_tile_size(m_image_atlas_params.log2_color_tile_size(), "log2_color_tile_size",
252 "Specifies the log2 of the width and height of each color tile.",
253 *this),
254 m_log2_num_color_tiles_per_row_per_col(m_image_atlas_params.log2_num_color_tiles_per_row_per_col(),
255 "log2_num_color_tiles_per_row_per_col",
256 "Specifies the log2 of the number of color tiles "
257 "in each row and column of each layer. Note that "
258 "then the total number of color tiles available "
259 "is given as num_color_layers*pow(2, 2*log2_num_color_tiles_per_row_per_col)",
260 *this),
261 m_num_color_layers(m_image_atlas_params.num_color_layers(), "num_color_layers",
262 "Specifies the number of layers in the color texture. Note that "
263 "then the total number of color tiles available is given as "
264 "num_color_layers*pow(2, 2*log2_num_color_tiles_per_row_per_col)"
265 "The number of layers grows to accomodate more images at the cost "
266 "of needing to move color data to new GL textures",
267 *this),
268 m_log2_index_tile_size(m_image_atlas_params.log2_index_tile_size(), "log2_index_tile_size",
269 "Specifies the log2 of the width and height of each index tile. "
270 "A negative value disables image atlasing",
271 *this),
272 m_log2_num_index_tiles_per_row_per_col(m_image_atlas_params.log2_num_index_tiles_per_row_per_col(),
273 "log2_num_index_tiles_per_row_per_col",
274 "Specifies the log2 of the number of index tiles "
275 "in each row and column of each layer; note that "
276 "then the total number of index tiles available "
277 "is given as num_index_layers*pow(2, 2*log2_num_index_tiles_per_row_per_col)",
278 *this),
279 m_num_index_layers(m_image_atlas_params.num_index_layers(), "num_index_layers",
280 "Specifies the intial number of layers in the index texture; "
281 "note that then the total number of index tiles initially available "
282 "is given as num_index_layers*pow(2, 2*log2_num_index_tiles_per_row_per_col) "
283 "The number of layers grows to accomodate more images at the cost "
284 "of needing to move index data to new GL textures",
285 *this),
286 m_support_image_on_atlas(m_image_atlas_params.support_image_on_atlas(),
287 "enabled_image_atlas",
288 "Specifies if image atlasing is enabled. When atlasing is disabled, "
289 "then a draw-call break is made on each different image used unless "
290 "bindless texturing is supported",
291 *this),
292
293 m_glyph_atlas_options("Glyph Atlas options", *this),
294 m_glyph_atlas_size(m_glyph_atlas_params.number_floats(),
295 "glyph_atlas_size", "size of glyph store in floats", *this),
296 m_glyph_backing_store_type(glyph_backing_store_auto,
297 enumerated_string_type<enum glyph_backing_store_t>()
298 .add_entry("texture_buffer",
299 glyph_backing_store_texture_buffer,
300 "use a texture buffer, feature is core in GL but for GLES requires version 3.2, "
301 "for GLES version pre-3.2, requires the extension GL_OES_texture_buffer or the "
302 "extension GL_EXT_texture_buffer")
303 .add_entry("texture_array",
304 glyph_backing_store_texture_array,
305 "use a 2D texture array to store the glyph data, "
306 "GL and GLES have feature in core")
307 .add_entry("storage_buffer",
308 glyph_backing_store_ssbo,
309 "use a shader storage buffer, feature is core starting in GLES 3.1 and available "
310 "in GL starting at version 4.2 or via the extension GL_ARB_shader_storage_buffer")
311 .add_entry("auto",
312 glyph_backing_store_auto,
313 "query context and decide optimal value"),
314 "geometry_backing_store_type",
315 "Determines how the glyph store is backed.",
316 *this),
317 m_glyph_backing_texture_log2_w(10, "glyph_backing_texture_log2_w",
318 "If glyph_backing_store_type is set to texture_array, then "
319 "this gives the log2 of the width of the texture array", *this),
320 m_glyph_backing_texture_log2_h(10, "glyph_backing_texture_log2_h",
321 "If glyph_backing_store_type is set to texture_array, then "
322 "this gives the log2 of the height of the texture array", *this),
323
324 m_colorstop_atlas_options("ColorStop Atlas options", *this),
325 m_color_stop_atlas_width(m_colorstop_atlas_params.width(),
326 "colorstop_atlas_width",
327 "width for color stop atlas", *this),
328 m_color_stop_atlas_layers(m_colorstop_atlas_params.num_layers(),
329 "colorstop_atlas_layers",
330 "number of layers for the color stop atlas",
331 *this),
332
333 m_painter_options("PainterBackendGL Options", *this),
334 m_painter_attributes_per_buffer(m_painter_params.attributes_per_buffer(),
335 "painter_verts_per_buffer",
336 "Number of vertices a single API draw can hold",
337 *this),
338 m_painter_indices_per_buffer(m_painter_params.indices_per_buffer(),
339 "painter_indices_per_buffer",
340 "Number of indices a single API draw can hold",
341 *this),
342 m_painter_number_pools(m_painter_params.number_pools(), "painter_number_pools",
343 "Number of GL object pools used by the painter", *this),
344 m_painter_break_on_shader_change(m_painter_params.break_on_shader_change(),
345 "painter_break_on_shader_change",
346 "If true, different shadings are placed into different "
347 "entries of a call to glMultiDrawElements", *this),
348 m_uber_vert_use_switch(m_painter_params.vert_shader_use_switch(),
349 "painter_uber_vert_use_switch",
350 "If true, use a switch statement in uber vertex shader dispatch",
351 *this),
352 m_uber_frag_use_switch(m_painter_params.frag_shader_use_switch(),
353 "painter_uber_frag_use_switch",
354 "If true, use a switch statement in uber fragment shader dispatch",
355 *this),
356 m_use_uber_item_shader(m_painter_params.use_uber_item_shader(),
357 "painter_use_uber_item_shader",
358 "If true, use an uber-shader for all item shaders",
359 *this),
360 m_uber_blend_use_switch(m_painter_params.blend_shader_use_switch(),
361 "painter_uber_blend_use_switch",
362 "If true, use a switch statement in uber blend shader dispatch",
363 *this),
364 m_separate_program_for_discard(m_painter_params.separate_program_for_discard(),
365 "separate_program_for_discard",
366 "if true, there are two GLSL programs active when drawing: "
367 "one for those item shaders that have discard and one for "
368 "those that do not",
369 *this),
370 m_allow_bindless_texture_from_surface(m_painter_params.allow_bindless_texture_from_surface(),
371 "allow_bindless_texture_from_surface",
372 "if both this is true and the GL/GLES driver supports "
373 "bindless texturing, the the textures of the surfaces "
374 "rendered to will be textured with bindless texturing",
375 *this),
376 m_painter_options_affected_by_context("PainterBackendGL Options that can be overridden "
377 "by version and extension supported by GL/GLES context",
378 *this),
379 m_use_hw_clip_planes(m_painter_params.clipping_type(),
380 enumerated_string_type<clipping_type_t>()
381 .add_entry("on", fastuidraw::gl::PainterEngineGL::clipping_via_gl_clip_distance,
382 "Use HW clip planes via gl_ClipDistance for clipping")
383 .add_entry_alias("true", fastuidraw::gl::PainterEngineGL::clipping_via_gl_clip_distance)
384 .add_entry("off", fastuidraw::gl::PainterEngineGL::clipping_via_discard,
385 "Use discard in fragment shader for clipping")
386 .add_entry_alias("false", fastuidraw::gl::PainterEngineGL::clipping_via_discard)
387 .add_entry("emulate_skip_color_write",
388 fastuidraw::gl::PainterEngineGL::clipping_via_skip_color_write,
389 "Emulate by (virtually) skipping color writes, painter_blend_type "
390 "must be framebuffer_fetch"),
391 "painter_use_hw_clip_planes",
392 "",
393 *this),
394 m_painter_data_blocks_per_buffer(m_painter_params.data_blocks_per_store_buffer(),
395 "painter_blocks_per_buffer",
396 "Number of data blocks a single API draw can hold",
397 *this),
398 m_data_store_backing(m_painter_params.data_store_backing(),
399 enumerated_string_type<data_store_backing_t>()
400 .add_entry("tbo",
401 fastuidraw::gl::PainterEngineGL::data_store_tbo,
402 "use a texture buffer (if available) to back the data store. "
403 "A texture buffer can have a very large maximum size")
404 .add_entry("ubo",
405 fastuidraw::gl::PainterEngineGL::data_store_ubo,
406 "use a uniform buffer object to back the data store. "
407 "A uniform buffer object's maximum size is much smaller than that "
408 "of a texture buffer object usually")
409 .add_entry("ssbo",
410 fastuidraw::gl::PainterEngineGL::data_store_ssbo,
411 "use a shader storage buffer object to back the data store. "
412 "A shader storage buffer can have a very large maximum size"),
413 "painter_data_store_backing_type",
414 "specifies how the data store buffer is backed",
415 *this),
416 m_assign_layout_to_vertex_shader_inputs(m_painter_params.assign_layout_to_vertex_shader_inputs(),
417 "painter_assign_layout_to_vertex_shader_inputs",
418 "If true, use layout(location=) in GLSL shader for vertex shader inputs",
419 *this),
420 m_assign_layout_to_varyings(m_painter_params.assign_layout_to_varyings(),
421 "painter_assign_layout_to_varyings",
422 "If true, use layout(location=) in GLSL shader for varyings", *this),
423 m_assign_binding_points(m_painter_params.assign_binding_points(),
424 "painter_assign_binding_points",
425 "If true, use layout(binding=) in GLSL shader on samplers and buffers", *this),
426 m_support_dual_src_blend_shaders(m_painter_params.support_dual_src_blend_shaders(),
427 "painter_support_dual_src_blending",
428 "If true allow the painter to support dual src blend shaders", *this),
429 m_preferred_blend_type(m_painter_params.preferred_blend_type(),
430 enumerated_string_type<shader_blend_type>()
431 .add_entry("single_src",
432 fastuidraw::PainterBlendShader::single_src,
433 "Use single-source blending")
434 .add_entry("dual_src",
435 fastuidraw::PainterBlendShader::dual_src,
436 "Use dual-source blending")
437 .add_entry("framebuffer_fetch",
438 fastuidraw::PainterBlendShader::framebuffer_fetch,
439 "Use framebuffer-fetch or interlock, depending on the value of painter_fbf_blending_type"),
440 "painter_preferred_blend_type",
441 "Specifies how to implement all blend shader mode for all those except those "
442 "that cannot be performed with 3D API blending",
443 *this),
444 m_fbf_blending_type(m_painter_params.fbf_blending_type(),
445 enumerated_string_type<fbf_blending_type_t>()
446 .add_entry("framebuffer_fetch",
447 fastuidraw::glsl::PainterShaderRegistrarGLSL::fbf_blending_framebuffer_fetch,
448 "use a framebuffer fetch (if available) to perform blending, "
449 "that cannot be performed with 3D API blending")
450 .add_entry("interlock",
451 fastuidraw::glsl::PainterShaderRegistrarGLSL::fbf_blending_interlock,
452 "use image-load store together with interlock (if both available) "
453 "to perform blending that cannot be performed with 3D API blending")
454 .add_entry("none",
455 fastuidraw::glsl::PainterShaderRegistrarGLSL::fbf_blending_not_supported,
456 "Do not support the blend shaders that cannot be performed with 3D API blending"),
457 "painter_fbf_blending_type",
458 "specifies if/how the painter will perform blending for those blend shaders "
459 "that cannot be performed with 3D API blending",
460 *this),
461 m_painter_optimal(painter_optimal_rendering,
462 enumerated_string_type<enum painter_optimal_t>()
463 .add_entry("painter_no_optimal",
464 painter_no_optimal,
465 "Do not query GL/GLES context to configure options and rely "
466 "on the values passed to the command line. Values not possible "
467 "to do by the GL/GLES context will be overriden")
468 .add_entry("painter_optimal_performance",
469 painter_optimal_performance,
470 "Query the GL/GLES context to configure options for optimal "
471 "performance. Additional options set by command line will "
472 "override the values")
473 .add_entry("painter_optimal_rendering",
474 painter_optimal_rendering,
475 "Query the GL/GLES context to configure options for optimal "
476 "rendering quality. Additional options set by command line will "
477 "override the values"),
478 "painter_optimal_auto",
479 "Decide how to initially configure the Painter",
480 *this),
481 m_demo_options("Demo Options", *this),
482 m_print_painter_config(default_value_for_print_painter,
483 "print_painter_config",
484 "Print PainterBackendGL config", *this),
485 m_print_painter_shader_ids(default_value_for_print_painter,
486 "print_painter_shader_ids",
487 "Print PainterBackendGL shader IDs", *this),
488 m_pixel_counter_stack(-1, "pixel_counter_latency",
489 "If non-negative, will add code to the painter ubder- shader "
490 "to count number of helper and non-helper pixels. The value "
491 "is how many frames to wait before reading the values from the "
492 "atomic buffers that are updated", *this),
493 m_distance_field_pixel_size(fastuidraw::GlyphGenerateParams::distance_field_pixel_size(),
494 "glyph_distance_field_pixel_size",
495 "Pixel size at which to generate distance field glyphs",
496 *this),
497 m_distance_field_max_distance(fastuidraw::GlyphGenerateParams::distance_field_max_distance(),
498 "glyph_distance_field_max_distance",
499 "Max distance value in pixels to use when generating "
500 "distance field glyphs; the texels of a distance field "
501 "glyph are always stored in fixed point 8-bits normalized "
502 "to [0,1]. This field gives the clamping and conversion "
503 "to [0,1]", *this),
504 m_restricted_rays_max_recursion(fastuidraw::GlyphGenerateParams::restricted_rays_max_recursion(),
505 "glyph_restricted_rays_max_recursion",
506 "Maximum level of recursion used when creating restricted rays glyphs",
507 *this),
508 m_restricted_rays_split_thresh(fastuidraw::GlyphGenerateParams::restricted_rays_split_thresh(),
509 "glyph_restricted_rays_split_thresh",
510 "Splitting threshhold used when creating restricted rays glyphs",
511 *this),
512 m_restricted_rays_expected_min_render_size(fastuidraw::GlyphGenerateParams::restricted_rays_minimum_render_size(),
513 "glyph_restricted_rays_expected_min_render_size",
514 "",
515 *this),
516 m_banded_rays_max_recursion(fastuidraw::GlyphGenerateParams::banded_rays_max_recursion(),
517 "glyph_banded_rays_max_recursion",
518 "Maximum level of recursion to use when generating banded-ray glyphs",
519 *this),
520 m_banded_rays_average_number_curves_thresh(fastuidraw::GlyphGenerateParams::banded_rays_average_number_curves_thresh(),
521 "glyph_banded_rays_average_number_curves_thresh",
522 "Threshhold to aim for number of curves per band when generating "
523 "banded-ray glyphs",
524 *this),
525 m_num_pixel_counter_buffers(0),
526 m_pixel_counts(0, 0, 0, 0),
527 m_painter_stats(fastuidraw::Painter::number_stats(), 0)
528{}
529
530sdl_painter_demo::
531~sdl_painter_demo()
532{
533 for (GLuint bo : m_pixel_counter_buffers)
534 {
535 fastuidraw_glDeleteBuffers(1, &bo);
536 }
537}
538
539void
540sdl_painter_demo::
541init_gl(int w, int h)
542{
543 int max_layers(0);
544
545 max_layers = fastuidraw::gl::context_get<GLint>(GL_MAX_ARRAY_TEXTURE_LAYERS);
546 if (max_layers < m_num_color_layers.value())
547 {
548 std::cout << "num_color_layers exceeds max number texture layers (" << max_layers
549 << "), num_color_layers set to that value.\n";
550 m_num_color_layers.value() = max_layers;
551 }
552
553 if (max_layers < m_color_stop_atlas_layers.value())
554 {
555 std::cout << "atlas_layers exceeds max number texture layers (" << max_layers
556 << "), atlas_layers set to that value.\n";
557 m_color_stop_atlas_layers.value() = max_layers;
558 }
559
560 if (m_painter_optimal.value() != painter_no_optimal)
561 {
562 m_painter_params.configure_from_context(m_painter_optimal.value() == painter_optimal_rendering);
563 }
564
565#define APPLY_PARAM(X, Y) do { \
566 if (Y.set_by_command_line()) \
567 { \
568 std::cout << "Apply: "#X": " << Y.value() \
569 << "\n"; m_painter_params.X(Y.value()); \
570 } \
571 } while (0)
572
573 APPLY_PARAM(attributes_per_buffer, m_painter_attributes_per_buffer);
574 APPLY_PARAM(indices_per_buffer, m_painter_indices_per_buffer);
575 APPLY_PARAM(data_blocks_per_store_buffer, m_painter_data_blocks_per_buffer);
576 APPLY_PARAM(number_pools, m_painter_number_pools);
577 APPLY_PARAM(break_on_shader_change, m_painter_break_on_shader_change);
578 APPLY_PARAM(clipping_type, m_use_hw_clip_planes);
579 APPLY_PARAM(vert_shader_use_switch, m_uber_vert_use_switch);
580 APPLY_PARAM(frag_shader_use_switch, m_uber_frag_use_switch);
581 APPLY_PARAM(blend_shader_use_switch, m_uber_blend_use_switch);
582 APPLY_PARAM(data_store_backing, m_data_store_backing);
583 APPLY_PARAM(assign_layout_to_vertex_shader_inputs, m_assign_layout_to_vertex_shader_inputs);
584 APPLY_PARAM(assign_layout_to_varyings, m_assign_layout_to_varyings);
585 APPLY_PARAM(assign_binding_points, m_assign_binding_points);
586 APPLY_PARAM(separate_program_for_discard, m_separate_program_for_discard);
587 APPLY_PARAM(allow_bindless_texture_from_surface, m_allow_bindless_texture_from_surface);
588 APPLY_PARAM(preferred_blend_type, m_preferred_blend_type);
589 APPLY_PARAM(fbf_blending_type, m_fbf_blending_type);
590 APPLY_PARAM(support_dual_src_blend_shaders, m_support_dual_src_blend_shaders);
591 APPLY_PARAM(use_uber_item_shader, m_use_uber_item_shader);
592
593#undef APPLY_PARAM
594
595#define APPLY_IMAGE_PARAM(X, Y) do { \
596 if (Y.set_by_command_line()) \
597 { \
598 std::cout << "Apply: "#X": " << Y.value() \
599 << "\n"; m_image_atlas_params.X(Y.value()); \
600 } \
601 } while (0)
602
603 m_image_atlas_params = m_painter_params.image_atlas_params();
604 APPLY_IMAGE_PARAM(log2_color_tile_size, m_log2_color_tile_size);
605 APPLY_IMAGE_PARAM(log2_num_color_tiles_per_row_per_col, m_log2_num_color_tiles_per_row_per_col);
606 APPLY_IMAGE_PARAM(num_color_layers, m_num_color_layers);
607 APPLY_IMAGE_PARAM(log2_index_tile_size, m_log2_index_tile_size);
608 APPLY_IMAGE_PARAM(log2_num_index_tiles_per_row_per_col, m_log2_num_index_tiles_per_row_per_col);
609 APPLY_IMAGE_PARAM(num_index_layers, m_num_index_layers);
610 APPLY_IMAGE_PARAM(support_image_on_atlas, m_support_image_on_atlas);
611
612#undef APPLY_IMAGE_PARAM
613
614 m_glyph_atlas_params = m_painter_params.glyph_atlas_params();
615 m_glyph_atlas_params.number_floats(m_glyph_atlas_size.value());
616 switch(m_glyph_backing_store_type.value())
617 {
618 case glyph_backing_store_texture_buffer:
619 m_glyph_atlas_params.use_texture_buffer_store();
620 break;
621
622 case glyph_backing_store_texture_array:
623 m_glyph_atlas_params.use_texture_2d_array_store(m_glyph_backing_texture_log2_w.value(),
624 m_glyph_backing_texture_log2_h.value());
625 break;
626
627 case glyph_backing_store_ssbo:
628 m_glyph_atlas_params.use_storage_buffer_store();
629 break;
630
631 default:
632 m_glyph_atlas_params.use_optimal_store_backing();
633 switch(m_glyph_atlas_params.glyph_data_backing_store_type())
634 {
635 case fastuidraw::glsl::PainterShaderRegistrarGLSL::glyph_data_tbo:
636 {
637 std::cout << "Glyph Store: auto selected texture buffer\n";
638 }
639 break;
640
641 case fastuidraw::glsl::PainterShaderRegistrarGLSL::glyph_data_ssbo:
642 {
643 std::cout << "Glyph Store: auto selected storage buffer\n";
644 }
645 break;
646
647 case fastuidraw::glsl::PainterShaderRegistrarGLSL::glyph_data_texture_array:
648 {
649 fastuidraw::ivec2 log2_dims(m_glyph_atlas_params.texture_2d_array_store_log2_dims());
650 std::cout << "Glyph Store: auto selected texture with dimensions: (2^"
651 << log2_dims.x() << ", 2^" << log2_dims.y() << ") = "
652 << fastuidraw::ivec2(1 << log2_dims.x(), 1 << log2_dims.y())
653 << "\n";
654 }
655 break;
656 }
657 }
658
659 m_colorstop_atlas_params = m_painter_params.colorstop_atlas_params();
660 m_colorstop_atlas_params
661 .width(m_color_stop_atlas_width.value())
662 .num_layers(m_color_stop_atlas_layers.value());
663
664 if (!m_color_stop_atlas_width.set_by_command_line())
665 {
666 m_colorstop_atlas_params.optimal_width();
667 std::cout << "Colorstop Atlas optimal width selected to be "
668 << m_colorstop_atlas_params.width() << "\n";
669 }
670
671 m_painter_params
672 .image_atlas_params(m_image_atlas_params)
673 .glyph_atlas_params(m_glyph_atlas_params)
674 .colorstop_atlas_params(m_colorstop_atlas_params);
675
676 if (m_pixel_counter_stack.value() >= 0)
677 {
678 fastuidraw::c_string version;
679 #ifdef FASTUIDRAW_GL_USE_GLES
680 {
681 version = "310 es";
682 }
683 #else
684 {
685 version = "450";
686 }
687 #endif
688 m_painter_params.glsl_version_override(version);
689 }
690
691 m_backend = fastuidraw::gl::PainterEngineGL::create(m_painter_params);
692
693 fastuidraw::GlyphGenerateParams::distance_field_max_distance(m_distance_field_max_distance.value());
694 fastuidraw::GlyphGenerateParams::distance_field_pixel_size(m_distance_field_pixel_size.value());
695 fastuidraw::GlyphGenerateParams::restricted_rays_max_recursion(m_restricted_rays_max_recursion.value());
696 fastuidraw::GlyphGenerateParams::restricted_rays_split_thresh(m_restricted_rays_split_thresh.value());
697 fastuidraw::GlyphGenerateParams::restricted_rays_minimum_render_size(m_restricted_rays_expected_min_render_size.value());
698 fastuidraw::GlyphGenerateParams::banded_rays_max_recursion(m_banded_rays_max_recursion.value());
699 fastuidraw::GlyphGenerateParams::banded_rays_average_number_curves_thresh(m_banded_rays_average_number_curves_thresh.value());
700
701 m_painter = FASTUIDRAWnew fastuidraw::Painter(m_backend);
702 m_font_database = FASTUIDRAWnew fastuidraw::FontDatabase();
703 m_ft_lib = FASTUIDRAWnew fastuidraw::FreeTypeLib();
704
705 if (m_pixel_counter_stack.value() >= 0)
706 {
707 fastuidraw::c_string code;
708 fastuidraw::reference_counted_ptr<fastuidraw::glsl::PainterShaderRegistrarGLSL> R;
709
710 m_pixel_counter_buffer_binding_index = fastuidraw::gl::context_get<GLint>(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS) - 1;
711 code =
712 "layout(binding = PIXEL_COUNTER_BINDING) buffer pixel_counter_buffer\n"
713 "{\n"
714 "\tuint num_pixels;\n"
715 "\tuint num_neighbor_helper_pixels;\n"
716 "};\n"
717 "void real_main(void);\n"
718 "void main(void)\n"
719 "{\n"
720 "\tfloat f;\n"
721 "\tf = float(gl_HelperInvocation);\n"
722 "\tatomicAdd(num_pixels, 1u);\n"
723 "\tif(abs(dFdxFine(f)) > 0.0 || abs(dFdyFine(f)) > 0.0)\n"
724 "\t\tatomicAdd(num_neighbor_helper_pixels, 1u);\n"
725 "\treal_main();\n"
726 "}\n";
727
728 R = static_cast<fastuidraw::glsl::PainterShaderRegistrarGLSL*>(&m_painter->painter_shader_registrar());
729 R->add_fragment_shader_util(fastuidraw::glsl::ShaderSource()
730 .add_macro("PIXEL_COUNTER_BINDING", m_pixel_counter_buffer_binding_index)
731 .add_source(code, fastuidraw::glsl::ShaderSource::from_string)
732 .add_macro("main", "real_main"));
733 }
734
735 if (m_print_painter_config.value())
736 {
737 std::cout << "\nPainterBackendGL configuration:\n";
738
739 #define LAZY_PARAM(X, Y) do { \
740 std::cout << std::setw(40) << Y.name() << ": " << std::setw(8) \
741 << m_backend->configuration_gl().X() \
742 << " (requested " << m_painter_params.X() << ")\n"; \
743 } while(0)
744
745 #define LAZY_IMAGE_PARAM(X, Y) do { \
746 std::cout << std::setw(40) << Y.name() << ": " << std::setw(8) \
747 << m_backend->configuration_gl().image_atlas_params().X() \
748 << " (requested " << m_painter_params.image_atlas_params().X() << ")\n"; \
749 } while(0)
750
751 #define LAZY_PARAM_ENUM(X, Y) do { \
752 std::cout << std::setw(40) << Y.name() <<": " << std::setw(8) \
753 << make_enum_wrapper(m_backend->configuration_gl().X()) \
754 << " (requested " << make_enum_wrapper(m_painter_params.X()) \
755 << ")\n"; \
756 } while(0)
757
758 #define LAZY_IMAGE_PARAM_ENUM(X, Y) do { \
759 std::cout << std::setw(40) << Y.name() <<": " << std::setw(8) \
760 << make_enum_wrapper(m_backend->configuration_gl().image_atlas_params().X()) \
761 << " (requested " << make_enum_wrapper(m_painter_params.image_atlas_params().X()) \
762 << ")\n"; \
763 } while(0)
764
765 LAZY_PARAM(attributes_per_buffer, m_painter_attributes_per_buffer);
766 LAZY_PARAM(indices_per_buffer, m_painter_indices_per_buffer);
767 LAZY_PARAM(data_blocks_per_store_buffer, m_painter_data_blocks_per_buffer);
768 LAZY_PARAM(number_pools, m_painter_number_pools);
769 LAZY_PARAM_ENUM(break_on_shader_change, m_painter_break_on_shader_change);
770 LAZY_PARAM_ENUM(clipping_type, m_use_hw_clip_planes);
771 LAZY_PARAM_ENUM(vert_shader_use_switch, m_uber_vert_use_switch);
772 LAZY_PARAM_ENUM(frag_shader_use_switch, m_uber_frag_use_switch);
773 LAZY_PARAM(use_uber_item_shader, m_use_uber_item_shader);
774 LAZY_PARAM_ENUM(blend_shader_use_switch, m_uber_blend_use_switch);
775 LAZY_PARAM_ENUM(data_store_backing, m_data_store_backing);
776 LAZY_PARAM_ENUM(assign_layout_to_vertex_shader_inputs, m_assign_layout_to_vertex_shader_inputs);
777 LAZY_PARAM_ENUM(assign_layout_to_varyings, m_assign_layout_to_varyings);
778 LAZY_PARAM_ENUM(assign_binding_points, m_assign_binding_points);
779 LAZY_PARAM_ENUM(separate_program_for_discard, m_separate_program_for_discard);
780 LAZY_PARAM_ENUM(allow_bindless_texture_from_surface, m_allow_bindless_texture_from_surface);
781 LAZY_PARAM_ENUM(preferred_blend_type, m_preferred_blend_type);
782 LAZY_PARAM_ENUM(fbf_blending_type, m_fbf_blending_type);
783 LAZY_PARAM_ENUM(support_dual_src_blend_shaders, m_support_dual_src_blend_shaders);
784 std::cout << std::setw(40) << "geometry_backing_store_type:"
785 << std::setw(8) << m_painter_params.glyph_atlas_params().glyph_data_backing_store_type()
786 << "\n";
787 LAZY_IMAGE_PARAM_ENUM(support_image_on_atlas, m_support_image_on_atlas);
788 if (m_backend->configuration_gl().image_atlas_params().support_image_on_atlas())
789 {
790 LAZY_IMAGE_PARAM(log2_color_tile_size, m_log2_color_tile_size);
791 LAZY_IMAGE_PARAM(log2_num_color_tiles_per_row_per_col, m_log2_num_color_tiles_per_row_per_col);
792 LAZY_IMAGE_PARAM(num_color_layers, m_num_color_layers);
793 LAZY_IMAGE_PARAM(log2_index_tile_size, m_log2_index_tile_size);
794 LAZY_IMAGE_PARAM(log2_num_index_tiles_per_row_per_col, m_log2_num_index_tiles_per_row_per_col);
795 LAZY_IMAGE_PARAM(num_index_layers, m_num_index_layers);
796 }
797
798 #undef LAZY_PARAM
799 #undef LAZY_IMAGE_PARAM
800 #undef LAZY_ENUM_PARAM
801 }
802
803 if (m_print_painter_shader_ids.value())
804 {
805 const fastuidraw::PainterShaderSet &sh(m_painter->default_shaders());
806 const fastuidraw::PainterShaderRegistrar &rp(m_backend->painter_shader_registrar());
807 std::cout << "Default shader IDs:\n";
808
809 std::cout << "\tGlyph Shaders:\n";
810 print_glyph_shader_ids(rp, sh.glyph_shader());
811
812 std::cout << "\tSolid StrokeShaders:\n";
813 print_stroke_shader_ids(rp, sh.stroke_shader());
814
815 std::cout << "\tDashed Stroke Shader:\n";
816 print_dashed_stroke_shader_ids(rp, sh.dashed_stroke_shader());
817
818 std::cout << "\tFill Shader:"
819 << sh.fill_shader().item_shader()->tag(rp) << "\n";
820 }
821
822 m_painter_params = m_backend->configuration_gl();
823 on_resize(w, h);
824 derived_init(w, h);
825}
826
827void
828sdl_painter_demo::
829on_resize(int w, int h)
830{
831 fastuidraw::ivec2 wh(w, h);
832 if (!m_surface || wh != m_surface->dimensions())
833 {
834 fastuidraw::PainterSurface::Viewport vwp(0, 0, w, h);
835
836 m_surface = FASTUIDRAWnew fastuidraw::gl::PainterSurfaceGL(fastuidraw::ivec2(w, h), *m_backend);
837 m_surface->viewport(vwp);
838 }
839}
840
841void
842sdl_painter_demo::
843draw_text(const std::string &text, float pixel_size,
844 const fastuidraw::FontBase *font,
845 fastuidraw::GlyphRenderer renderer,
846 const fastuidraw::PainterData &draw,
847 enum fastuidraw::Painter::screen_orientation orientation)
848{
849 std::istringstream str(text);
850 fastuidraw::GlyphRun run(pixel_size, orientation, m_painter->glyph_cache());
851
852 create_formatted_text(run, orientation, str, font, m_font_database);
853 m_painter->draw_glyphs(draw, run, 0, run.number_glyphs(), renderer);
854}
855
856void
857sdl_painter_demo::
858pre_draw_frame(void)
859{
860 if (m_pixel_counter_stack.value() >= 0)
861 {
862 GLuint bo;
863
864 bo = ready_pixel_counter_ssbo(m_pixel_counter_buffer_binding_index);
865 m_pixel_counter_buffers.push_back(bo);
866 ++m_num_pixel_counter_buffers;
867 }
868}
869
870void
871sdl_painter_demo::
872post_draw_frame(void)
873{
874 if (m_pixel_counter_stack.value() >= 0
875 && m_num_pixel_counter_buffers > m_pixel_counter_stack.value())
876 {
877 GLuint bo;
878
879 bo = m_pixel_counter_buffers.front();
880 update_pixel_counts(bo, m_pixel_counts);
881
882 m_pixel_counter_buffers.pop_front();
883 --m_num_pixel_counter_buffers;
884 }
885 m_painter->query_stats(cast_c_array(m_painter_stats));
886}
887