]> git.tdb.fi Git - libs/gl.git/blob - source/render/texturing.cpp
341cdb79712f6c739ffed027d4ac069f7e04b234
[libs/gl.git] / source / render / texturing.cpp
1 #include <msp/core/hash.h>
2 #include "texture.h"
3 #include "texturing.h"
4 #include "texunit.h"
5
6 using namespace std;
7
8 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
9
10 namespace Msp {
11 namespace GL {
12
13 Texturing::~Texturing()
14 {
15         if(current()==this)
16                 unbind();
17 }
18
19 int Texturing::find_free_unit(const string &name_hint) const
20 {
21         unsigned max_unit = TexUnit::get_n_units();
22         // Leave some space for effect textures
23         max_unit -= min(max_unit/4, 8U);
24         unsigned initial_unit = (name_hint.empty() ? 0 : hash32(name_hint)%max_unit);
25         unsigned unit = initial_unit;
26         while(get_attached_texture(unit) || get_attached_sampler(unit))
27         {
28                 unit = (unit+1)%max_unit;
29                 if(unit==initial_unit)
30                         return -1;
31         }
32
33         return unit;
34 }
35
36 void Texturing::attach(unsigned attch, const Texture &tex, const Sampler *samp)
37 {
38         set_attachment(attch, &tex, samp);
39 }
40
41 void Texturing::attach(unsigned attch, const Sampler &samp)
42 {
43         set_attachment(attch, 0, &samp);
44 }
45
46 void Texturing::detach(unsigned attch)
47 {
48         set_attachment(attch, 0, 0);
49 }
50
51 void Texturing::set_attachment(unsigned unit, const Texture *tex, const Sampler *samp)
52 {
53         if(unit>=TexUnit::get_n_units())
54                 throw out_of_range("Texturing::set_attachment");
55
56         if(tex || samp)
57         {
58                 vector<Attachment>::iterator i;
59                 for(i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
60                         if(i->unit==unit)
61                         {
62                                 i->texture = tex;
63                                 i->sampler = samp;
64                                 if(current()==this)
65                                         bind_attachment(*i);
66                                 return;
67                         }
68
69                 attachments.insert(i, Attachment(unit, tex, samp));
70                 if(current()==this)
71                         tex->bind_to(unit);
72         }
73         else
74         {
75                 for(vector<Attachment>::iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
76                         if(i->unit==unit)
77                         {
78                                 attachments.erase(i);
79                                 if(current()==this)
80                                         unbind_attachment(unit);
81                                 return;
82                         }
83         }
84 }
85
86 const Texture *Texturing::get_attached_texture(unsigned unit) const
87 {
88         for(vector<Attachment>::const_iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
89                 if(i->unit==unit)
90                         return i->texture;
91         return 0;
92 }
93
94 const Sampler *Texturing::get_attached_sampler(unsigned unit) const
95 {
96         for(vector<Attachment>::const_iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
97                 if(i->unit==unit)
98                         return i->sampler;
99         return 0;
100 }
101
102 void Texturing::bind() const
103 {
104         const Texturing *old = current();
105         if(set_current(this))
106         {
107                 if(old)
108                 {
109                         vector<Attachment>::const_iterator i = attachments.begin();
110                         vector<Attachment>::const_iterator j = old->attachments.begin();
111                         while(i!=attachments.end() || j!=old->attachments.end())
112                         {
113                                 if(i!=attachments.end() && (j==old->attachments.end() || i->unit<=j->unit))
114                                 {
115                                         bind_attachment(*i);
116                                         if(j!=old->attachments.end() && j->unit==i->unit)
117                                                 ++j;
118                                         ++i;
119                                 }
120                                 else
121                                 {
122                                         unbind_attachment(j->unit);
123                                         ++j;
124                                 }
125                         }
126                 }
127                 else
128                 {
129                         for(vector<Attachment>::const_iterator i=attachments.begin(); i!=attachments.end(); ++i)
130                                 bind_attachment(*i);
131                 }
132         }
133 }
134
135 void Texturing::bind_attachment(const Attachment &attch) const
136 {
137         if(attch.sampler)
138                 attch.sampler->bind_to(attch.unit);
139         else
140                 Sampler::unbind_from(attch.unit);
141         if(attch.texture)
142                 attch.texture->bind_to(attch.unit);
143         else
144                 Texture::unbind_from(attch.unit);
145 }
146
147 void Texturing::unbind()
148 {
149         const Texturing *old = current();
150         if(set_current(0))
151         {
152                 for(vector<Attachment>::const_iterator i=old->attachments.begin(); i!=old->attachments.end(); ++i)
153                         unbind_attachment(i->unit);
154         }
155 }
156
157 void Texturing::unbind_attachment(unsigned unit)
158 {
159         Texture::unbind_from(unit);
160         Sampler::unbind_from(unit);
161 }
162
163
164 Texturing::Attachment::Attachment(unsigned u, const Texture *t, const Sampler *s):
165         unit(u),
166         texture(t),
167         sampler(s)
168 { }
169
170 } // namespace GL
171 } // namespace Msp;