Skip to content

Commit 1d5fe9f

Browse files
committed
renderer: Allow resizing texture without recreating it.
1 parent 2298eb2 commit 1d5fe9f

File tree

5 files changed

+91
-5
lines changed

5 files changed

+91
-5
lines changed

libopenage/renderer/opengl/texture.cpp

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
// Copyright 2015-2024 the openage authors. See copying.md for legal info.
1+
// Copyright 2015-2025 the openage authors. See copying.md for legal info.
22

33
#include "texture.h"
44

55
#include <epoxy/gl.h>
66

7+
#include <algorithm>
78
#include <tuple>
89

910
#include "../../datastructure/constexpr_map.h"
@@ -86,14 +87,73 @@ GlTexture2d::GlTexture2d(const std::shared_ptr<GlContext> &context,
8687
std::get<2>(fmt_in_out),
8788
nullptr);
8889

89-
// TODO these are outdated, use sampler settings
90+
// TODO: these are outdated, use sampler settings
9091
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9192
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9293

9394
log::log(MSG(dbg) << "Created OpenGL texture from info parameters (size: "
9495
<< size.first << "x" << size.second << ")");
9596
}
9697

98+
void GlTexture2d::resize(size_t width, size_t height) {
99+
auto prev_size = this->info.get_size();
100+
if (width == static_cast<size_t>(prev_size.first)
101+
and height == static_cast<size_t>(prev_size.second)) {
102+
// size is the same, no need to resize
103+
log::log(MSG(dbg) << "Texture resize called, but size is unchanged (size: "
104+
<< prev_size.first << "x" << prev_size.second << ")");
105+
return;
106+
}
107+
108+
// only allow resizing for internal textures that are not created from
109+
// image files
110+
// TODO: maybe allow this for all textures?
111+
if (this->info.get_image_path().has_value()) {
112+
throw Error(MSG(err) << "Cannot resize a texture that was created from an image file.");
113+
}
114+
if (this->info.get_subtex_count() != 0) {
115+
throw Error(MSG(err) << "Cannot resize a texture that has subtextures.");
116+
}
117+
118+
// create new info object
119+
this->info = resources::Texture2dInfo(width,
120+
height,
121+
this->info.get_format(),
122+
this->info.get_image_path(),
123+
this->info.get_row_alignment());
124+
125+
glBindTexture(GL_TEXTURE_2D, *this->handle);
126+
127+
auto fmt_in_out = GL_PIXEL_FORMAT.get(this->info.get_format());
128+
auto size = this->info.get_size();
129+
130+
// redefine the texture with the new size
131+
glTexImage2D(
132+
GL_TEXTURE_2D,
133+
0,
134+
std::get<0>(fmt_in_out),
135+
size.first,
136+
size.second,
137+
0,
138+
std::get<1>(fmt_in_out),
139+
std::get<2>(fmt_in_out),
140+
nullptr);
141+
142+
// copy the old texture data into the new texture
143+
glCopyTexSubImage2D(
144+
GL_TEXTURE_2D,
145+
0,
146+
0,
147+
0,
148+
0,
149+
0,
150+
std::min(size.first, prev_size.first), // avoid buffer overread with std::min
151+
std::min(size.second, prev_size.second));
152+
153+
log::log(MSG(dbg) << "Resized OpenGL texture (size: "
154+
<< width << "x" << height << ")");
155+
}
156+
97157
resources::Texture2dData GlTexture2d::into_data() {
98158
auto fmt_in_out = GL_PIXEL_FORMAT.get(this->info.get_format());
99159
std::vector<uint8_t> data(this->info.get_data_size());

libopenage/renderer/opengl/texture.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2015-2023 the openage authors. See copying.md for legal info.
1+
// Copyright 2015-2025 the openage authors. See copying.md for legal info.
22

33
#pragma once
44

@@ -23,6 +23,8 @@ class GlTexture2d final : public Texture2d
2323
GlTexture2d(const std::shared_ptr<GlContext> &context,
2424
resources::Texture2dInfo const &);
2525

26+
void resize(size_t width, size_t height) override;
27+
2628
resources::Texture2dData into_data() override;
2729

2830
void upload(resources::Texture2dData const &) override;

libopenage/renderer/resources/texture_info.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017-2023 the openage authors. See copying.md for legal info.
1+
// Copyright 2017-2025 the openage authors. See copying.md for legal info.
22

33
#include "texture_info.h"
44

@@ -71,6 +71,10 @@ size_t Texture2dInfo::get_subtex_count() const {
7171
return this->subtextures.size();
7272
}
7373

74+
const std::vector<Texture2dSubInfo> &Texture2dInfo::get_subtextures() const {
75+
return this->subtextures;
76+
}
77+
7478
const Texture2dSubInfo &Texture2dInfo::get_subtex_info(size_t subidx) const {
7579
if (subidx < this->subtextures.size()) [[likely]] {
7680
return this->subtextures[subidx];

libopenage/renderer/resources/texture_info.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2017-2024 the openage authors. See copying.md for legal info.
1+
// Copyright 2017-2025 the openage authors. See copying.md for legal info.
22

33
#pragma once
44

@@ -151,6 +151,13 @@ class Texture2dInfo {
151151
*/
152152
size_t get_subtex_count() const;
153153

154+
/**
155+
* Get the subtexture information for all subtextures.
156+
*
157+
* @return Subtexture information objects.
158+
*/
159+
const std::vector<Texture2dSubInfo> &get_subtextures() const;
160+
154161
/**
155162
* Get the subtexture information for a specific subtexture.
156163
*

libopenage/renderer/texture.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ class Texture2d {
2323
*/
2424
const resources::Texture2dInfo &get_info() const;
2525

26+
/**
27+
* Resize the texture to a new size.
28+
*
29+
* Resizing is propagated to the GPU, so the texture may be reallocated depending on the
30+
* underlying graphics API. The texture info is updated accordingly.
31+
*
32+
* Texture created from images cannot be resized.
33+
*
34+
* @param width New width of the texture.
35+
* @param height New height of the texture.
36+
*/
37+
virtual void resize(size_t width, size_t height) = 0;
38+
2639
/**
2740
* Copies this texture's data from graphics hardware into a CPU-accessible
2841
* Texture2dData buffer.

0 commit comments

Comments
 (0)