From 819cf3e4e8abb5ad41d8830155fc20bd833b21e8 Mon Sep 17 00:00:00 2001 From: navewindre Date: Wed, 17 Jul 2024 08:36:51 +0200 Subject: render wip --- dwm/grender.cpp | 1288 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1288 insertions(+) create mode 100644 dwm/grender.cpp (limited to 'dwm/grender.cpp') diff --git a/dwm/grender.cpp b/dwm/grender.cpp new file mode 100644 index 0000000..9fd3151 --- /dev/null +++ b/dwm/grender.cpp @@ -0,0 +1,1288 @@ +#include "grender.h" +#include "freetype/freetype.h" +#include + +#define xors( s ) s + +// assignment with conditional expression +#pragma warning(disable : 4706) + +// TODO OT: UNDEF THIS +#define RENDER_DEBUG 1 + +static char const *d3d11_vert_shader = xors( + R"( + struct VS_INPUT + { + float2 pos : POSITION; + float2 uv : TEXCOORD; + float4 col : COLOR; + }; + + struct PS_INPUT + { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD; + float4 col : COLOR; + }; + + cbuffer CONSTANTS : register(b0) + { + float2 screen_size; + }; + + PS_INPUT main(VS_INPUT input) + { + PS_INPUT output; + output.pos = float4(input.pos.x / screen_size.x * 2.f - 1.f, (-input.pos.y) / screen_size.y * 2.f + 1.f, 0.0f, 1.0f); + output.uv = input.uv; + output.col = input.col; + return output; + } + )" +); + +static char const *d3d11_pixel_shader = xors( + R"( + struct PS_INPUT + { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD; + float4 col : COLOR; + }; + + float4 main(PS_INPUT input) : SV_TARGET + { + return input.col; + } + )" +); + +static char const *d3d11_pixel_shader_textured = xors( + R"( + struct PS_INPUT + { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD; + float4 col : COLOR; + }; + + Texture2D texture0 : register(t0); + SamplerState sampler0 : register(s0); + + float4 main(PS_INPUT input) : SV_TARGET + { + float4 out_col = texture0.Sample(sampler0, input.uv); + return input.col * out_col; + } + )" +); + +// TODO OT: +// find correct d3dcompiler export, u have ur api shit to handle it. +HRESULT +D3DCompile( + char const *src, size_t len, char const *entry_point, char const *target, UINT flags, UINT shader_flags, + ID3DBlob **blob, ID3DBlob **error_blob +) +{ + // return D3DCompile( src, len, nullptr, nullptr, nullptr, entry_point, target, flags, shader_flags, blob, error_blob ); + + static pD3DCompile D3DCompile_ = (pD3DCompile)GetProcAddress(GetModuleHandleA("d3dcompiler_47.dll"), "D3DCompile"); + return D3DCompile_(src, len, nullptr, nullptr, nullptr, entry_point, target, flags, shader_flags, blob, error_blob); +} + +D3D11_RENDERDATA* d3d11_init() { + D3D11_RENDERDATA* data = new D3D11_RENDERDATA; + memset( data, 0, sizeof(D3D11_RENDERDATA) - sizeof(std::vector) * 2); + + + return data; +} + +bool d3d11_init_shaders( D3D11_RENDERDATA* data ) { + ID3DBlob* error_blob; + + if( !!D3DCompile( + d3d11_vert_shader, + strlen( d3d11_vert_shader ), + xors("main"), xors("vs_4_0"), + 0, 0, + &data->vs_blob, + &error_blob ) + ) { +#if RENDER_DEBUG + printf( "d3d11_init_shaders() : error creating vertex shader: %s\n", (char*)error_blob->GetBufferPointer() ); +#endif + return false; + } + + if( !!data->device->CreateVertexShader( + data->vs_blob->GetBufferPointer(), + data->vs_blob->GetBufferSize(), + nullptr, + &data->vertex_shader + ) ) { + return false; + } + + if( !!D3DCompile( + d3d11_pixel_shader, + strlen( d3d11_pixel_shader ), + xors("main"), xors("ps_4_0"), + 0, 0, + &data->ps_blob, + &error_blob ) ) { + return false; + } + + if( !!data->device->CreatePixelShader( + data->ps_blob->GetBufferPointer(), + data->ps_blob->GetBufferSize(), + nullptr, + &data->pixel_shader + ) ) { +#if RENDER_DEBUG + printf( "d3d11_init_shaders() : error creating pixel shader: %s\n", (char*)error_blob->GetBufferPointer() ); +#endif + return false; + } + + if( !!D3DCompile( + d3d11_pixel_shader_textured, + strlen( d3d11_pixel_shader_textured ), + xors("main"), xors("ps_4_0"), + 0, 0, + &data->ps_blob_textured, + &error_blob ) ) { + return false; + } + + if( !!data->device->CreatePixelShader( + data->ps_blob_textured->GetBufferPointer(), + data->ps_blob_textured->GetBufferSize(), + nullptr, + &data->pixel_shader_textured + ) ) { +#if RENDER_DEBUG + printf( "d3d11_init_shaders() : error creating textured pixel shader: %s\n", (char*)error_blob->GetBufferPointer() ); +#endif + return false; + } + + D3D11_INPUT_ELEMENT_DESC input_element_desc[] = { + { xors("POSITION"), 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { xors("TEXCOORD"), 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(D3D11_VERTEX, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { xors("COLOR"), 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(D3D11_VERTEX, col), D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + + data->device->CreateInputLayout( + input_element_desc, + 3, + data->vs_blob->GetBufferPointer(), + data->vs_blob->GetBufferSize(), + &data->input_layout + ); + + return true; +} + +bool d3d11_init_resources( D3D11_RENDERDATA* data ) { + D3D11_BUFFER_DESC buffer_desc; + buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + buffer_desc.ByteWidth = sizeof(D3D11_VERTEX) * 8192; // ye baby + buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + buffer_desc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA subresource_data; + subresource_data.pSysMem = nullptr; + + HRESULT hr; + if( !!( hr = data->device->CreateBuffer( &buffer_desc, nullptr, &data->vertex_buffer ) ) ) { + return false; + } + + if( !!data->device->CreateRenderTargetView( data->back_buffer, nullptr, &data->render_target_view ) ) { + return false; + } + + data->back_buffer->Release(); + data->back_buffer = nullptr; + + D3D11_BLEND_DESC blend_desc; + blend_desc.AlphaToCoverageEnable = false; + blend_desc.IndependentBlendEnable = false; + blend_desc.RenderTarget[0].BlendEnable = true; + blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; + blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; + blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; + + if( !!data->device->CreateBlendState( &blend_desc, &data->blend_state ) ) { + return false; + } + + D3D11_RASTERIZER_DESC rasterizer_desc; + rasterizer_desc.FillMode = D3D11_FILL_SOLID; + rasterizer_desc.CullMode = D3D11_CULL_NONE; + rasterizer_desc.ScissorEnable = false; + rasterizer_desc.DepthClipEnable = false; + + if( !!data->device->CreateRasterizerState( &rasterizer_desc, &data->rasterizer_state ) ) { + return false; + } + + D3D11_DEPTH_STENCIL_DESC depth_stencil_desc; + depth_stencil_desc.DepthEnable = false; + depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depth_stencil_desc.DepthFunc = D3D11_COMPARISON_LESS; + depth_stencil_desc.StencilEnable = false; + depth_stencil_desc.StencilReadMask = 0xFF; + depth_stencil_desc.StencilWriteMask = 0xFF; + depth_stencil_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depth_stencil_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; + depth_stencil_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depth_stencil_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depth_stencil_desc.BackFace = depth_stencil_desc.FrontFace; + + if( !!data->device->CreateDepthStencilState( &depth_stencil_desc, &data->depth_stencil_state ) ) { + return false; + } + + // constant buffer + D3D11_BUFFER_DESC constant_buffer_desc; + constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; + constant_buffer_desc.ByteWidth = sizeof(DXMAT4X4); + constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constant_buffer_desc.MiscFlags = 0; + constant_buffer_desc.StructureByteStride = 0; + + if( !!data->device->CreateBuffer( &constant_buffer_desc, nullptr, &data->constant_buffer ) ) { + return false; + } + + for( auto& it : data->textures ) { + if( it->rgba ) + d3d11_texture_init( data, it ); + } + + return true; +} + +#define RELEASE_RSRC(x) if( x ) x->Release(); x = nullptr; + +void d3d11_destroy_resources( D3D11_RENDERDATA* data ) { + RELEASE_RSRC( data->input_layout ); + RELEASE_RSRC( data->blend_state ); + RELEASE_RSRC( data->rasterizer_state ); + RELEASE_RSRC( data->depth_stencil_state ); + + RELEASE_RSRC( data->vertex_shader ); + RELEASE_RSRC( data->pixel_shader ); + RELEASE_RSRC( data->pixel_shader_textured ); + + RELEASE_RSRC( data->vs_blob ); + RELEASE_RSRC( data->ps_blob ); + RELEASE_RSRC( data->ps_blob_textured ); + RELEASE_RSRC( data->render_target_view ); + + RELEASE_RSRC( data->vertex_buffer ); + RELEASE_RSRC( data->constant_buffer ); + for( auto& it : data->textures ) { + RELEASE_RSRC( it->srv ); + RELEASE_RSRC( it->tex2d ); + } +} + +#undef RELEASE_RSRC + +void d3d11_on_swapchain_lost( D3D11_RENDERDATA* data ) { + d3d11_destroy_resources( data ); + + if( !data->device ) { + data->clip = { 0, 0, (LONG)data->display[0], (LONG)data->display[1] }; + } + + data->swapchain->GetDevice( __uuidof( ID3D11Device ), ( LPVOID* )&data->device ); + data->device->GetImmediateContext( &data->context ); + data->swapchain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&data->back_buffer ); + + if( !d3d11_init_shaders( data ) ) { +#if RENDER_DEBUG + printf( "d3d11_on_swapchain_lost() : error initializing shaders\n" ); +#endif + return; + } + + if( !d3d11_init_resources( data ) ) { +#if RENDER_DEBUG + printf( "d3d11_on_swapchain_lost() : error initializing resources\n" ); +#endif + } +} + +void d3d11_texture_init( D3D11_RENDERDATA* data, D3D11_TEXTURE* tex ) { + D3D11_TEXTURE2D_DESC texture_desc; + memset( &texture_desc, 0, sizeof( texture_desc ) ); + + texture_desc.Width = tex->w; + texture_desc.Height = tex->h; + texture_desc.MipLevels = 1; + texture_desc.ArraySize = 1; + texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texture_desc.SampleDesc.Count = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + D3D11_SUBRESOURCE_DATA resource_data; + memset( &resource_data, 0, sizeof( resource_data ) ); + resource_data.pSysMem = tex->rgba; + resource_data.SysMemPitch = tex->w * 4; + resource_data.SysMemSlicePitch = tex->w * tex->h * 4; + + HRESULT hr; + if( !!( hr = data->device->CreateTexture2D( &texture_desc, &resource_data, &tex->tex2d ) ) ) { +#if RENDER_DEBUG + printf( "d3d11_texture_init() : error creating texture2d %x\n", hr ); +#endif + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; + memset( &srv_desc, 0, sizeof(srv_desc) ); + srv_desc.Format = texture_desc.Format; + srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = 1; + + if( !!data->device->CreateShaderResourceView( tex->tex2d, &srv_desc, &tex->srv ) ) { +#if RENDER_DEBUG + printf( "d3d11_texture_init() : error creating shader resource view\n" ); +#endif + } +} + +D3D11_TEXTURE* d3d11_texture_create( D3D11_RENDERDATA* data, UINT8* rgba, I32 width, I32 height ) { + D3D11_TEXTURE* tex = (D3D11_TEXTURE*)malloc( sizeof(D3D11_TEXTURE) ); + tex->w = width; + tex->h = height; + tex->rgba = rgba; + + d3d11_texture_init( data, tex ); + + data->textures.push_back( tex ); + return tex; +} + +void d3d11_texture_destroy( D3D11_RENDERDATA* data, D3D11_TEXTURE* tex ) { + for( auto it = data->textures.begin(); it != data->textures.end(); ++it ) { + if( *it == tex ) { + data->textures.erase( it ); + break; + } + } + + if( tex->srv ) + tex->srv->Release(); + if( tex->tex2d ) + tex->tex2d->Release(); + + free( tex ); +} + +void d3d11_on_present( D3D11_RENDERDATA* data, void* swapchain ) { + if( swapchain != data->swapchain ) { + data->swapchain = (IDXGISwapChain*)swapchain; + d3d11_on_swapchain_lost( data ); + } + + DXGI_SWAP_CHAIN_DESC desc; + data->swapchain->GetDesc( &desc ); + + if( data->display[0] != (float)desc.BufferDesc.Width + || data->display[1] != (float)desc.BufferDesc.Height ) + d3d11_on_swapchain_lost( data ); + + data->display[0] = (float)desc.BufferDesc.Width; + data->display[1] = (float)desc.BufferDesc.Height; + + F32 blend_factor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + data->context->OMSetBlendState( data->blend_state, blend_factor, 0xFFFFFFFF ); + data->context->OMSetDepthStencilState( data->depth_stencil_state, 0 ); + data->context->RSSetState( data->rasterizer_state ); + + D3D11_VIEWPORT viewport; + viewport.Width = data->display[0]; + viewport.Height = data->display[1]; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + viewport.TopLeftX = viewport.TopLeftY = 0; + data->context->RSSetViewports( 1, &viewport ); + + data->context->GSSetShader( nullptr, nullptr, 0 ); + data->context->HSSetShader( nullptr, nullptr, 0 ); + data->context->DSSetShader( nullptr, nullptr, 0 ); + data->context->CSSetShader( nullptr, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->constant_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, data->display, sizeof(DXVEC2) ); + data->context->Unmap( data->constant_buffer, 0 ); + data->context->VSSetConstantBuffers( 0, 1, &data->constant_buffer ); + + data->context->OMSetRenderTargets( 1, &data->render_target_view, nullptr ); + d3d11_set_clip( data, &data->clip ); +} + +void d3d11_set_clip( D3D11_RENDERDATA* data, RECT* clip ) { + if( clip ) { + D3D11_RECT rect; + rect.left = clip->left; + rect.top = clip->top; + rect.right = clip->right; + rect.bottom = clip->bottom; + data->context->RSSetScissorRects( 1, &rect ); + data->clip = *clip; + } else { + data->clip = { 0, 0, (I32)data->display[0], (I32)data->display[1] }; + data->context->RSSetScissorRects( 0, nullptr ); + } +} + +void d3d11_get_clip( D3D11_RENDERDATA* data, RECT* clip ) { + *clip = data->clip; +} + +/* +          ,、     ,、 +        r'ー》'´`⌒ヾ‐》,     / ̄ ̄ ̄ ̄ ̄ +         i  iミ ノ リハリ/!   .| +        ! i゙瓦゚ ヮ゚ノ!' i|  < Mikku Mikku♪ +        !l! ! と.フリ{つ!i! l    | +        ノリ | v/_j_、 i!l !   \_____ +        ゞノ  ~じ'フ~ル'ノ   _.__       lヽ,,lヽ +             _| ::|_      | |Θ|=つ≡つ;;)   ) +        | ̄ ̄ ̄| ̄ ̄|_ |_|≡つ=つ  と   i +        |___|__|_|  |_| ミクミクミクミクしーJ + + + */ + +void d3d11_line( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 pos2, FCLR col ) { + UINT stride = sizeof(D3D11_VERTEX); + UINT offset = 0; + + D3D11_VERTEX vertices[] = { + { pos.x, pos.y, 0.0f, 0.0f, col }, + { pos2.x, pos2.y, 0.0f, 0.0f, col } + }; + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(vertices) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST ); + + data->context->Draw( 2, 0 ); +} + + +void d3d11_rect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, FCLR col ) { + UINT stride = sizeof(D3D11_VERTEX); + UINT offset = 0; + + D3D11_VERTEX vertices[] = { + { pos.x , pos.y , 0.0f, 0.0f, col }, + { pos.x + size.x, pos.y , 0.0f, 1.0f, col }, + { pos.x + size.x, pos.y + size.y, 0.0f, 0.0f, col }, + { pos.x , pos.y + size.y, 0.0f, 1.0f, col }, + { pos.x , pos.y , 0.0f, 0.0f, col } + }; + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(vertices) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP ); + + data->context->Draw( 5, 0 ); +} + +void d3d11_frect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, FCLR col ) { + UINT stride = sizeof(D3D11_VERTEX); + UINT offset = 0; + + D3D11_VERTEX vertices[] = { + { pos.x, pos.y, 0.0f, 0.0f, col }, + { pos.x + size.x, pos.y, 0.0f, 1.0f, col }, + { pos.x, pos.y + size.y, 0.0f, 0.0f, col }, + { pos.x + size.x, pos.y + size.y, 0.0f, 1.0f, col } + }; + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(vertices) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); + + data->context->Draw( 4, 0 ); +} + +void d3d11_textured_frect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, D3D11_TEXTURE* texture, FCLR col ) { + UINT stride = sizeof(D3D11_VERTEX); + UINT offset = 0; + + D3D11_VERTEX vertices[] = { + { pos.x, pos.y, 0.0f, 0.0f, col }, + { pos.x + size.x, pos.y, 1.0f, 0.0f, col }, + { pos.x, pos.y + size.y, 0.0f, 1.0f, col }, + { pos.x + size.x, pos.y + size.y, 1.0f, 1.0f, col } + }; + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader_textured, nullptr, 0 ); + data->context->PSSetShaderResources( 0, 1, &texture->srv ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(vertices) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); + + data->context->Draw( 4, 0 ); +} + +void d3d11_gradient_frect( + D3D11_RENDERDATA* data, + DXVEC2 pos, + DXVEC2 size, + FCLR tl, + FCLR tr, + FCLR bl, + FCLR br +) { + UINT stride = sizeof(D3D11_VERTEX); + UINT offset = 0; + + D3D11_VERTEX vertices[] = { + { pos.x, pos.y, 0.0f, 0.0f, tl }, + { pos.x + size.x, pos.y, 0.0f, 1.0f, tr }, + { pos.x, pos.y + size.y, 0.0f, 0.0f, bl }, + { pos.x + size.x, pos.y + size.y, 0.0f, 1.0f, br } + }; + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(vertices) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); + + data->context->Draw( 4, 0 ); +} + + +void d3d11_fcircle( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, FCLR col, I32 res ) { + UINT stride = sizeof(D3D11_VERTEX); + UINT offset = 0; + + D3D11_VERTEX* vertices = (D3D11_VERTEX*)malloc( sizeof(D3D11_VERTEX) * (res * 2) ); + for( I32 i = 0; i < res * 2; i += 2 ) { + F32 sin = sinf( (float)i / res * 2.f * 3.14159265358979323846f ); + F32 cos = cosf( (float)i / res * 2.f * 3.14159265358979323846f ); + vertices[i].x = pos.x; + vertices[i].y = pos.y; + vertices[i].uv.x = 0.5f; + vertices[i].uv.y = 0.5f; + vertices[i].col = col; + + vertices[i + 1].x = pos.x + sin * radius; + vertices[i + 1].y = pos.y + cos * radius; + vertices[i + 1].uv.x = 0.5f + ( sin * radius * 0.5f ) / radius; + vertices[i + 1].uv.y = 0.5f + ( cos * radius * 0.5f ) / radius; + vertices[i + 1].col = col; + } + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(D3D11_VERTEX) * (res + 2) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); + + data->context->Draw( res + 2, 0 ); + free( vertices ); +} + +void d3d11_circle( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, FCLR col, I32 res ) { + UINT stride = sizeof(D3D11_VERTEX); + UINT offset = 0; + + D3D11_VERTEX* vertices = (D3D11_VERTEX*)malloc( sizeof(D3D11_VERTEX) * (res + 1) ); + for( I32 i = 0; i < res + 1; ++i ) { + F32 sin = sinf( (float)i / (float)res * 2.f * 3.14159265358979323846f ); + F32 cos = cosf( (float)i / (float)res * 2.f * 3.14159265358979323846f ); + + vertices[i].x = pos.x + sin * radius; + vertices[i].y = pos.y + cos * radius; + vertices[i].uv.x = 0.5f + ( sin * radius * 0.5f ) / radius; + vertices[i].uv.y = 0.5f + ( cos * radius * 0.5f ) / radius; + vertices[i].col = col; + } + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(D3D11_VERTEX) * (res + 1) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP ); + + data->context->Draw( res + 1, 0 ); + free( vertices ); +} + +void d3d11_arc( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, F32 start_angle, F32 end_angle, FCLR col, I32 res ) { + U32 stride = sizeof(D3D11_VERTEX); + U32 offset = 0; + + start_angle = start_angle * (3.14159265358979323846f / 180.f); + end_angle = end_angle * (3.14159265358979323846f / 180.f); + + D3D11_VERTEX* vertices = (D3D11_VERTEX*)malloc( sizeof(D3D11_VERTEX) * (res + 1) ); + for( I32 i = 0; i < res + 1; ++i ) { + F32 sin = sinf( (float)i / (float)res * ( end_angle - start_angle ) + start_angle ); + F32 cos = cosf( (float)i / (float)res * ( end_angle - start_angle ) + start_angle ); + + vertices[i].x = pos.x + sin * radius; + vertices[i].y = pos.y + cos * radius; + vertices[i].uv.x = 0.5f + ( sin * radius * 0.5f ) / radius; + vertices[i].uv.y = 0.5f + ( cos * radius * 0.5f ) / radius; + vertices[i].col = col; + } + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(D3D11_VERTEX) * (res + 1) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP ); + + data->context->Draw( res + 1, 0 ); + free( vertices ); +} + +void d3d11_farc( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, F32 start_angle, F32 end_angle, FCLR col, I32 res ) { + return d3d11_farc_2clr( data, pos, radius, start_angle, end_angle, col, col, res ); +} + +void d3d11_farc_2clr( + D3D11_RENDERDATA* data, + DXVEC2 pos, + F32 radius, + F32 start_angle, + F32 end_angle, + FCLR col1, + FCLR col2, + I32 res +) { + U32 stride = sizeof(D3D11_VERTEX); + U32 offset = 0; + + start_angle = start_angle * (3.14159265358979323846f / 180.f); + end_angle = end_angle * (3.14159265358979323846f / 180.f); + F32 step = ( end_angle - start_angle ) / (res - 1); + + D3D11_VERTEX* vertices = (D3D11_VERTEX*)malloc( sizeof(D3D11_VERTEX) * (res * 2) ); + for( I32 i = 0; i < res * 2; i += 2 ) { + F32 sin = sinf( (float)(i / 2) * step + start_angle ); + F32 cos = cosf( (float)(i / 2) * step + start_angle ); + + vertices[i].x = pos.x; + vertices[i].y = pos.y; + vertices[i].uv.x = 0.5f; + vertices[i].uv.y = 0.5f; + vertices[i].col = col1; + + vertices[i + 1].x = pos.x + cos * radius; + vertices[i + 1].y = pos.y + sin * radius; + vertices[i + 1].uv.x = 0.5f + ( sin * radius * 0.5f ) / radius; + vertices[i + 1].uv.y = 0.5f + ( cos * radius * 0.5f ) / radius; + vertices[i + 1].col = col2; + } + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(D3D11_VERTEX) * (res * 2) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ); + + data->context->Draw( res * 2, 0 ); + free( vertices ); +} + +void d3d11_thick_circle( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius_in, F32 radius_out, FCLR col, I32 res ) { + UINT stride = sizeof( D3D11_VERTEX ); + UINT offset = 0; + + D3D11_VERTEX* vertices = (D3D11_VERTEX*)malloc( sizeof(D3D11_VERTEX) * (res * 6) ); + F32 step = (2 * 3.14159265358979323846f) / (res - 1); + + for( I32 i = 0; i < res; ++i ) { + F32 t1 = step * i; + F32 t2 = step * (i + 1); + + F32 s1 = sinf( t1 ); + F32 c1 = cosf( t1 ); + + F32 s2 = sinf( t2 ); + F32 c2 = cosf( t2 ); + + D3D11_VERTEX bl = { pos.x + c1 * radius_in, pos.y + s1 * radius_in, 0, 0, col }; + D3D11_VERTEX tl = { pos.x + c1 * radius_out, pos.y + s1 * radius_out, 0, 0, col }; + D3D11_VERTEX br = { pos.x + c2 * radius_in, pos.y + s2 * radius_in, 0, 0, col }; + D3D11_VERTEX tr = { pos.x + c2 * radius_out, pos.y + s2 * radius_out, 0, 0, col }; + + vertices[i * 6] = tl; + vertices[i * 6 + 1] = tr; + vertices[i * 6 + 2] = bl; + vertices[i * 6 + 3] = bl; + vertices[i * 6 + 4] = tr; + vertices[i * 6 + 5] = br; + } + + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader, nullptr, 0 ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(D3D11_VERTEX) * (res * 6) ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); + + data->context->Draw( res * 6, 0 ); + free( vertices ); +} + + +void d3d11_rounded_rect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, F32 radius, FCLR col, I32 flags ) { + if( size.x <= 6 && flags == 0xFFFF ) { + d3d11_line( data, { pos.x, pos.y + 1 }, { pos.x, pos.y + size.y - 1 }, col ); + + if( size.x > 2 ) { + for( I32 i = 0; i < size.x - 2; ++i ) { + d3d11_line( data, { pos.x + i + 1, pos.y }, { pos.x + i + 1, pos.y + size.y }, col ); + } + } + + d3d11_line( data, { pos.x + size.x - 1, pos.y + 1 }, { pos.x + size.x - 1, pos.y + size.y - 1 }, col ); + return; + } + + d3d11_frect( data, { pos.x + radius, pos.y }, { size.x - radius * 2, size.y }, col ); + d3d11_frect( data, { pos.x, pos.y + radius }, { size.x, size.y - radius * 2 }, col ); + + if( flags & e_top_left ) + d3d11_farc( data, { pos.x + radius, pos.y + radius }, radius, 270.f, 360.f, col ); + else if( radius > size.x && radius > size.y ) + d3d11_frect( data, { pos.x, pos.y }, { radius, radius }, col ); + + if( flags & e_top_right ) + d3d11_farc( data, { pos.x + size.x - radius, pos.y + radius }, radius, 270.f, 360.f, col ); + else if( radius > size.x && radius > size.y ) + d3d11_frect( data, { pos.x + size.x - radius, pos.y }, { radius, radius }, col ); + + if( flags & e_bottom_left ) + d3d11_farc( data, { pos.x + radius, pos.y + size.y - radius }, radius, 90.f, 180.f, col ); + else if( radius > size.x && radius > size.y ) + d3d11_frect( data, { pos.x, pos.y + size.y - radius }, { radius, radius }, col ); + + if( flags & e_bottom_right ) + d3d11_farc( data, { pos.x + size.x - radius, pos.y + size.y - radius }, radius, 0.f, 90.f, col ); + else + d3d11_frect( data, { pos.x + size.x - radius, pos.y + size.y - radius }, { radius, radius }, col ); +} + + +/* + + _ + _|_.__ __|_ ._ _ ! + | |(/_(/_|_\/|_)(/_ ! + / | ! + + +                     ___,... __ +               ,. '"´       `丶、 +                  〃- ─=ミv' 彡=‐ -ミ、 +               /7         '´       ト 、 +              /_ノl                |ミ、\ +           〈〈´  |       jミ'ヘ        |  `>〉 +              ヾミ、|   i  //  ヽ  |   1-‐'" +              `ト|   |ノ//'   `弋、 |   j| +             j |   |≠ヵ    ヵ≠i|   jl +               从|   代リ     弋リ1   从 +                /fハ!  | ''''  ,   '''' j  ,小ハ、 +           ノ |!∧  ト、  rっ   ノ! 从!i| +            ノ少ヘ | 个r .__.. ィ彡 |/ \! +            /   V 八   /   /   \ +             /    八   \ 〃   /       ハ +            ハ   :.. : ヽ   /    / l.::   /  ! +          j  ヽ   :: !  \/    /  !//   | +          |    \::ノ:  /   /   ::{ ..::    | +            ノ ::..     |:. 〃/)(\    .:!..:::/ .:   | +         」 ::... ヾ::.. |::../∠ュr_ゝ ヽ .::::|:ノ..::::_..  〉 +            |::  ̄ ̄7ー-^{  ー {j ー  }ーヘ ̄  イ +        ___}::   ノ   ゝ '´/\` /   } ....:::::} +    ー=彡'"゙ {:::....  ト-‐ァ¬'"´   `¬=r‐-/.::::::::::/ +   、__ノ ..:.:.:八::::::::::|:::::/|==─‐--─==|:::/.:::::::::,イ +     フ .:.:.:.:.:.:.:.ヽ:::::::|::/.::|          |i/.:::::/.::| +*/ + +D3D11_FONT * +d3d11_font_create( + D3D11_RENDERDATA *data, char const *font_name, U32 font_size, UINT8 *font_data, U32 font_data_size +) +{ + D3D11_FONT* font = (D3D11_FONT*)malloc( sizeof(D3D11_FONT) ); + memset( font, 0, sizeof(D3D11_FONT) ); + + font->name = font_name; + font->size = font_size; + font->font_data = font_data; + font->font_data_size = font_data_size; + font->d3d11 = data; + + d3d11_font_init( font ); + + return font; +} + +U32 d3d11_font_count_glyphs( D3D11_FONT* font ) { + U32 ret = 0; + U32 idx; + U32 charcode = FT_Get_First_Char( font->face, &idx ); + while( idx != 0 ) { + ++ret; + charcode = FT_Get_Next_Char( font->face, charcode, &idx ); + } + + return ret; +} + +void d3d11_font_create_bitmap( D3D11_FONT* font ) { + U32 char_width = (U32)ceil((float)font->face->size->metrics.max_advance / 64.f) + 1; + U32 char_height = (U32)ceil((float)font->face->size->metrics.height / 64.f) + 3; + + U32 glyph_count = d3d11_font_count_glyphs( font ); + if( glyph_count == 0 ) + return; + if( glyph_count > 0xFFFF ) + glyph_count = 0xFFFF; + + U32 root = (U32)ceil( sqrt( glyph_count ) ); + U32 max_width = (root + 1) * char_width; + U32 max_height = (root + 1) * char_height; + + font->bitmap = (U32*)malloc( sizeof(U32) * max_width * max_height ); + memset( font->bitmap, 0, sizeof(U32) * max_width * max_height ); + + font->bitmap_width = max_width; + font->bitmap_height = max_height; + font->char_width = char_width; + font->char_height = char_height; + + U32 cur_x = 1, cur_y = 1; + for( U32 c = 0; c < 0xFFFF; ++c ) { + U32 idx = FT_Get_Char_Index( font->face, c ); + if( !idx || !!FT_Load_Char( font->face, c, FT_LOAD_DEFAULT ) ) + continue; + + if( c == ' ' ) { + font->blank_spacing = font->face->glyph->metrics.horiAdvance >> 6; + continue; + } + + if( !font->face->glyph ) + continue; + I32 w = font->face->glyph->metrics.width >> 6, h = font->face->glyph->metrics.height >> 6; + if( w > font->size && w > h * 3 ) + continue; // dumb sanity check. + if( h - (int)font->size > 1 ) // this will rape the stack if its more than 2. + continue; + if( c == 0xfdfd ) + continue; //in theory its checked above but this is cursed. fuck shitskin muzzies, learn to write. + + if( !!FT_Load_Char( font->face, c, FT_LOAD_RENDER ) ) + continue; + + FT_Bitmap* bitmap = &font->face->glyph->bitmap; + UINT8 pixel; + U32 dest_x, dest_y; + for( U32 y = 0; y < bitmap->rows; ++y ) { + for( U32 x = 0; x < bitmap->width; ++x ) { + dest_x = x + cur_x; + dest_y = y + cur_y; + + UINT8 pixel = bitmap->buffer[x + bitmap->pitch * y]; + U32 out_pixel = 0x00FFFFFF; + + out_pixel |= ((U32)(pixel) << 24); + font->bitmap[dest_x + max_width * dest_y] = out_pixel; + } + } + + font->glyphs[c] = (FONT_GLYPH*)malloc( sizeof(FONT_GLYPH) ); + font->glyphs[c]->offset_x = (float)cur_x; + font->glyphs[c]->offset_y = (float)cur_y - 1; + font->glyphs[c]->width = (float)bitmap->width; + font->glyphs[c]->height = (float)bitmap->rows + 3; + font->glyphs[c]->advance_x = (float)(font->face->glyph->metrics.horiAdvance >> 6); + font->glyphs[c]->advance_y = char_height - (float)(font->face->glyph->metrics.horiBearingY >> 6); + font->glyphs[c]->bearing_x = (float)(font->face->glyph->metrics.horiBearingX >> 6); + + if( cur_x + char_width > max_width ) { + cur_x = 1; + cur_y += char_height; + } else { + cur_x += char_width; + } + } +} + +void d3d11_font_create_atlas( D3D11_FONT* font ) { + font->atlas = d3d11_texture_create( + font->d3d11, + (UINT8*)font->bitmap, + font->bitmap_width, + font->bitmap_height + ); +} + +void d3d11_font_init( D3D11_FONT* font ) { + FT_Library libft; + + // invalid font size. + if( font->size < 2 ) { + return; + } + + // better to init every time because thread safety. it takes a miniscule amt of time + // comparing to parsing fonts anyway. + FT_Init_FreeType( &libft ); + U32 err; + if( !font->font_data ) { + char buf[256]; + sprintf( buf, "C:\\Windows\\Fonts\\%s", font->name ); + err = FT_New_Face( libft, buf, 0, &font->face ); + } + else + err = FT_New_Memory_Face( libft, font->font_data, font->font_data_size, 0, &font->face ); + + if( err ) { +#if RENDER_DEBUG + printf( "d3d11_font_init(%s) : failed to load font: %x\n", font->name, err ); +#endif + return; + } + + err = FT_Set_Pixel_Sizes( font->face, 0, font->size ); + if( err ) { +#if RENDER_DEBUG + printf( "d3d11_font_init(%s) : failed to set font size: %x\n", font->name, err ); +#endif + return; + } + + d3d11_font_create_bitmap( font ); + d3d11_font_create_atlas( font ); + + FT_Done_Face( font->face ); + FT_Done_FreeType( libft ); +} + +void d3d11_font_destroy( D3D11_FONT* font ) { + for( U32 c = 0; c < 0xFFFF; ++c ) { + if( font->glyphs[c] ) { + free( font->glyphs[c] ); + } + } + + d3d11_texture_destroy( font->d3d11, font->atlas ); + free( font->bitmap ); + free( font ); +} + +void +d3d11_font_calc_vertices_uvs(D3D11_FONT *font, DXVEC2 origin, wchar_t const *text, D3D11_VERTEX *vertices, FCLR col) +{ + U32 len = 0; for( ; text[len] != '\0'; len++ ); + + F32 cur_x = origin.x, cur_y = origin.y - font->char_height / 2 + 3; + for( U32 i = 0; i < len; ++i ) { + D3D11_VERTEX* v = &vertices[i * 6]; + + if( text[i] == '\n' || text[i] == ' ' ) { + D3D11_VERTEX v0; + memset( &v0, 0, sizeof(D3D11_VERTEX) ); + + v0.x = cur_y; + v0.y = cur_y; + + v[0] = v[1] = v[2] = v[3] = v[4] = v[5] = v0; + if( text[i] == '\n' ) { + cur_x = origin.x; + cur_y += (float)font->char_height; + } + else { + cur_x += font->blank_spacing > 0 ? (float)font->blank_spacing : (float)font->char_width / 2; + } + continue; + } + + U32 c = text[i]; + if( c >= 0xffff ) + c = '?'; + + FONT_GLYPH* glyph = font->glyphs[c]; + if( !glyph ) { + if( font->glyphs['?'] ) + glyph = font->glyphs['?']; + else + continue; + } + + F32 final_y = ceilf(cur_y + glyph->advance_y); + F32 final_x = ceilf(cur_x + glyph->bearing_x); + + v[0].x = final_x; v[0].y = final_y; + v[1].x = final_x + glyph->width; v[1].y = final_y; + v[2].x = final_x; v[2].y = ceilf(final_y + glyph->height); + v[3].x = final_x + glyph->width; v[3].y = ceilf(final_y + glyph->height); + v[4].x = final_x; v[4].y = ceilf(final_y + glyph->height); + v[5].x = final_x + glyph->width; v[5].y = final_y; + + v[0].uv = { glyph->offset_x / (float)font->bitmap_width, glyph->offset_y / (float)font->bitmap_height }; + v[1].uv = { (glyph->offset_x + glyph->width) / (float)font->bitmap_width, glyph->offset_y / (float)font->bitmap_height }; + v[2].uv = { glyph->offset_x / (float)font->bitmap_width, (glyph->offset_y + glyph->height) / (float)font->bitmap_height }; + v[3].uv = { (glyph->offset_x + glyph->width) / (float)font->bitmap_width, (glyph->offset_y + glyph->height) / (float)font->bitmap_height }; + v[4].uv = { glyph->offset_x / (float)font->bitmap_width, (glyph->offset_y + glyph->height) / (float)font->bitmap_height }; + v[5].uv = { (glyph->offset_x + glyph->width) / (float)font->bitmap_width, glyph->offset_y / (float)font->bitmap_height }; + + v[0].col = v[1].col = v[2].col = v[3].col = v[4].col = v[5].col = col; + + cur_x += glyph->advance_x; + } +} + +void +d3d11_font_drawW(D3D11_FONT *font, DXVEC2 pos, wchar_t const *text, FCLR col) +{ + if( !font || !font->bitmap || !font->atlas ) + return; + + U32 stride = sizeof(D3D11_VERTEX); + U32 offset = 0; + U32 len; + for( len = 0; !!text[len]; ++len ); + + D3D11_VERTEX* vertices = (D3D11_VERTEX*)malloc( sizeof(D3D11_VERTEX) * len * 6 ); + d3d11_font_calc_vertices_uvs( font, pos, text, vertices, col ); + + D3D11_RENDERDATA* data = font->d3d11; + data->context->IASetInputLayout( data->input_layout ); + + data->context->VSSetShader( data->vertex_shader, nullptr, 0 ); + data->context->PSSetShader( data->pixel_shader_textured, nullptr, 0 ); + data->context->PSSetShaderResources( 0, 1, &font->atlas->srv ); + + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if( !!data->context->Map( data->vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource ) ) { + return; + } + + memcpy( mapped_resource.pData, vertices, sizeof(D3D11_VERTEX) * len * 6 ); + data->context->Unmap( data->vertex_buffer, 0 ); + + data->context->IASetVertexBuffers( 0, 1, &data->vertex_buffer, &stride, &offset ); + data->context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); + + data->context->Draw( len * 6, 0 ); + free( vertices ); +} + +void +d3d11_font_drawA(D3D11_FONT *font, DXVEC2 pos, char const *text, FCLR col) +{ + if( !font || !font->bitmap || !font->atlas ) + return; + + UINT len = (UINT)strlen( text ); + wchar_t* wide = (wchar_t*)malloc( (len + 1) * sizeof(wchar_t) ); + memset( wide, 0, (len + 1) * sizeof(wchar_t) ); + + for( UINT i = 0; i < len; ++i ) { + wide[i] = (wchar_t)text[i]; + } + + d3d11_font_drawW( font, pos, wide, col ); + free( wide ); +} + +void +d3d11_font_get_extentW(D3D11_FONT *font, wchar_t const *text, DXVEC2 *extent) +{ + if( !font || !font->bitmap || !font->atlas ) + return; + + F32 cur_x = 0, cur_y = -(float)font->char_height / 2 + (float)font->char_height - 3; + UINT len; for( len = 0; !!text[len]; ++len ); + + if( !len ) { + extent->x = 0; + extent->y = 0; + return; + } + + for( UINT i = 0; i < len; ++i ) { + if( text[i] == '\n' || text[i] == ' ' ) { + if( text[i] == '\n' ) { + cur_x = 0; + cur_y += (float)font->char_height - 3; + } + else { + cur_x += font->blank_spacing > 0 ? (float)font->blank_spacing : (float)font->char_width / 2; + } + continue; + } + + U32 c = text[i]; + FONT_GLYPH* glyph = font->glyphs[c]; + if( !glyph ) { + if( font->glyphs['?'] ) + glyph = font->glyphs['?']; + else + continue; + } + + cur_x += glyph->advance_x; + } + + extent->x = cur_x; + extent->y = cur_y; +} + +void +d3d11_font_get_extentA(D3D11_FONT *font, char const *text, DXVEC2 *extent) +{ + if( !font || !font->bitmap || !font->atlas ) + return; + + UINT len = (UINT)strlen( text ); + wchar_t* wide = (wchar_t*)malloc( (len + 1) * sizeof(wchar_t) ); + memset( wide, 0, (len + 1) * sizeof(wchar_t) ); + + for( UINT i = 0; i < len; ++i ) { + wide[i] = (wchar_t)text[i]; + } + + d3d11_font_get_extentW( font, wide, extent ); + free( wide ); +} -- cgit v1.2.3