From 819cf3e4e8abb5ad41d8830155fc20bd833b21e8 Mon Sep 17 00:00:00 2001 From: navewindre Date: Wed, 17 Jul 2024 08:36:51 +0200 Subject: render wip --- dwm/dwm.vcxproj | 17 +- dwm/dwm.vcxproj.filters | 15 + dwm/dxhk.cpp | 67 +++ dwm/dxhk.h | 41 ++ dwm/grender.cpp | 1288 +++++++++++++++++++++++++++++++++++++++++++++++ dwm/grender.h | 155 ++++++ dwm/inter.h | 46 ++ dwm/source.cpp | 8 +- 8 files changed, 1632 insertions(+), 5 deletions(-) create mode 100644 dwm/dxhk.cpp create mode 100644 dwm/dxhk.h create mode 100644 dwm/grender.cpp create mode 100644 dwm/grender.h create mode 100644 dwm/inter.h (limited to 'dwm') diff --git a/dwm/dwm.vcxproj b/dwm/dwm.vcxproj index bab2871..f77abef 100644 --- a/dwm/dwm.vcxproj +++ b/dwm/dwm.vcxproj @@ -43,14 +43,14 @@ DynamicLibrary true v142 - Unicode + MultiByte DynamicLibrary false v142 true - Unicode + MultiByte @@ -81,12 +81,16 @@ $(SolutionDir)\bin\ ..\intermediate\X64\$(Configuration)\ dwmhook + C:\Users\aurelia\Documents\heavenhack-cs2\freetype;$(IncludePath) + C:\Users\aurelia\Documents\heavenhack-cs2\freetype;$(LibraryPath) false $(SolutionDir)\bin\ ..\intermediate\X64\$(Configuration)\ dwmhook + C:\Users\aurelia\Documents\heavenhack-cs2\freetype;$(IncludePath) + C:\Users\aurelia\Documents\heavenhack-cs2\freetype;$(LibraryPath) @@ -120,7 +124,7 @@ Level3 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions);X64 + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);X64;_CRT_SECURE_NO_WARNINGS true stdcpp17 @@ -135,7 +139,7 @@ true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions);X64 + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);X64;_CRT_SECURE_NO_WARNINGS true stdcpp17 @@ -147,9 +151,14 @@ + + + + + diff --git a/dwm/dwm.vcxproj.filters b/dwm/dwm.vcxproj.filters index 37e74bf..13c54bb 100644 --- a/dwm/dwm.vcxproj.filters +++ b/dwm/dwm.vcxproj.filters @@ -18,6 +18,12 @@ Source Files + + Source Files + + + Source Files + @@ -26,5 +32,14 @@ Source Files + + Source Files + + + Source Files + + + Source Files + \ No newline at end of file diff --git a/dwm/dxhk.cpp b/dwm/dxhk.cpp new file mode 100644 index 0000000..4de113f --- /dev/null +++ b/dwm/dxhk.cpp @@ -0,0 +1,67 @@ +#include "dxhk.h" +#include "inter.h" + +HOOK_DATA* hk; +D3D11_RENDERDATA* dx11; + +U64 __fastcall hk_multiplane_draw( + void* dxdev, + IDXGISwapChain* swpchain, + U32 a3, + U32 a4, + U32 a5, + U64 a6, + U64 a7, + U32 a8 +) { + static decltype( &hk_multiplane_draw ) original = (decltype( &hk_multiplane_draw ))hk->multiplane_o; + + U64 ret = original( dxdev, swpchain, a3, a4, a5, a6, a7, a8 ); + return ret; +} + +U64 __fastcall hk_present( + void* dxdev, + IDXGISwapChain* swpchain, + U32 a3, + U32 a4, + const RECT* rect, + U64 a6, + void* a7, + U32 a8, + void* rsrc, + U32 a10 +) { + static decltype( &hk_present ) original = (decltype( &hk_present ))hk->present_o; + + U64 ret = original( dxdev, swpchain, a3, a4, rect, a6, a7, a8, rsrc, a10 ); + return ret; +} + +U64 __stdcall hk_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { + U64 ret = CallWindowProcA( (WNDPROC)hk->wndproc_o, hwnd, msg, wparam, lparam ); + + + return ret; +} + +HOOK_DATA* dxhk_init() { + HOOK_DATA* hkd = new HOOK_DATA; + + U64 dxdev = u_find_pattern( (U64)GetModuleHandleA( "d2d1.dll" ), "48 8D 05 ? ? ? ? 33 ED 48 8D 71 08" ); + if( !dxdev ) { + delete hkd; + return 0; + } + + dxdev = dxdev + *(U64*)( dxdev + 3 ) + 7; + VMT vmt( *(U64*)dxdev ); + + hkd->multiplane_o = vmt.set( 7, (U64)&hk_multiplane_draw ); + hkd->present_o = vmt.set( 6, (U64)&hk_present ); + hkd->wndproc_o = SetWindowLongPtrA( FindWindowA( "Progman", "Program Manager" ), GWLP_WNDPROC, (LONG_PTR)&hk_wndproc ); + + dx11 = d3d11_init(); + + return hkd; +} \ No newline at end of file diff --git a/dwm/dxhk.h b/dwm/dxhk.h new file mode 100644 index 0000000..cd37c49 --- /dev/null +++ b/dwm/dxhk.h @@ -0,0 +1,41 @@ +#pragma once +#include "grender.h" + +struct HOOK_DATA { + U64 multiplane_o; + U64 present_o; + U64 wndproc_o; +}; + +U64 __fastcall hk_multiplane_draw( + void* dxdev, + IDXGISwapChain* swpchain, + U32 a3, + U32 a4, + U32 a5, + U64 a6, + U64 a7, + U32 a8 +); + +// 10 args is so microsoft +U64 __fastcall hk_present( + void* dxdev, + IDXGISwapChain* swpchain, + U32 a3, + U32 a4, + const RECT* rect, + U64 a6, + void* a7, + U32 a8, + void* rsrc, + U32 a10 +); + +U64 __stdcall hk_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ); + +extern HOOK_DATA* hk; +extern D3D11_RENDERDATA* dx11; + +HOOK_DATA* dxhk_init(); +void dxhk_destroy( HOOK_DATA* data ); \ No newline at end of file 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 ); +} diff --git a/dwm/grender.h b/dwm/grender.h new file mode 100644 index 0000000..bd65fba --- /dev/null +++ b/dwm/grender.h @@ -0,0 +1,155 @@ +#pragma once + +#include "../src/color.h" + +#include +#include +#include + +#include +#include FT_FREETYPE_H + +#ifdef _WIN64 +#pragma comment(lib, "freetype64.lib") +#else +#pragma comment(lib, "freetype32.lib") +#endif + +enum rounded_rect_corners { + e_top_left = 0b0001, + e_top_right = 0b0010, + e_bottom_left = 0b0100, + e_bottom_right = 0b1000, +}; + +struct DXVEC2 { + F32 x, y; +}; + +using DXMAT4X4 = float[4][4]; + +struct D3D11_VERTEX { + F32 x, y; + DXVEC2 uv; + FCLR col; +}; + +struct D3D11_TEXTURE { + ID3D11Texture2D* tex2d; + ID3D11ShaderResourceView* srv; + I32 w, h; + UINT8* rgba; +}; + +struct FONT_GLYPH { + F32 offset_x; + F32 offset_y; + F32 width; + F32 height; + F32 advance_x; + F32 advance_y; + F32 bearing_x; +}; + +struct D3D11_FONT { + struct D3D11_RENDERDATA* d3d11; + U32 size; + FT_Face face; + + const char* name; + UINT8* font_data; + U32 font_data_size; + + D3D11_TEXTURE* atlas; + + U32* bitmap; + U32 bitmap_width; + U32 bitmap_height; + U32 char_width; + U32 char_height; + U32 blank_spacing; + + // YEAH BABY + FONT_GLYPH* glyphs[0xFFFF]; +}; + +struct D3D11_RENDERDATA { + ID3D11Device* device; + ID3D11DeviceContext* context; + IDXGISwapChain* swapchain; + + ID3D11RenderTargetView* render_target_view; + ID3D11InputLayout* input_layout; + ID3D11BlendState* blend_state; + ID3D11RasterizerState* rasterizer_state; + ID3D11DepthStencilState* depth_stencil_state; + + ID3D11VertexShader* vertex_shader; + ID3D11PixelShader* pixel_shader; + ID3D11PixelShader* pixel_shader_textured; + ID3DBlob* vs_blob; + ID3DBlob* ps_blob; + ID3DBlob* ps_blob_textured; + + ID3D11Texture2D* back_buffer; + ID3D11Buffer* vertex_buffer; + ID3D11Buffer* constant_buffer; + + F32 display[2]; + + RECT clip; + + std::vector textures; + std::vector fonts; +}; + + + +extern D3D11_RENDERDATA* d3d11_init(); +extern void d3d11_on_present( D3D11_RENDERDATA* data, void* swapchain ); +extern void d3d11_on_swapchain_lost( D3D11_RENDERDATA* data ); + +extern bool d3d11_init_shaders( D3D11_RENDERDATA* data ); +extern bool d3d11_init_resources( D3D11_RENDERDATA* data ); +extern void d3d11_destroy_resources( D3D11_RENDERDATA* data ); + +extern D3D11_TEXTURE* d3d11_texture_create( D3D11_RENDERDATA* data, UINT8* rgba, I32 width, I32 height ); +extern void d3d11_texture_init( D3D11_RENDERDATA* data, D3D11_TEXTURE* tex ); +extern void d3d11_texture_destroy( D3D11_RENDERDATA* data, D3D11_TEXTURE* tex ); + +extern void d3d11_set_clip( D3D11_RENDERDATA* data, RECT* clip ); +extern void d3d11_get_clip( D3D11_RENDERDATA* data, RECT* clip ); + +extern void d3d11_line( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 pos2, FCLR col ); +extern void d3d11_rect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, FCLR col ); +extern void d3d11_frect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, FCLR col ); +extern void d3d11_textured_frect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, D3D11_TEXTURE* texture, FCLR col ); +extern void d3d11_gradient_frect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, FCLR tl, FCLR tr, FCLR bl, FCLR br ); +extern void d3d11_circle( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, FCLR col, I32 res = 48 ); +extern void d3d11_fcircle( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, FCLR col, I32 res = 48 ); +extern void d3d11_thick_circle( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius_in, F32 radius_out, FCLR col, I32 res = 48 ); +extern void d3d11_arc( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, F32 start_angle, F32 end_angle, FCLR col, I32 res = 48 ); +extern void d3d11_farc( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, F32 start_angle, F32 end_angle, FCLR col, I32 res = 48 ); +extern void d3d11_farc_2clr( D3D11_RENDERDATA* data, DXVEC2 pos, F32 radius, F32 start_angle, F32 end_angle, FCLR col1, FCLR col2, I32 res = 24 ); +extern void d3d11_rounded_rect( D3D11_RENDERDATA* data, DXVEC2 pos, DXVEC2 size, F32 radius, FCLR col, I32 flags ); + +extern D3D11_FONT* d3d11_font_create( + D3D11_RENDERDATA* data, + const char* font_name, + U32 font_size, + UINT8* font_data = 0, + U32 font_data_size = 0 +); +extern void d3d11_font_init( D3D11_FONT* font ); +extern void d3d11_font_destroy( D3D11_FONT* font ); +extern void d3d11_font_drawA( D3D11_FONT* font, DXVEC2 pos, const char* text, FCLR col ); +extern void d3d11_font_drawW( D3D11_FONT* font, DXVEC2 pos, const wchar_t* text, FCLR col ); +extern void d3d11_font_get_extentA( D3D11_FONT* font, const char* text, DXVEC2* extent ); +extern void d3d11_font_get_extentW( D3D11_FONT* font, const wchar_t* text, DXVEC2* extent ); + +inline void d3d11_font_get_extent( D3D11_FONT* font, const char* text, DXVEC2* extent ) { + return d3d11_font_get_extentA( font, text, extent ); +} +inline void d3d11_font_draw( D3D11_FONT* font, DXVEC2 pos, const char* text, FCLR col ) { + return d3d11_font_drawA( font, pos, text, col ); +} \ No newline at end of file diff --git a/dwm/inter.h b/dwm/inter.h new file mode 100644 index 0000000..d668eaa --- /dev/null +++ b/dwm/inter.h @@ -0,0 +1,46 @@ +#pragma once +#include "typedef.h" +#include "util.h" + +class VMT { + U64 ptr; + +public: + VMT( U64 ptr ) : ptr( ptr ) {} + + U64 get( U32 index ) { + return *(U64*)( ptr + index * sizeof( U64 ) ); + } + + U64 set( U32 index, U64 func ) { + U64 o = get( index ); + *(U64*)( ptr + index * sizeof( U64 ) ) = func; + + return o; + } +}; + +static U64 u_find_pattern( U64 module, const char* pattern, U64 start = 0 ) { + U32 len; + U8* sig_bytes = u_parse_signature( pattern, &len ); + + if( !sig_bytes || len <= 2 ) + return 0; + + IMAGE_DOS_HEADER dos_hdr; + IMAGE_NT_HEADERS64 nt_hdr; + U32 size; + + dos_hdr = *(IMAGE_DOS_HEADER*)module; + nt_hdr = *(IMAGE_NT_HEADERS64*)( module + dos_hdr.e_lfanew ); + size = nt_hdr.OptionalHeader.SizeOfImage; + + for( U64 off = start - module; off < size; ++off ) { + if( u_binary_match( (U8*)( module + off ), sig_bytes, len ) ) { + free( sig_bytes ); + return module + off; + } + } + + return 0; +} \ No newline at end of file diff --git a/dwm/source.cpp b/dwm/source.cpp index c8d4951..10e161c 100644 --- a/dwm/source.cpp +++ b/dwm/source.cpp @@ -1,12 +1,18 @@ #include -#include "typedef.h" +#include "dxhk.h" +void init( void* inst ) { + hk = dxhk_init(); +} int __stdcall DllMain( void* hinst, U32 reason, void* reserved ) { // coca cola yayo bought me this if( reason == DLL_PROCESS_ATTACH ) { // do a fucking EPIC here + DWORD tid; + HANDLE t = CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)init, hinst, 0, &tid ); + CloseHandle( t ); return 1; } } \ No newline at end of file -- cgit v1.2.3