r854: Merge 2.1:
[cinelerra_cv/ct.git] / guicast / bctexture.C
blob36767cb9d3ef7525551eea3506e558ef952d466a
1 #define GL_GLEXT_PROTOTYPES
3 #include "bcsynchronous.h"
4 #include "bctexture.h"
5 #include "bcwindowbase.h"
6 #include "colormodels.h"
9 BC_Texture::BC_Texture(int w, int h, int colormodel)
11         this->w = w;
12         this->h = h;
13         this->colormodel = colormodel;
14         texture_id = -1;
15         texture_id = -1;
16         texture_w = 0;
17         texture_h = 0;
18         texture_components = 0;
19         window_id = -1;
20         create_texture(w, h, colormodel);
24 BC_Texture::~BC_Texture()
26         clear_objects();
29 void BC_Texture::clear_objects()
31         if(get_texture_id() >= 0)
32         {
33 // printf("VFrame::clear_objects %p window_id=%d texture_id=%d w=%d h=%d\n", 
34 // this, window_id, texture_id, texture_w, texture_h);
35                 BC_WindowBase::get_synchronous()->release_texture(
36                         window_id,
37                         texture_id);
38                 texture_id = -1;
39         }
42 void BC_Texture::new_texture(BC_Texture **texture,
43         int w, 
44         int h, 
45         int colormodel)
47         if(!(*texture))
48         {
49                 (*texture) = new BC_Texture(w, h, colormodel);
50         }
51         else
52         {
53                 (*texture)->create_texture(w, h, colormodel);
54         }
57 void BC_Texture::create_texture(int w, int h, int colormodel)
59 #ifdef HAVE_GL
61 // Get max texture size from the server.
62 // Maximum size was 4096 on the earliest cards that could do video.
63         int max_texture_size = 0;
64         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
66 // Calculate dimensions of texture
67         int new_w = calculate_texture_size(w, &max_texture_size);
68         int new_h = calculate_texture_size(h, &max_texture_size);
69         int new_components = cmodel_components(colormodel);
72         if(new_w < w || new_h < h)
73         {
74                 printf("BC_Texture::create_texture frame size %dx%d bigger than maximum texture %dx%d.\n",
75                         w, 
76                         h,
77                         max_texture_size, 
78                         max_texture_size);
79         }
81 // Delete existing texture
82         if(texture_id >= 0 && 
83                 (new_h != texture_h ||
84                 new_w != texture_w ||
85                 new_components != texture_components ||
86                 BC_WindowBase::get_synchronous()->current_window->get_id() != window_id))
87         {
88 // printf("BC_Texture::create_texture released window_id=%d texture_id=%d\n", 
89 // BC_WindowBase::get_synchronous()->current_window->get_id(),
90 // texture_id);
91                 BC_WindowBase::get_synchronous()->release_texture(
92                         window_id,
93                         texture_id);
94             texture_id = -1;
95             window_id = -1;
96         }
99         texture_w = new_w;
100         texture_h = new_h;
101         texture_components = new_components;
103 // Get matching texture
104         if(texture_id < 0)
105         {
106                 texture_id = BC_WindowBase::get_synchronous()->get_texture(
107                         texture_w, 
108                         texture_h,
109                         texture_components);
110 // A new VFrame has no window_id, so it must read it from the matching texture.
111                 if(texture_id >= 0) 
112                         window_id = BC_WindowBase::get_synchronous()->current_window->get_id();
113         }
116 // No matching texture exists.
117 // Create new texture with the proper dimensions
118         if(texture_id < 0)
119         {
120                 glGenTextures(1, (GLuint*)&texture_id);
121                 glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id);
122                 glEnable(GL_TEXTURE_2D);
123                 if(texture_components == 4)
124                         glTexImage2D(GL_TEXTURE_2D, 
125                                 0, 
126                                 4, 
127                                 texture_w, 
128                         texture_h, 
129                                 0, 
130                                 GL_RGBA, 
131                                 GL_UNSIGNED_BYTE,
132                         0);
133                 else
134                         glTexImage2D(GL_TEXTURE_2D, 
135                                 0, 
136                                 3, 
137                                 texture_w, 
138                         texture_h, 
139                                 0, 
140                                 GL_RGB, 
141                                 GL_UNSIGNED_BYTE,
142                         0);
144                 window_id = BC_WindowBase::get_synchronous()->current_window->get_id();
145                 BC_WindowBase::get_synchronous()->put_texture(texture_id,
146                         texture_w,
147                         texture_h,
148                         texture_components);
149 // printf("VFrame::new_texture created texture_id=%d window_id=%d\n", 
150 // *texture_id,
151 // *window_id);
152         }
153         else
154         {
155                 glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id);
156                 glEnable(GL_TEXTURE_2D);
157         }
158 #endif
161 int BC_Texture::calculate_texture_size(int w, int *max)
163         int i;
164         for(i = 2; (max && i <= *max) || (!max && i < w); i *= 2)
165         {
166                 if(i >= w) 
167                 {
168                         return i;
169                         break;
170                 }
171         }
172         if(max && i > *max) return 16;
173         return i;
176 int BC_Texture::get_texture_id()
178         return texture_id;
181 int BC_Texture::get_texture_w()
183         return texture_w;
186 int BC_Texture::get_texture_h()
188         return texture_h;
191 int BC_Texture::get_texture_components()
193         return texture_components;
196 int BC_Texture::get_window_id()
198         return window_id;
202 void BC_Texture::bind(int texture_unit)
204 #ifdef HAVE_GL
205 // Bind the texture
206         if(texture_id >= 0)
207         {
208                 if(texture_unit >= 0) glActiveTexture(GL_TEXTURE0 + texture_unit);
209                 glBindTexture(GL_TEXTURE_2D, texture_id);
210                 glEnable(GL_TEXTURE_2D);
211                 if(texture_unit >= 0) 
212                 {
213                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
214                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
216 // GL_REPEAT in this case causes the upper left corners of the masks
217 // to blur.
218                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
219                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
221 // Get the texture to alpha blend
222                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
223                 }
224         }
225 #endif