130 lines
3.1 KiB
C++
130 lines
3.1 KiB
C++
/*
|
|
Copyright 2021 flyinghead
|
|
|
|
This file is part of Flycast.
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "d3d_texture.h"
|
|
|
|
void D3DTexture::UploadToGPU(int width, int height, u8* temp_tex_buffer, bool mipmapped, bool mipmapsIncluded)
|
|
{
|
|
D3DFORMAT d3dFormat;
|
|
u32 bpp = 2;
|
|
switch (tex_type)
|
|
{
|
|
case TextureType::_5551:
|
|
d3dFormat = D3DFMT_A1R5G5B5;
|
|
break;
|
|
case TextureType::_4444:
|
|
d3dFormat = D3DFMT_A4R4G4B4;
|
|
break;
|
|
case TextureType::_565:
|
|
d3dFormat = D3DFMT_R5G6B5;
|
|
break;
|
|
case TextureType::_8888:
|
|
bpp = 4;
|
|
d3dFormat = D3DFMT_A8R8G8B8;
|
|
break;
|
|
case TextureType::_8:
|
|
bpp = 1;
|
|
d3dFormat = D3DFMT_A8;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
int mipmapLevels = 1;
|
|
if (mipmapsIncluded)
|
|
{
|
|
mipmapLevels = 0;
|
|
int dim = width;
|
|
while (dim != 0)
|
|
{
|
|
mipmapLevels++;
|
|
dim >>= 1;
|
|
}
|
|
}
|
|
|
|
D3DLOCKED_RECT rect;
|
|
while (true)
|
|
{
|
|
if (texture == nullptr)
|
|
{
|
|
u32 levels = mipmapLevels;
|
|
u32 usage = 0;
|
|
if (mipmapped && !mipmapsIncluded)
|
|
{
|
|
levels = 0;
|
|
usage = D3DUSAGE_AUTOGENMIPMAP;
|
|
}
|
|
theDXContext.getDevice()->CreateTexture(width, height, levels, usage, d3dFormat, D3DPOOL_MANAGED, &texture.get(), 0); // TODO the managed pool persists between device resets
|
|
verify(texture != nullptr);
|
|
}
|
|
if (SUCCEEDED(texture->LockRect(mipmapLevels - 1, &rect, nullptr, 0)))
|
|
break;
|
|
D3DSURFACE_DESC desc;
|
|
texture->GetLevelDesc(0, &desc);
|
|
if (desc.Pool != D3DPOOL_DEFAULT)
|
|
// it should be lockable so error out
|
|
return;
|
|
// RTT targets are created in the default pool and aren't lockable, so delete it and recreate it in the managed pool
|
|
texture.reset();
|
|
}
|
|
for (int i = 0; i < mipmapLevels; i++)
|
|
{
|
|
u32 w = mipmapLevels == 1 ? width : 1 << i;
|
|
u32 h = mipmapLevels == 1 ? height : 1 << i;
|
|
if (w * bpp == (u32)rect.Pitch)
|
|
memcpy(rect.pBits, temp_tex_buffer, w * bpp * h);
|
|
else
|
|
{
|
|
u8 *dst = (u8 *)rect.pBits;
|
|
u8 *src = temp_tex_buffer;
|
|
for (u32 l = 0; l < h; l++)
|
|
{
|
|
memcpy(dst, src, w * bpp);
|
|
dst += rect.Pitch;
|
|
src += w * bpp;
|
|
}
|
|
}
|
|
texture->UnlockRect(mipmapLevels - i - 1);
|
|
temp_tex_buffer += (1 << (2 * i)) * bpp;
|
|
if (i < mipmapLevels - 1)
|
|
if (FAILED(texture->LockRect(mipmapLevels - i - 2, &rect, nullptr, 0)))
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool D3DTexture::Delete()
|
|
{
|
|
if (!BaseTextureCacheData::Delete())
|
|
return false;
|
|
|
|
texture.reset();
|
|
return true;
|
|
}
|
|
|
|
void D3DTexture::loadCustomTexture()
|
|
{
|
|
u32 size = custom_width * custom_height;
|
|
u8 *p = custom_image_data;
|
|
while (size--)
|
|
{
|
|
// RGBA -> BGRA
|
|
std::swap(p[0], p[2]);
|
|
p += 4;
|
|
}
|
|
CheckCustomTexture();
|
|
}
|