Implement Array, Cubemap, and Volume texture types (issue #1111).

- Add love.graphics.newArrayImage, newCubeImage, and newVolumeImage.
- Add love.graphics.newCanvas(w, h, layers) and newCanvas(w, h, layers, settings). Add ‘type’ field to the settings table of newCanvas.

- Add new love.graphics.setCanvas variants: setCanvas(canvas, slice), and setCanvas(canvastable) where canvastable is in the format: {{canvas1, layer=2}, {canvas2, face=5}}

- Add Texture:getTextureType, getDepth, getLayerCount, getMipmapCount, and getFormat.

- Remove Image:getData and Image:refresh.
- Add Image:replacePixels(imagedata [, slice] [, mipmap]).

- Update Canvas:newImageData to accept a slice argument.

- Add love.image.newCubeFaces(imagedata).

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-02-20 14:58:13 -04:00
parent d70fe5cb89
commit 73fd45558b
91 changed files with 3160 additions and 2003 deletions
+81 -2
View File
@@ -81,6 +81,7 @@ Font::Font(love::font::Rasterizer *r, const Texture::Filter &f)
if (!r->hasGlyph(9)) // No tab character in the Rasterizer.
useSpacesAsTab = true;
loadVolatile();
++fontCount;
}
@@ -113,6 +114,72 @@ Font::TextureSize Font::getNextTextureSize() const
return size;
}
bool Font::loadVolatile()
{
textureCacheID++;
createTexture();
return true;
}
void Font::createTexture()
{
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
gfx->flushStreamDraws();
Image *image = nullptr;
TextureSize size = {textureWidth, textureHeight};
TextureSize nextsize = getNextTextureSize();
bool recreatetexture = false;
// If we have an existing texture already, we'll try replacing it with a
// larger-sized one rather than creating a second one. Having a single
// texture reduces texture switches and draw calls when rendering.
if ((nextsize.width > size.width || nextsize.height > size.height) && !images.empty())
{
recreatetexture = true;
size = nextsize;
images.pop_back();
}
Image::Settings settings;
image = gfx->newImage(TEXTURE_2D, pixelFormat, size.width, size.height, 1, settings);
image->setFilter(filter);
// Initialize the texture with transparent black.
size_t bpp = getPixelFormatSize(pixelFormat);
std::vector<uint8> emptydata(size.width * size.height * bpp, 0);
Rect rect = {0, 0, size.width, size.height};
image->replacePixels(emptydata.data(), emptydata.size(), rect, 0, 0, false);
images.emplace_back(image, Acquire::NORETAIN);
textureWidth = size.width;
textureHeight = size.height;
rowHeight = textureX = textureY = TEXTURE_PADDING;
// Re-add the old glyphs if we re-created the existing texture object.
if (recreatetexture)
{
textureCacheID++;
std::vector<uint32> glyphstoadd;
for (const auto &glyphpair : glyphs)
glyphstoadd.push_back(glyphpair.first);
glyphs.clear();
for (uint32 g : glyphstoadd)
addGlyph(g);
}
}
void Font::unloadVolatile()
{
}
love::font::GlyphData *Font::getRasterizerGlyphData(uint32 glyph)
{
// Use spaces for the tab 'glyph'.
@@ -178,7 +245,11 @@ const Font::Glyph &Font::addGlyph(uint32 glyph)
// Don't waste space for empty glyphs.
if (w > 0 && h > 0)
{
uploadGlyphToTexture(gd, g);
Image *image = images.back();
g.texture = image;
Rect rect = {textureX, textureY, gd->getWidth(), gd->getHeight()};
image->replacePixels(gd->getData(), gd->getSize(), rect, 0, 0, false);
double tX = (double) textureX, tY = (double) textureY;
double tWidth = (double) textureWidth, tHeight = (double) textureHeight;
@@ -535,7 +606,7 @@ void Font::printv(graphics::Graphics *gfx, const Matrix4 &t, const std::vector<D
req.formats[0] = vertex::CommonFormat::XYf_STus_RGBAub;
req.indexMode = vertex::TriangleIndexMode::QUADS;
req.vertexCount = cmd.vertexcount;
req.textureHandle = cmd.texture;
req.texture = cmd.texture;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
GlyphVertex *vertexdata = (GlyphVertex *) data.stream[0];
@@ -809,6 +880,14 @@ float Font::getLineHeight() const
return lineHeight;
}
void Font::setFilter(const Texture::Filter &f)
{
for (const auto &image : images)
image->setFilter(f);
filter = f;
}
const Texture::Filter &Font::getFilter() const
{
return filter;