mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-23 16:19:44 +00:00
Break out image file management from DrawContext (thin3d)
This commit is contained in:
parent
4199eb3493
commit
6a7d3a3910
@ -187,7 +187,7 @@ 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(0);
|
||||
fbTex->Finalize();
|
||||
|
||||
float x, y, w, h;
|
||||
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "Core/Util/GameManager.h"
|
||||
#include "Core/Config.h"
|
||||
#include "UI/GameInfoCache.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
GameInfoCache *g_gameInfoCache;
|
||||
|
||||
@ -781,11 +782,11 @@ again:
|
||||
return info;
|
||||
}
|
||||
|
||||
void GameInfoCache::SetupTexture(GameInfo *info, std::string &textureData, Draw::DrawContext *thin3d, Draw::Texture *&tex, double &loadTime) {
|
||||
void GameInfoCache::SetupTexture(GameInfo *info, std::string &textureData, Draw::DrawContext *thin3d, ManagedTexture *&tex, double &loadTime) {
|
||||
using namespace Draw;
|
||||
if (textureData.size()) {
|
||||
if (!tex) {
|
||||
tex = thin3d->CreateTextureFromFileData((const uint8_t *)textureData.data(), (int)textureData.size(), ImageFileType::DETECT);
|
||||
tex = CreateTextureFromFileData(thin3d, (const uint8_t *)textureData.data(), (int)textureData.size(), ImageFileType::DETECT);
|
||||
if (tex) {
|
||||
loadTime = time_now_d();
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "file/file_util.h"
|
||||
#include "Core/ELF/ParamSFO.h"
|
||||
#include "Core/Loaders.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
namespace Draw {
|
||||
class DrawContext;
|
||||
@ -142,11 +143,11 @@ public:
|
||||
|
||||
// Pre read the data, create a texture the next time (GL thread..)
|
||||
std::string iconTextureData;
|
||||
Draw::Texture *iconTexture;
|
||||
ManagedTexture *iconTexture;
|
||||
std::string pic0TextureData;
|
||||
Draw::Texture *pic0Texture;
|
||||
ManagedTexture *pic0Texture;
|
||||
std::string pic1TextureData;
|
||||
Draw::Texture *pic1Texture;
|
||||
ManagedTexture *pic1Texture;
|
||||
|
||||
std::string sndFileData;
|
||||
|
||||
@ -202,7 +203,7 @@ public:
|
||||
private:
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void SetupTexture(GameInfo *info, std::string &textureData, Draw::DrawContext *thin3d, Draw::Texture *&tex, double &loadTime);
|
||||
void SetupTexture(GameInfo *info, std::string &textureData, Draw::DrawContext *thin3d, ManagedTexture *&tex, double &loadTime);
|
||||
|
||||
// Maps ISO path to info.
|
||||
std::map<std::string, GameInfo *> info_;
|
||||
|
@ -192,7 +192,7 @@ void GameScreen::update(InputState &input) {
|
||||
if (tvTitle_)
|
||||
tvTitle_->SetText(info->GetTitle() + " (" + info->id + ")");
|
||||
if (info->iconTexture && texvGameIcon_) {
|
||||
texvGameIcon_->SetTexture(info->iconTexture);
|
||||
texvGameIcon_->SetTexture(info->iconTexture->GetTexture());
|
||||
// Fade the icon with the background.
|
||||
double loadTime = info->timeIconWasLoaded;
|
||||
if (info->pic1Texture) {
|
||||
|
@ -179,7 +179,7 @@ void GameButton::Draw(UIContext &dc) {
|
||||
using namespace UI;
|
||||
|
||||
if (ginfo->iconTexture) {
|
||||
texture = ginfo->iconTexture;
|
||||
texture = ginfo->iconTexture->GetTexture();
|
||||
}
|
||||
|
||||
int x = bounds_.x;
|
||||
@ -1013,9 +1013,9 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, f
|
||||
}
|
||||
|
||||
if (ginfo->pic1Texture) {
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic1Texture);
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic1Texture->GetTexture());
|
||||
} else if (ginfo->pic0Texture) {
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic0Texture);
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic0Texture->GetTexture());
|
||||
}
|
||||
|
||||
uint32_t color = whiteAlpha(ease(progress)) & 0xFFc0c0c0;
|
||||
|
@ -110,11 +110,11 @@ void DrawGameBackground(UIContext &dc, const std::string &gamePath) {
|
||||
bool hasPic = false;
|
||||
double loadTime;
|
||||
if (ginfo->pic1Texture) {
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic1Texture);
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic1Texture->GetTexture());
|
||||
loadTime = ginfo->timePic1WasLoaded;
|
||||
hasPic = true;
|
||||
} else if (ginfo->pic0Texture) {
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic0Texture);
|
||||
dc.GetThin3DContext()->BindTexture(0, ginfo->pic0Texture->GetTexture());
|
||||
loadTime = ginfo->timePic0WasLoaded;
|
||||
hasPic = true;
|
||||
}
|
||||
|
@ -90,6 +90,7 @@
|
||||
#include "UI/MiscScreens.h"
|
||||
#include "UI/TiltEventProcessor.h"
|
||||
#include "UI/BackgroundAudio.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
#include "Common/KeyMap.h"
|
||||
@ -117,7 +118,7 @@ static UI::Theme ui_theme;
|
||||
#include "android/android-ndk-profiler/prof.h"
|
||||
#endif
|
||||
|
||||
Draw::Texture *uiTexture;
|
||||
ManagedTexture *uiTexture;
|
||||
|
||||
ScreenManager *screenManager;
|
||||
std::string config_filename;
|
||||
@ -578,7 +579,7 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
ui_theme.popupTitle.fgColor = 0xFF59BEE3;
|
||||
#endif
|
||||
|
||||
uiTexture = thin3d->CreateTextureFromFile("ui_atlas.zim", ImageFileType::ZIM);
|
||||
uiTexture = CreateTextureFromFile(thin3d, "ui_atlas.zim", ImageFileType::ZIM);
|
||||
if (!uiTexture) {
|
||||
PanicAlert("Failed to load ui_atlas.zim.\n\nPlace it in the directory \"assets\" under your PPSSPP directory.");
|
||||
ELOG("Failed to load ui_atlas.zim");
|
||||
@ -618,7 +619,7 @@ void NativeInitGraphics(GraphicsContext *graphicsContext) {
|
||||
ui_draw2d.Init(thin3d, texColorPipeline);
|
||||
ui_draw2d_front.Init(thin3d, texColorPipeline);
|
||||
|
||||
uiContext->Init(thin3d, texColorPipeline, colorPipeline, uiTexture, &ui_draw2d, &ui_draw2d_front);
|
||||
uiContext->Init(thin3d, texColorPipeline, colorPipeline, &ui_draw2d, &ui_draw2d_front);
|
||||
RasterStateDesc desc;
|
||||
desc.cull = CullMode::NONE;
|
||||
desc.frontFace = Facing::CCW;
|
||||
@ -648,9 +649,8 @@ void NativeShutdownGraphics() {
|
||||
delete g_gameInfoCache;
|
||||
g_gameInfoCache = nullptr;
|
||||
|
||||
if (uiTexture->Release()) {
|
||||
uiTexture = nullptr;
|
||||
}
|
||||
delete uiTexture;
|
||||
uiTexture = nullptr;
|
||||
|
||||
delete uiContext;
|
||||
uiContext = NULL;
|
||||
@ -737,6 +737,8 @@ void DrawDownloadsOverlay(UIContext &dc) {
|
||||
|
||||
void NativeRender(GraphicsContext *graphicsContext) {
|
||||
g_GameManager.Update();
|
||||
// If uitexture gets reloaded, make sure we use the latest one.
|
||||
uiContext->FrameSetup(uiTexture->GetTexture());
|
||||
|
||||
float xres = dp_xres;
|
||||
float yres = dp_yres;
|
||||
|
@ -69,7 +69,7 @@ void AsyncImageFileView::SetFilename(std::string filename) {
|
||||
textureFailed_ = false;
|
||||
filename_ = filename;
|
||||
if (texture_) {
|
||||
texture_->Release();
|
||||
delete texture_;
|
||||
texture_ = nullptr;
|
||||
}
|
||||
}
|
||||
@ -78,11 +78,11 @@ void AsyncImageFileView::SetFilename(std::string filename) {
|
||||
void AsyncImageFileView::Draw(UIContext &dc) {
|
||||
using namespace Draw;
|
||||
if (!texture_ && !textureFailed_ && !filename_.empty()) {
|
||||
texture_ = dc.GetThin3DContext()->CreateTextureFromFile(filename_.c_str(), DETECT);
|
||||
texture_ = CreateTextureFromFile(dc.GetThin3DContext(), filename_.c_str(), DETECT);
|
||||
if (!texture_)
|
||||
textureFailed_ = true;
|
||||
else if (textureAutoGen_)
|
||||
texture_->AutoGenMipmaps();
|
||||
else if (textureAutoGen_) // TODO: Iffy
|
||||
texture_->GetTexture()->AutoGenMipmaps();
|
||||
}
|
||||
|
||||
if (HasFocus()) {
|
||||
@ -92,7 +92,7 @@ void AsyncImageFileView::Draw(UIContext &dc) {
|
||||
// TODO: involve sizemode
|
||||
if (texture_) {
|
||||
dc.Flush();
|
||||
dc.GetThin3DContext()->BindTexture(0, texture_);
|
||||
dc.GetThin3DContext()->BindTexture(0, texture_->GetTexture());
|
||||
dc.Draw()->Rect(bounds_.x, bounds_.y, bounds_.w, bounds_.h, color_);
|
||||
dc.Flush();
|
||||
dc.RebindTexture();
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "ui/ui_screen.h"
|
||||
#include "ui/viewgroup.h"
|
||||
#include "UI/MiscScreens.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
class GamePauseScreen : public UIDialogScreenWithGameBackground {
|
||||
public:
|
||||
@ -95,7 +96,7 @@ private:
|
||||
uint32_t color_;
|
||||
UI::ImageSizeMode sizeMode_;
|
||||
|
||||
Draw::Texture *texture_;
|
||||
ManagedTexture *texture_;
|
||||
bool textureFailed_;
|
||||
bool textureAutoGen_;
|
||||
float fixedSizeW_;
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
std::string savedata_title = ginfo->paramSFO.GetValueString("SAVEDATA_TITLE");
|
||||
|
||||
if (ginfo->iconTexture) {
|
||||
toprow->Add(new Thin3DTextureView(ginfo->iconTexture, IS_FIXED, new LinearLayoutParams(Margins(10, 5))));
|
||||
toprow->Add(new Thin3DTextureView(ginfo->iconTexture->GetTexture(), IS_FIXED, new LinearLayoutParams(Margins(10, 5))));
|
||||
}
|
||||
LinearLayout *topright = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1.0f));
|
||||
topright->SetSpacing(1.0f);
|
||||
@ -159,7 +159,7 @@ void SavedataButton::Draw(UIContext &dc) {
|
||||
using namespace UI;
|
||||
|
||||
if (ginfo->iconTexture) {
|
||||
texture = ginfo->iconTexture;
|
||||
texture = ginfo->iconTexture->GetTexture();
|
||||
}
|
||||
|
||||
int x = bounds_.x;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "Core/Util/GameManager.h"
|
||||
#include "UI/EmuScreen.h"
|
||||
#include "UI/Store.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
const std::string storeBaseUrl = "http://store.ppsspp.org/";
|
||||
|
||||
@ -84,7 +85,7 @@ private:
|
||||
std::shared_ptr<http::Download> download_;
|
||||
|
||||
std::string textureData_;
|
||||
Draw::Texture *texture_;
|
||||
ManagedTexture *texture_;
|
||||
bool textureFailed_;
|
||||
float fixedSizeW_;
|
||||
float fixedSizeH_;
|
||||
@ -116,7 +117,7 @@ void HttpImageFileView::SetFilename(std::string filename) {
|
||||
textureFailed_ = false;
|
||||
path_ = filename;
|
||||
if (texture_) {
|
||||
texture_->Release();
|
||||
delete texture_;
|
||||
texture_ = nullptr;
|
||||
}
|
||||
}
|
||||
@ -142,7 +143,7 @@ void HttpImageFileView::Draw(UIContext &dc) {
|
||||
}
|
||||
|
||||
if (!textureData_.empty()) {
|
||||
texture_ = dc.GetThin3DContext()->CreateTextureFromFileData((const uint8_t *)(textureData_.data()), (int)textureData_.size(), DETECT);
|
||||
texture_ = CreateTextureFromFileData(dc.GetThin3DContext(), (const uint8_t *)(textureData_.data()), (int)textureData_.size(), DETECT);
|
||||
if (!texture_)
|
||||
textureFailed_ = true;
|
||||
textureData_.clear();
|
||||
@ -156,7 +157,7 @@ void HttpImageFileView::Draw(UIContext &dc) {
|
||||
// TODO: involve sizemode
|
||||
if (texture_) {
|
||||
dc.Flush();
|
||||
dc.GetThin3DContext()->BindTexture(0, texture_);
|
||||
dc.GetThin3DContext()->BindTexture(0, texture_->GetTexture());
|
||||
dc.Draw()->Rect(bounds_.x, bounds_.y, bounds_.w, bounds_.h, color_);
|
||||
dc.Flush();
|
||||
dc.RebindTexture();
|
||||
|
142
UI/TextureUtil.cpp
Normal file
142
UI/TextureUtil.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
#include "thin3d/thin3d.h"
|
||||
#include "image/zim_load.h"
|
||||
#include "image/png_load.h"
|
||||
#include "file/vfs.h"
|
||||
#include "ext/jpge/jpgd.h"
|
||||
#include "UI/TextureUtil.h"
|
||||
|
||||
static Draw::DataFormat ZimToT3DFormat(int zim) {
|
||||
switch (zim) {
|
||||
case ZIM_ETC1: return Draw::DataFormat::ETC1;
|
||||
case ZIM_RGBA8888: return Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
case ZIM_LUMINANCE: return Draw::DataFormat::R8_UNORM;
|
||||
default: return Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static ImageFileType DetectImageFileType(const uint8_t *data, size_t size) {
|
||||
if (!memcmp(data, "ZIMG", 4)) {
|
||||
return ZIM;
|
||||
}
|
||||
else if (!memcmp(data, "\x89\x50\x4E\x47", 4)) {
|
||||
return PNG;
|
||||
}
|
||||
else if (!memcmp(data, "\xff\xd8\xff\xe0", 4)) {
|
||||
return JPEG;
|
||||
}
|
||||
else {
|
||||
return TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static bool LoadTextureLevels(const uint8_t *data, size_t size, ImageFileType type, int width[16], int height[16], int *num_levels, Draw::DataFormat *fmt, uint8_t *image[16], int *zim_flags) {
|
||||
if (type == DETECT) {
|
||||
type = DetectImageFileType(data, size);
|
||||
}
|
||||
if (type == TYPE_UNKNOWN) {
|
||||
ELOG("File has unknown format");
|
||||
return false;
|
||||
}
|
||||
|
||||
*num_levels = 0;
|
||||
*zim_flags = 0;
|
||||
|
||||
switch (type) {
|
||||
case ZIM:
|
||||
{
|
||||
*num_levels = LoadZIMPtr((const uint8_t *)data, size, width, height, zim_flags, image);
|
||||
*fmt = ZimToT3DFormat(*zim_flags & ZIM_FORMAT_MASK);
|
||||
}
|
||||
break;
|
||||
|
||||
case PNG:
|
||||
if (1 == pngLoadPtr((const unsigned char *)data, size, &width[0], &height[0], &image[0], false)) {
|
||||
*num_levels = 1;
|
||||
*fmt = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
break;
|
||||
|
||||
case JPEG:
|
||||
{
|
||||
int actual_components = 0;
|
||||
unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(data, (int)size, &width[0], &height[0], &actual_components, 4);
|
||||
if (jpegBuf) {
|
||||
*num_levels = 1;
|
||||
*fmt = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
image[0] = (uint8_t *)jpegBuf;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ELOG("Unknown image format");
|
||||
return false;
|
||||
}
|
||||
|
||||
return *num_levels > 0;
|
||||
}
|
||||
|
||||
bool ManagedTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, ImageFileType type) {
|
||||
int width[16], height[16];
|
||||
uint8_t *image[16] = { nullptr };
|
||||
|
||||
int num_levels;
|
||||
int zim_flags;
|
||||
Draw::DataFormat fmt;
|
||||
|
||||
if (!LoadTextureLevels(data, dataSize, type, width, height, &num_levels, &fmt, image, &zim_flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_levels < 0 || num_levels >= 16) {
|
||||
ELOG("Invalid num_levels: %d. Falling back to one. Image: %dx%d", num_levels, width[0], height[0]);
|
||||
num_levels = 1;
|
||||
}
|
||||
texture_->Create(Draw::LINEAR2D, fmt, width[0], height[0], 1, num_levels);
|
||||
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]);
|
||||
free(image[i]);
|
||||
}
|
||||
else {
|
||||
ELOG("Missing image level %i", i);
|
||||
}
|
||||
}
|
||||
|
||||
texture_->Finalize();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ManagedTexture::LoadFromFile(const std::string &filename, ImageFileType type) {
|
||||
filename_ = "";
|
||||
size_t fileSize;
|
||||
uint8_t *buffer = VFSReadFile(filename.c_str(), &fileSize);
|
||||
if (!buffer) {
|
||||
return false;
|
||||
}
|
||||
bool retval = LoadFromFileData(buffer, fileSize, type);
|
||||
if (retval) {
|
||||
filename_ = filename;
|
||||
}
|
||||
else {
|
||||
ELOG("%s: Failed to load texture %s", __FUNCTION__, filename.c_str());
|
||||
}
|
||||
delete[] buffer;
|
||||
return retval;
|
||||
}
|
||||
|
||||
ManagedTexture *CreateTextureFromFile(Draw::DrawContext *draw, const char *filename, ImageFileType type) {
|
||||
ManagedTexture *mtex = new ManagedTexture(draw);
|
||||
if (!mtex->LoadFromFile(filename, type)) {
|
||||
delete mtex;
|
||||
return nullptr;
|
||||
}
|
||||
return mtex;
|
||||
}
|
||||
|
||||
// TODO: Remove the code duplication between this and LoadFromFileData
|
||||
ManagedTexture *CreateTextureFromFileData(Draw::DrawContext *draw, const uint8_t *data, int size, ImageFileType type) {
|
||||
ManagedTexture *mtex = new ManagedTexture(draw);
|
||||
mtex->LoadFromFileData(data, size, type);
|
||||
return mtex;
|
||||
}
|
54
UI/TextureUtil.h
Normal file
54
UI/TextureUtil.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "thin3d/thin3d.h"
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
|
||||
enum ImageFileType {
|
||||
PNG,
|
||||
JPEG,
|
||||
ZIM,
|
||||
DETECT,
|
||||
TYPE_UNKNOWN,
|
||||
};
|
||||
|
||||
class ManagedTexture : public GfxResourceHolder {
|
||||
public:
|
||||
ManagedTexture(Draw::DrawContext *draw) : draw_(draw) {
|
||||
register_gl_resource_holder(this);
|
||||
texture_ = draw->CreateTexture();
|
||||
}
|
||||
~ManagedTexture() {
|
||||
unregister_gl_resource_holder(this);
|
||||
}
|
||||
void GLLost() override {
|
||||
delete texture_;
|
||||
}
|
||||
void GLRestore() override {
|
||||
if (!filename_.empty()) {
|
||||
if (LoadFromFile(filename_.c_str())) {
|
||||
ILOG("Reloaded lost texture %s", filename_.c_str());
|
||||
}
|
||||
else {
|
||||
ELOG("Failed to reload lost texture %s", filename_.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
WLOG("Texture cannot be restored - has no filename");
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadFromFile(const std::string &filename, ImageFileType type = ImageFileType::DETECT);
|
||||
bool LoadFromFileData(const uint8_t *data, size_t dataSize, ImageFileType type = ImageFileType::DETECT);
|
||||
Draw::Texture *GetTexture() { return texture_; } // For immediate use, don't store.
|
||||
int Width() const { return texture_->Width(); }
|
||||
int Height() const { return texture_->Height(); }
|
||||
|
||||
private:
|
||||
Draw::Texture *texture_;
|
||||
Draw::DrawContext *draw_;
|
||||
std::string filename_; // Textures that are loaded from files can reload themselves automatically.
|
||||
};
|
||||
|
||||
// Common Thin3D function, uses CreateTexture
|
||||
ManagedTexture *CreateTextureFromFile(Draw::DrawContext *draw, const char *filename, ImageFileType fileType);
|
||||
ManagedTexture *CreateTextureFromFileData(Draw::DrawContext *draw, const uint8_t *data, int size, ImageFileType fileType);
|
@ -41,6 +41,7 @@
|
||||
<ClCompile Include="ReportScreen.cpp" />
|
||||
<ClCompile Include="SavedataScreen.cpp" />
|
||||
<ClCompile Include="Store.cpp" />
|
||||
<ClCompile Include="TextureUtil.cpp" />
|
||||
<ClCompile Include="TiltAnalogSettingsScreen.cpp" />
|
||||
<ClCompile Include="TiltEventProcessor.cpp" />
|
||||
<ClCompile Include="TouchControlLayoutScreen.cpp" />
|
||||
@ -71,6 +72,7 @@
|
||||
<ClInclude Include="ReportScreen.h" />
|
||||
<ClInclude Include="SavedataScreen.h" />
|
||||
<ClInclude Include="Store.h" />
|
||||
<ClInclude Include="TextureUtil.h" />
|
||||
<ClInclude Include="TiltAnalogSettingsScreen.h" />
|
||||
<ClInclude Include="TiltEventProcessor.h" />
|
||||
<ClInclude Include="TouchControlLayoutScreen.h" />
|
||||
@ -125,7 +127,6 @@
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
|
@ -69,6 +69,7 @@
|
||||
<ClCompile Include="RemoteISOScreen.cpp">
|
||||
<Filter>Screens</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TextureUtil.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="GameInfoCache.h" />
|
||||
@ -139,10 +140,11 @@
|
||||
<ClInclude Include="RemoteISOScreen.h">
|
||||
<Filter>Screens</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TextureUtil.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Screens">
|
||||
<UniqueIdentifier>{faee5dce-633b-4ba6-b19d-ea70ee3c1c38}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -290,7 +290,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
|
||||
}
|
||||
}
|
||||
entry->texture->SetImageData(0, 0, 0, entry->bmWidth, entry->bmHeight, 1, 0, entry->bmWidth * 2, (const uint8_t *)bitmapData);
|
||||
entry->texture->Finalize(0);
|
||||
entry->texture->Finalize();
|
||||
delete [] bitmapData;
|
||||
|
||||
cache_[entryHash] = std::unique_ptr<TextStringEntry>(entry);
|
||||
|
@ -2,10 +2,6 @@
|
||||
#include <thin3d/thin3d.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "image/zim_load.h"
|
||||
#include "image/png_load.h"
|
||||
#include "file/vfs.h"
|
||||
#include "ext/jpge/jpgd.h"
|
||||
|
||||
namespace Draw {
|
||||
|
||||
@ -211,151 +207,4 @@ DrawContext::~DrawContext() {
|
||||
}
|
||||
}
|
||||
|
||||
static DataFormat ZimToT3DFormat(int zim) {
|
||||
switch (zim) {
|
||||
case ZIM_ETC1: return DataFormat::ETC1;
|
||||
case ZIM_RGBA8888: return DataFormat::R8G8B8A8_UNORM;
|
||||
case ZIM_LUMINANCE: return DataFormat::R8_UNORM;
|
||||
default: return DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static ImageFileType DetectImageFileType(const uint8_t *data, size_t size) {
|
||||
if (!memcmp(data, "ZIMG", 4)) {
|
||||
return ZIM;
|
||||
} else if (!memcmp(data, "\x89\x50\x4E\x47", 4)) {
|
||||
return PNG;
|
||||
} else if (!memcmp(data, "\xff\xd8\xff\xe0", 4)) {
|
||||
return JPEG;
|
||||
} else {
|
||||
return TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static bool LoadTextureLevels(const uint8_t *data, size_t size, ImageFileType type, int width[16], int height[16], int *num_levels, DataFormat *fmt, uint8_t *image[16], int *zim_flags) {
|
||||
if (type == DETECT) {
|
||||
type = DetectImageFileType(data, size);
|
||||
}
|
||||
if (type == TYPE_UNKNOWN) {
|
||||
ELOG("File has unknown format");
|
||||
return false;
|
||||
}
|
||||
|
||||
*num_levels = 0;
|
||||
*zim_flags = 0;
|
||||
|
||||
switch (type) {
|
||||
case ZIM:
|
||||
{
|
||||
*num_levels = LoadZIMPtr((const uint8_t *)data, size, width, height, zim_flags, image);
|
||||
*fmt = ZimToT3DFormat(*zim_flags & ZIM_FORMAT_MASK);
|
||||
}
|
||||
break;
|
||||
|
||||
case PNG:
|
||||
if (1 == pngLoadPtr((const unsigned char *)data, size, &width[0], &height[0], &image[0], false)) {
|
||||
*num_levels = 1;
|
||||
*fmt = DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
break;
|
||||
|
||||
case JPEG:
|
||||
{
|
||||
int actual_components = 0;
|
||||
unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(data, (int)size, &width[0], &height[0], &actual_components, 4);
|
||||
if (jpegBuf) {
|
||||
*num_levels = 1;
|
||||
*fmt = DataFormat::R8G8B8A8_UNORM;
|
||||
image[0] = (uint8_t *)jpegBuf;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ELOG("Unknown image format");
|
||||
return false;
|
||||
}
|
||||
|
||||
return *num_levels > 0;
|
||||
}
|
||||
|
||||
bool Texture::LoadFromFileData(const uint8_t *data, size_t dataSize, ImageFileType type) {
|
||||
int width[16], height[16];
|
||||
uint8_t *image[16] = { nullptr };
|
||||
|
||||
int num_levels;
|
||||
int zim_flags;
|
||||
DataFormat fmt;
|
||||
|
||||
if (!LoadTextureLevels(data, dataSize, type, width, height, &num_levels, &fmt, image, &zim_flags)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_levels < 0 || num_levels >= 16) {
|
||||
ELOG("Invalid num_levels: %d. Falling back to one. Image: %dx%d", num_levels, width[0], height[0]);
|
||||
num_levels = 1;
|
||||
}
|
||||
|
||||
Create(LINEAR2D, fmt, width[0], height[0], 1, num_levels);
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
if (image[i]) {
|
||||
SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]);
|
||||
free(image[i]);
|
||||
} else {
|
||||
ELOG("Missing image level %i", i);
|
||||
}
|
||||
}
|
||||
|
||||
Finalize(zim_flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Texture::LoadFromFile(const std::string &filename, ImageFileType type) {
|
||||
filename_ = "";
|
||||
size_t fileSize;
|
||||
uint8_t *buffer = VFSReadFile(filename.c_str(), &fileSize);
|
||||
if (!buffer) {
|
||||
return false;
|
||||
}
|
||||
bool retval = LoadFromFileData(buffer, fileSize, type);
|
||||
if (retval) {
|
||||
filename_ = filename;
|
||||
} else {
|
||||
ELOG("%s: Failed to load texture %s", __FUNCTION__, filename.c_str());
|
||||
}
|
||||
delete[] buffer;
|
||||
return retval;
|
||||
}
|
||||
|
||||
Texture *DrawContext::CreateTextureFromFile(const char *filename, ImageFileType type) {
|
||||
Texture *tex = CreateTexture();
|
||||
if (!tex->LoadFromFile(filename, type)) {
|
||||
tex->Release();
|
||||
return NULL;
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
|
||||
// TODO: Remove the code duplication between this and LoadFromFileData
|
||||
Texture *DrawContext::CreateTextureFromFileData(const uint8_t *data, int size, ImageFileType type) {
|
||||
int width[16], height[16];
|
||||
int num_levels = 0;
|
||||
int zim_flags = 0;
|
||||
DataFormat fmt;
|
||||
uint8_t *image[16] = { nullptr };
|
||||
|
||||
if (!LoadTextureLevels(data, size, type, width, height, &num_levels, &fmt, image, &zim_flags)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Texture *tex = CreateTexture(LINEAR2D, fmt, width[0], height[0], 1, num_levels);
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
tex->SetImageData(0, 0, 0, width[i], height[i], 1, i, width[i] * 4, image[i]);
|
||||
free(image[i]);
|
||||
}
|
||||
|
||||
tex->Finalize(zim_flags);
|
||||
return tex;
|
||||
}
|
||||
|
||||
} // namespace Draw
|
@ -281,14 +281,6 @@ enum class ShaderLanguage {
|
||||
METAL_BYTECODE = 1024,
|
||||
};
|
||||
|
||||
enum ImageFileType {
|
||||
PNG,
|
||||
JPEG,
|
||||
ZIM,
|
||||
DETECT,
|
||||
TYPE_UNKNOWN,
|
||||
};
|
||||
|
||||
enum InfoField {
|
||||
APINAME,
|
||||
APIVERSION,
|
||||
@ -340,19 +332,15 @@ public:
|
||||
|
||||
class Texture : public RefCountedObject {
|
||||
public:
|
||||
bool LoadFromFile(const std::string &filename, ImageFileType type = ImageFileType::DETECT);
|
||||
bool LoadFromFileData(const uint8_t *data, size_t dataSize, ImageFileType type = ImageFileType::DETECT);
|
||||
|
||||
virtual bool Create(TextureType type, DataFormat format, int width, int height, int depth, int mipLevels) = 0;
|
||||
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(int zim_flags) = 0; // TODO: Tidy up
|
||||
virtual void Finalize() = 0; // TODO: Tidy up
|
||||
|
||||
int Width() { return width_; }
|
||||
int Height() { return height_; }
|
||||
int Depth() { return depth_; }
|
||||
protected:
|
||||
std::string filename_; // Textures that are loaded from files can reload themselves automatically.
|
||||
int width_, height_, depth_;
|
||||
};
|
||||
|
||||
@ -497,10 +485,6 @@ public:
|
||||
// virtual ComputePipeline CreateComputePipeline(const ComputePipelineDesc &desc) = 0
|
||||
virtual InputLayout *CreateInputLayout(const InputLayoutDesc &desc) = 0;
|
||||
|
||||
// Common Thin3D function, uses CreateTexture
|
||||
Texture *CreateTextureFromFile(const char *filename, ImageFileType fileType);
|
||||
Texture *CreateTextureFromFileData(const uint8_t *data, int size, ImageFileType fileType);
|
||||
|
||||
// Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them.
|
||||
ShaderModule *GetVshaderPreset(VertexShaderPreset preset) { return fsPresets_[preset]; }
|
||||
ShaderModule *GetFshaderPreset(FragmentShaderPreset preset) { return vsPresets_[preset]; }
|
||||
|
@ -6,6 +6,10 @@ namespace Draw {
|
||||
|
||||
#if 0
|
||||
|
||||
// A problem is that we can't get the D3Dcompiler.dll without using a later SDK than 7.1, which was the last that
|
||||
// supported XP. A possible solution might be here:
|
||||
// https://tedwvc.wordpress.com/2014/01/01/how-to-target-xp-with-vc2012-or-vc2013-and-continue-to-use-the-windows-8-x-sdk/
|
||||
|
||||
class D3D11Pipeline;
|
||||
|
||||
class D3D11DrawContext : public DrawContext {
|
||||
@ -308,7 +312,7 @@ public:
|
||||
std::vector<uint8_t> byteCode_;
|
||||
};
|
||||
|
||||
ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize) {
|
||||
ShaderModule *D3D11DrawContext::CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize) {
|
||||
// ...
|
||||
|
||||
return nullptr;
|
||||
@ -371,6 +375,22 @@ void D3D11DrawContext::ApplyCurrentState() {
|
||||
}
|
||||
}
|
||||
|
||||
class D3D11Buffer : public Buffer {
|
||||
public:
|
||||
ID3D11Buffer *buf;
|
||||
|
||||
virtual void SetData(const uint8_t *data, size_t size) override {
|
||||
|
||||
}
|
||||
virtual void SubData(const uint8_t *data, size_t offset, size_t size) override {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Buffer *D3D11DrawContext::CreateBuffer(size_t size, uint32_t usageFlags) {
|
||||
D3D11Buffer *b = new D3D11Buffer();
|
||||
}
|
||||
|
||||
void D3D11DrawContext::Draw(Buffer *vdata, int vertexCount, int offset) {
|
||||
ApplyCurrentState();
|
||||
}
|
||||
|
@ -359,7 +359,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 SetToSampler(LPDIRECT3DDEVICE9 device, int sampler);
|
||||
void Finalize(int zim_flags) override {}
|
||||
void Finalize() override {}
|
||||
|
||||
private:
|
||||
LPDIRECT3DDEVICE9 device_;
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <map>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "image/zim_load.h"
|
||||
#include "math/dataconv.h"
|
||||
#include "math/lin/matrix4x4.h"
|
||||
#include "thin3d/thin3d.h"
|
||||
@ -542,7 +541,7 @@ public:
|
||||
}
|
||||
|
||||
void SetViewports(int count, Viewport *viewports) override {
|
||||
// TODO: Add support for multiple viewports.
|
||||
// TODO: Use glViewportArrayv.
|
||||
glViewport(viewports[0].TopLeftX, viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height);
|
||||
#if defined(USING_GLES2)
|
||||
glDepthRangef(viewports[0].MinDepth, viewports[0].MaxDepth);
|
||||
@ -702,20 +701,9 @@ public:
|
||||
}
|
||||
|
||||
void GLRestore() override {
|
||||
if (!filename_.empty()) {
|
||||
if (LoadFromFile(filename_.c_str())) {
|
||||
ILOG("Reloaded lost texture %s", filename_.c_str());
|
||||
} else {
|
||||
ELOG("Failed to reload lost texture %s", filename_.c_str());
|
||||
tex_ = 0;
|
||||
}
|
||||
} else {
|
||||
WLOG("Texture %p cannot be restored - has no filename", this);
|
||||
tex_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Finalize(int zim_flags) override;
|
||||
void Finalize() override;
|
||||
|
||||
private:
|
||||
GLuint tex_;
|
||||
@ -784,11 +772,10 @@ bool isPowerOf2(int n) {
|
||||
return n == 1 || (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
void Thin3DGLTexture::Finalize(int zim_flags) {
|
||||
canWrap_ = (zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_);
|
||||
void Thin3DGLTexture::Finalize() {
|
||||
canWrap_ = !isPowerOf2(width_) || !isPowerOf2(height_);
|
||||
}
|
||||
|
||||
|
||||
OpenGLInputLayout::~OpenGLInputLayout() {
|
||||
if (id_) {
|
||||
glDeleteVertexArrays(1, &id_);
|
||||
|
@ -588,7 +588,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 Finalize(int zim_flags) override;
|
||||
void Finalize() override {}
|
||||
void AutoGenMipmaps() override {}
|
||||
|
||||
VkImageView GetImageView() { return vkTex_->GetImageView(); }
|
||||
@ -965,10 +965,6 @@ void VKTexture::SetImageData(int x, int y, int z, int width, int height, int dep
|
||||
vkTex_->Unlock();
|
||||
}
|
||||
|
||||
void VKTexture::Finalize(int zim_flags) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
inline void CopySide(VkStencilOpState &dest, const StencilSide &src) {
|
||||
dest.compareMask = src.compareMask;
|
||||
dest.reference = src.reference;
|
||||
|
@ -18,13 +18,12 @@ UIContext::~UIContext() {
|
||||
delete textDrawer_;
|
||||
}
|
||||
|
||||
void UIContext::Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pipeline *uipipenotex, Draw::Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) {
|
||||
void UIContext::Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pipeline *uipipenotex, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) {
|
||||
using namespace Draw;
|
||||
thin3d_ = thin3d;
|
||||
sampler_ = thin3d_->CreateSamplerState({ TextureFilter::LINEAR, TextureFilter::LINEAR, TextureFilter::LINEAR });
|
||||
ui_pipeline_ = uipipe;
|
||||
ui_pipeline_notex_ = uipipenotex;
|
||||
uitexture_ = uitexture;
|
||||
uidrawbuffer_ = uidrawbuffer;
|
||||
uidrawbufferTop_ = uidrawbufferTop;
|
||||
#if defined(_WIN32) || defined(USING_QT_UI)
|
||||
@ -34,6 +33,10 @@ void UIContext::Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pi
|
||||
#endif
|
||||
}
|
||||
|
||||
void UIContext::FrameSetup(Draw::Texture *uiTexture) {
|
||||
uitexture_ = uiTexture;
|
||||
}
|
||||
|
||||
void UIContext::Begin() {
|
||||
thin3d_->BindSamplerStates(0, 1, &sampler_);
|
||||
thin3d_->BindTexture(0, uitexture_);
|
||||
|
@ -36,7 +36,9 @@ public:
|
||||
UIContext();
|
||||
~UIContext();
|
||||
|
||||
void Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pipeline *uipipenotex, Draw::Texture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop);
|
||||
void Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pipeline *uipipenotex, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop);
|
||||
|
||||
void FrameSetup(Draw::Texture *uiTexture);
|
||||
|
||||
void Begin();
|
||||
void BeginNoTex();
|
||||
|
Loading…
Reference in New Issue
Block a user