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