-
Notifications
You must be signed in to change notification settings - Fork 51
/
Texture.h
227 lines (203 loc) · 7.46 KB
/
Texture.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <istream>
#include "winheaders.h"
#include <string>
#include "ResourceManager.h"
#include "gl/ubo.h"
struct opengl_texture {
static DDSURFACEDESC2 deserialize_ddsd(std::istream&);
static DDCOLORKEY deserialize_ddck(std::istream&);
static DDPIXELFORMAT deserialize_ddpf(std::istream&);
static DDSCAPS2 deserialize_ddscaps(std::istream&);
// constructors
opengl_texture() = default;
// methods
void
load();
bool
bind( size_t unit );
static void
unbind( size_t unit );
bool
create( bool const Static = false );
// releases resources allocated on the opengl end, storing local copy if requested
void
release();
void
make_stub();
void
alloc_rendertarget( GLint format, GLint components, int width, int height, int layers = 1, int samples = 1, GLint wrap = GL_CLAMP_TO_EDGE );
void
set_components_hint( GLint hint );
static void
reset_unit_cache();
inline
int
width() const {
return data_width; }
inline
int
height() const {
return data_height; }
inline
bool
is_stub() const {
return is_texstub; }
void make_from_memory(size_t width, size_t height, const uint8_t *data);
// members
GLuint id{ (GLuint)-1 }; // associated GL resource
bool has_alpha{ false }; // indicates the texture has alpha channel
bool is_ready{ false }; // indicates the texture was processed and is ready for use
std::string traits; // requested texture attributes: wrapping modes etc
std::string name; // name of the texture source file
std::string type; // type of the texture source file
std::size_t size{ 0 }; // size of the texture data, in kb
GLint components_hint = 0; // components that material wants
GLenum target = GL_TEXTURE_2D;
static std::array<GLuint, gl::MAX_TEXTURES + gl::HELPER_TEXTURES> units;
static GLint m_activeunit;
private:
// methods
void make_request();
void load_PNG();
void load_DDS();
void load_KTX();
void load_TEX();
void load_STBI();
void load_TGA();
void set_filtering() const;
void downsize( GLuint const Format );
void flip_vertical();
void gles_match_internalformat(GLuint format);
// members
bool is_static = false; // is excluded from garbage collection
bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data
int samples = 1;
int layers = 1;
bool is_texstub = false; // for make_from_memory internal_src: functionality
std::vector<unsigned char> data; // texture data (stored GL-style, bottom-left origin)
resource_state data_state{ resource_state::none }; // current state of texture data
int data_width{ 0 },
data_height{ 0 },
data_mapcount{ 0 };
GLint data_format{ 0 },
data_components{ 0 };
GLint data_type = GL_UNSIGNED_BYTE;
GLint wrap_mode_s = GL_REPEAT;
GLint wrap_mode_t = GL_REPEAT;
/*
std::atomic<bool> is_loaded{ false }; // indicates the texture data was loaded and can be processed
std::atomic<bool> is_good{ false }; // indicates the texture data was retrieved without errors
*/
static std::unordered_map<GLint, int> precompressed_formats;
static std::unordered_map<GLint, GLint> drivercompressed_formats;
static std::unordered_map<GLint, std::unordered_map<GLint, GLint>> mapping;
};
typedef int texture_handle;
class texture_manager {
public:
texture_manager();
~texture_manager() { delete_textures(); }
// activates specified texture unit
void
unit( GLint const Textureunit );
// creates texture object out of data stored in specified file
texture_handle
create( std::string Filename, bool const Loadnow = true, GLint Formathint = GL_SRGB_ALPHA );
// binds specified texture to specified texture unit
void
bind( std::size_t const Unit, texture_handle const Texture );
opengl_texture &
mark_as_used( texture_handle const Texture );
// provides direct access to specified texture object
opengl_texture &
texture( texture_handle const Texture ) const { return *(m_textures[ Texture ].first); }
// performs a resource sweep
void
update();
// debug performance string
std::string
info() const;
private:
// types:
typedef std::pair<
opengl_texture *,
resource_timestamp > texturetimepoint_pair;
typedef std::vector< texturetimepoint_pair > texturetimepointpair_sequence;
typedef std::unordered_map<std::string, std::size_t> index_map;
// methods:
// checks whether specified texture is in the texture bank. returns texture id, or npos.
texture_handle
find_in_databank( std::string const &Texturename ) const;
// checks whether specified file exists. returns name of the located file, or empty string.
std::pair<std::string, std::string>
find_on_disk( std::string const &Texturename ) const;
void
delete_textures();
// members:
texture_handle const npos { 0 }; // should be -1, but the rest of the code uses -1 for something else
texturetimepointpair_sequence m_textures;
index_map m_texturemappings;
garbage_collector<texturetimepointpair_sequence> m_garbagecollector { m_textures, 600, 60, "texture" };
};
// reduces provided data image to half of original size, using basic 2x2 average
template <typename Colortype_>
void
downsample( std::size_t const Width, std::size_t const Height, unsigned char *Imagedata ) {
Colortype_ *destination = reinterpret_cast<Colortype_*>( Imagedata );
Colortype_ *sampler = reinterpret_cast<Colortype_*>( Imagedata );
Colortype_ accumulator, color;
/*
_Colortype color;
float component;
*/
for( std::size_t row = 0; row < Height; row += 2, sampler += Width ) { // column movement advances us down another row
for( std::size_t column = 0; column < Width; column += 2, sampler += 2 ) {
/*
// straightforward, but won't work with byte data
auto color = (
*sampler
+ *( sampler + 1 )
+ *( sampler + Width )
+ *( sampler + Width + 1 ) );
color /= 4;
*/
// manual version of the above, but drops colour resolution to 6 bits
accumulator = *sampler;
accumulator /= 4;
color = accumulator;
accumulator = *(sampler + 1);
accumulator /= 4;
color += accumulator;
accumulator = *(sampler + Width);
accumulator /= 4;
color += accumulator;
accumulator = *(sampler + Width + 1);
accumulator /= 4;
color += accumulator;
*destination++ = color;
/*
// "full" 8bit resolution
color = Colortype_(); component = 0;
for( int idx = 0; idx < sizeof( Colortype_ ); ++idx ) {
component = (
(*sampler)[idx]
+ ( *( sampler + 1 ) )[idx]
+ ( *( sampler + Width ) )[idx]
+ ( *( sampler + Width + 1 ))[idx] );
color[ idx ] = component /= 4;
}
*destination++ = color;
*/
}
}
}
//---------------------------------------------------------------------------