New upstream version 23.2.1+dfsg1
This commit is contained in:
parent
cdc9a9fc87
commit
b14f9eae6d
1017 changed files with 37232 additions and 11111 deletions
|
|
@ -142,6 +142,9 @@ EXPORT void device_frustum(gs_device_t *device, float left, float right,
|
|||
float top, float bottom, float znear, float zfar);
|
||||
EXPORT void device_projection_push(gs_device_t *device);
|
||||
EXPORT void device_projection_pop(gs_device_t *device);
|
||||
EXPORT void device_debug_marker_begin(gs_device_t *device,
|
||||
const char *markername, const float color[4]);
|
||||
EXPORT void device_debug_marker_end(gs_device_t *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,39 @@
|
|||
#include "effect-parser.h"
|
||||
#include "effect.h"
|
||||
|
||||
static inline bool ep_parse_param_assign(struct effect_parser *ep,
|
||||
struct ep_param *param);
|
||||
|
||||
static enum gs_shader_param_type get_effect_param_type(const char *type)
|
||||
{
|
||||
if (strcmp(type, "float") == 0)
|
||||
return GS_SHADER_PARAM_FLOAT;
|
||||
else if (strcmp(type, "float2") == 0)
|
||||
return GS_SHADER_PARAM_VEC2;
|
||||
else if (strcmp(type, "float3") == 0)
|
||||
return GS_SHADER_PARAM_VEC3;
|
||||
else if (strcmp(type, "float4") == 0)
|
||||
return GS_SHADER_PARAM_VEC4;
|
||||
else if (strcmp(type, "int2") == 0)
|
||||
return GS_SHADER_PARAM_INT2;
|
||||
else if (strcmp(type, "int3") == 0)
|
||||
return GS_SHADER_PARAM_INT3;
|
||||
else if (strcmp(type, "int4") == 0)
|
||||
return GS_SHADER_PARAM_INT4;
|
||||
else if (astrcmp_n(type, "texture", 7) == 0)
|
||||
return GS_SHADER_PARAM_TEXTURE;
|
||||
else if (strcmp(type, "float4x4") == 0)
|
||||
return GS_SHADER_PARAM_MATRIX4X4;
|
||||
else if (strcmp(type, "bool") == 0)
|
||||
return GS_SHADER_PARAM_BOOL;
|
||||
else if (strcmp(type, "int") == 0)
|
||||
return GS_SHADER_PARAM_INT;
|
||||
else if (strcmp(type, "string") == 0)
|
||||
return GS_SHADER_PARAM_STRING;
|
||||
|
||||
return GS_SHADER_PARAM_UNKNOWN;
|
||||
}
|
||||
|
||||
void ep_free(struct effect_parser *ep)
|
||||
{
|
||||
size_t i;
|
||||
|
|
@ -92,6 +125,18 @@ static inline struct ep_param *ep_getparam(struct effect_parser *ep,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct ep_param *ep_getannotation(struct ep_param *param,
|
||||
const char *name)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < param->annotations.num; i++) {
|
||||
if (strcmp(name, param->annotations.array[i].name) == 0)
|
||||
return param->annotations.array+i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct ep_func *ep_getfunc_strref(struct effect_parser *ep,
|
||||
const struct strref *ref)
|
||||
{
|
||||
|
|
@ -262,6 +307,145 @@ error:
|
|||
ep_struct_free(&eps);
|
||||
}
|
||||
|
||||
static inline int ep_parse_param_annotation_var(struct effect_parser *ep,
|
||||
struct ep_param *var)
|
||||
{
|
||||
int code;
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* variable type */
|
||||
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&ep->cfp, ";"))
|
||||
return PARSE_CONTINUE;
|
||||
if (cf_token_is(&ep->cfp, ">"))
|
||||
return PARSE_BREAK;
|
||||
|
||||
code = cf_token_is_type(&ep->cfp, CFTOKEN_NAME, "type name", ";");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
bfree(var->type);
|
||||
cf_copy_token(&ep->cfp, &var->type);
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* variable name */
|
||||
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&ep->cfp, ";")) {
|
||||
cf_adderror_expecting(&ep->cfp, "variable name");
|
||||
return PARSE_UNEXPECTED_CONTINUE;
|
||||
}
|
||||
if (cf_token_is(&ep->cfp, ">")) {
|
||||
cf_adderror_expecting(&ep->cfp, "variable name");
|
||||
return PARSE_UNEXPECTED_BREAK;
|
||||
}
|
||||
|
||||
code = cf_token_is_type(&ep->cfp, CFTOKEN_NAME, "variable name", ";");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
bfree(var->name);
|
||||
cf_copy_token(&ep->cfp, &var->name);
|
||||
|
||||
/* -------------------------------------- */
|
||||
/* variable mapping if any (POSITION, TEXCOORD, etc) */
|
||||
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&ep->cfp, ":")) {
|
||||
cf_adderror_expecting(&ep->cfp, "= or ;");
|
||||
return PARSE_UNEXPECTED_BREAK;
|
||||
} else if (cf_token_is(&ep->cfp, ">")) {
|
||||
cf_adderror_expecting(&ep->cfp, "= or ;");
|
||||
return PARSE_UNEXPECTED_BREAK;
|
||||
} else if (cf_token_is(&ep->cfp, "=")) {
|
||||
if (!ep_parse_param_assign(ep, var)) {
|
||||
cf_adderror_expecting(&ep->cfp, "assignment value");
|
||||
return PARSE_UNEXPECTED_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------- */
|
||||
|
||||
if (!cf_token_is(&ep->cfp, ";")) {
|
||||
if (!cf_go_to_valid_token(&ep->cfp, ";", ">")) {
|
||||
cf_adderror_expecting(&ep->cfp, "; or >");
|
||||
return PARSE_EOF;
|
||||
}
|
||||
return PARSE_CONTINUE;
|
||||
}
|
||||
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
static int ep_parse_annotations(struct effect_parser *ep,
|
||||
struct darray *annotations)
|
||||
{
|
||||
if (!cf_token_is(&ep->cfp, "<")) {
|
||||
cf_adderror_expecting(&ep->cfp, "<");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* get annotation variables */
|
||||
while (true) {
|
||||
bool do_break = false;
|
||||
struct ep_param var;
|
||||
|
||||
ep_param_init(&var, bstrdup(""), bstrdup(""), false, false,
|
||||
false);
|
||||
|
||||
switch (ep_parse_param_annotation_var(ep, &var)) {
|
||||
case PARSE_UNEXPECTED_CONTINUE:
|
||||
cf_adderror_syntax_error(&ep->cfp);
|
||||
/* Falls through. */
|
||||
case PARSE_CONTINUE:
|
||||
ep_param_free(&var);
|
||||
continue;
|
||||
|
||||
case PARSE_UNEXPECTED_BREAK:
|
||||
cf_adderror_syntax_error(&ep->cfp);
|
||||
/* Falls through. */
|
||||
case PARSE_BREAK:
|
||||
ep_param_free(&var);
|
||||
do_break = true;
|
||||
break;
|
||||
|
||||
case PARSE_EOF:
|
||||
ep_param_free(&var);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (do_break)
|
||||
break;
|
||||
|
||||
darray_push_back(sizeof(struct ep_param), annotations, &var);
|
||||
}
|
||||
|
||||
if (!cf_token_is(&ep->cfp, ">")) {
|
||||
cf_adderror_expecting(&ep->cfp, ">");
|
||||
goto error;
|
||||
}
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
goto error;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ep_parse_param_annotations(struct effect_parser *ep,
|
||||
struct ep_param *param)
|
||||
{
|
||||
return ep_parse_annotations(ep, ¶m->annotations.da);
|
||||
}
|
||||
|
||||
static inline int ep_parse_pass_command_call(struct effect_parser *ep,
|
||||
struct darray *call)
|
||||
{
|
||||
|
|
@ -328,7 +512,7 @@ static int ep_parse_pass(struct effect_parser *ep, struct ep_pass *pass)
|
|||
|
||||
if (!cf_token_is(&ep->cfp, "{")) {
|
||||
pass->name = bstrdup_n(ep->cfp.cur_token->str.array,
|
||||
ep->cfp.cur_token->str.len);
|
||||
ep->cfp.cur_token->str.len);
|
||||
if (!cf_next_valid_token(&ep->cfp)) return PARSE_EOF;
|
||||
}
|
||||
|
||||
|
|
@ -356,9 +540,19 @@ static void ep_parse_technique(struct effect_parser *ep)
|
|||
|
||||
if (cf_next_name(&ep->cfp, &ept.name, "name", ";") != PARSE_SUCCESS)
|
||||
goto error;
|
||||
if (cf_next_token_should_be(&ep->cfp, "{", ";", NULL) != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
return;
|
||||
|
||||
if (!cf_token_is(&ep->cfp, "{")) {
|
||||
if (!cf_go_to_token(&ep->cfp, ";", NULL)) {
|
||||
cf_adderror_expecting(&ep->cfp, ";");
|
||||
return;
|
||||
}
|
||||
|
||||
cf_adderror_expecting(&ep->cfp, "{");
|
||||
goto error;
|
||||
}
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
goto error;
|
||||
|
||||
|
|
@ -756,6 +950,30 @@ static inline int ep_parse_param_assign_texture(struct effect_parser *ep,
|
|||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
static inline int ep_parse_param_assign_string(struct effect_parser *ep,
|
||||
struct ep_param *param)
|
||||
{
|
||||
int code;
|
||||
char *str = NULL;
|
||||
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
code = cf_token_is_type(&ep->cfp, CFTOKEN_STRING, "string", ";");
|
||||
if (code != PARSE_SUCCESS)
|
||||
return code;
|
||||
|
||||
str = cf_literal_to_str(ep->cfp.cur_token->str.array,
|
||||
ep->cfp.cur_token->str.len);
|
||||
|
||||
if (str) {
|
||||
da_copy_array(param->default_val, str, strlen(str) + 1);
|
||||
bfree(str);
|
||||
}
|
||||
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
static inline int ep_parse_param_assign_intfloat(struct effect_parser *ep,
|
||||
struct ep_param *param, bool is_float)
|
||||
{
|
||||
|
|
@ -789,30 +1007,51 @@ static inline int ep_parse_param_assign_intfloat(struct effect_parser *ep,
|
|||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* parses assignment for float1, float2, float3, float4, and any combination
|
||||
* for float3x3, float4x4, etc
|
||||
*/
|
||||
static inline int ep_parse_param_assign_float_array(struct effect_parser *ep,
|
||||
static inline int ep_parse_param_assign_bool(struct effect_parser *ep,
|
||||
struct ep_param *param)
|
||||
{
|
||||
const char *float_type = param->type+5;
|
||||
int float_count = 0, code, i;
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
return PARSE_EOF;
|
||||
|
||||
if (cf_token_is(&ep->cfp, "true")) {
|
||||
long l = 1;
|
||||
da_push_back_array(param->default_val, &l, sizeof(long));
|
||||
return PARSE_SUCCESS;
|
||||
} else if (cf_token_is(&ep->cfp, "false")) {
|
||||
long l = 0;
|
||||
da_push_back_array(param->default_val, &l, sizeof(long));
|
||||
return PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
cf_adderror_expecting(&ep->cfp, "true or false");
|
||||
|
||||
return PARSE_EOF;
|
||||
}
|
||||
|
||||
/*
|
||||
* parses assignment for float1, float2, float3, float4, int1, int2, int3, int4,
|
||||
* and any combination for float3x3, float4x4, int3x3, int4x4, etc
|
||||
*/
|
||||
static inline int ep_parse_param_assign_intfloat_array(struct effect_parser *ep,
|
||||
struct ep_param *param, bool is_float)
|
||||
{
|
||||
const char *intfloat_type = param->type + (is_float ? 5 : 3);
|
||||
int intfloat_count = 0, code, i;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
if (float_type[0] < '1' || float_type[0] > '4')
|
||||
if (intfloat_type[0] < '1' || intfloat_type[0] > '4')
|
||||
cf_adderror(&ep->cfp, "Invalid row count", LEX_ERROR,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
float_count = float_type[0]-'0';
|
||||
intfloat_count = intfloat_type[0]-'0';
|
||||
|
||||
if (float_type[1] == 'x') {
|
||||
if (float_type[2] < '1' || float_type[2] > '4')
|
||||
if (intfloat_type[1] == 'x') {
|
||||
if (intfloat_type[2] < '1' || intfloat_type[2] > '4')
|
||||
cf_adderror(&ep->cfp, "Invalid column count",
|
||||
LEX_ERROR, NULL, NULL, NULL);
|
||||
|
||||
float_count *= float_type[2]-'0';
|
||||
intfloat_count *= intfloat_type[2]-'0';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
@ -820,10 +1059,10 @@ static inline int ep_parse_param_assign_float_array(struct effect_parser *ep,
|
|||
code = cf_next_token_should_be(&ep->cfp, "{", ";", NULL);
|
||||
if (code != PARSE_SUCCESS) return code;
|
||||
|
||||
for (i = 0; i < float_count; i++) {
|
||||
char *next = ((i+1) < float_count) ? "," : "}";
|
||||
for (i = 0; i < intfloat_count; i++) {
|
||||
char *next = ((i+1) < intfloat_count) ? "," : "}";
|
||||
|
||||
code = ep_parse_param_assign_intfloat(ep, param, true);
|
||||
code = ep_parse_param_assign_intfloat(ep, param, is_float);
|
||||
if (code != PARSE_SUCCESS) return code;
|
||||
|
||||
code = cf_next_token_should_be(&ep->cfp, next, ";", NULL);
|
||||
|
|
@ -842,8 +1081,14 @@ static int ep_parse_param_assignment_val(struct effect_parser *ep,
|
|||
return ep_parse_param_assign_intfloat(ep, param, false);
|
||||
else if (strcmp(param->type, "float") == 0)
|
||||
return ep_parse_param_assign_intfloat(ep, param, true);
|
||||
else if (astrcmp_n(param->type, "int", 3) == 0)
|
||||
return ep_parse_param_assign_intfloat_array(ep, param, false);
|
||||
else if (astrcmp_n(param->type, "float", 5) == 0)
|
||||
return ep_parse_param_assign_float_array(ep, param);
|
||||
return ep_parse_param_assign_intfloat_array(ep, param, true);
|
||||
else if (astrcmp_n(param->type, "string", 6) == 0)
|
||||
return ep_parse_param_assign_string(ep, param);
|
||||
else if (strcmp(param->type, "bool") == 0)
|
||||
return ep_parse_param_assign_bool(ep, param);
|
||||
|
||||
cf_adderror(&ep->cfp, "Invalid type '$1' used for assignment",
|
||||
LEX_ERROR, param->type, NULL, NULL);
|
||||
|
|
@ -879,6 +1124,9 @@ static void ep_parse_param(struct effect_parser *ep,
|
|||
goto complete;
|
||||
if (cf_token_is(&ep->cfp, "[") && !ep_parse_param_array(ep, ¶m))
|
||||
goto error;
|
||||
if (cf_token_is(&ep->cfp, "<") && !ep_parse_param_annotations(ep,
|
||||
¶m))
|
||||
goto error;
|
||||
if (cf_token_is(&ep->cfp, "=") && !ep_parse_param_assign(ep, ¶m))
|
||||
goto error;
|
||||
/*
|
||||
|
|
@ -945,7 +1193,6 @@ static void ep_parse_other(struct effect_parser *ep)
|
|||
goto error;
|
||||
if (cf_next_name(&ep->cfp, &name, "name", ";") != PARSE_SUCCESS)
|
||||
goto error;
|
||||
|
||||
if (!cf_next_valid_token(&ep->cfp))
|
||||
goto error;
|
||||
|
||||
|
|
@ -971,6 +1218,213 @@ static bool ep_compile(struct effect_parser *ep);
|
|||
|
||||
extern const char *gs_preprocessor_name(void);
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
static void debug_get_default_value(struct gs_effect_param *param,
|
||||
char* buffer, unsigned long long buf_size)
|
||||
{
|
||||
if (param->default_val.num == 0) {
|
||||
snprintf(buffer, buf_size, "(null)");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (param->type) {
|
||||
case GS_SHADER_PARAM_STRING:
|
||||
snprintf(buffer, buf_size, "'%.*s'",
|
||||
param->default_val.num,
|
||||
param->default_val.array);
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT:
|
||||
snprintf(buffer, buf_size, "%ld",
|
||||
*(int*)(param->default_val.array + 0));
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT2:
|
||||
snprintf(buffer, buf_size, "%ld,%ld",
|
||||
*(int*)(param->default_val.array + 0),
|
||||
*(int*)(param->default_val.array + 4));
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT3:
|
||||
snprintf(buffer, buf_size, "%ld,%ld,%ld",
|
||||
*(int*)(param->default_val.array + 0),
|
||||
*(int*)(param->default_val.array + 4),
|
||||
*(int*)(param->default_val.array + 8));
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT4:
|
||||
snprintf(buffer, buf_size, "%ld,%ld,%ld,%ld",
|
||||
*(int*)(param->default_val.array + 0),
|
||||
*(int*)(param->default_val.array + 4),
|
||||
*(int*)(param->default_val.array + 8),
|
||||
*(int*)(param->default_val.array + 12));
|
||||
break;
|
||||
case GS_SHADER_PARAM_FLOAT:
|
||||
snprintf(buffer, buf_size, "%e",
|
||||
*(float*)(param->default_val.array + 0));
|
||||
break;
|
||||
case GS_SHADER_PARAM_VEC2:
|
||||
snprintf(buffer, buf_size, "%e,%e",
|
||||
*(float*)(param->default_val.array + 0),
|
||||
*(float*)(param->default_val.array + 4));
|
||||
break;
|
||||
case GS_SHADER_PARAM_VEC3:
|
||||
snprintf(buffer, buf_size, "%e,%e,%e",
|
||||
*(float*)(param->default_val.array + 0),
|
||||
*(float*)(param->default_val.array + 4),
|
||||
*(float*)(param->default_val.array + 8));
|
||||
break;
|
||||
case GS_SHADER_PARAM_VEC4:
|
||||
snprintf(buffer, buf_size, "%e,%e,%e,%e",
|
||||
*(float*)(param->default_val.array + 0),
|
||||
*(float*)(param->default_val.array + 4),
|
||||
*(float*)(param->default_val.array + 8),
|
||||
*(float*)(param->default_val.array + 12));
|
||||
break;
|
||||
case GS_SHADER_PARAM_MATRIX4X4:
|
||||
snprintf(buffer, buf_size,
|
||||
"[[%e,%e,%e,%e],[%e,%e,%e,%e],"
|
||||
"[%e,%e,%e,%e],[%e,%e,%e,%e]]",
|
||||
*(float*)(param->default_val.array + 0),
|
||||
*(float*)(param->default_val.array + 4),
|
||||
*(float*)(param->default_val.array + 8),
|
||||
*(float*)(param->default_val.array + 12),
|
||||
*(float*)(param->default_val.array + 16),
|
||||
*(float*)(param->default_val.array + 20),
|
||||
*(float*)(param->default_val.array + 24),
|
||||
*(float*)(param->default_val.array + 28),
|
||||
*(float*)(param->default_val.array + 32),
|
||||
*(float*)(param->default_val.array + 36),
|
||||
*(float*)(param->default_val.array + 40),
|
||||
*(float*)(param->default_val.array + 44),
|
||||
*(float*)(param->default_val.array + 48),
|
||||
*(float*)(param->default_val.array + 52),
|
||||
*(float*)(param->default_val.array + 56),
|
||||
*(float*)(param->default_val.array + 60));
|
||||
break;
|
||||
case GS_SHADER_PARAM_BOOL:
|
||||
snprintf(buffer, buf_size, "%s",
|
||||
(*param->default_val.array) != 0
|
||||
? "true\0"
|
||||
: "false\0");
|
||||
break;
|
||||
case GS_SHADER_PARAM_UNKNOWN:
|
||||
case GS_SHADER_PARAM_TEXTURE:
|
||||
snprintf(buffer, buf_size, "<unknown>");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void debug_param(struct gs_effect_param *param,
|
||||
struct ep_param *param_in, unsigned long long idx, const char* offset)
|
||||
{
|
||||
char _debug_type[4096];
|
||||
switch (param->type) {
|
||||
case GS_SHADER_PARAM_STRING:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "string");
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "int");
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT2:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "int2");
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT3:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "int3");
|
||||
break;
|
||||
case GS_SHADER_PARAM_INT4:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "int4");
|
||||
break;
|
||||
case GS_SHADER_PARAM_FLOAT:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "float");
|
||||
break;
|
||||
case GS_SHADER_PARAM_VEC2:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "float2");
|
||||
break;
|
||||
case GS_SHADER_PARAM_VEC3:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "float3");
|
||||
break;
|
||||
case GS_SHADER_PARAM_VEC4:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "float4");
|
||||
break;
|
||||
case GS_SHADER_PARAM_MATRIX4X4:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "float4x4");
|
||||
break;
|
||||
case GS_SHADER_PARAM_BOOL:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "bool");
|
||||
break;
|
||||
case GS_SHADER_PARAM_UNKNOWN:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "unknown");
|
||||
break;
|
||||
case GS_SHADER_PARAM_TEXTURE:
|
||||
snprintf(_debug_type, sizeof(_debug_type), "texture");
|
||||
break;
|
||||
}
|
||||
|
||||
char _debug_buf[4096];
|
||||
debug_get_default_value(param, _debug_buf, sizeof(_debug_buf));
|
||||
if (param->annotations.num > 0) {
|
||||
blog(LOG_DEBUG, "%s[%4lld] %.*s '%s' with value %.*s and %lld annotations:",
|
||||
offset,
|
||||
idx,
|
||||
sizeof(_debug_type), _debug_type,
|
||||
param->name,
|
||||
sizeof(_debug_buf), _debug_buf,
|
||||
param->annotations.num);
|
||||
} else {
|
||||
blog(LOG_DEBUG, "%s[%4lld] %.*s '%s' with value %.*s.",
|
||||
offset,
|
||||
idx,
|
||||
sizeof(_debug_type), _debug_type,
|
||||
param->name,
|
||||
sizeof(_debug_buf), _debug_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void debug_param_annotation(struct gs_effect_param *param,
|
||||
struct ep_param *param_in, unsigned long long idx, const char* offset)
|
||||
{
|
||||
char _debug_buf[4096];
|
||||
debug_get_default_value(param, _debug_buf, sizeof(_debug_buf));
|
||||
blog(LOG_DEBUG, "%s[%4lld] %s '%s' with value %.*s",
|
||||
offset,
|
||||
idx,
|
||||
param_in->type,
|
||||
param->name,
|
||||
sizeof(_debug_buf), _debug_buf);
|
||||
}
|
||||
|
||||
static void debug_print_string(const char* offset, const char* str)
|
||||
{
|
||||
// Bypass 4096 limit in def_log_handler.
|
||||
char const *begin = str;
|
||||
unsigned long long line = 1;
|
||||
for (char const *here = begin; here[0] != '\0'; here++) {
|
||||
char const * str = begin;
|
||||
unsigned long long len = here - begin;
|
||||
bool is_line = false;
|
||||
|
||||
if (here[0] == '\r') {
|
||||
is_line = true;
|
||||
if (here[1] == '\n') {
|
||||
here += 1;
|
||||
}
|
||||
begin = here + 1;
|
||||
} else if (here[0] == '\n') {
|
||||
is_line = true;
|
||||
begin = here + 1;
|
||||
}
|
||||
|
||||
if (is_line) {
|
||||
blog(LOG_DEBUG, "\t\t\t\t[%4lld] %.*s", line,
|
||||
len, str);
|
||||
line++;
|
||||
}
|
||||
}
|
||||
if (begin[0] != '\0') {
|
||||
// Final line was not written.
|
||||
blog(LOG_DEBUG, "\t\t\t\t[%4lld] %*s", line, strlen(begin), begin);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ep_parse(struct effect_parser *ep, gs_effect_t *effect,
|
||||
const char *effect_string, const char *file)
|
||||
{
|
||||
|
|
@ -1020,10 +1474,21 @@ bool ep_parse(struct effect_parser *ep, gs_effect_t *effect,
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
blog(LOG_DEBUG, "================================================================================");
|
||||
blog(LOG_DEBUG, "Effect Parser reformatted shader '%s' to:", file);
|
||||
debug_print_string("\t", ep->cfp.lex.reformatted);
|
||||
#endif
|
||||
|
||||
success = !error_data_has_errors(&ep->cfp.error_list);
|
||||
if (success)
|
||||
success = ep_compile(ep);
|
||||
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
blog(LOG_DEBUG, "================================================================================");
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -1309,6 +1774,9 @@ static void ep_makeshaderstring(struct effect_parser *ep,
|
|||
|
||||
dstr_init(&call_str);
|
||||
|
||||
if (!token)
|
||||
return;
|
||||
|
||||
while (token->type != CFTOKEN_NONE && is_whitespace(*token->str.array))
|
||||
token++;
|
||||
|
||||
|
|
@ -1339,6 +1807,39 @@ static void ep_makeshaderstring(struct effect_parser *ep,
|
|||
ep_reset_written(ep);
|
||||
}
|
||||
|
||||
static void ep_compile_annotations(struct darray *ep_annotations,
|
||||
struct darray *gsp_annotations, struct effect_parser *ep)
|
||||
{
|
||||
darray_resize(sizeof(struct gs_effect_param),
|
||||
gsp_annotations, ep_annotations->num);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < ep_annotations->num; i++) {
|
||||
struct gs_effect_param *param = ((struct gs_effect_param *)
|
||||
gsp_annotations->array)+i;
|
||||
struct ep_param *param_in = ((struct ep_param *)
|
||||
ep_annotations->array)+i;
|
||||
|
||||
param->name = bstrdup(param_in->name);
|
||||
param->section = EFFECT_ANNOTATION;
|
||||
param->effect = ep->effect;
|
||||
da_move(param->default_val, param_in->default_val);
|
||||
|
||||
param->type = get_effect_param_type(param_in->type);
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
debug_param(param, param_in, i, "\t\t");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void ep_compile_param_annotations(struct ep_param *ep_param_input,
|
||||
struct gs_effect_param *gs_effect_input, struct effect_parser *ep)
|
||||
{
|
||||
ep_compile_annotations(&(ep_param_input->annotations.da),
|
||||
&(gs_effect_input->annotations.da), ep);
|
||||
}
|
||||
|
||||
static void ep_compile_param(struct effect_parser *ep, size_t idx)
|
||||
{
|
||||
struct gs_effect_param *param;
|
||||
|
|
@ -1353,27 +1854,18 @@ static void ep_compile_param(struct effect_parser *ep, size_t idx)
|
|||
param->effect = ep->effect;
|
||||
da_move(param->default_val, param_in->default_val);
|
||||
|
||||
if (strcmp(param_in->type, "bool") == 0)
|
||||
param->type = GS_SHADER_PARAM_BOOL;
|
||||
else if (strcmp(param_in->type, "float") == 0)
|
||||
param->type = GS_SHADER_PARAM_FLOAT;
|
||||
else if (strcmp(param_in->type, "int") == 0)
|
||||
param->type = GS_SHADER_PARAM_INT;
|
||||
else if (strcmp(param_in->type, "float2") == 0)
|
||||
param->type = GS_SHADER_PARAM_VEC2;
|
||||
else if (strcmp(param_in->type, "float3") == 0)
|
||||
param->type = GS_SHADER_PARAM_VEC3;
|
||||
else if (strcmp(param_in->type, "float4") == 0)
|
||||
param->type = GS_SHADER_PARAM_VEC4;
|
||||
else if (strcmp(param_in->type, "float4x4") == 0)
|
||||
param->type = GS_SHADER_PARAM_MATRIX4X4;
|
||||
else if (param_in->is_texture)
|
||||
param->type = GS_SHADER_PARAM_TEXTURE;
|
||||
param->type = get_effect_param_type(param_in->type);
|
||||
|
||||
if (strcmp(param_in->name, "ViewProj") == 0)
|
||||
ep->effect->view_proj = param;
|
||||
else if (strcmp(param_in->name, "World") == 0)
|
||||
ep->effect->world = param;
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
debug_param(param, param_in, idx, "\t");
|
||||
#endif
|
||||
|
||||
ep_compile_param_annotations(param_in, param, ep);
|
||||
}
|
||||
|
||||
static bool ep_compile_pass_shaderparams(struct effect_parser *ep,
|
||||
|
|
@ -1397,6 +1889,10 @@ static bool ep_compile_pass_shaderparams(struct effect_parser *ep,
|
|||
param->sparam = gs_shader_get_param_by_name(shader,
|
||||
param_name->array);
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
debug_param(param->eparam, 0, i, "\t\t\t\t");
|
||||
#endif
|
||||
|
||||
if (!param->sparam) {
|
||||
blog(LOG_ERROR, "Effect shader parameter not found");
|
||||
return false;
|
||||
|
|
@ -1441,6 +1937,7 @@ static inline bool ep_compile_pass_shader(struct effect_parser *ep,
|
|||
pass->vertshader = gs_vertexshader_create(shader_str.array,
|
||||
location.array, NULL);
|
||||
|
||||
|
||||
shader = pass->vertshader;
|
||||
pass_params = &pass->vertshader_params.da;
|
||||
} else if (type == GS_SHADER_PIXEL) {
|
||||
|
|
@ -1454,12 +1951,12 @@ static inline bool ep_compile_pass_shader(struct effect_parser *ep,
|
|||
pass_params = &pass->pixelshader_params.da;
|
||||
}
|
||||
|
||||
#if 0
|
||||
blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++");
|
||||
blog(LOG_DEBUG, " %s", location.array);
|
||||
blog(LOG_DEBUG, "-----------------------------------");
|
||||
blog(LOG_DEBUG, "%s", shader_str.array);
|
||||
blog(LOG_DEBUG, "+++++++++++++++++++++++++++++++++++");
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
blog(LOG_DEBUG, "\t\t\t%s Shader:",
|
||||
type == GS_SHADER_VERTEX ? "Vertex" : "Fragment");
|
||||
blog(LOG_DEBUG, "\t\t\tCode:");
|
||||
debug_print_string("\t\t\t\t\t", shader_str.array);
|
||||
blog(LOG_DEBUG, "\t\t\tParameters:");
|
||||
#endif
|
||||
|
||||
if (shader)
|
||||
|
|
@ -1491,14 +1988,23 @@ static bool ep_compile_pass(struct effect_parser *ep,
|
|||
pass->name = bstrdup(pass_in->name);
|
||||
pass->section = EFFECT_PASS;
|
||||
|
||||
if (!ep_compile_pass_shader(ep, tech, pass, pass_in, idx,
|
||||
GS_SHADER_VERTEX))
|
||||
success = false;
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
blog(LOG_DEBUG, "\t\t[%4lld] Pass '%s':",
|
||||
idx, pass->name);
|
||||
#endif
|
||||
|
||||
if (!ep_compile_pass_shader(ep, tech, pass, pass_in, idx,
|
||||
GS_SHADER_PIXEL))
|
||||
GS_SHADER_VERTEX)) {
|
||||
success = false;
|
||||
|
||||
blog(LOG_ERROR, "Pass (%zu) <%s> missing vertex shader!",
|
||||
idx, pass->name ? pass->name : "");
|
||||
}
|
||||
if (!ep_compile_pass_shader(ep, tech, pass, pass_in, idx,
|
||||
GS_SHADER_PIXEL)) {
|
||||
success = false;
|
||||
blog(LOG_ERROR, "Pass (%zu) <%s> missing pixel shader!",
|
||||
idx, pass->name ? pass->name : "");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -1518,6 +2024,11 @@ static inline bool ep_compile_technique(struct effect_parser *ep, size_t idx)
|
|||
|
||||
da_resize(tech->passes, tech_in->passes.num);
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
blog(LOG_DEBUG, "\t[%4lld] Technique '%s' has %lld passes:",
|
||||
idx, tech->name, tech->passes.num);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < tech->passes.num; i++) {
|
||||
if (!ep_compile_pass(ep, tech, tech_in, i))
|
||||
success = false;
|
||||
|
|
@ -1536,8 +2047,17 @@ static bool ep_compile(struct effect_parser *ep)
|
|||
da_resize(ep->effect->params, ep->params.num);
|
||||
da_resize(ep->effect->techniques, ep->techniques.num);
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
blog(LOG_DEBUG, "Shader has %lld parameters:", ep->params.num);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ep->params.num; i++)
|
||||
ep_compile_param(ep, i);
|
||||
|
||||
#if defined(_DEBUG) && defined(_DEBUG_SHADERS)
|
||||
blog(LOG_DEBUG, "Shader has %lld techniques:", ep->techniques.num);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ep->techniques.num; i++) {
|
||||
if (!ep_compile_technique(ep, i))
|
||||
success = false;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "../util/darray.h"
|
||||
#include "../util/cf-parser.h"
|
||||
#include "graphics.h"
|
||||
#include "shader-parser.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -72,6 +73,7 @@ struct ep_param {
|
|||
struct gs_effect_param *param;
|
||||
bool is_const, is_property, is_uniform, is_texture, written;
|
||||
int writeorder, array_count;
|
||||
DARRAY(struct ep_param) annotations;
|
||||
};
|
||||
|
||||
extern void ep_param_writevar(struct dstr *dst, struct darray *use_params);
|
||||
|
|
@ -91,6 +93,7 @@ static inline void ep_param_init(struct ep_param *epp,
|
|||
epp->array_count = 0;
|
||||
da_init(epp->default_val);
|
||||
da_init(epp->properties);
|
||||
da_init(epp->annotations);
|
||||
}
|
||||
|
||||
static inline void ep_param_free(struct ep_param *epp)
|
||||
|
|
@ -99,6 +102,10 @@ static inline void ep_param_free(struct ep_param *epp)
|
|||
bfree(epp->name);
|
||||
da_free(epp->default_val);
|
||||
da_free(epp->properties);
|
||||
|
||||
for (size_t i = 0; i < epp->annotations.num; i++)
|
||||
ep_param_free(epp->annotations.array + i);
|
||||
da_free(epp->annotations);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -286,6 +286,63 @@ gs_eparam_t *gs_effect_get_param_by_name(const gs_effect_t *effect,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
size_t gs_param_get_num_annotations(const gs_eparam_t *param)
|
||||
{
|
||||
return param ? param->annotations.num : 0;
|
||||
}
|
||||
|
||||
gs_eparam_t *gs_param_get_annotation_by_idx(const gs_eparam_t *param,
|
||||
size_t annotation)
|
||||
{
|
||||
if (!param) return NULL;
|
||||
|
||||
struct gs_effect_param *params = param->annotations.array;
|
||||
if (annotation > param->annotations.num)
|
||||
return NULL;
|
||||
|
||||
return params + annotation;
|
||||
}
|
||||
|
||||
gs_eparam_t *gs_param_get_annotation_by_name(const gs_eparam_t *param,
|
||||
const char *name)
|
||||
{
|
||||
if (!param) return NULL;
|
||||
struct gs_effect_param *params = param->annotations.array;
|
||||
|
||||
for (size_t i = 0; i < param->annotations.num; i++) {
|
||||
struct gs_effect_param *g_param = params + i;
|
||||
if (strcmp(g_param->name, name) == 0)
|
||||
return g_param;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gs_epass_t *gs_technique_get_pass_by_idx(const gs_technique_t *technique,
|
||||
size_t pass)
|
||||
{
|
||||
if (!technique) return NULL;
|
||||
struct gs_effect_pass *passes = technique->passes.array;
|
||||
|
||||
if (pass > technique->passes.num)
|
||||
return NULL;
|
||||
|
||||
return passes + pass;
|
||||
}
|
||||
|
||||
gs_epass_t *gs_technique_get_pass_by_name(const gs_technique_t *technique,
|
||||
const char *name)
|
||||
{
|
||||
if (!technique) return NULL;
|
||||
struct gs_effect_pass *passes = technique->passes.array;
|
||||
|
||||
for (size_t i = 0; i < technique->passes.num; i++) {
|
||||
struct gs_effect_pass *g_pass = passes + i;
|
||||
if (strcmp(g_pass->name, name) == 0)
|
||||
return g_pass;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gs_eparam_t *gs_effect_get_viewproj_matrix(const gs_effect_t *effect)
|
||||
{
|
||||
return effect ? effect->view_proj : NULL;
|
||||
|
|
@ -332,6 +389,45 @@ static inline void effect_setval_inline(gs_eparam_t *param,
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
static inline void effect_getval_inline(gs_eparam_t *param, void *data,
|
||||
size_t size)
|
||||
{
|
||||
if (!param) {
|
||||
blog(LOG_ERROR, "effect_getval_inline: invalid param");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
blog(LOG_ERROR, "effect_getval_inline: invalid data");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bytes = min(size, param->cur_val.num);
|
||||
|
||||
memcpy(data, param->cur_val.array, bytes);
|
||||
}
|
||||
|
||||
static inline void effect_getdefaultval_inline(gs_eparam_t *param, void *data,
|
||||
size_t size)
|
||||
{
|
||||
if (!param) {
|
||||
blog(LOG_ERROR, "effect_getdefaultval_inline: invalid param");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
blog(LOG_ERROR, "effect_getdefaultval_inline: invalid data");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bytes = min(size, param->default_val.num);
|
||||
|
||||
memcpy(data, param->default_val.array, bytes);
|
||||
}
|
||||
|
||||
void gs_effect_set_bool(gs_eparam_t *param, bool val)
|
||||
{
|
||||
int b_val = (int)val;
|
||||
|
|
@ -385,6 +481,54 @@ void gs_effect_set_val(gs_eparam_t *param, const void *val, size_t size)
|
|||
effect_setval_inline(param, val, size);
|
||||
}
|
||||
|
||||
void *gs_effect_get_val(gs_eparam_t *param)
|
||||
{
|
||||
if (!param) {
|
||||
blog(LOG_ERROR, "gs_effect_get_val: invalid param");
|
||||
return NULL;
|
||||
}
|
||||
size_t size = param->cur_val.num;
|
||||
void *data;
|
||||
|
||||
if (size)
|
||||
data = (void*)bzalloc(size);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
effect_getval_inline(param, data, size);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t gs_effect_get_val_size(gs_eparam_t *param)
|
||||
{
|
||||
return param ? param->cur_val.num : 0;
|
||||
}
|
||||
|
||||
void *gs_effect_get_default_val(gs_eparam_t *param)
|
||||
{
|
||||
if (!param) {
|
||||
blog(LOG_ERROR, "gs_effect_get_default_val: invalid param");
|
||||
return NULL;
|
||||
}
|
||||
size_t size = param->default_val.num;
|
||||
void *data;
|
||||
|
||||
if (size)
|
||||
data = (void*)bzalloc(size);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
effect_getdefaultval_inline(param, data, size);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t gs_effect_get_default_val_size(gs_eparam_t *param)
|
||||
{
|
||||
return param ? param->default_val.num : 0;
|
||||
}
|
||||
|
||||
void gs_effect_set_default(gs_eparam_t *param)
|
||||
{
|
||||
effect_setval_inline(param, param->default_val.array,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ enum effect_section {
|
|||
EFFECT_PARAM,
|
||||
EFFECT_TECHNIQUE,
|
||||
EFFECT_SAMPLER,
|
||||
EFFECT_PASS
|
||||
EFFECT_PASS,
|
||||
EFFECT_ANNOTATION
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
|
@ -61,11 +62,13 @@ struct gs_effect_param {
|
|||
|
||||
/*char *full_name;
|
||||
float scroller_min, scroller_max, scroller_inc, scroller_mul;*/
|
||||
DARRAY(struct gs_effect_param) annotations;
|
||||
};
|
||||
|
||||
static inline void effect_param_init(struct gs_effect_param *param)
|
||||
{
|
||||
memset(param, 0, sizeof(struct gs_effect_param));
|
||||
da_init(param->annotations);
|
||||
}
|
||||
|
||||
static inline void effect_param_free(struct gs_effect_param *param)
|
||||
|
|
@ -74,6 +77,12 @@ static inline void effect_param_free(struct gs_effect_param *param)
|
|||
//bfree(param->full_name);
|
||||
da_free(param->cur_val);
|
||||
da_free(param->default_val);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < param->annotations.num; i++)
|
||||
effect_param_free(param->annotations.array + i);
|
||||
|
||||
da_free(param->annotations);
|
||||
}
|
||||
|
||||
EXPORT void effect_param_parse_property(gs_eparam_t *param,
|
||||
|
|
@ -106,6 +115,7 @@ static inline void effect_pass_free(struct gs_effect_pass *pass)
|
|||
bfree(pass->name);
|
||||
da_free(pass->vertshader_params);
|
||||
da_free(pass->pixelshader_params);
|
||||
|
||||
gs_shader_destroy(pass->vertshader);
|
||||
gs_shader_destroy(pass->pixelshader);
|
||||
}
|
||||
|
|
@ -130,6 +140,7 @@ static inline void effect_technique_free(struct gs_effect_technique *t)
|
|||
size_t i;
|
||||
for (i = 0; i < t->passes.num; i++)
|
||||
effect_pass_free(t->passes.array+i);
|
||||
|
||||
da_free(t->passes);
|
||||
bfree(t->name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@ bool load_graphics_imports(struct gs_exports *exports, void *module,
|
|||
GRAPHICS_IMPORT(gs_shader_set_default);
|
||||
GRAPHICS_IMPORT(gs_shader_set_next_sampler);
|
||||
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_nv12_available);
|
||||
|
||||
GRAPHICS_IMPORT(device_debug_marker_begin);
|
||||
GRAPHICS_IMPORT(device_debug_marker_end);
|
||||
|
||||
/* OSX/Cocoa specific functions */
|
||||
#ifdef __APPLE__
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_create_from_iosurface);
|
||||
|
|
@ -189,6 +194,11 @@ bool load_graphics_imports(struct gs_exports *exports, void *module,
|
|||
GRAPHICS_IMPORT_OPTIONAL(gs_texture_get_dc);
|
||||
GRAPHICS_IMPORT_OPTIONAL(gs_texture_release_dc);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_open_shared);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_get_shared_handle);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_acquire_sync);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_release_sync);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_texture_create_nv12);
|
||||
GRAPHICS_IMPORT_OPTIONAL(device_stagesurface_create_nv12);
|
||||
#endif
|
||||
|
||||
return success;
|
||||
|
|
|
|||
|
|
@ -232,6 +232,12 @@ struct gs_exports {
|
|||
void (*gs_shader_set_next_sampler)(gs_sparam_t *param,
|
||||
gs_samplerstate_t *sampler);
|
||||
|
||||
bool (*device_nv12_available)(gs_device_t *device);
|
||||
|
||||
void (*device_debug_marker_begin)(gs_device_t *device,
|
||||
const char *markername, const float color[4]);
|
||||
void (*device_debug_marker_end)(gs_device_t *device);
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* OSX/Cocoa specific functions */
|
||||
gs_texture_t *(*device_texture_create_from_iosurface)(gs_device_t *dev,
|
||||
|
|
@ -261,6 +267,16 @@ struct gs_exports {
|
|||
|
||||
gs_texture_t *(*device_texture_open_shared)(gs_device_t *device,
|
||||
uint32_t handle);
|
||||
uint32_t (*device_texture_get_shared_handle)(gs_texture_t *tex);
|
||||
int (*device_texture_acquire_sync)(gs_texture_t *tex, uint64_t key,
|
||||
uint32_t ms);
|
||||
int (*device_texture_release_sync)(gs_texture_t *tex, uint64_t key);
|
||||
bool (*device_texture_create_nv12)(gs_device_t *device,
|
||||
gs_texture_t **tex_y, gs_texture_t **tex_uv,
|
||||
uint32_t width, uint32_t height, uint32_t flags);
|
||||
|
||||
gs_stagesurf_t *(*device_stagesurface_create_nv12)(gs_device_t *device,
|
||||
uint32_t width, uint32_t height);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -160,12 +160,12 @@ static bool graphics_init(struct graphics_subsystem *graphics)
|
|||
|
||||
graphics->exports.device_blend_function_separate(graphics->device,
|
||||
GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA,
|
||||
GS_BLEND_ONE, GS_BLEND_ONE);
|
||||
GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
graphics->cur_blend_state.enabled = true;
|
||||
graphics->cur_blend_state.src_c = GS_BLEND_SRCALPHA;
|
||||
graphics->cur_blend_state.dest_c = GS_BLEND_INVSRCALPHA;
|
||||
graphics->cur_blend_state.src_a = GS_BLEND_ONE;
|
||||
graphics->cur_blend_state.dest_a = GS_BLEND_ONE;
|
||||
graphics->cur_blend_state.dest_a = GS_BLEND_INVSRCALPHA;
|
||||
|
||||
graphics->exports.device_leave_context(graphics->device);
|
||||
|
||||
|
|
@ -1240,10 +1240,10 @@ void gs_reset_blend_state(void)
|
|||
if (graphics->cur_blend_state.src_c != GS_BLEND_SRCALPHA ||
|
||||
graphics->cur_blend_state.dest_c != GS_BLEND_INVSRCALPHA ||
|
||||
graphics->cur_blend_state.src_a != GS_BLEND_ONE ||
|
||||
graphics->cur_blend_state.dest_a != GS_BLEND_ONE)
|
||||
graphics->cur_blend_state.dest_a != GS_BLEND_INVSRCALPHA)
|
||||
gs_blend_function_separate(
|
||||
GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA,
|
||||
GS_BLEND_ONE, GS_BLEND_ONE);
|
||||
GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
|
@ -1517,9 +1517,7 @@ gs_indexbuffer_t *gs_indexbuffer_create(enum gs_index_type type,
|
|||
return NULL;
|
||||
|
||||
if (indices && num && (flags & GS_DUP_BUFFER) != 0) {
|
||||
size_t size = type == GS_UNSIGNED_SHORT
|
||||
? sizeof(unsigned short)
|
||||
: sizeof(unsigned long);
|
||||
size_t size = type == GS_UNSIGNED_SHORT ? 2 : 4;
|
||||
indices = bmemdup(indices, size * num);
|
||||
}
|
||||
|
||||
|
|
@ -2545,6 +2543,61 @@ enum gs_index_type gs_indexbuffer_get_type(const gs_indexbuffer_t *indexbuffer)
|
|||
return thread_graphics->exports.gs_indexbuffer_get_type(indexbuffer);
|
||||
}
|
||||
|
||||
bool gs_nv12_available(void)
|
||||
{
|
||||
if (!gs_valid("gs_nv12_available"))
|
||||
return false;
|
||||
|
||||
if (!thread_graphics->exports.device_nv12_available)
|
||||
return false;
|
||||
|
||||
return thread_graphics->exports.device_nv12_available(
|
||||
thread_graphics->device);
|
||||
}
|
||||
|
||||
void gs_debug_marker_begin(const float color[4],
|
||||
const char *markername)
|
||||
{
|
||||
if (!gs_valid("gs_debug_marker_begin"))
|
||||
return;
|
||||
|
||||
if (!markername)
|
||||
markername = "(null)";
|
||||
|
||||
thread_graphics->exports.device_debug_marker_begin(
|
||||
thread_graphics->device, markername,
|
||||
color);
|
||||
}
|
||||
|
||||
void gs_debug_marker_begin_format(const float color[4],
|
||||
const char *format, ...)
|
||||
{
|
||||
if (!gs_valid("gs_debug_marker_begin"))
|
||||
return;
|
||||
|
||||
if (format) {
|
||||
char markername[64];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(markername, sizeof(markername), format, args);
|
||||
va_end(args);
|
||||
thread_graphics->exports.device_debug_marker_begin(
|
||||
thread_graphics->device, markername,
|
||||
color);
|
||||
} else {
|
||||
gs_debug_marker_begin(color, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void gs_debug_marker_end(void)
|
||||
{
|
||||
if (!gs_valid("gs_debug_marker_end"))
|
||||
return;
|
||||
|
||||
thread_graphics->exports.device_debug_marker_end(
|
||||
thread_graphics->device);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/** Platform specific functions */
|
||||
|
|
@ -2692,4 +2745,98 @@ gs_texture_t *gs_texture_open_shared(uint32_t handle)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t gs_texture_get_shared_handle(gs_texture_t *tex)
|
||||
{
|
||||
graphics_t *graphics = thread_graphics;
|
||||
if (!gs_valid("gs_texture_get_shared_handle"))
|
||||
return GS_INVALID_HANDLE;
|
||||
|
||||
if (graphics->exports.device_texture_get_shared_handle)
|
||||
return graphics->exports.device_texture_get_shared_handle(tex);
|
||||
return GS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
int gs_texture_acquire_sync(gs_texture_t *tex, uint64_t key, uint32_t ms)
|
||||
{
|
||||
graphics_t *graphics = thread_graphics;
|
||||
if (!gs_valid("gs_texture_acquire_sync"))
|
||||
return -1;
|
||||
|
||||
if (graphics->exports.device_texture_acquire_sync)
|
||||
return graphics->exports.device_texture_acquire_sync(tex,
|
||||
key, ms);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gs_texture_release_sync(gs_texture_t *tex, uint64_t key)
|
||||
{
|
||||
graphics_t *graphics = thread_graphics;
|
||||
if (!gs_valid("gs_texture_release_sync"))
|
||||
return -1;
|
||||
|
||||
if (graphics->exports.device_texture_release_sync)
|
||||
return graphics->exports.device_texture_release_sync(tex, key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool gs_texture_create_nv12(gs_texture_t **tex_y, gs_texture_t **tex_uv,
|
||||
uint32_t width, uint32_t height, uint32_t flags)
|
||||
{
|
||||
graphics_t *graphics = thread_graphics;
|
||||
bool success = false;
|
||||
|
||||
if (!gs_valid("gs_texture_create_nv12"))
|
||||
return false;
|
||||
|
||||
if ((width & 1) == 1 || (height & 1) == 1) {
|
||||
blog(LOG_ERROR, "NV12 textures must have dimensions "
|
||||
"divisible by 2.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (graphics->exports.device_texture_create_nv12) {
|
||||
success = graphics->exports.device_texture_create_nv12(
|
||||
graphics->device, tex_y, tex_uv,
|
||||
width, height, flags);
|
||||
if (success)
|
||||
return true;
|
||||
}
|
||||
|
||||
*tex_y = gs_texture_create(width, height, GS_R8, 1, NULL, flags);
|
||||
*tex_uv = gs_texture_create(width / 2, height / 2, GS_R8G8, 1, NULL,
|
||||
flags);
|
||||
|
||||
if (!*tex_y || !*tex_uv) {
|
||||
if (*tex_y)
|
||||
gs_texture_destroy(*tex_y);
|
||||
if (*tex_uv)
|
||||
gs_texture_destroy(*tex_uv);
|
||||
*tex_y = NULL;
|
||||
*tex_uv = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gs_stagesurf_t *gs_stagesurface_create_nv12(uint32_t width, uint32_t height)
|
||||
{
|
||||
graphics_t *graphics = thread_graphics;
|
||||
|
||||
if (!gs_valid("gs_stagesurface_create_nv12"))
|
||||
return NULL;
|
||||
|
||||
if ((width & 1) == 1 || (height & 1) == 1) {
|
||||
blog(LOG_ERROR, "NV12 textures must have dimensions "
|
||||
"divisible by 2.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (graphics->exports.device_stagesurface_create_nv12)
|
||||
return graphics->exports.device_stagesurface_create_nv12(
|
||||
graphics->device, width, height);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ enum gs_color_format {
|
|||
GS_R32F,
|
||||
GS_DXT1,
|
||||
GS_DXT3,
|
||||
GS_DXT5
|
||||
GS_DXT5,
|
||||
GS_R8G8,
|
||||
};
|
||||
|
||||
enum gs_zstencil_format {
|
||||
|
|
@ -267,6 +268,7 @@ typedef struct gs_shader gs_shader_t;
|
|||
typedef struct gs_shader_param gs_sparam_t;
|
||||
typedef struct gs_effect gs_effect_t;
|
||||
typedef struct gs_effect_technique gs_technique_t;
|
||||
typedef struct gs_effect_pass gs_epass_t;
|
||||
typedef struct gs_effect_param gs_eparam_t;
|
||||
typedef struct gs_device gs_device_t;
|
||||
typedef struct graphics_subsystem graphics_t;
|
||||
|
|
@ -368,12 +370,21 @@ EXPORT bool gs_technique_begin_pass(gs_technique_t *technique, size_t pass);
|
|||
EXPORT bool gs_technique_begin_pass_by_name(gs_technique_t *technique,
|
||||
const char *name);
|
||||
EXPORT void gs_technique_end_pass(gs_technique_t *technique);
|
||||
EXPORT gs_epass_t *gs_technique_get_pass_by_idx(const gs_technique_t *technique,
|
||||
size_t pass);
|
||||
EXPORT gs_epass_t *gs_technique_get_pass_by_name(
|
||||
const gs_technique_t *technique, const char *name);
|
||||
|
||||
EXPORT size_t gs_effect_get_num_params(const gs_effect_t *effect);
|
||||
EXPORT gs_eparam_t *gs_effect_get_param_by_idx(const gs_effect_t *effect,
|
||||
size_t param);
|
||||
EXPORT gs_eparam_t *gs_effect_get_param_by_name(const gs_effect_t *effect,
|
||||
const char *name);
|
||||
EXPORT size_t gs_param_get_num_annotations(const gs_eparam_t *param);
|
||||
EXPORT gs_eparam_t *gs_param_get_annotation_by_idx(const gs_eparam_t *param,
|
||||
size_t annotation);
|
||||
EXPORT gs_eparam_t *gs_param_get_annotation_by_name(const gs_eparam_t *param,
|
||||
const char *name);
|
||||
|
||||
/** Helper function to simplify effect usage. Use with a while loop that
|
||||
* contains drawing functions. Automatically handles techniques, passes, and
|
||||
|
|
@ -402,6 +413,10 @@ EXPORT void gs_effect_set_vec4(gs_eparam_t *param, const struct vec4 *val);
|
|||
EXPORT void gs_effect_set_texture(gs_eparam_t *param, gs_texture_t *val);
|
||||
EXPORT void gs_effect_set_val(gs_eparam_t *param, const void *val, size_t size);
|
||||
EXPORT void gs_effect_set_default(gs_eparam_t *param);
|
||||
EXPORT size_t gs_effect_get_val_size(gs_eparam_t *param);
|
||||
EXPORT void *gs_effect_get_val(gs_eparam_t *param);
|
||||
EXPORT size_t gs_effect_get_default_val_size(gs_eparam_t *param);
|
||||
EXPORT void *gs_effect_get_default_val(gs_eparam_t *param);
|
||||
EXPORT void gs_effect_set_next_sampler(gs_eparam_t *param,
|
||||
gs_samplerstate_t *sampler);
|
||||
|
||||
|
|
@ -430,6 +445,8 @@ EXPORT gs_texture_t *gs_texrender_get_texture(const gs_texrender_t *texrender);
|
|||
#define GS_GL_DUMMYTEX (1<<3) /**<< texture with no allocated texture data */
|
||||
#define GS_DUP_BUFFER (1<<4) /**<< do not pass buffer ownership when
|
||||
* creating a vertex/index buffer */
|
||||
#define GS_SHARED_TEX (1<<5)
|
||||
#define GS_SHARED_KM_TEX (1<<6)
|
||||
|
||||
/* ---------------- */
|
||||
/* global functions */
|
||||
|
|
@ -742,6 +759,36 @@ EXPORT size_t gs_indexbuffer_get_num_indices(
|
|||
EXPORT enum gs_index_type gs_indexbuffer_get_type(
|
||||
const gs_indexbuffer_t *indexbuffer);
|
||||
|
||||
EXPORT bool gs_nv12_available(void);
|
||||
|
||||
#define GS_USE_DEBUG_MARKERS 0
|
||||
#if GS_USE_DEBUG_MARKERS
|
||||
static const float GS_DEBUG_COLOR_DEFAULT[] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||
static const float GS_DEBUG_COLOR_RENDER_VIDEO[] = { 0.0f, 0.5f, 0.0f, 1.0f };
|
||||
static const float GS_DEBUG_COLOR_MAIN_TEXTURE[] = { 0.0f, 0.25f, 0.0f, 1.0f };
|
||||
static const float GS_DEBUG_COLOR_DISPLAY[] = { 0.0f, 0.5f, 0.5f, 1.0f };
|
||||
static const float GS_DEBUG_COLOR_SOURCE[] = { 0.0f, 0.5f, 5.0f, 1.0f };
|
||||
static const float GS_DEBUG_COLOR_ITEM[] = { 0.5f, 0.0f, 0.0f, 1.0f };
|
||||
static const float GS_DEBUG_COLOR_ITEM_TEXTURE[] = { 0.25f, 0.0f, 0.0f, 1.0f };
|
||||
static const float GS_DEBUG_COLOR_CONVERT_FORMAT[] = { 0.5f, 0.5f, 0.0f, 1.0f };
|
||||
#define GS_DEBUG_MARKER_BEGIN(color, markername) \
|
||||
gs_debug_marker_begin(color, markername)
|
||||
#define GS_DEBUG_MARKER_BEGIN_FORMAT(color, format, ...) \
|
||||
gs_debug_marker_begin_format(color, format, \
|
||||
__VA_ARGS__)
|
||||
#define GS_DEBUG_MARKER_END() gs_debug_marker_end()
|
||||
#else
|
||||
#define GS_DEBUG_MARKER_BEGIN(color, markername) ((void)0)
|
||||
#define GS_DEBUG_MARKER_BEGIN_FORMAT(color, format, ...) ((void)0)
|
||||
#define GS_DEBUG_MARKER_END() ((void)0)
|
||||
#endif
|
||||
|
||||
EXPORT void gs_debug_marker_begin(const float color[4],
|
||||
const char *markername);
|
||||
EXPORT void gs_debug_marker_begin_format(const float color[4],
|
||||
const char *format, ...);
|
||||
EXPORT void gs_debug_marker_end(void);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/** platform specific function for creating (GL_TEXTURE_RECTANGLE) textures
|
||||
|
|
@ -780,6 +827,30 @@ EXPORT void gs_texture_release_dc(gs_texture_t *gdi_tex);
|
|||
|
||||
/** creates a windows shared texture from a texture handle */
|
||||
EXPORT gs_texture_t *gs_texture_open_shared(uint32_t handle);
|
||||
|
||||
#define GS_INVALID_HANDLE (uint32_t)-1
|
||||
EXPORT uint32_t gs_texture_get_shared_handle(gs_texture_t *tex);
|
||||
|
||||
#define GS_WAIT_INFINITE (uint32_t)-1
|
||||
|
||||
/**
|
||||
* acquires a lock on a keyed mutex texture.
|
||||
* returns -1 on generic failure, ETIMEDOUT if timed out
|
||||
*/
|
||||
EXPORT int gs_texture_acquire_sync(gs_texture_t *tex, uint64_t key, uint32_t ms);
|
||||
|
||||
/**
|
||||
* releases a lock on a keyed mutex texture to another device.
|
||||
* return 0 on success, -1 on error
|
||||
*/
|
||||
EXPORT int gs_texture_release_sync(gs_texture_t *tex, uint64_t key);
|
||||
|
||||
EXPORT bool gs_texture_create_nv12(gs_texture_t **tex_y, gs_texture_t **tex_uv,
|
||||
uint32_t width, uint32_t height, uint32_t flags);
|
||||
|
||||
EXPORT gs_stagesurf_t *gs_stagesurface_create_nv12(
|
||||
uint32_t width, uint32_t height);
|
||||
|
||||
#endif
|
||||
|
||||
/* inline functions used by modules */
|
||||
|
|
@ -804,6 +875,7 @@ static inline uint32_t gs_get_format_bpp(enum gs_color_format format)
|
|||
case GS_DXT1: return 4;
|
||||
case GS_DXT3: return 8;
|
||||
case GS_DXT5: return 8;
|
||||
case GS_R8G8: return 16;
|
||||
case GS_UNKNOWN: return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,18 @@ static inline int get_full_decoded_gif_size(gs_image_file_t *image)
|
|||
return image->gif.width * image->gif.height * 4 * image->gif.frame_count;
|
||||
}
|
||||
|
||||
static bool init_animated_gif(gs_image_file_t *image, const char *path)
|
||||
static inline void *alloc_mem(gs_image_file_t *image, uint64_t *mem_usage,
|
||||
size_t size)
|
||||
{
|
||||
UNUSED_PARAMETER(image);
|
||||
|
||||
if (mem_usage)
|
||||
*mem_usage += size;
|
||||
return bzalloc(size);
|
||||
}
|
||||
|
||||
static bool init_animated_gif(gs_image_file_t *image, const char *path,
|
||||
uint64_t *mem_usage)
|
||||
{
|
||||
bool is_animated_gif = true;
|
||||
gif_result result;
|
||||
|
|
@ -121,9 +132,9 @@ static bool init_animated_gif(gs_image_file_t *image, const char *path)
|
|||
if (image->is_animated_gif) {
|
||||
gif_decode_frame(&image->gif, 0);
|
||||
|
||||
image->animation_frame_cache = bzalloc(
|
||||
image->animation_frame_cache = alloc_mem(image, mem_usage,
|
||||
image->gif.frame_count * sizeof(uint8_t*));
|
||||
image->animation_frame_data = bzalloc(
|
||||
image->animation_frame_data = alloc_mem(image, mem_usage,
|
||||
get_full_decoded_gif_size(image));
|
||||
|
||||
for (unsigned int i = 0; i < image->gif.frame_count; i++) {
|
||||
|
|
@ -137,6 +148,11 @@ static bool init_animated_gif(gs_image_file_t *image, const char *path)
|
|||
image->cx = (uint32_t)image->gif.width;
|
||||
image->cy = (uint32_t)image->gif.height;
|
||||
image->format = GS_RGBA;
|
||||
|
||||
if (mem_usage) {
|
||||
*mem_usage += image->cx * image->cy * 4;
|
||||
*mem_usage += size;
|
||||
}
|
||||
} else {
|
||||
gif_finalise(&image->gif);
|
||||
bfree(image->gif_data);
|
||||
|
|
@ -157,7 +173,8 @@ not_animated:
|
|||
return is_animated_gif;
|
||||
}
|
||||
|
||||
void gs_image_file_init(gs_image_file_t *image, const char *file)
|
||||
static void gs_image_file_init_internal(gs_image_file_t *image,
|
||||
const char *file, uint64_t *mem_usage)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
|
|
@ -172,13 +189,18 @@ void gs_image_file_init(gs_image_file_t *image, const char *file)
|
|||
len = strlen(file);
|
||||
|
||||
if (len > 4 && strcmp(file + len - 4, ".gif") == 0) {
|
||||
if (init_animated_gif(image, file))
|
||||
if (init_animated_gif(image, file, mem_usage))
|
||||
return;
|
||||
}
|
||||
|
||||
image->texture_data = gs_create_texture_file_data(file,
|
||||
&image->format, &image->cx, &image->cy);
|
||||
|
||||
if (mem_usage) {
|
||||
*mem_usage += image->cx * image->cy *
|
||||
gs_get_format_bpp(image->format) / 8;
|
||||
}
|
||||
|
||||
image->loaded = !!image->texture_data;
|
||||
if (!image->loaded) {
|
||||
blog(LOG_WARNING, "Failed to load file '%s'", file);
|
||||
|
|
@ -186,6 +208,11 @@ void gs_image_file_init(gs_image_file_t *image, const char *file)
|
|||
}
|
||||
}
|
||||
|
||||
void gs_image_file_init(gs_image_file_t *image, const char *file)
|
||||
{
|
||||
gs_image_file_init_internal(image, file, NULL);
|
||||
}
|
||||
|
||||
void gs_image_file_free(gs_image_file_t *image)
|
||||
{
|
||||
if (!image)
|
||||
|
|
@ -206,6 +233,11 @@ void gs_image_file_free(gs_image_file_t *image)
|
|||
memset(image, 0, sizeof(*image));
|
||||
}
|
||||
|
||||
void gs_image_file2_init(gs_image_file2_t *if2, const char *file)
|
||||
{
|
||||
gs_image_file_init_internal(&if2->image, file, &if2->mem_usage);
|
||||
}
|
||||
|
||||
void gs_image_file_init_texture(gs_image_file_t *image)
|
||||
{
|
||||
if (!image->loaded)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
#include "graphics.h"
|
||||
#include "libnsgif/libnsgif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct gs_image_file {
|
||||
gs_texture_t *texture;
|
||||
enum gs_color_format format;
|
||||
|
|
@ -42,7 +46,13 @@ struct gs_image_file {
|
|||
gif_bitmap_callback_vt bitmap_callbacks;
|
||||
};
|
||||
|
||||
struct gs_image_file2 {
|
||||
struct gs_image_file image;
|
||||
uint64_t mem_usage;
|
||||
};
|
||||
|
||||
typedef struct gs_image_file gs_image_file_t;
|
||||
typedef struct gs_image_file2 gs_image_file2_t;
|
||||
|
||||
EXPORT void gs_image_file_init(gs_image_file_t *image, const char *file);
|
||||
EXPORT void gs_image_file_free(gs_image_file_t *image);
|
||||
|
|
@ -51,3 +61,31 @@ EXPORT void gs_image_file_init_texture(gs_image_file_t *image);
|
|||
EXPORT bool gs_image_file_tick(gs_image_file_t *image,
|
||||
uint64_t elapsed_time_ns);
|
||||
EXPORT void gs_image_file_update_texture(gs_image_file_t *image);
|
||||
|
||||
EXPORT void gs_image_file2_init(gs_image_file2_t *if2, const char *file);
|
||||
|
||||
static void gs_image_file2_free(gs_image_file2_t *if2)
|
||||
{
|
||||
gs_image_file_free(&if2->image);
|
||||
if2->mem_usage = 0;
|
||||
}
|
||||
|
||||
static inline void gs_image_file2_init_texture(gs_image_file2_t *if2)
|
||||
{
|
||||
gs_image_file_init_texture(&if2->image);
|
||||
}
|
||||
|
||||
static inline bool gs_image_file2_tick(gs_image_file2_t *if2,
|
||||
uint64_t elapsed_time_ns)
|
||||
{
|
||||
return gs_image_file_tick(&if2->image, elapsed_time_ns);
|
||||
}
|
||||
|
||||
static inline void gs_image_file2_update_texture(gs_image_file2_t *if2)
|
||||
{
|
||||
gs_image_file_update_texture(&if2->image);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ void shader_sampler_convert(struct shader_sampler *ss,
|
|||
size_t i;
|
||||
memset(info, 0, sizeof(struct gs_sampler_info));
|
||||
|
||||
info->max_anisotropy = 1;
|
||||
|
||||
for (i = 0; i < ss->states.num; i++) {
|
||||
const char *state = ss->states.array[i];
|
||||
const char *value = ss->values.array[i];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue