1 // GnashTexture.cpp: GnashImage class used for OpenGL rendering
3 // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "GnashTexture.h"
34 // Returns a string representation of an OpenGL error
35 static const char *gl_get_error_string(GLenum error
)
42 { GL_NO_ERROR
, "no error" },
43 { GL_INVALID_ENUM
, "invalid enumerant" },
44 { GL_INVALID_VALUE
, "invalid value" },
45 { GL_INVALID_OPERATION
, "invalid operation" },
46 { GL_STACK_OVERFLOW
, "stack overflow" },
47 { GL_STACK_UNDERFLOW
, "stack underflow" },
48 { GL_OUT_OF_MEMORY
, "out of memory" },
49 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
50 { GL_INVALID_FRAMEBUFFER_OPERATION_EXT
, "invalid framebuffer operation" },
56 for (i
= 0; gl_errors
[i
].str
; i
++) {
57 if (gl_errors
[i
].val
== error
)
58 return gl_errors
[i
].str
;
63 static inline bool gl_do_check_error(int report
)
66 bool is_error
= false;
67 while ((error
= glGetError()) != GL_NO_ERROR
) {
69 log_error("glError: %s caught\n", gl_get_error_string(error
));
75 static inline void gl_purge_errors(void)
80 static inline bool gl_check_error(void)
82 return gl_do_check_error(1);
85 // glGetIntegerv() wrapper
86 static bool gl_get_param(GLenum param
, unsigned int *pval
)
91 glGetIntegerv(param
, &val
);
99 // Check for GLX extensions (TFP, FBO)
100 static bool check_extension(const char *name
, const char *ext
)
105 if (name
== NULL
|| ext
== NULL
)
108 end
= ext
+ strlen(ext
);
109 name_len
= strlen(name
);
111 n
= strcspn(ext
, " ");
112 if (n
== name_len
&& strncmp(name
, ext
, n
) == 0)
119 GnashTextureFormat::GnashTextureFormat(image::ImageType type
)
122 case image::TYPE_RGB
:
123 _internal_format
= GL_RGB
;
126 case image::TYPE_RGBA
:
127 _internal_format
= GL_RGBA
;
136 GnashTexture::GnashTexture(unsigned int width
, unsigned int height
,
137 image::ImageType type
)
145 D(bug("GnashTexture::GnashTexture()\n"));
150 GnashTexture::~GnashTexture()
152 D(bug("GnashTexture::~GnashTexture()\n"));
155 glDeleteTextures(1, &_texture
);
160 bool GnashTexture::init()
162 // XXX: we only support NPOT textures
163 const char *gl_extensions
= (const char *)glGetString(GL_EXTENSIONS
);
164 if (!check_extension("GL_ARB_texture_non_power_of_two", gl_extensions
))
169 if (_width
== 0 || _height
== 0)
172 glGenTextures(1, &_texture
);
177 glDeleteTextures(1, &_texture
);
181 glPixelStorei(GL_UNPACK_ALIGNMENT
, internal_format() == GL_RGBA
? 4 : 1);
182 glTexImage2D(GL_TEXTURE_2D
, 0, internal_format(), _width
, _height
, 0,
183 format(), GL_UNSIGNED_BYTE
, NULL
);
188 // Bind texture, preserve previous texture state
189 bool GnashTexture::bind()
191 TextureState
* const ts
= &_texture_state
;
194 ts
->was_enabled
= glIsEnabled(GL_TEXTURE_2D
);
196 if (!ts
->was_enabled
)
197 glEnable(GL_TEXTURE_2D
);
198 else if (gl_get_param(GL_TEXTURE_BINDING_2D
, &ts
->old_texture
))
199 ts
->was_bound
= _texture
== ts
->old_texture
;
203 if (!ts
->was_bound
) {
205 glBindTexture(GL_TEXTURE_2D
, _texture
);
206 if (gl_check_error())
210 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
211 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
212 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
213 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
217 // Release texture, restore previous texture state
218 void GnashTexture::release()
220 TextureState
* const ts
= &_texture_state
;
221 if (!ts
->was_bound
&& ts
->old_texture
)
222 glBindTexture(GL_TEXTURE_2D
, ts
->old_texture
);
223 if (!ts
->was_enabled
)
224 glDisable(GL_TEXTURE_2D
);
228 // Update texture with data
229 void GnashTexture::update(const boost::uint8_t *data
)
231 D(bug("GnashTexture::update(): data %p, size %dx%d\n", data
, _width
, _height
));
234 glTexSubImage2D(GL_TEXTURE_2D
, 0,
235 0, 0, _width
, _height
,
236 format(), GL_UNSIGNED_BYTE
, data
);