dusk/src/duskgl/display/texture.c

103 lines
2.3 KiB
C

/**
* Copyright (c) 2023 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "texture.h"
#include "assert/assert.h"
#include "assert/assertgl.h"
#include "asset.h"
#include "util/math.h"
#include "util/memory.h"
#define TEXTURE_BUFFER_SIZE 32768
int32_t TEXTURE_ACTIVE_COUNT;
void textureLoad(
texture_t *texture,
const char_t *path
) {
assertNotNull(texture, "Texture is null.");
assertNotNull(path, "Path is null.");
// Open asset
assetOpen(path);
// Setup spng
spng_ctx *ctx = spng_ctx_new(0);
spng_set_png_stream(ctx, &textureSPNGBuffer, NULL);
// Get image info
struct spng_ihdr ihdr;
spng_get_ihdr(ctx, &ihdr);
texture->width = ihdr.width;
texture->height = ihdr.height;
// Decode the image. I can probably stream this in the future.
size_t dataSize = ihdr.width * ihdr.height * 4;// 4 for RGBA
uint8_t *data = (uint8_t *)memoryAllocate(dataSize);
assertNotNull(data, "Failed to allocate memory for texture data.");
spng_decode_image(ctx, data, dataSize, SPNG_FMT_RGBA8, 0);
// Finish decoding
spng_ctx_free(ctx);
assetClose();
// Create texture
glGenTextures(1, &texture->id);
assertNoGLError();
glBindTexture(GL_TEXTURE_2D, texture->id);
assertNoGLError();
// Buffer then cleanup
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA,
texture->width, texture->height,
0, GL_RGBA, GL_UNSIGNED_BYTE, data
);
assertNoGLError();
memoryFree(data);
// Setup texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
assertNoGLError();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
assertNoGLError();
glBindTexture(GL_TEXTURE_2D, 0);
assertNoGLError();
}
void textureBind(
const texture_t *texture,
const GLuint slot
) {
assertNotNull(texture, "Texture is null.");
glActiveTexture(GL_TEXTURE0 + slot);
assertNoGLError();
glBindTexture(GL_TEXTURE_2D, texture->id);
assertNoGLError();
}
void textureDispose(texture_t *texture) {
glDeleteTextures(1, &texture->id);
assertNoGLError();
}
int32_t textureSPNGBuffer(
spng_ctx *ctx,
void *user,
void *destination,
size_t length
) {
size_t read = assetRead(destination, length);
if(read == 0) return SPNG_IO_EOF;
return SPNG_OK;
}