Minor lifting in the render side, getting ready to just hunker down and take notes on whats next

* VEFontCache needs to get fixed up (possibly bring back ELFHash)
  * Problably going to do conversion early to odin's array and map usage
* Need get the quad tree setup for the ui so that I can do fast and efficient traversal for the layer based rendering.
This commit is contained in:
2024-06-24 16:36:22 -04:00
parent 0d9623c340
commit c93c0ed567
9 changed files with 440 additions and 396 deletions

View File

@ -84,6 +84,13 @@ UI_RenderBoxInfo :: struct {
layer_signal : b32,
}
UI_RenderMethod :: enum u32 {
Depth_First,
Layers,
}
UI_Render_Method :: UI_RenderMethod.Depth_First
// TODO(Ed): Rename to UI_Context
UI_State :: struct {
// TODO(Ed) : Use these?
@ -96,6 +103,7 @@ UI_State :: struct {
prev_cache : ^HMapZPL( UI_Box ),
curr_cache : ^HMapZPL( UI_Box ),
// For rendering via a set of layers organized into a single command list
// render_queue_builder : SubArena,
render_queue : Array(UI_RenderLayer),
render_list : Array(UI_RenderBoxInfo),
@ -214,186 +222,191 @@ ui_graph_build_end :: proc( ui : ^UI_State )
computed.content = computed.bounds
}
// Auto-layout and initial render_queue generation
render_queue := array_to_slice(ui.render_queue)
for current := root.first; current != nil; current = ui_box_tranverse_next( current )
for current := root.first; current != nil; current = ui_box_tranverse_next_depth_based( current )
{
if ! current.computed.fresh {
ui_box_compute_layout( current )
}
// TODO(Ed): Eventually put this into a sub-arena
entry, error := new(UI_RenderEntry)
(entry^) = UI_RenderEntry {
info = {
current.computed,
current.style,
current.text,
current.layout.font_size,
current.layout.border_width,
current.label,
false,
},
layer_id = current.ancestors -1,
}
when UI_Render_Method == .Layers
{
if entry.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {})
render_queue = array_to_slice(ui.render_queue)
}
// TODO(Ed): Eventually put this into a sub-arena
entry, error := new(UI_RenderEntry)
(entry^) = UI_RenderEntry {
info = {
current.computed,
current.style,
current.text,
current.layout.font_size,
current.layout.border_width,
current.label,
false,
},
layer_id = current.ancestors -1,
}
// else if layer.last == nil {
// layer.first.next = entry
// entry.prev = layer.first
// layer.last = entry
// }
if entry.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {})
render_queue = array_to_slice(ui.render_queue)
}
// push_back to next layer
layer := & render_queue[entry.layer_id]
if layer.first == nil {
layer.first = entry
layer.last = entry
}
else {
layer.last.next = entry
entry.prev = layer.last
layer.last = entry
}
// dll_full_push_back( layer, entry, nil )
// else if layer.last == nil {
// layer.first.next = entry
// entry.prev = layer.first
// layer.last = entry
// }
// If there is a parent entry, give it a reference to the child entry
parent_entry : ^UI_RenderEntry
if entry.layer_id > 0 {
parent_layer := & render_queue[entry.layer_id - 1]
parent_entry = parent_layer.last
entry.parent = parent_entry
if parent_entry.first == nil {
parent_entry.first = entry
parent_entry.last = entry
// push_back to next layer
layer := & render_queue[entry.layer_id]
if layer.first == nil {
layer.first = entry
layer.last = entry
}
else {
parent_entry.last = entry
layer.last.next = entry
entry.prev = layer.last
layer.last = entry
}
// dll_full_push_back( layer, entry, nil )
// If there is a parent entry, give it a reference to the child entry
parent_entry : ^UI_RenderEntry
if entry.layer_id > 0 {
parent_layer := & render_queue[entry.layer_id - 1]
parent_entry = parent_layer.last
entry.parent = parent_entry
if parent_entry.first == nil {
parent_entry.first = entry
parent_entry.last = entry
}
else {
parent_entry.last = entry
}
// dll_fl_append( parent_entry, entry )
}
// dll_fl_append( parent_entry, entry )
}
}
// render_queue overlap corrections & render_list generation
render_queue = array_to_slice(ui.render_queue)
for layer_id : i32 = 0; layer_id < i32(ui.render_queue.num); layer_id += 1
when UI_Render_Method == .Layers
{
layer := & ui.render_queue.data[ layer_id ]
append( & ui.render_list, UI_RenderBoxInfo { layer_signal = true })
to_increment, error := make( Array(^UI_RenderEntry), 4 * Kilo )
verify( error == .None, "Faied to make to_increment array.")
to_inc_last_iterated : i32 = 0
for entry := layer.first; entry != nil; entry = entry.next
// render_queue overlap corrections & render_list generation
render_queue = array_to_slice(ui.render_queue)
for layer_id : i32 = 0; layer_id < i32(ui.render_queue.num); layer_id += 1
{
for neighbor := entry.next; neighbor != nil; neighbor = neighbor.next
layer := & ui.render_queue.data[ layer_id ]
append( & ui.render_list, UI_RenderBoxInfo { layer_signal = true })
to_increment, error := make( Array(^UI_RenderEntry), 4 * Kilo )
verify( error == .None, "Faied to make to_increment array.")
to_inc_last_iterated : i32 = 0
for entry := layer.first; entry != nil; entry = entry.next
{
if ! overlap_range2( entry.info.computed.bounds, neighbor.info.computed.bounds) do continue
append( & to_increment, neighbor )
} // for neighbor := entry.next; neighbor != nil; neighbor = neighbor.next
if entry == to_increment.data[ to_inc_last_iterated ] {
to_inc_last_iterated += 1
}
else {
// This entry stayed in this layer, we can append the value
array_append_value( & ui.render_list, entry.info )
}
} // for entry := layer.first; entry != nil; entry = entry.next
// Move overlaping entries & their children's by 1 layer
to_inc_slice := array_to_slice(to_increment)
for entry in to_inc_slice
{
pop_layer := render_queue[entry.layer_id]
entry.layer_id += 1
if entry.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {} )
render_queue = array_to_slice(ui.render_queue)
}
push_layer := render_queue[entry.layer_id]
// pop entry from layer
prev := entry.prev
prev.next = entry.next
if entry == pop_layer.last {
pop_layer.last = prev
}
// push entry to next layer
if push_layer.first == nil {
push_layer.first = entry
push_layer.last = entry
}
else {
push_layer.last.next = entry
entry.prev = push_layer.last
push_layer.last = entry
entry.next = nil
}
// else if push_layer.last == nil {
// push_layer.last = entry
// entry.prev = push_layer.first
// push_layer.first.next = entry
// entry.next = nil
// }
// increment children's layers
if entry.first != nil
{
for child := entry.first; child != nil; child = ui_render_entry_tranverse( child )
for neighbor := entry.next; neighbor != nil; neighbor = neighbor.next
{
pop_layer := render_queue[child.layer_id]
child.layer_id += 1
if ! overlap_range2( entry.info.computed.bounds, neighbor.info.computed.bounds) do continue
append( & to_increment, neighbor )
} // for neighbor := entry.next; neighbor != nil; neighbor = neighbor.next
if child.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {})
render_queue = array_to_slice(ui.render_queue)
}
push_layer := render_queue[child.layer_id]
if entry == to_increment.data[ to_inc_last_iterated ] {
to_inc_last_iterated += 1
}
else {
// This entry stayed in this layer, we can append the value
array_append_value( & ui.render_list, entry.info )
}
} // for entry := layer.first; entry != nil; entry = entry.next
// pop from current layer
if child == pop_layer.first {
pop_layer.first = nil
}
if child == pop_layer.last {
pop_layer.last = child.prev
}
// Move overlaping entries & their children's by 1 layer
to_inc_slice := array_to_slice(to_increment)
for entry in to_inc_slice
{
pop_layer := render_queue[entry.layer_id]
entry.layer_id += 1
if entry.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {} )
render_queue = array_to_slice(ui.render_queue)
}
push_layer := render_queue[entry.layer_id]
// push_back to next layer
if push_layer.first == nil {
push_layer.first = child
push_layer.last = child
}
else {
push_layer.last.next = child
child.prev = push_layer.last
push_layer.last = child
}
// pop entry from layer
prev := entry.prev
prev.next = entry.next
if entry == pop_layer.last {
pop_layer.last = prev
}
// else if push_layer.last == nil {
// push_layer.first.next = child
// child.prev = push_layer.first
// push_layer.last = child
// }
// push entry to next layer
if push_layer.first == nil {
push_layer.first = entry
push_layer.last = entry
}
else {
push_layer.last.next = entry
entry.prev = push_layer.last
push_layer.last = entry
entry.next = nil
}
// else if push_layer.last == nil {
// push_layer.last = entry
// entry.prev = push_layer.first
// push_layer.first.next = entry
// entry.next = nil
// }
} // for child := neighbor.first; child != nil; child = ui_render_entry_traverse_depth( child )
} // if entry.first != nil
} // for entry in to_inc_slice
} // for & layer in render_queue
// increment children's layers
if entry.first != nil
{
for child := entry.first; child != nil; child = ui_render_entry_tranverse( child )
{
pop_layer := render_queue[child.layer_id]
child.layer_id += 1
if child.layer_id >= i32(ui.render_queue.num) {
append( & ui.render_queue, UI_RenderLayer {})
render_queue = array_to_slice(ui.render_queue)
}
push_layer := render_queue[child.layer_id]
// pop from current layer
if child == pop_layer.first {
pop_layer.first = nil
}
if child == pop_layer.last {
pop_layer.last = child.prev
}
// push_back to next layer
if push_layer.first == nil {
push_layer.first = child
push_layer.last = child
}
else {
push_layer.last.next = child
child.prev = push_layer.last
push_layer.last = child
}
// else if push_layer.last == nil {
// push_layer.first.next = child
// child.prev = push_layer.first
// push_layer.last = child
// }
} // for child := neighbor.first; child != nil; child = ui_render_entry_traverse_depth( child )
} // if entry.first != nil
} // for entry in to_inc_slice
} // for & layer in render_queue
}
render_list := array_to_slice(ui.render_list)
}
render_queue := array_to_slice(ui.render_queue)
render_list := array_to_slice(ui.render_list)
get_state().ui_context = nil
}

View File

@ -118,7 +118,7 @@ ui_prev_cached_box :: #force_inline proc( box : ^UI_Box ) -> ^UI_Box { return hm
// TODO(Ed): Rename to ui_box_tranverse_view_next
// Traveral pritorizes immeidate children
ui_box_tranverse_next :: proc "contextless" ( box : ^ UI_Box, bypass_intersection_test := false ) -> (^ UI_Box)
ui_box_tranverse_next_depth_based :: proc "contextless" ( box : ^ UI_Box, bypass_intersection_test := false ) -> (^ UI_Box)
{
using state := get_state()
// If current has children, do them first

View File

@ -181,7 +181,7 @@ ui_compute_children_bounding_area :: proc ( box : ^UI_Box )
ui_box_compute_layout_children :: proc( box : ^UI_Box )
{
for current := box.first; current != nil && current.prev != box; current = ui_box_tranverse_next( current )
for current := box.first; current != nil && current.prev != box; current = ui_box_tranverse_next_depth_based( current )
{
if current == box do return
if current.computed.fresh do continue