1 /** 2 * Copyright (c) 2006-2011 LOVE Development Team 3 * 4 * This software is provided 'as-is', without any express or implied 5 * warranty. In no event will the authors be held liable for any damages 6 * arising from the use of this software. 7 * 8 * Permission is granted to anyone to use this software for any purpose, 9 * including commercial applications, and to alter it and redistribute it 10 * freely, subject to the following restrictions: 11 * 12 * 1. The origin of this software must not be misrepresented; you must not 13 * claim that you wrote the original software. If you use this software 14 * in a product, an acknowledgment in the product documentation would be 15 * appreciated but is not required. 16 * 2. Altered source versions must be plainly marked as such, and must not be 17 * misrepresented as being the original software. 18 * 3. This notice may not be removed or altered from any source distribution. 19 **/ 20 21 #include "Image.h" 22 23 // STD 24 #include <cstring> // For memcpy 25 26 namespace love 27 { 28 namespace graphics 29 { 30 namespace opengl 31 { 32 Image(love::image::ImageData * data)33 Image::Image(love::image::ImageData * data) 34 : width((float)(data->getWidth())), height((float)(data->getHeight())), texture(0) 35 { 36 data->retain(); 37 this->data = data; 38 39 memset(vertices, 255, sizeof(vertex)*4); 40 41 vertices[0].x = 0; vertices[0].y = 0; 42 vertices[1].x = 0; vertices[1].y = height; 43 vertices[2].x = width; vertices[2].y = height; 44 vertices[3].x = width; vertices[3].y = 0; 45 46 vertices[0].s = 0; vertices[0].t = 0; 47 vertices[1].s = 0; vertices[1].t = 1; 48 vertices[2].s = 1; vertices[2].t = 1; 49 vertices[3].s = 1; vertices[3].t = 0; 50 51 } 52 ~Image()53 Image::~Image() 54 { 55 if(data != 0) 56 data->release(); 57 unload(); 58 } 59 getWidth() const60 float Image::getWidth() const 61 { 62 return width; 63 } 64 getHeight() const65 float Image::getHeight() const 66 { 67 return height; 68 } 69 getVertices() const70 const vertex * Image::getVertices() const 71 { 72 return vertices; 73 } 74 getData() const75 love::image::ImageData * Image::getData() const 76 { 77 return data; 78 } 79 getRectangleVertices(int x,int y,int w,int h,vertex * vertices) const80 void Image::getRectangleVertices(int x, int y, int w, int h, vertex * vertices) const 81 { 82 // Check upper. 83 x = (x+w > (int)width) ? (int)width-w : x; 84 y = (y+h > (int)height) ? (int)height-h : y; 85 86 // Check lower. 87 x = (x < 0) ? 0 : x; 88 y = (y < 0) ? 0 : y; 89 90 vertices[0].x = 0; vertices[0].y = 0; 91 vertices[1].x = 0; vertices[1].y = (float)h; 92 vertices[2].x = (float)w; vertices[2].y = (float)h; 93 vertices[3].x = (float)w; vertices[3].y = 0; 94 95 float tx = (float)x/width; 96 float ty = (float)y/height; 97 float tw = (float)w/width; 98 float th = (float)h/height; 99 100 vertices[0].s = tx; vertices[0].t = ty; 101 vertices[1].s = tx; vertices[1].t = ty+th; 102 vertices[2].s = tx+tw; vertices[2].t = ty+th; 103 vertices[3].s = tx+tw; vertices[3].t = ty; 104 } 105 draw(float x,float y,float angle,float sx,float sy,float ox,float oy) const106 void Image::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const 107 { 108 static Matrix t; 109 110 t.setTransformation(x, y, angle, sx, sy, ox, oy); 111 drawv(t, vertices); 112 } 113 drawq(Quad * quad,float x,float y,float angle,float sx,float sy,float ox,float oy) const114 void Image::drawq(Quad * quad, float x, float y, float angle, float sx, float sy, float ox, float oy) const 115 { 116 static Matrix t; 117 const vertex * v = quad->getVertices(); 118 119 t.setTransformation(x, y, angle, sx, sy, ox, oy); 120 drawv(t, v); 121 } 122 setFilter(Image::Filter f)123 void Image::setFilter(Image::Filter f) 124 { 125 GLint gmin, gmag; 126 gmin = gmag = 0; // so that they're not used uninitialized 127 128 switch(f.min) 129 { 130 case FILTER_LINEAR: 131 gmin = GL_LINEAR; 132 break; 133 case FILTER_NEAREST: 134 gmin = GL_NEAREST; 135 break; 136 default: 137 break; 138 } 139 140 switch(f.mag) 141 { 142 case FILTER_LINEAR: 143 gmag = GL_LINEAR; 144 break; 145 case FILTER_NEAREST: 146 gmag = GL_NEAREST; 147 break; 148 default: 149 break; 150 } 151 152 bind(); 153 154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gmin); 155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gmag); 156 } 157 getFilter() const158 Image::Filter Image::getFilter() const 159 { 160 bind(); 161 162 GLint gmin, gmag; 163 164 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &gmin); 165 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &gmag); 166 167 Image::Filter f; 168 169 switch(gmin) 170 { 171 case GL_NEAREST: 172 f.min = FILTER_NEAREST; 173 break; 174 case GL_LINEAR: 175 default: 176 f.min = FILTER_LINEAR; 177 break; 178 } 179 180 switch(gmin) 181 { 182 case GL_NEAREST: 183 f.mag = FILTER_NEAREST; 184 break; 185 case GL_LINEAR: 186 default: 187 f.mag = FILTER_LINEAR; 188 break; 189 } 190 191 return f; 192 } 193 setWrap(Image::Wrap w)194 void Image::setWrap(Image::Wrap w) 195 { 196 GLint gs, gt; 197 198 switch(w.s) 199 { 200 case WRAP_CLAMP: 201 gs = GL_CLAMP_TO_EDGE; 202 break; 203 case WRAP_REPEAT: 204 default: 205 gs = GL_REPEAT; 206 break; 207 } 208 209 switch(w.t) 210 { 211 case WRAP_CLAMP: 212 gt = GL_CLAMP_TO_EDGE; 213 break; 214 case WRAP_REPEAT: 215 default: 216 gt = GL_REPEAT; 217 break; 218 } 219 220 bind(); 221 222 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gs); 223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gt); 224 } 225 getWrap() const226 Image::Wrap Image::getWrap() const 227 { 228 bind(); 229 230 GLint gs, gt; 231 232 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &gs); 233 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, >); 234 235 Wrap w; 236 237 switch(gs) 238 { 239 case GL_CLAMP_TO_EDGE: 240 w.s = WRAP_CLAMP; 241 break; 242 case GL_REPEAT: 243 default: 244 w.s = WRAP_REPEAT; 245 break; 246 } 247 248 switch(gt) 249 { 250 case GL_CLAMP_TO_EDGE: 251 w.t = WRAP_CLAMP; 252 break; 253 case GL_REPEAT: 254 default: 255 w.t = WRAP_REPEAT; 256 break; 257 } 258 259 return w; 260 } 261 bind() const262 void Image::bind() const 263 { 264 if(texture != 0) 265 glBindTexture(GL_TEXTURE_2D,texture); 266 } 267 load()268 bool Image::load() 269 { 270 return loadVolatile(); 271 } 272 unload()273 void Image::unload() 274 { 275 return unloadVolatile(); 276 } 277 loadVolatile()278 bool Image::loadVolatile() 279 { 280 glGenTextures(1,(GLuint*)&texture); 281 glBindTexture(GL_TEXTURE_2D, texture); 282 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 284 285 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 286 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 287 288 glTexImage2D(GL_TEXTURE_2D, 289 0, 290 GL_RGBA8, 291 (GLsizei)width, 292 (GLsizei)height, 293 0, 294 GL_RGBA, 295 GL_UNSIGNED_BYTE, 296 data->getData()); 297 298 setFilter(settings.filter); 299 setWrap(settings.wrap); 300 301 return true; 302 } 303 unloadVolatile()304 void Image::unloadVolatile() 305 { 306 settings.filter = getFilter(); 307 settings.wrap = getWrap(); 308 // Delete the hardware texture. 309 if(texture != 0) 310 { 311 glDeleteTextures(1, (GLuint*)&texture); 312 texture = 0; 313 } 314 } 315 drawv(const Matrix & t,const vertex * v) const316 void Image::drawv(const Matrix & t, const vertex * v) const 317 { 318 bind(); 319 320 glPushMatrix(); 321 322 glMultMatrixf((const GLfloat*)t.getElements()); 323 324 glEnableClientState(GL_VERTEX_ARRAY); 325 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 326 glVertexPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&v[0].x); 327 glTexCoordPointer(2, GL_FLOAT, sizeof(vertex), (GLvoid*)&v[0].s); 328 glDrawArrays(GL_QUADS, 0, 4); 329 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 330 glDisableClientState(GL_VERTEX_ARRAY); 331 332 glPopMatrix(); 333 } 334 335 } // opengl 336 } // graphics 337 } // love 338