CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/GPU/Common/ReplacedTexture.h
Views: 1401
1
// Copyright (c) 2016- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#pragma once
19
20
#include <mutex>
21
#include <string>
22
23
#include "Common/File/VFS/VFS.h"
24
#include "Common/GPU/thin3d.h"
25
#include "Common/Log.h"
26
#include "Core/ConfigValues.h"
27
28
class TextureReplacer;
29
class LimitedWaitable;
30
31
// These must match the constants in TextureCacheCommon.
32
enum class ReplacedTextureAlpha {
33
UNKNOWN = 0x04,
34
FULL = 0x00,
35
};
36
37
// For forward compatibility, we specify the hash.
38
enum class ReplacedTextureHash {
39
QUICK,
40
XXH32,
41
XXH64,
42
};
43
44
enum class ReplacedImageType {
45
PNG,
46
ZIM,
47
DDS,
48
BASIS, // TODO: Might not even do this, KTX2 is a better container.
49
KTX2,
50
INVALID,
51
};
52
53
static const int MAX_REPLACEMENT_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP.
54
55
enum class ReplacementState : uint32_t {
56
UNLOADED,
57
PENDING,
58
NOT_FOUND, // Also used on error loading the images.
59
ACTIVE,
60
CANCEL_INIT,
61
};
62
63
const char *StateString(ReplacementState state);
64
65
struct GPUFormatSupport {
66
bool bc123;
67
bool astc;
68
bool bc7;
69
bool etc2;
70
};
71
72
struct ReplacementDesc {
73
int newW;
74
int newH;
75
uint64_t cachekey;
76
uint32_t hash;
77
int w;
78
int h;
79
TextureFiltering forceFiltering;
80
std::string hashfiles;
81
Path basePath;
82
std::vector<std::string> filenames;
83
std::string logId;
84
GPUFormatSupport formatSupport;
85
};
86
87
class ReplacedTexture;
88
89
// These aren't actually all replaced, they can also represent a placeholder for a not-found
90
// replacement (texture == nullptr).
91
struct ReplacedTextureRef {
92
ReplacedTexture *texture; // shortcut
93
std::string hashfiles; // key into the cache
94
};
95
96
// Metadata about a given texture level.
97
struct ReplacedTextureLevel {
98
// Data dimensions
99
int w = 0;
100
int h = 0;
101
// PSP texture dimensions
102
int fullW = 0;
103
int fullH = 0;
104
105
int fullDataSize = 0;
106
107
// To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t.
108
// TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects.
109
VFSFileReference *fileRef = nullptr;
110
};
111
112
class ReplacedTexture {
113
public:
114
ReplacedTexture(VFSBackend *vfs, const ReplacementDesc &desc);
115
~ReplacedTexture();
116
117
inline ReplacementState State() const {
118
return state_;
119
}
120
121
void SetState(ReplacementState state) {
122
_dbg_assert_(state != state_);
123
#ifdef _DEBUG
124
// WARN_LOG(Log::G3D, "Texture %s changed state from %s to %s", logId_.c_str(), StateString(state_), StateString(state));
125
#endif
126
state_ = state;
127
}
128
129
void GetSize(int level, int *w, int *h) const {
130
_dbg_assert_(State() == ReplacementState::ACTIVE);
131
_dbg_assert_((size_t)level < levels_.size());
132
*w = levels_[level].fullW;
133
*h = levels_[level].fullH;
134
}
135
136
int GetLevelDataSizeAfterCopy(int level) const {
137
// Includes padding etc.
138
return levels_[level].fullDataSize;
139
}
140
141
size_t GetTotalDataSize() const {
142
if (State() != ReplacementState::ACTIVE) {
143
return 0;
144
}
145
size_t sz = 0;
146
for (auto &data : data_) {
147
sz += data.size();
148
}
149
return sz;
150
}
151
152
bool ForceFiltering(TextureFiltering *forceFiltering) const {
153
if (desc_.forceFiltering != (TextureFiltering)0) {
154
*forceFiltering = desc_.forceFiltering;
155
return true;
156
} else {
157
return false;
158
}
159
}
160
161
int NumLevels() const {
162
_dbg_assert_(State() == ReplacementState::ACTIVE);
163
return (int)levels_.size();
164
}
165
166
Draw::DataFormat Format() const {
167
_dbg_assert_(State() == ReplacementState::ACTIVE);
168
return fmt;
169
}
170
171
u8 AlphaStatus() const {
172
return (u8)alphaStatus_;
173
}
174
175
bool Poll(double budget);
176
bool CopyLevelTo(int level, uint8_t *out, size_t outDataSize, int rowPitch);
177
178
std::string logId_;
179
180
private:
181
enum class LoadLevelResult {
182
LOAD_ERROR = 0,
183
CONTINUE = 1,
184
DONE = 2,
185
};
186
187
void Prepare(VFSBackend *vfs);
188
LoadLevelResult LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int level, Draw::DataFormat *pixelFormat);
189
void PurgeIfNotUsedSinceTime(double t);
190
191
std::vector<std::vector<uint8_t>> data_;
192
std::vector<ReplacedTextureLevel> levels_;
193
194
double lastUsed_ = 0.0;
195
LimitedWaitable *threadWaitable_ = nullptr;
196
std::mutex lock_;
197
Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM.
198
ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN;
199
double lastUsed = 0.0;
200
201
std::atomic<ReplacementState> state_ = ReplacementState::UNLOADED;
202
203
VFSBackend *vfs_ = nullptr;
204
ReplacementDesc desc_;
205
206
friend class TextureReplacer;
207
friend class ReplacedTextureTask;
208
};
209
210