Misc changes (refactors, notes)
This commit is contained in:
		| @@ -154,17 +154,15 @@ eval_point_on_bezier4 :: proc( p0, p1, p2, p3 : Vec2, alpha : f32 ) -> Vec2 | ||||
| } | ||||
|  | ||||
| screenspace_x_form :: proc( position, scale : ^Vec2, width, height : f32 ) { | ||||
| 	scale.x    = (scale.x / width ) * 2.0 | ||||
| 	scale.y    = (scale.y / height) * 2.0 | ||||
| 	position.x = position.x * (2.0 / width)  - 1.0 | ||||
| 	position.y = position.y * (2.0 / height) - 1.0 | ||||
| 	quotient    := 1.0 / Vec2 { width, height } | ||||
| 	(position^) = (position^) * quotient * 2.0 - 1.0 | ||||
| 	(scale^)    = (scale^)    * quotient * 2.0 | ||||
| } | ||||
|  | ||||
| textspace_x_form :: proc( position, scale : ^Vec2, width, height : f32 ) { | ||||
| 	position.x /= width | ||||
| 	position.y /= height | ||||
| 	scale.x    /= width | ||||
| 	scale.y    /= height | ||||
| 	quotient := 1.0 / Vec2 { width, height } | ||||
| 	(position^) *= quotient | ||||
| 	(scale^)    *= quotient | ||||
| } | ||||
|  | ||||
| InitAtlasRegionParams :: struct { | ||||
|   | ||||
| @@ -310,14 +310,3 @@ array_block_size :: proc "contextless" ( self : Array( $Type ) ) -> u64 { | ||||
| 	block_size  := cast(u64) (header_size + self.capacity * size_of(Type)) | ||||
| 	return block_size | ||||
| } | ||||
|  | ||||
| array_memtracker_entry :: proc( self : Array( $Type ), name : string ) -> MemoryTrackerEntry { | ||||
| 	header_size :: size_of(ArrayHeader(Type)) | ||||
| 	block_size  := cast(uintptr) (header_size + (cast(uintptr) self.capacity) * size_of(Type)) | ||||
|  | ||||
| 	block_start := transmute(^u8) self.header | ||||
| 	block_end   := ptr_offset( block_start, block_size ) | ||||
|  | ||||
| 	tracker_entry := MemoryTrackerEntry { name, block_start, block_end } | ||||
| 	return tracker_entry | ||||
| } | ||||
|   | ||||
							
								
								
									
										1
									
								
								code/grime/growing_sub_arena.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								code/grime/growing_sub_arena.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| package grime | ||||
| @@ -21,27 +21,6 @@ push_back_slice_queue :: proc( self : ^$QueueType / Queue($Type), slice : []Type | ||||
| { | ||||
| 	queue.push_back_elems( self, ..slice ) | ||||
| 	return | ||||
|  | ||||
| 	// num := cast(uint) len(slice) | ||||
|  | ||||
| 	// if uint( space_left( self^ )) < num { | ||||
| 	// 	error = queue._grow( self, self.len + num ) | ||||
| 	// 	if error != .None do return | ||||
| 	// } | ||||
|  | ||||
| 	// size        := uint(len(self.data)) | ||||
| 	// insert_from := (self.offset + self.len) % size | ||||
| 	// insert_to   := num | ||||
|  | ||||
| 	// if insert_from + insert_to > size { | ||||
| 	// 	insert_to = size - insert_from | ||||
| 	// } | ||||
|  | ||||
| 	// copy( self.data[ insert_from : ], slice[ : insert_to ]) | ||||
| 	// copy( self.data[ : insert_from ], slice[ insert_to : ]) | ||||
|  | ||||
| 	// self.len += num | ||||
| 	// return | ||||
| } | ||||
|  | ||||
| QueueIterator :: struct( $Type : typeid ) { | ||||
|   | ||||
| @@ -64,6 +64,8 @@ str_cache_init :: proc( table_allocator, slabs_allocator : Allocator ) -> (cache | ||||
|  | ||||
| 	@static dbg_name := "StringCache slab" | ||||
|  | ||||
| 	// TODO(Ed): Is this nessary (essentially is there a perf impact of using vs not using, which is better because thats all that matters) | ||||
| 	// Interning should only be handled on a growing arena anyway so it doesn't really need this. | ||||
| 	alloc_error : AllocatorError | ||||
| 	cache.slab, alloc_error = slab_init( & policy, allocator = slabs_allocator, dbg_name = dbg_name ) | ||||
| 	verify(alloc_error == .None, "Failed to initialize the string cache" ) | ||||
|   | ||||
| @@ -123,16 +123,40 @@ setup_memory :: proc( profiler : ^SpallProfiler ) -> ClientMemory | ||||
| 	// Setup the static arena for the entire application | ||||
| 	{ | ||||
| 		alloc_error : AllocatorError | ||||
| 		persistent, alloc_error = varena_init( sectr.Memory_Base_Address_Persistent, sectr.Memory_Reserve_Persistent, sectr.Memory_Commit_Initial_Persistent, nil, dbg_name = "persistent" ) | ||||
| 		persistent, alloc_error = varena_init( | ||||
| 			sectr.Memory_Base_Address_Persistent, | ||||
| 			sectr.Memory_Reserve_Persistent, | ||||
| 			sectr.Memory_Commit_Initial_Persistent, | ||||
| 			growth_policy    = nil, | ||||
| 			allow_any_resize = false, | ||||
| 			dbg_name         = "persistent" ) | ||||
| 		verify( alloc_error == .None, "Failed to allocate persistent virtual arena for the sectr module") | ||||
|  | ||||
| 		frame, alloc_error = varena_init( sectr.Memory_Base_Address_Frame, sectr.Memory_Reserve_Frame, sectr.Memory_Commit_Initial_Frame, nil, allow_any_reize = true, dbg_name = "frame" ) | ||||
| 		frame, alloc_error = varena_init( | ||||
| 			sectr.Memory_Base_Address_Frame, | ||||
| 			sectr.Memory_Reserve_Frame, | ||||
| 			sectr.Memory_Commit_Initial_Frame, | ||||
| 			growth_policy    = nil, | ||||
| 			allow_any_resize = true, | ||||
| 			dbg_name         = "frame" ) | ||||
| 		verify( alloc_error == .None, "Failed to allocate frame virtual arena for the sectr module") | ||||
|  | ||||
| 		transient, alloc_error = varena_init( sectr.Memory_Base_Address_Transient, sectr.Memory_Reserve_Transient, sectr.Memory_Commit_Initial_Transient, nil, allow_any_reize = true, dbg_name = "transient" ) | ||||
| 		transient, alloc_error = varena_init( | ||||
| 			sectr.Memory_Base_Address_Transient, | ||||
| 			sectr.Memory_Reserve_Transient, | ||||
| 			sectr.Memory_Commit_Initial_Transient, | ||||
| 			growth_policy    = nil, | ||||
| 			allow_any_resize = true, | ||||
| 			dbg_name         = "transient" ) | ||||
| 		verify( alloc_error == .None, "Failed to allocate transient virtual arena for the sectr module") | ||||
|  | ||||
| 		files_buffer, alloc_error = varena_init( sectr.Memory_Base_Address_Files_Buffer, sectr.Memory_Reserve_FilesBuffer, sectr.Memory_Commit_Initial_Filebuffer, nil, dbg_name = "files_buffer" ) | ||||
| 		files_buffer, alloc_error = varena_init( | ||||
| 			sectr.Memory_Base_Address_Files_Buffer, | ||||
| 			sectr.Memory_Reserve_FilesBuffer, | ||||
| 			sectr.Memory_Commit_Initial_Filebuffer, | ||||
| 			growth_policy    = nil, | ||||
| 			allow_any_resize = true, | ||||
| 			dbg_name         = "files_buffer" ) | ||||
| 		verify( alloc_error == .None, "Failed to allocate files buffer virtual arena for the sectr module") | ||||
| 	} | ||||
|  | ||||
| @@ -149,8 +173,8 @@ setup_memory :: proc( profiler : ^SpallProfiler ) -> ClientMemory | ||||
| 				file_resize( snapshot_file, sectr.Memory_Chunk_Size ) | ||||
| 			} | ||||
| 		} | ||||
| 		map_error                : MapFileError | ||||
| 		map_flags                : MapFileFlags = { MapFileFlag.Read, MapFileFlag.Write } | ||||
| 		map_error : MapFileError | ||||
| 		map_flags : MapFileFlags = { MapFileFlag.Read, MapFileFlag.Write } | ||||
| 		sectr_snapshot, map_error = virtual.map_file_from_file_descriptor( uintptr(snapshot_file), map_flags ) | ||||
| 		verify( map_error == MapFileError.None, "Failed to allocate snapshot memory for the sectr module" ) | ||||
| 		file_close(snapshot_file) | ||||
| @@ -250,7 +274,7 @@ sync_sectr_api :: proc( sectr_api : ^sectr.ModuleAPI, memory : ^ClientMemory, lo | ||||
|  | ||||
| fmt_backing : [16 * Kilobyte] u8 | ||||
|  | ||||
| persistent_backing : [2 * Megabyte] byte | ||||
| persistent_backing : [2  * Megabyte] byte | ||||
| transient_backing  : [32 * Megabyte] byte | ||||
|  | ||||
| main :: proc() | ||||
|   | ||||
| @@ -1,169 +0,0 @@ | ||||
| package sectr | ||||
|  | ||||
| import sokol_gfx "thirdparty:sokol/gfx" | ||||
| import sokol_glue "thirdparty:sokol/glue" | ||||
|  | ||||
| PassActions :: struct { | ||||
| 	bg_clear_black : sokol_gfx.Pass_Action, | ||||
|  | ||||
| } | ||||
|  | ||||
| RenderState :: struct { | ||||
| 	pass_actions : PassActions, | ||||
| } | ||||
|  | ||||
| // TODO(Ed) : Review this and put into space.odin when ready | ||||
| ortho :: proc(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> [4][4]f32 { | ||||
|     result: [4][4]f32 | ||||
|     result[0][0] = 2.0 / (right - left) | ||||
|     result[1][1] = 2.0 / (top - bottom) | ||||
|     result[2][2] = -2.0 / (far - near) | ||||
|     result[3][0] = -(right + left) / (right - left) | ||||
|     result[3][1] = -(top + bottom) / (top - bottom) | ||||
|     result[3][2] = -(far + near) / (far - near) | ||||
|     result[3][3] = 1.0 | ||||
|     return result | ||||
| } | ||||
|  | ||||
| render :: proc() | ||||
| { | ||||
| 	Bindings    :: sokol_gfx.Bindings | ||||
| 	Range       :: sokol_gfx.Range | ||||
| 	ShaderStage :: sokol_gfx.Shader_Stage | ||||
|  | ||||
| 	state := get_state(); using state | ||||
| 	using render_data | ||||
|  | ||||
| 	do_nothing : bool | ||||
| 	do_nothing = false | ||||
|  | ||||
| 	// apply_bindings :: sokol_gfx.apply_bindings | ||||
|  | ||||
| 	// Clear Demo | ||||
| 	if false | ||||
| 	{ | ||||
| 	  green_value := debug.gfx_clear_demo_pass_action.colors[0].clear_value.g + 0.01 | ||||
| 	  debug.gfx_clear_demo_pass_action.colors[0].clear_value.g = green_value > 1.0 ? 0.0 : green_value | ||||
|  | ||||
| 	  sokol_gfx.begin_pass( sokol_gfx.Pass { | ||||
| 	  	action    = debug.gfx_clear_demo_pass_action, | ||||
| 	  	swapchain = sokol_glue.swapchain() | ||||
| 	  }) | ||||
| 	  sokol_gfx.end_pass() | ||||
| 	  sokol_gfx.commit() | ||||
| 	} | ||||
|  | ||||
| 	// Triangle Demo | ||||
| 	if false | ||||
| 	{ | ||||
| 		using debug.gfx_tri_demo_state | ||||
| 		sokol_gfx.begin_pass(sokol_gfx.Pass { action = pass_action, swapchain = sokol_glue.swapchain() }) | ||||
| 		sokol_gfx.apply_pipeline( pipeline ) | ||||
| 		sokol_gfx.apply_bindings( bindings ) | ||||
|  | ||||
| 		sokol_gfx.draw( 0, 3, 1 ) | ||||
|  | ||||
| 		sokol_gfx.end_pass() | ||||
| 		sokol_gfx.commit() | ||||
| 	} | ||||
|  | ||||
| 	// learnopengl.com/In-Practice/Text-Rendering | ||||
| 	when true | ||||
| 	{ | ||||
| 		profile("learngl_text_render_pass") | ||||
| 		using font_provider_data | ||||
|  | ||||
| 	  // green_value := debug.gfx_clear_demo_pass_action.colors[0].clear_value.g + 0.01 | ||||
| 	  // debug.gfx_clear_demo_pass_action.colors[0].clear_value.g = green_value > 1.0 ? 0.0 : green_value | ||||
| 	  // sokol_gfx.begin_pass( sokol_gfx.Pass { | ||||
| 	  // 	action    = debug.gfx_clear_demo_pass_action, | ||||
| 	  // 	swapchain = sokol_glue.swapchain() | ||||
| 	  // }) | ||||
| 		sokol_gfx.begin_pass(sokol_gfx.Pass { action = pass_actions.bg_clear_black, swapchain = sokol_glue.swapchain() }) | ||||
| 		sokol_gfx.apply_pipeline( gfx_pipeline ) | ||||
| 		// sokol_gfx.update_buffer( gfx_vbuffer, sokol_gfx.Range{ , Font_Provider_Ggfx_Buffer_Size } ) | ||||
|  | ||||
| 		projection := ortho( 0, app_window.extent.x * 2, 0, app_window.extent.y * 2, -1, 1 ) | ||||
| 		sokol_gfx.apply_uniforms( ShaderStage.VS, SLOT_font_glyph_vs_params, sokol_gfx.Range{ & projection[0][0] , size_of(projection) }) | ||||
|  | ||||
| 		text_test_str := str_fmt("frametime: %v", frametime_avg_ms) | ||||
| 		def := hmap_chained_get( font_cache, default_font.key ) | ||||
|  | ||||
| 		x     : f32 = 0.0 | ||||
| 		y     : f32 = 25.0 | ||||
| 		scale : f32 = 0.5 | ||||
| 		next := 0 | ||||
| 		for codepoint, byte_offset in text_test_str | ||||
| 		{ | ||||
| 			using def | ||||
| 			glyph := & glyphs[ int(codepoint) ] | ||||
|  | ||||
| 			if glyph.size.x == 0 do continue | ||||
| 			// logf("Drawing glyph: %v", codepoint) | ||||
|  | ||||
| 			bearing : Vec2 = { f32(glyph.bearing.x), f32(glyph.bearing.y) } | ||||
| 			size    : Vec2 = { f32(glyph.size.x),    f32(glyph.size.y) } | ||||
|  | ||||
| 			pos := vec2( | ||||
| 				x + bearing.x            * scale, | ||||
| 				y - (size.y - bearing.y) * scale | ||||
| 			) | ||||
|  | ||||
| 			width  := size.x * scale | ||||
| 			height := size.y * scale | ||||
|  | ||||
| 			vertices : [6]Vec2 = { | ||||
| 				{ pos.x,         pos.y + height }, | ||||
| 				{ pos.x,         pos.y          }, | ||||
| 				{ pos.x + width, pos.y          }, | ||||
|  | ||||
| 				{ pos.x,         pos.y + height }, | ||||
| 				{ pos.x + width, pos.y          }, | ||||
| 				{ pos.x + width, pos.y + height } | ||||
| 			} | ||||
|  | ||||
| 			uv_coords : [6]Vec2 = { | ||||
| 				0 = { 0.0, 0.0 }, | ||||
| 				1 = { 0.0, 1.0 }, | ||||
| 				2 = { 1.0, 1.0 }, | ||||
|  | ||||
| 				3 = { 0.0, 0.0 }, | ||||
| 				4 = { 1.0, 1.0 }, | ||||
| 				5 = { 1.0, 0.0 }, | ||||
| 			} | ||||
|  | ||||
| 			color : Vec3 = { 1.0, 1.0, 1.0 } | ||||
| 			fs_uniform := Font_Glyph_Fs_Params { | ||||
| 				glyph_color = color | ||||
| 			} | ||||
| 			sokol_gfx.apply_uniforms( sokol_gfx.Shader_Stage.FS, SLOT_font_glyph_fs_params, Range{ & fs_uniform, size_of(fs_uniform) }) | ||||
|  | ||||
| 			vbuf_offset := sokol_gfx.append_buffer( gfx_v_buffer, { & vertices[0], size_of(vertices) }) | ||||
| 			// sokol_gfx.update_buffer( gfx_uv_buffer, { & uv_coords[0], size_of(uv_coords) }) | ||||
|  | ||||
| 			bindings := Bindings { | ||||
| 				vertex_buffers        = { | ||||
| 					ATTR_font_glyph_vs_vertex        = gfx_v_buffer, | ||||
| 					ATTR_font_glyph_vs_texture_coord = gfx_uv_buffer, | ||||
| 				}, | ||||
| 				vertex_buffer_offsets = { | ||||
| 					ATTR_font_glyph_vs_vertex        = vbuf_offset, | ||||
| 					ATTR_font_glyph_vs_texture_coord = 0, | ||||
| 				}, | ||||
| 				fs                    = { | ||||
| 					images   = { SLOT_glyph_bitmap         = glyph.texture }, | ||||
| 					samplers = { SLOT_glyph_bitmap_sampler = gfx_sampler   } | ||||
| 				}, | ||||
| 			} | ||||
| 			sokol_gfx.apply_bindings( bindings ) | ||||
|  | ||||
| 			sokol_gfx.draw( 0, 6, 1 ) | ||||
| 			next += 6 | ||||
|  | ||||
| 			x += f32(glyph.advance >> 6) * scale | ||||
| 		} | ||||
|  | ||||
| 		sokol_gfx.end_pass() | ||||
| 		sokol_gfx.commit() | ||||
| 	} | ||||
| } | ||||
| @@ -97,7 +97,7 @@ sokol_app_log_callback :: proc "c" ( | ||||
| 	logf( "%-80s %s::%v", cloned_msg, cloned_tag, line_nr, level = odin_level ) | ||||
| } | ||||
|  | ||||
| // TODO(Ed): This needs to queue to a job stask for a event callback handling thread to deal with. | ||||
| // TODO(Ed): Does this need to be queued to a separate thread? | ||||
| sokol_app_event_callback :: proc "c" (sokol_event : ^sokol_app.Event) | ||||
| { | ||||
| 	state := get_state(); using state | ||||
|   | ||||
| @@ -119,7 +119,7 @@ render_mode_screenspace :: proc() | ||||
| 		content := str_fmt_buffer( draw_text_scratch[:], format, ..args ) | ||||
| 		debug_draw_text( content, position, 12.0 ) | ||||
|  | ||||
| 		debug.draw_debug_text_y += 14 | ||||
| 		debug.draw_debug_text_y += 12 | ||||
| 	} | ||||
|  | ||||
| 	debug.debug_text_vis = true | ||||
|   | ||||
| @@ -1,3 +0,0 @@ | ||||
| package sectr | ||||
|  | ||||
| import fstash "codebase:font/fontstash" | ||||
| @@ -1,319 +0,0 @@ | ||||
| package sectr | ||||
|  | ||||
| import "core:os" | ||||
| import "core:strings" | ||||
| import "core:unicode" | ||||
| import sokol_gfx "thirdparty:sokol/gfx" | ||||
| import "thirdparty:freetype" | ||||
|  | ||||
| Font_Provider_Use_Freetype :: true | ||||
|  | ||||
| Font_Largest_Px_Size :: 32 | ||||
|  | ||||
| Font_Size_Interval :: 2 | ||||
|  | ||||
| // Font_Default :: "" | ||||
| Font_Default            :: FontID { 0, "" } | ||||
| Font_Default_Point_Size :: 18.0 | ||||
|  | ||||
| Font_TTF_Default_Chars_Padding :: 4 | ||||
|  | ||||
| Font_Load_Use_Default_Size :: -1 | ||||
| Font_Load_Gen_ID           :: "" | ||||
|  | ||||
| FontID  :: struct { | ||||
| 	key   : u64, | ||||
| 	label : string, | ||||
| } | ||||
| FontTag :: struct { | ||||
| 	key        : FontID, | ||||
| 	point_size : f32 | ||||
| } | ||||
|  | ||||
| when Font_Provider_Use_Freetype | ||||
| { | ||||
| 	FontParserFontData :: struct { | ||||
| 		using face : freetype.Face, | ||||
| 	} | ||||
| 	FontParserData :: struct { | ||||
| 		lib : freetype.Library, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| FontGlyph :: struct { | ||||
| 	size       : Vec2i, | ||||
| 	bearing    : Vec2i, | ||||
| 	advance    : u32, | ||||
| 	texture    : sokol_gfx.Image, | ||||
| } | ||||
|  | ||||
| FontDef :: struct { | ||||
| 	path_file   : string, | ||||
| 	parser_info : FontParserFontData, | ||||
| 	glyphs      : [256]FontGlyph, | ||||
| } | ||||
|  | ||||
| FontProviderData :: struct { | ||||
| 	font_cache    : HMapChained(FontDef), | ||||
| 	parser        : FontParserData, | ||||
| 	glyph_shader  : sokol_gfx.Shader, | ||||
| 	gfx_bindings  : sokol_gfx.Bindings, | ||||
| 	gfx_pipeline  : sokol_gfx.Pipeline, | ||||
| 	gfx_v_buffer  : sokol_gfx.Buffer, | ||||
| 	gfx_uv_buffer : sokol_gfx.Buffer, | ||||
| 	gfx_sampler   : sokol_gfx.Sampler, | ||||
| } | ||||
|  | ||||
| Font_Quad_Vert_Size            :: size_of(Vec2) * 6 | ||||
| Font_Provider_Gfx_vBuffer_Size :: Font_Quad_Vert_Size * Kilo * 64 | ||||
|  | ||||
| font_provider_startup :: proc() | ||||
| { | ||||
| 	profile(#procedure) | ||||
| 	state := get_state() | ||||
| 	font_provider_data := & get_state().font_provider_data; using font_provider_data | ||||
|  | ||||
| 	font_cache_alloc_error : AllocatorError | ||||
| 	font_cache, font_cache_alloc_error = make( HMapChained(FontDef), hmap_closest_prime(1 * Kilo), persistent_allocator() /*dbg_name = "font_cache"*/ ) | ||||
| 	verify( font_cache_alloc_error == AllocatorError.None, "Failed to allocate font_cache" ) | ||||
|  | ||||
| 	log("font_cache created") | ||||
|  | ||||
| 	when Font_Provider_Use_Freetype | ||||
| 	{ | ||||
| 		result := freetype.init_free_type( & font_provider_data.parser.lib ) | ||||
| 		if result != freetype.Error.Ok { | ||||
| 			fatal( "font_provider_setup: Failed to initialize freetype" ) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Setup Graphics Pipeline | ||||
| 	{ | ||||
| 		BlendFactor             :: sokol_gfx.Blend_Factor | ||||
| 		BlendOp                 :: sokol_gfx.Blend_Op | ||||
| 		BlendState              :: sokol_gfx.Blend_State | ||||
| 		BorderColor             :: sokol_gfx.Border_Color | ||||
| 		BufferDesciption        :: sokol_gfx.Buffer_Desc | ||||
| 		BufferUsage             :: sokol_gfx.Usage | ||||
| 		BufferType              :: sokol_gfx.Buffer_Type | ||||
| 		ColorTargetState        :: sokol_gfx.Color_Target_State | ||||
| 		Filter                  :: sokol_gfx.Filter | ||||
| 		Range                   :: sokol_gfx.Range | ||||
| 		SamplerDescription      :: sokol_gfx.Sampler_Desc | ||||
| 		Wrap                    :: sokol_gfx.Wrap | ||||
| 		VertexAttributeState    :: sokol_gfx.Vertex_Attr_State | ||||
| 		VertexBufferLayoutState :: sokol_gfx.Vertex_Buffer_Layout_State | ||||
| 		VertexIndexType         :: sokol_gfx.Index_Type | ||||
| 		VertexFormat            :: sokol_gfx.Vertex_Format | ||||
| 		VertexLayoutState       :: sokol_gfx.Vertex_Layout_State | ||||
| 		VertexStep              :: sokol_gfx.Vertex_Step | ||||
|  | ||||
| 		using font_provider_data | ||||
| 		backend := sokol_gfx.query_backend() | ||||
|  | ||||
| 		glyph_shader = sokol_gfx.make_shader(font_glyph_shader_desc(backend)) | ||||
|  | ||||
| 		// Glyphs append to a large vertex buffer that must be able to hold all verts per frame, the budget is fixed. | ||||
| 		// TODO(Ed): Add a way to relase and remake the buffer when an overflow is detected for a frame. | ||||
| 		gfx_v_buffer = sokol_gfx.make_buffer( BufferDesciption { | ||||
| 			size  = Font_Provider_Gfx_vBuffer_Size, | ||||
| 			usage = BufferUsage.DYNAMIC, | ||||
| 			type  = BufferType.VERTEXBUFFER, | ||||
| 		}) | ||||
| 		verify( sokol_gfx.query_buffer_state(gfx_v_buffer) != sokol_gfx.Resource_State.INVALID, | ||||
| 			"Failed to make font provider's gfx_v_buffer" ) | ||||
|  | ||||
| 		uv_coords : [6]Vec2 = { | ||||
| 			0 = { 0.0, 0.0 }, | ||||
| 			1 = { 0.0, 1.0 }, | ||||
| 			2 = { 1.0, 1.0 }, | ||||
|  | ||||
| 			3 = { 0.0, 0.0 }, | ||||
| 			4 = { 1.0, 1.0 }, | ||||
| 			5 = { 1.0, 0.0 }, | ||||
| 		} | ||||
|  | ||||
| 		// All quads will use the same vertex buffer for texture coordinates. | ||||
| 		gfx_uv_buffer = sokol_gfx.make_buffer( BufferDesciption { | ||||
| 			size  = 0, | ||||
| 			usage = BufferUsage.IMMUTABLE, | ||||
| 			type  = BufferType.VERTEXBUFFER, | ||||
| 			data  = Range { & uv_coords[0], size_of(uv_coords) }, | ||||
| 		}) | ||||
| 		verify( sokol_gfx.query_buffer_state(gfx_uv_buffer) != sokol_gfx.Resource_State.INVALID, | ||||
| 			"Failed to make font provider's gfx_uv_buffer" ) | ||||
|  | ||||
|  | ||||
| 		gfx_sampler = sokol_gfx.make_sampler( SamplerDescription { | ||||
| 			min_filter    = Filter.NEAREST, | ||||
| 			mag_filter    = Filter.NEAREST, | ||||
| 			mipmap_filter = Filter.NONE, | ||||
| 			wrap_u        = Wrap.CLAMP_TO_EDGE, | ||||
| 			wrap_v        = Wrap.CLAMP_TO_EDGE, | ||||
| 			border_color  = BorderColor.OPAQUE_BLACK, | ||||
| 		}) | ||||
|  | ||||
| 		glyph_vs_layout : VertexLayoutState | ||||
| 		{ | ||||
| 			using glyph_vs_layout | ||||
| 			attrs[ATTR_font_glyph_vs_vertex] = VertexAttributeState { | ||||
| 				format       = VertexFormat.FLOAT2, | ||||
| 				offset       = 0, | ||||
| 				buffer_index = ATTR_font_glyph_vs_vertex, | ||||
| 			} | ||||
| 			buffers[ATTR_font_glyph_vs_vertex] = VertexBufferLayoutState { | ||||
| 				stride    = size_of(Vec2), | ||||
| 				step_func = VertexStep.PER_VERTEX, | ||||
| 			} | ||||
|  | ||||
| 			attrs[ATTR_font_glyph_vs_texture_coord] = VertexAttributeState { | ||||
| 				format       = VertexFormat.FLOAT2, | ||||
| 				offset       = 0, | ||||
| 				buffer_index = ATTR_font_glyph_vs_texture_coord, | ||||
| 			} | ||||
| 			buffers[ATTR_font_glyph_vs_texture_coord] = VertexBufferLayoutState { | ||||
| 				stride    = size_of(Vec2), | ||||
| 				step_func = VertexStep.PER_VERTEX, | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		gfx_pipeline = sokol_gfx.make_pipeline( | ||||
| 		{ | ||||
| 			shader     = glyph_shader, | ||||
| 			layout     = glyph_vs_layout, | ||||
| 			index_type = VertexIndexType.NONE, | ||||
| 			colors = { | ||||
| 				0 = ColorTargetState \ | ||||
| 				{ | ||||
| 					blend = BlendState { | ||||
| 						enabled = true, | ||||
| 						src_factor_rgb   = BlendFactor.SRC_ALPHA, | ||||
| 						dst_factor_rgb   = BlendFactor.ONE_MINUS_SRC_ALPHA, | ||||
| 						op_rgb           = BlendOp.ADD, | ||||
| 						src_factor_alpha = BlendFactor.ONE, | ||||
| 						dst_factor_alpha = BlendFactor.ZERO, | ||||
| 						op_alpha         = BlendOp.ADD, | ||||
| 					} | ||||
| 				}, | ||||
| 			}, | ||||
| 			color_count  = 1, | ||||
| 			sample_count = 1, | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	log("font_provider initialized") | ||||
| } | ||||
|  | ||||
| font_provider_reload :: proc() | ||||
| { | ||||
| 	 | ||||
| } | ||||
|  | ||||
| font_provider_shutdown :: proc() | ||||
| { | ||||
| 	font_provider_data := & get_state().font_provider_data; using font_provider_data | ||||
| 	for & entry in font_cache.lookup | ||||
| 	{ | ||||
| 		if entry == nil do continue | ||||
| 		def := entry.value | ||||
|  | ||||
| 		// TODO(Ed): Free entry resources. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| when Font_Provider_Use_Freetype | ||||
| { | ||||
| 	font_load :: proc(path_file : string, | ||||
| 		default_size : f32    = Font_Load_Use_Default_Size, | ||||
| 		desired_id   : string = Font_Load_Gen_ID | ||||
| 	) -> FontID | ||||
| 	{ | ||||
| 		profile(#procedure) | ||||
|  | ||||
| 		logf("Loading font: %v", path_file) | ||||
| 		font_provider_data := & get_state().font_provider_data; using font_provider_data | ||||
|  | ||||
| 		font_data, read_succeded : = os.read_entire_file( path_file ) | ||||
| 		verify( b32(read_succeded), str_fmt("Failed to read font file for: %v", path_file) ) | ||||
| 		font_data_size := cast(i32) len(font_data) | ||||
|  | ||||
| 		desired_id := desired_id | ||||
| 		// Use file name as key | ||||
| 		if len(desired_id) == 0 { | ||||
| 			// NOTE(Ed): This should never be used except for laziness so I'll be throwing a warning everytime. | ||||
| 			log("desired_key not provided, using file name. Give it a proper name!", LogLevel.Warning) | ||||
| 			// desired_id = cast(FontID) file_name_from_path(path_file) | ||||
| 			desired_id = file_name_from_path(path_file) | ||||
| 		} | ||||
|  | ||||
| 		key            := cast(u64) crc32( transmute([]byte) desired_id ) | ||||
| 		def, set_error := hmap_chained_set(font_cache, key, FontDef{}) | ||||
| 		verify( set_error == AllocatorError.None, "Failed to add new font entry to cache" ) | ||||
|  | ||||
| 		def.path_file = path_file | ||||
|  | ||||
| 		face_index :: 0 | ||||
| 		freetype.new_memory_face( font_provider_data.parser.lib, raw_data(font_data), font_data_size, face_index, & def.parser_info.face ) | ||||
|  | ||||
| 		// Hardcoding to 24 pt for testing (until we have a proper cached atlas) | ||||
| 		freetype.set_pixel_sizes( def.parser_info.face, 0, 72 ) | ||||
|  | ||||
| 		for ascii_code in 0 ..< 128 | ||||
| 		{ | ||||
| 			load_error := freetype.load_char(def.parser_info.face, u32(ascii_code), {freetype.Load_Flag.Render}) | ||||
| 			verify( load_error == .Ok, "Failed to load character using freetype" ) | ||||
|  | ||||
| 			// using def.parser_info | ||||
| 			using def | ||||
| 			// glyph  := parser_info.face.glyph | ||||
| 			// bitmap := & glyph.bitmap | ||||
| 			using parser_info.face.glyph | ||||
|  | ||||
| 			codepoint := rune(ascii_code) | ||||
| 			if ! unicode.is_print(codepoint) || bitmap.width <= 0 do continue | ||||
|  | ||||
| 			ImageDescription :: sokol_gfx.Image_Desc | ||||
| 			ImageUsage       :: sokol_gfx.Usage | ||||
| 			Range            :: sokol_gfx.Range | ||||
| 			PixelFormat      :: sokol_gfx.Pixel_Format | ||||
|  | ||||
| 			glyph_data : sokol_gfx.Image_Data | ||||
| 			glyph_data.subimage[0][0] = Range { bitmap.buffer, u64(bitmap.width * bitmap.rows)	} | ||||
|  | ||||
| 			desc := sokol_gfx.Image_Desc { | ||||
| 				type          = sokol_gfx.Image_Type._2D, | ||||
| 				render_target = false, | ||||
| 				width         = i32(bitmap.width), | ||||
| 				height        = i32(bitmap.rows), | ||||
| 				num_slices    = 1, | ||||
| 				num_mipmaps   = 1, | ||||
| 				usage         = ImageUsage.IMMUTABLE, | ||||
| 				pixel_format  = PixelFormat.R8, | ||||
| 				sample_count  = 0, | ||||
| 				data          = glyph_data, | ||||
| 				label         = strings.clone_to_cstring(str_fmt("font_ascii %v", ascii_code)) | ||||
| 			} | ||||
|  | ||||
| 			// width := i32(bitmap.width) | ||||
| 			// rows  := i32(bitmap.rows) | ||||
| 			// logf("font_ascii      : %v", ascii_code ) | ||||
| 			// logf("font_ascii glyph: %v", rune(ascii_code) ) | ||||
|  | ||||
| 			sokol_img := sokol_gfx.make_image( desc ) | ||||
| 			verify( sokol_gfx.query_image_state(sokol_img) != sokol_gfx.Resource_State.INVALID, | ||||
| 				"Failed to create image on sokol gfx" ); | ||||
|  | ||||
| 			def.glyphs[ascii_code] = FontGlyph { | ||||
| 				size     = { i32(bitmap.width), i32(bitmap.rows) }, | ||||
| 				bearing  = { bitmap_left,  bitmap_top }, | ||||
| 				texture  = sokol_img, | ||||
| 				advance  = u32(advance.x), | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		freetype.done_face( def.parser_info.face ) | ||||
|  | ||||
| 		fid := FontID { key, desired_id } | ||||
| 		return fid | ||||
| 	} | ||||
| } | ||||
| @@ -191,6 +191,9 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input | ||||
| 		input.mouse.btns[id].ended_down = prev_btn.ended_down | ||||
| 	} | ||||
|  | ||||
| 	input.mouse.raw_pos = prev_input.mouse.raw_pos | ||||
| 	input.mouse.pos     = prev_input.mouse.pos | ||||
|  | ||||
| 	input_events := input_events | ||||
| 	using input_events | ||||
|  | ||||
| @@ -266,11 +269,12 @@ poll_input_events :: proc( input, prev_input : ^InputState, input_events : Input | ||||
| 				case .Mouse_Move: | ||||
| 				case .Mouse_Enter: | ||||
| 				case .Mouse_Leave: | ||||
| 					// Handled elsewhere | ||||
| 					// Handled below | ||||
| 			} | ||||
|  | ||||
| 			input.mouse.pos   = event.pos | ||||
| 			input.mouse.delta = event.delta | ||||
| 			input.mouse.raw_pos = event.pos | ||||
| 			input.mouse.pos     = render_to_screen_pos( event.pos ) | ||||
| 			input.mouse.delta   = event.delta | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -98,7 +98,7 @@ PWS_LineArray_ReserveSize  :: 32 * Kilobyte | ||||
| PWS_ParseResult :: struct { | ||||
| 	content   : string, | ||||
| 	tokens    : Array(PWS_Token), | ||||
| 	nodes     : Array(PWS_AST), // Nodes should be dumped in a pool. | ||||
| 	nodes     : Array(PWS_AST), // Nodes should be dumped in a pool? | ||||
| 	lines     : Array( ^PWS_AST), | ||||
| 	errors    : [PWS_ParseError_Max] PWS_ParseError, | ||||
| } | ||||
|   | ||||
| @@ -32,26 +32,6 @@ Side :: enum i32 { | ||||
| // 	Count, | ||||
| // } | ||||
|  | ||||
| // UI_AnchorPresets :: enum u32 { | ||||
| // 	Top_Left, | ||||
| // 	Top_Right, | ||||
| // 	Bottom_Right, | ||||
| // 	Bottom_Left, | ||||
| // 	Center_Left, | ||||
| // 	Center_Top, | ||||
| // 	Center_Right, | ||||
| // 	Center_Bottom, | ||||
| // 	Center, | ||||
| // 	Left_Wide, | ||||
| // 	Top_Wide, | ||||
| // 	Right_Wide, | ||||
| // 	Bottom_Wide, | ||||
| // 	VCenter_Wide, | ||||
| // 	HCenter_Wide, | ||||
| // 	Full, | ||||
| // 	Count, | ||||
| // } | ||||
|  | ||||
| UI_Cursor :: struct { | ||||
| 	placeholder : int, | ||||
| } | ||||
| @@ -78,7 +58,6 @@ UI_ScalarConstraint :: struct { | ||||
|  | ||||
| UI_Scalar2 :: [Axis2.Count]UI_Scalar | ||||
|  | ||||
|  | ||||
| // UI_BoxFlags_Stack_Size    :: 512 | ||||
| UI_Layout_Stack_Size      :: 512 | ||||
| UI_Style_Stack_Size       :: 512 | ||||
| @@ -88,7 +67,7 @@ UI_Built_Boxes_Array_Size :: 128 * Kilobyte | ||||
|  | ||||
| // TODO(Ed): Rename to UI_Context | ||||
| UI_State :: struct { | ||||
| 	// TODO(Ed) : Use these | ||||
| 	// TODO(Ed) : Use these? | ||||
| 	// build_arenas : [2]Arena, | ||||
| 	// build_arena  : ^ Arena, | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,25 @@ package sectr | ||||
| import "core:math" | ||||
| import "core:math/linalg" | ||||
|  | ||||
| // UI_AnchorPresets :: enum u32 { | ||||
| // 	Top_Left, | ||||
| // 	Top_Right, | ||||
| // 	Bottom_Right, | ||||
| // 	Bottom_Left, | ||||
| // 	Center_Left, | ||||
| // 	Center_Top, | ||||
| // 	Center_Right, | ||||
| // 	Center_Bottom, | ||||
| // 	Center, | ||||
| // 	Left_Wide, | ||||
| // 	Top_Wide, | ||||
| // 	Right_Wide, | ||||
| // 	Bottom_Wide, | ||||
| // 	VCenter_Wide, | ||||
| // 	HCenter_Wide, | ||||
| // 	Full, | ||||
| // 	Count, | ||||
| // } | ||||
|  | ||||
| // Anchor_ | ||||
|  | ||||
| @@ -16,7 +35,6 @@ LayoutAlign_OriginTL_Bottom       :: Vec2{0.5,   1} | ||||
| LayoutAlign_OriginTL_BottomLeft   :: Vec2{  0,   1} | ||||
| LayoutAlign_OriginTL_BottomRight  :: Vec2{  1,   1} | ||||
|  | ||||
|  | ||||
| Layout_OriginCenter_Centered :: Vec2{0.5, 0.5} | ||||
|  | ||||
| UI_Align_Presets_Struct :: struct { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user