]> git.tdb.fi Git - libs/gl.git/blob - source/texture2d.cpp
Notify Renderables about the start and end of a frame
[libs/gl.git] / source / texture2d.cpp
1 #include "bindable.h"
2 #include "error.h"
3 #include "texture2d.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9
10 Texture2D::Texture2D():
11         Texture(GL_TEXTURE_2D),
12         width(0),
13         height(0),
14         allocated(0)
15 { }
16
17 void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht)
18 {
19         if(width>0)
20                 throw invalid_operation("Texture2D::storage");
21         if(wd==0 || ht==0)
22                 throw invalid_argument("Texture2D::storage");
23         require_pixelformat(fmt);
24
25         ifmt = fmt;
26         width = wd;
27         height = ht;
28 }
29
30 void Texture2D::allocate(unsigned level)
31 {
32         if(allocated&(1<<level))
33                 return;
34
35         image(level, get_base_pixelformat(ifmt), UNSIGNED_BYTE, 0);
36 }
37
38 void Texture2D::image(unsigned level, PixelFormat fmt, DataType type, const void *data)
39 {
40         if(width==0 || height==0)
41                 throw invalid_operation("Texture2D::image");
42
43         unsigned w = width;
44         unsigned h = height;
45         get_level_size(level, w, h);
46
47         Bind _bind(this, true);
48         glTexImage2D(target, level, ifmt, w, h, 0, fmt, type, data);
49
50         allocated |= 1<<level;
51         if(gen_mipmap && level==0)
52         {
53                 for(; (w || h); w>>=1, h>>=1, ++level) ;
54                 allocated |= (1<<level)-1;
55         }
56 }
57
58 void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, PixelFormat fmt, DataType type, const void *data)
59 {
60         if(width==0 || height==0)
61                 throw invalid_operation("Texture2D::sub_image");
62
63         allocate(level);
64
65         Bind _bind(this, true);
66         glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data);
67 }
68
69 void Texture2D::load_image(const string &fn)
70 {
71         Graphics::Image img;
72         img.load_file(fn);
73
74         image(img);
75 }
76
77 void Texture2D::image(const Graphics::Image &img)
78 {
79         unsigned w = img.get_width();
80         unsigned h = img.get_height();
81         PixelFormat fmt = pixelformat_from_graphics(img.get_format());
82         if(width==0)
83                 storage(fmt, w, h);
84         else if(w!=width || h!=height)
85                 throw incompatible_data("Texture2D::image");
86
87         image(0, fmt, UNSIGNED_BYTE, img.get_data());
88 }
89
90 void Texture2D::get_level_size(unsigned level, unsigned &w, unsigned &h)
91 {
92         w >>= level;
93         h >>= level;
94
95         if(!w && h)
96                 w = 1;
97         else if(!h && w)
98                 h = 1;
99 }
100
101
102 Texture2D::Loader::Loader(Texture2D &t):
103         DataFile::DerivedObjectLoader<Texture2D, Texture::Loader>(t)
104 {
105         add("image_data", &Loader::image_data);
106         add("raw_data", &Loader::raw_data);
107         add("storage", &Loader::storage);
108         add("storage", &Loader::storage_b);
109 }
110
111 void Texture2D::Loader::image_data(const string &data)
112 {
113         Graphics::Image img;
114         img.load_memory(data.data(), data.size());
115
116         obj.image(img);
117 }
118
119 void Texture2D::Loader::raw_data(const string &data)
120 {
121         obj.image(0, obj.ifmt, UNSIGNED_BYTE, data.data());
122 }
123
124 void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h)
125 {
126         obj.storage(fmt, w, h);
127 }
128
129 void Texture2D::Loader::storage_b(PixelFormat fmt, unsigned w, unsigned h, unsigned)
130 {
131         storage(fmt, w, h);
132 }
133
134 } // namespace GL
135 } // namespace Msp