mirror of https://github.com/bjornbytes/lovr.git
Make textures immutable and fix font atlas resizing;
This commit is contained in:
parent
ef0ba9124d
commit
eecc675043
|
@ -46,12 +46,8 @@ Font* lovrFontCreate(FontData* fontData) {
|
|||
lovrFontExpandTexture(font);
|
||||
}
|
||||
|
||||
// Texture
|
||||
TextureData* textureData = lovrTextureDataGetBlank(font->atlas.width, font->atlas.height, 0x0, FORMAT_RGB);
|
||||
TextureFilter filter = { .mode = FILTER_BILINEAR };
|
||||
font->texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, false);
|
||||
lovrTextureSetFilter(font->texture, filter);
|
||||
lovrTextureSetWrap(font->texture, (TextureWrap) { .s = WRAP_CLAMP, .t = WRAP_CLAMP });
|
||||
// Create the texture
|
||||
lovrFontCreateTexture(font);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -298,9 +294,8 @@ void lovrFontExpandTexture(Font* font) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Resize the texture storage
|
||||
lovrTextureDataResize(font->texture->slices[0], atlas->width, atlas->height, 0x0);
|
||||
lovrTextureRefresh(font->texture);
|
||||
// Recreate the texture
|
||||
lovrFontCreateTexture(font);
|
||||
|
||||
// Reset the cursor
|
||||
atlas->x = atlas->padding;
|
||||
|
@ -315,3 +310,15 @@ void lovrFontExpandTexture(Font* font) {
|
|||
lovrFontAddGlyph(font, glyph);
|
||||
}
|
||||
}
|
||||
|
||||
void lovrFontCreateTexture(Font* font) {
|
||||
if (font->texture) {
|
||||
lovrRelease(&font->texture->ref);
|
||||
}
|
||||
|
||||
TextureData* textureData = lovrTextureDataGetBlank(font->atlas.width, font->atlas.height, 0x0, FORMAT_RGB);
|
||||
TextureFilter filter = { .mode = FILTER_BILINEAR };
|
||||
font->texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, false);
|
||||
lovrTextureSetFilter(font->texture, filter);
|
||||
lovrTextureSetWrap(font->texture, (TextureWrap) { .s = WRAP_CLAMP, .t = WRAP_CLAMP });
|
||||
}
|
||||
|
|
|
@ -56,3 +56,4 @@ void lovrFontSetPixelDensity(Font* font, float pixelDensity);
|
|||
Glyph* lovrFontGetGlyph(Font* font, uint32_t codepoint);
|
||||
void lovrFontAddGlyph(Font* font, Glyph* glyph);
|
||||
void lovrFontExpandTexture(Font* font);
|
||||
void lovrFontCreateTexture(Font* font);
|
||||
|
|
|
@ -5,36 +5,70 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void lovrTextureCreateStorage(Texture* texture) {
|
||||
static void lovrTextureUpload(Texture* texture) {
|
||||
TextureData* textureData = texture->slices[0];
|
||||
texture->width = textureData->width;
|
||||
texture->height = textureData->height;
|
||||
|
||||
if (textureData->format.compressed || texture->type == TEXTURE_CUBE) {
|
||||
return;
|
||||
}
|
||||
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
int mipmapCount = log2(MAX(w, h)) + 1;
|
||||
GLenum internalFormat;
|
||||
if (lovrGraphicsIsGammaCorrect() && texture->srgb) {
|
||||
internalFormat = textureData->format.glInternalFormat.srgb;
|
||||
} else {
|
||||
internalFormat = textureData->format.glInternalFormat.linear;
|
||||
}
|
||||
GLenum format = textureData->format.glFormat;
|
||||
// Allocate storage
|
||||
if (!textureData->format.compressed && texture->type != TEXTURE_CUBE) {
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
int mipmapCount = log2(MAX(w, h)) + 1;
|
||||
GLenum internalFormat;
|
||||
if (lovrGraphicsIsGammaCorrect() && texture->srgb) {
|
||||
internalFormat = textureData->format.glInternalFormat.srgb;
|
||||
} else {
|
||||
internalFormat = textureData->format.glInternalFormat.linear;
|
||||
}
|
||||
GLenum format = textureData->format.glFormat;
|
||||
#ifndef EMSCRIPTEN
|
||||
if (GLAD_GL_ARB_texture_storage) {
|
||||
if (GLAD_GL_ARB_texture_storage) {
|
||||
#endif
|
||||
glTexStorage2D(GL_TEXTURE_2D, mipmapCount, internalFormat, w, h);
|
||||
glTexStorage2D(GL_TEXTURE_2D, mipmapCount, internalFormat, w, h);
|
||||
#ifndef EMSCRIPTEN
|
||||
} else {
|
||||
for (int i = 0; i < mipmapCount; i++) {
|
||||
glTexImage2D(GL_TEXTURE_2D, i, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, NULL);
|
||||
w = MAX(w >> 1, 1);
|
||||
h = MAX(h >> 1, 1);
|
||||
} else {
|
||||
for (int i = 0; i < mipmapCount; i++) {
|
||||
glTexImage2D(GL_TEXTURE_2D, i, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, NULL);
|
||||
w = MAX(w >> 1, 1);
|
||||
h = MAX(h >> 1, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Upload data
|
||||
for (int i = 0; i < texture->sliceCount; i++) {
|
||||
TextureData* textureData = texture->slices[i];
|
||||
GLenum glInternalFormat;
|
||||
if (lovrGraphicsIsGammaCorrect() && texture->srgb) {
|
||||
glInternalFormat = textureData->format.glInternalFormat.srgb;
|
||||
} else {
|
||||
glInternalFormat = textureData->format.glInternalFormat.linear;
|
||||
}
|
||||
GLenum glFormat = textureData->format.glFormat;
|
||||
GLenum binding = (texture->type == TEXTURE_CUBE) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + i : GL_TEXTURE_2D;
|
||||
|
||||
if (textureData->format.compressed) {
|
||||
Mipmap m; int i;
|
||||
vec_foreach(&textureData->mipmaps.list, m, i) {
|
||||
glCompressedTexImage2D(binding, i, glInternalFormat, m.width, m.height, 0, m.size, m.data);
|
||||
}
|
||||
} else {
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
|
||||
if (texture->type == TEXTURE_CUBE) {
|
||||
glTexImage2D(binding, 0, glInternalFormat, w, h, 0, glFormat, GL_UNSIGNED_BYTE, textureData->data);
|
||||
} else if (textureData->data) {
|
||||
glTexSubImage2D(binding, 0, 0, 0, w, h, glFormat, GL_UNSIGNED_BYTE, textureData->data);
|
||||
}
|
||||
|
||||
if (textureData->mipmaps.generated) {
|
||||
glGenerateMipmap(texture->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void validateSlices(TextureType type, TextureData* slices[6], int sliceCount) {
|
||||
|
@ -67,8 +101,7 @@ Texture* lovrTextureCreate(TextureType type, TextureData* slices[6], int sliceCo
|
|||
texture->srgb = srgb;
|
||||
glGenTextures(1, &texture->id);
|
||||
lovrGraphicsBindTexture(texture, type, 0);
|
||||
lovrTextureCreateStorage(texture);
|
||||
lovrTextureRefresh(texture);
|
||||
lovrTextureUpload(texture);
|
||||
lovrTextureSetFilter(texture, lovrGraphicsGetDefaultFilter());
|
||||
WrapMode wrapMode = (type == TEXTURE_CUBE) ? WRAP_CLAMP : WRAP_REPEAT;
|
||||
lovrTextureSetWrap(texture, (TextureWrap) { .s = wrapMode, .t = wrapMode, .r = wrapMode });
|
||||
|
@ -179,44 +212,6 @@ void lovrTextureResolveMSAA(Texture* texture) {
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void lovrTextureRefresh(Texture* texture) {
|
||||
lovrGraphicsBindTexture(texture, texture->type, 0);
|
||||
|
||||
validateSlices(texture->type, texture->slices, texture->sliceCount);
|
||||
texture->width = texture->slices[0]->width;
|
||||
texture->height = texture->slices[0]->height;
|
||||
|
||||
for (int i = 0; i < texture->sliceCount; i++) {
|
||||
TextureData* textureData = texture->slices[i];
|
||||
GLenum glInternalFormat;
|
||||
if (lovrGraphicsIsGammaCorrect() && texture->srgb) {
|
||||
glInternalFormat = textureData->format.glInternalFormat.srgb;
|
||||
} else {
|
||||
glInternalFormat = textureData->format.glInternalFormat.linear;
|
||||
}
|
||||
GLenum glFormat = textureData->format.glFormat;
|
||||
GLenum binding = (texture->type == TEXTURE_CUBE) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + i : GL_TEXTURE_2D;
|
||||
|
||||
if (textureData->format.compressed) {
|
||||
Mipmap m; int i;
|
||||
vec_foreach(&textureData->mipmaps.list, m, i) {
|
||||
glCompressedTexImage2D(binding, i, glInternalFormat, m.width, m.height, 0, m.size, m.data);
|
||||
}
|
||||
} else {
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
|
||||
if (textureData->data) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, glFormat, GL_UNSIGNED_BYTE, textureData->data);
|
||||
}
|
||||
|
||||
if (textureData->mipmaps.generated) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D); // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextureFilter lovrTextureGetFilter(Texture* texture) {
|
||||
return texture->filter;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,6 @@ Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProje
|
|||
void lovrTextureDestroy(const Ref* ref);
|
||||
void lovrTextureBindFramebuffer(Texture* texture);
|
||||
void lovrTextureResolveMSAA(Texture* texture);
|
||||
void lovrTextureRefresh(Texture* texture);
|
||||
TextureFilter lovrTextureGetFilter(Texture* texture);
|
||||
void lovrTextureSetFilter(Texture* texture, TextureFilter filter);
|
||||
TextureWrap lovrTextureGetWrap(Texture* texture);
|
||||
|
|
|
@ -192,18 +192,6 @@ TextureData* lovrTextureDataFromBlob(Blob* blob) {
|
|||
return textureData;
|
||||
}
|
||||
|
||||
void lovrTextureDataResize(TextureData* textureData, int width, int height, uint8_t value) {
|
||||
if (textureData->format.compressed || textureData->mipmaps.generated) {
|
||||
lovrThrow("Can't resize a compressed texture or a texture with generated mipmaps.");
|
||||
}
|
||||
|
||||
int size = width * height * textureData->format.blockBytes;
|
||||
textureData->width = width;
|
||||
textureData->height = height;
|
||||
textureData->data = realloc(textureData->data, size);
|
||||
memset(textureData->data, value, size);
|
||||
}
|
||||
|
||||
void lovrTextureDataDestroy(TextureData* textureData) {
|
||||
if (textureData->blob) {
|
||||
lovrRelease(&textureData->blob->ref);
|
||||
|
|
|
@ -49,5 +49,4 @@ typedef struct {
|
|||
TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value, TextureFormat format);
|
||||
TextureData* lovrTextureDataGetEmpty(int width, int height, TextureFormat format);
|
||||
TextureData* lovrTextureDataFromBlob(Blob* blob);
|
||||
void lovrTextureDataResize(TextureData* textureData, int width, int height, uint8_t value);
|
||||
void lovrTextureDataDestroy(TextureData* textureData);
|
||||
|
|
Loading…
Reference in New Issue