]> git.tdb.fi Git - libs/gl.git/blob - source/texturing.cpp
Add a texunit statement which automatically determines the unit number
[libs/gl.git] / source / 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))
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)
35 {
36         set_attachment(attch, &tex);
37 }
38
39 void Texturing::detach(unsigned attch)
40 {
41         set_attachment(attch, 0);
42 }
43
44 void Texturing::set_attachment(unsigned unit, const Texture *tex)
45 {
46         if(unit>=TexUnit::get_n_units())
47                 throw out_of_range("Texturing::set_attachment");
48
49         if(tex)
50         {
51                 vector<Attachment>::iterator i;
52                 for(i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
53                         if(i->unit==unit)
54                         {
55                                 i->texture = tex;
56                                 if(current()==this)
57                                         tex->bind_to(unit);
58                                 return;
59                         }
60
61                 attachments.insert(i, Attachment(unit, tex));
62                 if(current()==this)
63                         tex->bind_to(unit);
64         }
65         else
66         {
67                 for(vector<Attachment>::iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
68                         if(i->unit==unit)
69                         {
70                                 attachments.erase(i);
71                                 if(current()==this)
72                                         Texture::unbind_from(unit);
73                                 return;
74                         }
75         }
76 }
77
78 const Texture *Texturing::get_attached_texture(unsigned unit) const
79 {
80         for(vector<Attachment>::const_iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
81                 if(i->unit==unit)
82                         return i->texture;
83         return 0;
84 }
85
86 void Texturing::bind() const
87 {
88         const Texturing *old = current();
89         if(set_current(this))
90         {
91                 if(old)
92                 {
93                         vector<Attachment>::const_iterator i = attachments.begin();
94                         vector<Attachment>::const_iterator j = old->attachments.begin();
95                         while(i!=attachments.end() || j!=old->attachments.end())
96                         {
97                                 if(i!=attachments.end() && (j==old->attachments.end() || i->unit<=j->unit))
98                                 {
99                                         i->texture->bind_to(i->unit);
100                                         if(j!=old->attachments.end() && j->unit==i->unit)
101                                                 ++j;
102                                         ++i;
103                                 }
104                                 else
105                                 {
106                                         Texture::unbind_from(j->unit);
107                                         ++j;
108                                 }
109                         }
110                 }
111                 else
112                 {
113                         for(vector<Attachment>::const_iterator i=attachments.begin(); i!=attachments.end(); ++i)
114                                 i->texture->bind_to(i->unit);
115                 }
116         }
117 }
118
119 void Texturing::unbind()
120 {
121         const Texturing *old = current();
122         if(set_current(0))
123         {
124                 for(vector<Attachment>::const_iterator i=old->attachments.begin(); i!=old->attachments.end(); ++i)
125                         Texture::unbind_from(i->unit);
126         }
127 }
128
129
130 Texturing::Attachment::Attachment(unsigned u, const Texture *t):
131         unit(u),
132         texture(t)
133 { }
134
135 } // namespace GL
136 } // namespace Msp;