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
|
#include <mbgl/platform/platform.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/util/raster.hpp>
#include <cassert>
#include <cstring>
namespace mbgl {
bool Raster::isLoaded() const {
return loaded;
}
GLuint Raster::getID() const {
return texture ? *texture : 0;
}
std::array<uint16_t, 2> Raster::getSize() const {
return size;
}
void Raster::load(PremultipliedImage image, uint32_t mipmapLevel) {
if (images.size() <= mipmapLevel) {
images.resize(mipmapLevel + 1);
}
images.at(mipmapLevel) = std::move(image);
loaded = true;
}
void Raster::bind(gl::ObjectStore& store,
gl::Context& context,
uint32_t unit,
Scaling newFilter,
MipMap newMipMap) {
bool filterNeedsUpdate = false;
if (!texture) {
if (images.empty()) {
Log::Error(Event::OpenGL, "trying to bind texture without images");
return;
} else {
upload(store, context, unit);
filterNeedsUpdate = true;
}
} else {
if (context.texture[unit] != *texture) {
context.activeTexture = unit;
context.texture[unit] = *texture;
}
filterNeedsUpdate = (filter != newFilter || mipmap != newMipMap);
}
if (filterNeedsUpdate) {
filter = newFilter;
mipmap = newMipMap;
updateFilter();
}
}
void Raster::updateFilter() {
MBGL_CHECK_ERROR(glTexParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
filter == Scaling::Linear
? (mipmap == MipMap::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR)
: (mipmap == MipMap::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
filter == Scaling::Linear ? GL_LINEAR : GL_NEAREST));
}
void Raster::upload(gl::ObjectStore& store, gl::Context& context, uint32_t unit) {
if (!images.empty() && !texture) {
texture = store.createTexture();
context.activeTexture = unit;
context.texture[unit] = *texture;
updateFilter();
#ifndef GL_ES_VERSION_2_0
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, images.size()));
#endif
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GLint level = 0;
for (auto& img : images) {
MBGL_CHECK_ERROR(glTexImage2D(
GL_TEXTURE_2D, level++, GL_RGBA, static_cast<GLsizei>(img.width),
static_cast<GLsizei>(img.height), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data.get()));
}
size = { { images.front().width, images.front().height } };
images.clear();
images.shrink_to_fit();
}
}
} // namespace mbgl
|