]> git.tdb.fi Git - libs/gl.git/blob - source/core/texture2d.cpp
Always delay texture creation until it is allocated
[libs/gl.git] / source / core / texture2d.cpp
1 #include "error.h"
2 #include "texture2d.h"
3
4 using namespace std;
5
6 namespace Msp {
7 namespace GL {
8
9 Texture2D::Texture2D(ResourceManager *m):
10         Texture2DBackend(m),
11         width(0),
12         height(0)
13 { }
14
15 Texture2D::~Texture2D()
16 {
17         set_manager(0);
18 }
19
20 void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv)
21 {
22         if(width>0)
23         {
24                 if(fmt!=format || wd!=width || ht!=height || (lv && lv!=levels))
25                         throw incompatible_data("Texture2D::storage");
26                 return;
27         }
28         if(wd==0 || ht==0)
29                 throw invalid_argument("Texture2D::storage");
30
31         set_format(fmt);
32         width = wd;
33         height = ht;
34         levels = get_n_levels();
35         if(lv>0)
36                 levels = min(levels, lv);
37
38         allocate();
39 }
40
41 void Texture2D::image(unsigned level, const void *data)
42 {
43         LinAl::Vector<unsigned, 2> size = get_level_size(level);
44         return sub_image(level, 0, 0, size.x, size.y, data);
45 }
46
47 void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
48 {
49         if(width==0 || height==0)
50                 throw invalid_operation("Texture2D::sub_image");
51         if(level>=levels)
52                 throw out_of_range("Texture2D::sub_image");
53
54         Texture2DBackend::sub_image(level, x, y, wd, ht, data);
55 }
56
57 void Texture2D::image(const Graphics::Image &img, unsigned lv)
58 {
59         storage(pixelformat_from_image(img, use_srgb_format), img.get_width(), img.get_height(), lv);
60         image(0, img.get_pixels());
61 }
62
63 unsigned Texture2D::get_n_levels() const
64 {
65         unsigned n = 0;
66         for(unsigned s=max(width, height); s; s>>=1, ++n) ;
67         return n;
68 }
69
70 LinAl::Vector<unsigned, 2> Texture2D::get_level_size(unsigned level) const
71 {
72         unsigned w = width>>level;
73         unsigned h = height>>level;
74
75         if(!w && h)
76                 w = 1;
77         else if(!h && w)
78                 h = 1;
79
80         return LinAl::Vector<unsigned, 2>(w, h);
81 }
82
83 Resource::AsyncLoader *Texture2D::load(IO::Seekable &io, const Resources *)
84 {
85         return create_async_loader(io);
86 }
87
88 uint64_t Texture2D::get_data_size() const
89 {
90         return id ? width*height*get_pixel_size(format) : 0;
91 }
92
93
94 Texture2D::Loader::Loader(Texture2D &t):
95         DataFile::DerivedObjectLoader<Texture2D, Texture::Loader>(t)
96 {
97         init();
98 }
99
100 Texture2D::Loader::Loader(Texture2D &t, Collection &c):
101         DataFile::DerivedObjectLoader<Texture2D, Texture::Loader>(t, c)
102 {
103         init();
104 }
105
106 void Texture2D::Loader::init()
107 {
108         add("raw_data", &Loader::raw_data);
109         add("storage", &Loader::storage);
110         add("storage", &Loader::storage_levels);
111 }
112
113 void Texture2D::Loader::raw_data(const string &data)
114 {
115         if(obj.manager)
116                 obj.set_manager(0);
117         obj.image(0, data.data());
118 }
119
120 void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h)
121 {
122         obj.storage(fmt, w, h);
123 }
124
125 void Texture2D::Loader::storage_levels(PixelFormat fmt, unsigned w, unsigned h, unsigned l)
126 {
127         obj.storage(fmt, w, h, l);
128 }
129
130 } // namespace GL
131 } // namespace Msp