]> git.tdb.fi Git - libs/gl.git/blob - source/texture2d.cpp
c92099cedb35e79c362ab6cab25acd0d7359bd25
[libs/gl.git] / source / texture2d.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include "bindable.h"
9 #include "except.h"
10 #include "texture2d.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 Texture2D::Texture2D():
18         Texture(GL_TEXTURE_2D),
19         width(0),
20         height(0),
21         allocated(0)
22 { }
23
24 void Texture2D::storage(PixelFormat fmt, unsigned wd, unsigned ht)
25 {
26         if(width>0)
27                 throw InvalidState("Texture storage may only be specified once");
28         if(wd==0 || ht==0)
29                 throw InvalidParameterValue("Invalid texture dimensions");
30
31         ifmt = fmt;
32         width = wd;
33         height = ht;
34 }
35
36 void Texture2D::allocate(unsigned level)
37 {
38         if(allocated&(1<<level))
39                 return;
40
41         image(level, get_base_pixelformat(ifmt), UNSIGNED_BYTE, 0);
42 }
43
44 void Texture2D::image(unsigned level, PixelFormat fmt, DataType type, const void *data)
45 {
46         require_storage();
47
48         unsigned w = width;
49         unsigned h = height;
50         get_level_size(level, w, h);
51
52         Bind _bind(this, true);
53         glTexImage2D(target, level, ifmt, w, h, 0, fmt, type, data);
54
55         allocated |= 1<<level;
56         if(gen_mipmap && level==0)
57         {
58                 for(; (w || h); w>>=1, h>>=1, ++level) ;
59                 allocated |= (1<<level)-1;
60         }
61 }
62
63 void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, PixelFormat fmt, DataType type, const void *data)
64 {
65         require_storage();
66         allocate(level);
67
68         Bind _bind(this, true);
69         glTexSubImage2D(target, level, x, y, wd, ht, fmt, type, data);
70 }
71
72 void Texture2D::load_image(const string &fn)
73 {
74         Graphics::Image img;
75         img.load_file(fn);
76
77         image(img);
78 }
79
80 void Texture2D::image(const Graphics::Image &img)
81 {
82         unsigned w = img.get_width();
83         unsigned h = img.get_height();
84         PixelFormat fmt = pixelformat_from_graphics(img.get_format());
85         if(width==0)
86                 storage(fmt, w, h);
87         else if(w!=width || h!=height)
88                 throw IncompatibleData("Image does not match texture storage");
89
90         image(0, fmt, UNSIGNED_BYTE, img.get_data());
91 }
92
93 void Texture2D::require_storage()
94 {
95         if(width==0 || height==0)
96                 throw InvalidState("Texture storage has not been specified");
97 }
98
99 void Texture2D::get_level_size(unsigned level, unsigned &w, unsigned &h)
100 {
101         w >>= level;
102         h >>= level;
103
104         if(!w && h)
105                 w = 1;
106         else if(!h && w)
107                 h = 1;
108 }
109
110
111 Texture2D::Loader::Loader(Texture2D &t):
112         Texture::Loader(t)
113 {
114         add("image_data", &Loader::image_data);
115         add("raw_data", &Loader::raw_data);
116         add("storage", &Loader::storage);
117         add("storage", &Loader::storage_b);
118 }
119
120 void Texture2D::Loader::image_data(const string &data)
121 {
122         Graphics::Image img;
123         img.load_memory(data.data(), data.size());
124
125         static_cast<Texture2D &>(obj).image(img);
126 }
127
128 void Texture2D::Loader::raw_data(const string &data)
129 {
130         Texture2D &t2d = static_cast<Texture2D &>(obj);
131         t2d.image(0, t2d.ifmt, UNSIGNED_BYTE, data.data());
132 }
133
134 void Texture2D::Loader::storage(PixelFormat fmt, unsigned w, unsigned h)
135 {
136         static_cast<Texture2D &>(obj).storage(fmt, w, h);
137 }
138
139 void Texture2D::Loader::storage_b(PixelFormat fmt, unsigned w, unsigned h, unsigned)
140 {
141         storage(fmt, w, h);
142 }
143
144 } // namespace GL
145 } // namespace Msp