Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/GPU/Common/ReplacedTexture.h
3186 views
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 "Core/ConfigValues.h"
26
27
class TextureReplacer;
28
class LimitedWaitable;
29
30
// These must match the constants in TextureCacheCommon.
31
enum class ReplacedTextureAlpha {
32
UNKNOWN = 0x04,
33
FULL = 0x00,
34
};
35
36
// For forward compatibility, we specify the hash.
37
enum class ReplacedTextureHash {
38
QUICK,
39
XXH32,
40
XXH64,
41
};
42
43
enum class ReplacedImageType {
44
PNG,
45
ZIM,
46
DDS,
47
BASIS, // TODO: Might not even do this, KTX2 is a better container.
48
KTX2,
49
INVALID,
50
};
51
52
static const int MAX_REPLACEMENT_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP.
53
54
enum class ReplacementState : uint32_t {
55
UNLOADED,
56
PENDING,
57
NOT_FOUND, // Also used on error loading the images.
58
ACTIVE,
59
CANCEL_INIT,
60
COUNT, // Not a valid state
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
state_ = state;
124
}
125
126
void GetSize(int level, int *w, int *h) const {
127
_dbg_assert_(State() == ReplacementState::ACTIVE);
128
_dbg_assert_((size_t)level < levels_.size());
129
*w = levels_[level].fullW;
130
*h = levels_[level].fullH;
131
}
132
133
int GetLevelDataSizeAfterCopy(int level) const {
134
// Includes padding etc.
135
return levels_[level].fullDataSize;
136
}
137
138
size_t GetTotalDataSize() const {
139
if (State() != ReplacementState::ACTIVE) {
140
return 0;
141
}
142
size_t sz = 0;
143
for (auto &data : data_) {
144
sz += data.size();
145
}
146
return sz;
147
}
148
149
bool ForceFiltering(TextureFiltering *forceFiltering) const {
150
if (desc_.forceFiltering != (TextureFiltering)0) {
151
*forceFiltering = desc_.forceFiltering;
152
return true;
153
} else {
154
return false;
155
}
156
}
157
158
int NumLevels() const {
159
_dbg_assert_(State() == ReplacementState::ACTIVE);
160
return (int)levels_.size();
161
}
162
163
Draw::DataFormat Format() const {
164
_dbg_assert_(State() == ReplacementState::ACTIVE);
165
return fmt;
166
}
167
168
const ReplacementDesc &Desc() const {
169
return desc_;
170
}
171
172
u8 AlphaStatus() const {
173
return (u8)alphaStatus_;
174
}
175
176
bool Poll(double budget);
177
bool CopyLevelTo(int level, uint8_t *out, size_t outDataSize, int rowPitch);
178
179
std::string logId_;
180
181
private:
182
enum class LoadLevelResult {
183
LOAD_ERROR = 0,
184
CONTINUE = 1,
185
DONE = 2,
186
};
187
188
void Prepare(VFSBackend *vfs);
189
LoadLevelResult LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int level, Draw::DataFormat *pixelFormat);
190
void PurgeIfNotUsedSinceTime(double t);
191
192
std::vector<std::vector<uint8_t>> data_;
193
std::vector<ReplacedTextureLevel> levels_;
194
195
double lastUsed_ = 0.0;
196
LimitedWaitable *threadWaitable_ = nullptr;
197
std::mutex lock_;
198
Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM.
199
ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN;
200
double lastUsed = 0.0;
201
202
std::atomic<ReplacementState> state_ = ReplacementState::UNLOADED;
203
204
VFSBackend *vfs_ = nullptr;
205
ReplacementDesc desc_;
206
207
friend class TextureReplacer;
208
friend class ReplacedTextureTask;
209
};
210
211