Eevee-Next: World Reflective Light #108149
|
@ -10,9 +10,9 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
ccl_device float spot_light_attenuation(const ccl_global KernelSpotLight *spot, float3 ray)
|
||||
{
|
||||
const float3 scaled_ray = safe_normalize(
|
||||
make_float3(dot(ray, spot->axis_u), dot(ray, spot->axis_v), dot(ray, spot->dir)) /
|
||||
spot->len);
|
||||
const float3 scaled_ray = safe_normalize(make_float3(dot(ray, spot->scaled_axis_u),
|
||||
dot(ray, spot->scaled_axis_v),
|
||||
dot(ray, spot->dir * spot->inv_len_z)));
|
||||
|
||||
return smoothstepf((scaled_ray.z - spot->cos_half_spot_angle) * spot->spot_smooth);
|
||||
}
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
\
|
||||
for (int i = 0; i <= ceil(params.detail); ++i) { \
|
||||
VoronoiOutput octave; \
|
||||
if (params.feature == "f1") { \
|
||||
octave = voronoi_f1(params, coord * scale); \
|
||||
if (params.feature == "f2") { \
|
||||
octave = voronoi_f2(params, coord * scale); \
|
||||
} \
|
||||
else if (params.feature == "smooth_f1") { \
|
||||
else if (params.feature == "smooth_f1" && params.smoothness != 0.0) { \
|
||||
octave = voronoi_smooth_f1(params, coord * scale); \
|
||||
} \
|
||||
else { \
|
||||
octave = voronoi_f2(params, coord * scale); \
|
||||
octave = voronoi_f1(params, coord * scale); \
|
||||
} \
|
||||
\
|
||||
if (zero_input) { \
|
||||
|
|
|
@ -878,11 +878,12 @@ ccl_device VoronoiOutput fractal_voronoi_x_fx(ccl_private const VoronoiParams &p
|
|||
params.lacunarity == 0.0f;
|
||||
|
||||
for (int i = 0; i <= ceilf(params.detail); ++i) {
|
||||
VoronoiOutput octave = (params.feature == NODE_VORONOI_F1) ?
|
||||
voronoi_f1(params, coord * scale) :
|
||||
(params.feature == NODE_VORONOI_SMOOTH_F1) ?
|
||||
VoronoiOutput octave = (params.feature == NODE_VORONOI_F2) ?
|
||||
voronoi_f2(params, coord * scale) :
|
||||
(params.feature == NODE_VORONOI_SMOOTH_F1 &&
|
||||
params.smoothness != 0.0f) ?
|
||||
voronoi_smooth_f1(params, coord * scale) :
|
||||
voronoi_f2(params, coord * scale);
|
||||
voronoi_f1(params, coord * scale);
|
||||
|
||||
if (zero_input) {
|
||||
max_amplitude = 1.0f;
|
||||
|
|
|
@ -1350,14 +1350,15 @@ typedef struct KernelCurveSegment {
|
|||
static_assert_align(KernelCurveSegment, 8);
|
||||
|
||||
typedef struct KernelSpotLight {
|
||||
packed_float3 axis_u;
|
||||
packed_float3 scaled_axis_u;
|
||||
float radius;
|
||||
packed_float3 axis_v;
|
||||
packed_float3 scaled_axis_v;
|
||||
float invarea;
|
||||
packed_float3 dir;
|
||||
float cos_half_spot_angle;
|
||||
packed_float3 len;
|
||||
float inv_len_z;
|
||||
float spot_smooth;
|
||||
float pad[2];
|
||||
} KernelSpotLight;
|
||||
|
||||
/* PointLight is SpotLight with only radius and invarea being used. */
|
||||
|
|
|
@ -1309,13 +1309,12 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
else if (light->light_type == LIGHT_SPOT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
||||
float3 len;
|
||||
float3 axis_u = normalize_len(light->axisu, &len.x);
|
||||
float3 axis_v = normalize_len(light->axisv, &len.y);
|
||||
float3 dir = normalize_len(light->dir, &len.z);
|
||||
if (len.z == 0.0f) {
|
||||
dir = zero_float3();
|
||||
}
|
||||
/* Scale axes to accommodate non-uniform scaling. */
|
||||
float3 scaled_axis_u = light->axisu / len_squared(light->axisu);
|
||||
float3 scaled_axis_v = light->axisv / len_squared(light->axisv);
|
||||
float len_z;
|
||||
/* Keep direction normalized. */
|
||||
float3 dir = safe_normalize_len(light->dir, &len_z);
|
||||
|
||||
float radius = light->size;
|
||||
float invarea = (light->normalize && radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) :
|
||||
|
@ -1327,13 +1326,13 @@ void LightManager::device_update_lights(Device *device, DeviceScene *dscene, Sce
|
|||
shader_id |= SHADER_USE_MIS;
|
||||
|
||||
klights[light_index].co = co;
|
||||
klights[light_index].spot.axis_u = axis_u;
|
||||
klights[light_index].spot.scaled_axis_u = scaled_axis_u;
|
||||
klights[light_index].spot.radius = radius;
|
||||
klights[light_index].spot.axis_v = axis_v;
|
||||
klights[light_index].spot.scaled_axis_v = scaled_axis_v;
|
||||
klights[light_index].spot.invarea = invarea;
|
||||
klights[light_index].spot.dir = dir;
|
||||
klights[light_index].spot.cos_half_spot_angle = cos_half_spot_angle;
|
||||
klights[light_index].spot.len = len;
|
||||
klights[light_index].spot.inv_len_z = 1.0f / len_z;
|
||||
klights[light_index].spot.spot_smooth = spot_smooth;
|
||||
}
|
||||
|
||||
|
|
|
@ -1157,7 +1157,6 @@ classes = (
|
|||
NODE_PT_node_color_presets,
|
||||
NODE_PT_active_node_generic,
|
||||
NODE_PT_active_node_color,
|
||||
NODE_PT_active_node_properties,
|
||||
NODE_PT_texture_mapping,
|
||||
NODE_PT_active_tool,
|
||||
NODE_PT_backdrop,
|
||||
|
@ -1171,6 +1170,7 @@ classes = (
|
|||
NODE_PT_panels,
|
||||
NODE_UL_simulation_zone_items,
|
||||
NODE_PT_simulation_zone_items,
|
||||
NODE_PT_active_node_properties,
|
||||
|
||||
node_panel(EEVEE_MATERIAL_PT_settings),
|
||||
node_panel(MATERIAL_PT_viewport),
|
||||
|
|
|
@ -68,6 +68,20 @@ typedef struct EditFont {
|
|||
|
||||
} EditFont;
|
||||
|
||||
typedef enum eEditFontMode {
|
||||
FO_EDIT = 0,
|
||||
FO_CURS = 1,
|
||||
FO_CURSUP = 2,
|
||||
FO_CURSDOWN = 3,
|
||||
FO_DUPLI = 4,
|
||||
FO_PAGEUP = 8,
|
||||
FO_PAGEDOWN = 9,
|
||||
FO_SELCHANGE = 10,
|
||||
} eEditFontMode;
|
||||
|
||||
/* BKE_vfont_to_curve will move the cursor in these cases */
|
||||
#define FO_CURS_IS_MOTION(mode) (ELEM(mode, FO_CURSUP, FO_CURSDOWN, FO_PAGEUP, FO_PAGEDOWN))
|
||||
|
||||
bool BKE_vfont_is_builtin(const struct VFont *vfont);
|
||||
void BKE_vfont_builtin_register(const void *mem, int size);
|
||||
|
||||
|
@ -83,20 +97,20 @@ struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath);
|
|||
|
||||
bool BKE_vfont_to_curve_ex(struct Object *ob,
|
||||
struct Curve *cu,
|
||||
int mode,
|
||||
eEditFontMode mode,
|
||||
struct ListBase *r_nubase,
|
||||
const char32_t **r_text,
|
||||
int *r_text_len,
|
||||
bool *r_text_free,
|
||||
struct CharTrans **r_chartransdata);
|
||||
bool BKE_vfont_to_curve_nubase(struct Object *ob, int mode, struct ListBase *r_nubase);
|
||||
bool BKE_vfont_to_curve_nubase(struct Object *ob, eEditFontMode mode, struct ListBase *r_nubase);
|
||||
|
||||
int BKE_vfont_cursor_to_text_index(struct Object *ob, float cursor_location[2]);
|
||||
|
||||
/**
|
||||
* \warning Expects to have access to evaluated data (i.e. passed object should be evaluated one).
|
||||
*/
|
||||
bool BKE_vfont_to_curve(struct Object *ob, int mode);
|
||||
bool BKE_vfont_to_curve(struct Object *ob, eEditFontMode mode);
|
||||
void BKE_vfont_build_char(struct Curve *cu,
|
||||
struct ListBase *nubase,
|
||||
unsigned int character,
|
||||
|
|
|
@ -151,8 +151,8 @@ set(SRC
|
|||
intern/gpencil_legacy.c
|
||||
intern/gpencil_modifier_legacy.c
|
||||
intern/gpencil_update_cache_legacy.c
|
||||
intern/grease_pencil_convert_legacy.cc
|
||||
intern/grease_pencil.cc
|
||||
intern/grease_pencil_convert_legacy.cc
|
||||
intern/icons.cc
|
||||
intern/icons_rasterize.c
|
||||
intern/idprop.c
|
||||
|
@ -833,6 +833,7 @@ if(WITH_GTESTS)
|
|||
intern/cryptomatte_test.cc
|
||||
intern/curves_geometry_test.cc
|
||||
intern/fcurve_test.cc
|
||||
intern/grease_pencil_test.cc
|
||||
intern/idprop_serialize_test.cc
|
||||
intern/image_partial_update_test.cc
|
||||
intern/image_test.cc
|
||||
|
@ -843,7 +844,6 @@ if(WITH_GTESTS)
|
|||
intern/lib_remap_test.cc
|
||||
intern/nla_test.cc
|
||||
intern/tracking_test.cc
|
||||
intern/grease_pencil_test.cc
|
||||
)
|
||||
set(TEST_INC
|
||||
../editors/include
|
||||
|
|
|
@ -1165,7 +1165,7 @@ static ImBuf *add_ibuf_for_tile(Image *ima, ImageTile *tile)
|
|||
|
||||
if (ibuf != nullptr) {
|
||||
rect = ibuf->byte_buffer.data;
|
||||
IMB_colormanagement_assign_rect_colorspace(ibuf, ima->colorspace_settings.name);
|
||||
IMB_colormanagement_assign_byte_colorspace(ibuf, ima->colorspace_settings.name);
|
||||
}
|
||||
|
||||
copy_v4_v4(fill_color, tile->gen_color);
|
||||
|
@ -1264,8 +1264,8 @@ static void image_colorspace_from_imbuf(Image *image, const ImBuf *ibuf)
|
|||
const char *colorspace_name = nullptr;
|
||||
|
||||
if (ibuf->float_buffer.data) {
|
||||
if (ibuf->float_colorspace) {
|
||||
colorspace_name = IMB_colormanagement_colorspace_get_name(ibuf->float_colorspace);
|
||||
if (ibuf->float_buffer.colorspace) {
|
||||
colorspace_name = IMB_colormanagement_colorspace_get_name(ibuf->float_buffer.colorspace);
|
||||
}
|
||||
else {
|
||||
colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_FLOAT);
|
||||
|
@ -1273,8 +1273,8 @@ static void image_colorspace_from_imbuf(Image *image, const ImBuf *ibuf)
|
|||
}
|
||||
|
||||
if (ibuf->byte_buffer.data && !colorspace_name) {
|
||||
if (ibuf->rect_colorspace) {
|
||||
colorspace_name = IMB_colormanagement_colorspace_get_name(ibuf->rect_colorspace);
|
||||
if (ibuf->byte_buffer.colorspace) {
|
||||
colorspace_name = IMB_colormanagement_colorspace_get_name(ibuf->byte_buffer.colorspace);
|
||||
}
|
||||
else {
|
||||
colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
|
||||
|
@ -3635,12 +3635,12 @@ void BKE_image_set_filepath_from_tile_number(char *filepath,
|
|||
}
|
||||
|
||||
if (tile_format == UDIM_TILE_FORMAT_UDIM) {
|
||||
BLI_sprintf(filepath, pattern, tile_number);
|
||||
BLI_snprintf(filepath, FILE_MAX, pattern, tile_number);
|
||||
}
|
||||
else if (tile_format == UDIM_TILE_FORMAT_UVTILE) {
|
||||
int u = ((tile_number - 1001) % 10);
|
||||
int v = ((tile_number - 1001) / 10);
|
||||
BLI_sprintf(filepath, pattern, u + 1, v + 1);
|
||||
BLI_snprintf(filepath, FILE_MAX, pattern, u + 1, v + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4442,7 +4442,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
|
|||
*/
|
||||
if (ibuf->byte_buffer.data != byte_buffer->data) {
|
||||
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
|
||||
IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace);
|
||||
IMB_colormanagement_assign_byte_colorspace(ibuf, colorspace);
|
||||
}
|
||||
|
||||
/* invalidate color managed buffers if render result changed */
|
||||
|
|
|
@ -769,11 +769,11 @@ static void gpu_texture_update_from_ibuf(
|
|||
}
|
||||
else {
|
||||
/* Byte image is in original colorspace from the file, and may need conversion. */
|
||||
if (IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
|
||||
if (IMB_colormanagement_space_is_data(ibuf->byte_buffer.colorspace)) {
|
||||
/* Non-color data, just store buffer as is. */
|
||||
}
|
||||
else if (IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace) ||
|
||||
IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace))
|
||||
else if (IMB_colormanagement_space_is_srgb(ibuf->byte_buffer.colorspace) ||
|
||||
IMB_colormanagement_space_is_scene_linear(ibuf->byte_buffer.colorspace))
|
||||
{
|
||||
/* sRGB or scene linear, store as byte texture that the GPU can decode directly. */
|
||||
rect = (uchar *)MEM_mallocN(sizeof(uchar[4]) * w * h, __func__);
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
|
||||
#include "NOD_common.h"
|
||||
#include "NOD_composite.h"
|
||||
#include "NOD_geometry.h"
|
||||
#include "NOD_geometry.hh"
|
||||
#include "NOD_geometry_nodes_lazy_function.hh"
|
||||
#include "NOD_node_declaration.hh"
|
||||
#include "NOD_register.hh"
|
||||
|
|
|
@ -200,8 +200,9 @@ static void find_logical_origins_for_socket_recursive(
|
|||
sockets_in_current_chain.pop_last();
|
||||
}
|
||||
|
||||
static void update_logical_origins(const bNodeTree &ntree)
|
||||
static void update_logically_linked_sockets(const bNodeTree &ntree)
|
||||
{
|
||||
/* Compute logically linked sockets to inputs. */
|
||||
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
|
||||
Span<bNode *> nodes = tree_runtime.nodes_by_id;
|
||||
threading::parallel_for(nodes.index_range(), 128, [&](const IndexRange range) {
|
||||
|
@ -220,6 +221,26 @@ static void update_logical_origins(const bNodeTree &ntree)
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Clear logically linked sockets to outputs. */
|
||||
threading::parallel_for(nodes.index_range(), 128, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
bNode &node = *nodes[i];
|
||||
for (bNodeSocket *socket : node.runtime->outputs) {
|
||||
socket->runtime->logically_linked_sockets.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Compute logically linked sockets to outputs using the previously computed logically linked
|
||||
* sockets to inputs. */
|
||||
for (const bNode *node : nodes) {
|
||||
for (bNodeSocket *input_socket : node->runtime->inputs) {
|
||||
for (bNodeSocket *output_socket : input_socket->runtime->logically_linked_sockets) {
|
||||
output_socket->runtime->logically_linked_sockets.append(input_socket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_nodes_by_type(const bNodeTree &ntree)
|
||||
|
@ -499,7 +520,7 @@ static void ensure_topology_cache(const bNodeTree &ntree)
|
|||
update_nodes_by_type(ntree);
|
||||
threading::parallel_invoke(
|
||||
tree_runtime.nodes_by_id.size() > 32,
|
||||
[&]() { update_logical_origins(ntree); },
|
||||
[&]() { update_logically_linked_sockets(ntree); },
|
||||
[&]() { update_sockets_by_identifier(ntree); },
|
||||
[&]() {
|
||||
update_toposort(ntree,
|
||||
|
|
|
@ -3133,19 +3133,23 @@ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_laye
|
|||
BKE_ptcache_bake(&baker);
|
||||
}
|
||||
|
||||
static void ptcache_dt_to_str(char *str, double dtime)
|
||||
static void ptcache_dt_to_str(char *str, size_t str_maxncpy, double dtime)
|
||||
{
|
||||
if (dtime > 60.0) {
|
||||
if (dtime > 3600.0) {
|
||||
BLI_sprintf(
|
||||
str, "%ih %im %is", (int)(dtime / 3600), (int)(dtime / 60) % 60, ((int)dtime) % 60);
|
||||
BLI_snprintf(str,
|
||||
str_maxncpy,
|
||||
"%ih %im %is",
|
||||
(int)(dtime / 3600),
|
||||
(int)(dtime / 60) % 60,
|
||||
((int)dtime) % 60);
|
||||
}
|
||||
else {
|
||||
BLI_sprintf(str, "%im %is", (int)(dtime / 60) % 60, ((int)dtime) % 60);
|
||||
BLI_snprintf(str, str_maxncpy, "%im %is", (int)(dtime / 60) % 60, ((int)dtime) % 60);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_sprintf(str, "%is", ((int)dtime) % 60);
|
||||
BLI_snprintf(str, str_maxncpy, "%is", ((int)dtime) % 60);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3300,9 +3304,9 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
|
|||
if (use_timer || fetd > 60.0) {
|
||||
use_timer = true;
|
||||
|
||||
ptcache_dt_to_str(cur, ctime - ptime);
|
||||
ptcache_dt_to_str(run, ctime - stime);
|
||||
ptcache_dt_to_str(etd, fetd);
|
||||
ptcache_dt_to_str(cur, sizeof(cur), ctime - ptime);
|
||||
ptcache_dt_to_str(run, sizeof(run), ctime - stime);
|
||||
ptcache_dt_to_str(etd, sizeof(etd), fetd);
|
||||
|
||||
printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r",
|
||||
run,
|
||||
|
@ -3325,7 +3329,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
|
|||
|
||||
if (use_timer) {
|
||||
/* start with newline because of \r above */
|
||||
ptcache_dt_to_str(run, PIL_check_seconds_timer() - stime);
|
||||
ptcache_dt_to_str(run, sizeof(run), PIL_check_seconds_timer() - stime);
|
||||
printf("\nBake %s %s (%i frames simulated).\n",
|
||||
(cancel ? "canceled after" : "finished in"),
|
||||
run,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include "BKE_simulation.h"
|
||||
#include "BKE_simulation_state.hh"
|
||||
|
||||
#include "NOD_geometry.h"
|
||||
#include "NOD_geometry.hh"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLT_translation.h"
|
||||
|
|
|
@ -1730,8 +1730,11 @@ static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb)
|
|||
tmp = MEM_mallocN(linea->len + lineb->len + 1, "textline_string");
|
||||
|
||||
s = tmp;
|
||||
s += BLI_strcpy_rlen(s, linea->line);
|
||||
s += BLI_strcpy_rlen(s, lineb->line);
|
||||
memcpy(s, linea->line, linea->len);
|
||||
s += linea->len;
|
||||
memcpy(s, lineb->line, lineb->len);
|
||||
s += lineb->len;
|
||||
*s = '\0';
|
||||
(void)s;
|
||||
|
||||
make_new_line(linea, tmp);
|
||||
|
|
|
@ -2872,8 +2872,8 @@ ImBuf *BKE_tracking_get_plane_imbuf(const ImBuf *frame_ibuf,
|
|||
&warped_position_y);
|
||||
}
|
||||
|
||||
plane_ibuf->rect_colorspace = frame_ibuf->rect_colorspace;
|
||||
plane_ibuf->float_colorspace = frame_ibuf->float_colorspace;
|
||||
plane_ibuf->byte_buffer.colorspace = frame_ibuf->byte_buffer.colorspace;
|
||||
plane_ibuf->float_buffer.colorspace = frame_ibuf->float_buffer.colorspace;
|
||||
|
||||
return plane_ibuf;
|
||||
}
|
||||
|
|
|
@ -792,7 +792,7 @@ static float vfont_descent(const VFontData *vfd)
|
|||
|
||||
static bool vfont_to_curve(Object *ob,
|
||||
Curve *cu,
|
||||
int mode,
|
||||
const eEditFontMode mode,
|
||||
VFontToCurveIter *iter_data,
|
||||
VFontCursor_Params *cursor_params,
|
||||
ListBase *r_nubase,
|
||||
|
@ -1501,6 +1501,12 @@ static bool vfont_to_curve(Object *ob,
|
|||
case FO_PAGEDOWN:
|
||||
lnr = ct->linenr + 10;
|
||||
break;
|
||||
/* Ignored. */
|
||||
case FO_EDIT:
|
||||
case FO_CURS:
|
||||
case FO_DUPLI:
|
||||
case FO_SELCHANGE:
|
||||
break;
|
||||
}
|
||||
cnr = ct->charnr;
|
||||
/* Seek for char with `lnr` & `cnr`. */
|
||||
|
@ -1826,7 +1832,7 @@ finally:
|
|||
|
||||
bool BKE_vfont_to_curve_ex(Object *ob,
|
||||
Curve *cu,
|
||||
int mode,
|
||||
const eEditFontMode mode,
|
||||
ListBase *r_nubase,
|
||||
const char32_t **r_text,
|
||||
int *r_text_len,
|
||||
|
@ -1880,14 +1886,14 @@ int BKE_vfont_cursor_to_text_index(Object *ob, float cursor_location[2])
|
|||
#undef FONT_TO_CURVE_SCALE_ITERATIONS
|
||||
#undef FONT_TO_CURVE_SCALE_THRESHOLD
|
||||
|
||||
bool BKE_vfont_to_curve_nubase(Object *ob, int mode, ListBase *r_nubase)
|
||||
bool BKE_vfont_to_curve_nubase(Object *ob, const eEditFontMode mode, ListBase *r_nubase)
|
||||
{
|
||||
BLI_assert(ob->type == OB_FONT);
|
||||
|
||||
return BKE_vfont_to_curve_ex(ob, ob->data, mode, r_nubase, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
bool BKE_vfont_to_curve(Object *ob, int mode)
|
||||
bool BKE_vfont_to_curve(Object *ob, const eEditFontMode mode)
|
||||
{
|
||||
Curve *cu = ob->data;
|
||||
|
||||
|
|
|
@ -108,9 +108,6 @@ size_t BLI_strncpy_rlen(char *__restrict dst,
|
|||
const char *__restrict src,
|
||||
size_t dst_maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
|
||||
|
||||
size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL(1, 2);
|
||||
|
||||
char *BLI_strncat(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy)
|
||||
ATTR_NONNULL(1, 2);
|
||||
|
||||
|
@ -246,14 +243,6 @@ size_t BLI_vsnprintf_rlen(char *__restrict dst,
|
|||
char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2);
|
||||
|
||||
/**
|
||||
* A wrapper around `::sprintf()` which does not generate security warnings.
|
||||
*
|
||||
* \note Use #BLI_snprintf for cases when the string size is known.
|
||||
*/
|
||||
int BLI_sprintf(char *__restrict str, const char *__restrict format, ...) ATTR_NONNULL(1, 2)
|
||||
ATTR_PRINTF_FORMAT(2, 3);
|
||||
|
||||
/**
|
||||
* This roughly matches C and Python's string escaping with double quotes - `"`.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Unicode characters as UTF-8 strings. Last portion should include the official assigned name.
|
||||
* Please do not add defines here that are not actually in use. */
|
||||
|
||||
#define BLI_STR_UTF8_MULTIPLICATION_SIGN u8"\u00D7" /* × */
|
||||
#define BLI_STR_UTF8_EM_DASH u8"\u2014" /* — */
|
||||
#define BLI_STR_UTF8_BULLET u8"\u2022" /* • */
|
||||
#define BLI_STR_UTF8_HORIZONTAL_ELLIPSIS u8"\u2026" /* … */
|
||||
#define BLI_STR_UTF8_LEFTWARDS_ARROW u8"\u2190" /* ← */
|
||||
#define BLI_STR_UTF8_UPWARDS_ARROW u8"\u2191" /* ↑ */
|
||||
#define BLI_STR_UTF8_RIGHTWARDS_ARROW u8"\u2192" /* → */
|
||||
#define BLI_STR_UTF8_DOWNWARDS_ARROW u8"\u2193" /* ↓ */
|
||||
#define BLI_STR_UTF8_UPWARDS_WHITE_ARROW u8"\u21E7" /* ⇧ */
|
||||
#define BLI_STR_UTF8_UP_ARROWHEAD u8"\u2303" /* ⌃ */
|
||||
#define BLI_STR_UTF8_PLACE_OF_INTEREST_SIGN u8"\u2318" /* ⌘ */
|
||||
#define BLI_STR_UTF8_OPTION_KEY u8"\u2325" /* ⌥ */
|
||||
#define BLI_STR_UTF8_ERASE_TO_THE_LEFT u8"\u232B" /* ⌫ */
|
||||
#define BLI_STR_UTF8_BROKEN_CIRCLE_WITH_NORTHWEST_ARROW u8"\u238B" /* ⎋ */
|
||||
#define BLI_STR_UTF8_RETURN_SYMBOL u8"\u23CE" /* ⏎ */
|
||||
#define BLI_STR_UTF8_BLACK_RIGHT_POINTING_DOUBLE_TRIANGLE_WITH_VERTICAL_BAR u8"\u23ED" /* ⏭ */
|
||||
#define BLI_STR_UTF8_BLACK_LEFT_POINTING_DOUBLE_TRIANGLE_WITH_VERTICAL_BAR u8"\u23EE" /* ⏮ */
|
||||
#define BLI_STR_UTF8_BLACK_RIGHT_POINTING_TRIANGLE_WITH_DOUBLE_VERTICAL_BAR u8"\u23EF" /* ⏯ */
|
||||
#define BLI_STR_UTF8_BLACK_SQUARE_FOR_STOP u8"\u23F9" /* ⏹ */
|
||||
#define BLI_STR_UTF8_OPEN_BOX u8"\u2423" /* ␣ */
|
||||
#define BLI_STR_UTF8_BLACK_RIGHT_POINTING_SMALL_TRIANGLE u8"\u25B8" /* ▸ */
|
||||
#define BLI_STR_UTF8_HORIZONTAL_TAB_KEY u8"\u2B7E" /* ⭾ */
|
||||
#define BLI_STR_UTF8_BLACK_DIAMOND_MINUS_WHITE_X u8"\u2756" /* ❖ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -118,6 +118,9 @@ bool BLI_uniquename(struct ListBase *list,
|
|||
|
||||
/* Expand array functions. */
|
||||
|
||||
size_t BLI_string_len_array(const char *strings[], uint strings_num) ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_NONNULL();
|
||||
|
||||
/* Intentionally no comma after `_BLI_STRING_ARGS_0` to allow it to be empty. */
|
||||
#define _BLI_STRING_ARGS_1 _BLI_STRING_ARGS_0 const char *a
|
||||
#define _BLI_STRING_ARGS_2 _BLI_STRING_ARGS_1, const char *b
|
||||
|
|
|
@ -39,7 +39,7 @@ bool BLI_uuid_equal(bUUID uuid1, bUUID uuid2);
|
|||
/**
|
||||
* Format UUID as string.
|
||||
* The buffer must be at least 37 bytes (36 bytes for the UUID + terminating 0).
|
||||
* Use `UUID_STRING_LEN` from DNA_uuid_types.h if you want to use a constant for this.
|
||||
* Use `UUID_STRING_SIZE` from DNA_uuid_types.h if you want to use a constant for this.
|
||||
*/
|
||||
void BLI_uuid_format(char *buffer, bUUID uuid) ATTR_NONNULL();
|
||||
|
||||
|
|
|
@ -354,6 +354,7 @@ set(SRC
|
|||
BLI_string_ref.hh
|
||||
BLI_string_search.h
|
||||
BLI_string_utf8.h
|
||||
BLI_string_utf8_symbols.h
|
||||
BLI_string_utils.h
|
||||
BLI_sub_frame.hh
|
||||
BLI_sys_types.h
|
||||
|
|
|
@ -2262,11 +2262,12 @@ VoronoiOutput fractal_voronoi_x_fx(const VoronoiParams ¶ms,
|
|||
params.lacunarity == 0.0f;
|
||||
|
||||
for (int i = 0; i <= ceilf(params.detail); ++i) {
|
||||
VoronoiOutput octave = (params.feature == NOISE_SHD_VORONOI_F1) ?
|
||||
voronoi_f1(params, coord * scale) :
|
||||
(params.feature == NOISE_SHD_VORONOI_SMOOTH_F1) ?
|
||||
VoronoiOutput octave = (params.feature == NOISE_SHD_VORONOI_F2) ?
|
||||
voronoi_f2(params, coord * scale) :
|
||||
(params.feature == NOISE_SHD_VORONOI_SMOOTH_F1 &&
|
||||
params.smoothness != 0.0f) ?
|
||||
voronoi_smooth_f1(params, coord * scale, calc_color) :
|
||||
voronoi_f2(params, coord * scale);
|
||||
voronoi_f1(params, coord * scale);
|
||||
|
||||
if (zero_input) {
|
||||
max_amplitude = 1.0f;
|
||||
|
|
|
@ -666,7 +666,6 @@ void BLI_path_rel(char path[FILE_MAX], const char *basepath)
|
|||
|
||||
const char *lslash;
|
||||
char temp[FILE_MAX];
|
||||
char res[FILE_MAX];
|
||||
|
||||
/* If path is already relative, bail out. */
|
||||
if (BLI_path_is_rel(path)) {
|
||||
|
@ -739,7 +738,6 @@ void BLI_path_rel(char path[FILE_MAX], const char *basepath)
|
|||
* This is replaced by the two slashes at the beginning. */
|
||||
const char *p = temp;
|
||||
const char *q = path;
|
||||
char *r = res;
|
||||
|
||||
#ifdef WIN32
|
||||
while (tolower(*p) == tolower(*q))
|
||||
|
@ -771,7 +769,8 @@ void BLI_path_rel(char path[FILE_MAX], const char *basepath)
|
|||
}
|
||||
}
|
||||
|
||||
r += BLI_strcpy_rlen(r, "//");
|
||||
char res[FILE_MAX] = "//";
|
||||
char *r = res + 2;
|
||||
|
||||
/* `p` now points to the slash that is at the beginning of the part
|
||||
* where the path is different from the relative path.
|
||||
|
@ -782,13 +781,13 @@ void BLI_path_rel(char path[FILE_MAX], const char *basepath)
|
|||
}
|
||||
while (p && p < lslash) {
|
||||
if (*p == '/') {
|
||||
r += BLI_strcpy_rlen(r, "../");
|
||||
r += BLI_strncpy_rlen(r, "../", sizeof(res) - (r - res));
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Don't copy the slash at the beginning. */
|
||||
r += BLI_strncpy_rlen(r, q + 1, FILE_MAX - (r - res));
|
||||
r += BLI_strncpy_rlen(r, q + 1, sizeof(res) - (r - res));
|
||||
|
||||
#ifdef WIN32
|
||||
BLI_str_replace_char(res + 2, '/', '\\');
|
||||
|
|
|
@ -123,13 +123,6 @@ size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const
|
|||
return srclen;
|
||||
}
|
||||
|
||||
size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src)
|
||||
{
|
||||
size_t srclen = strlen(src);
|
||||
memcpy(dst, src, srclen + 1);
|
||||
return srclen;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name String Append
|
||||
* \{ */
|
||||
|
@ -251,17 +244,6 @@ char *BLI_sprintfN(const char *__restrict format, ...)
|
|||
return n;
|
||||
}
|
||||
|
||||
int BLI_sprintf(char *__restrict str, const char *__restrict format, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, format);
|
||||
const int result = vsprintf(str, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -10,10 +10,11 @@
|
|||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_string_search.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utf8_symbols.h"
|
||||
#include "BLI_timeit.hh"
|
||||
|
||||
/* Right arrow, keep in sync with #UI_MENU_ARROW_SEP in `UI_interface.h`. */
|
||||
#define UI_MENU_ARROW_SEP "\xe2\x96\xb8"
|
||||
#define UI_MENU_ARROW_SEP BLI_STR_UTF8_BLACK_RIGHT_POINTING_SMALL_TRIANGLE
|
||||
#define UI_MENU_ARROW_SEP_UNICODE 0x25b8
|
||||
|
||||
namespace blender::string_search {
|
||||
|
|
|
@ -357,6 +357,15 @@ bool BLI_uniquename(ListBase *list,
|
|||
name_maxncpy);
|
||||
}
|
||||
|
||||
size_t BLI_string_len_array(const char *strings[], uint strings_num)
|
||||
{
|
||||
size_t total_len = 0;
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
total_len += strlen(strings[i]);
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/** \name Join Strings
|
||||
*
|
||||
|
@ -379,7 +388,11 @@ size_t BLI_string_join_array(char *result,
|
|||
char *c_end = &result[result_maxncpy - 1];
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
const char *p = strings[i];
|
||||
while (*p && (c < c_end)) {
|
||||
while (*p) {
|
||||
if (UNLIKELY(!(c < c_end))) {
|
||||
i = strings_num; /* Break outer loop. */
|
||||
break;
|
||||
}
|
||||
*c++ = *p++;
|
||||
}
|
||||
}
|
||||
|
@ -396,12 +409,17 @@ size_t BLI_string_join_array_by_sep_char(
|
|||
char *c_end = &result[result_maxncpy - 1];
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
if (i != 0) {
|
||||
if (c < c_end) {
|
||||
*c++ = sep;
|
||||
if (UNLIKELY(!(c < c_end))) {
|
||||
break;
|
||||
}
|
||||
*c++ = sep;
|
||||
}
|
||||
const char *p = strings[i];
|
||||
while (*p && (c < c_end)) {
|
||||
while (*p) {
|
||||
if (UNLIKELY(!(c < c_end))) {
|
||||
i = strings_num; /* Break outer loop. */
|
||||
break;
|
||||
}
|
||||
*c++ = *p++;
|
||||
}
|
||||
}
|
||||
|
@ -411,41 +429,38 @@ size_t BLI_string_join_array_by_sep_char(
|
|||
|
||||
char *BLI_string_join_arrayN(const char *strings[], uint strings_num)
|
||||
{
|
||||
uint total_len = 1;
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
total_len += strlen(strings[i]);
|
||||
}
|
||||
char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
|
||||
const uint result_size = BLI_string_len_array(strings, strings_num) + 1;
|
||||
char *result = MEM_mallocN(sizeof(char) * result_size, __func__);
|
||||
char *c = result;
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
c += BLI_strcpy_rlen(c, strings[i]);
|
||||
const size_t string_len = strlen(strings[i]);
|
||||
memcpy(c, strings[i], string_len);
|
||||
c += string_len;
|
||||
}
|
||||
/* Only needed when `strings_num == 0`. */
|
||||
*c = '\0';
|
||||
BLI_assert(result + result_size == c + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
char *BLI_string_join_array_by_sep_charN(char sep, const char *strings[], uint strings_num)
|
||||
{
|
||||
uint total_len = 0;
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
total_len += strlen(strings[i]) + 1;
|
||||
}
|
||||
if (total_len == 0) {
|
||||
total_len = 1;
|
||||
}
|
||||
|
||||
char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
|
||||
const uint result_size = BLI_string_len_array(strings, strings_num) +
|
||||
(strings_num ? strings_num - 1 : 0) + 1;
|
||||
char *result = MEM_mallocN(sizeof(char) * result_size, __func__);
|
||||
char *c = result;
|
||||
if (strings_num != 0) {
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
c += BLI_strcpy_rlen(c, strings[i]);
|
||||
const size_t string_len = strlen(strings[i]);
|
||||
memcpy(c, strings[i], string_len);
|
||||
c += string_len;
|
||||
*c = sep;
|
||||
c++;
|
||||
}
|
||||
c--;
|
||||
}
|
||||
*c = '\0';
|
||||
BLI_assert(result + result_size == c + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -454,26 +469,30 @@ char *BLI_string_join_array_by_sep_char_with_tableN(char sep,
|
|||
const char *strings[],
|
||||
uint strings_num)
|
||||
{
|
||||
uint total_len = 0;
|
||||
uint result_size = 0;
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
total_len += strlen(strings[i]) + 1;
|
||||
result_size += strlen(strings[i]) + 1;
|
||||
}
|
||||
if (total_len == 0) {
|
||||
total_len = 1;
|
||||
if (result_size == 0) {
|
||||
result_size = 1;
|
||||
}
|
||||
|
||||
char *result = MEM_mallocN(sizeof(char) * total_len, __func__);
|
||||
char *result = MEM_mallocN(sizeof(char) * result_size, __func__);
|
||||
char *c = result;
|
||||
if (strings_num != 0) {
|
||||
for (uint i = 0; i < strings_num; i++) {
|
||||
const size_t string_len = strlen(strings[i]);
|
||||
memcpy(c, strings[i], string_len);
|
||||
table[i] = c; /* <-- only difference to BLI_string_join_array_by_sep_charN. */
|
||||
c += BLI_strcpy_rlen(c, strings[i]);
|
||||
memcpy(c, strings[i], string_len);
|
||||
c += string_len;
|
||||
*c = sep;
|
||||
c++;
|
||||
}
|
||||
c--;
|
||||
}
|
||||
*c = '\0';
|
||||
BLI_assert(result + result_size == c + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,19 +88,25 @@ bool BLI_uuid_equal(const bUUID uuid1, const bUUID uuid2)
|
|||
|
||||
void BLI_uuid_format(char *buffer, const bUUID uuid)
|
||||
{
|
||||
BLI_sprintf(buffer,
|
||||
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
uuid.time_low,
|
||||
uuid.time_mid,
|
||||
uuid.time_hi_and_version,
|
||||
uuid.clock_seq_hi_and_reserved,
|
||||
uuid.clock_seq_low,
|
||||
uuid.node[0],
|
||||
uuid.node[1],
|
||||
uuid.node[2],
|
||||
uuid.node[3],
|
||||
uuid.node[4],
|
||||
uuid.node[5]);
|
||||
const size_t buffer_len_unclamped = BLI_snprintf(
|
||||
buffer,
|
||||
UUID_STRING_SIZE,
|
||||
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
uuid.time_low,
|
||||
uuid.time_mid,
|
||||
uuid.time_hi_and_version,
|
||||
uuid.clock_seq_hi_and_reserved,
|
||||
uuid.clock_seq_low,
|
||||
uuid.node[0],
|
||||
uuid.node[1],
|
||||
uuid.node[2],
|
||||
uuid.node[3],
|
||||
uuid.node[4],
|
||||
uuid.node[5]);
|
||||
|
||||
/* Assert the string length is not clamped. */
|
||||
BLI_assert(buffer_len_unclamped == UUID_STRING_SIZE - 1);
|
||||
UNUSED_VARS_NDEBUG(buffer_len_unclamped);
|
||||
}
|
||||
|
||||
bool BLI_uuid_parse_string(bUUID *uuid, const char *buffer)
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_string_utils.h"
|
||||
|
@ -859,6 +861,104 @@ TEST(string, StringNLen)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name String Join
|
||||
* \{ */
|
||||
|
||||
#define BUFFER_SIZE 128
|
||||
|
||||
static void string_join_array_test_truncate(const char *strings[],
|
||||
int strings_num,
|
||||
char buffer[BUFFER_SIZE])
|
||||
{
|
||||
const int buffer_len = BLI_string_join_array(buffer, BUFFER_SIZE, strings, strings_num);
|
||||
|
||||
{ /* Ensure the allocated version is the same. */
|
||||
char *buffer_alloc = BLI_string_join_arrayN(strings, strings_num);
|
||||
EXPECT_STREQ(buffer_alloc, buffer);
|
||||
MEM_freeN(buffer_alloc);
|
||||
}
|
||||
|
||||
for (int dst_size = buffer_len + 1; dst_size > 0; dst_size--) {
|
||||
char dst_tmp[BUFFER_SIZE];
|
||||
int dst_tmp_len = BLI_string_join_array(dst_tmp, dst_size, strings, strings_num);
|
||||
EXPECT_EQ(dst_tmp_len + 1, dst_size);
|
||||
EXPECT_EQ(strncmp(dst_tmp, buffer, dst_tmp_len), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void string_join_array_with_sep_char_test_truncate(const char *strings[],
|
||||
int strings_num,
|
||||
char buffer[BUFFER_SIZE])
|
||||
{
|
||||
const int buffer_len = BLI_string_join_array_by_sep_char(
|
||||
buffer, BUFFER_SIZE, '|', strings, strings_num);
|
||||
|
||||
{ /* Ensure the allocated version is the same. */
|
||||
char *buffer_alloc = BLI_string_join_array_by_sep_charN('|', strings, strings_num);
|
||||
EXPECT_STREQ(buffer_alloc, buffer);
|
||||
MEM_freeN(buffer_alloc);
|
||||
}
|
||||
|
||||
for (int dst_size = buffer_len + 1; dst_size > 0; dst_size--) {
|
||||
char dst_tmp[BUFFER_SIZE];
|
||||
int dst_tmp_len = BLI_string_join_array_by_sep_char(
|
||||
dst_tmp, dst_size, '|', strings, strings_num);
|
||||
EXPECT_EQ(dst_tmp_len + 1, dst_size);
|
||||
EXPECT_EQ(strncmp(dst_tmp, buffer, dst_tmp_len), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(string, StrJoin_Truncate)
|
||||
{
|
||||
char buffer[BUFFER_SIZE];
|
||||
{ /* Multiple single char words. */
|
||||
const char *strings[] = {"a", "b", "c", "d", "e", "f"};
|
||||
string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "abcdef");
|
||||
string_join_array_with_sep_char_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "a|b|c|d|e|f");
|
||||
}
|
||||
{ /* Multiple char pair words. */
|
||||
const char *strings[] = {"aa", "bb", "cc", "dd", "ee", "ff"};
|
||||
string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "aabbccddeeff");
|
||||
string_join_array_with_sep_char_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "aa|bb|cc|dd|ee|ff");
|
||||
}
|
||||
{ /* Multiple empty words. */
|
||||
const char *strings[] = {"", "", "", "", "", ""};
|
||||
string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "");
|
||||
string_join_array_with_sep_char_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "|||||");
|
||||
}
|
||||
{ /* Single word. */
|
||||
const char *strings[] = {"test"};
|
||||
string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "test");
|
||||
string_join_array_with_sep_char_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "test");
|
||||
}
|
||||
{ /* Empty item. */
|
||||
const char *strings[] = {""};
|
||||
string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "");
|
||||
string_join_array_with_sep_char_test_truncate(strings, ARRAY_SIZE(strings), buffer);
|
||||
EXPECT_STREQ(buffer, "");
|
||||
}
|
||||
{ /* Empty array. */
|
||||
string_join_array_test_truncate(nullptr, 0, buffer);
|
||||
EXPECT_STREQ(buffer, "");
|
||||
string_join_array_with_sep_char_test_truncate(nullptr, 0, buffer);
|
||||
EXPECT_STREQ(buffer, "");
|
||||
}
|
||||
}
|
||||
|
||||
#undef BUFFER_SIZE
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name String Find Split Words
|
||||
* \{ */
|
||||
|
|
|
@ -2133,8 +2133,8 @@ if (!MAIN_VERSION_ATLEAST(bmain, 269, 3)) {
|
|||
}
|
||||
|
||||
/* 'Increment' mode disabled for nodes, use true grid snapping instead */
|
||||
if (scene->toolsettings->snap_node_mode == 0) { /* SCE_SNAP_MODE_INCREMENT */
|
||||
scene->toolsettings->snap_node_mode = 8; /* SCE_SNAP_MODE_GRID */
|
||||
if (scene->toolsettings->snap_node_mode == 0) { /* SCE_SNAP_TO_INCREMENT */
|
||||
scene->toolsettings->snap_node_mode = 8; /* SCE_SNAP_TO_GRID */
|
||||
}
|
||||
|
||||
#ifdef WITH_FFMPEG
|
||||
|
|
|
@ -3818,42 +3818,42 @@ void blo_do_versions_280(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
switch (scene->toolsettings->snap_mode) {
|
||||
case 0:
|
||||
scene->toolsettings->snap_mode = (1 << 4); /* SCE_SNAP_MODE_INCREMENT */
|
||||
scene->toolsettings->snap_mode = (1 << 4); /* SCE_SNAP_TO_INCREMENT */
|
||||
break;
|
||||
case 1:
|
||||
scene->toolsettings->snap_mode = (1 << 0); /* SCE_SNAP_MODE_VERTEX */
|
||||
scene->toolsettings->snap_mode = (1 << 0); /* SCE_SNAP_TO_VERTEX */
|
||||
break;
|
||||
case 2:
|
||||
scene->toolsettings->snap_mode = (1 << 1); /* SCE_SNAP_MODE_EDGE */
|
||||
scene->toolsettings->snap_mode = (1 << 1); /* SCE_SNAP_TO_EDGE */
|
||||
break;
|
||||
case 3:
|
||||
scene->toolsettings->snap_mode = (1 << 2); /* SCE_SNAP_MODE_FACE_RAYCAST */
|
||||
scene->toolsettings->snap_mode = (1 << 2); /* SCE_SNAP_INDIVIDUAL_PROJECT */
|
||||
break;
|
||||
case 4:
|
||||
scene->toolsettings->snap_mode = (1 << 3); /* SCE_SNAP_MODE_VOLUME */
|
||||
scene->toolsettings->snap_mode = (1 << 3); /* SCE_SNAP_TO_VOLUME */
|
||||
break;
|
||||
}
|
||||
switch (scene->toolsettings->snap_node_mode) {
|
||||
case 5:
|
||||
scene->toolsettings->snap_node_mode = (1 << 5); /* SCE_SNAP_MODE_NODE_X */
|
||||
scene->toolsettings->snap_node_mode = (1 << 5); /* SCE_SNAP_TO_NODE_X */
|
||||
break;
|
||||
case 6:
|
||||
scene->toolsettings->snap_node_mode = (1 << 6); /* SCE_SNAP_MODE_NODE_Y */
|
||||
scene->toolsettings->snap_node_mode = (1 << 6); /* SCE_SNAP_TO_NODE_Y */
|
||||
break;
|
||||
case 7:
|
||||
scene->toolsettings->snap_node_mode =
|
||||
(1 << 5) | (1 << 6); /* SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y */
|
||||
(1 << 5) | (1 << 6); /* SCE_SNAP_TO_NODE_X | SCE_SNAP_TO_NODE_Y */
|
||||
break;
|
||||
case 8:
|
||||
scene->toolsettings->snap_node_mode = (1 << 7); /* SCE_SNAP_MODE_GRID */
|
||||
scene->toolsettings->snap_node_mode = (1 << 7); /* SCE_SNAP_TO_GRID */
|
||||
break;
|
||||
}
|
||||
switch (scene->toolsettings->snap_uv_mode) {
|
||||
case 0:
|
||||
scene->toolsettings->snap_uv_mode = (1 << 4); /* SCE_SNAP_MODE_INCREMENT */
|
||||
scene->toolsettings->snap_uv_mode = (1 << 4); /* SCE_SNAP_TO_INCREMENT */
|
||||
break;
|
||||
case 1:
|
||||
scene->toolsettings->snap_uv_mode = (1 << 0); /* SCE_SNAP_MODE_VERTEX */
|
||||
scene->toolsettings->snap_uv_mode = (1 << 0); /* SCE_SNAP_TO_VERTEX */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5749,8 +5749,8 @@ void blo_do_versions_280(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 281, 15)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
if (scene->toolsettings->snap_node_mode == SCE_SNAP_MODE_NODE_X) {
|
||||
scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
|
||||
if (scene->toolsettings->snap_node_mode == SCE_SNAP_TO_NODE_X) {
|
||||
scene->toolsettings->snap_node_mode = SCE_SNAP_TO_GRID;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2523,22 +2523,22 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
tool_settings->snap_node_mode &= ~((1 << 5) | (1 << 6));
|
||||
tool_settings->snap_uv_mode &= ~(1 << 4);
|
||||
if (snap_mode & (1 << 4)) {
|
||||
tool_settings->snap_mode |= (1 << 6); /* SCE_SNAP_MODE_INCREMENT */
|
||||
tool_settings->snap_mode |= (1 << 6); /* SCE_SNAP_TO_INCREMENT */
|
||||
}
|
||||
if (snap_mode & (1 << 5)) {
|
||||
tool_settings->snap_mode |= (1 << 4); /* SCE_SNAP_MODE_EDGE_MIDPOINT */
|
||||
tool_settings->snap_mode |= (1 << 4); /* SCE_SNAP_TO_EDGE_MIDPOINT */
|
||||
}
|
||||
if (snap_mode & (1 << 6)) {
|
||||
tool_settings->snap_mode |= (1 << 5); /* SCE_SNAP_MODE_EDGE_PERPENDICULAR */
|
||||
tool_settings->snap_mode |= (1 << 5); /* SCE_SNAP_TO_EDGE_PERPENDICULAR */
|
||||
}
|
||||
if (snap_node_mode & (1 << 5)) {
|
||||
tool_settings->snap_node_mode |= (1 << 0); /* SCE_SNAP_MODE_NODE_X */
|
||||
tool_settings->snap_node_mode |= (1 << 0); /* SCE_SNAP_TO_NODE_X */
|
||||
}
|
||||
if (snap_node_mode & (1 << 6)) {
|
||||
tool_settings->snap_node_mode |= (1 << 1); /* SCE_SNAP_MODE_NODE_Y */
|
||||
tool_settings->snap_node_mode |= (1 << 1); /* SCE_SNAP_TO_NODE_Y */
|
||||
}
|
||||
if (snap_uv_mode & (1 << 4)) {
|
||||
tool_settings->snap_uv_mode |= (1 << 6); /* SCE_SNAP_MODE_INCREMENT */
|
||||
tool_settings->snap_uv_mode |= (1 << 6); /* SCE_SNAP_TO_INCREMENT */
|
||||
}
|
||||
|
||||
SequencerToolSettings *sequencer_tool_settings = SEQ_tool_settings_ensure(scene);
|
||||
|
@ -2582,7 +2582,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
ToolSettings *tool_settings = scene->toolsettings;
|
||||
if (tool_settings->snap_uv_mode & (1 << 4)) {
|
||||
tool_settings->snap_uv_mode |= (1 << 6); /* SCE_SNAP_MODE_INCREMENT */
|
||||
tool_settings->snap_uv_mode |= (1 << 6); /* SCE_SNAP_TO_INCREMENT */
|
||||
tool_settings->snap_uv_mode &= ~(1 << 4);
|
||||
}
|
||||
}
|
||||
|
@ -4472,7 +4472,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
if (!MAIN_VERSION_ATLEAST(bmain, 306, 10)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
/* Set default values for new members. */
|
||||
scene->toolsettings->snap_mode_tools = SCE_SNAP_MODE_GEOM;
|
||||
scene->toolsettings->snap_mode_tools = SCE_SNAP_TO_GEOM;
|
||||
scene->toolsettings->plane_axis = 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,8 +43,6 @@ void do_versions_after_linking_400(FileData * /*fd*/, Main * /*bmain*/)
|
|||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - #blo_do_versions_400 in this file.
|
||||
* - "versioning_cycles.cc", #blo_do_versions_cycles
|
||||
* - "versioning_cycles.cc", #do_versions_after_linking_cycles
|
||||
* - "versioning_userdef.c", #blo_do_versions_userdef
|
||||
* - "versioning_userdef.c", #do_versions_theme
|
||||
*
|
||||
|
@ -229,13 +227,13 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
if (!MAIN_VERSION_ATLEAST(bmain, 400, 5)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
if (ts->snap_mode_tools != SCE_SNAP_MODE_NONE) {
|
||||
ts->snap_mode_tools = SCE_SNAP_MODE_GEOM;
|
||||
if (ts->snap_mode_tools != SCE_SNAP_TO_NONE) {
|
||||
ts->snap_mode_tools = SCE_SNAP_TO_GEOM;
|
||||
}
|
||||
|
||||
#define SCE_SNAP_PROJECT (1 << 3)
|
||||
if (ts->snap_flag & SCE_SNAP_PROJECT) {
|
||||
ts->snap_mode |= SCE_SNAP_MODE_FACE_RAYCAST;
|
||||
ts->snap_mode |= SCE_SNAP_INDIVIDUAL_PROJECT;
|
||||
}
|
||||
#undef SCE_SNAP_PROJECT
|
||||
}
|
||||
|
@ -263,8 +261,6 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
*
|
||||
* \note Be sure to check when bumping the version:
|
||||
* - #do_versions_after_linking_400 in this file.
|
||||
* - "versioning_cycles.cc", #blo_do_versions_cycles
|
||||
* - "versioning_cycles.cc", #do_versions_after_linking_cycles
|
||||
* - "versioning_userdef.c", #blo_do_versions_userdef
|
||||
* - "versioning_userdef.c", #do_versions_theme
|
||||
*
|
||||
|
|
|
@ -322,8 +322,8 @@ if(WITH_COMPOSITOR_CPU)
|
|||
nodes/COM_FilterNode.h
|
||||
nodes/COM_InpaintNode.cc
|
||||
nodes/COM_InpaintNode.h
|
||||
nodes/COM_KuwaharaNode.h
|
||||
nodes/COM_KuwaharaNode.cc
|
||||
nodes/COM_KuwaharaNode.h
|
||||
nodes/COM_PosterizeNode.cc
|
||||
nodes/COM_PosterizeNode.h
|
||||
|
||||
|
@ -351,10 +351,10 @@ if(WITH_COMPOSITOR_CPU)
|
|||
operations/COM_GaussianXBlurOperation.h
|
||||
operations/COM_GaussianYBlurOperation.cc
|
||||
operations/COM_GaussianYBlurOperation.h
|
||||
operations/COM_KuwaharaClassicOperation.h
|
||||
operations/COM_KuwaharaClassicOperation.cc
|
||||
operations/COM_KuwaharaAnisotropicOperation.h
|
||||
operations/COM_KuwaharaAnisotropicOperation.cc
|
||||
operations/COM_KuwaharaAnisotropicOperation.h
|
||||
operations/COM_KuwaharaClassicOperation.cc
|
||||
operations/COM_KuwaharaClassicOperation.h
|
||||
operations/COM_MovieClipAttributeOperation.cc
|
||||
operations/COM_MovieClipAttributeOperation.h
|
||||
operations/COM_MovieDistortionOperation.cc
|
||||
|
|
|
@ -361,7 +361,7 @@ void MemoryBuffer::copy_from(const ImBuf *src,
|
|||
to_y,
|
||||
to_channel_offset);
|
||||
if (ensure_linear_space) {
|
||||
colorspace_to_scene_linear(this, area, src->rect_colorspace);
|
||||
colorspace_to_scene_linear(this, area, src->byte_buffer.colorspace);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -80,11 +80,7 @@ void COM_execute(Render *render,
|
|||
node_tree->execution_mode == NTREE_EXECUTION_MODE_REALTIME)
|
||||
{
|
||||
/* Realtime GPU compositor. */
|
||||
|
||||
/* TODO: add persistence and depsgraph updates for better performance. */
|
||||
blender::render::RealtimeCompositor compositor(
|
||||
*render, *scene, *render_data, *node_tree, rendering, view_name);
|
||||
compositor.execute();
|
||||
RE_compositor_execute(*render, *scene, *render_data, *node_tree, rendering, view_name);
|
||||
}
|
||||
else {
|
||||
/* Tiled and Full Frame compositors. */
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "COM_KuwaharaNode.h"
|
||||
|
||||
#include "COM_ConvertOperation.h"
|
||||
#include "COM_ConvolutionFilterOperation.h"
|
||||
#include "COM_FastGaussianBlurOperation.h"
|
||||
#include "COM_KuwaharaAnisotropicOperation.h"
|
||||
|
@ -31,7 +32,11 @@ void KuwaharaNode::convert_to_operations(NodeConverter &converter,
|
|||
}
|
||||
|
||||
case CMP_NODE_KUWAHARA_ANISOTROPIC: {
|
||||
/* Edge detection */
|
||||
/* Edge detection on luminance. */
|
||||
auto rgb_to_lum = new ConvertColorToBWOperation();
|
||||
converter.add_operation(rgb_to_lum);
|
||||
converter.map_input_socket(get_input_socket(0), rgb_to_lum->get_input_socket(0));
|
||||
|
||||
auto const_fact = new SetValueOperation();
|
||||
const_fact->set_value(1.0f);
|
||||
converter.add_operation(const_fact);
|
||||
|
@ -39,16 +44,16 @@ void KuwaharaNode::convert_to_operations(NodeConverter &converter,
|
|||
auto sobel_x = new ConvolutionFilterOperation();
|
||||
sobel_x->set3x3Filter(1, 0, -1, 2, 0, -2, 1, 0, -1);
|
||||
converter.add_operation(sobel_x);
|
||||
converter.map_input_socket(get_input_socket(0), sobel_x->get_input_socket(0));
|
||||
converter.add_link(rgb_to_lum->get_output_socket(0), sobel_x->get_input_socket(0));
|
||||
converter.add_link(const_fact->get_output_socket(0), sobel_x->get_input_socket(1));
|
||||
|
||||
auto sobel_y = new ConvolutionFilterOperation();
|
||||
sobel_y->set3x3Filter(1, 2, 1, 0, 0, 0, -1, -2, -1);
|
||||
converter.add_operation(sobel_y);
|
||||
converter.map_input_socket(get_input_socket(0), sobel_y->get_input_socket(0));
|
||||
converter.add_link(rgb_to_lum->get_output_socket(0), sobel_y->get_input_socket(0));
|
||||
converter.add_link(const_fact->get_output_socket(0), sobel_y->get_input_socket(1));
|
||||
|
||||
/* Compute intensity of edges */
|
||||
/* Compute intensity of edges. */
|
||||
auto sobel_xx = new MathMultiplyOperation();
|
||||
auto sobel_yy = new MathMultiplyOperation();
|
||||
auto sobel_xy = new MathMultiplyOperation();
|
||||
|
|
|
@ -136,7 +136,8 @@ static void sample_image_at_location(
|
|||
}
|
||||
rgba_uchar_to_float(color, byte_color);
|
||||
if (make_linear_rgb) {
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v4(color, false, ibuf->rect_colorspace);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v4(
|
||||
color, false, ibuf->byte_buffer.colorspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,11 +202,10 @@ void KuwaharaAnisotropicOperation::update_memory_buffer_partial(MemoryBuffer *ou
|
|||
const int x = it.x;
|
||||
const int y = it.y;
|
||||
|
||||
/* For now use green channel to compute orientation. */
|
||||
/* TODO: convert to HSV and compute orientation and strength on luminance channel. */
|
||||
const float a = s_xx->get_value(x, y, 1);
|
||||
const float b = s_xy->get_value(x, y, 1);
|
||||
const float c = s_yy->get_value(x, y, 1);
|
||||
/* All channels are identical. Take first channel for simplicity. */
|
||||
const float a = s_xx->get_value(x, y, 0);
|
||||
const float b = s_xy->get_value(x, y, 0);
|
||||
const float c = s_yy->get_value(x, y, 0);
|
||||
|
||||
/* Compute egenvalues of structure tensor */
|
||||
const double tr = a + c;
|
||||
|
|
|
@ -68,10 +68,14 @@ set(SRC
|
|||
COM_texture_pool.hh
|
||||
COM_utilities.hh
|
||||
|
||||
algorithms/intern/algorithm_parallel_reduction.cc
|
||||
algorithms/intern/morphological_distance.cc
|
||||
algorithms/intern/morphological_distance_feather.cc
|
||||
algorithms/intern/parallel_reduction.cc
|
||||
algorithms/intern/smaa.cc
|
||||
algorithms/intern/symmetric_separable_blur.cc
|
||||
|
||||
algorithms/COM_algorithm_morphological_distance.hh
|
||||
algorithms/COM_algorithm_morphological_distance_feather.hh
|
||||
algorithms/COM_algorithm_parallel_reduction.hh
|
||||
algorithms/COM_algorithm_smaa.hh
|
||||
algorithms/COM_algorithm_symmetric_separable_blur.hh
|
||||
|
@ -135,6 +139,11 @@ set(GLSL_SRC
|
|||
shaders/compositor_glare_streaks_filter.glsl
|
||||
shaders/compositor_id_mask.glsl
|
||||
shaders/compositor_image_crop.glsl
|
||||
shaders/compositor_keying_compute_image.glsl
|
||||
shaders/compositor_keying_compute_matte.glsl
|
||||
shaders/compositor_keying_extract_chroma.glsl
|
||||
shaders/compositor_keying_replace_chroma.glsl
|
||||
shaders/compositor_keying_tweak_matte.glsl
|
||||
shaders/compositor_map_uv.glsl
|
||||
shaders/compositor_morphological_distance.glsl
|
||||
shaders/compositor_morphological_distance_feather.glsl
|
||||
|
@ -239,6 +248,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_glare_info.hh
|
||||
shaders/infos/compositor_id_mask_info.hh
|
||||
shaders/infos/compositor_image_crop_info.hh
|
||||
shaders/infos/compositor_keying_info.hh
|
||||
shaders/infos/compositor_map_uv_info.hh
|
||||
shaders/infos/compositor_morphological_distance_feather_info.hh
|
||||
shaders/infos/compositor_morphological_distance_info.hh
|
||||
|
|
|
@ -84,7 +84,9 @@ class Context {
|
|||
|
||||
/* Get the texture where the given render pass is stored. This should be called by the Render
|
||||
* Layer node to populate its outputs. */
|
||||
virtual GPUTexture *get_input_texture(int view_layer, const char *pass_name) = 0;
|
||||
virtual GPUTexture *get_input_texture(const Scene *scene,
|
||||
int view_layer,
|
||||
const char *pass_name) = 0;
|
||||
|
||||
/* Get the name of the view currently being rendered. */
|
||||
virtual StringRef get_view_name() = 0;
|
||||
|
|
|
@ -45,10 +45,7 @@ class NodeOperation : public Operation {
|
|||
void compute_results_reference_counts(const Schedule &schedule);
|
||||
|
||||
protected:
|
||||
/* Compute a preview for the operation and set to the bNodePreview of the node. This is only done
|
||||
* for nodes which enables previews, are not hidden, and are part of the active node context. The
|
||||
* preview is computed as a lower resolution version of the output of the get_preview_result
|
||||
* method. */
|
||||
/* Compute a node preview using the result returned from the get_preview_result method. */
|
||||
void compute_preview() override;
|
||||
|
||||
/* Returns a reference to the derived node that this operation represents. */
|
||||
|
@ -67,10 +64,6 @@ class NodeOperation : public Operation {
|
|||
* guaranteed not to be returned, since the node will always either have a linked output or an
|
||||
* allocated input. */
|
||||
Result *get_preview_result();
|
||||
|
||||
/* Resize the give input result to the given preview size and set it to the preview buffer after
|
||||
* applying the necessary color management processor.*/
|
||||
void write_preview_from_result(bNodePreview &preview, Result &input_result);
|
||||
};
|
||||
|
||||
} // namespace blender::realtime_compositor
|
||||
|
|
|
@ -164,6 +164,20 @@ class Result {
|
|||
* the discussion above for more information. */
|
||||
void pass_through(Result &target);
|
||||
|
||||
/* Steal the allocated data from the given source result and assign it to this result, then
|
||||
* remove any references to the data from the source result. It is assumed that:
|
||||
*
|
||||
* - Both results are of the same type.
|
||||
* - This result is not allocated but the source result is allocated.
|
||||
* - Neither of the results is a proxy one, that is, has a master result.
|
||||
*
|
||||
* This is different from proxy results and the pass_through mechanism in that it can be used on
|
||||
* temporary results. This is most useful in multi-step compositor operations where some steps
|
||||
* can be optional, in that case, intermediate results can be temporary results that can
|
||||
* eventually be stolen by the actual output of the operation. See the uses of the method for
|
||||
* a practical example of use. */
|
||||
void steal_data(Result &source);
|
||||
|
||||
/* Transform the result by the given transformation. This effectively pre-multiply the given
|
||||
* transformation by the current transformation of the domain of the result. */
|
||||
void transform(const float3x3 &transformation);
|
||||
|
|
|
@ -112,6 +112,9 @@ class ShaderOperation : public Operation {
|
|||
* the attribute that was created for it. This is used to share the same attribute with all
|
||||
* inputs that are linked to the same output socket. */
|
||||
Map<DOutputSocket, GPUNodeLink *> output_to_material_attribute_map_;
|
||||
/* A vector set that stores all output sockets that are used as previews for nodes inside the
|
||||
* shader operation. */
|
||||
VectorSet<DOutputSocket> preview_outputs_;
|
||||
|
||||
public:
|
||||
/* Construct and compile a GPU material from the given shader compile unit by calling
|
||||
|
@ -125,6 +128,13 @@ class ShaderOperation : public Operation {
|
|||
* shader. */
|
||||
void execute() override;
|
||||
|
||||
/* Compute a node preview for all nodes in the shader operations if the node requires a preview.
|
||||
*
|
||||
* Previews are computed from results that are populated for outputs that are used to compute
|
||||
* previews even if they are internally linked, and those outputs are stored and tracked in the
|
||||
* preview_outputs_ vector set, see the populate_results_for_node method for more information. */
|
||||
void compute_preview() override;
|
||||
|
||||
/* Get the identifier of the operation output corresponding to the given output socket. This is
|
||||
* called by the compiler to identify the operation output that provides the result for an input
|
||||
* by providing the output socket that the input is linked to. See
|
||||
|
@ -138,9 +148,14 @@ class ShaderOperation : public Operation {
|
|||
|
||||
/* Compute and set the initial reference counts of all the results of the operation. The
|
||||
* reference counts of the results are the number of operations that use those results, which is
|
||||
* computed as the number of inputs whose node is part of the schedule and is linked to the
|
||||
* output corresponding to each of the results of the operation. The node execution schedule is
|
||||
* given as an input. */
|
||||
* computed as the number of inputs linked to the output corresponding to each of the results of
|
||||
* the operation, but only the linked inputs whose node is part of the schedule but not part of
|
||||
* the shader operation, since inputs that are part of the shader operations are internal links.
|
||||
*
|
||||
* Additionally, results that are used as node previews gets an extra reference count because
|
||||
* they are referenced and released by the compute_preview method.
|
||||
*
|
||||
* The node execution schedule is given as an input. */
|
||||
void compute_results_reference_counts(const Schedule &schedule);
|
||||
|
||||
private:
|
||||
|
@ -209,7 +224,8 @@ class ShaderOperation : public Operation {
|
|||
GPUMaterial *material);
|
||||
|
||||
/* Populate the output results of the shader operation for output sockets of the given node that
|
||||
* are linked to nodes outside of the shader operation. */
|
||||
* are linked to nodes outside of the shader operation or are used to compute a preview for the
|
||||
* node. */
|
||||
void populate_results_for_node(DNode node, GPUMaterial *material);
|
||||
|
||||
/* Given the output socket of a node that is part of the shader operation which is linked to an
|
||||
|
|
|
@ -70,4 +70,11 @@ void compute_dispatch_threads_at_least(GPUShader *shader,
|
|||
int2 threads_range,
|
||||
int2 local_size = int2(16));
|
||||
|
||||
/* Returns true if a node preview needs to be computed for the give node. */
|
||||
bool is_node_preview_needed(const DNode &node);
|
||||
|
||||
/* Computes a lower resolution version of the given result and sets it as a preview for the given
|
||||
* node after applying the appropriate color management specified in the given context. */
|
||||
void compute_preview_from_result(Context &context, const DNode &node, Result &input_result);
|
||||
|
||||
} // namespace blender::realtime_compositor
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_result.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
||||
/* Dilate or erode the given input using a morphological operator with a circular structuring
|
||||
* element of radius equivalent to the absolute value of the given distance parameter. A positive
|
||||
* distance corresponds to dilate operator, while a negative distance corresponds to an erode
|
||||
* operator. */
|
||||
void morphological_distance(Context &context, Result &input, Result &output, int distance);
|
||||
|
||||
} // namespace blender::realtime_compositor
|
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_result.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
||||
/* Dilate or erode the given input using a morphological inverse distance operation evaluated at
|
||||
* the given falloff. The radius of the structuring element is equivalent to the absolute value of
|
||||
* the given distance parameter. A positive distance corresponds to a dilate operator, while a
|
||||
* negative distance corresponds to an erode operator. See the implementation and shader for more
|
||||
* information. */
|
||||
void morphological_distance_feather(
|
||||
Context &context, Result &input, Result &output, int distance, int falloff_type = PROP_SMOOTH);
|
||||
|
||||
} // namespace blender::realtime_compositor
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_result.hh"
|
||||
|
||||
|
@ -22,8 +24,8 @@ void symmetric_separable_blur(Context &context,
|
|||
Result &input,
|
||||
Result &output,
|
||||
float2 radius,
|
||||
int filter_type,
|
||||
bool extend_bounds,
|
||||
bool gamma_correct);
|
||||
int filter_type = R_FILTER_GAUSS,
|
||||
bool extend_bounds = false,
|
||||
bool gamma_correct = false);
|
||||
|
||||
} // namespace blender::realtime_compositor
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_base.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_result.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "COM_algorithm_morphological_distance.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
||||
static const char *get_shader_name(int distance)
|
||||
{
|
||||
if (distance > 0) {
|
||||
return "compositor_morphological_distance_dilate";
|
||||
}
|
||||
return "compositor_morphological_distance_erode";
|
||||
}
|
||||
|
||||
void morphological_distance(Context &context, Result &input, Result &output, int distance)
|
||||
{
|
||||
GPUShader *shader = context.shader_manager().get(get_shader_name(distance));
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
/* Pass the absolute value of the distance. We have specialized shaders for each sign. */
|
||||
GPU_shader_uniform_1i(shader, "radius", math::abs(distance));
|
||||
|
||||
input.bind_as_texture(shader, "input_tx");
|
||||
|
||||
output.allocate_texture(input.domain());
|
||||
output.bind_as_image(shader, "output_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, input.domain().size);
|
||||
|
||||
GPU_shader_unbind();
|
||||
output.unbind_as_image();
|
||||
input.unbind_as_texture();
|
||||
}
|
||||
|
||||
} // namespace blender::realtime_compositor
|
|
@ -0,0 +1,108 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_math_base.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "COM_algorithm_morphological_distance_feather.hh" /* Own include. */
|
||||
#include "COM_algorithm_symmetric_separable_blur.hh"
|
||||
#include "COM_context.hh"
|
||||
#include "COM_morphological_distance_feather_weights.hh"
|
||||
#include "COM_result.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
||||
static const char *get_shader_name(int distance)
|
||||
{
|
||||
if (distance > 0) {
|
||||
return "compositor_morphological_distance_feather_dilate";
|
||||
}
|
||||
return "compositor_morphological_distance_feather_erode";
|
||||
}
|
||||
|
||||
static Result horizontal_pass(Context &context, Result &input, int distance, int falloff_type)
|
||||
{
|
||||
GPUShader *shader = context.shader_manager().get(get_shader_name(distance));
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
input.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const MorphologicalDistanceFeatherWeights &weights =
|
||||
context.cache_manager().morphological_distance_feather_weights.get(falloff_type,
|
||||
math::abs(distance));
|
||||
weights.bind_weights_as_texture(shader, "weights_tx");
|
||||
weights.bind_distance_falloffs_as_texture(shader, "falloffs_tx");
|
||||
|
||||
/* We allocate an output image of a transposed size, that is, with a height equivalent to the
|
||||
* width of the input and vice versa. This is done as a performance optimization. The shader
|
||||
* will process the image horizontally and write it to the intermediate output transposed. Then
|
||||
* the vertical pass will execute the same horizontal pass shader, but since its input is
|
||||
* transposed, it will effectively do a vertical pass and write to the output transposed,
|
||||
* effectively undoing the transposition in the horizontal pass. This is done to improve
|
||||
* spatial cache locality in the shader and to avoid having two separate shaders for each of
|
||||
* the passes. */
|
||||
const Domain domain = input.domain();
|
||||
const int2 transposed_domain = int2(domain.size.y, domain.size.x);
|
||||
|
||||
Result output = Result::Temporary(ResultType::Float, context.texture_pool());
|
||||
output.allocate_texture(transposed_domain);
|
||||
output.bind_as_image(shader, "output_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, domain.size);
|
||||
|
||||
GPU_shader_unbind();
|
||||
input.unbind_as_texture();
|
||||
weights.unbind_weights_as_texture();
|
||||
weights.unbind_distance_falloffs_as_texture();
|
||||
output.unbind_as_image();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static void vertical_pass(Context &context,
|
||||
Result &original_input,
|
||||
Result &horizontal_pass_result,
|
||||
Result &output,
|
||||
int distance,
|
||||
int falloff_type)
|
||||
{
|
||||
GPUShader *shader = context.shader_manager().get(get_shader_name(distance));
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
horizontal_pass_result.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const MorphologicalDistanceFeatherWeights &weights =
|
||||
context.cache_manager().morphological_distance_feather_weights.get(falloff_type,
|
||||
math::abs(distance));
|
||||
weights.bind_weights_as_texture(shader, "weights_tx");
|
||||
weights.bind_distance_falloffs_as_texture(shader, "falloffs_tx");
|
||||
|
||||
const Domain domain = original_input.domain();
|
||||
output.allocate_texture(domain);
|
||||
output.bind_as_image(shader, "output_img");
|
||||
|
||||
/* Notice that the domain is transposed, see the note on the horizontal pass function for more
|
||||
* information on the reasoning behind this. */
|
||||
compute_dispatch_threads_at_least(shader, int2(domain.size.y, domain.size.x));
|
||||
|
||||
GPU_shader_unbind();
|
||||
horizontal_pass_result.unbind_as_texture();
|
||||
weights.unbind_weights_as_texture();
|
||||
weights.unbind_distance_falloffs_as_texture();
|
||||
output.unbind_as_image();
|
||||
}
|
||||
|
||||
void morphological_distance_feather(
|
||||
Context &context, Result &input, Result &output, int distance, int falloff_type)
|
||||
{
|
||||
Result horizontal_pass_result = horizontal_pass(context, input, distance, falloff_type);
|
||||
vertical_pass(context, input, horizontal_pass_result, output, distance, falloff_type);
|
||||
horizontal_pass_result.release();
|
||||
}
|
||||
|
||||
} // namespace blender::realtime_compositor
|
|
@ -10,6 +10,7 @@
|
|||
#include "GPU_texture.h"
|
||||
|
||||
#include "COM_context.hh"
|
||||
#include "COM_result.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "COM_algorithm_symmetric_separable_blur.hh"
|
||||
|
@ -18,6 +19,15 @@
|
|||
|
||||
namespace blender::realtime_compositor {
|
||||
|
||||
static const char *get_blur_shader(ResultType type)
|
||||
{
|
||||
if (type == ResultType::Float) {
|
||||
return "compositor_symmetric_separable_blur_float";
|
||||
}
|
||||
|
||||
return "compositor_symmetric_separable_blur_color";
|
||||
}
|
||||
|
||||
static Result horizontal_pass(Context &context,
|
||||
Result &input,
|
||||
float radius,
|
||||
|
@ -25,7 +35,7 @@ static Result horizontal_pass(Context &context,
|
|||
bool extend_bounds,
|
||||
bool gamma_correct)
|
||||
{
|
||||
GPUShader *shader = context.shader_manager().get("compositor_symmetric_separable_blur");
|
||||
GPUShader *shader = context.shader_manager().get(get_blur_shader(input.type()));
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_shader_uniform_1b(shader, "extend_bounds", extend_bounds);
|
||||
|
@ -53,7 +63,7 @@ static Result horizontal_pass(Context &context,
|
|||
* pass. */
|
||||
const int2 transposed_domain = int2(domain.size.y, domain.size.x);
|
||||
|
||||
Result output = Result::Temporary(ResultType::Color, context.texture_pool());
|
||||
Result output = Result::Temporary(input.type(), context.texture_pool());
|
||||
output.allocate_texture(transposed_domain);
|
||||
output.bind_as_image(shader, "output_img");
|
||||
|
||||
|
@ -76,7 +86,7 @@ static void vertical_pass(Context &context,
|
|||
bool extend_bounds,
|
||||
bool gamma_correct)
|
||||
{
|
||||
GPUShader *shader = context.shader_manager().get("compositor_symmetric_separable_blur");
|
||||
GPUShader *shader = context.shader_manager().get(get_blur_shader(original_input.type()));
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_shader_uniform_1b(shader, "extend_bounds", extend_bounds);
|
||||
|
|
|
@ -5,21 +5,16 @@
|
|||
#include <memory>
|
||||
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_base.hh"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "NOD_derived_node_tree.hh"
|
||||
|
@ -53,53 +48,11 @@ NodeOperation::NodeOperation(Context &context, DNode node) : Operation(context),
|
|||
}
|
||||
}
|
||||
|
||||
/* Given the size of a result, compute a lower resolution size for a preview. The greater dimension
|
||||
* will be assigned an arbitrarily chosen size of 128, while the other dimension will get the size
|
||||
* that maintains the same aspect ratio. */
|
||||
static int2 compute_preview_size(int2 size)
|
||||
{
|
||||
const int greater_dimension_size = 128;
|
||||
if (size.x > size.y) {
|
||||
return int2(greater_dimension_size, int(greater_dimension_size * (float(size.y) / size.x)));
|
||||
}
|
||||
else {
|
||||
return int2(int(greater_dimension_size * (float(size.x) / size.y)), greater_dimension_size);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeOperation::compute_preview()
|
||||
{
|
||||
if (!(node()->flag & NODE_PREVIEW)) {
|
||||
return;
|
||||
if (is_node_preview_needed(node())) {
|
||||
compute_preview_from_result(context(), node(), *get_preview_result());
|
||||
}
|
||||
|
||||
if (node()->flag & NODE_HIDDEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only compute previews for nodes in the active context. */
|
||||
if (node().context()->instance_key().value !=
|
||||
node().context()->derived_tree().active_context().instance_key().value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize node tree previews if not already initialized. */
|
||||
bNodeTree *root_tree = const_cast<bNodeTree *>(
|
||||
&node().context()->derived_tree().root_context().btree());
|
||||
if (!root_tree->previews) {
|
||||
root_tree->previews = BKE_node_instance_hash_new("node previews");
|
||||
}
|
||||
|
||||
Result *preview_result = get_preview_result();
|
||||
const int2 preview_size = compute_preview_size(preview_result->domain().size);
|
||||
node()->runtime->preview_xsize = preview_size.x;
|
||||
node()->runtime->preview_ysize = preview_size.y;
|
||||
|
||||
bNodePreview *preview = bke::node_preview_verify(
|
||||
root_tree->previews, node().instance_key(), preview_size.x, preview_size.y, true);
|
||||
|
||||
write_preview_from_result(*preview, *preview_result);
|
||||
}
|
||||
|
||||
Result *NodeOperation::get_preview_result()
|
||||
|
@ -124,55 +77,6 @@ Result *NodeOperation::get_preview_result()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeOperation::write_preview_from_result(bNodePreview &preview, Result &input_result)
|
||||
{
|
||||
GPUShader *shader = shader_manager().get("compositor_compute_preview");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rrr1");
|
||||
}
|
||||
|
||||
input_result.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const int2 preview_size = int2(preview.xsize, preview.ysize);
|
||||
Result preview_result = Result::Temporary(ResultType::Color, texture_pool());
|
||||
preview_result.allocate_texture(Domain(preview_size));
|
||||
preview_result.bind_as_image(shader, "preview_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, preview_size);
|
||||
|
||||
input_result.unbind_as_texture();
|
||||
preview_result.unbind_as_image();
|
||||
GPU_shader_unbind();
|
||||
|
||||
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
float *preview_pixels = static_cast<float *>(
|
||||
GPU_texture_read(preview_result.texture(), GPU_DATA_FLOAT, 0));
|
||||
preview_result.release();
|
||||
|
||||
ColormanageProcessor *color_processor = IMB_colormanagement_display_processor_new(
|
||||
&context().get_scene().view_settings, &context().get_scene().display_settings);
|
||||
|
||||
threading::parallel_for(IndexRange(preview_size.y), 1, [&](const IndexRange sub_y_range) {
|
||||
for (const int64_t y : sub_y_range) {
|
||||
for (const int64_t x : IndexRange(preview_size.x)) {
|
||||
const int index = (y * preview_size.x + x) * 4;
|
||||
IMB_colormanagement_processor_apply_v4(color_processor, preview_pixels + index);
|
||||
rgba_float_to_uchar(preview.rect + index, preview_pixels + index);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Restore original swizzle mask set above. */
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rgba");
|
||||
}
|
||||
|
||||
IMB_colormanagement_processor_free(color_processor);
|
||||
MEM_freeN(preview_pixels);
|
||||
}
|
||||
|
||||
void NodeOperation::compute_results_reference_counts(const Schedule &schedule)
|
||||
{
|
||||
for (const bNodeSocket *output : this->node()->output_sockets()) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_math_matrix_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
|
@ -133,6 +134,33 @@ void Result::pass_through(Result &target)
|
|||
target.master_ = this;
|
||||
}
|
||||
|
||||
void Result::steal_data(Result &source)
|
||||
{
|
||||
BLI_assert(type_ == source.type_);
|
||||
BLI_assert(!is_allocated() && source.is_allocated());
|
||||
BLI_assert(master_ == nullptr && source.master_ == nullptr);
|
||||
|
||||
is_single_value_ = source.is_single_value_;
|
||||
texture_ = source.texture_;
|
||||
texture_pool_ = source.texture_pool_;
|
||||
domain_ = source.domain_;
|
||||
|
||||
switch (type_) {
|
||||
case ResultType::Float:
|
||||
float_value_ = source.float_value_;
|
||||
break;
|
||||
case ResultType::Vector:
|
||||
vector_value_ = source.vector_value_;
|
||||
break;
|
||||
case ResultType::Color:
|
||||
color_value_ = source.color_value_;
|
||||
break;
|
||||
}
|
||||
|
||||
source.texture_ = nullptr;
|
||||
source.texture_pool_ = nullptr;
|
||||
}
|
||||
|
||||
void Result::transform(const float3x3 &transformation)
|
||||
{
|
||||
domain_.transform(transformation);
|
||||
|
@ -235,6 +263,7 @@ void Result::release()
|
|||
reference_count_--;
|
||||
if (reference_count_ == 0) {
|
||||
texture_pool_->release(texture_);
|
||||
texture_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,15 @@ void ShaderOperation::execute()
|
|||
GPU_shader_unbind();
|
||||
}
|
||||
|
||||
void ShaderOperation::compute_preview()
|
||||
{
|
||||
for (const DOutputSocket &output : preview_outputs_) {
|
||||
Result &result = get_result(get_output_identifier_from_output_socket(output));
|
||||
compute_preview_from_result(context(), output.node(), result);
|
||||
result.release();
|
||||
}
|
||||
}
|
||||
|
||||
StringRef ShaderOperation::get_output_identifier_from_output_socket(DOutputSocket output_socket)
|
||||
{
|
||||
return output_sockets_to_output_identifiers_map_.lookup(output_socket);
|
||||
|
@ -84,7 +93,7 @@ Map<std::string, DOutputSocket> &ShaderOperation::get_inputs_to_linked_outputs_m
|
|||
void ShaderOperation::compute_results_reference_counts(const Schedule &schedule)
|
||||
{
|
||||
for (const auto item : output_sockets_to_output_identifiers_map_.items()) {
|
||||
const int reference_count = number_of_inputs_linked_to_output_conditioned(
|
||||
int reference_count = number_of_inputs_linked_to_output_conditioned(
|
||||
item.key, [&](DInputSocket input) {
|
||||
/* We only consider inputs that are not part of the shader operations, because inputs
|
||||
* that are part of the shader operations are internal and do not deal with the result
|
||||
|
@ -92,6 +101,10 @@ void ShaderOperation::compute_results_reference_counts(const Schedule &schedule)
|
|||
return schedule.contains(input.node()) && !compile_unit_.contains(input.node());
|
||||
});
|
||||
|
||||
if (preview_outputs_.contains(item.key)) {
|
||||
reference_count++;
|
||||
}
|
||||
|
||||
get_result(item.value).set_initial_reference_count(reference_count);
|
||||
}
|
||||
}
|
||||
|
@ -248,17 +261,41 @@ void ShaderOperation::declare_operation_input(DInputSocket input_socket,
|
|||
inputs_to_linked_outputs_map_.add_new(input_identifier, output_socket);
|
||||
}
|
||||
|
||||
static DOutputSocket find_preview_output_socket(const DNode &node)
|
||||
{
|
||||
if (!is_node_preview_needed(node)) {
|
||||
return DOutputSocket();
|
||||
}
|
||||
|
||||
for (const bNodeSocket *output : node->output_sockets()) {
|
||||
if (output->is_logically_linked()) {
|
||||
return DOutputSocket(node.context(), output);
|
||||
}
|
||||
}
|
||||
|
||||
return DOutputSocket();
|
||||
}
|
||||
|
||||
void ShaderOperation::populate_results_for_node(DNode node, GPUMaterial *material)
|
||||
{
|
||||
const DOutputSocket preview_output = find_preview_output_socket(node);
|
||||
|
||||
for (const bNodeSocket *output : node->output_sockets()) {
|
||||
const DOutputSocket doutput{node.context(), output};
|
||||
|
||||
/* If any of the nodes linked to the output are not part of the shader operation, then an
|
||||
* output result needs to be populated for it. */
|
||||
const bool need_to_populate_result = is_output_linked_to_node_conditioned(
|
||||
const bool is_operation_output = is_output_linked_to_node_conditioned(
|
||||
doutput, [&](DNode node) { return !compile_unit_.contains(node); });
|
||||
|
||||
if (need_to_populate_result) {
|
||||
/* If the output is used as the node preview, then an output result needs to be populated for
|
||||
* it, and we additionally keep track of that output to later compute the previes from. */
|
||||
const bool is_preview_output = doutput == preview_output;
|
||||
if (is_preview_output) {
|
||||
preview_outputs_.add(doutput);
|
||||
}
|
||||
|
||||
if (is_operation_output || is_preview_output) {
|
||||
populate_operation_result(doutput, material);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,15 @@
|
|||
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "IMB_colormanagement.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "NOD_derived_node_tree.hh"
|
||||
|
@ -133,4 +138,100 @@ void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, in
|
|||
GPU_compute_dispatch(shader, groups_to_dispatch.x, groups_to_dispatch.y, 1);
|
||||
}
|
||||
|
||||
bool is_node_preview_needed(const DNode &node)
|
||||
{
|
||||
if (!(node->flag & NODE_PREVIEW)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node->flag & NODE_HIDDEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only compute previews for nodes in the active context. */
|
||||
if (node.context()->instance_key().value !=
|
||||
node.context()->derived_tree().active_context().instance_key().value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Given the size of a result, compute a lower resolution size for a preview. The greater dimension
|
||||
* will be assigned an arbitrarily chosen size of 128, while the other dimension will get the size
|
||||
* that maintains the same aspect ratio. */
|
||||
static int2 compute_preview_size(int2 size)
|
||||
{
|
||||
const int greater_dimension_size = 128;
|
||||
if (size.x > size.y) {
|
||||
return int2(greater_dimension_size, int(greater_dimension_size * (float(size.y) / size.x)));
|
||||
}
|
||||
else {
|
||||
return int2(int(greater_dimension_size * (float(size.x) / size.y)), greater_dimension_size);
|
||||
}
|
||||
}
|
||||
|
||||
void compute_preview_from_result(Context &context, const DNode &node, Result &input_result)
|
||||
{
|
||||
/* Initialize node tree previews if not already initialized. */
|
||||
bNodeTree *root_tree = const_cast<bNodeTree *>(
|
||||
&node.context()->derived_tree().root_context().btree());
|
||||
if (!root_tree->previews) {
|
||||
root_tree->previews = BKE_node_instance_hash_new("node previews");
|
||||
}
|
||||
|
||||
const int2 preview_size = compute_preview_size(input_result.domain().size);
|
||||
node->runtime->preview_xsize = preview_size.x;
|
||||
node->runtime->preview_ysize = preview_size.y;
|
||||
|
||||
bNodePreview *preview = bke::node_preview_verify(
|
||||
root_tree->previews, node.instance_key(), preview_size.x, preview_size.y, true);
|
||||
|
||||
GPUShader *shader = context.shader_manager().get("compositor_compute_preview");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rrr1");
|
||||
}
|
||||
|
||||
input_result.bind_as_texture(shader, "input_tx");
|
||||
|
||||
Result preview_result = Result::Temporary(ResultType::Color, context.texture_pool());
|
||||
preview_result.allocate_texture(Domain(preview_size));
|
||||
preview_result.bind_as_image(shader, "preview_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, preview_size);
|
||||
|
||||
input_result.unbind_as_texture();
|
||||
preview_result.unbind_as_image();
|
||||
GPU_shader_unbind();
|
||||
|
||||
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
|
||||
float *preview_pixels = static_cast<float *>(
|
||||
GPU_texture_read(preview_result.texture(), GPU_DATA_FLOAT, 0));
|
||||
preview_result.release();
|
||||
|
||||
ColormanageProcessor *color_processor = IMB_colormanagement_display_processor_new(
|
||||
&context.get_scene().view_settings, &context.get_scene().display_settings);
|
||||
|
||||
threading::parallel_for(IndexRange(preview_size.y), 1, [&](const IndexRange sub_y_range) {
|
||||
for (const int64_t y : sub_y_range) {
|
||||
for (const int64_t x : IndexRange(preview_size.x)) {
|
||||
const int index = (y * preview_size.x + x) * 4;
|
||||
IMB_colormanagement_processor_apply_v4(color_processor, preview_pixels + index);
|
||||
rgba_float_to_uchar(preview->rect + index, preview_pixels + index);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Restore original swizzle mask set above. */
|
||||
if (input_result.type() == ResultType::Float) {
|
||||
GPU_texture_swizzle_set(input_result.texture(), "rgba");
|
||||
}
|
||||
|
||||
IMB_colormanagement_processor_free(color_processor);
|
||||
MEM_freeN(preview_pixels);
|
||||
}
|
||||
|
||||
} // namespace blender::realtime_compositor
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
vec4 key = texture_load(key_tx, texel);
|
||||
vec4 color = texture_load(input_tx, texel);
|
||||
float matte = texture_load(matte_tx, texel).x;
|
||||
|
||||
/* Alpha multiply the matte to the image. */
|
||||
color *= matte;
|
||||
|
||||
/* Color despill. */
|
||||
ivec3 key_argmax = argmax(key.rgb);
|
||||
float weighted_average = mix(color[key_argmax.y], color[key_argmax.z], despill_balance);
|
||||
color[key_argmax.x] -= (color[key_argmax.x] - weighted_average) * despill_factor;
|
||||
|
||||
imageStore(output_img, texel, color);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
|
||||
|
||||
float compute_saturation(vec4 color, ivec3 argmax)
|
||||
{
|
||||
float weighted_average = mix(color[argmax.y], color[argmax.z], key_balance);
|
||||
return (color[argmax.x] - weighted_average) * abs(1.0 - weighted_average);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
vec4 input_color = texture_load(input_tx, texel);
|
||||
|
||||
/* We assume that the keying screen will not be overexposed in the image, so if the input
|
||||
* brightness is high, we assume the pixel is opaque. */
|
||||
if (min_v3(input_color) > 1.0f) {
|
||||
imageStore(output_img, texel, vec4(1.0));
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 key_color = texture_load(key_tx, texel);
|
||||
ivec3 key_argmax = argmax(key_color.rgb);
|
||||
float input_saturation = compute_saturation(input_color, key_argmax);
|
||||
float key_saturation = compute_saturation(key_color, key_argmax);
|
||||
|
||||
float matte = 1.0f - clamp(input_saturation / key_saturation, 0.0, 1.0);
|
||||
|
||||
imageStore(output_img, texel, vec4(matte));
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
vec4 color_ycca;
|
||||
rgba_to_ycca_itu_709(texture_load(input_tx, texel), color_ycca);
|
||||
|
||||
imageStore(output_img, texel, color_ycca);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#pragma BLENDER_REQUIRE(gpu_shader_common_color_utils.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
vec4 color_ycca;
|
||||
rgba_to_ycca_itu_709(texture_load(input_tx, texel), color_ycca);
|
||||
|
||||
color_ycca.yz = texture_load(new_chroma_tx, texel).yz;
|
||||
|
||||
vec4 color_rgba;
|
||||
ycca_to_rgba_itu_709(color_ycca, color_rgba);
|
||||
|
||||
imageStore(output_img, texel, color_rgba);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
float matte = texture_load(input_matte_tx, texel).x;
|
||||
|
||||
/* Search the neighbourhood around the current matte value and identify if it lies along the
|
||||
* edges of the matte. This is needs to be computed only when we need to compute the edges output
|
||||
* or tweak the levels of the matte. */
|
||||
bool is_edge = false;
|
||||
if (compute_edges || black_level != 0.0 || white_level != 1.0) {
|
||||
/* Count the number of neighbours whose matte is sufficiently similar to the current matte,
|
||||
* as controlled by the edge_tolerance factor. */
|
||||
int count = 0;
|
||||
for (int j = -edge_search_radius; j <= edge_search_radius; j++) {
|
||||
for (int i = -edge_search_radius; i <= edge_search_radius; i++) {
|
||||
float neighbour_matte = texture_load(input_matte_tx, texel + ivec2(i, j)).x;
|
||||
count += int(distance(matte, neighbour_matte) < edge_tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the number of neighbours that are sufficiently similar to the center matte is less that
|
||||
* 90% of the total number of neighbours, then that means the variance is high in that areas
|
||||
* and it is considered an edge. */
|
||||
is_edge = count < ((edge_search_radius * 2 + 1) * (edge_search_radius * 2 + 1)) * 0.9;
|
||||
}
|
||||
|
||||
float tweaked_matte = matte;
|
||||
|
||||
/* Remap the matte using the black and white levels, but only for areas that are not on the edge
|
||||
* of the matte to preserve details. Also check for equality between levels to avoid zero
|
||||
* division. */
|
||||
if (!is_edge && white_level != black_level) {
|
||||
tweaked_matte = clamp((matte - black_level) / (white_level - black_level), 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* Exclude unwanted areas using the provided garbage matte, 1 means unwanted, so invert the
|
||||
* garbage matte and take the minimum. */
|
||||
if (apply_garbage_matte) {
|
||||
float garbage_matte = texture_load(garbage_matte_tx, texel).x;
|
||||
tweaked_matte = min(tweaked_matte, 1.0 - garbage_matte);
|
||||
}
|
||||
|
||||
/* Include wanted areas that were incorrectly keyed using the provided core matte. */
|
||||
if (apply_core_matte) {
|
||||
float core_matte = texture_load(core_matte_tx, texel).x;
|
||||
tweaked_matte = max(tweaked_matte, core_matte);
|
||||
}
|
||||
|
||||
imageStore(output_matte_img, texel, vec4(tweaked_matte));
|
||||
imageStore(output_edges_img, texel, vec4(is_edge ? 1.0 : 0.0));
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_keying_extract_chroma)
|
||||
.local_group_size(16, 16)
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_keying_extract_chroma.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_keying_replace_chroma)
|
||||
.local_group_size(16, 16)
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D, "new_chroma_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_keying_replace_chroma.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_keying_compute_matte)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::FLOAT, "key_balance")
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D, "key_tx")
|
||||
.image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_keying_compute_matte.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_keying_tweak_matte)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::BOOL, "compute_edges")
|
||||
.push_constant(Type::BOOL, "apply_core_matte")
|
||||
.push_constant(Type::BOOL, "apply_garbage_matte")
|
||||
.push_constant(Type::INT, "edge_search_radius")
|
||||
.push_constant(Type::FLOAT, "edge_tolerance")
|
||||
.push_constant(Type::FLOAT, "black_level")
|
||||
.push_constant(Type::FLOAT, "white_level")
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_matte_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D, "garbage_matte_tx")
|
||||
.sampler(2, ImageType::FLOAT_2D, "core_matte_tx")
|
||||
.image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_matte_img")
|
||||
.image(1, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_edges_img")
|
||||
.compute_source("compositor_keying_tweak_matte.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_keying_compute_image)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::FLOAT, "despill_factor")
|
||||
.push_constant(Type::FLOAT, "despill_balance")
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D, "matte_tx")
|
||||
.sampler(2, ImageType::FLOAT_2D, "key_tx")
|
||||
.image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_keying_compute_image.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -4,13 +4,21 @@
|
|||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_symmetric_separable_blur)
|
||||
GPU_SHADER_CREATE_INFO(compositor_symmetric_separable_blur_shared)
|
||||
.local_group_size(16, 16)
|
||||
.push_constant(Type::BOOL, "extend_bounds")
|
||||
.push_constant(Type::BOOL, "gamma_correct_input")
|
||||
.push_constant(Type::BOOL, "gamma_uncorrect_output")
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.sampler(1, ImageType::FLOAT_1D, "weights_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_symmetric_separable_blur.glsl")
|
||||
.compute_source("compositor_symmetric_separable_blur.glsl");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_symmetric_separable_blur_float)
|
||||
.additional_info("compositor_symmetric_separable_blur_shared")
|
||||
.image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_symmetric_separable_blur_color)
|
||||
.additional_info("compositor_symmetric_separable_blur_shared")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.do_static_compilation(true);
|
||||
|
|
|
@ -149,8 +149,8 @@ set(SRC
|
|||
engines/eevee_next/eevee_instance.cc
|
||||
engines/eevee_next/eevee_irradiance_cache.cc
|
||||
engines/eevee_next/eevee_light.cc
|
||||
engines/eevee_next/eevee_lightprobe.cc
|
||||
engines/eevee_next/eevee_lightcache.cc
|
||||
engines/eevee_next/eevee_lightprobe.cc
|
||||
engines/eevee_next/eevee_material.cc
|
||||
engines/eevee_next/eevee_motion_blur.cc
|
||||
engines/eevee_next/eevee_pipeline.cc
|
||||
|
@ -159,8 +159,8 @@ set(SRC
|
|||
engines/eevee_next/eevee_sampling.cc
|
||||
engines/eevee_next/eevee_shader.cc
|
||||
engines/eevee_next/eevee_shadow.cc
|
||||
engines/eevee_next/eevee_sync.cc
|
||||
engines/eevee_next/eevee_subsurface.cc
|
||||
engines/eevee_next/eevee_sync.cc
|
||||
engines/eevee_next/eevee_velocity.cc
|
||||
engines/eevee_next/eevee_view.cc
|
||||
engines/eevee_next/eevee_world.cc
|
||||
|
@ -292,6 +292,7 @@ set(SRC
|
|||
engines/eevee_next/eevee_irradiance_cache.hh
|
||||
engines/eevee_next/eevee_light.hh
|
||||
engines/eevee_next/eevee_lightcache.hh
|
||||
engines/eevee_next/eevee_lightprobe.hh
|
||||
engines/eevee_next/eevee_material.hh
|
||||
engines/eevee_next/eevee_motion_blur.hh
|
||||
engines/eevee_next/eevee_pipeline.hh
|
||||
|
@ -300,8 +301,8 @@ set(SRC
|
|||
engines/eevee_next/eevee_sampling.hh
|
||||
engines/eevee_next/eevee_shader.hh
|
||||
engines/eevee_next/eevee_shadow.hh
|
||||
engines/eevee_next/eevee_sync.hh
|
||||
engines/eevee_next/eevee_subsurface.hh
|
||||
engines/eevee_next/eevee_sync.hh
|
||||
engines/eevee_next/eevee_velocity.hh
|
||||
engines/eevee_next/eevee_view.hh
|
||||
engines/eevee_next/eevee_world.hh
|
||||
|
|
|
@ -163,9 +163,12 @@ class Context : public realtime_compositor::Context {
|
|||
return DRW_viewport_texture_list_get()->color;
|
||||
}
|
||||
|
||||
GPUTexture *get_input_texture(int view_layer, const char *pass_name) override
|
||||
GPUTexture *get_input_texture(const Scene *scene, int view_layer, const char *pass_name) override
|
||||
{
|
||||
if (view_layer == 0 && STREQ(pass_name, RE_PASSNAME_COMBINED)) {
|
||||
if ((DEG_get_original_id(const_cast<ID *>(&scene->id)) ==
|
||||
DEG_get_original_id(&DRW_context_state_get()->scene->id)) &&
|
||||
view_layer == 0 && STREQ(pass_name, RE_PASSNAME_COMBINED))
|
||||
{
|
||||
return get_output_texture();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup eevee
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup eevee
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup eevee
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup eevee
|
||||
|
|
|
@ -2130,7 +2130,7 @@ void DRW_custom_pipeline_begin(DrawEngineType *draw_engine_type, Depsgraph *deps
|
|||
DRW_view_data_engine_data_get_ensure(DST.view_data_active, draw_engine_type);
|
||||
}
|
||||
|
||||
void DRW_custom_pipeline_end()
|
||||
void DRW_custom_pipeline_end(void)
|
||||
{
|
||||
DST.buffer_finish_called = false;
|
||||
|
||||
|
@ -3187,8 +3187,7 @@ void DRW_render_context_enable(Render *render)
|
|||
if (re_system_gpu_context != NULL) {
|
||||
DRW_system_gpu_render_context_enable(re_system_gpu_context);
|
||||
/* We need to query gpu context after a gl context has been bound. */
|
||||
void *re_blender_gpu_context = NULL;
|
||||
re_blender_gpu_context = RE_blender_gpu_context_get(render);
|
||||
void *re_blender_gpu_context = RE_blender_gpu_context_ensure(render);
|
||||
DRW_blender_gpu_render_context_enable(re_blender_gpu_context);
|
||||
}
|
||||
else {
|
||||
|
@ -3208,8 +3207,7 @@ void DRW_render_context_disable(Render *render)
|
|||
void *re_system_gpu_context = RE_system_gpu_context_get(render);
|
||||
|
||||
if (re_system_gpu_context != NULL) {
|
||||
void *re_blender_gpu_context = NULL;
|
||||
re_blender_gpu_context = RE_blender_gpu_context_get(render);
|
||||
void *re_blender_gpu_context = RE_blender_gpu_context_ensure(render);
|
||||
/* GPU rendering may occur during context disable. */
|
||||
DRW_blender_gpu_render_context_disable(re_blender_gpu_context);
|
||||
GPU_render_end();
|
||||
|
|
|
@ -264,6 +264,13 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
|
|||
deferred = false;
|
||||
}
|
||||
|
||||
/* Avoid crashes with RenderDoc on Windows + Nvidia. */
|
||||
if (G.debug & G_DEBUG_GPU_RENDERDOC &&
|
||||
GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_OFFICIAL))
|
||||
{
|
||||
deferred = false;
|
||||
}
|
||||
|
||||
if (!deferred) {
|
||||
DRW_deferred_shader_remove(mat);
|
||||
/* Shaders could already be compiling. Have to wait for compilation to finish. */
|
||||
|
|
|
@ -54,6 +54,20 @@ mat2 rot2_from_angle(float a)
|
|||
return mat2(c, -s, s, c);
|
||||
}
|
||||
|
||||
/* Computes the full argmax of the given vector, that is, the index of the greatest component will
|
||||
* be in the returned x component, the index of the smallest component will be in the returned z
|
||||
* component, and the index of the middle component will be in the returned y component.
|
||||
*
|
||||
* This is computed by utilizing the fact that booleans are converted to the integers 0 and 1 for
|
||||
* false and true respectively. So if we compare every component to all other components using the
|
||||
* greaterThan comparator, we get 0 for the greatest component, because no other component is
|
||||
* greater, 1 for the middle component, and 2 for the smallest component. */
|
||||
ivec3 argmax(vec3 v)
|
||||
{
|
||||
return ivec3(greaterThan(v, v.xxx)) + ivec3(greaterThan(v, v.yyy)) +
|
||||
ivec3(greaterThan(v, v.zzz));
|
||||
}
|
||||
|
||||
#define min3(a, b, c) min(a, min(b, c))
|
||||
#define min4(a, b, c, d) min(a, min3(b, c, d))
|
||||
#define min5(a, b, c, d, e) min(a, min4(b, c, d, e))
|
||||
|
|
|
@ -268,7 +268,7 @@ struct AssetEntryWriter {
|
|||
|
||||
void add_catalog_id(const CatalogID &catalog_id)
|
||||
{
|
||||
char catalog_id_str[UUID_STRING_LEN];
|
||||
char catalog_id_str[UUID_STRING_SIZE];
|
||||
BLI_uuid_format(catalog_id_str, catalog_id);
|
||||
attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_CATALOG_ID, new StringValue(catalog_id_str)));
|
||||
}
|
||||
|
|
|
@ -5609,7 +5609,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
Curve *cu;
|
||||
float location[3];
|
||||
const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
|
||||
(vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
|
||||
(vc.scene->toolsettings->snap_mode == SCE_SNAP_TO_FACE));
|
||||
|
||||
Nurb *nu;
|
||||
BezTriple *bezt;
|
||||
|
@ -5641,7 +5641,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
vc.depsgraph,
|
||||
vc.region,
|
||||
vc.v3d,
|
||||
SCE_SNAP_MODE_FACE,
|
||||
SCE_SNAP_TO_FACE,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_target_select = (vc.obedit != NULL) ? SCE_SNAP_TARGET_NOT_ACTIVE :
|
||||
SCE_SNAP_TARGET_ALL,
|
||||
|
|
|
@ -394,7 +394,7 @@ static int insert_into_textbuf(Object *obedit, uintptr_t c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void text_update_edited(bContext *C, Object *obedit, int mode)
|
||||
static void text_update_edited(bContext *C, Object *obedit, const eEditFontMode mode)
|
||||
{
|
||||
Curve *cu = obedit->data;
|
||||
EditFont *ef = cu->editfont;
|
||||
|
|
|
@ -280,7 +280,7 @@ static int gizmo_move_modal(bContext *C,
|
|||
CTX_data_ensure_evaluated_depsgraph(C),
|
||||
region,
|
||||
CTX_wm_view3d(C),
|
||||
(SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
|
||||
(SCE_SNAP_TO_VERTEX | SCE_SNAP_TO_EDGE | SCE_SNAP_TO_FACE),
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_target_select = SCE_SNAP_TARGET_ALL,
|
||||
.edit_mode_type = SNAP_GEOM_EDIT,
|
||||
|
|
|
@ -266,7 +266,7 @@ static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2])
|
|||
ED_view3d_cursor_snap_data_update(snap_gizmo->snap_state, C, x, y);
|
||||
V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
|
||||
|
||||
if (snap_data->snap_elem != SCE_SNAP_MODE_NONE) {
|
||||
if (snap_data->snap_elem != SCE_SNAP_TO_NONE) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -201,7 +201,6 @@ static int select_alternate_exec(bContext *C, wmOperator *op)
|
|||
Scene *scene = CTX_data_scene(C);
|
||||
Object *object = CTX_data_active_object(C);
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
|
||||
eAttrDomain selection_domain = ED_grease_pencil_selection_domain_get(C);
|
||||
|
||||
grease_pencil.foreach_editable_drawing(
|
||||
scene->r.cfra, [&](int /*drawing_index*/, GreasePencilDrawing &drawing) {
|
||||
|
@ -223,7 +222,7 @@ static void GREASE_PENCIL_OT_select_alternate(wmOperatorType *ot)
|
|||
ot->description = "Select alternated points in strokes with already selected points";
|
||||
|
||||
ot->exec = select_alternate_exec;
|
||||
ot->poll = editable_grease_pencil_poll;
|
||||
ot->poll = editable_grease_pencil_point_selection_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_string_utf8_symbols.h"
|
||||
#include "BLI_sys_types.h" /* size_t */
|
||||
#include "BLI_utildefines.h"
|
||||
#include "UI_interface_icons.h"
|
||||
|
@ -87,7 +88,7 @@ typedef struct uiViewItemHandle uiViewItemHandle;
|
|||
|
||||
/* Separator for text in search menus (right pointing arrow).
|
||||
* keep in sync with `string_search.cc`. */
|
||||
#define UI_MENU_ARROW_SEP "\xe2\x96\xb8"
|
||||
#define UI_MENU_ARROW_SEP BLI_STR_UTF8_BLACK_RIGHT_POINTING_SMALL_TRIANGLE
|
||||
|
||||
/* names */
|
||||
#define UI_MAX_DRAW_STR 400
|
||||
|
@ -1937,7 +1938,7 @@ struct Panel *UI_panel_add_instanced(const struct bContext *C,
|
|||
*/
|
||||
void UI_panels_free_instanced(const struct bContext *C, struct ARegion *region);
|
||||
|
||||
#define INSTANCED_PANEL_UNIQUE_STR_LEN 16
|
||||
#define INSTANCED_PANEL_UNIQUE_STR_SIZE 16
|
||||
/**
|
||||
* Find a unique key to append to the #PanelType.idname for the lookup to the panel's #uiBlock.
|
||||
* Needed for instanced panels, where there can be multiple with the same type and identifier.
|
||||
|
|
|
@ -69,8 +69,8 @@ set(SRC
|
|||
interface_style.cc
|
||||
interface_template_asset_view.cc
|
||||
interface_template_attribute_search.cc
|
||||
interface_template_light_linking.cc
|
||||
interface_template_grease_pencil_layer_tree.cc
|
||||
interface_template_light_linking.cc
|
||||
interface_template_list.cc
|
||||
interface_template_search_menu.cc
|
||||
interface_template_search_operator.cc
|
||||
|
|
|
@ -79,12 +79,12 @@ void icon_draw_rect_input(
|
|||
icon_draw_rect_input_text(&rect, color, str, event_type > EVT_F9KEY ? 8.5f : 11.5f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_LEFTSHIFTKEY) { /* Right Shift has already been converted to left. */
|
||||
const char str[] = {0xe2, 0x87, 0xa7, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_UPWARDS_WHITE_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 16.0f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_LEFTCTRLKEY) { /* Right Shift has already been converted to left. */
|
||||
if (platform == MACOS) {
|
||||
const char str[] = {0xe2, 0x8c, 0x83, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_UP_ARROWHEAD;
|
||||
icon_draw_rect_input_text(&rect, color, str, 21.0f, -8.0f);
|
||||
}
|
||||
else {
|
||||
|
@ -93,7 +93,7 @@ void icon_draw_rect_input(
|
|||
}
|
||||
else if (event_type == EVT_LEFTALTKEY) { /* Right Alt has already been converted to left. */
|
||||
if (platform == MACOS) {
|
||||
const char str[] = {0xe2, 0x8c, 0xa5, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_OPTION_KEY;
|
||||
icon_draw_rect_input_text(&rect, color, str, 13.0f, 0.0f);
|
||||
}
|
||||
else {
|
||||
|
@ -102,11 +102,11 @@ void icon_draw_rect_input(
|
|||
}
|
||||
else if (event_type == EVT_OSKEY) {
|
||||
if (platform == MACOS) {
|
||||
const char str[] = {0xe2, 0x8c, 0x98, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_PLACE_OF_INTEREST_SIGN;
|
||||
icon_draw_rect_input_text(&rect, color, str, 16.0f, 0.0f);
|
||||
}
|
||||
else if (platform == MSWIN) {
|
||||
const char str[] = {0xe2, 0x9d, 0x96, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_BLACK_DIAMOND_MINUS_WHITE_X;
|
||||
icon_draw_rect_input_text(&rect, color, str, 16.0f, 0.0f);
|
||||
}
|
||||
else {
|
||||
|
@ -117,7 +117,7 @@ void icon_draw_rect_input(
|
|||
icon_draw_rect_input_text(&rect, color, "Del", 9.0f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_TABKEY) {
|
||||
const char str[] = {0xe2, 0xad, 0xbe, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_HORIZONTAL_TAB_KEY;
|
||||
icon_draw_rect_input_text(&rect, color, str, 18.0f, -1.5f);
|
||||
}
|
||||
else if (event_type == EVT_HOMEKEY) {
|
||||
|
@ -127,12 +127,12 @@ void icon_draw_rect_input(
|
|||
icon_draw_rect_input_text(&rect, color, "End", 8.0f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_RETKEY) {
|
||||
const char str[] = {0xe2, 0x8f, 0x8e, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_RETURN_SYMBOL;
|
||||
icon_draw_rect_input_text(&rect, color, str, 17.0f, -1.0f);
|
||||
}
|
||||
else if (event_type == EVT_ESCKEY) {
|
||||
if (platform == MACOS) {
|
||||
const char str[] = {0xe2, 0x8e, 0x8b, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_BROKEN_CIRCLE_WITH_NORTHWEST_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 21.0f, -1.0f);
|
||||
}
|
||||
else {
|
||||
|
@ -140,31 +140,31 @@ void icon_draw_rect_input(
|
|||
}
|
||||
}
|
||||
else if (event_type == EVT_PAGEUPKEY) {
|
||||
const char str[] = {'P', 0xe2, 0x86, 0x91, 0x0};
|
||||
const char str[] = "P" BLI_STR_UTF8_UPWARDS_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 12.0f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_PAGEDOWNKEY) {
|
||||
const char str[] = {'P', 0xe2, 0x86, 0x93, 0x0};
|
||||
const char str[] = "P" BLI_STR_UTF8_DOWNWARDS_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 12.0f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_LEFTARROWKEY) {
|
||||
const char str[] = {0xe2, 0x86, 0x90, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_LEFTWARDS_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 18.0f, -1.5f);
|
||||
}
|
||||
else if (event_type == EVT_UPARROWKEY) {
|
||||
const char str[] = {0xe2, 0x86, 0x91, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_UPWARDS_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 16.0f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_RIGHTARROWKEY) {
|
||||
const char str[] = {0xe2, 0x86, 0x92, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_RIGHTWARDS_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 18.0f, -1.5f);
|
||||
}
|
||||
else if (event_type == EVT_DOWNARROWKEY) {
|
||||
const char str[] = {0xe2, 0x86, 0x93, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_DOWNWARDS_ARROW;
|
||||
icon_draw_rect_input_text(&rect, color, str, 16.0f, 0.0f);
|
||||
}
|
||||
else if (event_type == EVT_SPACEKEY) {
|
||||
const char str[] = {0xe2, 0x90, 0xa3, 0x0};
|
||||
const char str[] = BLI_STR_UTF8_OPEN_BOX;
|
||||
icon_draw_rect_input_text(&rect, color, str, 20.0f, 2.0f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -283,7 +283,7 @@ void UI_list_panel_unique_str(Panel *panel, char *r_name)
|
|||
{
|
||||
/* The panel sort-order will be unique for a specific panel type because the instanced
|
||||
* panel list is regenerated for every change in the data order / length. */
|
||||
BLI_snprintf(r_name, INSTANCED_PANEL_UNIQUE_STR_LEN, "%d", panel->sortorder);
|
||||
BLI_snprintf(r_name, INSTANCED_PANEL_UNIQUE_STR_SIZE, "%d", panel->sortorder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1538,8 +1538,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
|
|||
float strwidth = BLF_width(fstyle->uifont_id, str, max_len);
|
||||
|
||||
if ((okwidth > 0.0f) && (strwidth > okwidth)) {
|
||||
/* Ellipsis. Some compilers complain with real literal string. */
|
||||
const char sep[] = {0xe2, 0x80, 0xA6, 0x0};
|
||||
const char sep[] = BLI_STR_UTF8_HORIZONTAL_ELLIPSIS;
|
||||
const int sep_len = sizeof(sep) - 1;
|
||||
const float sep_strwidth = BLF_width(fstyle->uifont_id, sep, sep_len + 1);
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ static int wm_ply_import_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
return WM_operator_filesel(C, op, event);
|
||||
}
|
||||
|
||||
static int wm_ply_import_execute(bContext *C, wmOperator *op)
|
||||
static int wm_ply_import_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PLYImportParams params{};
|
||||
params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
|
||||
|
@ -283,7 +283,7 @@ void WM_OT_ply_import(wmOperatorType *ot)
|
|||
ot->idname = "WM_OT_ply_import";
|
||||
|
||||
ot->invoke = wm_ply_import_invoke;
|
||||
ot->exec = wm_ply_import_execute;
|
||||
ot->exec = wm_ply_import_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ static int wm_stl_import_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
return WM_operator_filesel(C, op, event);
|
||||
}
|
||||
|
||||
static int wm_stl_import_execute(bContext *C, wmOperator *op)
|
||||
static int wm_stl_import_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
STLImportParams params{};
|
||||
params.forward_axis = eIOAxis(RNA_enum_get(op->ptr, "forward_axis"));
|
||||
|
@ -95,7 +95,7 @@ void WM_OT_stl_import(wmOperatorType *ot)
|
|||
ot->idname = "WM_OT_stl_import";
|
||||
|
||||
ot->invoke = wm_stl_import_invoke;
|
||||
ot->exec = wm_stl_import_execute;
|
||||
ot->exec = wm_stl_import_exec;
|
||||
ot->poll = WM_operator_winactive;
|
||||
ot->check = wm_stl_import_check;
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
|
||||
|
|
|
@ -710,7 +710,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
|
|||
|
||||
const bool rot_src = RNA_boolean_get(op->ptr, "rotate_source");
|
||||
const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) &&
|
||||
(vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE));
|
||||
(vc.scene->toolsettings->snap_mode == SCE_SNAP_TO_FACE));
|
||||
|
||||
/* First calculate the center of transformation. */
|
||||
zero_v3(center);
|
||||
|
|
|
@ -1951,7 +1951,7 @@ void EDBM_project_snap_verts(
|
|||
depsgraph,
|
||||
region,
|
||||
CTX_wm_view3d(C),
|
||||
SCE_SNAP_MODE_FACE,
|
||||
SCE_SNAP_TO_FACE,
|
||||
¶ms,
|
||||
nullptr,
|
||||
mval,
|
||||
|
|
|
@ -362,7 +362,7 @@ static void bake_simulation_job_endjob(void *customdata)
|
|||
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, nullptr);
|
||||
}
|
||||
|
||||
static int bake_simulation_execute(bContext *C, wmOperator *op)
|
||||
static int bake_simulation_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
@ -556,7 +556,7 @@ static int bake_simulation_invoke(bContext *C, wmOperator *op, const wmEvent * /
|
|||
if (has_existing_bake_data) {
|
||||
return WM_operator_confirm_message(C, op, "Overwrite existing bake data");
|
||||
}
|
||||
return bake_simulation_execute(C, op);
|
||||
return bake_simulation_exec(C, op);
|
||||
}
|
||||
|
||||
static int bake_simulation_modal(bContext *C, wmOperator * /*op*/, const wmEvent * /*event*/)
|
||||
|
@ -647,7 +647,7 @@ void OBJECT_OT_simulation_nodes_cache_bake(wmOperatorType *ot)
|
|||
ot->description = "Bake simulations in geometry nodes modifiers";
|
||||
ot->idname = __func__;
|
||||
|
||||
ot->exec = bake_simulation_execute;
|
||||
ot->exec = bake_simulation_exec;
|
||||
ot->invoke = bake_simulation_invoke;
|
||||
ot->modal = bake_simulation_modal;
|
||||
ot->poll = bake_simulation_poll;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_timecode.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -402,17 +403,25 @@ static void render_freejob(void *rjv)
|
|||
MEM_freeN(rj);
|
||||
}
|
||||
|
||||
/* str is IMA_MAX_RENDER_TEXT in size */
|
||||
static void make_renderinfo_string(const RenderStats *rs,
|
||||
const Scene *scene,
|
||||
const bool v3d_override,
|
||||
const char *error,
|
||||
char *str)
|
||||
char ret[IMA_MAX_RENDER_TEXT])
|
||||
{
|
||||
char info_time_str[32]; /* used to be extern to header_info.c */
|
||||
const char *info_space = " ";
|
||||
const char *info_sep = "| ";
|
||||
struct {
|
||||
char time_last[32];
|
||||
char time_elapsed[32];
|
||||
char frame[16];
|
||||
char statistics[64];
|
||||
} info_buffers;
|
||||
|
||||
uintptr_t mem_in_use, peak_memory;
|
||||
float megs_used_memory, megs_peak_memory;
|
||||
char *spos = str;
|
||||
const char *ret_array[32];
|
||||
int i = 0;
|
||||
|
||||
mem_in_use = MEM_get_memory_in_use();
|
||||
peak_memory = MEM_get_peak_memory();
|
||||
|
@ -422,65 +431,96 @@ static void make_renderinfo_string(const RenderStats *rs,
|
|||
|
||||
/* local view */
|
||||
if (rs->localview) {
|
||||
spos += BLI_sprintf(spos, "%s | ", TIP_("3D Local View"));
|
||||
ret_array[i++] = TIP_("3D Local View ");
|
||||
ret_array[i++] = info_sep;
|
||||
}
|
||||
else if (v3d_override) {
|
||||
spos += BLI_sprintf(spos, "%s | ", TIP_("3D View"));
|
||||
ret_array[i++] = TIP_("3D View ");
|
||||
ret_array[i++] = info_sep;
|
||||
}
|
||||
|
||||
/* frame number */
|
||||
spos += BLI_sprintf(spos, TIP_("Frame:%d "), (scene->r.cfra));
|
||||
SNPRINTF(info_buffers.frame, "%d ", scene->r.cfra);
|
||||
ret_array[i++] = TIP_("Frame:");
|
||||
ret_array[i++] = info_buffers.frame;
|
||||
|
||||
/* previous and elapsed time */
|
||||
BLI_timecode_string_from_time_simple(info_time_str, sizeof(info_time_str), rs->lastframetime);
|
||||
/* Previous and elapsed time. */
|
||||
const char *info_time = info_buffers.time_last;
|
||||
BLI_timecode_string_from_time_simple(
|
||||
info_buffers.time_last, sizeof(info_buffers.time_last), rs->lastframetime);
|
||||
|
||||
ret_array[i++] = info_sep;
|
||||
if (rs->infostr && rs->infostr[0]) {
|
||||
if (rs->lastframetime != 0.0) {
|
||||
spos += BLI_sprintf(spos, TIP_("| Last:%s "), info_time_str);
|
||||
ret_array[i++] = "Last:";
|
||||
ret_array[i++] = info_buffers.time_last;
|
||||
ret_array[i++] = info_space;
|
||||
}
|
||||
|
||||
info_time = info_buffers.time_elapsed;
|
||||
BLI_timecode_string_from_time_simple(info_buffers.time_elapsed,
|
||||
sizeof(info_buffers.time_elapsed),
|
||||
PIL_check_seconds_timer() - rs->starttime);
|
||||
}
|
||||
|
||||
ret_array[i++] = TIP_("Time:");
|
||||
ret_array[i++] = info_time;
|
||||
ret_array[i++] = info_space;
|
||||
|
||||
/* Statistics. */
|
||||
{
|
||||
const char *info_statistics = nullptr;
|
||||
if (rs->statstr) {
|
||||
if (rs->statstr[0]) {
|
||||
info_statistics = rs->statstr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
spos += BLI_sprintf(spos, "| ");
|
||||
if (rs->mem_peak == 0.0f) {
|
||||
SNPRINTF(info_buffers.statistics,
|
||||
TIP_("Mem:%.2fM (Peak %.2fM)"),
|
||||
megs_used_memory,
|
||||
megs_peak_memory);
|
||||
}
|
||||
else {
|
||||
SNPRINTF(
|
||||
info_buffers.statistics, TIP_("Mem:%.2fM, Peak: %.2fM"), rs->mem_used, rs->mem_peak);
|
||||
}
|
||||
info_statistics = info_buffers.statistics;
|
||||
}
|
||||
|
||||
BLI_timecode_string_from_time_simple(
|
||||
info_time_str, sizeof(info_time_str), PIL_check_seconds_timer() - rs->starttime);
|
||||
}
|
||||
else {
|
||||
spos += BLI_sprintf(spos, "| ");
|
||||
}
|
||||
|
||||
spos += BLI_sprintf(spos, TIP_("Time:%s "), info_time_str);
|
||||
|
||||
/* statistics */
|
||||
if (rs->statstr) {
|
||||
if (rs->statstr[0]) {
|
||||
spos += BLI_sprintf(spos, "| %s ", rs->statstr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rs->mem_peak == 0.0f) {
|
||||
spos += BLI_sprintf(
|
||||
spos, TIP_("| Mem:%.2fM (Peak %.2fM) "), megs_used_memory, megs_peak_memory);
|
||||
}
|
||||
else {
|
||||
spos += BLI_sprintf(spos, TIP_("| Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak);
|
||||
if (info_statistics) {
|
||||
ret_array[i++] = info_sep;
|
||||
ret_array[i++] = info_statistics;
|
||||
ret_array[i++] = info_space;
|
||||
}
|
||||
}
|
||||
|
||||
/* extra info */
|
||||
if (rs->infostr && rs->infostr[0]) {
|
||||
spos += BLI_sprintf(spos, "| %s ", rs->infostr);
|
||||
}
|
||||
else if (error && error[0]) {
|
||||
spos += BLI_sprintf(spos, "| %s ", error);
|
||||
/* Extra info. */
|
||||
{
|
||||
const char *info_extra = nullptr;
|
||||
if (rs->infostr && rs->infostr[0]) {
|
||||
info_extra = rs->infostr;
|
||||
}
|
||||
else if (error && error[0]) {
|
||||
info_extra = error;
|
||||
}
|
||||
|
||||
if (info_extra) {
|
||||
ret_array[i++] = info_sep;
|
||||
ret_array[i++] = info_extra;
|
||||
ret_array[i++] = info_space;
|
||||
}
|
||||
}
|
||||
|
||||
/* very weak... but 512 characters is quite safe */
|
||||
if (spos >= str + IMA_MAX_RENDER_TEXT) {
|
||||
if (G.debug & G_DEBUG) {
|
||||
if (G.debug & G_DEBUG) {
|
||||
if (BLI_string_len_array(ret_array, i) >= IMA_MAX_RENDER_TEXT) {
|
||||
printf("WARNING! renderwin text beyond limit\n");
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert(i < int(BOUNDED_ARRAY_TYPE_SIZE<decltype(ret_array)>()));
|
||||
BLI_string_join_array(ret, IMA_MAX_RENDER_TEXT, ret_array, i);
|
||||
}
|
||||
|
||||
static void image_renderinfo_cb(void *rjv, RenderStats *rs)
|
||||
|
@ -1088,7 +1128,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
RE_current_scene_update_cb(re, rj, current_scene_update);
|
||||
RE_stats_draw_cb(re, rj, image_renderinfo_cb);
|
||||
RE_progress_cb(re, rj, render_progress_update);
|
||||
RE_system_gpu_context_create(re);
|
||||
RE_system_gpu_context_ensure(re);
|
||||
|
||||
rj->re = re;
|
||||
G.is_break = false;
|
||||
|
|
|
@ -2695,7 +2695,7 @@ static void ed_panel_draw(const bContext *C,
|
|||
const uiStyle *style = UI_style_get_dpi();
|
||||
|
||||
/* Draw panel. */
|
||||
char block_name[BKE_ST_MAXNAME + INSTANCED_PANEL_UNIQUE_STR_LEN];
|
||||
char block_name[BKE_ST_MAXNAME + INSTANCED_PANEL_UNIQUE_STR_SIZE];
|
||||
if (unique_panel_str) {
|
||||
/* Instanced panels should have already been added at this point. */
|
||||
BLI_string_join(block_name, sizeof(block_name), pt->idname, unique_panel_str);
|
||||
|
@ -3019,7 +3019,7 @@ void ED_region_panels_layout_ex(const bContext *C,
|
|||
|
||||
/* Use a unique identifier for instanced panels, otherwise an old block for a different
|
||||
* panel of the same type might be found. */
|
||||
char unique_panel_str[INSTANCED_PANEL_UNIQUE_STR_LEN];
|
||||
char unique_panel_str[INSTANCED_PANEL_UNIQUE_STR_SIZE];
|
||||
UI_list_panel_unique_str(panel, unique_panel_str);
|
||||
ed_panel_draw(C,
|
||||
region,
|
||||
|
|
|
@ -451,9 +451,13 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf,
|
|||
immDrawPixelsTexSetupAttributes(&state);
|
||||
|
||||
if (ibuf->float_buffer.data) {
|
||||
if (ibuf->float_colorspace) {
|
||||
ok = IMB_colormanagement_setup_glsl_draw_from_space(
|
||||
view_settings, display_settings, ibuf->float_colorspace, ibuf->dither, true, false);
|
||||
if (ibuf->float_buffer.colorspace) {
|
||||
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings,
|
||||
display_settings,
|
||||
ibuf->float_buffer.colorspace,
|
||||
ibuf->dither,
|
||||
true,
|
||||
false);
|
||||
}
|
||||
else {
|
||||
ok = IMB_colormanagement_setup_glsl_draw(
|
||||
|
@ -461,8 +465,12 @@ void ED_draw_imbuf_clipping(ImBuf *ibuf,
|
|||
}
|
||||
}
|
||||
else {
|
||||
ok = IMB_colormanagement_setup_glsl_draw_from_space(
|
||||
view_settings, display_settings, ibuf->rect_colorspace, ibuf->dither, false, false);
|
||||
ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings,
|
||||
display_settings,
|
||||
ibuf->byte_buffer.colorspace,
|
||||
ibuf->dither,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
|
|
|
@ -167,7 +167,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata,
|
|||
/* For consistency, sampling always returns color in linear space. */
|
||||
if (tex_ibuf && tex_ibuf->float_buffer.data == nullptr) {
|
||||
convert_to_linear = true;
|
||||
colorspace = tex_ibuf->rect_colorspace;
|
||||
colorspace = tex_ibuf->byte_buffer.colorspace;
|
||||
}
|
||||
BKE_image_pool_release_ibuf(mtex->tex->ima, tex_ibuf, pool);
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ static bool paint_brush_update(bContext *C,
|
|||
brush->mtex.tex->ima, &brush->mtex.tex->iuser, nullptr);
|
||||
if (tex_ibuf && tex_ibuf->float_buffer.data == nullptr) {
|
||||
ups->do_linear_conversion = true;
|
||||
ups->colorspace = tex_ibuf->rect_colorspace;
|
||||
ups->colorspace = tex_ibuf->byte_buffer.colorspace;
|
||||
}
|
||||
BKE_image_pool_release_ibuf(brush->mtex.tex->ima, tex_ibuf, nullptr);
|
||||
}
|
||||
|
|
|
@ -332,7 +332,7 @@ bool ED_space_clip_color_sample(const SpaceClip *sc,
|
|||
else if (ibuf->byte_buffer.data) {
|
||||
cp = ibuf->byte_buffer.data + 4 * (y * ibuf->x + x);
|
||||
rgb_uchar_to_float(r_col, cp);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->rect_colorspace);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->byte_buffer.colorspace);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -301,7 +301,7 @@ void AssetCatalogTreeViewItem::build_context_menu(bContext &C, uiLayout &column)
|
|||
&props);
|
||||
RNA_string_set(&props, "parent_path", catalog_item_.catalog_path().c_str());
|
||||
|
||||
char catalog_id_str_buffer[UUID_STRING_LEN] = "";
|
||||
char catalog_id_str_buffer[UUID_STRING_SIZE] = "";
|
||||
BLI_uuid_format(catalog_id_str_buffer, catalog_item_.get_catalog_id());
|
||||
uiItemFullO(&column,
|
||||
"ASSET_OT_catalog_delete",
|
||||
|
|
|
@ -3377,7 +3377,7 @@ bool ED_space_image_color_sample(
|
|||
else if (ibuf->byte_buffer.data) {
|
||||
cp = ibuf->byte_buffer.data + 4 * (y * ibuf->x + x);
|
||||
rgb_uchar_to_float(r_col, cp);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->rect_colorspace);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->byte_buffer.colorspace);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "NOD_composite.h"
|
||||
#include "NOD_geometry.h"
|
||||
#include "NOD_geometry.hh"
|
||||
#include "NOD_node_declaration.hh"
|
||||
#include "NOD_shader.h"
|
||||
#include "NOD_texture.h"
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
#include "IMB_imbuf_types.h"
|
||||
|
||||
#include "NOD_composite.h"
|
||||
#include "NOD_geometry.h"
|
||||
#include "NOD_geometry.hh"
|
||||
#include "NOD_shader.h"
|
||||
#include "NOD_socket.h"
|
||||
#include "NOD_texture.h"
|
||||
|
@ -250,7 +250,7 @@ static void compo_initjob(void *cjv)
|
|||
}
|
||||
|
||||
cj->re = RE_NewSceneRender(scene);
|
||||
RE_system_gpu_context_create(cj->re);
|
||||
RE_system_gpu_context_ensure(cj->re);
|
||||
}
|
||||
|
||||
/* Called before redraw notifiers, it moves finished previews over. */
|
||||
|
@ -309,8 +309,6 @@ static void compo_startjob(void *cjv,
|
|||
}
|
||||
}
|
||||
|
||||
RE_system_gpu_context_destroy(cj->re);
|
||||
|
||||
ntree->runtime->test_break = nullptr;
|
||||
ntree->runtime->stats_draw = nullptr;
|
||||
ntree->runtime->progress = nullptr;
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
#include "NOD_common.h"
|
||||
#include "NOD_composite.h"
|
||||
#include "NOD_geometry.h"
|
||||
#include "NOD_geometry.hh"
|
||||
#include "NOD_shader.h"
|
||||
#include "NOD_socket.h"
|
||||
#include "NOD_texture.h"
|
||||
|
|
|
@ -520,7 +520,7 @@ bool ED_space_node_color_sample(
|
|||
else if (ibuf->byte_buffer.data) {
|
||||
cp = ibuf->byte_buffer.data + 4 * (y * ibuf->x + x);
|
||||
rgb_uchar_to_float(r_col, cp);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->rect_colorspace);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(r_col, ibuf->byte_buffer.colorspace);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -593,7 +593,7 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
copy_v4_v4(info->linearcol, info->colf);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v4(
|
||||
info->linearcol, false, ibuf->rect_colorspace);
|
||||
info->linearcol, false, ibuf->byte_buffer.colorspace);
|
||||
|
||||
info->color_manage = true;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue