mirror of https://github.com/bjornbytes/lovr.git
TextureData is now named Image!;
The existing Image construct was renamed StorageImage.
This commit is contained in:
parent
dca79f83f0
commit
8164e0b6e8
|
@ -349,18 +349,18 @@ endif()
|
|||
if(LOVR_ENABLE_DATA)
|
||||
target_sources(lovr PRIVATE
|
||||
src/modules/data/blob.c
|
||||
src/modules/data/image.c
|
||||
src/modules/data/modelData.c
|
||||
src/modules/data/modelData_gltf.c
|
||||
src/modules/data/modelData_obj.c
|
||||
src/modules/data/rasterizer.c
|
||||
src/modules/data/sound.c
|
||||
src/modules/data/textureData.c
|
||||
src/api/l_data.c
|
||||
src/api/l_data_blob.c
|
||||
src/api/l_data_image.c
|
||||
src/api/l_data_modelData.c
|
||||
src/api/l_data_rasterizer.c
|
||||
src/api/l_data_sound.c
|
||||
src/api/l_data_textureData.c
|
||||
src/lib/minimp3/minimp3.c
|
||||
src/lib/stb/stb_image.c
|
||||
src/lib/stb/stb_truetype.c
|
||||
|
|
|
@ -41,6 +41,7 @@ extern const luaL_Reg lovrCylinderShape[];
|
|||
extern const luaL_Reg lovrDistanceJoint[];
|
||||
extern const luaL_Reg lovrFont[];
|
||||
extern const luaL_Reg lovrHingeJoint[];
|
||||
extern const luaL_Reg lovrImage[];
|
||||
extern const luaL_Reg lovrMat4[];
|
||||
extern const luaL_Reg lovrMaterial[];
|
||||
extern const luaL_Reg lovrMesh[];
|
||||
|
@ -58,7 +59,6 @@ extern const luaL_Reg lovrSource[];
|
|||
extern const luaL_Reg lovrSphereShape[];
|
||||
extern const luaL_Reg lovrMeshShape[];
|
||||
extern const luaL_Reg lovrTexture[];
|
||||
extern const luaL_Reg lovrTextureData[];
|
||||
extern const luaL_Reg lovrThread[];
|
||||
extern const luaL_Reg lovrVec2[];
|
||||
extern const luaL_Reg lovrVec4[];
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "data/modelData.h"
|
||||
#include "data/rasterizer.h"
|
||||
#include "data/sound.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -90,37 +90,37 @@ static int l_lovrDataNewSound(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrDataNewTextureData(lua_State* L) {
|
||||
TextureData* textureData = NULL;
|
||||
static int l_lovrDataNewImage(lua_State* L) {
|
||||
Image* image = NULL;
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) {
|
||||
int width = luaL_checkinteger(L, 1);
|
||||
int height = luaL_checkinteger(L, 2);
|
||||
TextureFormat format = luax_checkenum(L, 3, TextureFormat, "rgba");
|
||||
Blob* blob = lua_isnoneornil(L, 4) ? NULL : luax_checktype(L, 4, Blob);
|
||||
textureData = lovrTextureDataCreate(width, height, blob, 0x0, format);
|
||||
image = lovrImageCreate(width, height, blob, 0x0, format);
|
||||
} else {
|
||||
TextureData* source = luax_totype(L, 1, TextureData);
|
||||
Image* source = luax_totype(L, 1, Image);
|
||||
if (source) {
|
||||
textureData = lovrTextureDataCreate(source->width, source->height, source->blob, 0x0, source->format);
|
||||
image = lovrImageCreate(source->width, source->height, source->blob, 0x0, source->format);
|
||||
} else {
|
||||
Blob* blob = luax_readblob(L, 1, "Texture");
|
||||
bool flip = lua_isnoneornil(L, 2) ? true : lua_toboolean(L, 2);
|
||||
textureData = lovrTextureDataCreateFromBlob(blob, flip);
|
||||
image = lovrImageCreateFromBlob(blob, flip);
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
}
|
||||
}
|
||||
|
||||
luax_pushtype(L, TextureData, textureData);
|
||||
lovrRelease(textureData, lovrTextureDataDestroy);
|
||||
luax_pushtype(L, Image, image);
|
||||
lovrRelease(image, lovrImageDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg lovrData[] = {
|
||||
{ "newBlob", l_lovrDataNewBlob },
|
||||
{ "newImage", l_lovrDataNewImage },
|
||||
{ "newModelData", l_lovrDataNewModelData },
|
||||
{ "newRasterizer", l_lovrDataNewRasterizer },
|
||||
{ "newSound", l_lovrDataNewSound },
|
||||
{ "newTextureData", l_lovrDataNewTextureData },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -128,9 +128,9 @@ int luaopen_lovr_data(lua_State* L) {
|
|||
lua_newtable(L);
|
||||
luax_register(L, lovrData);
|
||||
luax_registertype(L, Blob);
|
||||
luax_registertype(L, Image);
|
||||
luax_registertype(L, ModelData);
|
||||
luax_registertype(L, Rasterizer);
|
||||
luax_registertype(L, Sound);
|
||||
luax_registertype(L, TextureData);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,57 +1,57 @@
|
|||
#include "api.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "data/blob.h"
|
||||
|
||||
static int l_lovrTextureDataEncode(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
Blob* blob = lovrTextureDataEncode(textureData);
|
||||
static int l_lovrImageEncode(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
Blob* blob = lovrImageEncode(image);
|
||||
luax_pushtype(L, Blob, blob);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataGetWidth(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
lua_pushinteger(L, textureData->width);
|
||||
static int l_lovrImageGetWidth(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
lua_pushinteger(L, image->width);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataGetHeight(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
lua_pushinteger(L, textureData->height);
|
||||
static int l_lovrImageGetHeight(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
lua_pushinteger(L, image->height);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataGetDimensions(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
lua_pushinteger(L, textureData->width);
|
||||
lua_pushinteger(L, textureData->height);
|
||||
static int l_lovrImageGetDimensions(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
lua_pushinteger(L, image->width);
|
||||
lua_pushinteger(L, image->height);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataGetFormat(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
luax_pushenum(L, TextureFormat, textureData->format);
|
||||
static int l_lovrImageGetFormat(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
luax_pushenum(L, TextureFormat, image->format);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataPaste(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
TextureData* source = luax_checktype(L, 2, TextureData);
|
||||
static int l_lovrImagePaste(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
Image* source = luax_checktype(L, 2, Image);
|
||||
uint32_t dx = luaL_optinteger(L, 3, 0);
|
||||
uint32_t dy = luaL_optinteger(L, 4, 0);
|
||||
uint32_t sx = luaL_optinteger(L, 5, 0);
|
||||
uint32_t sy = luaL_optinteger(L, 6, 0);
|
||||
uint32_t w = luaL_optinteger(L, 7, source->width);
|
||||
uint32_t h = luaL_optinteger(L, 8, source->height);
|
||||
lovrTextureDataPaste(textureData, source, dx, dy, sx, sy, w, h);
|
||||
lovrImagePaste(image, source, dx, dy, sx, sy, w, h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataGetPixel(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
static int l_lovrImageGetPixel(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
int x = luaL_checkinteger(L, 2);
|
||||
int y = luaL_checkinteger(L, 3);
|
||||
Color color = lovrTextureDataGetPixel(textureData, x, y);
|
||||
Color color = lovrImageGetPixel(image, x, y);
|
||||
lua_pushnumber(L, color.r);
|
||||
lua_pushnumber(L, color.g);
|
||||
lua_pushnumber(L, color.b);
|
||||
|
@ -59,8 +59,8 @@ static int l_lovrTextureDataGetPixel(lua_State* L) {
|
|||
return 4;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataSetPixel(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
static int l_lovrImageSetPixel(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
int x = luaL_checkinteger(L, 2);
|
||||
int y = luaL_checkinteger(L, 3);
|
||||
Color color = {
|
||||
|
@ -69,26 +69,26 @@ static int l_lovrTextureDataSetPixel(lua_State* L) {
|
|||
luax_optfloat(L, 6, 1.f),
|
||||
luax_optfloat(L, 7, 1.f)
|
||||
};
|
||||
lovrTextureDataSetPixel(textureData, x, y, color);
|
||||
lovrImageSetPixel(image, x, y, color);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_lovrTextureDataGetBlob(lua_State* L) {
|
||||
TextureData* textureData = luax_checktype(L, 1, TextureData);
|
||||
Blob* blob = textureData->blob;
|
||||
static int l_lovrImageGetBlob(lua_State* L) {
|
||||
Image* image = luax_checktype(L, 1, Image);
|
||||
Blob* blob = image->blob;
|
||||
luax_pushtype(L, Blob, blob);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrTextureData[] = {
|
||||
{ "encode", l_lovrTextureDataEncode },
|
||||
{ "getWidth", l_lovrTextureDataGetWidth },
|
||||
{ "getHeight", l_lovrTextureDataGetHeight },
|
||||
{ "getDimensions", l_lovrTextureDataGetDimensions },
|
||||
{ "getFormat", l_lovrTextureDataGetFormat },
|
||||
{ "paste", l_lovrTextureDataPaste },
|
||||
{ "getPixel", l_lovrTextureDataGetPixel },
|
||||
{ "setPixel", l_lovrTextureDataSetPixel },
|
||||
{ "getBlob", l_lovrTextureDataGetBlob },
|
||||
const luaL_Reg lovrImage[] = {
|
||||
{ "encode", l_lovrImageEncode },
|
||||
{ "getWidth", l_lovrImageGetWidth },
|
||||
{ "getHeight", l_lovrImageGetHeight },
|
||||
{ "getDimensions", l_lovrImageGetDimensions },
|
||||
{ "getFormat", l_lovrImageGetFormat },
|
||||
{ "paste", l_lovrImagePaste },
|
||||
{ "getPixel", l_lovrImageGetPixel },
|
||||
{ "setPixel", l_lovrImageSetPixel },
|
||||
{ "getBlob", l_lovrImageGetBlob },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "data/blob.h"
|
||||
#include "data/modelData.h"
|
||||
#include "data/rasterizer.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "core/os.h"
|
||||
#include "core/util.h"
|
||||
#include <math.h>
|
||||
|
@ -304,18 +304,18 @@ static void stencilCallback(void* userdata) {
|
|||
}
|
||||
|
||||
// Must be released when done
|
||||
static TextureData* luax_checktexturedata(lua_State* L, int index, bool flip) {
|
||||
TextureData* textureData = luax_totype(L, index, TextureData);
|
||||
static Image* luax_checkimage(lua_State* L, int index, bool flip) {
|
||||
Image* image = luax_totype(L, index, Image);
|
||||
|
||||
if (textureData) {
|
||||
lovrRetain(textureData);
|
||||
if (image) {
|
||||
lovrRetain(image);
|
||||
} else {
|
||||
Blob* blob = luax_readblob(L, index, "Texture");
|
||||
textureData = lovrTextureDataCreateFromBlob(blob, flip);
|
||||
image = lovrImageCreateFromBlob(blob, flip);
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
}
|
||||
|
||||
return textureData;
|
||||
return image;
|
||||
}
|
||||
|
||||
// Base
|
||||
|
@ -360,12 +360,12 @@ static int l_lovrGraphicsCreateWindow(lua_State* L) {
|
|||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "icon");
|
||||
TextureData* textureData = NULL;
|
||||
Image* image = NULL;
|
||||
if (!lua_isnil(L, -1)) {
|
||||
textureData = luax_checktexturedata(L, -1, false);
|
||||
flags.icon.data = textureData->blob->data;
|
||||
flags.icon.width = textureData->width;
|
||||
flags.icon.height = textureData->height;
|
||||
image = luax_checkimage(L, -1, false);
|
||||
flags.icon.data = image->blob->data;
|
||||
flags.icon.width = image->width;
|
||||
flags.icon.height = image->height;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
|
@ -375,7 +375,7 @@ static int l_lovrGraphicsCreateWindow(lua_State* L) {
|
|||
|
||||
lovrGraphicsCreateWindow(&flags);
|
||||
luax_atexit(L, lovrGraphicsDestroy); // The lua_State that creates the window shall be the one to destroy it
|
||||
lovrRelease(textureData, lovrTextureDataDestroy);
|
||||
lovrRelease(image, lovrImageDestroy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1262,11 +1262,11 @@ static int l_lovrGraphicsNewMaterial(lua_State* L) {
|
|||
|
||||
if (lua_type(L, index) == LUA_TSTRING) {
|
||||
Blob* blob = luax_readblob(L, index++, "Texture");
|
||||
TextureData* textureData = lovrTextureDataCreateFromBlob(blob, true);
|
||||
Texture* texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true, true, 0);
|
||||
Image* image = lovrImageCreateFromBlob(blob, true);
|
||||
Texture* texture = lovrTextureCreate(TEXTURE_2D, &image, 1, true, true, 0);
|
||||
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, texture);
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
lovrRelease(textureData, lovrTextureDataDestroy);
|
||||
lovrRelease(image, lovrImageDestroy);
|
||||
lovrRelease(texture, lovrTextureDestroy);
|
||||
} else if (lua_isuserdata(L, index)) {
|
||||
Texture* texture = luax_checktype(L, index, Texture);
|
||||
|
@ -1710,12 +1710,12 @@ static int l_lovrGraphicsNewTexture(lua_State* L) {
|
|||
|
||||
for (int i = 0; i < depth; i++) {
|
||||
lua_rawgeti(L, 1, i + 1);
|
||||
TextureData* textureData = luax_checktexturedata(L, -1, type != TEXTURE_CUBE);
|
||||
Image* image = luax_checkimage(L, -1, type != TEXTURE_CUBE);
|
||||
if (i == 0) {
|
||||
lovrTextureAllocate(texture, textureData->width, textureData->height, depth, textureData->format);
|
||||
lovrTextureAllocate(texture, image->width, image->height, depth, image->format);
|
||||
}
|
||||
lovrTextureReplacePixels(texture, textureData, 0, 0, i, 0);
|
||||
lovrRelease(textureData, lovrTextureDataDestroy);
|
||||
lovrTextureReplacePixels(texture, image, 0, 0, i, 0);
|
||||
lovrRelease(image, lovrImageDestroy);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,15 +50,15 @@ void luax_readattachments(lua_State* L, int index, Attachment* attachments, int*
|
|||
}
|
||||
}
|
||||
|
||||
static int l_lovrCanvasNewTextureData(lua_State* L) {
|
||||
static int l_lovrCanvasNewImage(lua_State* L) {
|
||||
Canvas* canvas = luax_checktype(L, 1, Canvas);
|
||||
uint32_t index = luaL_optinteger(L, 2, 1) - 1;
|
||||
uint32_t count;
|
||||
lovrCanvasGetAttachments(canvas, &count);
|
||||
lovrAssert(index < count, "Can not create a TextureData from Texture #%d of Canvas (it only has %d textures)", index, count);
|
||||
TextureData* textureData = lovrCanvasNewTextureData(canvas, index);
|
||||
luax_pushtype(L, TextureData, textureData);
|
||||
lovrRelease(textureData, lovrTextureDataDestroy);
|
||||
lovrAssert(index < count, "Can not create an Image from Texture #%d of Canvas (it only has %d textures)", index, count);
|
||||
Image* image = lovrCanvasNewImage(canvas, index);
|
||||
luax_pushtype(L, Image, image);
|
||||
lovrRelease(image, lovrImageDestroy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@ static int l_lovrCanvasIsStereo(lua_State* L) {
|
|||
}
|
||||
|
||||
const luaL_Reg lovrCanvas[] = {
|
||||
{ "newTextureData", l_lovrCanvasNewTextureData },
|
||||
{ "newImage", l_lovrCanvasNewImage },
|
||||
{ "renderTo", l_lovrCanvasRenderTo },
|
||||
{ "getTexture", l_lovrCanvasGetTexture },
|
||||
{ "setTexture", l_lovrCanvasSetTexture },
|
||||
|
|
|
@ -71,13 +71,13 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
|
|||
}
|
||||
|
||||
case UNIFORM_IMAGE: {
|
||||
Image* image = (Image*) dest + i;
|
||||
StorageImage* image = (StorageImage*) dest + i;
|
||||
image->texture = luax_checktype(L, j, Texture);
|
||||
image->slice = -1;
|
||||
image->mipmap = 0;
|
||||
image->access = ACCESS_READ_WRITE;
|
||||
TextureType type = lovrTextureGetType(image->texture);
|
||||
lovrAssert(type == uniform->textureType, "Attempt to send %s texture to %s image uniform", lovrTextureType[type], lovrTextureType[uniform->textureType]);
|
||||
lovrAssert(type == uniform->textureType, "Attempt to send %s texture to %s storage image uniform", lovrTextureType[type], lovrTextureType[uniform->textureType]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ static int l_lovrShaderSendImage(lua_State* L) {
|
|||
int slice = luaL_optinteger(L, index++, 0) - 1; // Default is -1
|
||||
int mipmap = luax_optmipmap(L, index++, texture);
|
||||
UniformAccess access = luax_checkenum(L, index++, UniformAccess, "readwrite");
|
||||
Image image = { .texture = texture, .slice = slice, .mipmap = mipmap, .access = access };
|
||||
StorageImage image = { .texture = texture, .slice = slice, .mipmap = mipmap, .access = access };
|
||||
lovrShaderSetImages(shader, name, &image, start, 1);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -83,12 +83,12 @@ static int l_lovrTextureGetWrap(lua_State* L) {
|
|||
|
||||
static int l_lovrTextureReplacePixels(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
TextureData* textureData = luax_checktype(L, 2, TextureData);
|
||||
Image* image = luax_checktype(L, 2, Image);
|
||||
int x = luaL_optinteger(L, 3, 0);
|
||||
int y = luaL_optinteger(L, 4, 0);
|
||||
int slice = luaL_optinteger(L, 5, 1) - 1;
|
||||
int mipmap = luaL_optinteger(L, 6, 1) - 1;
|
||||
lovrTextureReplacePixels(texture, textureData, x, y, slice, mipmap);
|
||||
lovrTextureReplacePixels(texture, image, x, y, slice, mipmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "data/blob.h"
|
||||
#include "lib/stb/stb_image.h"
|
||||
#include <stdlib.h>
|
||||
|
@ -32,7 +32,7 @@ static size_t getPixelSize(TextureFormat format) {
|
|||
}
|
||||
|
||||
// Modified from ddsparse (https://bitbucket.org/slime73/ddsparse)
|
||||
static bool parseDDS(uint8_t* data, size_t size, TextureData* textureData) {
|
||||
static bool parseDDS(uint8_t* data, size_t size, Image* image) {
|
||||
enum {
|
||||
DDPF_ALPHAPIXELS = 0x000001,
|
||||
DDPF_ALPHA = 0x000002,
|
||||
|
@ -255,17 +255,17 @@ static bool parseDDS(uint8_t* data, size_t size, TextureData* textureData) {
|
|||
case DXGI_FORMAT_BC1_TYPELESS:
|
||||
case DXGI_FORMAT_BC1_UNORM:
|
||||
case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
textureData->format = FORMAT_DXT1;
|
||||
image->format = FORMAT_DXT1;
|
||||
break;
|
||||
case DXGI_FORMAT_BC2_TYPELESS:
|
||||
case DXGI_FORMAT_BC2_UNORM:
|
||||
case DXGI_FORMAT_BC2_UNORM_SRGB:
|
||||
textureData->format = FORMAT_DXT3;
|
||||
image->format = FORMAT_DXT3;
|
||||
break;
|
||||
case DXGI_FORMAT_BC3_TYPELESS:
|
||||
case DXGI_FORMAT_BC3_UNORM:
|
||||
case DXGI_FORMAT_BC3_UNORM_SRGB:
|
||||
textureData->format = FORMAT_DXT5;
|
||||
image->format = FORMAT_DXT5;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
|
@ -277,20 +277,20 @@ static bool parseDDS(uint8_t* data, size_t size, TextureData* textureData) {
|
|||
|
||||
// Ensure DXT 1/3/5
|
||||
switch (header->format.fourCC) {
|
||||
case FOUR_CC('D', 'X', 'T', '1'): textureData->format = FORMAT_DXT1; break;
|
||||
case FOUR_CC('D', 'X', 'T', '3'): textureData->format = FORMAT_DXT3; break;
|
||||
case FOUR_CC('D', 'X', 'T', '5'): textureData->format = FORMAT_DXT5; break;
|
||||
case FOUR_CC('D', 'X', 'T', '1'): image->format = FORMAT_DXT1; break;
|
||||
case FOUR_CC('D', 'X', 'T', '3'): image->format = FORMAT_DXT3; break;
|
||||
case FOUR_CC('D', 'X', 'T', '5'): image->format = FORMAT_DXT5; break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t width = textureData->width = header->width;
|
||||
uint32_t height = textureData->height = header->height;
|
||||
uint32_t mipmapCount = textureData->mipmapCount = MAX(header->mipMapCount, 1);
|
||||
textureData->mipmaps = malloc(mipmapCount * sizeof(Mipmap));
|
||||
uint32_t width = image->width = header->width;
|
||||
uint32_t height = image->height = header->height;
|
||||
uint32_t mipmapCount = image->mipmapCount = MAX(header->mipMapCount, 1);
|
||||
image->mipmaps = malloc(mipmapCount * sizeof(Mipmap));
|
||||
size_t blockBytes = 0;
|
||||
|
||||
switch (textureData->format) {
|
||||
switch (image->format) {
|
||||
case FORMAT_DXT1: blockBytes = 8; break;
|
||||
case FORMAT_DXT3: blockBytes = 16; break;
|
||||
case FORMAT_DXT5: blockBytes = 16; break;
|
||||
|
@ -305,22 +305,22 @@ static bool parseDDS(uint8_t* data, size_t size, TextureData* textureData) {
|
|||
|
||||
// Overflow check
|
||||
if (mipmapSize == 0 || (offset + mipmapSize) > size) {
|
||||
free(textureData->mipmaps);
|
||||
free(image->mipmaps);
|
||||
return false;
|
||||
}
|
||||
|
||||
textureData->mipmaps[i] = (Mipmap) { .width = width, .height = height, .data = &data[offset], .size = mipmapSize };
|
||||
image->mipmaps[i] = (Mipmap) { .width = width, .height = height, .data = &data[offset], .size = mipmapSize };
|
||||
offset += mipmapSize;
|
||||
width = MAX(width >> 1, 1);
|
||||
height = MAX(height >> 1, 1);
|
||||
}
|
||||
|
||||
textureData->blob->data = NULL;
|
||||
image->blob->data = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parseKTX(uint8_t* bytes, size_t size, TextureData* textureData) {
|
||||
static bool parseKTX(uint8_t* bytes, size_t size, Image* image) {
|
||||
typedef struct {
|
||||
uint8_t magic[12];
|
||||
uint32_t endianness;
|
||||
|
@ -356,34 +356,34 @@ static bool parseKTX(uint8_t* bytes, size_t size, TextureData* textureData) {
|
|||
|
||||
// TODO MOAR FORMATS, GIMME COOOBMAPS
|
||||
switch (data.ktx->glInternalFormat) {
|
||||
case 0x83F0: textureData->format = FORMAT_DXT1; break;
|
||||
case 0x83F2: textureData->format = FORMAT_DXT3; break;
|
||||
case 0x83F3: textureData->format = FORMAT_DXT5; break;
|
||||
case 0x93B0: case 0x93D0: textureData->format = FORMAT_ASTC_4x4; break;
|
||||
case 0x93B1: case 0x93D1: textureData->format = FORMAT_ASTC_5x4; break;
|
||||
case 0x93B2: case 0x93D2: textureData->format = FORMAT_ASTC_5x5; break;
|
||||
case 0x93B3: case 0x93D3: textureData->format = FORMAT_ASTC_6x5; break;
|
||||
case 0x93B4: case 0x93D4: textureData->format = FORMAT_ASTC_6x6; break;
|
||||
case 0x93B5: case 0x93D5: textureData->format = FORMAT_ASTC_8x5; break;
|
||||
case 0x93B6: case 0x93D6: textureData->format = FORMAT_ASTC_8x6; break;
|
||||
case 0x93B7: case 0x93D7: textureData->format = FORMAT_ASTC_8x8; break;
|
||||
case 0x93B8: case 0x93D8: textureData->format = FORMAT_ASTC_10x5; break;
|
||||
case 0x93B9: case 0x93D9: textureData->format = FORMAT_ASTC_10x6; break;
|
||||
case 0x93BA: case 0x93DA: textureData->format = FORMAT_ASTC_10x8; break;
|
||||
case 0x93BB: case 0x93DB: textureData->format = FORMAT_ASTC_10x10; break;
|
||||
case 0x93BC: case 0x93DC: textureData->format = FORMAT_ASTC_12x10; break;
|
||||
case 0x93BD: case 0x93DD: textureData->format = FORMAT_ASTC_12x12; break;
|
||||
case 0x83F0: image->format = FORMAT_DXT1; break;
|
||||
case 0x83F2: image->format = FORMAT_DXT3; break;
|
||||
case 0x83F3: image->format = FORMAT_DXT5; break;
|
||||
case 0x93B0: case 0x93D0: image->format = FORMAT_ASTC_4x4; break;
|
||||
case 0x93B1: case 0x93D1: image->format = FORMAT_ASTC_5x4; break;
|
||||
case 0x93B2: case 0x93D2: image->format = FORMAT_ASTC_5x5; break;
|
||||
case 0x93B3: case 0x93D3: image->format = FORMAT_ASTC_6x5; break;
|
||||
case 0x93B4: case 0x93D4: image->format = FORMAT_ASTC_6x6; break;
|
||||
case 0x93B5: case 0x93D5: image->format = FORMAT_ASTC_8x5; break;
|
||||
case 0x93B6: case 0x93D6: image->format = FORMAT_ASTC_8x6; break;
|
||||
case 0x93B7: case 0x93D7: image->format = FORMAT_ASTC_8x8; break;
|
||||
case 0x93B8: case 0x93D8: image->format = FORMAT_ASTC_10x5; break;
|
||||
case 0x93B9: case 0x93D9: image->format = FORMAT_ASTC_10x6; break;
|
||||
case 0x93BA: case 0x93DA: image->format = FORMAT_ASTC_10x8; break;
|
||||
case 0x93BB: case 0x93DB: image->format = FORMAT_ASTC_10x10; break;
|
||||
case 0x93BC: case 0x93DC: image->format = FORMAT_ASTC_12x10; break;
|
||||
case 0x93BD: case 0x93DD: image->format = FORMAT_ASTC_12x12; break;
|
||||
default: lovrThrow("Unsupported KTX format '%d' (please open an issue)", data.ktx->glInternalFormat);
|
||||
}
|
||||
|
||||
uint32_t width = textureData->width = data.ktx->pixelWidth;
|
||||
uint32_t height = textureData->height = data.ktx->pixelHeight;
|
||||
uint32_t mipmapCount = textureData->mipmapCount = data.ktx->numberOfMipmapLevels;
|
||||
textureData->mipmaps = malloc(mipmapCount * sizeof(Mipmap));
|
||||
uint32_t width = image->width = data.ktx->pixelWidth;
|
||||
uint32_t height = image->height = data.ktx->pixelHeight;
|
||||
uint32_t mipmapCount = image->mipmapCount = data.ktx->numberOfMipmapLevels;
|
||||
image->mipmaps = malloc(mipmapCount * sizeof(Mipmap));
|
||||
|
||||
data.u8 += sizeof(KTXHeader) + data.ktx->bytesOfKeyValueData;
|
||||
for (uint32_t i = 0; i < mipmapCount; i++) {
|
||||
textureData->mipmaps[i] = (Mipmap) { .width = width, .height = height, .data = data.u8 + sizeof(uint32_t), .size = *data.u32 };
|
||||
image->mipmaps[i] = (Mipmap) { .width = width, .height = height, .data = data.u8 + sizeof(uint32_t), .size = *data.u32 };
|
||||
width = MAX(width >> 1, 1u);
|
||||
height = MAX(height >> 1, 1u);
|
||||
data.u8 = (uint8_t*) ALIGN(data.u8 + sizeof(uint32_t) + *data.u32, 4);
|
||||
|
@ -392,7 +392,7 @@ static bool parseKTX(uint8_t* bytes, size_t size, TextureData* textureData) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool parseASTC(uint8_t* bytes, size_t size, TextureData* textureData) {
|
||||
static bool parseASTC(uint8_t* bytes, size_t size, Image* image) {
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint8_t blockX;
|
||||
|
@ -416,36 +416,36 @@ static bool parseASTC(uint8_t* bytes, size_t size, TextureData* textureData) {
|
|||
}
|
||||
|
||||
uint32_t bx = data.astc->blockX, by = data.astc->blockY, bz = data.astc->blockZ;
|
||||
if (bx == 4 && by == 4 && bz == 1) { textureData->format = FORMAT_ASTC_4x4; }
|
||||
else if (bx == 5 && by == 4 && bz == 1) { textureData->format = FORMAT_ASTC_5x4; }
|
||||
else if (bx == 5 && by == 5 && bz == 1) { textureData->format = FORMAT_ASTC_5x5; }
|
||||
else if (bx == 6 && by == 5 && bz == 1) { textureData->format = FORMAT_ASTC_6x5; }
|
||||
else if (bx == 6 && by == 6 && bz == 1) { textureData->format = FORMAT_ASTC_6x6; }
|
||||
else if (bx == 8 && by == 5 && bz == 1) { textureData->format = FORMAT_ASTC_8x5; }
|
||||
else if (bx == 8 && by == 6 && bz == 1) { textureData->format = FORMAT_ASTC_8x6; }
|
||||
else if (bx == 8 && by == 8 && bz == 1) { textureData->format = FORMAT_ASTC_8x8; }
|
||||
else if (bx == 10 && by == 5 && bz == 1) { textureData->format = FORMAT_ASTC_10x5; }
|
||||
else if (bx == 10 && by == 6 && bz == 1) { textureData->format = FORMAT_ASTC_10x6; }
|
||||
else if (bx == 10 && by == 8 && bz == 1) { textureData->format = FORMAT_ASTC_10x8; }
|
||||
else if (bx == 10 && by == 10 && bz == 1) { textureData->format = FORMAT_ASTC_10x10; }
|
||||
else if (bx == 12 && by == 10 && bz == 1) { textureData->format = FORMAT_ASTC_12x10; }
|
||||
else if (bx == 12 && by == 12 && bz == 1) { textureData->format = FORMAT_ASTC_12x12; }
|
||||
if (bx == 4 && by == 4 && bz == 1) { image->format = FORMAT_ASTC_4x4; }
|
||||
else if (bx == 5 && by == 4 && bz == 1) { image->format = FORMAT_ASTC_5x4; }
|
||||
else if (bx == 5 && by == 5 && bz == 1) { image->format = FORMAT_ASTC_5x5; }
|
||||
else if (bx == 6 && by == 5 && bz == 1) { image->format = FORMAT_ASTC_6x5; }
|
||||
else if (bx == 6 && by == 6 && bz == 1) { image->format = FORMAT_ASTC_6x6; }
|
||||
else if (bx == 8 && by == 5 && bz == 1) { image->format = FORMAT_ASTC_8x5; }
|
||||
else if (bx == 8 && by == 6 && bz == 1) { image->format = FORMAT_ASTC_8x6; }
|
||||
else if (bx == 8 && by == 8 && bz == 1) { image->format = FORMAT_ASTC_8x8; }
|
||||
else if (bx == 10 && by == 5 && bz == 1) { image->format = FORMAT_ASTC_10x5; }
|
||||
else if (bx == 10 && by == 6 && bz == 1) { image->format = FORMAT_ASTC_10x6; }
|
||||
else if (bx == 10 && by == 8 && bz == 1) { image->format = FORMAT_ASTC_10x8; }
|
||||
else if (bx == 10 && by == 10 && bz == 1) { image->format = FORMAT_ASTC_10x10; }
|
||||
else if (bx == 12 && by == 10 && bz == 1) { image->format = FORMAT_ASTC_12x10; }
|
||||
else if (bx == 12 && by == 12 && bz == 1) { image->format = FORMAT_ASTC_12x12; }
|
||||
else { lovrThrow("Unsupported ASTC format %dx%dx%d", bx, by, bz); }
|
||||
|
||||
textureData->width = data.astc->width[0] + (data.astc->width[1] << 8) + (data.astc->width[2] << 16);
|
||||
textureData->height = data.astc->height[0] + (data.astc->height[1] << 8) + (data.astc->height[2] << 16);
|
||||
image->width = data.astc->width[0] + (data.astc->width[1] << 8) + (data.astc->width[2] << 16);
|
||||
image->height = data.astc->height[0] + (data.astc->height[1] << 8) + (data.astc->height[2] << 16);
|
||||
|
||||
size_t imageSize = ((textureData->width + bx - 1) / bx) * ((textureData->height + by - 1) / by) * (128 / 8);
|
||||
size_t imageSize = ((image->width + bx - 1) / bx) * ((image->height + by - 1) / by) * (128 / 8);
|
||||
|
||||
if (imageSize > size - sizeof(ASTCHeader)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
textureData->mipmapCount = 1;
|
||||
textureData->mipmaps = malloc(sizeof(Mipmap));
|
||||
textureData->mipmaps[0] = (Mipmap) {
|
||||
.width = textureData->width,
|
||||
.height = textureData->height,
|
||||
image->mipmapCount = 1;
|
||||
image->mipmaps = malloc(sizeof(Mipmap));
|
||||
image->mipmaps[0] = (Mipmap) {
|
||||
.width = image->width,
|
||||
.height = image->height,
|
||||
.data = data.u8 + sizeof(ASTCHeader),
|
||||
.size = imageSize
|
||||
};
|
||||
|
@ -453,18 +453,18 @@ static bool parseASTC(uint8_t* bytes, size_t size, TextureData* textureData) {
|
|||
return true;
|
||||
}
|
||||
|
||||
TextureData* lovrTextureDataCreate(uint32_t width, uint32_t height, Blob* contents, uint8_t value, TextureFormat format) {
|
||||
TextureData* textureData = calloc(1, sizeof(TextureData));
|
||||
lovrAssert(textureData, "Out of memory");
|
||||
textureData->ref = 1;
|
||||
Image* lovrImageCreate(uint32_t width, uint32_t height, Blob* contents, uint8_t value, TextureFormat format) {
|
||||
Image* image = calloc(1, sizeof(Image));
|
||||
lovrAssert(image, "Out of memory");
|
||||
image->ref = 1;
|
||||
size_t pixelSize = getPixelSize(format);
|
||||
size_t size = width * height * pixelSize;
|
||||
lovrAssert(width > 0 && height > 0, "TextureData dimensions must be positive");
|
||||
lovrAssert(format < FORMAT_DXT1, "Blank TextureData cannot be compressed");
|
||||
lovrAssert(!contents || contents->size >= size, "TextureData Blob is too small (%d bytes needed, got %d)", size, contents->size);
|
||||
textureData->width = width;
|
||||
textureData->height = height;
|
||||
textureData->format = format;
|
||||
lovrAssert(width > 0 && height > 0, "Image dimensions must be positive");
|
||||
lovrAssert(format < FORMAT_DXT1, "Blank images cannot be compressed");
|
||||
lovrAssert(!contents || contents->size >= size, "Image Blob is too small (%d bytes needed, got %d)", size, contents->size);
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->format = format;
|
||||
void* data = malloc(size);
|
||||
lovrAssert(data, "Out of memory");
|
||||
if (contents) {
|
||||
|
@ -472,27 +472,27 @@ TextureData* lovrTextureDataCreate(uint32_t width, uint32_t height, Blob* conten
|
|||
} else {
|
||||
memset(data, value, size);
|
||||
}
|
||||
textureData->blob = lovrBlobCreate(data, size, "TextureData plain");
|
||||
return textureData;
|
||||
image->blob = lovrBlobCreate(data, size, "Image");
|
||||
return image;
|
||||
}
|
||||
|
||||
TextureData* lovrTextureDataCreateFromBlob(Blob* blob, bool flip) {
|
||||
TextureData* textureData = calloc(1, sizeof(TextureData));
|
||||
lovrAssert(textureData, "Out of memory");
|
||||
textureData->ref = 1;
|
||||
textureData->blob = lovrBlobCreate(NULL, 0, NULL);
|
||||
if (parseDDS(blob->data, blob->size, textureData)) {
|
||||
textureData->source = blob;
|
||||
Image* lovrImageCreateFromBlob(Blob* blob, bool flip) {
|
||||
Image* image = calloc(1, sizeof(Image));
|
||||
lovrAssert(image, "Out of memory");
|
||||
image->ref = 1;
|
||||
image->blob = lovrBlobCreate(NULL, 0, NULL);
|
||||
if (parseDDS(blob->data, blob->size, image)) {
|
||||
image->source = blob;
|
||||
lovrRetain(blob);
|
||||
return textureData;
|
||||
} else if (parseKTX(blob->data, blob->size, textureData)) {
|
||||
textureData->source = blob;
|
||||
return image;
|
||||
} else if (parseKTX(blob->data, blob->size, image)) {
|
||||
image->source = blob;
|
||||
lovrRetain(blob);
|
||||
return textureData;
|
||||
} else if (parseASTC(blob->data, blob->size, textureData)) {
|
||||
textureData->source = blob;
|
||||
return image;
|
||||
} else if (parseASTC(blob->data, blob->size, image)) {
|
||||
image->source = blob;
|
||||
lovrRetain(blob);
|
||||
return textureData;
|
||||
return image;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
|
@ -500,71 +500,79 @@ TextureData* lovrTextureDataCreateFromBlob(Blob* blob, bool flip) {
|
|||
stbi_set_flip_vertically_on_load_thread(flip);
|
||||
if (stbi_is_16_bit_from_memory(blob->data, length)) {
|
||||
int channels;
|
||||
textureData->blob->data = stbi_load_16_from_memory(blob->data, length, &width, &height, &channels, 0);
|
||||
image->blob->data = stbi_load_16_from_memory(blob->data, length, &width, &height, &channels, 0);
|
||||
switch (channels) {
|
||||
case 1:
|
||||
textureData->format = FORMAT_R16;
|
||||
textureData->blob->size = 2 * width * height;
|
||||
image->format = FORMAT_R16;
|
||||
image->blob->size = 2 * width * height;
|
||||
break;
|
||||
case 2:
|
||||
textureData->format = FORMAT_RG16;
|
||||
textureData->blob->size = 4 * width * height;
|
||||
image->format = FORMAT_RG16;
|
||||
image->blob->size = 4 * width * height;
|
||||
break;
|
||||
case 4:
|
||||
textureData->format = FORMAT_RGBA16;
|
||||
textureData->blob->size = 8 * width * height;
|
||||
image->format = FORMAT_RGBA16;
|
||||
image->blob->size = 8 * width * height;
|
||||
break;
|
||||
default:
|
||||
lovrThrow("Unsupported channel count for 16 bit image: %d", channels);
|
||||
}
|
||||
} else if (stbi_is_hdr_from_memory(blob->data, length)) {
|
||||
textureData->format = FORMAT_RGBA32F;
|
||||
textureData->blob->data = stbi_loadf_from_memory(blob->data, length, &width, &height, NULL, 4);
|
||||
textureData->blob->size = 16 * width * height;
|
||||
image->format = FORMAT_RGBA32F;
|
||||
image->blob->data = stbi_loadf_from_memory(blob->data, length, &width, &height, NULL, 4);
|
||||
image->blob->size = 16 * width * height;
|
||||
} else {
|
||||
textureData->format = FORMAT_RGBA;
|
||||
textureData->blob->data = stbi_load_from_memory(blob->data, length, &width, &height, NULL, 4);
|
||||
textureData->blob->size = 4 * width * height;
|
||||
image->format = FORMAT_RGBA;
|
||||
image->blob->data = stbi_load_from_memory(blob->data, length, &width, &height, NULL, 4);
|
||||
image->blob->size = 4 * width * height;
|
||||
}
|
||||
|
||||
if (!textureData->blob->data) {
|
||||
lovrThrow("Could not load texture data from '%s'", blob->name);
|
||||
lovrRelease(textureData->blob, lovrBlobDestroy);
|
||||
free(textureData);
|
||||
if (!image->blob->data) {
|
||||
lovrThrow("Could not load image from '%s'", blob->name);
|
||||
lovrRelease(image->blob, lovrBlobDestroy);
|
||||
free(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
textureData->width = width;
|
||||
textureData->height = height;
|
||||
textureData->mipmapCount = 0;
|
||||
return textureData;
|
||||
image->width = width;
|
||||
image->height = height;
|
||||
image->mipmapCount = 0;
|
||||
return image;
|
||||
}
|
||||
|
||||
Color lovrTextureDataGetPixel(TextureData* textureData, uint32_t x, uint32_t y) {
|
||||
lovrAssert(textureData->blob->data, "TextureData does not have any pixel data");
|
||||
lovrAssert(x < textureData->width && y < textureData->height, "getPixel coordinates must be within TextureData bounds");
|
||||
size_t index = (textureData->height - (y + 1)) * textureData->width + x;
|
||||
size_t pixelSize = getPixelSize(textureData->format);
|
||||
uint8_t* u8 = (uint8_t*) textureData->blob->data + pixelSize * index;
|
||||
void lovrImageDestroy(void* ref) {
|
||||
Image* image = ref;
|
||||
lovrRelease(image->source, lovrBlobDestroy);
|
||||
free(image->mipmaps);
|
||||
lovrRelease(image->blob, lovrBlobDestroy);
|
||||
free(image);
|
||||
}
|
||||
|
||||
Color lovrImageGetPixel(Image* image, uint32_t x, uint32_t y) {
|
||||
lovrAssert(image->blob->data, "Image does not have any pixel data");
|
||||
lovrAssert(x < image->width && y < image->height, "getPixel coordinates must be within Image bounds");
|
||||
size_t index = (image->height - (y + 1)) * image->width + x;
|
||||
size_t pixelSize = getPixelSize(image->format);
|
||||
uint8_t* u8 = (uint8_t*) image->blob->data + pixelSize * index;
|
||||
float* f32 = (float*) u8;
|
||||
switch (textureData->format) {
|
||||
switch (image->format) {
|
||||
case FORMAT_RGB: return (Color) { u8[0] / 255.f, u8[1] / 255.f, u8[2] / 255.f, 1.f };
|
||||
case FORMAT_RGBA: return (Color) { u8[0] / 255.f, u8[1] / 255.f, u8[2] / 255.f, u8[3] / 255.f };
|
||||
case FORMAT_RGBA32F: return (Color) { f32[0], f32[1], f32[2], f32[3] };
|
||||
case FORMAT_R32F: return (Color) { f32[0], 1.f, 1.f, 1.f };
|
||||
case FORMAT_RG32F: return (Color) { f32[0], f32[1], 1.f, 1.f };
|
||||
default: lovrThrow("Unsupported format for TextureData:getPixel");
|
||||
default: lovrThrow("Unsupported format for Image:getPixel");
|
||||
}
|
||||
}
|
||||
|
||||
void lovrTextureDataSetPixel(TextureData* textureData, uint32_t x, uint32_t y, Color color) {
|
||||
lovrAssert(textureData->blob->data, "TextureData does not have any pixel data");
|
||||
lovrAssert(x < textureData->width && y < textureData->height, "setPixel coordinates must be within TextureData bounds");
|
||||
size_t index = (textureData->height - (y + 1)) * textureData->width + x;
|
||||
size_t pixelSize = getPixelSize(textureData->format);
|
||||
uint8_t* u8 = (uint8_t*) textureData->blob->data + pixelSize * index;
|
||||
void lovrImageSetPixel(Image* image, uint32_t x, uint32_t y, Color color) {
|
||||
lovrAssert(image->blob->data, "Image does not have any pixel data");
|
||||
lovrAssert(x < image->width && y < image->height, "setPixel coordinates must be within Image bounds");
|
||||
size_t index = (image->height - (y + 1)) * image->width + x;
|
||||
size_t pixelSize = getPixelSize(image->format);
|
||||
uint8_t* u8 = (uint8_t*) image->blob->data + pixelSize * index;
|
||||
float* f32 = (float*) u8;
|
||||
switch (textureData->format) {
|
||||
switch (image->format) {
|
||||
case FORMAT_RGB:
|
||||
u8[0] = (uint8_t) (color.r * 255.f + .5f);
|
||||
u8[1] = (uint8_t) (color.g * 255.f + .5f);
|
||||
|
@ -594,7 +602,7 @@ void lovrTextureDataSetPixel(TextureData* textureData, uint32_t x, uint32_t y, C
|
|||
f32[1] = color.g;
|
||||
break;
|
||||
|
||||
default: lovrThrow("Unsupported format for TextureData:setPixel");
|
||||
default: lovrThrow("Unsupported format for Image:setPixel");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -623,11 +631,11 @@ static uint32_t crc32(uint8_t* data, size_t length) {
|
|||
return c ^ 0xffffffff;
|
||||
}
|
||||
|
||||
Blob* lovrTextureDataEncode(TextureData* textureData) {
|
||||
lovrAssert(textureData->format == FORMAT_RGBA, "Only RGBA TextureData can be encoded");
|
||||
uint32_t w = textureData->width;
|
||||
uint32_t h = textureData->height;
|
||||
uint8_t* pixels = (uint8_t*) textureData->blob->data + (h - 1) * w * 4;
|
||||
Blob* lovrImageEncode(Image* image) {
|
||||
lovrAssert(image->format == FORMAT_RGBA, "Only RGBA Image can be encoded");
|
||||
uint32_t w = image->width;
|
||||
uint32_t h = image->height;
|
||||
uint8_t* pixels = (uint8_t*) image->blob->data + (h - 1) * w * 4;
|
||||
int32_t stride = -1 * (int) (w * 4);
|
||||
|
||||
// The world's worst png encoder
|
||||
|
@ -732,28 +740,20 @@ Blob* lovrTextureDataEncode(TextureData* textureData) {
|
|||
memcpy(data + 8, (uint8_t[4]) { crc >> 24, crc >> 16, crc >> 8, crc >> 0 }, 4);
|
||||
data += 8 + 4;
|
||||
|
||||
return lovrBlobCreate(data - size, size, "Encoded TextureData");
|
||||
return lovrBlobCreate(data - size, size, "Encoded Image");
|
||||
}
|
||||
|
||||
void lovrTextureDataPaste(TextureData* textureData, TextureData* source, uint32_t dx, uint32_t dy, uint32_t sx, uint32_t sy, uint32_t w, uint32_t h) {
|
||||
lovrAssert(textureData->format == source->format, "Currently TextureData must have the same format to paste");
|
||||
lovrAssert(textureData->format < FORMAT_DXT1, "Compressed TextureData cannot be pasted");
|
||||
size_t pixelSize = getPixelSize(textureData->format);
|
||||
lovrAssert(dx + w <= textureData->width && dy + h <= textureData->height, "Attempt to paste outside of destination TextureData bounds");
|
||||
lovrAssert(sx + w <= source->width && sy + h <= source->height, "Attempt to paste from outside of source TextureData bounds");
|
||||
void lovrImagePaste(Image* image, Image* source, uint32_t dx, uint32_t dy, uint32_t sx, uint32_t sy, uint32_t w, uint32_t h) {
|
||||
lovrAssert(image->format == source->format, "Currently Image must have the same format to paste");
|
||||
lovrAssert(image->format < FORMAT_DXT1, "Compressed Image cannot be pasted");
|
||||
size_t pixelSize = getPixelSize(image->format);
|
||||
lovrAssert(dx + w <= image->width && dy + h <= image->height, "Attempt to paste outside of destination Image bounds");
|
||||
lovrAssert(sx + w <= source->width && sy + h <= source->height, "Attempt to paste from outside of source Image bounds");
|
||||
uint8_t* src = (uint8_t*) source->blob->data + ((source->height - 1 - sy) * source->width + sx) * pixelSize;
|
||||
uint8_t* dst = (uint8_t*) textureData->blob->data + ((textureData->height - 1 - dy) * textureData->width + sx) * pixelSize;
|
||||
uint8_t* dst = (uint8_t*) image->blob->data + ((image->height - 1 - dy) * image->width + sx) * pixelSize;
|
||||
for (uint32_t y = 0; y < h; y++) {
|
||||
memcpy(dst, src, w * pixelSize);
|
||||
src -= source->width * pixelSize;
|
||||
dst -= textureData->width * pixelSize;
|
||||
dst -= image->width * pixelSize;
|
||||
}
|
||||
}
|
||||
|
||||
void lovrTextureDataDestroy(void* ref) {
|
||||
TextureData* textureData = ref;
|
||||
lovrRelease(textureData->source, lovrBlobDestroy);
|
||||
free(textureData->mipmaps);
|
||||
lovrRelease(textureData->blob, lovrBlobDestroy);
|
||||
free(textureData);
|
||||
}
|
|
@ -51,7 +51,7 @@ typedef struct {
|
|||
void* data;
|
||||
} Mipmap;
|
||||
|
||||
typedef struct TextureData {
|
||||
typedef struct Image {
|
||||
ref_t ref;
|
||||
struct Blob* blob;
|
||||
uint32_t width;
|
||||
|
@ -60,12 +60,12 @@ typedef struct TextureData {
|
|||
TextureFormat format;
|
||||
Mipmap* mipmaps;
|
||||
uint32_t mipmapCount;
|
||||
} TextureData;
|
||||
} Image;
|
||||
|
||||
TextureData* lovrTextureDataCreate(uint32_t width, uint32_t height, struct Blob* contents, uint8_t value, TextureFormat format);
|
||||
TextureData* lovrTextureDataCreateFromBlob(struct Blob* blob, bool flip);
|
||||
Color lovrTextureDataGetPixel(TextureData* textureData, uint32_t x, uint32_t y);
|
||||
void lovrTextureDataSetPixel(TextureData* textureData, uint32_t x, uint32_t y, Color color);
|
||||
struct Blob* lovrTextureDataEncode(TextureData* textureData);
|
||||
void lovrTextureDataPaste(TextureData* textureData, TextureData* source, uint32_t dx, uint32_t dy, uint32_t sx, uint32_t sy, uint32_t w, uint32_t h);
|
||||
void lovrTextureDataDestroy(void* ref);
|
||||
Image* lovrImageCreate(uint32_t width, uint32_t height, struct Blob* contents, uint8_t value, TextureFormat format);
|
||||
Image* lovrImageCreateFromBlob(struct Blob* blob, bool flip);
|
||||
void lovrImageDestroy(void* ref);
|
||||
Color lovrImageGetPixel(Image* image, uint32_t x, uint32_t y);
|
||||
void lovrImageSetPixel(Image* image, uint32_t x, uint32_t y, Color color);
|
||||
struct Blob* lovrImageEncode(Image* image);
|
||||
void lovrImagePaste(Image* image, Image* source, uint32_t dx, uint32_t dy, uint32_t sx, uint32_t sy, uint32_t w, uint32_t h);
|
|
@ -1,6 +1,6 @@
|
|||
#include "data/modelData.h"
|
||||
#include "data/blob.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
ModelData* lovrModelDataCreate(Blob* source, ModelDataIO* io) {
|
||||
|
@ -23,8 +23,8 @@ void lovrModelDataDestroy(void* ref) {
|
|||
for (uint32_t i = 0; i < model->blobCount; i++) {
|
||||
lovrRelease(model->blobs[i], lovrBlobDestroy);
|
||||
}
|
||||
for (uint32_t i = 0; i < model->textureCount; i++) {
|
||||
lovrRelease(model->textures[i], lovrTextureDataDestroy);
|
||||
for (uint32_t i = 0; i < model->imageCount; i++) {
|
||||
lovrRelease(model->images[i], lovrImageDestroy);
|
||||
}
|
||||
map_free(&model->animationMap);
|
||||
map_free(&model->materialMap);
|
||||
|
@ -40,7 +40,7 @@ void lovrModelDataAllocate(ModelData* model) {
|
|||
size_t alignment = 8;
|
||||
totalSize += sizes[0] = ALIGN(model->blobCount * sizeof(Blob*), alignment);
|
||||
totalSize += sizes[1] = ALIGN(model->bufferCount * sizeof(ModelBuffer), alignment);
|
||||
totalSize += sizes[2] = ALIGN(model->textureCount * sizeof(TextureData*), alignment);
|
||||
totalSize += sizes[2] = ALIGN(model->imageCount * sizeof(Image*), alignment);
|
||||
totalSize += sizes[3] = ALIGN(model->materialCount * sizeof(ModelMaterial), alignment);
|
||||
totalSize += sizes[4] = ALIGN(model->attributeCount * sizeof(ModelAttribute), alignment);
|
||||
totalSize += sizes[5] = ALIGN(model->primitiveCount * sizeof(ModelPrimitive), alignment);
|
||||
|
@ -57,7 +57,7 @@ void lovrModelDataAllocate(ModelData* model) {
|
|||
lovrAssert(model->data, "Out of memory");
|
||||
model->blobs = (Blob**) (p + offset), offset += sizes[0];
|
||||
model->buffers = (ModelBuffer*) (p + offset), offset += sizes[1];
|
||||
model->textures = (TextureData**) (p + offset), offset += sizes[2];
|
||||
model->images = (Image**) (p + offset), offset += sizes[2];
|
||||
model->materials = (ModelMaterial*) (p + offset), offset += sizes[3];
|
||||
model->attributes = (ModelAttribute*) (p + offset), offset += sizes[4];
|
||||
model->primitives = (ModelPrimitive*) (p + offset), offset += sizes[5];
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
#define MAX_BONES 48
|
||||
|
||||
struct TextureData;
|
||||
struct Blob;
|
||||
struct Image;
|
||||
|
||||
typedef enum {
|
||||
ATTR_POSITION,
|
||||
|
@ -142,7 +142,7 @@ typedef struct {
|
|||
const char* name;
|
||||
float scalars[MAX_MATERIAL_SCALARS];
|
||||
Color colors[MAX_MATERIAL_COLORS];
|
||||
uint32_t textures[MAX_MATERIAL_TEXTURES];
|
||||
uint32_t images[MAX_MATERIAL_TEXTURES];
|
||||
TextureFilter filters[MAX_MATERIAL_TEXTURES];
|
||||
TextureWrap wraps[MAX_MATERIAL_TEXTURES];
|
||||
} ModelMaterial;
|
||||
|
@ -183,7 +183,7 @@ typedef struct ModelData {
|
|||
void* data;
|
||||
struct Blob** blobs;
|
||||
ModelBuffer* buffers;
|
||||
struct TextureData** textures;
|
||||
struct Image** images;
|
||||
ModelMaterial* materials;
|
||||
ModelAttribute* attributes;
|
||||
ModelPrimitive* primitives;
|
||||
|
@ -194,7 +194,7 @@ typedef struct ModelData {
|
|||
|
||||
uint32_t blobCount;
|
||||
uint32_t bufferCount;
|
||||
uint32_t textureCount;
|
||||
uint32_t imageCount;
|
||||
uint32_t materialCount;
|
||||
uint32_t attributeCount;
|
||||
uint32_t primitiveCount;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "data/modelData.h"
|
||||
#include "data/blob.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "core/maf.h"
|
||||
#include "lib/jsmn/jsmn.h"
|
||||
#include <stdbool.h>
|
||||
|
@ -133,7 +133,7 @@ static jsmntok_t* resolveTexture(const char* json, jsmntok_t* token, ModelMateri
|
|||
uint32_t index = NOM_INT(json, token);
|
||||
gltfTexture* texture = &textures[index];
|
||||
gltfSampler* sampler = texture->sampler == ~0u ? NULL : &samplers[texture->sampler];
|
||||
material->textures[textureType] = texture->image;
|
||||
material->images[textureType] = texture->image;
|
||||
material->filters[textureType] = sampler ? sampler->filter : (TextureFilter) { .mode = FILTER_BILINEAR };
|
||||
material->wraps[textureType] = sampler ? sampler->wrap : (TextureWrap) { .s = WRAP_REPEAT, .t = WRAP_REPEAT, .r = WRAP_REPEAT };
|
||||
} else if (STR_EQ(key, "texCoord")) {
|
||||
|
@ -303,7 +303,7 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
|
|||
|
||||
} else if (STR_EQ(key, "images")) {
|
||||
info.images = token;
|
||||
model->textureCount = token->size;
|
||||
model->imageCount = token->size;
|
||||
token += NOM_VALUE(json, token);
|
||||
|
||||
} else if (STR_EQ(key, "samplers")) {
|
||||
|
@ -649,17 +649,17 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
|
|||
}
|
||||
}
|
||||
|
||||
// Textures (glTF images)
|
||||
if (model->textureCount > 0) {
|
||||
// Images
|
||||
if (model->imageCount > 0) {
|
||||
jsmntok_t* token = info.images;
|
||||
TextureData** texture = model->textures;
|
||||
for (int i = (token++)->size; i > 0; i--, texture++) {
|
||||
Image** image = model->images;
|
||||
for (int i = (token++)->size; i > 0; i--, image++) {
|
||||
for (int k = (token++)->size; k > 0; k--) {
|
||||
gltfString key = NOM_STR(json, token);
|
||||
if (STR_EQ(key, "bufferView")) {
|
||||
ModelBuffer* buffer = &model->buffers[NOM_INT(json, token)];
|
||||
Blob* blob = lovrBlobCreate(buffer->data, buffer->size, NULL);
|
||||
*texture = lovrTextureDataCreateFromBlob(blob, false);
|
||||
*image = lovrImageCreateFromBlob(blob, false);
|
||||
blob->data = NULL; // XXX Blob data ownership
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
} else if (STR_EQ(key, "uri")) {
|
||||
|
@ -669,9 +669,9 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
|
|||
lovrAssert(uri.length < maxPathLength, "Image filename is too long");
|
||||
strncat(filename, uri.data, uri.length);
|
||||
void* data = io(filename, &size);
|
||||
lovrAssert(data && size > 0, "Unable to read texture from '%s'", filename);
|
||||
lovrAssert(data && size > 0, "Unable to read image from '%s'", filename);
|
||||
Blob* blob = lovrBlobCreate(data, size, NULL);
|
||||
*texture = lovrTextureDataCreateFromBlob(blob, false);
|
||||
*image = lovrImageCreateFromBlob(blob, false);
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
*root = '\0';
|
||||
} else {
|
||||
|
@ -690,7 +690,7 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
|
|||
material->scalars[SCALAR_ROUGHNESS] = 1.f;
|
||||
material->colors[COLOR_DIFFUSE] = (Color) { 1.f, 1.f, 1.f, 1.f };
|
||||
material->colors[COLOR_EMISSIVE] = (Color) { 0.f, 0.f, 0.f, 0.f };
|
||||
memset(material->textures, 0xff, MAX_MATERIAL_TEXTURES * sizeof(uint32_t));
|
||||
memset(material->images, 0xff, MAX_MATERIAL_TEXTURES * sizeof(uint32_t));
|
||||
|
||||
for (int k = (token++)->size; k > 0; k--) {
|
||||
gltfString key = NOM_STR(json, token);
|
||||
|
@ -711,7 +711,7 @@ ModelData* lovrModelDataInitGltf(ModelData* model, Blob* source, ModelDataIO* io
|
|||
material->scalars[SCALAR_ROUGHNESS] = NOM_FLOAT(json, token);
|
||||
} else if (STR_EQ(key, "metallicRoughnessTexture")) {
|
||||
token = resolveTexture(json, token, material, TEXTURE_METALNESS, textures, samplers);
|
||||
material->textures[TEXTURE_ROUGHNESS] = material->textures[TEXTURE_METALNESS];
|
||||
material->images[TEXTURE_ROUGHNESS] = material->images[TEXTURE_METALNESS];
|
||||
material->filters[TEXTURE_ROUGHNESS] = material->filters[TEXTURE_METALNESS];
|
||||
material->wraps[TEXTURE_ROUGHNESS] = material->wraps[TEXTURE_METALNESS];
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "data/modelData.h"
|
||||
#include "data/blob.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "core/maf.h"
|
||||
#include "core/map.h"
|
||||
#include "core/util.h"
|
||||
|
@ -15,7 +15,7 @@ typedef struct {
|
|||
} objGroup;
|
||||
|
||||
typedef arr_t(ModelMaterial) arr_material_t;
|
||||
typedef arr_t(TextureData*) arr_texturedata_t;
|
||||
typedef arr_t(Image*) arr_image_t;
|
||||
typedef arr_t(objGroup) arr_group_t;
|
||||
|
||||
#define STARTS_WITH(a, b) !strncmp(a, b, strlen(b))
|
||||
|
@ -27,7 +27,7 @@ static uint32_t nomu32(char* s, char** end) {
|
|||
return n;
|
||||
}
|
||||
|
||||
static void parseMtl(char* path, char* base, ModelDataIO* io, arr_texturedata_t* textures, arr_material_t* materials, map_t* names) {
|
||||
static void parseMtl(char* path, char* base, ModelDataIO* io, arr_image_t* images, arr_material_t* materials, map_t* names) {
|
||||
size_t size = 0;
|
||||
char* p = io(path, &size);
|
||||
lovrAssert(p && size > 0, "Unable to read mtl from '%s'", path);
|
||||
|
@ -53,7 +53,7 @@ static void parseMtl(char* path, char* base, ModelDataIO* io, arr_texturedata_t*
|
|||
.colors[COLOR_DIFFUSE] = { 1.f, 1.f, 1.f, 1.f },
|
||||
.colors[COLOR_EMISSIVE] = { 0.f, 0.f, 0.f, 0.f }
|
||||
}));
|
||||
memset(&materials->data[materials->length - 1].textures, 0xff, MAX_MATERIAL_TEXTURES * sizeof(int));
|
||||
memset(&materials->data[materials->length - 1].images, 0xff, MAX_MATERIAL_TEXTURES * sizeof(int));
|
||||
} else if (line[0] == 'K' && line[1] == 'd' && line[2] == ' ') {
|
||||
float r, g, b;
|
||||
char* s = line + 3;
|
||||
|
@ -63,22 +63,22 @@ static void parseMtl(char* path, char* base, ModelDataIO* io, arr_texturedata_t*
|
|||
ModelMaterial* material = &materials->data[materials->length - 1];
|
||||
material->colors[COLOR_DIFFUSE] = (Color) { r, g, b, 1.f };
|
||||
} else if (STARTS_WITH(line, "map_Kd ")) {
|
||||
lovrAssert(base - path + (length - 7) < 1024, "Bad OBJ: Material texture filename is too long");
|
||||
lovrAssert(base - path + (length - 7) < 1024, "Bad OBJ: Material image filename is too long");
|
||||
memcpy(base, line + 7, length - 7);
|
||||
base[length - 7] = '\0';
|
||||
|
||||
size_t imageSize = 0;
|
||||
void* image = io(path, &imageSize);
|
||||
lovrAssert(image && imageSize > 0, "Unable to read texture from %s", path);
|
||||
Blob* blob = lovrBlobCreate(image, imageSize, NULL);
|
||||
void* pixels = io(path, &imageSize);
|
||||
lovrAssert(pixels && imageSize > 0, "Unable to read image from %s", path);
|
||||
Blob* blob = lovrBlobCreate(pixels, imageSize, NULL);
|
||||
|
||||
TextureData* texture = lovrTextureDataCreateFromBlob(blob, true);
|
||||
Image* image = lovrImageCreateFromBlob(blob, true);
|
||||
lovrAssert(materials->length > 0, "Tried to set a material property without declaring a material first");
|
||||
ModelMaterial* material = &materials->data[materials->length - 1];
|
||||
material->textures[TEXTURE_DIFFUSE] = (uint32_t) textures->length;
|
||||
material->images[TEXTURE_DIFFUSE] = (uint32_t) images->length;
|
||||
material->filters[TEXTURE_DIFFUSE].mode = FILTER_TRILINEAR;
|
||||
material->wraps[TEXTURE_DIFFUSE] = (TextureWrap) { .s = WRAP_REPEAT, .t = WRAP_REPEAT };
|
||||
arr_push(textures, texture);
|
||||
arr_push(images, image);
|
||||
lovrRelease(blob, lovrBlobDestroy);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO* io)
|
|||
size_t size = source->size;
|
||||
|
||||
arr_group_t groups;
|
||||
arr_texturedata_t textures;
|
||||
arr_image_t images;
|
||||
arr_material_t materials;
|
||||
arr_t(float) vertexBlob;
|
||||
arr_t(int) indexBlob;
|
||||
|
@ -107,7 +107,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO* io)
|
|||
arr_t(float) uvs;
|
||||
|
||||
arr_init(&groups, realloc);
|
||||
arr_init(&textures, realloc);
|
||||
arr_init(&images, realloc);
|
||||
arr_init(&materials, realloc);
|
||||
map_init(&materialMap, 0);
|
||||
arr_init(&vertexBlob, realloc);
|
||||
|
@ -215,7 +215,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO* io)
|
|||
lovrAssert(baseLength + filenameLength < sizeof(path), "Bad OBJ: Material filename is too long");
|
||||
memcpy(path + baseLength, filename, filenameLength);
|
||||
path[baseLength + filenameLength] = '\0';
|
||||
parseMtl(path, base, io, &textures, &materials, &materialMap);
|
||||
parseMtl(path, base, io, &images, &materials, &materialMap);
|
||||
} else if (STARTS_WITH(line, "usemtl ")) {
|
||||
uint64_t index = map_get(&materialMap, hash64(line + 7, length - 7));
|
||||
int material = index == MAP_NIL ? -1 : index;
|
||||
|
@ -244,7 +244,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO* io)
|
|||
model->attributeCount = 3 + (uint32_t) groups.length;
|
||||
model->primitiveCount = (uint32_t) groups.length;
|
||||
model->nodeCount = 1;
|
||||
model->textureCount = (uint32_t) textures.length;
|
||||
model->imageCount = (uint32_t) images.length;
|
||||
model->materialCount = (uint32_t) materials.length;
|
||||
lovrModelDataAllocate(model);
|
||||
|
||||
|
@ -263,7 +263,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO* io)
|
|||
.stride = sizeof(int)
|
||||
};
|
||||
|
||||
memcpy(model->textures, textures.data, model->textureCount * sizeof(TextureData*));
|
||||
memcpy(model->images, images.data, model->imageCount * sizeof(Image*));
|
||||
memcpy(model->materials, materials.data, model->materialCount * sizeof(ModelMaterial));
|
||||
memcpy(model->materialMap.hashes, materialMap.hashes, materialMap.size * sizeof(uint64_t));
|
||||
memcpy(model->materialMap.values, materialMap.values, materialMap.size * sizeof(uint64_t));
|
||||
|
@ -348,7 +348,7 @@ ModelData* lovrModelDataInitObj(ModelData* model, Blob* source, ModelDataIO* io)
|
|||
|
||||
finish:
|
||||
arr_free(&groups);
|
||||
arr_free(&textures);
|
||||
arr_free(&images);
|
||||
arr_free(&materials);
|
||||
map_free(&materialMap);
|
||||
map_free(&vertexMap);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "data/rasterizer.h"
|
||||
#include "data/blob.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "resources/VarelaRound.ttf.h"
|
||||
#include "core/utf.h"
|
||||
#include "core/util.h"
|
||||
|
@ -167,7 +167,7 @@ void lovrRasterizerLoadGlyph(Rasterizer* rasterizer, uint32_t character, Glyph*
|
|||
glyph->dx = empty ? 0 : roundf(bearing * rasterizer->scale);
|
||||
glyph->dy = empty ? 0 : roundf(y1 * rasterizer->scale);
|
||||
glyph->advance = roundf(advance * rasterizer->scale);
|
||||
glyph->data = lovrTextureDataCreate(glyph->tw, glyph->th, NULL, 0, FORMAT_RGB);
|
||||
glyph->data = lovrImageCreate(glyph->tw, glyph->th, NULL, 0, FORMAT_RGB);
|
||||
|
||||
// Render SDF
|
||||
float tx = GLYPH_PADDING + -glyph->dx;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#define GLYPH_PADDING 1
|
||||
|
||||
struct Blob;
|
||||
struct TextureData;
|
||||
struct Image;
|
||||
|
||||
typedef struct {
|
||||
uint32_t x;
|
||||
|
@ -18,7 +18,7 @@ typedef struct {
|
|||
int32_t dx;
|
||||
int32_t dy;
|
||||
int32_t advance;
|
||||
struct TextureData* data;
|
||||
struct Image* data;
|
||||
} Glyph;
|
||||
|
||||
typedef struct Rasterizer Rasterizer;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MAX_CANVAS_ATTACHMENTS 4
|
||||
|
||||
struct Image;
|
||||
struct Texture;
|
||||
struct TextureData;
|
||||
|
||||
typedef struct Attachment {
|
||||
struct Texture* texture;
|
||||
|
@ -39,4 +39,4 @@ void lovrCanvasSetWidth(Canvas* canvas, uint32_t width);
|
|||
void lovrCanvasSetHeight(Canvas* canvas, uint32_t height);
|
||||
uint32_t lovrCanvasGetMSAA(Canvas* canvas);
|
||||
struct Texture* lovrCanvasGetDepthTexture(Canvas* canvas);
|
||||
struct TextureData* lovrCanvasNewTextureData(Canvas* canvas, uint32_t index);
|
||||
struct Image* lovrCanvasNewImage(Canvas* canvas, uint32_t index);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "graphics/font.h"
|
||||
#include "graphics/texture.h"
|
||||
#include "data/rasterizer.h"
|
||||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "core/map.h"
|
||||
#include "core/utf.h"
|
||||
#include <string.h>
|
||||
|
@ -85,7 +85,7 @@ void lovrFontDestroy(void* ref) {
|
|||
lovrRelease(font->rasterizer, lovrRasterizerDestroy);
|
||||
lovrRelease(font->texture, lovrTextureDestroy);
|
||||
for (size_t i = 0; i < font->atlas.glyphs.length; i++) {
|
||||
lovrRelease(font->atlas.glyphs.data[i].data, lovrTextureDataDestroy);
|
||||
lovrRelease(font->atlas.glyphs.data[i].data, lovrImageDestroy);
|
||||
}
|
||||
arr_free(&font->atlas.glyphs);
|
||||
map_free(&font->atlas.glyphMap);
|
||||
|
@ -369,13 +369,13 @@ static void lovrFontExpandTexture(Font* font) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO we only need the TextureData here to clear the texture, but it's a big waste of memory.
|
||||
// TODO we only need the Image here to clear the texture, but it's a big waste of memory.
|
||||
// Could look into using glClearTexImage when supported to make this more efficient.
|
||||
static void lovrFontCreateTexture(Font* font) {
|
||||
lovrRelease(font->texture, lovrTextureDestroy);
|
||||
TextureData* textureData = lovrTextureDataCreate(font->atlas.width, font->atlas.height, NULL, 0x0, FORMAT_RGB);
|
||||
font->texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, false, false, 0);
|
||||
Image* image = lovrImageCreate(font->atlas.width, font->atlas.height, NULL, 0x0, FORMAT_RGB);
|
||||
font->texture = lovrTextureCreate(TEXTURE_2D, &image, 1, false, false, 0);
|
||||
lovrTextureSetFilter(font->texture, (TextureFilter) { .mode = FILTER_BILINEAR });
|
||||
lovrTextureSetWrap(font->texture, (TextureWrap) { .s = WRAP_CLAMP, .t = WRAP_CLAMP });
|
||||
lovrRelease(textureData, lovrTextureDataDestroy);
|
||||
lovrRelease(image, lovrImageDestroy);
|
||||
}
|
||||
|
|
|
@ -86,8 +86,8 @@ Model* lovrModelCreate(ModelData* data) {
|
|||
if (data->materialCount > 0) {
|
||||
model->materials = malloc(data->materialCount * sizeof(Material*));
|
||||
|
||||
if (data->textureCount > 0) {
|
||||
model->textures = calloc(data->textureCount, sizeof(Texture*));
|
||||
if (data->imageCount > 0) {
|
||||
model->textures = calloc(data->imageCount, sizeof(Texture*));
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < data->materialCount; i++) {
|
||||
|
@ -102,13 +102,13 @@ Model* lovrModelCreate(ModelData* data) {
|
|||
}
|
||||
|
||||
for (uint32_t j = 0; j < MAX_MATERIAL_TEXTURES; j++) {
|
||||
uint32_t index = data->materials[i].textures[j];
|
||||
uint32_t index = data->materials[i].images[j];
|
||||
|
||||
if (index != ~0u) {
|
||||
if (!model->textures[index]) {
|
||||
TextureData* textureData = data->textures[index];
|
||||
Image* image = data->images[index];
|
||||
bool srgb = j == TEXTURE_DIFFUSE || j == TEXTURE_EMISSIVE;
|
||||
model->textures[index] = lovrTextureCreate(TEXTURE_2D, &textureData, 1, srgb, true, 0);
|
||||
model->textures[index] = lovrTextureCreate(TEXTURE_2D, &image, 1, srgb, true, 0);
|
||||
lovrTextureSetFilter(model->textures[index], data->materials[i].filters[j]);
|
||||
lovrTextureSetWrap(model->textures[index], data->materials[i].wraps[j]);
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ void lovrModelDestroy(void* ref) {
|
|||
}
|
||||
|
||||
if (model->textures) {
|
||||
for (uint32_t i = 0; i < model->data->textureCount; i++) {
|
||||
for (uint32_t i = 0; i < model->data->imageCount; i++) {
|
||||
lovrRelease(model->textures[i], lovrTextureDestroy);
|
||||
}
|
||||
free(model->textures);
|
||||
|
|
|
@ -189,7 +189,7 @@ static struct {
|
|||
BlockBuffer blockBuffers[2][MAX_BLOCK_BUFFERS];
|
||||
int activeTexture;
|
||||
Texture* textures[MAX_TEXTURES];
|
||||
Image images[MAX_IMAGES];
|
||||
StorageImage images[MAX_IMAGES];
|
||||
float viewports[2][4];
|
||||
uint32_t viewportCount;
|
||||
arr_t(void*) incoherents[MAX_BARRIERS];
|
||||
|
@ -766,11 +766,11 @@ static void lovrGpuBindTexture(Texture* texture, int slot) {
|
|||
}
|
||||
|
||||
#ifndef LOVR_WEBGL
|
||||
static void lovrGpuBindImage(Image* image, int slot, const char* name) {
|
||||
static void lovrGpuBindImage(StorageImage* image, int slot, const char* name) {
|
||||
lovrAssert(slot >= 0 && slot < MAX_IMAGES, "Invalid image slot %d", slot);
|
||||
|
||||
// This is a risky way to compare the two structs
|
||||
if (memcmp(state.images + slot, image, sizeof(Image))) {
|
||||
if (memcmp(state.images + slot, image, sizeof(StorageImage))) {
|
||||
Texture* texture = image->texture;
|
||||
lovrAssert(texture, "No Texture bound to image uniform '%s'", name);
|
||||
lovrAssert(texture->format != FORMAT_RGBA || !texture->srgb, "Attempt to bind sRGB texture to image uniform '%s'", name);
|
||||
|
@ -786,7 +786,7 @@ static void lovrGpuBindImage(Image* image, int slot, const char* name) {
|
|||
lovrRetain(texture);
|
||||
lovrRelease(state.images[slot].texture, lovrTextureDestroy);
|
||||
glBindImageTexture(slot, texture->id, image->mipmap, layered, slice, glAccess, glFormat);
|
||||
memcpy(state.images + slot, image, sizeof(Image));
|
||||
memcpy(state.images + slot, image, sizeof(StorageImage));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1167,7 +1167,7 @@ static void lovrGpuBindShader(Shader* shader) {
|
|||
case UNIFORM_IMAGE:
|
||||
#ifndef LOVR_WEBGL
|
||||
for (int j = 0; j < count; j++) {
|
||||
Image* image = &uniform->value.images[j];
|
||||
StorageImage* image = &uniform->value.images[j];
|
||||
Texture* texture = image->texture;
|
||||
lovrAssert(!texture || texture->type == uniform->textureType, "Uniform texture type mismatch for uniform '%s'", uniform->name);
|
||||
|
||||
|
@ -1348,11 +1348,11 @@ void lovrGpuInit(void* (*getProcAddress)(const char*), bool debug) {
|
|||
arr_init(&state.incoherents[i], realloc);
|
||||
}
|
||||
|
||||
TextureData* textureData = lovrTextureDataCreate(1, 1, NULL, 0xff, FORMAT_RGBA);
|
||||
state.defaultTexture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true, false, 0);
|
||||
Image* image = lovrImageCreate(1, 1, NULL, 0xff, FORMAT_RGBA);
|
||||
state.defaultTexture = lovrTextureCreate(TEXTURE_2D, &image, 1, true, false, 0);
|
||||
lovrTextureSetFilter(state.defaultTexture, (TextureFilter) { .mode = FILTER_NEAREST });
|
||||
lovrTextureSetWrap(state.defaultTexture, (TextureWrap) { WRAP_CLAMP, WRAP_CLAMP, WRAP_CLAMP });
|
||||
lovrRelease(textureData, lovrTextureDataDestroy);
|
||||
lovrRelease(image, lovrImageDestroy);
|
||||
|
||||
map_init(&state.timerMap, 4);
|
||||
state.queryPool.next = ~0u;
|
||||
|
@ -1670,7 +1670,7 @@ const GpuStats* lovrGpuGetStats() {
|
|||
|
||||
// Texture
|
||||
|
||||
Texture* lovrTextureCreate(TextureType type, TextureData** slices, uint32_t sliceCount, bool srgb, bool mipmaps, uint32_t msaa) {
|
||||
Texture* lovrTextureCreate(TextureType type, Image** slices, uint32_t sliceCount, bool srgb, bool mipmaps, uint32_t msaa) {
|
||||
Texture* texture = calloc(1, sizeof(Texture));
|
||||
lovrAssert(texture, "Out of memory");
|
||||
texture->ref = 1;
|
||||
|
@ -1814,7 +1814,7 @@ void lovrTextureAllocate(Texture* texture, uint32_t width, uint32_t height, uint
|
|||
state.stats.textureMemory += getTextureMemorySize(texture);
|
||||
}
|
||||
|
||||
void lovrTextureReplacePixels(Texture* texture, TextureData* textureData, uint32_t x, uint32_t y, uint32_t slice, uint32_t mipmap) {
|
||||
void lovrTextureReplacePixels(Texture* texture, Image* image, uint32_t x, uint32_t y, uint32_t slice, uint32_t mipmap) {
|
||||
lovrGraphicsFlush();
|
||||
lovrAssert(texture->allocated, "Texture is not allocated");
|
||||
|
||||
|
@ -1826,21 +1826,21 @@ void lovrTextureReplacePixels(Texture* texture, TextureData* textureData, uint32
|
|||
|
||||
uint32_t maxWidth = lovrTextureGetWidth(texture, mipmap);
|
||||
uint32_t maxHeight = lovrTextureGetHeight(texture, mipmap);
|
||||
uint32_t width = textureData->width;
|
||||
uint32_t height = textureData->height;
|
||||
uint32_t width = image->width;
|
||||
uint32_t height = image->height;
|
||||
bool overflow = (x + width > maxWidth) || (y + height > maxHeight);
|
||||
lovrAssert(!overflow, "Trying to replace pixels outside the texture's bounds");
|
||||
lovrAssert(mipmap < texture->mipmapCount, "Invalid mipmap level %d", mipmap);
|
||||
GLenum glFormat = convertTextureFormat(textureData->format);
|
||||
GLenum glInternalFormat = convertTextureFormatInternal(textureData->format, texture->srgb);
|
||||
GLenum glFormat = convertTextureFormat(image->format);
|
||||
GLenum glInternalFormat = convertTextureFormatInternal(image->format, texture->srgb);
|
||||
GLenum binding = (texture->type == TEXTURE_CUBE) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice : texture->target;
|
||||
|
||||
lovrGpuBindTexture(texture, 0);
|
||||
if (isTextureFormatCompressed(textureData->format)) {
|
||||
if (isTextureFormatCompressed(image->format)) {
|
||||
lovrAssert(width == maxWidth && height == maxHeight, "Compressed texture pixels must be fully replaced");
|
||||
lovrAssert(mipmap == 0, "Unable to replace a specific mipmap of a compressed texture");
|
||||
for (uint32_t i = 0; i < textureData->mipmapCount; i++) {
|
||||
Mipmap* m = textureData->mipmaps + i;
|
||||
for (uint32_t i = 0; i < image->mipmapCount; i++) {
|
||||
Mipmap* m = image->mipmaps + i;
|
||||
switch (texture->type) {
|
||||
case TEXTURE_2D:
|
||||
case TEXTURE_CUBE:
|
||||
|
@ -1853,17 +1853,17 @@ void lovrTextureReplacePixels(Texture* texture, TextureData* textureData, uint32
|
|||
}
|
||||
}
|
||||
} else {
|
||||
lovrAssert(textureData->blob->data, "Trying to replace Texture pixels with empty pixel data");
|
||||
GLenum glType = convertTextureFormatType(textureData->format);
|
||||
lovrAssert(image->blob->data, "Trying to replace Texture pixels with empty pixel data");
|
||||
GLenum glType = convertTextureFormatType(image->format);
|
||||
|
||||
switch (texture->type) {
|
||||
case TEXTURE_2D:
|
||||
case TEXTURE_CUBE:
|
||||
glTexSubImage2D(binding, mipmap, x, y, width, height, glFormat, glType, textureData->blob->data);
|
||||
glTexSubImage2D(binding, mipmap, x, y, width, height, glFormat, glType, image->blob->data);
|
||||
break;
|
||||
case TEXTURE_ARRAY:
|
||||
case TEXTURE_VOLUME:
|
||||
glTexSubImage3D(binding, mipmap, x, y, slice, width, height, 1, glFormat, glType, textureData->blob->data);
|
||||
glTexSubImage3D(binding, mipmap, x, y, slice, width, height, 1, glFormat, glType, image->blob->data);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2110,7 +2110,7 @@ void lovrCanvasResolve(Canvas* canvas) {
|
|||
canvas->needsResolve = false;
|
||||
}
|
||||
|
||||
TextureData* lovrCanvasNewTextureData(Canvas* canvas, uint32_t index) {
|
||||
Image* lovrCanvasNewImage(Canvas* canvas, uint32_t index) {
|
||||
lovrGraphicsFlushCanvas(canvas);
|
||||
lovrGpuBindCanvas(canvas, false);
|
||||
|
||||
|
@ -2129,14 +2129,14 @@ TextureData* lovrCanvasNewTextureData(Canvas* canvas, uint32_t index) {
|
|||
glReadBuffer(index);
|
||||
}
|
||||
|
||||
TextureData* textureData = lovrTextureDataCreate(canvas->width, canvas->height, NULL, 0x0, FORMAT_RGBA);
|
||||
glReadPixels(0, 0, canvas->width, canvas->height, GL_RGBA, GL_UNSIGNED_BYTE, textureData->blob->data);
|
||||
Image* image = lovrImageCreate(canvas->width, canvas->height, NULL, 0x0, FORMAT_RGBA);
|
||||
glReadPixels(0, 0, canvas->width, canvas->height, GL_RGBA, GL_UNSIGNED_BYTE, image->blob->data);
|
||||
|
||||
if (index != 0) {
|
||||
glReadBuffer(0);
|
||||
}
|
||||
|
||||
return textureData;
|
||||
return image;
|
||||
}
|
||||
|
||||
const Attachment* lovrCanvasGetAttachments(Canvas* canvas, uint32_t* count) {
|
||||
|
@ -2536,7 +2536,7 @@ static void lovrShaderSetupUniforms(Shader* shader) {
|
|||
|
||||
case UNIFORM_SAMPLER:
|
||||
case UNIFORM_IMAGE:
|
||||
uniform.size = uniform.count * (uniform.type == UNIFORM_SAMPLER ? sizeof(Texture*) : sizeof(Image));
|
||||
uniform.size = uniform.count * (uniform.type == UNIFORM_SAMPLER ? sizeof(Texture*) : sizeof(StorageImage));
|
||||
uniform.value.data = calloc(1, uniform.size);
|
||||
lovrAssert(uniform.value.data, "Out of memory");
|
||||
|
||||
|
@ -2815,8 +2815,8 @@ void lovrShaderSetTextures(Shader* shader, const char* name, Texture** data, int
|
|||
lovrShaderSetUniform(shader, name, UNIFORM_SAMPLER, data, start, count, sizeof(Texture*), "texture");
|
||||
}
|
||||
|
||||
void lovrShaderSetImages(Shader* shader, const char* name, Image* data, int start, int count) {
|
||||
lovrShaderSetUniform(shader, name, UNIFORM_IMAGE, data, start, count, sizeof(Image), "image");
|
||||
void lovrShaderSetImages(Shader* shader, const char* name, StorageImage* data, int start, int count) {
|
||||
lovrShaderSetUniform(shader, name, UNIFORM_IMAGE, data, start, count, sizeof(StorageImage), "image");
|
||||
}
|
||||
|
||||
void lovrShaderSetColor(Shader* shader, const char* name, Color color) {
|
||||
|
|
|
@ -64,7 +64,7 @@ typedef struct {
|
|||
int slice;
|
||||
int mipmap;
|
||||
UniformAccess access;
|
||||
} Image;
|
||||
} StorageImage;
|
||||
|
||||
typedef struct Uniform {
|
||||
char name[LOVR_MAX_UNIFORM_LENGTH];
|
||||
|
@ -80,7 +80,7 @@ typedef struct Uniform {
|
|||
int* ints;
|
||||
float* floats;
|
||||
struct Texture** textures;
|
||||
Image* images;
|
||||
StorageImage* images;
|
||||
} value;
|
||||
TextureType textureType;
|
||||
int baseSlot;
|
||||
|
@ -118,7 +118,7 @@ void lovrShaderSetFloats(Shader* shader, const char* name, float* data, int star
|
|||
void lovrShaderSetInts(Shader* shader, const char* name, int* data, int start, int count);
|
||||
void lovrShaderSetMatrices(Shader* shader, const char* name, float* data, int start, int count);
|
||||
void lovrShaderSetTextures(Shader* shader, const char* name, struct Texture** data, int start, int count);
|
||||
void lovrShaderSetImages(Shader* shader, const char* name, Image* data, int start, int count);
|
||||
void lovrShaderSetImages(Shader* shader, const char* name, StorageImage* data, int start, int count);
|
||||
void lovrShaderSetColor(Shader* shader, const char* name, Color color);
|
||||
void lovrShaderSetBlock(Shader* shader, const char* name, struct Buffer* buffer, size_t offset, size_t size, UniformAccess access);
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "data/textureData.h"
|
||||
#include "data/image.h"
|
||||
#include "graphics/graphics.h"
|
||||
#include "data/modelData.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
struct TextureData;
|
||||
struct Image;
|
||||
|
||||
typedef enum {
|
||||
TEXTURE_2D,
|
||||
|
@ -15,11 +15,11 @@ typedef enum {
|
|||
} TextureType;
|
||||
|
||||
typedef struct Texture Texture;
|
||||
Texture* lovrTextureCreate(TextureType type, struct TextureData** slices, uint32_t sliceCount, bool srgb, bool mipmaps, uint32_t msaa);
|
||||
Texture* lovrTextureCreate(TextureType type, struct Image** slices, uint32_t sliceCount, bool srgb, bool mipmaps, uint32_t msaa);
|
||||
Texture* lovrTextureCreateFromHandle(uint32_t handle, TextureType type, uint32_t depth, uint32_t msaa);
|
||||
void lovrTextureDestroy(void* ref);
|
||||
void lovrTextureAllocate(Texture* texture, uint32_t width, uint32_t height, uint32_t depth, TextureFormat format);
|
||||
void lovrTextureReplacePixels(Texture* texture, struct TextureData* data, uint32_t x, uint32_t y, uint32_t slice, uint32_t mipmap);
|
||||
void lovrTextureReplacePixels(Texture* texture, struct Image* data, uint32_t x, uint32_t y, uint32_t slice, uint32_t mipmap);
|
||||
uint64_t lovrTextureGetId(Texture* texture);
|
||||
uint32_t lovrTextureGetWidth(Texture* texture, uint32_t mipmap);
|
||||
uint32_t lovrTextureGetHeight(Texture* texture, uint32_t mipmap);
|
||||
|
|
|
@ -626,7 +626,7 @@ static ModelData* openvr_newModelData(Device device, bool animated) {
|
|||
model->nodeCount = animated ? (1 + modelCount) : 1;
|
||||
model->bufferCount = 2 * modelCount;
|
||||
model->attributeCount = 4 * modelCount;
|
||||
model->textureCount = modelCount;
|
||||
model->imageCount = modelCount;
|
||||
model->materialCount = modelCount;
|
||||
model->primitiveCount = modelCount;
|
||||
model->childCount = animated ? modelCount : 0;
|
||||
|
@ -702,12 +702,12 @@ static ModelData* openvr_newModelData(Device device, bool animated) {
|
|||
};
|
||||
|
||||
RenderModel_TextureMap_t* texture = renderModelTextures[i];
|
||||
model->textures[i] = lovrTextureDataCreate(texture->unWidth, texture->unHeight, NULL, 0, FORMAT_RGBA);
|
||||
memcpy(model->textures[i]->blob->data, texture->rubTextureMapData, texture->unWidth * texture->unHeight * 4);
|
||||
model->images[i] = lovrImageCreate(texture->unWidth, texture->unHeight, NULL, 0, FORMAT_RGBA);
|
||||
memcpy(model->images[i]->blob->data, texture->rubTextureMapData, texture->unWidth * texture->unHeight * 4);
|
||||
|
||||
model->materials[i] = (ModelMaterial) {
|
||||
.colors[COLOR_DIFFUSE] = { 1.f, 1.f, 1.f, 1.f },
|
||||
.textures[TEXTURE_DIFFUSE] = i,
|
||||
.images[TEXTURE_DIFFUSE] = i,
|
||||
.filters[TEXTURE_DIFFUSE] = lovrGraphicsGetDefaultFilter()
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue