2018-08-01 01:23:04 +00:00
|
|
|
#include "api.h"
|
2019-04-05 11:58:29 +00:00
|
|
|
#include "graphics/buffer.h"
|
2018-08-01 01:23:04 +00:00
|
|
|
#include "graphics/shader.h"
|
2019-06-02 07:20:10 +00:00
|
|
|
#include <stdlib.h>
|
2019-09-07 22:07:07 +00:00
|
|
|
#include <string.h>
|
2018-08-01 01:23:04 +00:00
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrShaderBlockGetType(lua_State* L) {
|
2018-08-06 17:42:19 +00:00
|
|
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
2020-02-17 02:31:02 +00:00
|
|
|
luax_pushenum(L, BlockTypes, lovrShaderBlockGetType(block));
|
2018-08-06 17:42:19 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrShaderBlockGetSize(lua_State* L) {
|
2018-08-01 01:23:04 +00:00
|
|
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
2018-12-07 00:34:14 +00:00
|
|
|
Buffer* buffer = lovrShaderBlockGetBuffer(block);
|
|
|
|
lua_pushinteger(L, lovrBufferGetSize(buffer));
|
2018-08-01 01:23:04 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrShaderBlockGetOffset(lua_State* L) {
|
2018-08-06 17:41:57 +00:00
|
|
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
2020-06-04 16:10:56 +00:00
|
|
|
const char* name = luaL_checkstring(L, 2);
|
|
|
|
const Uniform* uniform = lovrShaderBlockGetUniform(block, name);
|
|
|
|
lovrAssert(uniform, "Unknown uniform for ShaderBlock '%s'", name);
|
2018-08-06 18:46:42 +00:00
|
|
|
lua_pushinteger(L, uniform->offset);
|
2018-08-06 17:41:57 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrShaderBlockSend(lua_State* L) {
|
2018-08-01 01:23:04 +00:00
|
|
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
2018-08-06 17:42:23 +00:00
|
|
|
if (lua_type(L, 2) == LUA_TSTRING) {
|
|
|
|
const char* name = luaL_checkstring(L, 2);
|
|
|
|
const Uniform* uniform = lovrShaderBlockGetUniform(block, name);
|
|
|
|
lovrAssert(uniform, "Unknown uniform for ShaderBlock '%s'", name);
|
2018-12-07 00:34:14 +00:00
|
|
|
Buffer* buffer = lovrShaderBlockGetBuffer(block);
|
|
|
|
uint8_t* data = lovrBufferMap(buffer, uniform->offset);
|
2018-08-06 17:42:23 +00:00
|
|
|
luax_checkuniform(L, 3, uniform, data, name);
|
2019-05-14 03:35:21 +00:00
|
|
|
lovrBufferFlush(buffer, uniform->offset, uniform->size);
|
2018-08-06 17:42:23 +00:00
|
|
|
return 0;
|
|
|
|
} else {
|
2020-05-20 20:34:19 +00:00
|
|
|
Blob* blob = luax_checktype(L, 2, Blob);
|
2018-12-07 00:34:14 +00:00
|
|
|
Buffer* buffer = lovrShaderBlockGetBuffer(block);
|
|
|
|
void* data = lovrBufferMap(buffer, 0);
|
|
|
|
size_t bufferSize = lovrBufferGetSize(buffer);
|
|
|
|
size_t copySize = MIN(bufferSize, blob->size);
|
2018-08-06 17:42:23 +00:00
|
|
|
memcpy(data, blob->data, copySize);
|
2019-05-14 03:35:21 +00:00
|
|
|
lovrBufferFlush(buffer, 0, copySize);
|
2018-08-06 17:42:23 +00:00
|
|
|
lua_pushinteger(L, copySize);
|
|
|
|
return 1;
|
|
|
|
}
|
2018-08-01 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrShaderBlockRead(lua_State* L) {
|
2019-01-08 17:14:10 +00:00
|
|
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
|
|
|
const char* name = luaL_checkstring(L, 2);
|
|
|
|
const Uniform* uniform = lovrShaderBlockGetUniform(block, name);
|
|
|
|
lovrAssert(uniform, "Unknown uniform for ShaderBlock '%s'", name);
|
|
|
|
Buffer* buffer = lovrShaderBlockGetBuffer(block);
|
2019-01-16 16:52:21 +00:00
|
|
|
lovrAssert(lovrBufferIsReadable(buffer), "ShaderBlock:read requires the ShaderBlock to be created with the readable flag");
|
2019-01-08 17:14:10 +00:00
|
|
|
union { float* floats; int* ints; } data = { .floats = lovrBufferMap(buffer, uniform->offset) };
|
|
|
|
int components = uniform->components;
|
|
|
|
|
|
|
|
if (uniform->type == UNIFORM_MATRIX) {
|
|
|
|
components *= components;
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_createtable(L, uniform->count, 0);
|
|
|
|
for (int i = 0; i < uniform->count; i++) {
|
|
|
|
if (components == 1) {
|
|
|
|
switch (uniform->type) {
|
|
|
|
case UNIFORM_FLOAT:
|
|
|
|
lua_pushnumber(L, data.floats[i]);
|
|
|
|
lua_rawseti(L, -2, i + 1);
|
|
|
|
break;
|
|
|
|
case UNIFORM_INT:
|
|
|
|
lua_pushinteger(L, data.ints[i]);
|
|
|
|
lua_rawseti(L, -2, i + 1);
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lua_createtable(L, components, 0);
|
|
|
|
for (int j = 0; j < components; j++) {
|
|
|
|
switch (uniform->type) {
|
|
|
|
case UNIFORM_FLOAT:
|
|
|
|
case UNIFORM_MATRIX:
|
|
|
|
lua_pushnumber(L, data.floats[i * components + j]);
|
|
|
|
lua_rawseti(L, -2, j + 1);
|
|
|
|
break;
|
|
|
|
case UNIFORM_INT:
|
|
|
|
lua_pushinteger(L, data.ints[i * components + j]);
|
|
|
|
lua_rawseti(L, -2, j + 1);
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lua_rawseti(L, -2, i + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrShaderBlockGetShaderCode(lua_State* L) {
|
2018-08-06 18:46:42 +00:00
|
|
|
ShaderBlock* block = luax_checktype(L, 1, ShaderBlock);
|
|
|
|
const char* blockName = luaL_checkstring(L, 2);
|
2020-07-04 23:50:00 +00:00
|
|
|
const char* namespace = luaL_optstring(L, 3, NULL);
|
2018-08-06 18:46:42 +00:00
|
|
|
size_t length;
|
2020-07-04 23:50:00 +00:00
|
|
|
char* code = lovrShaderBlockGetShaderCode(block, blockName, namespace, &length);
|
2018-08-06 18:46:42 +00:00
|
|
|
lua_pushlstring(L, code, length);
|
2019-01-25 01:43:25 +00:00
|
|
|
free(code);
|
2018-08-06 18:46:42 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-08-01 01:23:04 +00:00
|
|
|
const luaL_Reg lovrShaderBlock[] = {
|
2019-01-16 16:52:21 +00:00
|
|
|
{ "getType", l_lovrShaderBlockGetType },
|
2018-08-06 18:46:42 +00:00
|
|
|
{ "getSize", l_lovrShaderBlockGetSize },
|
|
|
|
{ "getOffset", l_lovrShaderBlockGetOffset },
|
2019-01-16 16:52:21 +00:00
|
|
|
{ "read", l_lovrShaderBlockRead },
|
2018-08-01 01:23:04 +00:00
|
|
|
{ "send", l_lovrShaderBlockSend },
|
2018-08-06 18:46:42 +00:00
|
|
|
{ "getShaderCode", l_lovrShaderBlockGetShaderCode },
|
2018-08-01 01:23:04 +00:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|