Misc: VFontCache perf and features, exposing config on prototype side...
This commit is contained in:
parent
ce84652417
commit
b4abde1094
@ -82,7 +82,7 @@ atlas_region_bbox :: #force_inline proc( region : Atlas_Region, local_idx : i32
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_decide_region :: #force_inline proc "contextless" (atlas : Atlas, glyph_buffer_size : Vec2, bounds_size_scaled : Vec2 ) -> (region_kind : Atlas_Region_Kind)
|
||||
{
|
||||
profile(#procedure)
|
||||
// profile(#procedure)
|
||||
glyph_padding_dbl := atlas.glyph_padding * 2
|
||||
padded_bounds := bounds_size_scaled + glyph_padding_dbl
|
||||
|
||||
@ -99,43 +99,6 @@ atlas_decide_region :: #force_inline proc "contextless" (atlas : Atlas, glyph_bu
|
||||
return .None
|
||||
}
|
||||
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_decide_region_branchless :: #force_inline proc "contextless" (
|
||||
atlas: Atlas,
|
||||
glyph_buffer_size : Vec2,
|
||||
bounds_size_scaled : Vec2,
|
||||
) -> Atlas_Region_Kind
|
||||
{
|
||||
profile(#procedure)
|
||||
|
||||
glyph_padding_dbl := atlas.glyph_padding * 2
|
||||
padded_bounds := bounds_size_scaled + glyph_padding_dbl
|
||||
|
||||
slot_size_region_a := vec2(atlas.region_a.slot_size)
|
||||
slot_size_region_b := vec2(atlas.region_b.slot_size)
|
||||
slot_size_region_c := vec2(atlas.region_c.slot_size)
|
||||
slot_size_region_d := vec2(atlas.region_d.slot_size)
|
||||
|
||||
within_a := padded_bounds.x <= slot_size_region_a.x && padded_bounds.y <= slot_size_region_a.y
|
||||
within_b := padded_bounds.x <= slot_size_region_b.x && padded_bounds.y <= slot_size_region_b.y
|
||||
within_c := padded_bounds.x <= slot_size_region_c.x && padded_bounds.y <= slot_size_region_c.y
|
||||
within_d := padded_bounds.x <= slot_size_region_d.x && padded_bounds.y <= slot_size_region_d.y
|
||||
within_buffer := padded_bounds.x <= glyph_buffer_size.x && padded_bounds.y <= glyph_buffer_size.y
|
||||
within_none := cast(i32) ! (within_a || within_b || within_c || within_d )
|
||||
|
||||
score_a := i32(within_a) * -5
|
||||
score_b := i32(within_b) * -4
|
||||
score_c := i32(within_c) * -3
|
||||
score_d := i32(within_d) * -2
|
||||
score_buffer := i32(within_buffer) * -1
|
||||
|
||||
which_ab := min(score_a, score_b)
|
||||
which_cd := min(score_c, score_d)
|
||||
which_region := min(which_ab, which_cd)
|
||||
resolved := min(which_region, score_buffer) + 6
|
||||
return Atlas_Region_Kind(resolved)
|
||||
}
|
||||
|
||||
// Grab an atlas LRU cache slot.
|
||||
@(optimization_mode="favor_size")
|
||||
atlas_reserve_slot :: #force_inline proc ( region : ^Atlas_Region, lru_code : Atlas_Key ) -> (atlas_index : i32)
|
||||
|
@ -35,21 +35,17 @@ Glyph_Draw_Quad :: struct {
|
||||
Glyph_Pack_Entry :: struct #packed {
|
||||
position : Vec2,
|
||||
|
||||
// index : Glyph,
|
||||
// lru_code : Atlas_Key,
|
||||
atlas_index : i32,
|
||||
in_atlas : b8,
|
||||
should_cache : b8,
|
||||
// region_kind : Atlas_Region_Kind,
|
||||
region_pos : Vec2,
|
||||
region_size : Vec2,
|
||||
|
||||
// bounds : Range2,
|
||||
// bounds_scaled : Range2,
|
||||
// bounds_size : Vec2,
|
||||
// bounds_size_scaled : Vec2,
|
||||
over_sample : Vec2,
|
||||
// scale : Vec2,
|
||||
// bounds_scaled : Range2,
|
||||
// bounds_size : Vec2,
|
||||
// bounds_size_scaled : Vec2,
|
||||
// scale : Vec2,
|
||||
over_sample : Vec2, // Only used for oversized glyphs
|
||||
|
||||
shape : Parser_Glyph_Shape,
|
||||
draw_transform : Transform,
|
||||
@ -283,9 +279,7 @@ generate_shapes_draw_list :: #force_inline proc ( ctx : ^Context, font : Font_ID
|
||||
This procedure has no awareness of layers. That should be handled by a higher-order codepath.
|
||||
For this level of codepaths what matters is maximizing memory locality for:
|
||||
* Dealing with shaping (essentially minimizing having to ever deal with it in a hot path if possible)
|
||||
* Metric resolution of glyphs within a shape
|
||||
* Note: It may be better to have the shape to track/store the glyph bounds and lru codes
|
||||
* The shaper has access to the atlas's dependencies and to parser's metrics (including the unscaled bounds).
|
||||
* Dealing with atlas regioning (the expensive region resolution & parser calls are done on the shape pass)
|
||||
|
||||
Pipleine order:
|
||||
* Resolve atlas lru codes and track shape indexes
|
||||
@ -339,7 +333,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
oversized := & glyph_buffer.oversized
|
||||
to_cache := & glyph_buffer.to_cache
|
||||
cached := & glyph_buffer.cached
|
||||
resize_soa_non_zero(glyph_pack, len(shape.glyph_id))
|
||||
resize_soa_non_zero(glyph_pack, len(shape.glyph))
|
||||
|
||||
append_sub_pack :: #force_inline proc ( pack : ^[dynamic]i32, entry : i32 )
|
||||
{
|
||||
@ -355,7 +349,7 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("batching")
|
||||
profile_begin("batching & segregating glyphs")
|
||||
clear(oversized)
|
||||
clear(to_cache)
|
||||
clear(cached)
|
||||
@ -372,17 +366,20 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
assert(false, "FAILED TO ASSGIN REGION")
|
||||
continue
|
||||
}
|
||||
if region_kind == .E
|
||||
when ENABLE_OVERSIZED_GLYPHS
|
||||
{
|
||||
glyph.over_sample = \
|
||||
bounds_size_scaled.x <= glyph_buffer_size.x / 2 &&
|
||||
bounds_size_scaled.y <= glyph_buffer_size.y / 2 ? \
|
||||
{2.0, 2.0} \
|
||||
: {1.0, 1.0}
|
||||
append_sub_pack(oversized, cast(i32) index)
|
||||
continue
|
||||
if region_kind == .E
|
||||
{
|
||||
glyph.over_sample = \
|
||||
bounds_size_scaled.x <= glyph_buffer_size.x / 2 &&
|
||||
bounds_size_scaled.y <= glyph_buffer_size.y / 2 ? \
|
||||
{2.0, 2.0} \
|
||||
: {1.0, 1.0}
|
||||
append_sub_pack(oversized, cast(i32) index)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
glyph.over_sample = glyph_buffer.over_sample
|
||||
region := atlas.regions[region_kind]
|
||||
glyph.atlas_index = lru_get( & region.state, atlas_key )
|
||||
@ -390,13 +387,14 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
// Glyphs are prepared in batches based on the capacity of the batch cache.
|
||||
Prepare_For_Batch:
|
||||
{
|
||||
pack := cached
|
||||
|
||||
// Determine if we hit the limit for this batch.
|
||||
if glyph_buffer.batch_cache.num >= glyph_buffer.batch_cache.cap do break Prepare_For_Batch
|
||||
|
||||
if glyph.atlas_index == - 1
|
||||
{
|
||||
// Check to see if we reached capacity for the atlas
|
||||
if region.next_idx > region.state.capacity
|
||||
if region.next_idx > region.state.capacity
|
||||
{
|
||||
// We will evict LRU. We must predict which LRU will get evicted, and if it's something we've seen then we need to take slowpath and flush batch.
|
||||
next_evict_glyph := lru_get_next_evicted( region.state )
|
||||
@ -406,19 +404,15 @@ generate_shape_draw_list :: proc( draw_list : ^Draw_List, shape : Shaped_Text,
|
||||
break Prepare_For_Batch
|
||||
}
|
||||
}
|
||||
|
||||
profile("append to_cache")
|
||||
// profile_begin("glyph needs caching")
|
||||
glyph.atlas_index = atlas_reserve_slot(region, atlas_key)
|
||||
glyph.region_pos, glyph.region_size = atlas_region_bbox(region ^, glyph.atlas_index)
|
||||
append_sub_pack(to_cache, cast(i32) index)
|
||||
mark_glyph_seen(& glyph_buffer.batch_cache, atlas_key)
|
||||
continue
|
||||
pack = to_cache
|
||||
profile_end()
|
||||
}
|
||||
|
||||
profile("append cached")
|
||||
// profile("append cached")
|
||||
glyph.region_pos, glyph.region_size = atlas_region_bbox(region ^, glyph.atlas_index)
|
||||
append_sub_pack(cached, cast(i32) index)
|
||||
mark_glyph_seen(& glyph_buffer.batch_cache, atlas_key)
|
||||
append_sub_pack(pack, cast(i32) index)
|
||||
continue
|
||||
}
|
||||
|
||||
@ -498,7 +492,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
profile(#procedure)
|
||||
colour := colour
|
||||
|
||||
profile_begin("glyph buffer transform & draw quads compute")
|
||||
profile_begin("glyph transform & draw quads compute")
|
||||
for id, index in cached
|
||||
{
|
||||
// Quad to for drawing atlas slot to target
|
||||
@ -519,7 +513,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
glyph := & glyph_pack[id]
|
||||
bounds := shape.bounds[id]
|
||||
bounds_scaled := mul(bounds, font_scale)
|
||||
glyph_scale := size(bounds_scaled) + glyph_buffer.draw_padding
|
||||
glyph_scale := ceil(size(bounds_scaled) + glyph_buffer.draw_padding)
|
||||
|
||||
f32_allocated_x := cast(f32) glyph_buffer.allocated_x
|
||||
|
||||
@ -596,7 +590,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("generate oversized glyphs draw_list")
|
||||
profile_begin("gen oversized glyphs draw_list")
|
||||
when ENABLE_OVERSIZED_GLYPHS do if len(oversized) > 0
|
||||
{
|
||||
// colour.r = max(colour.a, enable_debug_vis_type)
|
||||
@ -604,7 +598,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
// colour.b = colour.b * f32(cast(i32) ! b32(cast(i32) enable_debug_vis_type))
|
||||
for pack_id, index in oversized {
|
||||
error : Allocator_Error
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph_id[pack_id])
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
||||
assert(error == .None)
|
||||
}
|
||||
for id, index in oversized
|
||||
@ -647,7 +641,8 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
}
|
||||
profile_end()
|
||||
|
||||
generate_cached_draw_list :: #force_inline proc (draw_list : ^Draw_List, glyph_pack : #soa[]Glyph_Pack_Entry, sub_pack : []i32, colour : RGBAN )
|
||||
@(optimization_mode = "favor_size")
|
||||
generate_blit_from_atlas_draw_list :: #force_inline proc (draw_list : ^Draw_List, glyph_pack : #soa[]Glyph_Pack_Entry, sub_pack : []i32, colour : RGBAN )
|
||||
{
|
||||
profile(#procedure)
|
||||
call := Draw_Call_Default
|
||||
@ -655,7 +650,7 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
call.colour = colour
|
||||
for id, index in sub_pack
|
||||
{
|
||||
profile("glyph")
|
||||
// profile("glyph")
|
||||
call.start_index = u32(len(draw_list.indices))
|
||||
|
||||
quad := glyph_pack[id].draw_quad
|
||||
@ -673,13 +668,13 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
{
|
||||
for pack_id, index in to_cache {
|
||||
error : Allocator_Error
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph_id[pack_id])
|
||||
glyph_pack[pack_id].shape, error = parser_get_glyph_shape(entry.parser_info, shape.glyph[pack_id])
|
||||
assert(error == .None)
|
||||
}
|
||||
|
||||
for id, index in to_cache
|
||||
{
|
||||
profile("glyph")
|
||||
// profile("glyph")
|
||||
glyph := & glyph_pack[id]
|
||||
bounds := shape.bounds[id]
|
||||
bounds_scaled := mul(bounds, font_scale)
|
||||
@ -707,11 +702,13 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
|
||||
dst_glyph_pos := glyph.region_pos
|
||||
dst_glyph_size := bounds_size_scaled + atlas.glyph_padding
|
||||
dst_glyph_size.x = ceil(dst_glyph_size.x)
|
||||
dst_glyph_size.y = max(dst_glyph_size.y, ceil(dst_glyph_size.y) * glyph_buffer.snap_glyph_height) // Note(Ed): Seems to improve hinting
|
||||
to_glyph_buffer_space( & dst_glyph_pos, & dst_glyph_size, atlas_size )
|
||||
|
||||
src_position := Vec2 { glyph.buffer_x, 0 }
|
||||
src_size := (bounds_size_scaled + atlas.glyph_padding) * glyph_buffer.over_sample
|
||||
src_size.x = ceil(src_size.x)
|
||||
src_size.y = max(src_size.y, ceil(src_size.y) * glyph_buffer.snap_glyph_height) // Note(Ed): Seems to improve hinting
|
||||
to_target_space( & src_position, & src_size, glyph_buffer_size )
|
||||
|
||||
@ -740,20 +737,20 @@ batch_generate_glyphs_draw_list :: proc ( draw_list : ^Draw_List,
|
||||
flush_glyph_buffer_draw_list(draw_list, & glyph_buffer.draw_list, & glyph_buffer.clear_draw_list, & glyph_buffer.allocated_x)
|
||||
for id, index in to_cache do parser_free_shape(entry.parser_info, glyph_pack[id].shape)
|
||||
|
||||
profile_begin("generate_cached_draw_list: cached")
|
||||
profile_begin("gen_cached_draw_list: to_cache")
|
||||
colour.r = max(colour.r, 1.0 * enable_debug_vis_type)
|
||||
colour.g = max(colour.g, 1.0 * enable_debug_vis_type)
|
||||
colour.b = max(colour.b, 1.0 * enable_debug_vis_type)
|
||||
generate_cached_draw_list( draw_list, glyph_pack[:], to_cache, colour )
|
||||
generate_blit_from_atlas_draw_list( draw_list, glyph_pack[:], to_cache, colour )
|
||||
profile_end()
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("generate_cached_draw_list: to_cache")
|
||||
profile_begin("gen_cached_draw_list: cached")
|
||||
colour.r = max(colour.r, 0.80 * enable_debug_vis_type)
|
||||
colour.g = max(colour.g, 0.25 * enable_debug_vis_type)
|
||||
colour.b = max(colour.b, 0.25 * enable_debug_vis_type)
|
||||
generate_cached_draw_list( draw_list, glyph_pack[:], cached, colour )
|
||||
generate_blit_from_atlas_draw_list( draw_list, glyph_pack[:], cached, colour )
|
||||
profile_end()
|
||||
}
|
||||
|
||||
|
@ -32,23 +32,6 @@ reload_map :: #force_inline proc( self : ^map [$KeyType] $EntryType, allocator :
|
||||
|
||||
to_bytes :: #force_inline proc "contextless" ( typed_data : ^$Type ) -> []byte { return slice_ptr( transmute(^byte) typed_data, size_of(Type) ) }
|
||||
|
||||
// Provides the nearest prime number value for the given capacity
|
||||
// closest_prime :: proc( capacity : uint ) -> uint
|
||||
// {
|
||||
// prime_table : []uint = {
|
||||
// 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
|
||||
// 49157, 98317, 196613, 393241, 786433, 1572869, 3145739,
|
||||
// 6291469, 12582917, 25165843, 50331653, 100663319,
|
||||
// 201326611, 402653189, 805306457, 1610612741, 3221225473, 6442450941
|
||||
// };
|
||||
// for slot in prime_table {
|
||||
// if slot >= capacity {
|
||||
// return slot
|
||||
// }
|
||||
// }
|
||||
// return prime_table[len(prime_table) - 1]
|
||||
// }
|
||||
|
||||
@(optimization_mode="favor_size")
|
||||
djb8_hash :: #force_inline proc "contextless" ( hash : ^$Type, bytes : []byte ) { for value in bytes do (hash^) = (( (hash^) << 8) + (hash^) ) + Type(value) }
|
||||
|
||||
|
@ -118,7 +118,7 @@ parser_unload_font :: proc( font : ^Parser_Font_Info )
|
||||
|
||||
parser_find_glyph_index :: #force_inline proc "contextless" ( font : Parser_Font_Info, codepoint : rune ) -> (glyph_index : Glyph)
|
||||
{
|
||||
profile(#procedure)
|
||||
// profile(#procedure)
|
||||
// switch font.kind
|
||||
// {
|
||||
// case .Freetype:
|
||||
@ -227,8 +227,7 @@ parser_get_font_vertical_metrics :: #force_inline proc "contextless" ( font : Pa
|
||||
|
||||
parser_get_bounds :: #force_inline proc "contextless" ( font : Parser_Font_Info, glyph_index : Glyph ) -> (bounds : Range2)
|
||||
{
|
||||
profile(#procedure)
|
||||
|
||||
// profile(#procedure)
|
||||
bounds_0, bounds_1 : Vec2i
|
||||
|
||||
// switch font.kind
|
||||
@ -302,7 +301,7 @@ parser_is_glyph_empty :: #force_inline proc "contextless" ( font : Parser_Font_I
|
||||
|
||||
parser_scale :: #force_inline proc "contextless" ( font : Parser_Font_Info, size : f32 ) -> f32
|
||||
{
|
||||
profile(#procedure)
|
||||
// profile(#procedure)
|
||||
// size_scale := size < 0.0 ? parser_scale_for_pixel_height( font, -size ) : parser_scale_for_mapping_em_to_pixels( font, size )
|
||||
size_scale := size > 0.0 ? parser_scale_for_pixel_height( font, size ) : parser_scale_for_mapping_em_to_pixels( font, -size )
|
||||
return size_scale
|
||||
|
@ -6,7 +6,7 @@ Note(Ed): The only reason I didn't directly use harfbuzz is because hamza exists
|
||||
import "core:c"
|
||||
import "thirdparty:harfbuzz"
|
||||
|
||||
Shape_Key :: u32
|
||||
Shape_Key :: u64
|
||||
|
||||
/* A text whose codepoints have had their relevant glyphs and
|
||||
associated data resolved for processing in a draw list generation stage.
|
||||
@ -26,14 +26,16 @@ Shape_Key :: u32
|
||||
your not going to be satisfied with keeping that in the iteration).
|
||||
*/
|
||||
Shaped_Text :: struct #packed {
|
||||
glyph_id : [dynamic]Glyph,
|
||||
glyph : [dynamic]Glyph,
|
||||
position : [dynamic]Vec2,
|
||||
atlas_lru_code : [dynamic]Atlas_Key,
|
||||
region_kind : [dynamic]Atlas_Region_Kind,
|
||||
bounds : [dynamic]Range2,
|
||||
bounds : [dynamic]Range2,
|
||||
// TODO(Ed): Profile if its worth not doing compute for these per frame.
|
||||
// bounds_scaled : [dynamic]Range2,
|
||||
// bounds_size : [dynamic]Vec2,
|
||||
// bounds_size_Scaled : [dynamic]Vec2,
|
||||
atlas_bbox : [dynamic]Transform,
|
||||
end_cursor_pos : Vec2,
|
||||
size : Vec2,
|
||||
}
|
||||
@ -165,7 +167,7 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
{
|
||||
hb_glyph := glyph_infos[ index ]
|
||||
hb_gposition := glyph_positions[ index ]
|
||||
glyph_id := cast(Glyph) hb_glyph.codepoint
|
||||
glyph := cast(Glyph) hb_glyph.codepoint
|
||||
|
||||
if hb_glyph.cluster > 0
|
||||
{
|
||||
@ -196,9 +198,9 @@ shaper_shape_harfbuzz :: proc( ctx : ^Shaper_Context, text_utf8 : string, entry
|
||||
(position^) += advance
|
||||
(max_line_width^) = max(max_line_width^, position.x)
|
||||
|
||||
is_empty := parser_is_glyph_empty(entry.parser_info, glyph_id)
|
||||
is_empty := parser_is_glyph_empty(entry.parser_info, glyph)
|
||||
if ! is_empty {
|
||||
append( & output.glyph_id, glyph_id )
|
||||
append( & output.glyph, glyph )
|
||||
append( & output.position, glyph_pos)
|
||||
}
|
||||
}
|
||||
@ -277,47 +279,30 @@ shaper_shape_text_uncached_advanced :: #force_inline proc( ctx : ^Shaper_Context
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
|
||||
clear( & output.glyph_id )
|
||||
clear( & output.glyph )
|
||||
clear( & output.position )
|
||||
|
||||
shaper_shape_harfbuzz( ctx, text_utf8, entry, font_px_size, font_scale, output )
|
||||
|
||||
// Resolve each glyphs: bounds, atlas lru, and the atlas region as we have everything we need now.
|
||||
|
||||
resize( & output.atlas_lru_code, len(output.glyph_id) )
|
||||
resize( & output.region_kind, len(output.glyph_id) )
|
||||
resize( & output.bounds, len(output.glyph_id) )
|
||||
// resize( & output.bounds_scaled, len(output.glyph_id) )
|
||||
|
||||
profile_begin("bounds")
|
||||
for id, index in output.glyph_id
|
||||
{
|
||||
bounds := & output.bounds[index]
|
||||
// bounds_scaled := & output.bounds_scaled[index]
|
||||
// bounds_size := & output.bounds_size[index]
|
||||
// bounds_size_scaled := & output.bounds_size_scaled[index]
|
||||
// scale := & output.scale[index]
|
||||
(bounds ^) = parser_get_bounds( entry.parser_info, id )
|
||||
// (bounds_scaled ^) = { bounds.p0 * font_scale, bounds.p1 * font_scale }
|
||||
// bounds_size = bounds.p1 - bounds.p0
|
||||
// bounds_size_scaled = bounds_size * font_scale
|
||||
// scale = glyph.bounds_size_scaled + atlas.glyph_padding
|
||||
}
|
||||
profile_end()
|
||||
resize( & output.atlas_lru_code, len(output.glyph) )
|
||||
resize( & output.region_kind, len(output.glyph) )
|
||||
resize( & output.bounds, len(output.glyph) )
|
||||
|
||||
profile_begin("atlas_lru_code")
|
||||
for id, index in output.glyph_id
|
||||
for id, index in output.glyph
|
||||
{
|
||||
output.atlas_lru_code[index] = atlas_glyph_lru_code(entry.id, font_px_size, id)
|
||||
}
|
||||
profile_end()
|
||||
|
||||
profile_begin("region")
|
||||
for id, index in output.glyph_id
|
||||
profile_begin("bounds & region")
|
||||
for id, index in output.glyph
|
||||
{
|
||||
bounds := & output.bounds[index]
|
||||
bounds_size_scaled := (bounds.p1 - bounds.p0) * font_scale
|
||||
|
||||
bounds := & output.bounds[index]
|
||||
(bounds ^) = parser_get_bounds( entry.parser_info, id )
|
||||
bounds_size_scaled := (bounds.p1 - bounds.p0) * font_scale
|
||||
output.region_kind[index] = atlas_decide_region( atlas, glyph_buffer_size, bounds_size_scaled )
|
||||
}
|
||||
profile_end()
|
||||
@ -337,7 +322,7 @@ shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
|
||||
clear( & output.glyph_id )
|
||||
clear( & output.glyph )
|
||||
clear( & output.position )
|
||||
|
||||
line_height := (entry.ascent - entry.descent + entry.line_gap) * font_scale
|
||||
@ -371,7 +356,7 @@ shaper_shape_text_latin :: proc( ctx : ^Shaper_Context,
|
||||
is_glyph_empty := parser_is_glyph_empty( entry.parser_info, glyph_index )
|
||||
if ! is_glyph_empty
|
||||
{
|
||||
append( & output.glyph_id, glyph_index)
|
||||
append( & output.glyph, glyph_index)
|
||||
append( & output.position, Vec2 {
|
||||
ceil(position.x),
|
||||
ceil(position.y)
|
||||
|
@ -11,7 +11,7 @@ import "base:runtime"
|
||||
DISABLE_PROFILING :: false
|
||||
ENABLE_OVERSIZED_GLYPHS :: true
|
||||
|
||||
Font_ID :: distinct i32
|
||||
Font_ID :: distinct i16
|
||||
Glyph :: distinct i32
|
||||
|
||||
Load_Font_Error :: enum(i32) {
|
||||
@ -138,9 +138,9 @@ Init_Glyph_Draw_Params_Default :: Init_Glyph_Draw_Params {
|
||||
snap_glyph_height = true,
|
||||
over_sample = 4,
|
||||
draw_padding = Init_Atlas_Params_Default.glyph_padding,
|
||||
shape_gen_scratch_reserve = 10 * 1024,
|
||||
buffer_glyph_limit = 4,
|
||||
batch_glyph_limit = 512,
|
||||
shape_gen_scratch_reserve = 4 * 1024,
|
||||
buffer_glyph_limit = 16,
|
||||
batch_glyph_limit = 2 * 1024,
|
||||
}
|
||||
|
||||
Init_Shaper_Params :: struct {
|
||||
@ -166,7 +166,7 @@ Init_Shape_Cache_Params :: struct {
|
||||
|
||||
Init_Shape_Cache_Params_Default :: Init_Shape_Cache_Params {
|
||||
capacity = 10 * 1024,
|
||||
reserve = 1024,
|
||||
reserve = 512,
|
||||
}
|
||||
|
||||
//#region("lifetime")
|
||||
@ -178,8 +178,8 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
glyph_draw_params := Init_Glyph_Draw_Params_Default,
|
||||
shape_cache_params := Init_Shape_Cache_Params_Default,
|
||||
shaper_params := Init_Shaper_Params_Default,
|
||||
alpha_sharpen : f32 = 0.2,
|
||||
px_scalar : f32 = 1.0,
|
||||
alpha_sharpen : f32 = 0.15,
|
||||
px_scalar : f32 = 2.0,
|
||||
|
||||
// Curve quality to use for a font when unspecified,
|
||||
// Affects step size for bezier curve passes in generate_glyph_pass_draw_list
|
||||
@ -226,7 +226,7 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
slot_region_c := Vec2i { 64, 64 } * i32(atlas.size_multiplier)
|
||||
slot_region_b := Vec2i { 32, 64 } * i32(atlas.size_multiplier)
|
||||
slot_region_d := Vec2i { 128, 128 } * i32(atlas.size_multiplier)
|
||||
|
||||
|
||||
init_atlas_region :: proc( region : ^Atlas_Region, atlas_size, slot_size : Vec2i, factor : Vec2i )
|
||||
{
|
||||
region.next_idx = 0;
|
||||
@ -274,7 +274,7 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType,
|
||||
{
|
||||
stroage_entry := & shape_cache.storage[idx]
|
||||
|
||||
stroage_entry.glyph_id, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve )
|
||||
stroage_entry.glyph, error = make( [dynamic]Glyph, len = 0, cap = shape_cache_params.reserve )
|
||||
assert( error == .None, "VEFontCache.init : Failed to allocate glyphs array for shape cache storage" )
|
||||
|
||||
stroage_entry.position, error = make( [dynamic]Vec2, len = 0, cap = shape_cache_params.reserve )
|
||||
@ -380,7 +380,7 @@ hot_reload :: proc( ctx : ^Context, allocator : Allocator )
|
||||
lru_reload( & shape_cache.state, allocator )
|
||||
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
|
||||
storage_entry := & shape_cache.storage[idx]
|
||||
reload_array( & storage_entry.glyph_id, allocator)
|
||||
reload_array( & storage_entry.glyph, allocator)
|
||||
reload_array( & storage_entry.position, allocator)
|
||||
reload_array( & storage_entry.atlas_lru_code, allocator)
|
||||
reload_array( & storage_entry.region_kind, allocator)
|
||||
@ -432,7 +432,7 @@ shutdown :: proc( ctx : ^Context )
|
||||
|
||||
for idx : i32 = 0; idx < i32(len(shape_cache.storage)); idx += 1 {
|
||||
storage_entry := & shape_cache.storage[idx]
|
||||
delete( storage_entry.glyph_id )
|
||||
delete( storage_entry.glyph )
|
||||
delete( storage_entry.position )
|
||||
delete( storage_entry.atlas_lru_code)
|
||||
delete( storage_entry.region_kind)
|
||||
@ -471,7 +471,7 @@ clear_shape_cache :: proc (ctx : ^Context)
|
||||
stroage_entry := & ctx.shape_cache.storage[idx]
|
||||
stroage_entry.end_cursor_pos = {}
|
||||
stroage_entry.size = {}
|
||||
clear(& stroage_entry.glyph_id)
|
||||
clear(& stroage_entry.glyph)
|
||||
clear(& stroage_entry.position)
|
||||
}
|
||||
ctx.shape_cache.next_cache_id = 0
|
||||
@ -486,18 +486,18 @@ load_font :: proc( ctx : ^Context, label : string, data : []byte, glyph_curve_qu
|
||||
|
||||
entries := & ctx.entries
|
||||
|
||||
id : i32 = -1
|
||||
id : Font_ID = -1
|
||||
|
||||
for index : i32 = 0; index < i32(len(entries)); index += 1 {
|
||||
if entries[index].used do continue
|
||||
id = index
|
||||
id = Font_ID(index)
|
||||
break
|
||||
}
|
||||
if id == -1 {
|
||||
append_elem( entries, Entry {})
|
||||
id = cast(i32) len(entries) - 1
|
||||
id = cast(Font_ID) len(entries) - 1
|
||||
}
|
||||
assert( id >= 0 && id < i32(len(entries)) )
|
||||
assert( id >= 0 && id < Font_ID(len(entries)) )
|
||||
|
||||
entry := & entries[ id ]
|
||||
{
|
||||
@ -655,11 +655,16 @@ set_colour :: #force_inline proc( ctx : ^Context, colour : RGBA
|
||||
set_draw_type_visualization :: #force_inline proc( ctx : ^Context, should_enable : b32 ) { assert(ctx != nil); ctx.enable_draw_type_visualization = cast(f32) i32(should_enable); }
|
||||
set_px_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.px_scalar = scalar }
|
||||
|
||||
set_snap_glyph_pos :: #force_inline proc( ctx : ^Context, should_snap : b32 ) {
|
||||
set_snap_glyph_shape_position :: #force_inline proc( ctx : ^Context, should_snap : b32 ) {
|
||||
assert(ctx != nil)
|
||||
ctx.shaper_ctx.snap_glyph_position = should_snap
|
||||
}
|
||||
|
||||
set_snap_glyph_render_height :: #force_inline proc( ctx : ^Context, should_snap : b32 ) {
|
||||
assert(ctx != nil)
|
||||
ctx.glyph_buffer.snap_glyph_height = cast(f32) i32(should_snap)
|
||||
}
|
||||
|
||||
// Non-scoping context. The most fundamental interface-level draw shape procedure.
|
||||
// (everything else is either batching/pipelining or quality of life warppers)
|
||||
// Note: Prefer over draw_text_normalized_space if possible to resolve shape once persistently or at least once per frame or non-dirty state.
|
||||
@ -728,7 +733,6 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
adjusted_position := get_snapped_position( ctx^, position )
|
||||
|
||||
|
||||
colour := ctx.colour
|
||||
colour.a = 1.0 + ctx.alpha_sharpen
|
||||
@ -757,7 +761,6 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
draw_shape :: #force_inline proc( ctx : ^Context, position, scale : Vec2, shape : Shaped_Text ) {
|
||||
// peek_position
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ set_profiler_module_context :: #force_inline proc "contextless" ( ctx : ^SpallPr
|
||||
Module_Context = ctx
|
||||
}
|
||||
|
||||
DISABLE_PROFILING :: true
|
||||
DISABLE_PROFILING :: false
|
||||
|
||||
@(deferred_none = profile_end, disabled = DISABLE_PROFILING)
|
||||
profile :: #force_inline proc "contextless" ( name : string, loc := #caller_location ) {
|
||||
|
@ -70,7 +70,7 @@ str_cache_init :: proc( table_allocator, slabs_allocator : Allocator ) -> (cache
|
||||
cache.slab, alloc_error = slab_init( & policy, allocator = slabs_allocator, dbg_name = dbg_name )
|
||||
verify(alloc_error == .None, "Failed to initialize the string cache" )
|
||||
|
||||
cache.table, alloc_error = make( HMapChained(StrCached), 1 * Kilo, table_allocator, dbg_name = dbg_name )
|
||||
cache.table, alloc_error = make( HMapChained(StrCached), 4 * Kilo, table_allocator, dbg_name = dbg_name )
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ sync_sectr_api :: proc( sectr_api : ^sectr.ModuleAPI, memory : ^ClientMemory, lo
|
||||
|
||||
fmt_backing : [16 * Kilobyte] u8
|
||||
|
||||
persistent_backing : [2 * Megabyte] byte
|
||||
persistent_backing : [32 * Megabyte] byte
|
||||
transient_backing : [32 * Megabyte] byte
|
||||
|
||||
main :: proc()
|
||||
@ -292,7 +292,7 @@ main :: proc()
|
||||
// Setup profiling
|
||||
profiler : SpallProfiler
|
||||
{
|
||||
buffer_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE)
|
||||
buffer_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE * 20)
|
||||
profiler.ctx = spall.context_create("sectr.spall")
|
||||
profiler.buffer = spall.buffer_create(buffer_backing)
|
||||
}
|
||||
|
@ -10,8 +10,11 @@ UI_SettingsMenu :: struct
|
||||
zoom_smooth_sensitivity_input : UI_TextInputBox,
|
||||
zoom_digital_sensitivity_input : UI_TextInputBox,
|
||||
zoom_scroll_delta_scale_input : UI_TextInputBox,
|
||||
font_size_canvas_scalar_input : UI_TextInputBox,
|
||||
font_size_screen_scalar_input : UI_TextInputBox,
|
||||
text_snap_glyph_shape_posiiton : UI_TextInputBox,
|
||||
text_snap_glyph_render_height : UI_TextInputBox,
|
||||
text_size_canvas_scalar_input : UI_TextInputBox,
|
||||
text_size_screen_scalar_input : UI_TextInputBox,
|
||||
text_alpha_sharpen : UI_TextInputBox,
|
||||
cfg_drop_down : UI_DropDown,
|
||||
zoom_mode_drop_down : UI_DropDown,
|
||||
|
||||
@ -496,9 +499,77 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
}
|
||||
}
|
||||
|
||||
Text_Snap_Glyph_Shape_Position:
|
||||
{
|
||||
ui_settings_entry_inputbox( & text_snap_glyph_shape_posiiton, false, "settings_menu.text_snap_glyph_shape_posiiton", str_intern("Text: Snap Glyph Shape Position"),
|
||||
UI_TextInput_Policy {
|
||||
digits_only = true,
|
||||
disallow_leading_zeros = false,
|
||||
disallow_decimal = false,
|
||||
digit_min = 0,
|
||||
digit_max = 1,
|
||||
max_length = 1,
|
||||
}
|
||||
)
|
||||
using text_snap_glyph_shape_posiiton
|
||||
|
||||
if was_active
|
||||
{
|
||||
value, success := parse_f32(to_string(array_to_slice(input_str)))
|
||||
if success {
|
||||
value = clamp(value, 0, 1)
|
||||
value_b32 := cast(b32) i32(value)
|
||||
if config.text_snap_glyph_shape_position != value_b32 {
|
||||
font_provider_flush_caches()
|
||||
font_provider_set_snap_glyph_shape_position( value_b32 )
|
||||
config.text_snap_glyph_shape_position = value_b32
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clear( input_str )
|
||||
append( & input_str, to_runes( str_fmt("%v", i32(config.text_snap_glyph_shape_position) ) ))
|
||||
}
|
||||
}
|
||||
|
||||
Text_Snap_Glyph_Render_Height:
|
||||
{
|
||||
ui_settings_entry_inputbox( & text_snap_glyph_render_height, false, "settings_menu.text_snap_glyph_render_height", str_intern("Text: Snap Glyph Render Height"),
|
||||
UI_TextInput_Policy {
|
||||
digits_only = true,
|
||||
disallow_leading_zeros = false,
|
||||
disallow_decimal = false,
|
||||
digit_min = 0,
|
||||
digit_max = 1,
|
||||
max_length = 1,
|
||||
}
|
||||
)
|
||||
using text_snap_glyph_render_height
|
||||
|
||||
if was_active
|
||||
{
|
||||
value, success := parse_f32(to_string(array_to_slice(input_str)))
|
||||
if success {
|
||||
value = clamp(value, 0, 1)
|
||||
value_b32 := cast(b32) i32(value)
|
||||
if config.text_snap_glyph_render_height != value_b32 {
|
||||
font_provider_flush_caches()
|
||||
font_provider_set_snap_glyph_render_height( value_b32 )
|
||||
config.text_snap_glyph_render_height = value_b32
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clear( input_str )
|
||||
append( & input_str, to_runes( str_fmt("%v", i32(config.text_snap_glyph_render_height) ) ))
|
||||
}
|
||||
}
|
||||
|
||||
Text_Size_Screen_Scalar:
|
||||
{
|
||||
ui_settings_entry_inputbox( & font_size_screen_scalar_input, false, "settings_menu.font_size_screen_scalar", str_intern("Font: Size Screen Scalar"),
|
||||
ui_settings_entry_inputbox( & text_size_screen_scalar_input, false, "settings_menu.text_size_screen_scalar", str_intern("Text: Size Screen Scalar"),
|
||||
UI_TextInput_Policy {
|
||||
digits_only = true,
|
||||
disallow_leading_zeros = false,
|
||||
@ -508,7 +579,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
max_length = 5,
|
||||
}
|
||||
)
|
||||
using font_size_screen_scalar_input
|
||||
using text_size_screen_scalar_input
|
||||
|
||||
if was_active
|
||||
{
|
||||
@ -525,38 +596,9 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
}
|
||||
}
|
||||
|
||||
Text_Snap_Glyph_Positions:
|
||||
{
|
||||
ui_settings_entry_inputbox( & font_size_canvas_scalar_input, false, "settings_menu.font_size_canvas_scalar", str_intern("Font: Size Canvas Scalar"),
|
||||
UI_TextInput_Policy {
|
||||
digits_only = true,
|
||||
disallow_leading_zeros = false,
|
||||
disallow_decimal = false,
|
||||
digit_min = 0,
|
||||
digit_max = 1,
|
||||
max_length = 1,
|
||||
}
|
||||
)
|
||||
using font_size_canvas_scalar_input
|
||||
|
||||
if was_active
|
||||
{
|
||||
value, success := parse_f32(to_string(array_to_slice(input_str)))
|
||||
if success {
|
||||
value = clamp(value, 0, 1)
|
||||
config.text_snap_glyph_positions = cast(b32) i32(value)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clear( input_str )
|
||||
append( & input_str, to_runes(str_fmt("%v", config.text_snap_glyph_positions)))
|
||||
}
|
||||
}
|
||||
|
||||
Text_Size_Canvas_Scalar:
|
||||
{
|
||||
ui_settings_entry_inputbox( & font_size_canvas_scalar_input, false, "settings_menu.font_size_canvas_scalar", str_intern("Font: Size Canvas Scalar"),
|
||||
ui_settings_entry_inputbox( & text_size_canvas_scalar_input, false, "settings_menu.text_size_canvas_scalar", str_intern("Text: Size Canvas Scalar"),
|
||||
UI_TextInput_Policy {
|
||||
digits_only = true,
|
||||
disallow_leading_zeros = false,
|
||||
@ -566,7 +608,7 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
max_length = 5,
|
||||
}
|
||||
)
|
||||
using font_size_canvas_scalar_input
|
||||
using text_size_canvas_scalar_input
|
||||
|
||||
if was_active
|
||||
{
|
||||
@ -585,24 +627,25 @@ ui_settings_menu_builder :: proc( captures : rawptr = nil ) -> ( should_raise :
|
||||
|
||||
Text_Alpha_Sharpen:
|
||||
{
|
||||
ui_settings_entry_inputbox( & font_size_canvas_scalar_input, false, "settings_menu.text_alpha_sharpen", str_intern("Text: Alpha Sharpen"),
|
||||
ui_settings_entry_inputbox( & text_alpha_sharpen, false, "settings_menu.text_alpha_sharpen", str_intern("Text: Alpha Sharpen"),
|
||||
UI_TextInput_Policy {
|
||||
digits_only = true,
|
||||
disallow_leading_zeros = false,
|
||||
disallow_decimal = false,
|
||||
digit_min = 0.001,
|
||||
digit_max = 10,
|
||||
digit_max = 999,
|
||||
max_length = 4,
|
||||
}
|
||||
)
|
||||
using font_size_canvas_scalar_input
|
||||
using text_alpha_sharpen
|
||||
|
||||
if was_active
|
||||
{
|
||||
value, success := parse_f32(to_string(array_to_slice(input_str)))
|
||||
if success {
|
||||
value = clamp(value, 0.001, 10.0)
|
||||
value = clamp(value, 0, 10.0)
|
||||
config.text_alpha_sharpen = value
|
||||
font_provider_set_alpha_sharpen(value)
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -161,10 +161,11 @@ AppConfig :: struct {
|
||||
|
||||
color_theme : AppColorTheme,
|
||||
|
||||
text_snap_glyph_positions : b32,
|
||||
text_size_screen_scalar : f32,
|
||||
text_size_canvas_scalar : f32,
|
||||
text_alpha_sharpen : f32,
|
||||
text_snap_glyph_shape_position : b32,
|
||||
text_snap_glyph_render_height : b32,
|
||||
text_size_screen_scalar : f32,
|
||||
text_size_canvas_scalar : f32,
|
||||
text_alpha_sharpen : f32,
|
||||
}
|
||||
|
||||
AppWindow :: struct {
|
||||
|
@ -136,7 +136,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
resolution_height = 600
|
||||
refresh_rate = 0
|
||||
|
||||
cam_min_zoom = 0.025
|
||||
cam_min_zoom = 0.034
|
||||
cam_max_zoom = 5.0
|
||||
cam_zoom_mode = .Digital
|
||||
cam_zoom_smooth_snappiness = 4.0
|
||||
@ -152,10 +152,11 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
|
||||
color_theme = App_Thm_Dusk
|
||||
|
||||
text_snap_glyph_positions = true
|
||||
text_size_screen_scalar = 2.0
|
||||
text_size_canvas_scalar = 2.0
|
||||
text_alpha_sharpen = 0.25
|
||||
text_snap_glyph_shape_position = false
|
||||
text_snap_glyph_render_height = false
|
||||
text_size_screen_scalar = 1.89
|
||||
text_size_canvas_scalar = 1.89
|
||||
text_alpha_sharpen = 0.1
|
||||
}
|
||||
|
||||
Desired_OS_Scheduler_MS :: 1
|
||||
@ -356,8 +357,9 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (197).txt", allocator = persistent_slab_allocator())
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/Lorem Ipsum (1022).txt", allocator = persistent_slab_allocator())
|
||||
debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gp.h", allocator = persistent_slab_allocator())
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/ve_fontcache.h", allocator = persistent_slab_allocator())
|
||||
debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gp.h", allocator = persistent_slab_allocator())
|
||||
// debug.path_lorem = str_fmt("C:/projects/SectrPrototype/examples/sokol_gl.h", allocator = persistent_slab_allocator())
|
||||
|
||||
alloc_error : AllocatorError; success : bool
|
||||
debug.lorem_content, success = os.read_entire_file( debug.path_lorem, persistent_slab_allocator() )
|
||||
@ -530,9 +532,6 @@ tick_work_frame :: #force_inline proc( host_delta_time_ms : f64 ) -> b32
|
||||
debug.draw_ui_padding_bounds = false
|
||||
debug.draw_ui_content_bounds = false
|
||||
|
||||
font_provider_set_alpha_sharpen(0.25)
|
||||
font_provider_set_snap_glyph_pos(true)
|
||||
|
||||
// config.engine_refresh_hz = 165
|
||||
|
||||
// config.color_theme = App_Thm_Light
|
||||
|
@ -123,7 +123,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
|
||||
screen_size := screen_extent * 2
|
||||
screen_ratio := screen_size.x * ( 1.0 / screen_size.y )
|
||||
|
||||
font_provider_set_px_scalar( app_config().text_size_canvas_scalar )
|
||||
font_provider_set_px_scalar( app_config().text_size_screen_scalar )
|
||||
ve.configure_snap( ve_ctx, u32(screen_size.x), u32(screen_size.y) )
|
||||
|
||||
render_screen_ui( screen_extent, screen_ui, ve_ctx, ve_render )
|
||||
|
@ -302,6 +302,7 @@ update :: proc( delta_time : f64 ) -> b32
|
||||
|
||||
// TODO(Ed): We need input buffer so that we can consume input actions based on the UI with priority
|
||||
|
||||
font_provider_set_px_scalar( app_config().text_size_screen_scalar )
|
||||
ui_screen_tick( & get_state().screen_ui )
|
||||
|
||||
//region WorkspaceImgui Tick
|
||||
|
@ -61,6 +61,13 @@ font_provider_reload :: proc( ctx : ^FontProviderContext )
|
||||
ve.clear_shape_cache(& ctx.ve_ctx)
|
||||
}
|
||||
|
||||
font_provider_flush_caches :: proc()
|
||||
{
|
||||
ve_ctx := & get_state().font_provider_ctx.ve_ctx
|
||||
ve.clear_atlas_region_caches(ve_ctx)
|
||||
ve.clear_shape_cache(ve_ctx)
|
||||
}
|
||||
|
||||
font_provider_shutdown :: proc( ctx : ^FontProviderContext )
|
||||
{
|
||||
ve.shutdown( & ctx.ve_ctx )
|
||||
@ -120,8 +127,12 @@ font_provider_set_px_scalar :: #force_inline proc( scalar : f32 ) {
|
||||
ve.set_px_scalar( & get_state().font_provider_ctx.ve_ctx, scalar )
|
||||
}
|
||||
|
||||
font_provider_set_snap_glyph_pos :: #force_inline proc( should_snap : b32 ) {
|
||||
ve.set_snap_glyph_pos( & get_state().font_provider_ctx.ve_ctx, should_snap )
|
||||
font_provider_set_snap_glyph_shape_position :: #force_inline proc( should_snap : b32 ) {
|
||||
ve.set_snap_glyph_shape_position( & get_state().font_provider_ctx.ve_ctx, should_snap )
|
||||
}
|
||||
|
||||
font_provider_set_snap_glyph_render_height :: #force_inline proc( should_snap : b32 ) {
|
||||
ve.set_snap_glyph_render_height( & get_state().font_provider_ctx.ve_ctx, should_snap )
|
||||
}
|
||||
|
||||
Font_Use_Default_Size :: f32(0.0)
|
||||
|
@ -89,9 +89,9 @@ PWS_ParseError :: struct {
|
||||
}
|
||||
|
||||
PWS_ParseError_Max :: 32
|
||||
PWS_TokenArray_ReserveSize :: 128
|
||||
PWS_NodeArray_ReserveSize :: 32 * Kilobyte
|
||||
PWS_LineArray_ReserveSize :: 32 * Kilobyte
|
||||
PWS_TokenArray_ReserveSize :: 4 * Kilobyte
|
||||
PWS_NodeArray_ReserveSize :: 64 * Kilobyte
|
||||
PWS_LineArray_ReserveSize :: 64 * Kilobyte
|
||||
|
||||
// TODO(Ed) : The ast arrays should be handled by a slab allocator dedicated to PWS_ASTs
|
||||
// This can grow in undeterministic ways, persistent will get very polluted otherwise.
|
||||
|
@ -114,8 +114,8 @@ UI_Layout_Stack_Size :: 512
|
||||
UI_Style_Stack_Size :: 512
|
||||
UI_Parent_Stack_Size :: 512
|
||||
// UI_Built_Boxes_Array_Size :: 8
|
||||
UI_Built_Boxes_Array_Size :: 56 * Kilobyte
|
||||
UI_BoxCache_TableSize :: 8 * Kilobyte
|
||||
UI_Built_Boxes_Array_Size :: 128 * Kilobyte
|
||||
UI_BoxCache_TableSize :: 32 * Kilobyte
|
||||
|
||||
// TODO(Ed): Rename to UI_Context
|
||||
UI_State :: struct {
|
||||
@ -381,7 +381,7 @@ ui_hash_part_from_key_string :: proc ( content : string ) -> string {
|
||||
ui_key_from_string :: #force_inline proc "contextless" ( value : string ) -> UI_Key
|
||||
{
|
||||
// profile(#procedure)
|
||||
USE_RAD_DEBUGGERS_METHOD :: true
|
||||
USE_RAD_DEBUGGERS_METHOD :: false
|
||||
|
||||
key : UI_Key
|
||||
|
||||
|
4811
examples/sokol_gl.h
Normal file
4811
examples/sokol_gl.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -205,11 +205,11 @@ push-location $path_root
|
||||
# $build_args += $flag_micro_architecture_native
|
||||
$build_args += $flag_use_separate_modules
|
||||
$build_args += $flag_thread_count + $CoreCount_Physical
|
||||
# $build_args += $flag_optimize_none
|
||||
$build_args += $flag_optimize_none
|
||||
# $build_args += $flag_optimize_minimal
|
||||
# $build_args += $flag_optimize_speed
|
||||
$build_args += $falg_optimize_aggressive
|
||||
# $build_args += $flag_debug
|
||||
# $build_args += $falg_optimize_aggressive
|
||||
$build_args += $flag_debug
|
||||
$build_args += $flag_pdb_name + $pdb
|
||||
$build_args += $flag_subsystem + 'windows'
|
||||
# $build_args += $flag_show_system_calls
|
||||
|
Loading…
x
Reference in New Issue
Block a user