Code cleanup

--HG--
branch : image-CompressedData
This commit is contained in:
Alex Szpakowski
2013-04-05 18:55:44 -03:00
parent 5301026f3c
commit 8a8adcce39
11 changed files with 129 additions and 90 deletions
+6 -8
View File
@@ -81,7 +81,6 @@ bool Parser::isDDS(const void *data, size_t dataSize)
// Data must be big enough for both headers plus the magic value.
if (dataSize < (sizeof(uint32_t) + sizeof(DDSHeader) + sizeof(DDSHeader10)))
return false;
}
return true;
@@ -106,7 +105,6 @@ Parser::Parser(const Parser &other)
if ((options & OPTIONS_COPY_DATA) && img.dataSize > 0)
{
uint8_t *data = 0;
try
{
data = new uint8_t[img.dataSize];
@@ -116,7 +114,7 @@ Parser::Parser(const Parser &other)
clearData();
throw;
}
memcpy(data, it->data, img.dataSize);
img.data = data;
}
@@ -164,7 +162,9 @@ Format Parser::parseDDSFormat(const DDSPixelFormat &fmt) const
else if (fmt.fourCC == FourCC('D','X','T','5'))
return FORMAT_DXT5;
else if (fmt.fourCC == FourCC('A','T','I','2'))
return FORMAT_BC5u;
return FORMAT_BC5;
else if (fmt.fourCC == FourCC('B','C','5','S'))
return FORMAT_BC5s;
}
return FORMAT_UNKNOWN;
@@ -196,7 +196,7 @@ Format Parser::parseDX10Format(DXGIFormat fmt) const
break;
case DXGI_FORMAT_BC5_TYPELESS:
case DXGI_FORMAT_BC5_UNORM:
f = FORMAT_BC5u;
f = FORMAT_BC5;
break;
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
@@ -221,7 +221,7 @@ size_t Parser::parseImageSize(Format fmt, int width, int height) const
case FORMAT_DXT3:
case FORMAT_DXT5:
case FORMAT_BC5s:
case FORMAT_BC5u:
case FORMAT_BC5:
case FORMAT_BC7:
case FORMAT_BC7srgb:
{
@@ -269,7 +269,6 @@ bool Parser::parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int
if (options & OPTIONS_COPY_DATA)
{
uint8_t *newData = 0;
try
{
newData = new uint8_t[img.dataSize];
@@ -280,7 +279,6 @@ bool Parser::parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int
clearData();
throw;
}
memcpy(newData, &data[offset], img.dataSize);
img.data = newData;
}
+1 -1
View File
@@ -43,7 +43,7 @@ enum Format
FORMAT_DXT3,
FORMAT_DXT5,
FORMAT_BC5s, // Signed.
FORMAT_BC5u, // Unsigned.
FORMAT_BC5, // Unsigned.
FORMAT_BC7,
FORMAT_BC7srgb, // sRGB color space.
FORMAT_UNKNOWN
+5 -1
View File
@@ -224,7 +224,11 @@ void Graphics::present()
void Graphics::setIcon(Image *image)
{
currentWindow->setIcon(image->getData());
love::image::ImageData *data = image->getData();
if (data)
currentWindow->setIcon(data);
else
throw love::Exception("Cannot use compressed image data to set an icon.");
}
void Graphics::setCaption(const char *caption)
+86 -67
View File
@@ -24,8 +24,6 @@
#include <cstring> // For memcpy
#include <algorithm> // for min/max
#include <iostream>
namespace love
{
namespace graphics
@@ -146,81 +144,102 @@ void Image::drawq(love::graphics::Quad *quad, float x, float y, float angle, flo
drawv(t, v);
}
void Image::checkMipmapsCreated()
void Image::uploadCompressedMipmaps()
{
if (mipmapsCreated || (filter.mipmap != FILTER_NEAREST && filter.mipmap != FILTER_LINEAR))
if (!isCompressed || !cdata || !hasCompressedTextureSupport(cdata->getType()))
return;
if (!(isCompressed && cdata) && !hasMipmapSupport())
throw love::Exception("Mipmap filtering is not supported on this system.");
// Some old drivers claim support for NPOT textures, but fail when creating mipmaps.
// we can't detect which systems will do this, so we fail gracefully for all NPOT images.
int w = int(width), h = int(height);
if (!isCompressed && (w != next_p2(w) || h != next_p2(h)))
throw love::Exception("Cannot create mipmaps: image does not have power of two dimensions.");
bind();
if (isCompressed && cdata && hasCompressedTextureSupport(cdata->getType()))
int numMipmaps = cdata->getNumMipmaps();
// We have to inform OpenGL if the image doesn't have all mipmap levels.
if (GLEE_VERSION_1_2 || GLEE_SGIS_texture_lod)
{
int numMipmaps = cdata->getNumMipmaps();
// We have to inform OpenGL if the image doesn't have all mipmap levels.
if (GLEE_VERSION_1_2 || GLEE_SGIS_texture_lod)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMipmaps - 1);
else if (cdata->getWidth(numMipmaps-1) > 1 || cdata->getHeight(numMipmaps-1) > 1)
{
// Telling OpenGL to ignore certain levels isn't always supported.
throw love::Exception("Cannot load mipmaps: "
"compressed image does not have all required levels.");
}
GLenum format = getCompressedFormat(cdata->getType());
for (int i = 1; i < numMipmaps; i++)
{
glCompressedTexImage2DARB(GL_TEXTURE_2D,
i,
format,
cdata->getWidth(i),
cdata->getHeight(i),
0,
GLsizei(cdata->getSize(i)),
cdata->getData(i));
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, numMipmaps - 1);
}
else if (data && hasNpot() && (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object))
else if (cdata->getWidth(numMipmaps-1) > 1 || cdata->getHeight(numMipmaps-1) > 1)
{
// Telling OpenGL to ignore certain levels isn't always supported.
throw love::Exception("Cannot load mipmaps: "
"compressed image does not have all required levels.");
}
for (int i = 1; i < numMipmaps; i++)
{
glCompressedTexImage2DARB(GL_TEXTURE_2D,
i,
getCompressedFormat(cdata->getType()),
cdata->getWidth(i),
cdata->getHeight(i),
0,
GLsizei(cdata->getSize(i)),
cdata->getData(i));
}
}
void Image::createMipmaps()
{
if (!data)
return;
if (!hasMipmapSupport())
throw love::Exception("Mipmap filtering is not supported on this system.");
// Some old drivers claim support for NPOT textures, but fail when creating
// mipmaps. We can't detect which systems will do this, so we fail gracefully
// for all NPOT images.
int w = int(width), h = int(height);
if (w != next_p2(w) || h != next_p2(h))
{
throw love::Exception("Cannot create mipmaps: "
"image does not have power of two dimensions.");
}
bind();
if (hasNpot() && (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object))
{
// AMD/ATI drivers have several bugs when generating mipmaps,
// re-uploading the entire base image seems to be required.
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA8,
(GLsizei)width,
(GLsizei)height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
data->getData());
0,
GL_RGBA8,
(GLsizei)width,
(GLsizei)height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
data->getData());
// More bugs: http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation
glEnable(GL_TEXTURE_2D);
glGenerateMipmap(GL_TEXTURE_2D);
}
else if (data)
else
{
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexSubImage2D(GL_TEXTURE_2D,
0,
0,
0,
(GLsizei)width,
(GLsizei)height,
GL_RGBA,
GL_UNSIGNED_BYTE,
data->getData());
0,
0,
0,
(GLsizei)width,
(GLsizei)height,
GL_RGBA,
GL_UNSIGNED_BYTE,
data->getData());
}
}
void Image::checkMipmapsCreated()
{
if (mipmapsCreated || filter.mipmap == FILTER_NONE)
return;
if (isCompressed && cdata && hasCompressedTextureSupport(cdata->getType()))
uploadCompressedMipmaps();
else if (data)
createMipmaps();
else
return;
@@ -262,7 +281,9 @@ void Image::setMipmapSharpness(float sharpness)
mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f);
bind();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapSharpness); // negative bias is sharper
// negative bias is sharper
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapSharpness);
}
else
mipmapSharpness = 0.0f;
@@ -325,7 +346,7 @@ bool Image::loadVolatile()
if (image::CompressedData::getConstant(cdata->getType(), str))
{
throw love::Exception("Cannot create image: "
"%s compressed images are not supported on this system.", str);
"%s compressed images are not supported on this system.", str);
}
else
throw love::Exception("cannot create image: format is not supported on this system.");
@@ -362,17 +383,15 @@ bool Image::loadVolatilePOT()
if (isCompressed && cdata)
{
if (s != 1.0f || t != 1.0f)
if (s < 1.0f || t < 1.0f)
{
throw love::Exception("Cannot create image: "
"NPOT compressed images are not supported on this system.");
"compressed NPOT images are not supported on this system.");
}
GLenum format = getCompressedFormat(cdata->getType());
glCompressedTexImage2DARB(GL_TEXTURE_2D,
0,
format,
getCompressedFormat(cdata->getType()),
cdata->getWidth(0),
cdata->getHeight(0),
0,
@@ -520,7 +539,7 @@ GLenum Image::getCompressedFormat(image::CompressedData::TextureType type) const
return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
case image::CompressedData::TYPE_BC5s:
return GL_COMPRESSED_SIGNED_RG_RGTC2;
case image::CompressedData::TYPE_BC5u:
case image::CompressedData::TYPE_BC5:
return GL_COMPRESSED_RG_RGTC2;
case image::CompressedData::TYPE_BC7:
return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
@@ -569,8 +588,8 @@ bool Image::hasCompressedTextureSupport(image::CompressedData::TextureType type)
return GLEE_EXT_texture_compression_s3tc;
case image::CompressedData::TYPE_BC5s:
case image::CompressedData::TYPE_BC5u:
return (GLEE_VERSION_3_0 || GLEE_ARB_texture_compression_rgtc);
case image::CompressedData::TYPE_BC5:
return (GLEE_VERSION_3_0 || GLEE_ARB_texture_compression_rgtc || GLEE_EXT_texture_compression_rgtc);
case image::CompressedData::TYPE_BC7:
case image::CompressedData::TYPE_BC7srgb:
+2
View File
@@ -180,6 +180,8 @@ private:
bool loadVolatilePOT();
bool loadVolatileNPOT();
void uploadCompressedMipmaps();
void createMipmaps();
void checkMipmapsCreated();
static float maxMipmapSharpness;
@@ -158,7 +158,14 @@ int w_present(lua_State *)
int w_setIcon(lua_State *L)
{
Image *image = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
instance->setIcon(image);
try
{
instance->setIcon(image);
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
return 0;
}
@@ -1139,7 +1146,7 @@ int w_isSupported(lua_State *L)
supported = false;
break;
case Graphics::SUPPORT_BC5:
if (!Image::hasCompressedTextureSupport(image::CompressedData::TYPE_BC5u))
if (!Image::hasCompressedTextureSupport(image::CompressedData::TYPE_BC5))
supported = false;
break;
case Graphics::SUPPORT_BC7:
+1 -1
View File
@@ -112,7 +112,7 @@ StringMap<CompressedData::TextureType, CompressedData::TYPE_MAX_ENUM>::Entry Com
{"dxt3", CompressedData::TYPE_DXT3},
{"dxt5", CompressedData::TYPE_DXT5},
{"bc5s", CompressedData::TYPE_BC5s},
{"bc5u", CompressedData::TYPE_BC5u},
{"bc5", CompressedData::TYPE_BC5},
{"bc7", CompressedData::TYPE_BC7},
{"bc7srgb", CompressedData::TYPE_BC7srgb},
};
+6 -3
View File
@@ -36,19 +36,22 @@ namespace love
namespace image
{
//
// CompressedData represents image data which is designed to be uploaded to the
// GPU and rendered in its compressed form, without being un-compressed.
// http://renderingpipeline.com/2012/07/texture-compression/
class CompressedData : public Data
{
public:
//
// Types of compressed image data.
enum TextureType
{
TYPE_DXT1,
TYPE_DXT3,
TYPE_DXT5,
TYPE_BC5s,
TYPE_BC5u,
TYPE_BC5,
TYPE_BC7,
TYPE_BC7srgb,
TYPE_MAX_ENUM
+10 -4
View File
@@ -79,22 +79,28 @@ public:
virtual ImageData *newImageData(int width, int height, void *data) = 0;
/**
*
* Creates new CompressedData from a file.
* @param file The file containing the compressed image data.
* @return The new CompressedData.
**/
virtual CompressedData *newCompressedData(love::filesystem::File *file) = 0;
/**
*
* Creates new CompressedData from a raw Data.
* @param data The object containing the compressed image data.
* @return The new CompressedData.
**/
virtual CompressedData *newCompressedData(Data *data) = 0;
/**
*
* Determines whether a File is Compressed image data or not.
* @param file The file to test.
**/
virtual bool isCompressed(love::filesystem::File *file) = 0;
/**
*
* Determines whether a raw Data is Compressed image data or not.
* @param data The data to test.
**/
virtual bool isCompressed(Data *data) = 0;
+2 -2
View File
@@ -67,8 +67,8 @@ bool CompressedData::convertFormat(dds::Format ddsformat)
case dds::FORMAT_BC5s:
type = TYPE_BC5s;
break;
case dds::FORMAT_BC5u:
type = TYPE_BC5u;
case dds::FORMAT_BC5:
type = TYPE_BC5;
break;
case dds::FORMAT_BC7:
type = TYPE_BC7;
+1 -1
View File
@@ -105,7 +105,7 @@ bool Image::isCompressed(love::filesystem::File *file)
// Check whether the actual data is compressed.
Data *data = file->read();
bool compressed = CompressedData::isCompressed(data);
bool compressed = isCompressed(data);
data->release();
return compressed;