]>
Dogcows Code - chaz/yoink/blob - src/Moof/Texture.cc
2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *******************************************************************************/
29 #include <cstring> // memcpy
31 #include <boost/bind.hpp>
34 #include <SDL/SDL_image.h>
36 #include "Dispatcher.hh"
38 #include "Mippleton.hh"
47 * The texture implementation just contains all the information about the image
48 * which is worth having in memory. The image data itself is not worth keeping
49 * in memory if the texture has been loaded to GL, but the name of the resource
50 * is retained so that it can be reloaded if necessary. The implementation is a
51 * mippleton so that multiple texture objects can share the same internal
52 * objects and avoid having duplicate textures loaded to GL.
55 class Texture::Impl
: public Mippleton
<Impl
>
59 * Delete the texture (if it is loaded) from GL.
66 if (object_
== globalObject_
)
71 glDeleteTextures(1, &object_
);
77 * If the GL context was recreated, we need to reload the texture. This may
78 * involve reading it from disk again, but hopefully the OS was smart enough
79 * to cache it if the client has plenty of RAM.
82 void contextRecreated(const Notification
* note
)
84 object_
= globalObject_
= 0;
89 * This is a helper method used by some of the texture loading code. It
90 * returns the first power of two which is greater than the input value.
93 static int powerOfTwo(int input
)
105 static void flipSurface(SDL_Surface
* image
)
107 unsigned char* pixels
= (Uint8
*)(image
->pixels
);
109 unsigned pitch
= image
->pitch
;
110 unsigned char line
[pitch
];
113 int yEnd
= image
->h
- 1;
115 if (SDL_MUSTLOCK(image
)) SDL_LockSurface(image
);
116 while (yBegin
< yEnd
)
118 memcpy(line
, pixels
+ pitch
* yBegin
, pitch
);
119 memcpy(pixels
+ pitch
* yBegin
, pixels
+ pitch
* yEnd
, pitch
);
120 memcpy(pixels
+ pitch
* yEnd
, line
, pitch
);
124 if (SDL_MUSTLOCK(image
)) SDL_UnlockSurface(image
);
130 * Construction is initialization.
133 explicit Impl(const std::string
& name
) :
134 Mippleton
<Impl
>(name
),
139 minFilter_(GL_NEAREST
),
140 magFilter_(GL_NEAREST
),
147 // we want to know when the GL context is recreated
148 Dispatcher::getInstance().addHandler("video.context_recreated",
149 boost::bind(&Impl::contextRecreated
, this, _1
), this);
156 SDL_FreeSurface(surface_
);
161 Dispatcher::getInstance().removeHandler(this);
166 * Adapted from some public domain code. This stuff is common enough that
167 * it really should be included in SDL_image... We need this because images
168 * loaded with SDL_image aren't exactly GL-ready right out of the box. This
169 * method makes them ready.
172 static SDL_Surface
* prepareImageForGL(SDL_Surface
* surface
)
174 int w
= powerOfTwo(surface
->w
);
175 int h
= powerOfTwo(surface
->h
);
177 // 2. OpenGL textures make more sense within the coordinate system when
178 // they are "upside down," so let's flip it.
180 flipSurface(surface
);
182 // 1. OpenGL images must (generally) have dimensions of a power-of-two.
183 // If this one doesn't, we can at least be more friendly by expanding
184 // the dimensions so that they are, though there will be some empty
185 // space within the range of normal texture coordinates. It's better if
186 // textures are the right size to begin with.
188 SDL_Surface
* image
= SDL_CreateRGBSurface
193 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
211 Uint32 savedFlags
= surface
->flags
&(SDL_SRCALPHA
|SDL_RLEACCELOK
);
212 Uint8 savedAlpha
= surface
->format
->alpha
;
213 if (savedFlags
& SDL_SRCALPHA
)
215 SDL_SetAlpha(surface
, 0, 0);
218 SDL_Rect srcArea
, destArea
;
219 srcArea
.x
= 0; destArea
.x
= 0;
220 srcArea
.y
= 0; destArea
.y
= h
- surface
->h
;
221 srcArea
.w
= surface
->w
;
222 srcArea
.h
= surface
->h
;
223 SDL_BlitSurface(surface
, &srcArea
, image
, &destArea
);
225 if (savedFlags
& SDL_SRCALPHA
)
227 SDL_SetAlpha(surface
, savedFlags
, savedAlpha
);
234 * Use SDL_image to load images from file. A surface with the image data is
236 * @return Image data.
241 SDL_Surface
* surface
;
243 surface
= IMG_Load(Texture::getPath(getName()).c_str());
247 logWarning("texture not found: %s", getName().c_str());
248 throw Exception(Exception::FILE_NOT_FOUND
);
251 SDL_Surface
* temp
= prepareImageForGL(surface
);
252 SDL_FreeSurface(surface
);
256 throw Exception(Exception::OPENGL_ERROR
);
259 if (temp
->format
->BytesPerPixel
== 3)
263 else if (temp
->format
->BytesPerPixel
== 4)
269 SDL_FreeSurface(temp
);
270 throw Exception(Exception::BAD_IMAGE_FORMAT
);
281 * Upload the image to GL so that it will be accessible by a much more
282 * manageable handle and hopefully reside in video memory.
293 if (!surface_
) loadFromFile();
295 glGenTextures(1, &object_
);
296 glBindTexture(GL_TEXTURE_2D
, object_
);
313 SDL_FreeSurface(surface_
);
319 * Sets some texture properties such as the filters and external coordinate
325 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, minFilter_
);
326 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, magFilter_
);
327 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrapS_
);
328 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrapT_
);
331 inline void setMinFilter(GLuint filter
)
335 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, minFilter_
);
338 inline void setMagFilter(GLuint filter
)
342 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, magFilter_
);
345 inline void setWrapS(GLuint wrap
)
349 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrapS_
);
352 inline void setWrapT(GLuint wrap
)
356 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrapT_
);
366 if (object_
!= globalObject_
)
368 glBindTexture(GL_TEXTURE_2D
, object_
);
369 globalObject_
= object_
;
374 SDL_Surface
* surface_
;
375 unsigned width_
; ///< Horizontal dimension of the image.
376 unsigned height_
; ///< Vertical dimension.
378 GLuint mode_
; ///< Depth of the image, GL_RGB or GL_RGBA.
379 GLuint minFilter_
; ///< Minifcation filter.
380 GLuint magFilter_
; ///< Magnification filter.
381 GLuint wrapS_
; ///< Wrapping behavior horizontally.
382 GLuint wrapT_
; ///< Wrapping behavior vertically.
384 GLuint object_
; ///< GL texture handle.
385 static GLuint globalObject_
; ///< Global GL texture handle.
388 GLuint
Texture::Impl::globalObject_
= 0;
391 Texture::Texture(const std::string
& name
) :
393 impl_(Texture::Impl::getInstance(name
)) {}
397 * Bind the GL texture for mapping, etc.
400 void Texture::bind() const
408 * Get the texture object, for the curious.
411 GLuint
Texture::getObject() const
414 return impl_
->object_
;
418 void Texture::resetBind()
420 glBindTexture(GL_TEXTURE_2D
, 0);
421 Impl::globalObject_
= 0;
425 unsigned Texture::getWidth() const
428 return impl_
->width_
;
431 unsigned Texture::getHeight() const
434 return impl_
->height_
;
438 void Texture::setMinFilter(GLuint filter
)
441 impl_
->setMinFilter(filter
);
444 void Texture::setMagFilter(GLuint filter
)
447 impl_
->setMagFilter(filter
);
450 void Texture::setWrapS(GLuint wrap
)
453 impl_
->setWrapS(wrap
);
456 void Texture::setWrapT(GLuint wrap
)
459 impl_
->setWrapT(wrap
);
463 std::string
Texture::getPath(const std::string
& name
)
465 std::string path
= Resource::getPath("textures/" + name
+ ".png");
472 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.057282 seconds and 4 git commands to generate.