mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Simplification around textures
This commit is contained in:
@@ -194,7 +194,6 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
|
||||
fbTex->SetImageData(0, 0, 0, srcwidth, srcheight, 1, 0, srcwidth * 4, (const uint8_t *)&fbTexBuffer[0]);
|
||||
u1 = 1.0f;
|
||||
}
|
||||
fbTex->Finalize();
|
||||
|
||||
float x, y, w, h;
|
||||
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);
|
||||
|
||||
@@ -81,8 +81,6 @@ void AsyncImageFileView::Draw(UIContext &dc) {
|
||||
texture_ = CreateTextureFromFile(dc.GetThin3DContext(), filename_.c_str(), DETECT);
|
||||
if (!texture_)
|
||||
textureFailed_ = true;
|
||||
else if (textureAutoGen_) // TODO: Iffy
|
||||
texture_->GetTexture()->AutoGenMipmaps();
|
||||
}
|
||||
|
||||
if (HasFocus()) {
|
||||
|
||||
+1
-3
@@ -70,7 +70,7 @@ class PrioritizedWorkQueue;
|
||||
class AsyncImageFileView : public UI::Clickable {
|
||||
public:
|
||||
AsyncImageFileView(const std::string &filename, UI::ImageSizeMode sizeMode, PrioritizedWorkQueue *wq, UI::LayoutParams *layoutParams = 0)
|
||||
: UI::Clickable(layoutParams), canFocus_(true), filename_(filename), color_(0xFFFFFFFF), sizeMode_(sizeMode), texture_(NULL), textureFailed_(false), textureAutoGen_(true), fixedSizeW_(0.0f), fixedSizeH_(0.0f) {}
|
||||
: UI::Clickable(layoutParams), canFocus_(true), filename_(filename), color_(0xFFFFFFFF), sizeMode_(sizeMode), texture_(nullptr), textureFailed_(false), fixedSizeW_(0.0f), fixedSizeH_(0.0f) {}
|
||||
~AsyncImageFileView() {
|
||||
delete texture_;
|
||||
}
|
||||
@@ -83,7 +83,6 @@ public:
|
||||
void SetOverlayText(std::string text) { text_ = text; }
|
||||
void SetFixedSize(float fixW, float fixH) { fixedSizeW_ = fixW; fixedSizeH_ = fixH; }
|
||||
void SetCanBeFocused(bool can) { canFocus_ = can; }
|
||||
void SetAutoGenMipmaps(bool a) { textureAutoGen_ = a; }
|
||||
|
||||
bool CanBeFocused() const override { return canFocus_; }
|
||||
|
||||
@@ -98,7 +97,6 @@ private:
|
||||
|
||||
ManagedTexture *texture_;
|
||||
bool textureFailed_;
|
||||
bool textureAutoGen_;
|
||||
float fixedSizeW_;
|
||||
float fixedSizeH_;
|
||||
};
|
||||
|
||||
@@ -193,11 +193,6 @@ void SavedataButton::Draw(UIContext &dc) {
|
||||
float nw = h * tw / th;
|
||||
x += (w - nw) / 2.0f;
|
||||
w = nw;
|
||||
|
||||
if (texture->Width() >= w * 2 || texture->Height() >= h * 2) {
|
||||
// Better to use mipmaps, then. This is probably a large savestate screenshot.
|
||||
texture->AutoGenMipmaps();
|
||||
}
|
||||
}
|
||||
|
||||
int txOffset = down_ ? 4 : 0;
|
||||
|
||||
+4
-8
@@ -105,18 +105,14 @@ bool ManagedTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, Imag
|
||||
desc.height = height[0];
|
||||
desc.depth = 1;
|
||||
desc.mipLevels = num_levels;
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
desc.initData.push_back(image[i]);
|
||||
}
|
||||
texture_ = draw_->CreateTexture(desc);
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
if (image[i]) {
|
||||
texture_->SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]);
|
||||
if (image[i])
|
||||
free(image[i]);
|
||||
}
|
||||
else {
|
||||
ELOG("Missing image level %i", i);
|
||||
}
|
||||
}
|
||||
|
||||
texture_->Finalize();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,14 +280,6 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
|
||||
entry->bmHeight = (size.cy + 3) & ~3;
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
|
||||
TextureDesc desc{};
|
||||
desc.type = TextureType::LINEAR2D;
|
||||
desc.format = DataFormat::R4G4B4A4_UNORM;
|
||||
desc.width = entry->bmWidth;
|
||||
desc.height = entry->bmHeight;
|
||||
desc.depth = 1;
|
||||
desc.mipLevels = 1;
|
||||
entry->texture = thin3d_->CreateTexture(desc);
|
||||
|
||||
// Convert the bitmap to a gl-compatible array of pixels.
|
||||
uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight];
|
||||
@@ -297,8 +289,16 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
|
||||
bitmapData[entry->bmWidth * y + x] = (bAlpha) | 0xfff0;
|
||||
}
|
||||
}
|
||||
entry->texture->SetImageData(0, 0, 0, entry->bmWidth, entry->bmHeight, 1, 0, entry->bmWidth * 2, (const uint8_t *)bitmapData);
|
||||
entry->texture->Finalize();
|
||||
|
||||
TextureDesc desc{};
|
||||
desc.type = TextureType::LINEAR2D;
|
||||
desc.format = DataFormat::R4G4B4A4_UNORM;
|
||||
desc.width = entry->bmWidth;
|
||||
desc.height = entry->bmHeight;
|
||||
desc.depth = 1;
|
||||
desc.mipLevels = 1;
|
||||
desc.initData.push_back((uint8_t *)bitmapData);
|
||||
entry->texture = thin3d_->CreateTexture(desc);
|
||||
delete [] bitmapData;
|
||||
|
||||
cache_[entryHash] = std::unique_ptr<TextStringEntry>(entry);
|
||||
|
||||
@@ -5,6 +5,33 @@
|
||||
|
||||
namespace Draw {
|
||||
|
||||
size_t DataFormatSizeInBytes(DataFormat fmt) {
|
||||
switch (fmt) {
|
||||
case DataFormat::R8_UNORM: return 1;
|
||||
case DataFormat::R8G8_UNORM: return 2;
|
||||
case DataFormat::R8G8B8_UNORM: return 3;
|
||||
|
||||
case DataFormat::R4G4B4A4_UNORM: return 2;
|
||||
|
||||
case DataFormat::R8G8B8A8_UNORM:
|
||||
case DataFormat::R8G8B8A8_UNORM_SRGB: return 4;
|
||||
|
||||
case DataFormat::R8G8B8A8_SNORM: return 4;
|
||||
case DataFormat::R8G8B8A8_UINT: return 4;
|
||||
case DataFormat::R8G8B8A8_SINT: return 4;
|
||||
case DataFormat::R16_FLOAT: return 2;
|
||||
case DataFormat::R16G16_FLOAT: return 4;
|
||||
case DataFormat::R16G16B16A16_FLOAT: return 8;
|
||||
case DataFormat::R32_FLOAT: return 4;
|
||||
case DataFormat::R32G32_FLOAT: return 8;
|
||||
case DataFormat::R32G32B32_FLOAT: return 12;
|
||||
case DataFormat::R32G32B32A32_FLOAT: return 16;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool RefCountedObject::Release() {
|
||||
if (refcount_ > 0 && refcount_ < 10000) {
|
||||
refcount_--;
|
||||
|
||||
@@ -333,8 +333,6 @@ public:
|
||||
class Texture : public RefCountedObject {
|
||||
public:
|
||||
virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) = 0;
|
||||
virtual void AutoGenMipmaps() = 0;
|
||||
virtual void Finalize() = 0; // TODO: Tidy up
|
||||
|
||||
int Width() { return width_; }
|
||||
int Height() { return height_; }
|
||||
@@ -474,6 +472,7 @@ struct TextureDesc {
|
||||
int height;
|
||||
int depth;
|
||||
int mipLevels;
|
||||
std::vector<uint8_t *> initData;
|
||||
};
|
||||
|
||||
class DrawContext : public RefCountedObject {
|
||||
@@ -500,6 +499,7 @@ public:
|
||||
// Resources
|
||||
virtual Buffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0;
|
||||
virtual Texture *CreateTexture(const TextureDesc &desc) = 0;
|
||||
|
||||
virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize) = 0;
|
||||
virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) = 0;
|
||||
|
||||
@@ -549,6 +549,8 @@ protected:
|
||||
int targetHeight_;
|
||||
};
|
||||
|
||||
size_t DataFormatSizeInBytes(DataFormat fmt);
|
||||
|
||||
DrawContext *T3DCreateGLContext();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -347,15 +347,14 @@ public:
|
||||
D3D9Texture(LPDIRECT3DDEVICE9 device, LPDIRECT3DDEVICE9EX deviceEx, const TextureDesc &desc);
|
||||
~D3D9Texture();
|
||||
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
|
||||
void AutoGenMipmaps() override {}
|
||||
void SetToSampler(LPDIRECT3DDEVICE9 device, int sampler);
|
||||
void Finalize() override {}
|
||||
|
||||
private:
|
||||
bool Create(const TextureDesc &desc);
|
||||
LPDIRECT3DDEVICE9 device_;
|
||||
LPDIRECT3DDEVICE9EX deviceEx_;
|
||||
TextureType type_;
|
||||
DataFormat format_;
|
||||
D3DFORMAT fmt_;
|
||||
LPDIRECT3DTEXTURE9 tex_;
|
||||
LPDIRECT3DVOLUMETEXTURE9 volTex_;
|
||||
@@ -394,6 +393,7 @@ bool D3D9Texture::Create(const TextureDesc &desc) {
|
||||
height_ = desc.height;
|
||||
depth_ = desc.depth;
|
||||
type_ = desc.type;
|
||||
format_ = desc.format;
|
||||
tex_ = NULL;
|
||||
fmt_ = FormatToD3D(desc.format);
|
||||
HRESULT hr = E_FAIL;
|
||||
@@ -420,6 +420,12 @@ bool D3D9Texture::Create(const TextureDesc &desc) {
|
||||
ELOG("Texture creation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (desc.initData.size()) {
|
||||
for (int i = 0; i < desc.initData.size(); i++) {
|
||||
this->SetImageData(0, 0, 0, width_, height_, depth_, i, 0, desc.initData[i]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -443,6 +449,10 @@ void D3D9Texture::SetImageData(int x, int y, int z, int width, int height, int d
|
||||
depth_ = depth;
|
||||
}
|
||||
|
||||
if (!stride) {
|
||||
stride = width * DataFormatSizeInBytes(format_);
|
||||
}
|
||||
|
||||
switch (type_) {
|
||||
case TextureType::LINEAR2D:
|
||||
{
|
||||
|
||||
@@ -653,6 +653,10 @@ GLuint TypeToTarget(TextureType type) {
|
||||
}
|
||||
}
|
||||
|
||||
inline bool isPowerOf2(int n) {
|
||||
return n == 1 || (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
class OpenGLTexture : public Texture, GfxResourceHolder {
|
||||
public:
|
||||
OpenGLTexture(const TextureDesc &desc) : tex_(0), target_(TypeToTarget(desc.type)), format_(desc.format), mipLevels_(desc.mipLevels) {
|
||||
@@ -661,8 +665,23 @@ public:
|
||||
width_ = desc.width;
|
||||
height_ = desc.height;
|
||||
depth_ = desc.depth;
|
||||
canWrap_ = !isPowerOf2(width_) || !isPowerOf2(height_);
|
||||
|
||||
glGenTextures(1, &tex_);
|
||||
register_gl_resource_holder(this);
|
||||
|
||||
if (!desc.initData.size())
|
||||
return;
|
||||
|
||||
int level = 0;
|
||||
for (auto data : desc.initData) {
|
||||
SetImageData(0, 0, 0, width_, height_, depth_, level, 0, data);
|
||||
width_ = (width_ + 1) /2;
|
||||
height_ = (height_ + 1) /2;
|
||||
level++;
|
||||
}
|
||||
if (desc.initData.size() < desc.mipLevels)
|
||||
AutoGenMipmaps();
|
||||
}
|
||||
~OpenGLTexture() {
|
||||
unregister_gl_resource_holder(this);
|
||||
@@ -678,7 +697,7 @@ public:
|
||||
}
|
||||
|
||||
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
|
||||
void AutoGenMipmaps() override;
|
||||
void AutoGenMipmaps();
|
||||
|
||||
bool HasMips() {
|
||||
return mipLevels_ > 1 || generatedMips_;
|
||||
@@ -700,8 +719,6 @@ public:
|
||||
void GLRestore() override {
|
||||
}
|
||||
|
||||
void Finalize() override;
|
||||
|
||||
private:
|
||||
GLuint tex_;
|
||||
GLuint target_;
|
||||
@@ -744,11 +761,6 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (level == 0) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
depth_ = depth;
|
||||
}
|
||||
|
||||
Bind();
|
||||
switch (target_) {
|
||||
@@ -761,13 +773,6 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
|
||||
}
|
||||
}
|
||||
|
||||
bool isPowerOf2(int n) {
|
||||
return n == 1 || (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
void OpenGLTexture::Finalize() {
|
||||
canWrap_ = !isPowerOf2(width_) || !isPowerOf2(height_);
|
||||
}
|
||||
|
||||
OpenGLInputLayout::~OpenGLInputLayout() {
|
||||
if (id_) {
|
||||
|
||||
@@ -589,8 +589,6 @@ public:
|
||||
}
|
||||
|
||||
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
|
||||
void Finalize() override {}
|
||||
void AutoGenMipmaps() override {}
|
||||
|
||||
VkImageView GetImageView() { return vkTex_->GetImageView(); }
|
||||
|
||||
@@ -602,7 +600,11 @@ private:
|
||||
height_ = desc.height;
|
||||
depth_ = desc.depth;
|
||||
vkTex_ = new VulkanTexture(vulkan_);
|
||||
// We don't actually do anything here.
|
||||
if (desc.initData.size()) {
|
||||
for (int i = 0; i < desc.initData.size(); i++) {
|
||||
this->SetImageData(0, 0, 0, width_, height_, depth_, i, 0, desc.initData[i]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -962,6 +964,9 @@ Texture *VKContext::CreateTexture(const TextureDesc &desc) {
|
||||
|
||||
void VKTexture::SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) {
|
||||
VkFormat vulkanFormat = DataFormatToVulkan(format_);
|
||||
if (stride == 0) {
|
||||
stride = width * DataFormatSizeInBytes(format_);
|
||||
}
|
||||
int bpp = GetBpp(vulkanFormat);
|
||||
int bytesPerPixel = bpp / 8;
|
||||
vkTex_->Create(width, height, vulkanFormat);
|
||||
|
||||
Reference in New Issue
Block a user