diff --git a/Windows_Libs/Dev/Render/RendererTexture.cpp b/Windows_Libs/Dev/Render/RendererTexture.cpp index ce5ea4e..2123b5b 100644 --- a/Windows_Libs/Dev/Render/RendererTexture.cpp +++ b/Windows_Libs/Dev/Render/RendererTexture.cpp @@ -1,329 +1,304 @@ -#pragma once #include "Renderer.h" #include "libpng/png.h" -#include -#include -#include -#include +unsigned char* dataStart; +unsigned char* dataCurr; +unsigned char* dataEnd; -DXGI_FORMAT Renderer::textureFormats[C4JRender::MAX_TEXTURE_FORMATS] = { - DXGI_FORMAT_B8G8R8A8_UNORM, -}; +DXGI_FORMAT Renderer::textureFormats[] = { DXGI_FORMAT_R8G8B8A8_UNORM }; -int Renderer::TextureCreate() { - for (int i = 0; i < 512; ++i) { - Texture &texture = m_textures[i]; - if (!texture.allocated) { - texture.texture = nullptr; - texture.allocated = true; - texture.mipLevels = 1; - texture.samplerParams = 0; - return i; +void user_write_data_init(unsigned char* pBuffer, int size) +{ + dataStart = pBuffer; + dataCurr = pBuffer; + dataEnd = pBuffer + size; +} + +int user_write_data_bytes_written() +{ + return (int)(dataCurr - dataStart); +} + +void user_write_data(png_struct_def* png_ptr, unsigned char* data, size_t length) +{ + int canWrite = (int)((unsigned char*)dataEnd - (unsigned char*)dataCurr); + if ((int)length < canWrite) + canWrite = (int)length; + memcpy(dataCurr, data, canWrite); + dataCurr = (unsigned char*)dataCurr + canWrite; +} + +void user_flush_data(png_struct_def* png_ptr) +{ + // TODO(3UR): this is for a different platform? it's empty in Render_PC.lib but not Render.lib +} + +int Renderer::TextureCreate() +{ + for (int i = 0; i < MAX_TEXTURES; i++) + { + if (!m_textures[i].allocated) + { + m_textures[i].texture = NULL; + m_textures[i].allocated = true; + m_textures[i].mipLevels = 1; + m_textures[i].textureFormat = 0; + return i; + } } - } - - return -1; + return -1; } -void Renderer::TextureSetTextureLevels(int levels) { - const int boundTextureIndex = this->getContext().boundTextureIndex; - m_textures[boundTextureIndex].mipLevels = levels; +void Renderer::TextureFree(int idx) +{ + m_textures[idx].texture->Release(); + m_textures[idx].view->Release(); + m_textures[idx].view = NULL; + m_textures[idx].allocated = false; + m_textures[idx].texture = NULL; } -int Renderer::TextureGetTextureLevels() { - const int boundTextureIndex = this->getContext().boundTextureIndex; - return m_textures[boundTextureIndex].mipLevels; +void Renderer::TextureBind(int idx) +{ + if (idx == -1) + idx = defaultTextureIndex; + + Context& c = this->getContext(); + + if (c.commandBuffer && c.commandBuffer->isActive) + c.commandBuffer->BindTexture(idx); + + c.boundTextureIndex = idx; + c.m_pDeviceContext->PSSetShaderResources(0, 1, &m_textures[idx].view); + + UpdateTextureState(false); } -void Renderer::TextureSetParam(int param, int value) { - Texture &texture = m_textures[this->getContext().boundTextureIndex]; +void Renderer::TextureBindVertex(int idx) +{ + if (idx == -1) + idx = defaultTextureIndex; - switch (param) { - case GL_TEXTURE_MIN_FILTER: - texture.samplerParams &= ~4u; - if (value == 1) { - texture.samplerParams |= 4u; + Context& c = this->getContext(); + + c.boundTextureIndex = idx; + c.m_pDeviceContext->VSSetShaderResources(0, 1, &m_textures[idx].view); + + UpdateTextureState(true); +} + +void Renderer::TextureSetTextureLevels(int levels) +{ + Context& c = this->getContext(); + m_textures[c.boundTextureIndex].mipLevels = levels; +} + +int Renderer::TextureGetTextureLevels() +{ + Context& c = this->getContext(); + return m_textures[c.boundTextureIndex].mipLevels; +} + +void Renderer::TextureData(int width, int height, void* data, int level, C4JRender::eTextureFormat format) +{ + Context& c = this->getContext(); + int idx = c.boundTextureIndex; + + m_textures[idx].textureFormat = format; + + if (level == 0) + { + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = m_textures[idx].mipLevels; + desc.ArraySize = 1; + desc.Format = (DXGI_FORMAT)textureFormats[format]; + 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; + + m_pDevice->CreateTexture2D(&desc, NULL, (ID3D11Texture2D**)&m_textures[idx].texture); + m_pDevice->CreateShaderResourceView(m_textures[idx].texture, NULL, &m_textures[idx].view); } - break; - case GL_TEXTURE_MAG_FILTER: - texture.samplerParams &= ~8u; - if (value == 1) { - texture.samplerParams |= 8u; + + c.m_pDeviceContext->UpdateSubresource( + m_textures[idx].texture, + level, + NULL, + data, + width * 4, + width * height * 4 + ); +} + +void Renderer::TextureDataUpdate(int xoffset, int yoffset, int width, int height, void* data, int level) +{ + Context& c = this->getContext(); + int idx = c.boundTextureIndex; + + D3D11_TEXTURE2D_DESC desc; + m_textures[idx].texture->GetDesc(&desc); + + D3D11_BOX box; + box.left = xoffset; + box.top = yoffset; + box.right = xoffset + width; + box.bottom = yoffset + height; + box.front = 0; + box.back = 1; + + c.m_pDeviceContext->UpdateSubresource( + m_textures[idx].texture, + level, + &box, + data, + width * 4, + width * height * 4 + ); +} + +void Renderer::TextureSetParam(int param, int value) +{ + Context& c = this->getContext(); + int idx = c.boundTextureIndex; + + switch (param) + { + case GL_TEXTURE_MIN_FILTER: + m_textures[idx].samplerParams &= ~4u; + if (value == GL_LINEAR) + m_textures[idx].samplerParams |= 4u; + break; + case GL_TEXTURE_MAG_FILTER: + m_textures[idx].samplerParams &= ~8u; + if (value == GL_LINEAR) + m_textures[idx].samplerParams |= 8u; + break; + case GL_TEXTURE_WRAP_S: + m_textures[idx].samplerParams &= ~1u; + if (value == GL_CLAMP) + m_textures[idx].samplerParams |= 1u; + break; + case GL_TEXTURE_WRAP_T: + m_textures[idx].samplerParams &= ~2u; + if (value == GL_CLAMP) + m_textures[idx].samplerParams |= 2u; + break; } - break; - case GL_TEXTURE_WRAP_S: - texture.samplerParams &= ~1u; - if (value == 0) { - texture.samplerParams |= 1u; +} + +void Renderer::TextureDynamicUpdateStart() +{ + // TODO: this is for a different platform? it's empty in Render_PC.lib but not Render.lib +} + +void Renderer::TextureDynamicUpdateEnd() +{ + // TODO: this is for a different platform? it's empty in Render_PC.lib but not Render.lib +} + +void Renderer::UpdateTextureState(bool bVertex) +{ + Context& c = this->getContext(); + ID3D11SamplerState* pSampler = GetManagedSamplerState(); + + if (bVertex) + c.m_pDeviceContext->VSSetSamplers(0, 1, &pSampler); + else + c.m_pDeviceContext->PSSetSamplers(0, 1, &pSampler); +} + +HRESULT Renderer::LoadTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut) +{ + png_image image; + memset(&image, 0, sizeof(image)); + image.version = PNG_IMAGE_VERSION; + + png_image_begin_read_from_file(&image, szFilename); + + if ((image.format & 3u) > 1) + return -1; + + image.format = PNG_FORMAT_RGBA; + + *ppDataOut = new int[image.width * image.height]; + if (!*ppDataOut || !png_image_finish_read(&image, NULL, *ppDataOut, 0, NULL)) + return -1; + + pSrcInfo->Width = image.width; + pSrcInfo->Height = image.height; + return S_OK; +} + +HRESULT Renderer::LoadTextureData(BYTE* pbData, DWORD dwBytes, D3DXIMAGE_INFO* pSrcInfo, int** ppDataOut) +{ + png_image image; + memset(&image, 0, sizeof(image)); + image.version = PNG_IMAGE_VERSION; + + png_image_begin_read_from_memory(&image, pbData, dwBytes); + + if ((image.format & 3u) > 1) + return -1; + + image.format = PNG_FORMAT_RGBA; + + *ppDataOut = new int[image.width * image.height]; + if (!*ppDataOut || !png_image_finish_read(&image, NULL, *ppDataOut, 0, NULL)) + return -1; + + pSrcInfo->Width = image.width; + pSrcInfo->Height = image.height; + return S_OK; +} + +HRESULT Renderer::SaveTextureData(const char* szFilename, D3DXIMAGE_INFO* pSrcInfo, int* ppDataOut) +{ + png_image image; + memset(&image, 0, sizeof(image)); + image.width = pSrcInfo->Width; + image.height = pSrcInfo->Height; + image.version = PNG_IMAGE_VERSION; + image.format = PNG_FORMAT_RGB; + + png_image_write_to_file(&image, szFilename, 0, ppDataOut, 0, NULL); + return S_OK; +} + +HRESULT Renderer::SaveTextureDataToMemory(void* pOutput, int outputCapacity, int* outputLength, int width, int height, int* ppDataIn) +{ + png_image image; + memset(&image, 0, sizeof(image)); + image.width = width; + image.height = height; + image.version = PNG_IMAGE_VERSION; + image.format = PNG_FORMAT_RGB; + + dataEnd = (BYTE*)pOutput + outputCapacity; + dataStart = (BYTE*)pOutput; + dataCurr = (BYTE*)pOutput; + + png_image_write_to_stdio(&image, NULL, 0, ppDataIn, 0, NULL, user_write_data, user_flush_data); + + *outputLength = (int)(dataCurr - dataStart); + return S_OK; +} + +void Renderer::TextureGetStats() +{ + // TODO: this is for a different platform? it's empty in Render_PC.lib but not Render.lib +} + +ID3D11ShaderResourceView* Renderer::TextureGetTexture(int idx) +{ + if ((unsigned int)idx <= 511) + { + if (m_textures[idx].allocated) + return m_textures[idx].view; } - break; - case GL_TEXTURE_WRAP_T: - case 5: - texture.samplerParams &= ~2u; - if (value == 0) { - texture.samplerParams |= 2u; - } - break; - default: - break; - } -} - -void Renderer::TextureDynamicUpdateStart() {} - -void Renderer::TextureDynamicUpdateEnd() {} - -void Renderer::TextureData(int width, int height, void *data, int level, - C4JRender::eTextureFormat format) { - Renderer::Context &context = this->getContext(); - Texture &texture = m_textures[context.boundTextureIndex]; - texture.textureFormat = format; - - if (level == 0) { - D3D11_TEXTURE2D_DESC desc = {}; - desc.Width = width; - desc.Height = height; - desc.MipLevels = texture.mipLevels; - desc.ArraySize = 1; - desc.Format = textureFormats[format]; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - m_pDevice->CreateTexture2D(&desc, nullptr, &texture.texture); - m_pDevice->CreateShaderResourceView(texture.texture, nullptr, - &texture.view); - } - - const UINT rowPitch = width * 4u; - const UINT depthPitch = width * height * 4u; - context.m_pDeviceContext->UpdateSubresource(texture.texture, level, nullptr, - data, rowPitch, depthPitch); -} - -void Renderer::TextureDataUpdate(int xoffset, int yoffset, int width, - int height, void *data, int level) { - Renderer::Context &context = this->getContext(); - Texture &texture = m_textures[context.boundTextureIndex]; - - D3D11_BOX box = {}; - box.left = xoffset; - box.right = xoffset + width; - box.top = yoffset; - box.bottom = yoffset + height; - box.front = 0; - box.back = 1; - - D3D11_TEXTURE2D_DESC desc = {}; - texture.texture->GetDesc(&desc); - - const UINT rowPitch = width * 4u; - const UINT depthPitch = width * height * 4u; - context.m_pDeviceContext->UpdateSubresource(texture.texture, level, &box, - data, rowPitch, depthPitch); -} - -void Renderer::TextureFree(int idx) { - Texture &texture = m_textures[idx]; - texture.texture->Release(); - texture.view->Release(); - texture.view = nullptr; - texture.allocated = false; - texture.texture = nullptr; -} - -void Renderer::TextureGetStats() {} - -ID3D11ShaderResourceView *Renderer::TextureGetTexture(int idx) { - if (idx < 0 || idx > 0x1FF) { - return nullptr; - } - - const Texture &texture = m_textures[idx]; - if (!texture.allocated) { - return nullptr; - } - - return texture.view; -} - -void Renderer::TextureBind(int idx) { - int textureIndex = idx; - if (textureIndex == -1) { - textureIndex = defaultTextureIndex; - } - - Renderer::Context &context = this->getContext(); - - if (context.commandBuffer && context.commandBuffer->isActive) { - context.commandBuffer->BindTexture(textureIndex); - } - - context.boundTextureIndex = textureIndex; - ID3D11ShaderResourceView *const view = m_textures[textureIndex].view; - context.m_pDeviceContext->PSSetShaderResources(0, 1, &view); - this->UpdateTextureState(false); -} - -void Renderer::TextureBindVertex(int idx) { - int textureIndex = idx; - if (textureIndex == -1) { - textureIndex = defaultTextureIndex; - } - - Renderer::Context &context = this->getContext(); - context.boundTextureIndex = textureIndex; - - ID3D11ShaderResourceView *const view = m_textures[textureIndex].view; - context.m_pDeviceContext->VSSetShaderResources(0, 1, &view); - this->UpdateTextureState(true); -} - -void Renderer::UpdateTextureState(bool vertexSampler) { - Renderer::Context &context = this->getContext(); - ID3D11SamplerState *sampler = this->GetManagedSamplerState(); - - if (vertexSampler) { - context.m_pDeviceContext->VSSetSamplers(0, 1, &sampler); - } else { - context.m_pDeviceContext->PSSetSamplers(0, 1, &sampler); - } -} - -HRESULT Renderer::LoadTextureData(const char *szFilename, - D3DXIMAGE_INFO *pSrcInfo, int **ppDataOut) { - if (!szFilename || !pSrcInfo || !ppDataOut) { - return -1; - } - - *ppDataOut = nullptr; - - png_image image; - std::memset(&image, 0, sizeof(image)); - image.version = PNG_IMAGE_VERSION; - if (!png_image_begin_read_from_file(&image, szFilename)) { - return -1; - } - - if (image.width == 0 || image.height == 0) { - png_image_free(&image); - return -1; - } - - image.format = PNG_FORMAT_RGBA; - const png_alloc_size_t pixelCount = - png_alloc_size_t(image.width) * png_alloc_size_t(image.height); - if (pixelCount == 0 || - pixelCount > (std::numeric_limits::max)() / sizeof(int)) { - png_image_free(&image); - return -1; - } - - int *output = new (std::nothrow) int[size_t(pixelCount)]; - - if (!output) { - png_image_free(&image); - return -1; - } - - if (!png_image_finish_read(&image, nullptr, output, 0, nullptr)) { - delete[] output; - png_image_free(&image); - return -1; - } - - *ppDataOut = output; - pSrcInfo->Width = image.width; - pSrcInfo->Height = image.height; - png_image_free(&image); - return 0; -} - -HRESULT Renderer::LoadTextureData(BYTE *pbData, DWORD dwBytes, - D3DXIMAGE_INFO *pSrcInfo, int **ppDataOut) { - if (!pbData || dwBytes == 0 || !pSrcInfo || !ppDataOut) { - return -1; - } - - *ppDataOut = nullptr; - - png_image image; - std::memset(&image, 0, sizeof(image)); - image.version = PNG_IMAGE_VERSION; - if (!png_image_begin_read_from_memory(&image, pbData, dwBytes)) { - return -1; - } - - if (image.width == 0 || image.height == 0) { - png_image_free(&image); - return -1; - } - - image.format = PNG_FORMAT_RGBA; - const png_alloc_size_t pixelCount = - png_alloc_size_t(image.width) * png_alloc_size_t(image.height); - if (pixelCount == 0 || - pixelCount > (std::numeric_limits::max)() / sizeof(int)) { - png_image_free(&image); - return -1; - } - - int *output = new (std::nothrow) int[size_t(pixelCount)]; - - if (!output) { - png_image_free(&image); - return -1; - } - - if (!png_image_finish_read(&image, nullptr, output, 0, nullptr)) { - delete[] output; - png_image_free(&image); - return -1; - } - - *ppDataOut = output; - pSrcInfo->Width = image.width; - pSrcInfo->Height = image.height; - png_image_free(&image); - return 0; -} - -HRESULT Renderer::SaveTextureData(const char *szFilename, - D3DXIMAGE_INFO *pSrcInfo, int *ppDataOut) { - png_image image = {}; - image.version = PNG_IMAGE_VERSION; - image.width = pSrcInfo->Width; - image.height = pSrcInfo->Height; - image.format = PNG_FORMAT_RGBA; - - png_image_write_to_file(&image, szFilename, 0, ppDataOut, 0, nullptr); - return 0; -} - -HRESULT Renderer::SaveTextureDataToMemory(void *pOutput, int outputCapacity, - int *outputLength, int width, - int height, int *ppDataIn) { - if (!pOutput || outputCapacity <= 0 || !outputLength || width <= 0 || - height <= 0 || !ppDataIn) { - return -1; - } - - png_image image; - std::memset(&image, 0, sizeof(image)); - image.version = PNG_IMAGE_VERSION; - image.width = width; - image.height = height; - image.format = PNG_FORMAT_RGBA; - - png_alloc_size_t memoryBytes = static_cast(outputCapacity); - if (!png_image_write_to_memory(&image, pOutput, &memoryBytes, 0, ppDataIn, 0, - nullptr)) { - *outputLength = 0; - png_image_free(&image); - return -1; - } - - *outputLength = static_cast(memoryBytes); - png_image_free(&image); - return 0; -} + return NULL; +} \ No newline at end of file