Improved performance of Image:refresh

This commit is contained in:
Alex Szpakowski
2013-10-13 16:31:29 -03:00
parent e068aab6ea
commit 43b3629e01
3 changed files with 49 additions and 61 deletions
+40 -52
View File
@@ -39,10 +39,11 @@ float Image::defaultMipmapSharpness = 0.0f;
Image::Image(love::image::ImageData *data) Image::Image(love::image::ImageData *data)
: data(data) : data(data)
, cdata(0) , cdata(0)
, width((float)(data->getWidth())) , width(data->getWidth())
, height((float)(data->getHeight())) , height(data->getHeight())
, paddedWidth(width)
, paddedHeight(height)
, texture(0) , texture(0)
, texCoordScale(1.0, 1.0)
, mipmapSharpness(defaultMipmapSharpness) , mipmapSharpness(defaultMipmapSharpness)
, mipmapsCreated(false) , mipmapsCreated(false)
, compressed(false) , compressed(false)
@@ -55,10 +56,11 @@ Image::Image(love::image::ImageData *data)
Image::Image(love::image::CompressedData *cdata) Image::Image(love::image::CompressedData *cdata)
: data(0) : data(0)
, cdata(cdata) , cdata(cdata)
, width((float)(cdata->getWidth(0))) , width(cdata->getWidth(0))
, height((float)(cdata->getHeight(0))) , height(cdata->getHeight(0))
, paddedWidth(width)
, paddedHeight(height)
, texture(0) , texture(0)
, texCoordScale(1.0, 1.0)
, mipmapSharpness(defaultMipmapSharpness) , mipmapSharpness(defaultMipmapSharpness)
, mipmapsCreated(false) , mipmapsCreated(false)
, compressed(true) , compressed(true)
@@ -77,12 +79,12 @@ Image::~Image()
unload(); unload();
} }
float Image::getWidth() const int Image::getWidth() const
{ {
return width; return width;
} }
float Image::getHeight() const int Image::getHeight() const
{ {
return height; return height;
} }
@@ -122,19 +124,19 @@ void Image::predraw() const
{ {
bind(); bind();
if (texCoordScale.x < 1.0f || texCoordScale.y < 1.0f) if (width != paddedWidth || height != paddedHeight)
{ {
// NPOT image padded to POT size, so the texcoords should be scaled. // NPOT image padded to POT size, so the texcoords should be scaled.
glMatrixMode(GL_TEXTURE); glMatrixMode(GL_TEXTURE);
glPushMatrix(); glPushMatrix();
glScalef(texCoordScale.x, texCoordScale.y, 0.0f); glScalef(float(width) / float(paddedWidth), float(height) / float(paddedHeight), 0.0f);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
} }
} }
void Image::postdraw() const void Image::postdraw() const
{ {
if (texCoordScale.x < 1.0f || texCoordScale.y < 1.0f) if (width != paddedWidth || height != paddedHeight)
{ {
glMatrixMode(GL_TEXTURE); glMatrixMode(GL_TEXTURE);
glPopMatrix(); glPopMatrix();
@@ -310,10 +312,10 @@ void Image::preload()
vertices[0].x = 0; vertices[0].x = 0;
vertices[0].y = 0; vertices[0].y = 0;
vertices[1].x = 0; vertices[1].x = 0;
vertices[1].y = height; vertices[1].y = (float) height;
vertices[2].x = width; vertices[2].x = (float) width;
vertices[2].y = height; vertices[2].y = (float) height;
vertices[3].x = width; vertices[3].x = (float) width;
vertices[3].y = 0; vertices[3].y = 0;
vertices[0].s = 0; vertices[0].s = 0;
@@ -363,26 +365,23 @@ bool Image::loadVolatile()
gl.setTextureWrap(wrap); gl.setTextureWrap(wrap);
setMipmapSharpness(mipmapSharpness); setMipmapSharpness(mipmapSharpness);
float texwidth = width; paddedWidth = width;
float texheight = height; paddedHeight = height;
if (!hasNpot()) if (!hasNpot())
{ {
// NPOT textures will be padded to POT dimensions if necessary. // NPOT textures will be padded to POT dimensions if necessary.
texwidth = next_p2(width); paddedWidth = next_p2(width);
texheight = next_p2(height); paddedHeight = next_p2(height);
} }
// Use a default texture if the size is too big for the system. // Use a default texture if the size is too big for the system.
if (texwidth > gl.getMaxTextureSize() || texheight > gl.getMaxTextureSize()) if (paddedWidth > gl.getMaxTextureSize() || paddedHeight > gl.getMaxTextureSize())
{ {
uploadDefaultTexture(); uploadDefaultTexture();
return true; return true;
} }
texCoordScale.x = width / texwidth;
texCoordScale.y = height / texheight;
// Mutex lock will potentially cover texture loading and mipmap creation. // Mutex lock will potentially cover texture loading and mipmap creation.
love::thread::EmptyLock lock; love::thread::EmptyLock lock;
if (data) if (data)
@@ -390,10 +389,10 @@ bool Image::loadVolatile()
while (glGetError() != GL_NO_ERROR); // Clear errors. while (glGetError() != GL_NO_ERROR); // Clear errors.
if (hasNpot() || (texwidth == width && texheight == height)) if (hasNpot() || (width == paddedWidth && height == paddedHeight))
uploadTexture(); uploadTexture();
else else
uploadTexturePadded(texwidth, texheight); uploadTexturePadded();
GLenum glerr = glGetError(); GLenum glerr = glGetError();
if (glerr != GL_NO_ERROR) if (glerr != GL_NO_ERROR)
@@ -406,7 +405,7 @@ bool Image::loadVolatile()
return true; return true;
} }
void Image::uploadTexturePadded(float p2width, float p2height) void Image::uploadTexturePadded()
{ {
if (isCompressed() && cdata) if (isCompressed() && cdata)
{ {
@@ -419,8 +418,8 @@ void Image::uploadTexturePadded(float p2width, float p2height)
glTexImage2D(GL_TEXTURE_2D, glTexImage2D(GL_TEXTURE_2D,
0, 0,
GL_RGBA8, GL_RGBA8,
(GLsizei)p2width, (GLsizei)paddedWidth,
(GLsizei)p2height, (GLsizei)paddedHeight,
0, 0,
GL_RGBA, GL_RGBA,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
@@ -481,37 +480,26 @@ bool Image::refresh()
if (texture == 0) if (texture == 0)
return false; return false;
while (glGetError() != GL_NO_ERROR); // clear errors if (usingDefaultTexture)
{
uploadDefaultTexture();
return true;
}
// We want this lock to potentially cover mipmap creation as well. // We want this lock to potentially cover mipmap creation as well.
love::thread::EmptyLock lock; love::thread::EmptyLock lock;
bind(); bind();
if (isCompressed() && cdata) if (data && !isCompressed())
{
GLenum format = getCompressedFormat(cdata->getFormat());
glCompressedTexSubImage2DARB(GL_TEXTURE_2D,
0,
0, 0,
cdata->getWidth(0),
cdata->getHeight(0),
format,
GLsizei(cdata->getSize(0)),
cdata->getData(0));
}
else if (data)
{
lock.setLock(data->getMutex()); lock.setLock(data->getMutex());
glTexSubImage2D(GL_TEXTURE_2D,
0, while (glGetError() != GL_NO_ERROR); // Clear errors.
0, 0,
(GLsizei)width, if (hasNpot() || (width == paddedWidth && height == paddedHeight))
(GLsizei)height, uploadTexture();
GL_RGBA, else
GL_UNSIGNED_BYTE, uploadTexturePadded();
data->getData());
}
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
uploadDefaultTexture(); uploadDefaultTexture();
+7 -7
View File
@@ -70,8 +70,8 @@ public:
**/ **/
virtual ~Image(); virtual ~Image();
float getWidth() const; int getWidth() const;
float getHeight() const; int getHeight() const;
const Vertex *getVertices() const; const Vertex *getVertices() const;
@@ -166,7 +166,10 @@ private:
love::image::CompressedData *cdata; love::image::CompressedData *cdata;
// Width and height of the hardware texture. // Width and height of the hardware texture.
float width, height; int width, height;
// Real dimensions of the texture, if it was auto-padded to POT size.
int paddedWidth, paddedHeight;
// OpenGL texture identifier. // OpenGL texture identifier.
GLuint texture; GLuint texture;
@@ -174,9 +177,6 @@ private:
// The source vertices of the image. // The source vertices of the image.
Vertex vertices[4]; Vertex vertices[4];
// The scale applied to texcoords for NPOT images without NPOT support.
love::Vector texCoordScale;
// Mipmap texture LOD bias (sharpness) value. // Mipmap texture LOD bias (sharpness) value.
float mipmapSharpness; float mipmapSharpness;
@@ -198,7 +198,7 @@ private:
void preload(); void preload();
void uploadTexturePadded(float p2width, float p2height); void uploadTexturePadded();
void uploadTexture(); void uploadTexture();
void uploadCompressedMipmaps(); void uploadCompressedMipmaps();
@@ -107,8 +107,8 @@ ParticleSystem::ParticleSystem(Image *image, uint32 size)
, spinStart(0) , spinStart(0)
, spinEnd(0) , spinEnd(0)
, spinVariation(0) , spinVariation(0)
, offsetX(image->getWidth()*0.5f) , offsetX(float(image->getWidth())*0.5f)
, offsetY(image->getHeight()*0.5f) , offsetY(float(image->getHeight())*0.5f)
{ {
if (size == 0 || size > MAX_PARTICLES) if (size == 0 || size > MAX_PARTICLES)
throw love::Exception("Invalid ParticleSystem size."); throw love::Exception("Invalid ParticleSystem size.");