diff Engine/Graphics/RenderD3D11.cpp @ 2524:c7264ab7132f

Main menu rendered using d3d11
author a.parshin
date Fri, 10 Oct 2014 17:42:05 +0300
parents c532d5242055
children 4cc81f981afb
line wrap: on
line diff
--- a/Engine/Graphics/RenderD3D11.cpp	Thu Oct 09 23:33:36 2014 +0300
+++ b/Engine/Graphics/RenderD3D11.cpp	Fri Oct 10 17:42:05 2014 +0300
@@ -6,6 +6,7 @@
 #include "../mm7_data.h"
 #include "Texture.h"
 #include "../Log.h"
+#include "Sprites.h"
 
 #define ErrorD3D(x)\
 {\
@@ -28,7 +29,6 @@
 
 void RenderD3D11::ClearBlack() {__debugbreak();}
 void RenderD3D11::SaveWinnersCertificate(const char *a1) {__debugbreak();}
-void RenderD3D11::Present() {__debugbreak();}
 void RenderD3D11::_49FD3A_fullscreen() {__debugbreak();}
 bool RenderD3D11::InitializeFullscreen() {__debugbreak(); return 0;}
 void RenderD3D11::CreateZBuffer() {__debugbreak();}
@@ -59,16 +59,10 @@
 void RenderD3D11::TransformBillboardsAndSetPalettesODM() {__debugbreak();}
 void RenderD3D11::DrawBillboardList_BLV() {__debugbreak();}
 void RenderD3D11::DrawProjectile(float srcX, float srcY, float a3, float a4, float dstX, float dstY, float a7, float a8, IDirect3DTexture2 *a9) {__debugbreak();}
-bool RenderD3D11::LoadTexture(const char *pName, unsigned int bMipMaps, IDirectDrawSurface4 **pOutSurface, IDirect3DTexture2 **pOutTexture) {__debugbreak(); return 0;}
-bool RenderD3D11::MoveSpriteToDevice(Sprite *pSprite) {__debugbreak(); return 0;}
 void RenderD3D11::ScreenFade(unsigned int color, float t) {__debugbreak();}
-void RenderD3D11::SetTextureClipRect(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW) {__debugbreak();}
-void RenderD3D11::ResetTextureClipRect() {__debugbreak();}
 void RenderD3D11::CreditsTextureScroll(unsigned int pX, unsigned int pY, int move_X, int move_Y, RGBTexture *pTexture) {__debugbreak();}
-void RenderD3D11::DrawTextureIndexed(unsigned int uX, unsigned int uY, struct Texture *a4) {__debugbreak();}
 void RenderD3D11::ZBuffer_Fill_2(signed int a2, signed int a3, struct Texture *pTexture, int a5) {__debugbreak();}
 void RenderD3D11::DrawMaskToZBuffer(signed int uOutX, unsigned int uOutY, struct Texture *pTexture, int zVal) {__debugbreak();}
-void RenderD3D11::DrawTextureTransparent(unsigned int uX, unsigned int uY, struct Texture *pTexture) {__debugbreak();}
 void RenderD3D11::DrawAura(unsigned int a2, unsigned int a3, struct Texture *a4, struct Texture *a5, int a6, int a7, int a8) {__debugbreak();}
 void RenderD3D11::_4A65CC(unsigned int x, unsigned int y, struct Texture *a4, struct Texture *a5, int a6, int a7, int a8) {__debugbreak();}
 void RenderD3D11::DrawTransparentRedShade(unsigned int a2, unsigned int a3, struct Texture *a4) {__debugbreak();}
@@ -77,7 +71,6 @@
 void RenderD3D11::DrawMasked(signed int a2, signed int a3, struct Texture *pTexture, unsigned __int16 mask) {__debugbreak();}
 void RenderD3D11::GetLeather(unsigned int a2, unsigned int a3, struct Texture *a4, __int16 height) {__debugbreak();}
 void RenderD3D11::DrawTextPalette(int x, int y, unsigned char* font_pixels, int a5, unsigned int uFontHeight, unsigned __int16 *pPalette, int a8) {__debugbreak();}
-void RenderD3D11::DrawText(signed int uOutX, signed int uOutY, unsigned __int8 *pFontPixels, unsigned int uCharWidth, unsigned int uCharHeight, unsigned __int16 *pFontPalette, unsigned __int16 uFaceColor, unsigned __int16 uShadowColor) {__debugbreak();}
 void RenderD3D11::FillRectFast(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, unsigned int uColor16) {__debugbreak();}
 void RenderD3D11::_4A6DF5(unsigned __int16 *pBitmap, unsigned int uBitmapPitch, struct Vec2_int_ *pBitmapXY, void *pTarget, unsigned int uTargetPitch, Vec4_int_ *a7) {__debugbreak();}
 void RenderD3D11::DrawTranslucent(unsigned int a2, unsigned int a3, struct Texture *a4) {__debugbreak();}
@@ -90,7 +83,7 @@
 void RenderD3D11::DrawSpriteObjects_ODM() {__debugbreak();}
 void RenderD3D11::RenderTerrainD3D() {__debugbreak();}
 void RenderD3D11::ChangeBetweenWinFullscreenModes() {__debugbreak();}
-bool RenderD3D11::AreRenderSurfacesOk() {__debugbreak(); return 0;}
+bool RenderD3D11::AreRenderSurfacesOk() {return true;}
 void RenderD3D11::SaveScreenshot(const char *pFilename, unsigned int width, unsigned int height) {__debugbreak();}
 void RenderD3D11::PackScreenshot(unsigned int width, unsigned int height, void *out_data, unsigned int data_size, unsigned int *screenshot_size) {__debugbreak();}
 void RenderD3D11::SavePCXScreenshot() {__debugbreak();}
@@ -115,6 +108,22 @@
 
 
 
+void RenderD3D11::SetUIClipRect(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW)
+{
+  ui_clip_rect.left = uX;
+  ui_clip_rect.top = uY;
+  ui_clip_rect.right = uZ;
+  ui_clip_rect.bottom = uW;
+}
+
+void RenderD3D11::ResetUIClipRect()
+{
+  ui_clip_rect.left = 0;
+  ui_clip_rect.top = 0;
+  ui_clip_rect.right = window->GetWidth();
+  ui_clip_rect.bottom = window->GetHeight();
+}
+
 void RenderD3D11::PresentBlackScreen()
 {
   ClearTarget(0xFF000000);
@@ -137,6 +146,19 @@
 }
 
 
+
+void RenderD3D11::DrawTextureIndexed(unsigned int uX, unsigned int uY, struct Texture *a4)
+{
+  PrepareTextureIndexed(a4);
+  DrawTexture((float)uX / window->GetWidth(), (float)uY / window->GetHeight(), a4->uTextureWidth, a4->uTextureHeight, a4->d3d11_srv, ui_blend_solid);
+}
+
+void RenderD3D11::DrawTextureIndexedAlpha(unsigned int uX, unsigned int uY, struct Texture *a4) 
+{
+  PrepareTextureIndexed(a4);
+  DrawTexture((float)uX / window->GetWidth(), (float)uY / window->GetHeight(), a4->uTextureWidth, a4->uTextureHeight, a4->d3d11_srv, ui_blend_alpha);
+}
+
 void RenderD3D11::DrawTextureRGB(unsigned int uOutX, unsigned int uOutY, RGBTexture *a4)
 {
   __debugbreak();
@@ -149,60 +171,32 @@
 
 void RenderD3D11::DrawTextureNew(float u, float v, RGBTexture *tex)
 {
-  if (!tex->d3d11_srv)
-  {
-    auto desc = tex->d3d11_desc = new D3D11_TEXTURE2D_DESC;
-    desc->Width = tex->uWidth;
-    desc->Height = tex->uHeight;
-    desc->ArraySize = 1;
-    desc->MipLevels = 1;
-    desc->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-    desc->SampleDesc.Count = 1;
-    desc->SampleDesc.Quality = 0;
-    desc->Usage = D3D11_USAGE_DEFAULT;
-    desc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
-    desc->CPUAccessFlags = 0;
-    desc->MiscFlags = 0;
-    
-    ID3D11Texture2D *vram_texture = nullptr;
-    ErrD3D(d3dd->CreateTexture2D(desc, nullptr, &vram_texture));
+  PrepareTexture(tex);
+  DrawTexture(u, v, tex->uWidth, tex->uHeight, tex->d3d11_srv, ui_blend_solid);
+}
 
-    D3D11_TEXTURE2D_DESC ram_desc;
-    memcpy(&ram_desc, desc, sizeof(ram_desc));
-    ram_desc.Usage = D3D11_USAGE_STAGING;
-    ram_desc.BindFlags = 0;
-    ram_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
-    
-    ID3D11Texture2D *ram_texture = nullptr;
-    ErrD3D(d3dd->CreateTexture2D(&ram_desc, nullptr, &ram_texture));
+void RenderD3D11::DrawText(signed int uX, signed int uY, unsigned __int8 *pFontPixels, unsigned int uCharWidth, unsigned int uCharHeight, unsigned __int16 *pFontPalette, unsigned __int16 uFaceColor, unsigned __int16 uShadowColor)
+{
+  auto srv = PrepareFontTexture(pFontPixels, uCharWidth, uCharHeight, pFontPalette, uFaceColor, uShadowColor);
+  {
+    DrawTexture((float)uX / window->GetWidth(), (float)uY / window->GetHeight(), uCharWidth, uCharHeight, srv, ui_blend_alpha);
+  }
+  srv->Release();
+}
 
-    D3D11_MAPPED_SUBRESOURCE map;
-    ErrD3D(d3dc->Map(ram_texture, 0, D3D11_MAP_WRITE, 0, &map));
-    for (unsigned int y = 0; y < desc->Height; ++y)
-      for (unsigned int x = 0; x < desc->Width; ++x)
-      {
-        auto src = tex->pPixels + y * tex->uWidth + x;
-        auto dst = (unsigned int *)((char *)map.pData + y * map.RowPitch) + x;
 
-        extern unsigned __int32 Color32_SwapRedBlue(unsigned __int16 color16);
-        *dst = 0xFF000000 | Color32_SwapRedBlue(*src);
-      }
-
-    d3dc->Unmap(ram_texture, 0);
-    d3dc->CopyResource(vram_texture, ram_texture);
-    ram_texture->Release();
-    
-    ErrD3D(d3dd->CreateShaderResourceView(vram_texture, nullptr, (ID3D11ShaderResourceView **)&tex->d3d11_srv));
-    vram_texture->Release();
-  }
-
+void RenderD3D11::DrawTexture(float u, float v, int texture_width, int texture_height, ID3D11ShaderResourceView *srv, ID3D11BlendState *blend)
+{
+  bool clipping = false;
+  if (ui_clip_rect.left != 0 || ui_clip_rect.top != 0
+      || ui_clip_rect.right != window->GetWidth()  || ui_clip_rect.bottom != window->GetHeight())
+      clipping = true;
 
   float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
   d3dc->OMSetRenderTargets(1, &primary_srv, depth_srv);
-  d3dc->OMSetBlendState(ui_blend, blendFactor, 0xFFFFFFFF);
+  d3dc->OMSetBlendState(blend, blendFactor, 0xFFFFFFFF);
   d3dc->OMSetDepthStencilState(ui_depthstencil, 1);
 
-
   {
     struct cb_fast
     {
@@ -219,8 +213,8 @@
       {
         data.pos_x = u;
         data.pos_y = v;
-        data.size_x = (float)tex->uWidth / window->GetWidth();
-        data.size_y = (float)tex->uHeight / window->GetHeight();
+        data.size_x = (float)texture_width / window->GetWidth();
+        data.size_y = (float)texture_height / window->GetHeight();
       }
       memcpy(map.pData, &data, sizeof(data));
     }
@@ -232,7 +226,14 @@
 
   d3dc->PSSetShader(ui_ps, nullptr, 0);
   d3dc->PSSetConstantBuffers(0, 1, &ui_cb_fast);
-  d3dc->PSSetShaderResources(0, 1, &tex->d3d11_srv);
+  d3dc->PSSetShaderResources(0, 1, &srv);
+
+  if (clipping)
+  {
+    d3dc->RSSetState(ui_rasterizer);
+    d3dc->RSSetScissorRects(1, &ui_clip_rect);
+  }
+  //d3dc->RSSetViewports(1, &ui_viewport);
 
   uint uOffset = 0;
   uint uStride = 4 * sizeof(float);
@@ -242,6 +243,17 @@
 
   d3dc->Draw(6, 0);
 
+  if (clipping)
+  {
+    d3dc->RSSetState(default_rasterizer);
+    //d3dc->RSSetScissorRects(0, nullptr);
+  }
+}
+
+
+
+void RenderD3D11::Present()
+{
   pSwapChain->Present(0, 0);
 }
 
@@ -313,7 +325,10 @@
 
   auto d3d_lib = LoadLibraryW(L"d3d11.dll");
   if (!d3d_lib)
-    return Error("d3d11.dll is missing"), false;
+  {
+    Error("d3d11.dll is missing");
+    return false;
+  }
 
 
   DXGI_SWAP_CHAIN_DESC swapChainDesc;
@@ -416,6 +431,24 @@
   ErrorD3D(d3dd->CreateRasterizerState(&default_rasterizer_desc, &default_rasterizer));
   d3dc->RSSetState(default_rasterizer);
 
+
+
+  D3D11_RASTERIZER_DESC ui_rasterizer_desc;
+  memset(&ui_rasterizer_desc, 0, sizeof(ui_rasterizer_desc));
+  ui_rasterizer_desc.FillMode = D3D11_FILL_SOLID;
+  ui_rasterizer_desc.CullMode = D3D11_CULL_NONE;
+  //ui_rasterizer_desc.FrontCounterClockwise = false;
+  //ui_rasterizer_desc.DepthBias = 0;
+  //ui_rasterizer_desc.DepthBiasClamp = 0.0f;
+  //ui_rasterizer_desc.SlopeScaledDepthBias = 0.0f;
+  //ui_rasterizer_desc.DepthClipEnable = true;
+  ui_rasterizer_desc.ScissorEnable = true;
+  //ui_rasterizer_desc.MultisampleEnable = false;
+  //ui_rasterizer_desc.AntialiasedLineEnable = false;
+
+  ErrorD3D(d3dd->CreateRasterizerState(&ui_rasterizer_desc, &ui_rasterizer));
+
+
   default_depthstencil = nullptr;
   default_blend = nullptr;
 
@@ -423,21 +456,23 @@
 
   D3D11_VIEWPORT viewport;
   memset(&viewport, 0, sizeof(viewport));
-  viewport.TopLeftX = game_viewport_x;
-  viewport.TopLeftY = game_viewport_y;
+  viewport.TopLeftX = 0;
+  viewport.TopLeftY = 0;
   viewport.Width    = window->GetWidth();
   viewport.Height   = window->GetHeight();
   viewport.MinDepth = 0;
   viewport.MaxDepth = 1;
   d3dc->RSSetViewports(1, &viewport);
 
+  ResetUIClipRect();
+
 
   D3D11_INPUT_ELEMENT_DESC layout_desc[] =
   {
     { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
     //{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,       0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },  
   };
-  CompileShader(d3dd, L"data/shaders/UI.shader", layout_desc, 1/*2*/, &ui_vs, &ui_ps, &ui_layout);
+  CompileShader(d3dd, L"data/shaders/UI.hlsl", layout_desc, 1/*2*/, &ui_vs, &ui_ps, &ui_layout);
 
       {
         uint uVertexSize = 4 * sizeof(float);
@@ -508,18 +543,123 @@
   ErrorD3D(d3dd->CreateDepthStencilState(&ui_depthstencil_desc, &ui_depthstencil));
 
 
-  D3D11_BLEND_DESC ui_blend_desc;
-  memset(&ui_blend_desc, 0, sizeof(ui_blend_desc));
-  ui_blend_desc.RenderTarget[0].BlendEnable = false;
-  ui_blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
-  ErrD3D(d3dd->CreateBlendState(&ui_blend_desc, &ui_blend));
+  D3D11_BLEND_DESC ui_blend_solid_desc;
+  memset(&ui_blend_solid_desc, 0, sizeof(ui_blend_solid_desc));
+  ui_blend_solid_desc.RenderTarget[0].BlendEnable = false;
+  ui_blend_solid_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+  ErrorD3D(d3dd->CreateBlendState(&ui_blend_solid_desc, &ui_blend_solid));
 
-  return true;
+  D3D11_BLEND_DESC ui_blend_alpha_desc;
+  memset(&ui_blend_alpha_desc, 0, sizeof(ui_blend_alpha_desc));
+  ui_blend_alpha_desc.RenderTarget[0].BlendEnable = true;
+  ui_blend_alpha_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+  ui_blend_alpha_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+  ui_blend_alpha_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
+  ui_blend_alpha_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+  ui_blend_alpha_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+  ui_blend_alpha_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
+  ui_blend_alpha_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
+  ErrorD3D(d3dd->CreateBlendState(&ui_blend_alpha_desc, &ui_blend_alpha));
+
+
+  return pD3DBitmaps.Load(L"data\\d3dbitmap.hwl") && pD3DSprites.Load(L"data\\d3dsprite.hwl");
 }
 
 
 
 
+bool RenderD3D11::MoveSpriteToDevice(Sprite *pSprite)
+{
+  HWLTexture *sprite_texture; // eax@1
+  unsigned __int16 *v9; // edx@5
+  LPVOID v10; // eax@5
+  DDSURFACEDESC2 Dst; // [sp+Ch] [bp-7Ch]@4
+
+  sprite_texture = pD3DSprites.LoadTexture(pSprite->pName, pSprite->uPaletteID);
+  if ( sprite_texture )
+  {
+    pSprite->uAreaX = sprite_texture->uAreaX;
+    pSprite->uAreaY = sprite_texture->uAreaY;
+    pSprite->uBufferWidth = sprite_texture->uBufferWidth;
+    pSprite->uBufferHeight = sprite_texture->uBufferHeight;
+    pSprite->uAreaWidth = sprite_texture->uAreaWidth;
+    pSprite->uAreaHeight = sprite_texture->uAreaHeigth;
+
+    {
+      D3D11_TEXTURE2D_DESC desc;
+      desc.Width = sprite_texture->uWidth;
+      desc.Height = sprite_texture->uHeight;
+      desc.ArraySize = 1;
+      desc.MipLevels = 1;
+      desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+      desc.SampleDesc.Count = 1;
+      desc.SampleDesc.Quality = 0;
+      desc.Usage = D3D11_USAGE_DEFAULT;
+      desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+      desc.CPUAccessFlags = 0;
+      desc.MiscFlags = 0;
+    
+      ID3D11Texture2D *vram_texture = nullptr;
+      ErrorD3D(d3dd->CreateTexture2D(&desc, nullptr, &vram_texture));
+
+      D3D11_TEXTURE2D_DESC ram_desc;
+      memcpy(&ram_desc, &desc, sizeof(ram_desc));
+      ram_desc.Usage = D3D11_USAGE_STAGING;
+      ram_desc.BindFlags = 0;
+      ram_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+      ID3D11Texture2D *ram_texture = nullptr;
+      ErrorD3D(d3dd->CreateTexture2D(&ram_desc, nullptr, &ram_texture));
+
+      D3D11_MAPPED_SUBRESOURCE map;
+      ErrorD3D(d3dc->Map(ram_texture, 0, D3D11_MAP_WRITE, 0, &map));
+      for (unsigned int y = 0; y < desc.Height; ++y)
+        for (unsigned int x = 0; x < desc.Width; ++x)
+        {
+          auto src = sprite_texture->pPixels + y * desc.Width + x;
+          auto dst = (unsigned int *)((char *)map.pData + y * map.RowPitch) + x;
+
+          extern unsigned __int32 Color32_SwapRedBlue(unsigned __int16 color16);
+          *dst = 0xFF000000 | Color32_SwapRedBlue(*src);
+        }
+
+
+      d3dc->Unmap(ram_texture, 0);
+      d3dc->CopyResource(vram_texture, ram_texture);
+      ram_texture->Release();
+    
+      ID3D11ShaderResourceView *srv = nullptr;
+      ErrorD3D(d3dd->CreateShaderResourceView(vram_texture, nullptr, &srv));
+      vram_texture->Release();
+
+      pSprite->d3d11_srv = srv;
+    }
+    /*if (!pRenderD3D->CreateTexture(sprite_texture->uWidth, sprite_texture->uHeight, &pSprite->pTextureSurface, &pSprite->pTexture, 1u, 0, uMinDeviceTextureDim))
+      Error("HiScreen16::LoadTexture - D3Drend->CreateTexture() failed: %x", 0);
+    memset(&Dst, 0, sizeof(DDSURFACEDESC2));
+    Dst.dwSize = 124;
+    if ( LockSurface_DDraw4((IDirectDrawSurface4 *)pSprite->pTextureSurface, &Dst, DDLOCK_WAIT | DDLOCK_WRITEONLY) )
+    {
+      v9 = sprite_texture->pPixels;
+      v10 = Dst.lpSurface;
+      for (uint i=0; i<sprite_texture->uHeight; ++i)
+      {
+        for (uint j=0; j<sprite_texture->uWidth/2; ++j)
+        {
+          *(int *)v10 = *(int *)v9;
+          v9 += 2;
+          v10 = (char *)v10 + 4;
+        }
+        v10 = (char *)v10 + Dst.lPitch-sprite_texture->uWidth*2;
+      }
+      ErrD3D(pSprite->pTextureSurface->Unlock(NULL));
+    }*/
+    delete [] sprite_texture->pPixels;
+    delete sprite_texture;
+	return true;
+  }
+  return false;
+}
 
 
 ID3DBlob *DoD3DCompiling(const wchar_t *shader_name, const char *pShaderSource, uint uShaderSourceLen, const char *pEntry, const char *pVersionString, uint uCompileOptions);
@@ -551,9 +691,9 @@
 
   DoCompile(pShaderSourceFile, pShaderSource, uShaderSourceLen, &vs, &vs_size, &ps, &ps_size);
 
-  ErrD3D(d3dd->CreateVertexShader(vs, vs_size, nullptr, vertex_out));
-  ErrD3D(d3dd->CreatePixelShader(ps, ps_size, nullptr, pixel_out));
-  ErrD3D(d3dd->CreateInputLayout(input_desc, input_desc_size, vs, vs_size, layout_out));
+  ErrorD3D(d3dd->CreateVertexShader(vs, vs_size, nullptr, vertex_out));
+  ErrorD3D(d3dd->CreatePixelShader(ps, ps_size, nullptr, pixel_out));
+  ErrorD3D(d3dd->CreateInputLayout(input_desc, input_desc_size, vs, vs_size, layout_out));
 
   delete [] vs;
   delete [] ps;
@@ -667,4 +807,255 @@
   }
 
   return pShader;
+}
+
+
+void RenderD3D11::PrepareTexture(RGBTexture *p)
+{
+  if (!p->d3d11_srv)
+  {
+    auto desc = p->d3d11_desc = new D3D11_TEXTURE2D_DESC;
+    desc->Width = p->uWidth;
+    desc->Height = p->uHeight;
+    desc->ArraySize = 1;
+    desc->MipLevels = 1;
+    desc->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+    desc->SampleDesc.Count = 1;
+    desc->SampleDesc.Quality = 0;
+    desc->Usage = D3D11_USAGE_DEFAULT;
+    desc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
+    desc->CPUAccessFlags = 0;
+    desc->MiscFlags = 0;
+    
+    ID3D11Texture2D *vram_texture = nullptr;
+    ErrorD3D(d3dd->CreateTexture2D(desc, nullptr, &vram_texture));
+
+    D3D11_TEXTURE2D_DESC ram_desc;
+    memcpy(&ram_desc, desc, sizeof(ram_desc));
+    ram_desc.Usage = D3D11_USAGE_STAGING;
+    ram_desc.BindFlags = 0;
+    ram_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    
+    ID3D11Texture2D *ram_texture = nullptr;
+    ErrorD3D(d3dd->CreateTexture2D(&ram_desc, nullptr, &ram_texture));
+
+    D3D11_MAPPED_SUBRESOURCE map;
+    ErrorD3D(d3dc->Map(ram_texture, 0, D3D11_MAP_WRITE, 0, &map));
+    for (unsigned int y = 0; y < desc->Height; ++y)
+      for (unsigned int x = 0; x < desc->Width; ++x)
+      {
+        auto src = p->pPixels + y * p->uWidth + x;
+        auto dst = (unsigned int *)((char *)map.pData + y * map.RowPitch) + x;
+
+        extern unsigned __int32 Color32_SwapRedBlue(unsigned __int16 color16);
+        *dst = 0xFF000000 | Color32_SwapRedBlue(*src);
+      }
+
+    d3dc->Unmap(ram_texture, 0);
+    d3dc->CopyResource(vram_texture, ram_texture);
+    ram_texture->Release();
+    
+    ErrorD3D(d3dd->CreateShaderResourceView(vram_texture, nullptr, (ID3D11ShaderResourceView **)&p->d3d11_srv));
+    vram_texture->Release();
+  }
+}
+
+
+
+void RenderD3D11::PrepareTextureIndexed(Texture *p)
+{
+  if (!p->d3d11_srv)
+  {
+    auto desc = p->d3d11_desc = new D3D11_TEXTURE2D_DESC;
+    desc->Width = p->uTextureWidth;
+    desc->Height = p->uTextureHeight;
+    desc->ArraySize = 1;
+    desc->MipLevels = 1;
+    desc->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+    desc->SampleDesc.Count = 1;
+    desc->SampleDesc.Quality = 0;
+    desc->Usage = D3D11_USAGE_DEFAULT;
+    desc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
+    desc->CPUAccessFlags = 0;
+    desc->MiscFlags = 0;
+    
+    ID3D11Texture2D *vram_texture = nullptr;
+    ErrorD3D(d3dd->CreateTexture2D(desc, nullptr, &vram_texture));
+
+    D3D11_TEXTURE2D_DESC ram_desc;
+    memcpy(&ram_desc, desc, sizeof(ram_desc));
+    ram_desc.Usage = D3D11_USAGE_STAGING;
+    ram_desc.BindFlags = 0;
+    ram_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    
+    ID3D11Texture2D *ram_texture = nullptr;
+    ErrorD3D(d3dd->CreateTexture2D(&ram_desc, nullptr, &ram_texture));
+
+    D3D11_MAPPED_SUBRESOURCE map;
+    ErrorD3D(d3dc->Map(ram_texture, 0, D3D11_MAP_WRITE, 0, &map));
+    for (unsigned int y = 0; y < desc->Height; ++y)
+      for (unsigned int x = 0; x < desc->Width; ++x)
+      {
+        auto index = p->pLevelOfDetail0_prolly_alpha_mask[y * p->uTextureWidth + x];
+        auto src = p->pPalette16[index];
+        auto dst = (unsigned int *)((char *)map.pData + y * map.RowPitch) + x;
+
+        if (index)
+        {
+          extern unsigned __int32 Color32_SwapRedBlue(unsigned __int16 color16);
+          *dst = 0xFF000000 | Color32_SwapRedBlue(src);
+        }
+        else
+          *dst = 0x00000000;
+      }
+
+    d3dc->Unmap(ram_texture, 0);
+    d3dc->CopyResource(vram_texture, ram_texture);
+    ram_texture->Release();
+    
+    ErrorD3D(d3dd->CreateShaderResourceView(vram_texture, nullptr, (ID3D11ShaderResourceView **)&p->d3d11_srv));
+    vram_texture->Release();
+  }
+}
+
+
+ID3D11ShaderResourceView *RenderD3D11::PrepareFontTexture(unsigned char *pFontPixels, unsigned int uCharWidth, unsigned int uCharHeight, unsigned short *pFontPalette, unsigned short uFaceColor, unsigned short uShadowColor)
+{
+  D3D11_TEXTURE2D_DESC desc;
+  desc.Width = uCharWidth;
+  desc.Height = uCharHeight;
+  desc.ArraySize = 1;
+  desc.MipLevels = 1;
+  desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+  desc.SampleDesc.Count = 1;
+  desc.SampleDesc.Quality = 0;
+  desc.Usage = D3D11_USAGE_DEFAULT;
+  desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+  desc.CPUAccessFlags = 0;
+  desc.MiscFlags = 0;
+    
+  ID3D11Texture2D *vram_texture = nullptr;
+  ErrorD3D(d3dd->CreateTexture2D(&desc, nullptr, &vram_texture));
+
+  D3D11_TEXTURE2D_DESC ram_desc;
+  memcpy(&ram_desc, &desc, sizeof(ram_desc));
+  ram_desc.Usage = D3D11_USAGE_STAGING;
+  ram_desc.BindFlags = 0;
+  ram_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    
+  ID3D11Texture2D *ram_texture = nullptr;
+  ErrorD3D(d3dd->CreateTexture2D(&ram_desc, nullptr, &ram_texture));
+
+  D3D11_MAPPED_SUBRESOURCE map;
+  ErrorD3D(d3dc->Map(ram_texture, 0, D3D11_MAP_WRITE, 0, &map));
+  for (unsigned int y = 0; y < desc.Height; ++y)
+    for (unsigned int x = 0; x < desc.Width; ++x)
+    {
+      auto index = pFontPixels[y * desc.Width + x];
+      auto src = pFontPalette[index];
+      auto dst = (unsigned int *)((char *)map.pData + y * map.RowPitch) + x;
+
+      if (index)
+      {
+        extern unsigned __int32 Color32_SwapRedBlue(unsigned __int16 color16);
+        *dst = 0xFF000000 | Color32_SwapRedBlue(index == 1 ? uShadowColor : uFaceColor);
+      }
+      else
+        *dst = 0x00000000;
+    }
+
+  d3dc->Unmap(ram_texture, 0);
+  d3dc->CopyResource(vram_texture, ram_texture);
+  ram_texture->Release();
+    
+  ID3D11ShaderResourceView *srv = nullptr;
+  ErrorD3D(d3dd->CreateShaderResourceView(vram_texture, nullptr, &srv));
+  vram_texture->Release();
+
+  return srv;
+}
+
+void d3d11_release(ID3D11ShaderResourceView *srv)
+{
+  srv->Release();
+}
+
+
+//----- (004A4DE1) --------------------------------------------------------
+bool RenderD3D11::LoadTexture(const char *pName, unsigned int bMipMaps, IDirectDrawSurface4 **pOutSurface, IDirect3DTexture2 **pOutTexture)
+{
+  unsigned __int16 *v13; // ecx@19
+  unsigned __int16 *v14; // eax@19
+  DWORD v15; // edx@20
+
+  HWLTexture* pHWLTexture = pD3DBitmaps.LoadTexture(pName, bMipMaps);
+  if (!pHWLTexture)
+    return false;
+
+  int num_min_levels = 1;
+  {
+    int dim = min(pHWLTexture->uWidth, pHWLTexture->uHeight);
+    while (dim > 1)
+    {
+      dim /= 2;
+      num_min_levels++;
+    }
+  }
+
+  
+    {
+      D3D11_TEXTURE2D_DESC desc;
+      desc.Width = pHWLTexture->uWidth;
+      desc.Height = pHWLTexture->uHeight;
+      desc.ArraySize = 1;
+      desc.MipLevels = num_min_levels;
+      desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+      desc.SampleDesc.Count = 1;
+      desc.SampleDesc.Quality = 0;
+      desc.Usage = D3D11_USAGE_DEFAULT;
+      desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET/* for mipmap generation */;
+      desc.CPUAccessFlags = 0;
+      desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
+    
+      ID3D11Texture2D *vram_texture = nullptr;
+      ErrorD3D(d3dd->CreateTexture2D(&desc, nullptr, &vram_texture));
+
+      D3D11_TEXTURE2D_DESC ram_desc;
+      memcpy(&ram_desc, &desc, sizeof(ram_desc));
+      ram_desc.Usage = D3D11_USAGE_STAGING;
+      ram_desc.BindFlags = 0;
+      ram_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+      ram_desc.MiscFlags = 0;
+
+      ID3D11Texture2D *ram_texture = nullptr;
+      ErrorD3D(d3dd->CreateTexture2D(&ram_desc, nullptr, &ram_texture));
+
+      D3D11_MAPPED_SUBRESOURCE map;
+      ErrorD3D(d3dc->Map(ram_texture, 0, D3D11_MAP_WRITE, 0, &map));
+      for (unsigned int y = 0; y < desc.Height; ++y)
+        for (unsigned int x = 0; x < desc.Width; ++x)
+        {
+          auto src = pHWLTexture->pPixels + y * desc.Width + x;
+          auto dst = (unsigned int *)((char *)map.pData + y * map.RowPitch) + x;
+
+          extern unsigned __int32 Color32_SwapRedBlue(unsigned __int16 color16);
+          *dst = 0xFF000000 | Color32_SwapRedBlue(*src);
+        }
+
+      d3dc->Unmap(ram_texture, 0);
+      d3dc->CopyResource(vram_texture, ram_texture);
+      ram_texture->Release();
+    
+      ID3D11ShaderResourceView *srv = nullptr;
+      ErrorD3D(d3dd->CreateShaderResourceView(vram_texture, nullptr, &srv));
+      vram_texture->Release();
+      
+      d3dc->GenerateMips(srv);
+      *pOutTexture = (IDirect3DTexture2 *)srv;
+      *pOutSurface = nullptr;
+    }
+
+    delete [] pHWLTexture->pPixels;
+    delete pHWLTexture;
+    return true;
 }
\ No newline at end of file