diff --git a/android/src/org/ppsspp/ppsspp/TextRenderer.java b/android/src/org/ppsspp/ppsspp/TextRenderer.java index 7ecdeb9a7f..6e753c8739 100644 --- a/android/src/org/ppsspp/ppsspp/TextRenderer.java +++ b/android/src/org/ppsspp/ppsspp/TextRenderer.java @@ -56,10 +56,15 @@ public class TextRenderer { total.y = (int) (p.descent() - p.ascent()) * lines.length + 2; // Returning a 0 size can create problems when the caller // uses the measurement to create a texture. + // Also, clamp to a reasonable maximum size. if (total.x < 1) total.x = 1; if (total.y < 1) total.y = 1; + if (total.x > 2048) + total.x = 2048; + if (total.y > 2048) + total.y = 2048; return total; } diff --git a/ext/native/gfx_es2/draw_text_android.cpp b/ext/native/gfx_es2/draw_text_android.cpp index 7059fab399..afb9bf6104 100644 --- a/ext/native/gfx_es2/draw_text_android.cpp +++ b/ext/native/gfx_es2/draw_text_android.cpp @@ -172,7 +172,8 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, if (iter != cache_.end()) { entry = iter->second.get(); entry->lastUsedFrame = frameCount_; - draw_->BindTexture(0, entry->texture); + if (entry->texture) + draw_->BindTexture(0, entry->texture); } else { double size = 0.0; auto iter = fontMap_.find(fontHash_); @@ -195,8 +196,10 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, env_->DeleteLocalRef(jstr); entry = new TextStringEntry(); - entry->bmWidth = entry->width = imageWidth; - entry->bmHeight = entry->height = imageHeight; + entry->bmWidth = imageWidth; + entry->width = imageWidth; + entry->bmHeight = imageHeight; + entry->height = imageHeight; entry->lastUsedFrame = frameCount_; TextureDesc desc{}; @@ -206,6 +209,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, desc.height = entry->bmHeight; desc.depth = 1; desc.mipLevels = 1; + desc.generateMips = false; desc.tag = "TextDrawer"; uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight]; @@ -224,13 +228,17 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, entry->texture = draw_->CreateTexture(desc); delete[] bitmapData; cache_[key] = std::unique_ptr(entry); - draw_->BindTexture(0, entry->texture); + if (entry->texture) { + draw_->BindTexture(0, entry->texture); + } } float w = entry->bmWidth * fontScaleX_ * dpiScale_; float h = entry->bmHeight * fontScaleY_ * dpiScale_; DrawBuffer::DoAlign(align, &x, &y, &w, &h); - target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color); - target.Flush(true); + if (entry->texture) { + target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color); + target.Flush(true); + } } void TextDrawerAndroid::ClearCache() { diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index f18b6129bc..fb36d8a3df 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -380,7 +380,9 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() { VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT }; VkResult res = vkBeginCommandBuffer(frameData.initCmd, &begin); - _assert_(res == VK_SUCCESS); + if (res != VK_SUCCESS) { + return VK_NULL_HANDLE; + } frameData.hasInitCommands = true; } return frameData_[curFrame].initCmd; diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 37d6497b51..41c94444b3 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -301,11 +301,9 @@ struct DescriptorSetKey { class VKTexture : public Texture { public: - VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc) - : vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) { - bool result = Create(cmd, pushBuffer, desc, alloc); - _assert_(result); - } + VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc) + : vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) {} + bool Create(VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc); ~VKTexture() { Destroy(); @@ -322,8 +320,6 @@ public: } private: - bool Create(VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc, VulkanDeviceAllocator *alloc); - void Destroy() { if (vkTex_) { vkTex_->Destroy(); @@ -335,9 +331,9 @@ private: VulkanContext *vulkan_; VulkanTexture *vkTex_ = nullptr; - int mipLevels_; + int mipLevels_ = 0; - DataFormat format_; + DataFormat format_ = DataFormat::UNDEFINED; }; class VKFramebuffer; @@ -698,6 +694,10 @@ enum class TextureState { bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const TextureDesc &desc, VulkanDeviceAllocator *alloc) { // Zero-sized textures not allowed. _assert_(desc.width * desc.height * desc.depth > 0); // remember to set depth to 1! + if (desc.width * desc.height * desc.depth <= 0) { + ELOG("Bad texture dimensions %dx%dx%d", desc.width, desc.height, desc.depth); + return false; + } _assert_(push); format_ = desc.format; mipLevels_ = desc.mipLevels; @@ -1079,12 +1079,20 @@ InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) { } Texture *VKContext::CreateTexture(const TextureDesc &desc) { - if (!push_ || !renderManager_.GetInitCmd()) { + VkCommandBuffer initCmd = renderManager_.GetInitCmd(); + if (!push_ || !initCmd) { // Too early! Fail. ELOG("Can't create textures before the first frame has started."); return nullptr; } - return new VKTexture(vulkan_, renderManager_.GetInitCmd(), push_, desc, allocator_); + VKTexture *tex = new VKTexture(vulkan_, initCmd, push_, desc); + if (tex->Create(initCmd, push_, desc, allocator_)) { + return tex; + } else { + ELOG("Failed to create texture"); + delete tex; + return nullptr; + } } static inline void CopySide(VkStencilOpState &dest, const StencilSide &src) {