4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #define GL_GLEXT_PROTOTYPES
24 #include "bcsynchronous.h"
25 #include "bctexture.h"
26 #include "bcwindowbase.h"
27 #include "bccmodels.h"
30 BC_Texture::BC_Texture(int w, int h, int colormodel)
34 this->colormodel = colormodel;
39 texture_components = 0;
41 create_texture(w, h, colormodel);
45 BC_Texture::~BC_Texture()
50 void BC_Texture::clear_objects()
52 if(get_texture_id() >= 0)
54 // printf("VFrame::clear_objects %p window_id=%d texture_id=%d w=%d h=%d\n",
55 // this, window_id, texture_id, texture_w, texture_h);
56 BC_WindowBase::get_synchronous()->release_texture(
63 void BC_Texture::new_texture(BC_Texture **texture,
64 int w, int h, int colormodel)
67 (*texture) = new BC_Texture(w, h, colormodel);
70 (*texture)->create_texture(w, h, colormodel);
74 void BC_Texture::create_texture(int w, int h, int colormodel)
78 // Get max texture size from the server.
79 // Maximum size was 4096 on the earliest cards that could do video.
80 int max_texture_size = 0;
81 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
83 // Calculate dimensions of texture
84 int new_w = calculate_texture_size(w, &max_texture_size);
85 int new_h = calculate_texture_size(h, &max_texture_size);
86 int new_components = BC_CModels::components(colormodel);
88 if(new_w < w || new_h < h) {
89 printf("BC_Texture::create_texture frame size %dx%d bigger than maximum texture %dx%d.\n",
90 w, h, max_texture_size, max_texture_size);
93 // Delete existing texture
94 if(texture_id >= 0 && (new_h != texture_h || new_w != texture_w ||
95 new_components != texture_components ||
96 BC_WindowBase::get_synchronous()->current_window->get_id() != window_id))
98 // printf("BC_Texture::create_texture released window_id=%d texture_id=%d\n",
99 // BC_WindowBase::get_synchronous()->current_window->get_id(),
101 BC_WindowBase::get_synchronous()->release_texture(
111 texture_components = new_components;
113 // Get matching texture
115 texture_id = BC_WindowBase::get_synchronous()->get_texture(
116 texture_w, texture_h, texture_components);
117 // A new VFrame has no window_id, so it must read it from the matching texture.
119 window_id = BC_WindowBase::get_synchronous()->current_window->get_id();
122 // No matching texture exists.
123 // Create new texture with the proper dimensions
125 glGenTextures(1, (GLuint*)&texture_id);
126 glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id);
127 glEnable(GL_TEXTURE_2D);
128 if(texture_components == 4)
129 glTexImage2D(GL_TEXTURE_2D, 0, 4, texture_w, texture_h,
130 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
132 glTexImage2D(GL_TEXTURE_2D, 0, 3, texture_w, texture_h,
133 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
135 window_id = BC_WindowBase::get_synchronous()->current_window->get_id();
136 BC_WindowBase::get_synchronous()->put_texture(texture_id,
137 texture_w, texture_h, texture_components);
138 //printf("BC_Texture::new_texture created texture_id=%d window_id=%d w=%d h=%d\n",
139 // texture_id, window_id, texture_w, texture_h);
142 glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id);
143 glEnable(GL_TEXTURE_2D);
148 int BC_Texture::calculate_texture_size(int w, int *max)
151 for(i = 2; (max && i <= *max) || (!max && i < w); i *= 2)
159 if(max && i > *max) return 16;
163 int BC_Texture::get_texture_id()
168 int BC_Texture::get_texture_w()
173 int BC_Texture::get_texture_h()
178 int BC_Texture::get_texture_components()
180 return texture_components;
183 int BC_Texture::get_window_id()
189 void BC_Texture::draw_texture(
190 float in_x1, float in_y1, float in_x2, float in_y2,
191 float out_x1, float out_y1, float out_x2, float out_y2)
195 glNormal3f(0, 0, 1.0);
196 glTexCoord2f(in_x1, in_y1); glVertex3f(out_x1, out_y1, 0);
197 glTexCoord2f(in_x2, in_y1); glVertex3f(out_x2, out_y1, 0);
198 glTexCoord2f(in_x2, in_y2); glVertex3f(out_x2, out_y2, 0);
199 glTexCoord2f(in_x1, in_y2); glVertex3f(out_x1, out_y2, 0);
204 void BC_Texture::bind(int texture_unit)
210 if(texture_unit >= 0) glActiveTexture(GL_TEXTURE0 + texture_unit);
211 glBindTexture(GL_TEXTURE_2D, texture_id);
212 glEnable(GL_TEXTURE_2D);
213 if(texture_unit >= 0)
215 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
216 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
218 // GL_REPEAT in this case causes the upper left corners of the masks
220 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
223 // Get the texture to alpha blend
224 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
230 void write_ppm(uint8_t *tp, int w, int h, const char *fmt, ...);
232 void BC_Texture::write_tex(const char *fn)
236 glGetIntegerv(GL_ACTIVE_TEXTURE, &prev_id);
237 glActiveTexture(this->texture_id);
238 int w = get_texture_w(), h = get_texture_h();
240 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
241 write_ppm(img, w, h, "%s", fn);
242 glActiveTexture(prev_id);