From be32882e1c40eb1cb72deab0bb6ee54fff917ca2 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 18 Oct 2022 15:57:47 -0500 Subject: Fix T101883: Issue applying modifier to mesh with shape keys Caused by 21f2bacad977d3fd83d which misunderstood the logic handling shape keys in this function. The shape key on the original mesh in the main data-base should be cleared if the "no-main" mesh doesn't have any shape key layers and the vertex count has changed. The complexity is necessary because shape keys are stored differently on original and evaluated meshes. Also change to "Warn" because this is expected behavior in some cases, like when applying a geometry nodes modifier that creates a new mesh from scratch. --- source/blender/blenkernel/intern/mesh_convert.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 027423f5774..784d35a8d65 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -1313,6 +1313,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob) CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly); CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop); + const bool verts_num_changed = mesh_dst->totvert != mesh_src->totvert; mesh_dst->totvert = mesh_src->totvert; mesh_dst->totedge = mesh_src->totedge; mesh_dst->totpoly = mesh_src->totpoly; @@ -1339,11 +1340,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob) const int uid_active = ob ? find_object_active_key_uid(*key_dst, *ob) : -1; move_shapekey_layers_to_keyblocks(*mesh_dst, mesh_src->vdata, *key_dst, uid_active); } - else if (mesh_src->totvert != mesh_dst->totvert) { - CLOG_ERROR(&LOG, "Mesh in Main '%s' lost shape keys", mesh_src->id.name); - if (mesh_src->key) { - id_us_min(&mesh_src->key->id); - } + else if (verts_num_changed) { + CLOG_WARN(&LOG, "Shape key data lost when replacing mesh '%s' in Main", mesh_src->id.name); + id_us_min(&mesh_dst->key->id); + mesh_dst->key = nullptr; } } -- cgit v1.2.3 From 8115d30dcaddeb399ea9a557694788b03505b2bd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:52:54 +1100 Subject: License headers: add missing license identifiers --- source/blender/gpu/metal/mtl_batch.mm | 1 + source/blender/gpu/metal/mtl_drawlist.mm | 2 ++ 2 files changed, 3 insertions(+) diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm index e9804d4be77..3961e7a71a0 100644 --- a/source/blender/gpu/metal/mtl_batch.mm +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup gpu diff --git a/source/blender/gpu/metal/mtl_drawlist.mm b/source/blender/gpu/metal/mtl_drawlist.mm index 76e2abb4ea6..dc3e4665dcf 100644 --- a/source/blender/gpu/metal/mtl_drawlist.mm +++ b/source/blender/gpu/metal/mtl_drawlist.mm @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + /** \file * \ingroup gpu * -- cgit v1.2.3 From 8aca40652a5729895f1ba6efd2d03829785ae43f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:52:55 +1100 Subject: Cleanup: spelling in comments --- source/blender/blenkernel/BKE_instances.hh | 2 +- source/blender/blenkernel/intern/instances.cc | 2 +- source/blender/blenkernel/intern/volume.cc | 4 ++-- .../depsgraph/intern/builder/deg_builder_nodes.cc | 4 ++-- source/blender/gpu/metal/mtl_batch.mm | 20 ++++++++++---------- source/blender/gpu/metal/mtl_drawlist.mm | 12 ++++++------ source/blender/gpu/metal/mtl_texture.mm | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh index 6502fefec88..f17ebba0dfa 100644 --- a/source/blender/blenkernel/BKE_instances.hh +++ b/source/blender/blenkernel/BKE_instances.hh @@ -5,7 +5,7 @@ /** \file * \ingroup bke * - * #Instances is a container for geometry instances. It fullfills some key requirements: + * #Instances is a container for geometry instances. It fulfills some key requirements: * - Support nested instances. * - Support instance attributes. * - Support referencing different kinds of instances (objects, collections, geometry sets). diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc index dd759453630..2f8acf477e2 100644 --- a/source/blender/blenkernel/intern/instances.cc +++ b/source/blender/blenkernel/intern/instances.cc @@ -266,7 +266,7 @@ bool Instances::owns_direct_data() const void Instances::ensure_owns_direct_data() { for (const InstanceReference &const_reference : references_) { - /* Const cast is fine because we are not changing anything that would change the hash of the + /* `const` cast is fine because we are not changing anything that would change the hash of the * reference. */ InstanceReference &reference = const_cast(const_reference); reference.ensure_owns_direct_data(); diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 7c54b4d3f2f..e81657f9ef0 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -445,7 +445,7 @@ struct VolumeGrid { * may actually be loaded by another user while this is false. But only after * calling load() and is_loaded changes to true is it safe to access. * - * Const write access to this must be protected by `entry->mutex`. + * `const` write access to this must be protected by `entry->mutex`. */ mutable bool is_loaded; }; @@ -480,7 +480,7 @@ struct VolumeGridVector : public std::list { metadata.reset(); } - /* Mutex for file loading of grids list. Const write access to the fields after this must be + /* Mutex for file loading of grids list. `const` write access to the fields after this must be * protected by locking with this mutex. */ mutable std::mutex mutex; /* Absolute file path that grids have been loaded from. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 6cb0b985d3d..c84852788fd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -454,8 +454,8 @@ static int foreach_id_cow_detect_need_for_update_callback(LibraryIDLinkCallbackD return IDWALK_RET_NOP; } if (!ID_TYPE_IS_COW(GS(id->name))) { - /* No need to go further if thte id never had a cow copy in the depsgraph. This function is - * only concerned with keeping the mapping between original and cow ids intact. */ + /* No need to go further if the id never had a cow copy in the depsgraph. This function is + * only concerned with keeping the mapping between original and COW ids intact. */ return IDWALK_RET_NOP; } diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm index 3961e7a71a0..0d9a3225a51 100644 --- a/source/blender/gpu/metal/mtl_batch.mm +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -69,7 +69,7 @@ void MTLBatch::MTLVertexDescriptorCache::vertex_descriptor_cache_ensure() } } - /* Initialise cache if not ready. */ + /* Initialize cache if not ready. */ if (cache_context_ == nullptr) { this->vertex_descriptor_cache_init(MTLContext::get()); } @@ -189,7 +189,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts, buffer_stride); } else { - /* Ensure stride is correct for de-interlevaed attributes. */ + /* Ensure stride is correct for de-interleaved attributes. */ desc.vertex_descriptor.buffer_layouts[buffer_index].stride = buffer_stride; } @@ -279,7 +279,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts, * elements). * * Certain conversion cannot be performed however, and in these cases, we need to - * instruct the shader to generate a specialised version with a conversion routine upon + * instruct the shader to generate a specialized version with a conversion routine upon * attribute read. * - This handles cases such as conversion between types e.g. Integer to float without * normalization. @@ -311,7 +311,7 @@ int MTLBatch::prepare_vertex_binding(MTLVertBuf *verts, * This then controls how a given attribute is interpreted. The data will be read * as specified and then converted appropriately to the correct form. * - * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialised read-routine + * e.g. if `GPU_FETCH_INT_TO_FLOAT` is specified, the specialized read-routine * in the shader will read the data as an int, and cast this to floating point * representation. (Rather than reading the source data as float). * @@ -404,7 +404,7 @@ id MTLBatch::bind(uint v_first, uint v_count, uint i_fi active_shader_ = (shader) ? static_cast(unwrap(shader)) : nullptr; if (active_shader_ == nullptr || !active_shader_->is_valid()) { - /* Skip drawing if there is no vaid Metal shader. + /* Skip drawing if there is no valid Metal shader. * This will occur if the path through which the shader is prepared * is invalid (e.g. Python without create-info), or, the source shader uses a geometry pass. */ BLI_assert_msg(false, "No valid Metal shader!"); @@ -456,7 +456,7 @@ id MTLBatch::bind(uint v_first, uint v_count, uint i_fi /* Fetch RenderPassState to enable resource binding for active pass. */ MTLRenderPassState &rps = ctx->main_command_buffer.get_render_pass_state(); - /* Debug Check: Ensure Framebuffer instance is not dirty. */ + /* Debug Check: Ensure Frame-buffer instance is not dirty. */ BLI_assert(!ctx->main_command_buffer.get_active_framebuffer()->get_dirty()); /* Bind Shader. */ @@ -496,8 +496,8 @@ id MTLBatch::bind(uint v_first, uint v_count, uint i_fi if (mtl_elem != nullptr) { - /* Fetch index buffer. This function can situationally return an optimised - * index buffer of a different primtiive type. If this is the case, `final_prim_type` + /* Fetch index buffer. This function can situationally return an optimized + * index buffer of a different primitive type. If this is the case, `final_prim_type` * and `v_count` will be updated with the new format. * NOTE: For indexed rendering, v_count represents the number of indices. */ idx_buffer = mtl_elem->get_index_buffer(final_prim_type, v_count); @@ -672,7 +672,7 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings( } } - /* Extract Vertex attribues (First-bound vertex buffer takes priority). */ + /* Extract Vertex attributes (First-bound vertex buffer takes priority). */ for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) { if (mtl_verts[v] != NULL) { MTL_LOG_INFO(" -- [Batch] Checking bindings for bound vertex buffer %p\n", mtl_verts[v]); @@ -830,7 +830,7 @@ void MTLBatch::draw_advanced(int v_first, int v_count, int i_first, int i_count) "Index offset is not 2/4-byte aligned as per METAL spec"); /* Fetch index buffer. May return an index buffer of a differing format, - * if index buffer optimisation is used. In these cases, final_prim_type and + * if index buffer optimization is used. In these cases, final_prim_type and * index_count get updated with the new properties. */ GPUPrimType final_prim_type = this->prim_type; uint index_count = v_count; diff --git a/source/blender/gpu/metal/mtl_drawlist.mm b/source/blender/gpu/metal/mtl_drawlist.mm index dc3e4665dcf..99194d2b72c 100644 --- a/source/blender/gpu/metal/mtl_drawlist.mm +++ b/source/blender/gpu/metal/mtl_drawlist.mm @@ -153,7 +153,7 @@ void MTLDrawList::submit() { /* Metal does not support MDI from the host side, but we still benefit from only executing the * batch bind a single time, rather than per-draw. - * NOTE(Metal): Consider using MTLIndirectCommandBuffer to achieve similar behaviour. */ + * NOTE(Metal): Consider using #MTLIndirectCommandBuffer to achieve similar behavior. */ if (command_len_ == 0) { return; } @@ -194,12 +194,12 @@ void MTLDrawList::submit() /* Common properties. */ MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(batch_->prim_type); - /* Execute multidraw indirect. */ + /* Execute multi-draw indirect. */ if (can_use_MDI && false) { /* Metal Doesn't support MDI -- Singular Indirect draw calls are supported, - * but Multidraw is not. - * TODO(Metal): Consider using IndirectCommandBuffers to provide similar - * behaviour. */ + * but Multi-draw is not. + * TODO(Metal): Consider using #IndirectCommandBuffers to provide similar + * behavior. */ } else { @@ -216,7 +216,7 @@ void MTLDrawList::submit() uint32_t index_count = cmd->indexCount; /* Fetch index buffer. May return an index buffer of a differing format, - * if index buffer optimisation is used. In these cases, mtl_prim_type and + * if index buffer optimization is used. In these cases, mtl_prim_type and * index_count get updated with the new properties. */ GPUPrimType final_prim_type = batch_->prim_type; id index_buffer = mtl_elem->get_index_buffer(final_prim_type, index_count); diff --git a/source/blender/gpu/metal/mtl_texture.mm b/source/blender/gpu/metal/mtl_texture.mm index 4931f8a4f52..29dcc8d32ee 100644 --- a/source/blender/gpu/metal/mtl_texture.mm +++ b/source/blender/gpu/metal/mtl_texture.mm @@ -1510,7 +1510,7 @@ bool gpu::MTLTexture::init_internal(GPUVertBuf *vbo) texture_descriptor_.mipmapLevelCount = mtl_max_mips_; texture_descriptor_.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite | - MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimise usage flags. */ + MTLTextureUsagePixelFormatView; /* TODO(Metal): Optimize usage flags. */ texture_descriptor_.storageMode = [source_buffer storageMode]; texture_descriptor_.sampleCount = 1; texture_descriptor_.cpuCacheMode = [source_buffer cpuCacheMode]; -- cgit v1.2.3 From ecda118be407163096641db36b6ee8bf1d88ee55 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:52:58 +1100 Subject: Fix T101866: Incorrect buttons for space-mouse enterprise Use key from spacenavd's wiki. Also add keys: ENTER, DELETE, TAB, SPACE & Views 1-3. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 67 ++++++++++++++++++++++++--- intern/ghost/intern/GHOST_NDOFManager.h | 18 +++++-- source/blender/makesrna/intern/rna_wm.c | 22 ++++++--- source/blender/windowmanager/wm_event_types.h | 51 +++++++++++--------- 4 files changed, 118 insertions(+), 40 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index f4c726c7450..2754b9c8a6f 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -53,11 +53,6 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_DOMINANT", "NDOF_BUTTON_PLUS", "NDOF_BUTTON_MINUS", - /* keyboard emulation */ - "NDOF_BUTTON_ESC", - "NDOF_BUTTON_ALT", - "NDOF_BUTTON_SHIFT", - "NDOF_BUTTON_CTRL", /* general-purpose buttons */ "NDOF_BUTTON_1", "NDOF_BUTTON_2", @@ -73,6 +68,19 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_A", "NDOF_BUTTON_B", "NDOF_BUTTON_C", + /* Stored views. */ + "NDOF_BUTTON_V1", + "NDOF_BUTTON_V2", + "NDOF_BUTTON_V3", + /* Keyboard emulation. */ + "NDOF_BUTTON_ESC", + "NDOF_BUTTON_ENTER", + "NDOF_BUTTON_DELETE", + "NDOF_BUTTON_TAB", + "NDOF_BUTTON_SPACE", + "NDOF_BUTTON_ALT", + "NDOF_BUTTON_SHIFT", + "NDOF_BUTTON_CTRL", /* the end */ "NDOF_BUTTON_LAST", }; @@ -134,6 +142,41 @@ static const NDOF_ButtonT Generic_HID_map[] = { NDOF_BUTTON_C, }; +/* Values taken from: https://github.com/FreeSpacenav/spacenavd/wiki/Device-button-names */ +static const NDOF_ButtonT SpaceMouseEnterprise_HID_map[] = { + NDOF_BUTTON_1, /* (0) */ + NDOF_BUTTON_2, /* (1) */ + NDOF_BUTTON_3, /* (2) */ + NDOF_BUTTON_4, /* (3) */ + NDOF_BUTTON_5, /* (4) */ + NDOF_BUTTON_6, /* (5) */ + NDOF_BUTTON_7, /* (6) */ + NDOF_BUTTON_8, /* (7) */ + NDOF_BUTTON_9, /* (8) */ + NDOF_BUTTON_A, /* Labeled "10" (9). */ + NDOF_BUTTON_B, /* Labeled "11" (10). */ + NDOF_BUTTON_C, /* Labeled "12" (11). */ + NDOF_BUTTON_MENU, /* (12). */ + NDOF_BUTTON_FIT, /* (13). */ + NDOF_BUTTON_TOP, /* (14). */ + NDOF_BUTTON_RIGHT, /* (15). */ + NDOF_BUTTON_FRONT, /* (16). */ + NDOF_BUTTON_ROLL_CW, /* (17). */ + NDOF_BUTTON_ESC, /* (18). */ + NDOF_BUTTON_ALT, /* (19). */ + NDOF_BUTTON_SHIFT, /* (20). */ + NDOF_BUTTON_CTRL, /* (21). */ + NDOF_BUTTON_ROTATE, /* Labeled "Lock Rotate" (22). */ + NDOF_BUTTON_ENTER, /* Labeled "Enter" (23). */ + NDOF_BUTTON_DELETE, /* (24). */ + NDOF_BUTTON_TAB, /* (25). */ + NDOF_BUTTON_SPACE, /* (26). */ + NDOF_BUTTON_V1, /* Labeled "V1" (27). */ + NDOF_BUTTON_V2, /* Labeled "V2" (28). */ + NDOF_BUTTON_V3, /* Labeled "V3" (29). */ + NDOF_BUTTON_ISO1, /* Labeled "ISO1" (30). */ +}; + static const int genericButtonCount = ARRAY_SIZE(Generic_HID_map); GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) @@ -257,7 +300,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) puts("ndof: using SpaceMouse Enterprise"); m_deviceType = NDOF_SpaceMouseEnterprise; m_buttonCount = 31; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = SpaceMouseEnterprise_HID_map; break; default: @@ -314,6 +357,18 @@ static GHOST_TKey ghost_map_keyboard_from_ndof_buttom(const NDOF_ButtonT button) case NDOF_BUTTON_ESC: { return GHOST_kKeyEsc; } + case NDOF_BUTTON_ENTER: { + return GHOST_kKeyEnter; + } + case NDOF_BUTTON_DELETE: { + return GHOST_kKeyDelete; + } + case NDOF_BUTTON_TAB: { + return GHOST_kKeyTab; + } + case NDOF_BUTTON_SPACE: { + return GHOST_kKeySpace; + } case NDOF_BUTTON_ALT: { return GHOST_kKeyLeftAlt; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 73c1b17f891..58371826527 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -58,11 +58,6 @@ typedef enum { NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS, - /* Keyboard emulation. */ - NDOF_BUTTON_ESC, - NDOF_BUTTON_ALT, - NDOF_BUTTON_SHIFT, - NDOF_BUTTON_CTRL, /* General-purpose buttons. * Users can assign functions via keymap editor. */ NDOF_BUTTON_1, @@ -79,6 +74,19 @@ typedef enum { NDOF_BUTTON_A, NDOF_BUTTON_B, NDOF_BUTTON_C, + /* Store Views. */ + NDOF_BUTTON_V1, + NDOF_BUTTON_V2, + NDOF_BUTTON_V3, + /* Keyboard emulation. */ + NDOF_BUTTON_ESC, + NDOF_BUTTON_ENTER, + NDOF_BUTTON_DELETE, + NDOF_BUTTON_TAB, + NDOF_BUTTON_SPACE, + NDOF_BUTTON_ALT, + NDOF_BUTTON_SHIFT, + NDOF_BUTTON_CTRL, /* The end. */ NDOF_BUTTON_LAST } NDOF_ButtonT; diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 5b5544120a1..eebe595820e 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -99,13 +99,6 @@ static const EnumPropertyItem event_ndof_type_items[] = { {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""}, {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""}, {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""}, -# if 0 /* Never used (converted to keyboard events by GHOST). */ - /* keyboard emulation */ - {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"}, - {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"}, - {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"}, - {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"}, -# endif /* general-purpose buttons */ {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""}, {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""}, @@ -120,6 +113,21 @@ static const EnumPropertyItem event_ndof_type_items[] = { {NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "Button A", ""}, {NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "Button B", ""}, {NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""}, + /* View buttons. */ + {NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "View 1", ""}, + {NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "View 2", ""}, + {NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "View 3", ""}, +# if 0 /* Never used (converted to keyboard events by GHOST). */ + /* keyboard emulation */ + {NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, "Esc"}, + {NDOF_BUTTON_ENTER, "NDOF_BUTTON_ENTER", 0, "Enter"}, + {NDOF_BUTTON_DELETE, "NDOF_BUTTON_DELETE", 0, "Delete"}, + {NDOF_BUTTON_TAB, "NDOF_BUTTON_TAB", 0, "Tab"}, + {NDOF_BUTTON_SPACE, "NDOF_BUTTON_SPACE", 0, "Space"}, + {NDOF_BUTTON_ALT, "NDOF_BUTTON_ALT", 0, "Alt"}, + {NDOF_BUTTON_SHIFT, "NDOF_BUTTON_SHIFT", 0, "Shift"}, + {NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "Ctrl"}, +# endif {0, NULL, 0, NULL, NULL}, }; #endif /* RNA_RUNTIME */ diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 405b7225bd5..10536a00501 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -281,35 +281,42 @@ enum { NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */ NDOF_BUTTON_PLUS = 0x01a4, /* 420 */ NDOF_BUTTON_MINUS = 0x01a5, /* 421 */ + /* General-purpose buttons. */ + NDOF_BUTTON_1 = 0x01a6, /* 422 */ + NDOF_BUTTON_2 = 0x01a7, /* 423 */ + NDOF_BUTTON_3 = 0x01a8, /* 424 */ + NDOF_BUTTON_4 = 0x01a9, /* 425 */ + NDOF_BUTTON_5 = 0x01aa, /* 426 */ + NDOF_BUTTON_6 = 0x01ab, /* 427 */ + NDOF_BUTTON_7 = 0x01ac, /* 428 */ + NDOF_BUTTON_8 = 0x01ad, /* 429 */ + NDOF_BUTTON_9 = 0x01ae, /* 430 */ + NDOF_BUTTON_10 = 0x01af, /* 431 */ + /* more general-purpose buttons */ + NDOF_BUTTON_A = 0x01b0, /* 432 */ + NDOF_BUTTON_B = 0x01b1, /* 433 */ + NDOF_BUTTON_C = 0x01b2, /* 434 */ + /* Store/restore views. */ + NDOF_BUTTON_V1 = 0x01b3, /* 435 */ + NDOF_BUTTON_V2 = 0x01b4, /* 436 */ + NDOF_BUTTON_V3 = 0x01b5, /* 437 */ /* Disabled as GHOST converts these to keyboard events * which use regular keyboard event handling logic. */ #if 0 /* keyboard emulation */ - NDOF_BUTTON_ESC = 0x01a6, /* 422 */ - NDOF_BUTTON_ALT = 0x01a7, /* 423 */ - NDOF_BUTTON_SHIFT = 0x01a8, /* 424 */ - NDOF_BUTTON_CTRL = 0x01a9, /* 425 */ + NDOF_BUTTON_ESC = 0x01b6, /* 438 */ + NDOF_BUTTON_ENTER = 0x01b7, /* 439 */ + NDOF_BUTTON_DELETE = 0x01b8, /* 440 */ + NDOF_BUTTON_TAB = 0x01b9, /* 441 */ + NDOF_BUTTON_SPACE = 0x01ba, /* 442 */ + NDOF_BUTTON_ALT = 0x01bb, /* 443 */ + NDOF_BUTTON_SHIFT = 0x01bc, /* 444 */ + NDOF_BUTTON_CTRL = 0x01bd, /* 445 */ #endif - /* general-purpose buttons */ - NDOF_BUTTON_1 = 0x01aa, /* 426 */ - NDOF_BUTTON_2 = 0x01ab, /* 427 */ - NDOF_BUTTON_3 = 0x01ac, /* 428 */ - NDOF_BUTTON_4 = 0x01ad, /* 429 */ - NDOF_BUTTON_5 = 0x01ae, /* 430 */ - NDOF_BUTTON_6 = 0x01af, /* 431 */ - NDOF_BUTTON_7 = 0x01b0, /* 432 */ - NDOF_BUTTON_8 = 0x01b1, /* 433 */ - NDOF_BUTTON_9 = 0x01b2, /* 434 */ - NDOF_BUTTON_10 = 0x01b3, /* 435 */ - /* more general-purpose buttons */ - NDOF_BUTTON_A = 0x01b4, /* 436 */ - NDOF_BUTTON_B = 0x01b5, /* 437 */ - NDOF_BUTTON_C = 0x01b6, /* 438 */ - -#define _NDOF_MAX NDOF_BUTTON_C -#define _NDOF_BUTTON_MAX NDOF_BUTTON_C +#define _NDOF_MAX NDOF_BUTTON_V3 +#define _NDOF_BUTTON_MAX NDOF_BUTTON_V3 /* ********** End of Input devices. ********** */ -- cgit v1.2.3 From ab28abcb6baaa728d8e2c30c4c98fef3655aa4dd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 12:58:36 +1100 Subject: Cleanup: remove the last button from NDOF button enum values This is only used for comparison, no need to make it part of the enum. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 4 +--- intern/ghost/intern/GHOST_NDOFManager.h | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 2754b9c8a6f..555e22dadbb 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -81,8 +81,6 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_ALT", "NDOF_BUTTON_SHIFT", "NDOF_BUTTON_CTRL", - /* the end */ - "NDOF_BUTTON_LAST", }; /* Shared by the latest 3Dconnexion hardware @@ -389,7 +387,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, uint64_t time, GHOST_IWindow *window) { - GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_LAST, + GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_NUM, "rogue button trying to escape NDOF manager"); GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window); diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 58371826527..c883c2dce65 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -87,8 +87,7 @@ typedef enum { NDOF_BUTTON_ALT, NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, - /* The end. */ - NDOF_BUTTON_LAST +#define NDOF_BUTTON_NUM (NDOF_BUTTON_CTRL + 1) } NDOF_ButtonT; class GHOST_NDOFManager { -- cgit v1.2.3 From c247562b0703841ba5f9f651dbd77a3d448a93c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 13:19:31 +1100 Subject: GHOST/NDOF: various minor changes to NDOF manager - Use logging for NDOF device output (this removes printing on startup buy default). - Use `ndof_` prefix for button maps. - Use full sentences. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 157 +++++++++++++++++------------- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- 2 files changed, 93 insertions(+), 66 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 555e22dadbb..e0913753e5b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -12,11 +12,14 @@ #include #include -#include /* For error/info reporting. */ #include /* For memory functions. */ -/* Printable version of each GHOST_TProgress value. */ -static const char *progress_string[] = { +/* -------------------------------------------------------------------- */ +/** \name NDOF Enum Strings + * \{ */ + +/* Printable values for #GHOST_TProgress enum (keep aligned). */ +static const char *ndof_progress_string[] = { "not started", "starting", "in progress", @@ -24,36 +27,31 @@ static const char *progress_string[] = { "finished", }; +/* Printable values for #NDOF_ButtonT enum (keep aligned) */ static const char *ndof_button_names[] = { - /* used internally, never sent */ "NDOF_BUTTON_NONE", - /* these two are available from any 3Dconnexion device */ + /* Real button values. */ "NDOF_BUTTON_MENU", "NDOF_BUTTON_FIT", - /* standard views */ "NDOF_BUTTON_TOP", "NDOF_BUTTON_BOTTOM", "NDOF_BUTTON_LEFT", "NDOF_BUTTON_RIGHT", "NDOF_BUTTON_FRONT", "NDOF_BUTTON_BACK", - /* more views */ "NDOF_BUTTON_ISO1", "NDOF_BUTTON_ISO2", - /* 90 degree rotations */ "NDOF_BUTTON_ROLL_CW", "NDOF_BUTTON_ROLL_CCW", "NDOF_BUTTON_SPIN_CW", "NDOF_BUTTON_SPIN_CCW", "NDOF_BUTTON_TILT_CW", "NDOF_BUTTON_TILT_CCW", - /* device control */ "NDOF_BUTTON_ROTATE", "NDOF_BUTTON_PANZOOM", "NDOF_BUTTON_DOMINANT", "NDOF_BUTTON_PLUS", "NDOF_BUTTON_MINUS", - /* general-purpose buttons */ "NDOF_BUTTON_1", "NDOF_BUTTON_2", "NDOF_BUTTON_3", @@ -64,15 +62,12 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_8", "NDOF_BUTTON_9", "NDOF_BUTTON_10", - /* more general-purpose buttons */ "NDOF_BUTTON_A", "NDOF_BUTTON_B", "NDOF_BUTTON_C", - /* Stored views. */ "NDOF_BUTTON_V1", "NDOF_BUTTON_V2", "NDOF_BUTTON_V3", - /* Keyboard emulation. */ "NDOF_BUTTON_ESC", "NDOF_BUTTON_ENTER", "NDOF_BUTTON_DELETE", @@ -83,10 +78,30 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_CTRL", }; +static const char *ndof_device_names[] = { + "UnknownDevice", + "SpaceNavigator", + "SpaceExplorer", + "SpacePilotPro", + "SpaceMousePro", + "SpaceMouseWireless", + "SpaceMouseProWireless", + "SpaceMouseEnterprise", + "SpacePilot", + "Spaceball5000", + "SpaceTraveler", +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Button Maps + * \{ */ + /* Shared by the latest 3Dconnexion hardware * SpacePilotPro uses all of these * smaller devices use only some, based on button mask. */ -static const NDOF_ButtonT Modern3Dx_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_Modern3Dx[] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT, NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_BOTTOM, NDOF_BUTTON_BACK, NDOF_BUTTON_ROLL_CW, NDOF_BUTTON_ROLL_CCW, NDOF_BUTTON_ISO1, NDOF_BUTTON_ISO2, @@ -96,7 +111,7 @@ static const NDOF_ButtonT Modern3Dx_HID_map[] = { NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, NDOF_BUTTON_ROTATE, NDOF_BUTTON_PANZOOM, NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS}; -static const NDOF_ButtonT SpaceExplorer_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_SpaceExplorer[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_TOP, @@ -114,9 +129,8 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = { NDOF_BUTTON_ROTATE, }; -/* This is the older SpacePilot (sans Pro) - * thanks to polosson for info about this device. */ -static const NDOF_ButtonT SpacePilot_HID_map[] = { +/* This is the older SpacePilot (sans Pro). */ +static const NDOF_ButtonT ndof_HID_map_SpacePilot[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, NDOF_BUTTON_4, NDOF_BUTTON_5, NDOF_BUTTON_6, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT, NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_ESC, NDOF_BUTTON_ALT, @@ -125,7 +139,7 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = { NDOF_BUTTON_NONE /* the CONFIG button -- what does it do? */ }; -static const NDOF_ButtonT Generic_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_Generic[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, @@ -141,7 +155,7 @@ static const NDOF_ButtonT Generic_HID_map[] = { }; /* Values taken from: https://github.com/FreeSpacenav/spacenavd/wiki/Device-button-names */ -static const NDOF_ButtonT SpaceMouseEnterprise_HID_map[] = { +static const NDOF_ButtonT ndof_HID_map_SpaceMouseEnterprise[] = { NDOF_BUTTON_1, /* (0) */ NDOF_BUTTON_2, /* (1) */ NDOF_BUTTON_3, /* (2) */ @@ -175,14 +189,20 @@ static const NDOF_ButtonT SpaceMouseEnterprise_HID_map[] = { NDOF_BUTTON_ISO1, /* Labeled "ISO1" (30). */ }; -static const int genericButtonCount = ARRAY_SIZE(Generic_HID_map); +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Manager Class + * \{ */ + +static const int genericButtonCount = ARRAY_SIZE(ndof_HID_map_Generic); GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) : m_system(sys), m_deviceType(NDOF_UnknownDevice), /* Each platform has its own device detection code. */ m_buttonCount(genericButtonCount), m_buttonMask(0), - m_hidMap(Generic_HID_map), + m_hidMap(ndof_HID_map_Generic), m_buttons(0), m_motionTime(0), m_prevMotionTime(0), @@ -196,6 +216,8 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) memset(m_rotation, 0, sizeof(m_rotation)); } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name NDOF Device Setup * \{ */ @@ -207,14 +229,14 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) { /* Call this function until it returns true * it's a good idea to stop calling it after that, as it will "forget" - * whichever device it already found */ + * whichever device it already found. */ /* Default to safe generic behavior for "unknown" devices * unidentified devices will emit motion events like normal * rogue buttons do nothing by default, but can be customized by the user. */ m_deviceType = NDOF_UnknownDevice; - m_hidMap = Generic_HID_map; + m_hidMap = ndof_HID_map_Generic; m_buttonCount = genericButtonCount; m_buttonMask = 0; @@ -226,87 +248,92 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0x046D: /* Logitech (3Dconnexion was a subsidiary). */ switch (product_id) { /* -- current devices -- */ - case 0xC626: /* full-size SpaceNavigator */ - case 0xC628: /* the "for Notebooks" one */ - puts("ndof: using SpaceNavigator"); + case 0xC626: /* Full-size SpaceNavigator. */ + case 0xC628: /* The "for Notebooks" one. */ + { m_deviceType = NDOF_SpaceNavigator; m_buttonCount = 2; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; - case 0xC627: - puts("ndof: using SpaceExplorer"); + } + case 0xC627: { m_deviceType = NDOF_SpaceExplorer; m_buttonCount = 15; - m_hidMap = SpaceExplorer_HID_map; + m_hidMap = ndof_HID_map_SpaceExplorer; break; - case 0xC629: - puts("ndof: using SpacePilot Pro"); + } + case 0xC629: { m_deviceType = NDOF_SpacePilotPro; m_buttonCount = 31; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; - case 0xC62B: - puts("ndof: using SpaceMouse Pro"); + } + case 0xC62B: { m_deviceType = NDOF_SpaceMousePro; - m_buttonCount = 27; - /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26 */ + m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ m_buttonMask = 0x07C0F137; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; + } /* -- older devices -- */ - case 0xC625: - puts("ndof: using SpacePilot"); + case 0xC625: { m_deviceType = NDOF_SpacePilot; m_buttonCount = 21; - m_hidMap = SpacePilot_HID_map; + m_hidMap = ndof_HID_map_SpacePilot; break; - case 0xC621: - puts("ndof: using Spaceball 5000"); + } + case 0xC621: { m_deviceType = NDOF_Spaceball5000; m_buttonCount = 12; break; - case 0xC623: - puts("ndof: using SpaceTraveler"); + } + case 0xC623: { m_deviceType = NDOF_SpaceTraveler; m_buttonCount = 8; break; - - default: - printf("ndof: unknown Logitech product %04hx\n", product_id); + } + default: { + CLOG_INFO(LOG, 2, "unknown Logitech product %04hx", product_id); + } } break; - case 0x256F: /* 3Dconnexion */ + case 0x256F: /* 3Dconnexion. */ switch (product_id) { case 0xC62E: /* Plugged in. */ case 0xC62F: /* Wireless. */ - puts("ndof: using SpaceMouse Wireless"); + { m_deviceType = NDOF_SpaceMouseWireless; m_buttonCount = 2; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; + } case 0xC631: /* Plugged in. */ case 0xC632: /* Wireless. */ - puts("ndof: using SpaceMouse Pro Wireless"); + { m_deviceType = NDOF_SpaceMouseProWireless; - m_buttonCount = 27; - /* ^^ actually has 15 buttons, but their HID codes range from 0 to 26. */ + m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ m_buttonMask = 0x07C0F137; - m_hidMap = Modern3Dx_HID_map; + m_hidMap = ndof_HID_map_Modern3Dx; break; - case 0xC633: - puts("ndof: using SpaceMouse Enterprise"); + } + case 0xC633: { m_deviceType = NDOF_SpaceMouseEnterprise; m_buttonCount = 31; - m_hidMap = SpaceMouseEnterprise_HID_map; + m_hidMap = ndof_HID_map_SpaceMouseEnterprise; break; - - default: - printf("ndof: unknown 3Dconnexion product %04hx\n", product_id); + } + default: { + CLOG_INFO(LOG, 2, "unknown 3Dconnexion product %04hx", product_id); + } } break; default: - printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); + CLOG_INFO(LOG, 2, "unknown device %04hx:%04hx", vendor_id, product_id); + } + + if (m_deviceType != NDOF_UnknownDevice) { + CLOG_INFO(LOG, 2, "using %s", ndof_device_names[m_deviceType]); } if (m_buttonMask == 0) { @@ -591,7 +618,7 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ry, data->rz, data->dt, - progress_string[data->progress]); + ndof_progress_string[data->progress]); #else /* Raw values, may be useful for debugging. */ CLOG_INFO(LOG, @@ -603,7 +630,7 @@ bool GHOST_NDOFManager::sendMotionEvent() m_rotation[0], m_rotation[1], m_rotation[2], - progress_string[data->progress]); + ndof_progress_string[data->progress]); #endif m_system.pushEvent(event); diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index c883c2dce65..2a1d94b052e 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -9,7 +9,7 @@ #include "GHOST_System.h" typedef enum { - NDOF_UnknownDevice, + NDOF_UnknownDevice = 0, /* Current devices. */ NDOF_SpaceNavigator, -- cgit v1.2.3 From c9f13788639790aba02acb3376dc505043dae175 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 13:52:51 +1100 Subject: Cleanup: use '_' suffix for private members for NDOF Manager --- intern/ghost/intern/GHOST_NDOFManager.cpp | 190 +++++++++++++------------- intern/ghost/intern/GHOST_NDOFManager.h | 26 ++-- intern/ghost/intern/GHOST_NDOFManagerUnix.cpp | 16 +-- intern/ghost/intern/GHOST_NDOFManagerUnix.h | 2 +- 4 files changed, 117 insertions(+), 117 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index e0913753e5b..882443ae839 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -198,22 +198,22 @@ static const NDOF_ButtonT ndof_HID_map_SpaceMouseEnterprise[] = { static const int genericButtonCount = ARRAY_SIZE(ndof_HID_map_Generic); GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys) - : m_system(sys), - m_deviceType(NDOF_UnknownDevice), /* Each platform has its own device detection code. */ - m_buttonCount(genericButtonCount), - m_buttonMask(0), - m_hidMap(ndof_HID_map_Generic), - m_buttons(0), - m_motionTime(0), - m_prevMotionTime(0), - m_motionState(GHOST_kNotStarted), - m_motionEventPending(false), - m_deadZone(0.0f) + : system_(sys), + device_type_(NDOF_UnknownDevice), /* Each platform has its own device detection code. */ + hid_map_button_num_(genericButtonCount), + hid_map_button_mask_(0), + hid_map_(ndof_HID_map_Generic), + button_depressed_(0), + motion_time_(0), + motion_time_prev_(0), + motion_state_(GHOST_kNotStarted), + motion_event_pending_(false), + motion_dead_zone_(0.0f) { /* To avoid the rare situation where one triple is updated and * the other is not, initialize them both here: */ - memset(m_translation, 0, sizeof(m_translation)); - memset(m_rotation, 0, sizeof(m_rotation)); + memset(translation_, 0, sizeof(translation_)); + memset(rotation_, 0, sizeof(rotation_)); } /** \} */ @@ -235,10 +235,10 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) * unidentified devices will emit motion events like normal * rogue buttons do nothing by default, but can be customized by the user. */ - m_deviceType = NDOF_UnknownDevice; - m_hidMap = ndof_HID_map_Generic; - m_buttonCount = genericButtonCount; - m_buttonMask = 0; + device_type_ = NDOF_UnknownDevice; + hid_map_ = ndof_HID_map_Generic; + hid_map_button_num_ = genericButtonCount; + hid_map_button_mask_ = 0; /* "mystery device" owners can help build a HID_map for their hardware * A few users have already contributed information about several older devices @@ -251,46 +251,46 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0xC626: /* Full-size SpaceNavigator. */ case 0xC628: /* The "for Notebooks" one. */ { - m_deviceType = NDOF_SpaceNavigator; - m_buttonCount = 2; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceNavigator; + hid_map_button_num_ = 2; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC627: { - m_deviceType = NDOF_SpaceExplorer; - m_buttonCount = 15; - m_hidMap = ndof_HID_map_SpaceExplorer; + device_type_ = NDOF_SpaceExplorer; + hid_map_button_num_ = 15; + hid_map_ = ndof_HID_map_SpaceExplorer; break; } case 0xC629: { - m_deviceType = NDOF_SpacePilotPro; - m_buttonCount = 31; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpacePilotPro; + hid_map_button_num_ = 31; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC62B: { - m_deviceType = NDOF_SpaceMousePro; - m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ - m_buttonMask = 0x07C0F137; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceMousePro; + hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_mask_ = 0x07C0F137; + hid_map_ = ndof_HID_map_Modern3Dx; break; } /* -- older devices -- */ case 0xC625: { - m_deviceType = NDOF_SpacePilot; - m_buttonCount = 21; - m_hidMap = ndof_HID_map_SpacePilot; + device_type_ = NDOF_SpacePilot; + hid_map_button_num_ = 21; + hid_map_ = ndof_HID_map_SpacePilot; break; } case 0xC621: { - m_deviceType = NDOF_Spaceball5000; - m_buttonCount = 12; + device_type_ = NDOF_Spaceball5000; + hid_map_button_num_ = 12; break; } case 0xC623: { - m_deviceType = NDOF_SpaceTraveler; - m_buttonCount = 8; + device_type_ = NDOF_SpaceTraveler; + hid_map_button_num_ = 8; break; } default: { @@ -303,24 +303,24 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0xC62E: /* Plugged in. */ case 0xC62F: /* Wireless. */ { - m_deviceType = NDOF_SpaceMouseWireless; - m_buttonCount = 2; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceMouseWireless; + hid_map_button_num_ = 2; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC631: /* Plugged in. */ case 0xC632: /* Wireless. */ { - m_deviceType = NDOF_SpaceMouseProWireless; - m_buttonCount = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ - m_buttonMask = 0x07C0F137; - m_hidMap = ndof_HID_map_Modern3Dx; + device_type_ = NDOF_SpaceMouseProWireless; + hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_mask_ = 0x07C0F137; + hid_map_ = ndof_HID_map_Modern3Dx; break; } case 0xC633: { - m_deviceType = NDOF_SpaceMouseEnterprise; - m_buttonCount = 31; - m_hidMap = ndof_HID_map_SpaceMouseEnterprise; + device_type_ = NDOF_SpaceMouseEnterprise; + hid_map_button_num_ = 31; + hid_map_ = ndof_HID_map_SpaceMouseEnterprise; break; } default: { @@ -332,17 +332,17 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) CLOG_INFO(LOG, 2, "unknown device %04hx:%04hx", vendor_id, product_id); } - if (m_deviceType != NDOF_UnknownDevice) { - CLOG_INFO(LOG, 2, "using %s", ndof_device_names[m_deviceType]); + if (device_type_ != NDOF_UnknownDevice) { + CLOG_INFO(LOG, 2, "using %s", ndof_device_names[device_type_]); } - if (m_buttonMask == 0) { - m_buttonMask = int(~(UINT_MAX << m_buttonCount)); + if (hid_map_button_mask_ == 0) { + hid_map_button_mask_ = int(~(UINT_MAX << hid_map_button_num_)); } - CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", m_buttonCount, (uint)m_buttonMask); + CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, (uint)hid_map_button_mask_); - return m_deviceType != NDOF_UnknownDevice; + return device_type_ != NDOF_UnknownDevice; } #undef LOG @@ -355,16 +355,16 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) void GHOST_NDOFManager::updateTranslation(const int t[3], uint64_t time) { - memcpy(m_translation, t, sizeof(m_translation)); - m_motionTime = time; - m_motionEventPending = true; + memcpy(translation_, t, sizeof(translation_)); + motion_time_ = time; + motion_event_pending_ = true; } void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time) { - memcpy(m_rotation, r, sizeof(m_rotation)); - m_motionTime = time; - m_motionEventPending = true; + memcpy(rotation_, r, sizeof(rotation_)); + motion_time_ = time; + motion_event_pending_ = true; } /** \} */ @@ -423,7 +423,7 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, data->action = press ? GHOST_kPress : GHOST_kRelease; data->button = button; - m_system.pushEvent(event); + system_.pushEvent(event); } void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, @@ -434,21 +434,21 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; GHOST_EventKey *event = new GHOST_EventKey(time, type, window, key, false); - m_system.pushEvent(event); + system_.pushEvent(event); } void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time) { - if (button_number >= m_buttonCount) { + if (button_number >= hid_map_button_num_) { CLOG_INFO(LOG, 2, "button=%d, press=%d (out of range %d, ignoring!)", button_number, (int)press, - m_buttonCount); + hid_map_button_num_); return; } - const NDOF_ButtonT button = m_hidMap[button_number]; + const NDOF_ButtonT button = hid_map_[button_number]; if (button == NDOF_BUTTON_NONE) { CLOG_INFO( LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, (int)press); @@ -462,7 +462,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim (int)press, ndof_button_names[button]); - GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); + GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow(); const GHOST_TKey key = ghost_map_keyboard_from_ndof_buttom(button); if (key != GHOST_kKeyUnknown) { sendKeyEvent(key, press, time, window); @@ -473,20 +473,20 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim int mask = 1 << button_number; if (press) { - m_buttons |= mask; /* Set this button's bit. */ + button_depressed_ |= mask; /* Set this button's bit. */ } else { - m_buttons &= ~mask; /* Clear this button's bit. */ + button_depressed_ &= ~mask; /* Clear this button's bit. */ } } void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time) { - button_bits &= m_buttonMask; /* Discard any "garbage" bits. */ + button_bits &= hid_map_button_mask_; /* Discard any "garbage" bits. */ - int diff = m_buttons ^ button_bits; + int diff = button_depressed_ ^ button_bits; - for (int button_number = 0; button_number < m_buttonCount; ++button_number) { + for (int button_number = 0; button_number < hid_map_button_num_; ++button_number) { int mask = 1 << button_number; if (diff & mask) { @@ -513,7 +513,7 @@ void GHOST_NDOFManager::setDeadZone(float dz) /* Negative values don't make sense, so clamp at zero. */ dz = 0.0f; } - m_deadZone = dz; + motion_dead_zone_ = dz; /* Warn the rogue user/developer about high dead-zone, but allow it. */ CLOG_INFO(LOG, 2, "dead zone set to %.2f%s", dz, (dz > 0.5f) ? " (unexpectedly high)" : ""); @@ -538,20 +538,20 @@ static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold) bool GHOST_NDOFManager::sendMotionEvent() { - if (!m_motionEventPending) { + if (!motion_event_pending_) { return false; } - m_motionEventPending = false; /* Any pending motion is handled right now. */ + motion_event_pending_ = false; /* Any pending motion is handled right now. */ - GHOST_IWindow *window = m_system.getWindowManager()->getActiveWindow(); + GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow(); if (window == nullptr) { - m_motionState = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */ + motion_state_ = GHOST_kNotStarted; /* Avoid large `dt` times when changing windows. */ return false; /* Delivery will fail, so don't bother sending. */ } - GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(m_motionTime, window); + GHOST_EventNDOFMotion *event = new GHOST_EventNDOFMotion(motion_time_, window); GHOST_TEventNDOFMotionData *data = (GHOST_TEventNDOFMotionData *)event->getData(); /* Scale axis values here to normalize them to around +/- 1 @@ -559,26 +559,26 @@ bool GHOST_NDOFManager::sendMotionEvent() const float scale = 1.0f / 350.0f; /* 3Dconnexion devices send +/- 350 usually */ - data->tx = scale * m_translation[0]; - data->ty = scale * m_translation[1]; - data->tz = scale * m_translation[2]; + data->tx = scale * translation_[0]; + data->ty = scale * translation_[1]; + data->tz = scale * translation_[2]; - data->rx = scale * m_rotation[0]; - data->ry = scale * m_rotation[1]; - data->rz = scale * m_rotation[2]; - data->dt = 0.001f * (m_motionTime - m_prevMotionTime); /* In seconds. */ - m_prevMotionTime = m_motionTime; + data->rx = scale * rotation_[0]; + data->ry = scale * rotation_[1]; + data->rz = scale * rotation_[2]; + data->dt = 0.001f * (motion_time_ - motion_time_prev_); /* In seconds. */ + motion_time_prev_ = motion_time_; - bool weHaveMotion = !nearHomePosition(data, m_deadZone); + bool weHaveMotion = !nearHomePosition(data, motion_dead_zone_); /* Determine what kind of motion event to send `(Starting, InProgress, Finishing)` * and where that leaves this NDOF manager `(NotStarted, InProgress, Finished)`. */ - switch (m_motionState) { + switch (motion_state_) { case GHOST_kNotStarted: case GHOST_kFinished: { if (weHaveMotion) { data->progress = GHOST_kStarting; - m_motionState = GHOST_kInProgress; + motion_state_ = GHOST_kInProgress; /* Previous motion time will be ancient, so just make up a reasonable time delta. */ data->dt = 0.0125f; } @@ -597,7 +597,7 @@ bool GHOST_NDOFManager::sendMotionEvent() } else { data->progress = GHOST_kFinishing; - m_motionState = GHOST_kFinished; + motion_state_ = GHOST_kFinished; } break; } @@ -624,15 +624,15 @@ bool GHOST_NDOFManager::sendMotionEvent() CLOG_INFO(LOG, 2, "motion sent, T=(%d,%d,%d) R=(%d,%d,%d) status=%s", - m_translation[0], - m_translation[1], - m_translation[2], - m_rotation[0], - m_rotation[1], - m_rotation[2], + translation_[0], + translation_[1], + translation_[2], + rotation_[0], + rotation_[1], + rotation_[2], ndof_progress_string[data->progress]); #endif - m_system.pushEvent(event); + system_.pushEvent(event); return true; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 2a1d94b052e..6dadeee1fcc 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -147,25 +147,25 @@ class GHOST_NDOFManager { bool sendMotionEvent(); protected: - GHOST_System &m_system; + GHOST_System &system_; private: void sendButtonEvent(NDOF_ButtonT, bool press, uint64_t time, GHOST_IWindow *); void sendKeyEvent(GHOST_TKey, bool press, uint64_t time, GHOST_IWindow *); - NDOF_DeviceT m_deviceType; - int m_buttonCount; - int m_buttonMask; - const NDOF_ButtonT *m_hidMap; + NDOF_DeviceT device_type_; + int hid_map_button_num_; + int hid_map_button_mask_; + const NDOF_ButtonT *hid_map_; - int m_translation[3]; - int m_rotation[3]; - int m_buttons; /* Bit field. */ + int translation_[3]; + int rotation_[3]; + int button_depressed_; /* Bit field. */ - uint64_t m_motionTime; /* In milliseconds. */ - uint64_t m_prevMotionTime; /* Time of most recent motion event sent. */ + uint64_t motion_time_; /* In milliseconds. */ + uint64_t motion_time_prev_; /* Time of most recent motion event sent. */ - GHOST_TProgress m_motionState; - bool m_motionEventPending; - float m_deadZone; /* Discard motion with each component < this. */ + GHOST_TProgress motion_state_; + bool motion_event_pending_; + float motion_dead_zone_; /* Discard motion with each component < this. */ }; diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp index 94bf0337371..0ccf4dc9bfb 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.cpp @@ -10,7 +10,7 @@ #define SPNAV_SOCK_PATH "/var/run/spnav.sock" GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) - : GHOST_NDOFManager(sys), m_available(false) + : GHOST_NDOFManager(sys), available_(false) { if (access(SPNAV_SOCK_PATH, F_OK) != 0) { #ifdef DEBUG @@ -20,7 +20,7 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) #endif } else if (spnav_open() != -1) { - m_available = true; + available_ = true; /* determine exactly which device (if any) is plugged in */ @@ -45,14 +45,14 @@ GHOST_NDOFManagerUnix::GHOST_NDOFManagerUnix(GHOST_System &sys) GHOST_NDOFManagerUnix::~GHOST_NDOFManagerUnix() { - if (m_available) { + if (available_) { spnav_close(); } } bool GHOST_NDOFManagerUnix::available() { - return m_available; + return available_; } /* @@ -74,7 +74,7 @@ bool GHOST_NDOFManagerUnix::processEvents() { bool anyProcessed = false; - if (m_available) { + if (available_) { spnav_event e; #ifdef USE_FINISH_GLITCH_WORKAROUND @@ -85,7 +85,7 @@ bool GHOST_NDOFManagerUnix::processEvents() switch (e.type) { case SPNAV_EVENT_MOTION: { /* convert to blender view coords */ - uint64_t now = m_system.getMilliSeconds(); + uint64_t now = system_.getMilliSeconds(); const int t[3] = {int(e.motion.x), int(e.motion.y), int(-e.motion.z)}; const int r[3] = {int(-e.motion.rx), int(-e.motion.ry), int(e.motion.rz)}; @@ -97,7 +97,7 @@ bool GHOST_NDOFManagerUnix::processEvents() break; } case SPNAV_EVENT_BUTTON: - uint64_t now = m_system.getMilliSeconds(); + uint64_t now = system_.getMilliSeconds(); updateButton(e.button.bnum, e.button.press, now); break; } @@ -106,7 +106,7 @@ bool GHOST_NDOFManagerUnix::processEvents() #ifdef USE_FINISH_GLITCH_WORKAROUND if (motion_test_prev == true && motion_test == false) { - uint64_t now = m_system.getMilliSeconds(); + uint64_t now = system_.getMilliSeconds(); const int v[3] = {0, 0, 0}; updateTranslation(v, now); diff --git a/intern/ghost/intern/GHOST_NDOFManagerUnix.h b/intern/ghost/intern/GHOST_NDOFManagerUnix.h index fd603e3cb54..2b98fad974f 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerUnix.h +++ b/intern/ghost/intern/GHOST_NDOFManagerUnix.h @@ -15,5 +15,5 @@ class GHOST_NDOFManagerUnix : public GHOST_NDOFManager { bool processEvents(); private: - bool m_available; + bool available_; }; -- cgit v1.2.3 From e4c5a46c1294eefd7464395bca9551b9ca866aea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 14:07:36 +1100 Subject: Cleanup: remove NDOF_BUTTON_NONE from the range of usable buttons This is used to represent unknown state, so there is no need to be able to store it's pressed state. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 8 ++++---- intern/ghost/intern/GHOST_NDOFManager.h | 6 +++--- source/blender/blenkernel/BKE_brush.h | 2 +- source/blender/windowmanager/intern/wm_event_system.cc | 2 +- source/blender/windowmanager/wm_event_types.h | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 882443ae839..9e9b9f14c43 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -29,8 +29,7 @@ static const char *ndof_progress_string[] = { /* Printable values for #NDOF_ButtonT enum (keep aligned) */ static const char *ndof_button_names[] = { - "NDOF_BUTTON_NONE", - /* Real button values. */ + /* Exclude `NDOF_BUTTON_NONE` (-1). */ "NDOF_BUTTON_MENU", "NDOF_BUTTON_FIT", "NDOF_BUTTON_TOP", @@ -68,6 +67,7 @@ static const char *ndof_button_names[] = { "NDOF_BUTTON_V1", "NDOF_BUTTON_V2", "NDOF_BUTTON_V3", + /* Keyboard emulation. */ "NDOF_BUTTON_ESC", "NDOF_BUTTON_ENTER", "NDOF_BUTTON_DELETE", @@ -270,7 +270,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) } case 0xC62B: { device_type_ = NDOF_SpaceMousePro; - hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */ hid_map_button_mask_ = 0x07C0F137; hid_map_ = ndof_HID_map_Modern3Dx; break; @@ -312,7 +312,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) case 0xC632: /* Wireless. */ { device_type_ = NDOF_SpaceMouseProWireless; - hid_map_button_num_ = 27; /* Actually has 15 buttons, but HID codes range from 0 to 26. */ + hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */ hid_map_button_mask_ = 0x07C0F137; hid_map_ = ndof_HID_map_Modern3Dx; break; diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 6dadeee1fcc..2d5bba14aa4 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -29,8 +29,8 @@ typedef enum { /* NDOF device button event types */ typedef enum { - /* Used internally, never sent. */ - NDOF_BUTTON_NONE = 0, + /* Used internally, never sent or used as an index. */ + NDOF_BUTTON_NONE = -1, /* These two are available from any 3Dconnexion device. */ NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, @@ -162,7 +162,7 @@ class GHOST_NDOFManager { int rotation_[3]; int button_depressed_; /* Bit field. */ - uint64_t motion_time_; /* In milliseconds. */ + uint64_t motion_time_; /* In milliseconds. */ uint64_t motion_time_prev_; /* Time of most recent motion event sent. */ GHOST_TProgress motion_state_; diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 8f069841fbc..a763b3d12c2 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -126,7 +126,7 @@ float BKE_brush_sample_masktex(const struct Scene *scene, * Get the mask texture for this given object mode. * * This is preferred above using mtex/mask_mtex attributes directly as due to legacy these - * attributes got switched in sculpt mode. + * attributes got switched in sculpt mode. */ const struct MTex *BKE_brush_mask_texture_get(const struct Brush *brush, const eObjectMode object_mode); diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index affe0bcf45a..181ec89cabd 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -5620,7 +5620,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void case GHOST_kEventNDOFButton: { GHOST_TEventNDOFButtonData *e = static_cast(customdata); - event.type = NDOF_BUTTON_NONE + e->button; + event.type = NDOF_BUTTON_INDEX_AS_EVENT(e->button); switch (e->action) { case GHOST_kPress: diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 10536a00501..c36c57a12ae 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -252,8 +252,6 @@ enum { #define _NDOF_MIN NDOF_MOTION #define _NDOF_BUTTON_MIN NDOF_BUTTON_MENU - /* used internally, never sent */ - NDOF_BUTTON_NONE = NDOF_MOTION, /* these two are available from any 3Dconnexion device */ NDOF_BUTTON_MENU = 0x0191, /* 401 */ @@ -456,6 +454,8 @@ enum eEventType_Mask { (EVT_TYPE_MASK_KEYBOARD | EVT_TYPE_MASK_MOUSE | EVT_TYPE_MASK_NDOF) #define EVT_TYPE_MASK_HOTKEY_EXCLUDE EVT_TYPE_MASK_KEYBOARD_MODIFIER +#define NDOF_BUTTON_INDEX_AS_EVENT(i) (_NDOF_BUTTON_MIN + (i)) + bool WM_event_type_mask_test(int event_type, enum eEventType_Mask mask); /** \} */ -- cgit v1.2.3 From 42f37106c59e454764a5a2c5c03c02a71efab49e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 14:53:48 +1100 Subject: GHOST/Wayland: add listener for touch events (no touch support yet) Currently unused as my tablet isn't generating touch events. This may be useful for development as touch events are logged. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 95 ++++++++++++++++++++++ .../extern/wayland_dynload_client.h | 1 + 2 files changed, 96 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 04c7e103bde..83bbcd60b2f 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -416,6 +416,7 @@ struct GWL_Seat { std::string name; struct wl_seat *wl_seat = nullptr; struct wl_pointer *wl_pointer = nullptr; + struct wl_touch *wl_touch = nullptr; struct wl_keyboard *wl_keyboard = nullptr; struct zwp_tablet_seat_v2 *tablet_seat = nullptr; @@ -643,6 +644,11 @@ static void display_destroy(GWL_Display *display) wl_pointer_destroy(seat->wl_pointer); } } + + if (seat->wl_touch) { + wl_touch_destroy(seat->wl_touch); + } + if (seat->wl_keyboard) { if (seat->key_repeat.timer) { keyboard_handle_key_repeat_cancel(seat); @@ -1898,6 +1904,89 @@ static const struct wl_pointer_listener pointer_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (Touch Seat), #wl_touch_listener + * + * TODO(@campbellbarton): Only setup the callbacks for now as I don't have + * hardware that generates touch events. + * \{ */ + +static CLG_LogRef LOG_WL_TOUCH = {"ghost.wl.handle.touch"}; +#define LOG (&LOG_WL_TOUCH) + +static void touch_seat_handle_down(void * /*data*/, + struct wl_touch * /*wl_touch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*wl_surface*/, + int32_t /*id*/, + wl_fixed_t /*x*/, + wl_fixed_t /*y*/) +{ + CLOG_INFO(LOG, 2, "down"); +} + +static void touch_seat_handle_up(void * /*data*/, + struct wl_touch * /*wl_touch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t /*id*/) +{ + CLOG_INFO(LOG, 2, "up"); +} + +static void touch_seat_handle_motion(void * /*data*/, + struct wl_touch * /*wl_touch*/, + uint32_t /*time*/, + int32_t /*id*/, + wl_fixed_t /*x*/, + wl_fixed_t /*y*/) +{ + CLOG_INFO(LOG, 2, "motion"); +} + +static void touch_seat_handle_frame(void * /*data*/, struct wl_touch * /*wl_touch*/) +{ + CLOG_INFO(LOG, 2, "frame"); +} + +static void touch_seat_handle_cancel(void * /*data*/, struct wl_touch * /*wl_touch*/) +{ + + CLOG_INFO(LOG, 2, "cancel"); +} + +static void touch_seat_handle_shape(void * /*data*/, + struct wl_touch * /*touch*/, + int32_t /*id*/, + wl_fixed_t /*major*/, + wl_fixed_t /*minor*/) +{ + CLOG_INFO(LOG, 2, "shape"); +} + +static void touch_seat_handle_orientation(void * /*data*/, + struct wl_touch * /*touch*/, + int32_t /*id*/, + wl_fixed_t /*orientation*/) +{ + CLOG_INFO(LOG, 2, "orientation"); +} + +static const struct wl_touch_listener touch_seat_listener = { + touch_seat_handle_down, + touch_seat_handle_up, + touch_seat_handle_motion, + touch_seat_handle_frame, + touch_seat_handle_cancel, + touch_seat_handle_shape, + touch_seat_handle_orientation, +}; + +#undef LOG + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Tablet Tool), #zwp_tablet_tool_v2_listener * \{ */ @@ -2717,6 +2806,12 @@ static void seat_handle_capabilities(void *data, ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); } + if (capabilities & WL_SEAT_CAPABILITY_TOUCH) { + seat->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(seat->wl_touch, seat); + wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat); + } + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data); diff --git a/intern/wayland_dynload/extern/wayland_dynload_client.h b/intern/wayland_dynload/extern/wayland_dynload_client.h index 8e9dddd91a3..d80ef5c9f0c 100644 --- a/intern/wayland_dynload/extern/wayland_dynload_client.h +++ b/intern/wayland_dynload/extern/wayland_dynload_client.h @@ -41,6 +41,7 @@ WAYLAND_DYNLOAD_IFACE(wl_seat_interface) WAYLAND_DYNLOAD_IFACE(wl_shm_interface) WAYLAND_DYNLOAD_IFACE(wl_shm_pool_interface) WAYLAND_DYNLOAD_IFACE(wl_surface_interface) +WAYLAND_DYNLOAD_IFACE(wl_touch_interface) #else /* Header guard. */ -- cgit v1.2.3 From da4bd24c3e6122c74fbc6dcc81604ee7a0dd3fe0 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 18 Oct 2022 23:44:07 -0500 Subject: Sculpt: Improve performance of face set creation from selection Skip BMesh conversion and read the selection attribute directly. With a Ryzen 3700x, my test face of a simple 4 million face grid became over 4000 times faster, from 2.6s to 0.6ms. --- .../editors/sculpt_paint/sculpt_face_set.cc | 29 ++++++++-------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index ee1238e0f24..8fb4dea668e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -18,6 +18,7 @@ #include "BLI_math_vector.hh" #include "BLI_span.hh" #include "BLI_task.h" +#include "BLI_task.hh" #include "DNA_brush_types.h" #include "DNA_customdata_types.h" @@ -313,6 +314,7 @@ static EnumPropertyItem prop_sculpt_face_set_create_types[] = { static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) { + using namespace blender; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); @@ -396,25 +398,16 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) } if (mode == SCULPT_FACE_SET_SELECTION) { - BMesh *bm; - const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); - BMeshCreateParams create_params{}; - create_params.use_toolflags = true; - bm = BM_mesh_create(&allocsize, &create_params); - - BMeshFromMeshParams convert_params{}; - convert_params.calc_vert_normal = true; - convert_params.calc_face_normal = true; - BM_mesh_bm_from_me(bm, mesh, &convert_params); - - BMIter iter; - BMFace *f; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - ss->face_sets[BM_elem_index_get(f)] = next_face_set; + const bke::AttributeAccessor attributes = mesh->attributes(); + const VArraySpan select_poly = attributes.lookup_or_default( + ".select_poly", ATTR_DOMAIN_FACE, false); + threading::parallel_for(IndexRange(mesh->totvert), 4096, [&](const IndexRange range) { + for (const int i : range) { + if (select_poly[i]) { + ss->face_sets[i] = next_face_set; + } } - } - BM_mesh_free(bm); + }); } for (int i = 0; i < totnode; i++) { -- cgit v1.2.3 From 30d9a6245f892492188318e92b85083ef8b301f2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 16:20:30 +1100 Subject: GHOST/Wayland: support high resolution 2D track-pad scroll events These events are interpreted as MOUSEPAN by Blender. Tested with a Wacom Intuos5. This isn't full touch support which is needed to support gestures such as Swipe, Rotate .. etc. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 99 +++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 83bbcd60b2f..09f51199047 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -10,6 +10,7 @@ #include "GHOST_EventCursor.h" #include "GHOST_EventDragnDrop.h" #include "GHOST_EventKey.h" +#include "GHOST_EventTrackpad.h" #include "GHOST_EventWheel.h" #include "GHOST_PathUtils.h" #include "GHOST_TimerManager.h" @@ -340,6 +341,11 @@ struct GWL_SeatStatePointer { */ wl_fixed_t xy[2] = {0, 0}; + /** Smooth scrolling (handled & reset with pointer "frame" callback). */ + wl_fixed_t scroll_xy[2] = {0, 0}; + /** Discrete scrolling (handled & reset with pointer "frame" callback). */ + int32_t scroll_discrete_xy[2] = {0, 0}; + /** Outputs on which the cursor is visible. */ std::unordered_set outputs; @@ -843,6 +849,21 @@ static GHOST_TKey xkb_map_gkey_or_scan_code(const xkb_keysym_t sym, const uint32 return gkey; } +static int pointer_axis_as_index(const uint32_t axis) +{ + switch (axis) { + case WL_POINTER_AXIS_HORIZONTAL_SCROLL: { + return 0; + } + case WL_POINTER_AXIS_VERTICAL_SCROLL: { + return 1; + } + default: { + return -1; + } + } +} + static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_tablet_tool_type) { switch (wl_tablet_tool_type) { @@ -1732,6 +1753,14 @@ static void pointer_handle_enter(void *data, seat->pointer.serial = serial; seat->pointer.xy[0] = surface_x; seat->pointer.xy[1] = surface_y; + + /* Resetting scroll events is likely unnecessary, + * do this to avoid any possible problems as it's harmless. */ + seat->pointer.scroll_xy[0] = 0; + seat->pointer.scroll_xy[1] = 0; + seat->pointer.scroll_discrete_xy[0] = 0; + seat->pointer.scroll_discrete_xy[1] = 0; + seat->pointer.wl_surface = wl_surface; win->setCursorShape(win->getCursorShape()); @@ -1843,18 +1872,69 @@ static void pointer_handle_button(void *data, } } -static void pointer_handle_axis(void * /*data*/, +static void pointer_handle_axis(void *data, struct wl_pointer * /*wl_pointer*/, const uint32_t /*time*/, const uint32_t axis, const wl_fixed_t value) { + /* NOTE: this is used for touch based scrolling - or other input that doesn't scroll with + * discrete "steps". This allows supporting smooth-scrolling without "touch" gesture support. */ CLOG_INFO(LOG, 2, "axis (axis=%u, value=%d)", axis, value); + const int index = pointer_axis_as_index(axis); + if (UNLIKELY(index == -1)) { + return; + } + GWL_Seat *seat = static_cast(data); + seat->pointer.scroll_xy[index] = value; } -static void pointer_handle_frame(void * /*data*/, struct wl_pointer * /*wl_pointer*/) +static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) { CLOG_INFO(LOG, 2, "frame"); + GWL_Seat *seat = static_cast(data); + + /* Discrete steps may generate non-discrete scrolling, in this case, + * give the mouse wheel priority otherwise mouse wheel events would be recognized + * as touch-pad scrolling too. */ + if (seat->pointer.scroll_discrete_xy[0]) { + seat->pointer.scroll_xy[0] = 0; + } + if (seat->pointer.scroll_discrete_xy[1]) { + seat->pointer.scroll_xy[1] = 0; + } + + /* Discrete Y steps currently unsupported. */ + if (seat->pointer.scroll_discrete_xy[0]) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); + const int32_t discrete = seat->pointer.scroll_discrete_xy[0]; + seat->system->pushEvent(new GHOST_EventWheel( + seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); + } + seat->pointer.scroll_discrete_xy[0] = 0; + seat->pointer.scroll_discrete_xy[1] = 0; + } + + if (seat->pointer.scroll_xy[0] || seat->pointer.scroll_xy[1]) { + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); + const wl_fixed_t scale = win->scale(); + seat->system->pushEvent(new GHOST_EventTrackpad( + seat->system->getMilliSeconds(), + win, + GHOST_kTrackpadEventScroll, + wl_fixed_to_int(scale * seat->pointer.xy[0]), + wl_fixed_to_int(scale * seat->pointer.xy[1]), + wl_fixed_to_int(seat->pointer.scroll_xy[0]), + wl_fixed_to_int(seat->pointer.scroll_xy[1]), + /* TODO: investigate a way to request this configuration from the system. */ + true)); + } + + seat->pointer.scroll_xy[0] = 0; + seat->pointer.scroll_xy[1] = 0; + } } static void pointer_handle_axis_source(void * /*data*/, struct wl_pointer * /*wl_pointer*/, @@ -1874,18 +1954,15 @@ static void pointer_handle_axis_discrete(void *data, uint32_t axis, int32_t discrete) { + /* NOTE: a discrete axis are typically mouse wheel events. + * The non-discrete version of this function is used for touch-pad. */ CLOG_INFO(LOG, 2, "axis_discrete (axis=%u, discrete=%d)", axis, discrete); - - GWL_Seat *seat = static_cast(data); - if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) { + const int index = pointer_axis_as_index(axis); + if (UNLIKELY(index == -1)) { return; } - - if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { - GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); - seat->system->pushEvent(new GHOST_EventWheel( - seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); - } + GWL_Seat *seat = static_cast(data); + seat->pointer.scroll_discrete_xy[index] = discrete; } static const struct wl_pointer_listener pointer_listener = { -- cgit v1.2.3 From 760a6aa1f5d67d9638e44748dfd453729634b331 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 16:35:32 +1100 Subject: Fix error in 30d9a6245f892492188318e92b85083ef8b301f2 X/Y for mouse wheel events was unintentionally flipped. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 09f51199047..62f96e4e620 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1904,11 +1904,11 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) seat->pointer.scroll_xy[1] = 0; } - /* Discrete Y steps currently unsupported. */ - if (seat->pointer.scroll_discrete_xy[0]) { + /* Discrete X axis currently unsupported. */ + if (seat->pointer.scroll_discrete_xy[1]) { if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); - const int32_t discrete = seat->pointer.scroll_discrete_xy[0]; + const int32_t discrete = seat->pointer.scroll_discrete_xy[1]; seat->system->pushEvent(new GHOST_EventWheel( seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); } -- cgit v1.2.3 From 96fa5e1e84d722fd9d4014ab5d100ec254d64cb5 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 14:42:35 +0200 Subject: Cleanup: remove unused 'VIEW3D_MT_brush_context_menu_paint_modes' This was added in rB4c9fe657458f, however that new code never used this menu (but the existing `VIEW3D_MT_brush_paint_modes` instead). Differential Revision: https://developer.blender.org/D16285 --- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 328e45f79b9..a28e93c34d1 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -81,22 +81,6 @@ class VIEW3D_MT_brush_gpencil_context_menu(Menu): layout.operator("gpencil.brush_reset_all") -class VIEW3D_MT_brush_context_menu_paint_modes(Menu): - bl_label = "Enabled Modes" - - def draw(self, context): - layout = self.layout - - settings = UnifiedPaintPanel.paint_settings(context) - brush = settings.brush - - layout.prop(brush, "use_paint_sculpt", text="Sculpt") - layout.prop(brush, "use_paint_uv_sculpt", text="UV Sculpt") - layout.prop(brush, "use_paint_vertex", text="Vertex Paint") - layout.prop(brush, "use_paint_weight", text="Weight Paint") - layout.prop(brush, "use_paint_image", text="Texture Paint") - - class View3DPanel: bl_space_type = 'VIEW_3D' bl_region_type = 'UI' @@ -2373,7 +2357,6 @@ class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel): classes = ( VIEW3D_MT_brush_context_menu, VIEW3D_MT_brush_gpencil_context_menu, - VIEW3D_MT_brush_context_menu_paint_modes, VIEW3D_PT_tools_object_options, VIEW3D_PT_tools_object_options_transform, VIEW3D_PT_tools_meshedit_options, -- cgit v1.2.3 From 4d185921f6cee93a1d8b5f3178b6f1267b0fb53a Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 14:57:57 +0200 Subject: Sculpt curves: Fix BKE_paint_object_mode_from_paintmode Currently harmless (since atm. it is not possible to trigger this part of the code from curves sculpting), but in a future fix (for T101518), it would be good to use `BKE_paint_init` (and having the correct ob_mode for the brush would be nice). Differential Revision: https://developer.blender.org/D16286 --- source/blender/blenkernel/intern/paint.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 13243925b28..408cd117e32 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1043,6 +1043,8 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode) return OB_MODE_TEXTURE_PAINT; case PAINT_MODE_SCULPT_UV: return OB_MODE_EDIT; + case PAINT_MODE_SCULPT_CURVES: + return OB_MODE_SCULPT_CURVES; case PAINT_MODE_INVALID: default: return OB_MODE_OBJECT; -- cgit v1.2.3 From 4163c63def98b46fe7ddba82ade997c818ab2b96 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 15:40:54 +0200 Subject: Curves sculptmode: fix missing mode and tool in Brush Specials For consistency with other brush based (paint) systems we should add these entries in the brushes context menu. For this, expose the brushes `ob_mode` to RNA and show this (along with the tool choice) to the appropriate menus. Differential Revision: https://developer.blender.org/D16287 --- release/scripts/startup/bl_ui/space_view3d.py | 1 + release/scripts/startup/bl_ui/space_view3d_toolbar.py | 2 ++ source/blender/makesrna/intern/rna_brush.c | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index ea257498e11..39684aaf161 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -3018,6 +3018,7 @@ class VIEW3D_MT_brush_paint_modes(Menu): layout.prop(brush, "use_paint_vertex", text="Vertex Paint") layout.prop(brush, "use_paint_weight", text="Weight Paint") layout.prop(brush, "use_paint_image", text="Texture Paint") + layout.prop(brush, "use_paint_sculpt_curves", text="Sculpt Curves") class VIEW3D_MT_paint_vertex(Menu): diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index a28e93c34d1..fec156580cf 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -52,6 +52,8 @@ class VIEW3D_MT_brush_context_menu(Menu): elif context.sculpt_object: layout.prop_menu_enum(brush, "sculpt_tool") layout.operator("brush.reset") + elif context.tool_settings.curves_sculpt: + layout.prop_menu_enum(brush, "curves_sculpt_tool") class VIEW3D_MT_brush_gpencil_context_menu(Menu): diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 35e01be366b..137020ce3f8 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -3616,6 +3616,10 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Vertex", "Use this brush in grease pencil vertex color mode"); + prop = RNA_def_property(srna, "use_paint_sculpt_curves", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ob_mode", OB_MODE_SCULPT_CURVES); + RNA_def_property_ui_text(prop, "Use Sculpt", "Use this brush in sculpt curves mode"); + /* texture */ prop = RNA_def_property(srna, "texture_slot", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "BrushTextureSlot"); -- cgit v1.2.3 From a450a2f2b288c5105f0d0522c440e82fb498e117 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 09:18:47 +0200 Subject: Fix T101903: Crash when deleting library in some cases. Remapping in batch deletion could end up calling viewlayer resync code on partially invalid BMain (some IDs still in Main using IDs removed from Main). Think this code can actually be further optimized, but this fix should be safe enough for 3.3 (and potentially 2.93). Thanks to Jeroen (@jbakker) for the initial investigation. --- source/blender/blenkernel/intern/lib_id_delete.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index f4f5ca7a1d7..aaf932accf1 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -23,6 +23,7 @@ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_remap.h" @@ -217,6 +218,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BKE_main_lock(bmain); if (do_tagged_deletion) { + BKE_layer_collection_resync_forbid(); /* Main idea of batch deletion is to remove all IDs to be deleted from Main database. * This means that we won't have to loop over all deleted IDs to remove usages * of other deleted IDs. @@ -279,6 +281,9 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) } } + BKE_layer_collection_resync_allow(); + BKE_main_collection_sync_remap(bmain); + /* Now we can safely mark that ID as not being in Main database anymore. */ /* NOTE: This needs to be done in a separate loop than above, otherwise some user-counts of * deleted IDs may not be properly decreased by the remappings (since `NO_MAIN` ID user-counts -- cgit v1.2.3 From 358155a8da60760acc9baf554a449bbaf277085e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 10:17:33 +0200 Subject: Make batch ID deletion 100 times faster. Simplify and optimize remapping handling in bacth ID deletion, by moving it outside of the initial loop gathering all IDs to be deleted, and and by using batch remapping code. Speedup can be over 100 times faster in complex production scenes using thousands of IDs, when e.g. deleting a whole library. Examples before/after times on my machine (deleting two different libraries): lib1: 5.55 sec/0.03 sec lib2: 13.60 sec/0.13 sec Found while investigating T101903. --- source/blender/blenkernel/intern/lib_id_delete.c | 64 +++++++++++++----------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index aaf932accf1..a2236089093 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -16,6 +16,7 @@ #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BKE_anim_data.h" @@ -27,7 +28,6 @@ #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_remap.h" -#include "BKE_library.h" #include "BKE_main.h" #include "BKE_main_namemap.h" @@ -203,7 +203,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) { const int tag = LIB_TAG_DOIT; ListBase *lbarray[INDEX_ID_MAX]; - Link dummy_link = {0}; int base_count, i; /* Used by batch tagged deletion, when we call BKE_id_free then, id is no more in Main database, @@ -218,7 +217,8 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BKE_main_lock(bmain); if (do_tagged_deletion) { - BKE_layer_collection_resync_forbid(); + struct IDRemapper *id_remapper = BKE_id_remapper_create(); + /* Main idea of batch deletion is to remove all IDs to be deleted from Main database. * This means that we won't have to loop over all deleted IDs to remove usages * of other deleted IDs. @@ -229,7 +229,6 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) bool keep_looping = true; while (keep_looping) { ID *id, *id_next; - ID *last_remapped_id = tagged_deleted_ids.last; keep_looping = false; /* First tag and remove from Main all datablocks directly from target lib. @@ -245,6 +244,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BLI_remlink(lb, id); BKE_main_namemap_remove_name(bmain, id, id->name + 2); BLI_addtail(&tagged_deleted_ids, id); + BKE_id_remapper_add(id_remapper, id, NULL); /* Do not tag as no_main now, we want to unlink it first (lower-level ID management * code has some specific handling of 'no main' IDs that would be a problem in that * case). */ @@ -253,34 +253,38 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) } } } - if (last_remapped_id == NULL) { - dummy_link.next = tagged_deleted_ids.first; - last_remapped_id = (ID *)(&dummy_link); - } - for (id = last_remapped_id->next; id; id = id->next) { - /* Will tag 'never NULL' users of this ID too. - * - * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect - * links, this can lead to nasty crashing here in second, actual deleting loop. - * Also, this will also flag users of deleted data that cannot be unlinked - * (object using deleted obdata, etc.), so that they also get deleted. */ - BKE_libblock_remap_locked(bmain, - id, - NULL, - (ID_REMAP_FLAG_NEVER_NULL_USAGE | - ID_REMAP_FORCE_NEVER_NULL_USAGE | - ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS)); - /* Since we removed ID from Main, - * we also need to unlink its own other IDs usages ourself. */ - BKE_libblock_relink_ex( - bmain, - id, - NULL, - NULL, - (ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | ID_REMAP_SKIP_USER_CLEAR)); - } } + BKE_layer_collection_resync_forbid(); + + /* Will tag 'never NULL' users of this ID too. + * + * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect + * links, this can lead to nasty crashing here in second, actual deleting loop. + * Also, this will also flag users of deleted data that cannot be unlinked + * (object using deleted obdata, etc.), so that they also get deleted. */ + BKE_libblock_remap_multiple_locked(bmain, + id_remapper, + ID_REMAP_FLAG_NEVER_NULL_USAGE | + ID_REMAP_FORCE_NEVER_NULL_USAGE | + ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS); + BKE_id_remapper_clear(id_remapper); + + /* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */ + LinkNode *cleanup_ids = NULL; + for (ID *id = tagged_deleted_ids.first; id; id = id->next) { + BLI_linklist_prepend(&cleanup_ids, id); + } + BKE_libblock_relink_multiple(bmain, + cleanup_ids, + ID_REMAP_TYPE_CLEANUP, + id_remapper, + ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS | + ID_REMAP_SKIP_USER_CLEAR); + + BKE_id_remapper_free(id_remapper); + BLI_linklist_free(cleanup_ids, NULL); + BKE_layer_collection_resync_allow(); BKE_main_collection_sync_remap(bmain); -- cgit v1.2.3 From e5782df4aba90ca70fca9a949e5b546abdb12ec3 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 10:27:56 +0200 Subject: Fix (unreported) error messages about invalid ID usercount when batch-deleting IDs. Batch-delete by-passes a lot of ID usages handling in to-be-deleted IDs, so usercount of deleted IDs needs to be manually reset to avoid the annoying error messages in the console. --- source/blender/blenkernel/intern/lib_id_delete.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index a2236089093..ae5dc75c36a 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -294,6 +294,10 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) * is never affected). */ for (ID *id = tagged_deleted_ids.first; id; id = id->next) { id->tag |= LIB_TAG_NO_MAIN; + /* Usercount needs to be reset artificially, since some usages may not be cleared in batch + * deletion (typically, if one deleted ID uses another deleted ID, this may not be cleared by + * remapping code, depending on order in which these are handled). */ + id->us = ID_FAKE_USERS(id); } } else { -- cgit v1.2.3 From 2180e6fc9ffb173e1a36e2668f048d18cf3940f2 Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 13 Sep 2022 13:19:15 +0200 Subject: Curves: make the "surface_uv_map" a searchable dropdown The users had to type in a name here, but we can also make it a dropdown choice with existing UV Maps for convenience: - dont have to remember a name or copy paste obviously - shows in red if it was removed / invalid Came up in T101028 Maniphest Tasks: T101028 Differential Revision: https://developer.blender.org/D15956 --- release/scripts/startup/bl_ui/properties_data_curves.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/properties_data_curves.py b/release/scripts/startup/bl_ui/properties_data_curves.py index ff0eabeb7d9..df80bdb4552 100644 --- a/release/scripts/startup/bl_ui/properties_data_curves.py +++ b/release/scripts/startup/bl_ui/properties_data_curves.py @@ -44,7 +44,13 @@ class DATA_PT_curves_surface(DataButtonsPanel, Panel): layout.use_property_split = True layout.prop(ob.data, "surface") - layout.prop(ob.data, "surface_uv_map", text="UV Map") + has_surface = ob.data.surface is not None + if has_surface: + layout.prop_search(ob.data, "surface_uv_map", ob.data.surface.data, "uv_layers", text="UV Map") + else: + row = layout.row() + row.prop(ob.data, "surface_uv_map", text="UV Map") + row.enabled = has_surface class CURVES_MT_add_attribute(Menu): -- cgit v1.2.3 From b51763a773009d887460bac14e9f7b65cbf54e5b Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Tue, 18 Oct 2022 10:30:37 +0200 Subject: Fix T101888: Curves editmode: modifiers "Display in Edit mode" no effect Add the eModifierMode_Editmode to the required modes for curves modifier evaluation. Only this way the modifier can be skipped in evaluation. Maniphest Tasks: T101888 Differential Revision: https://developer.blender.org/D16280 --- source/blender/blenkernel/intern/curves.cc | 5 ++++- source/blender/blenkernel/intern/object.cc | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc index 01be22a57b0..72e53023d6d 100644 --- a/source/blender/blenkernel/intern/curves.cc +++ b/source/blender/blenkernel/intern/curves.cc @@ -287,7 +287,10 @@ static void curves_evaluate_modifiers(struct Depsgraph *depsgraph, { /* Modifier evaluation modes. */ const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + if (BKE_object_is_in_editmode(object)) { + required_mode = (ModifierMode)(int(required_mode) | eModifierMode_Editmode); + } ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 2d949fb5c65..d98f5e85028 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -1902,6 +1902,7 @@ bool BKE_object_is_in_editmode(const Object *ob) /* Grease Pencil object has no edit mode data. */ return GPENCIL_EDIT_MODE((bGPdata *)ob->data); case OB_CURVES: + /* Curves object has no edit mode data. */ return ob->mode == OB_MODE_EDIT; default: return false; -- cgit v1.2.3 From d4b8e9b69fccf96a3c8035418a9fc1f00f43dee1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 17:02:40 +1100 Subject: Cleanup: format --- source/blender/gpu/metal/mtl_batch.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm index 0d9a3225a51..988fb9b793b 100644 --- a/source/blender/gpu/metal/mtl_batch.mm +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -595,8 +595,10 @@ void MTLBatch::prepare_vertex_descriptor_and_bindings( desc.reset_vertex_descriptor(); /* Fetch Vertex and Instance Buffers. */ - Span mtl_verts(reinterpret_cast(this->verts), GPU_BATCH_VBO_MAX_LEN); - Span mtl_inst(reinterpret_cast(this->inst), GPU_BATCH_INST_VBO_MAX_LEN); + Span mtl_verts(reinterpret_cast(this->verts), + GPU_BATCH_VBO_MAX_LEN); + Span mtl_inst(reinterpret_cast(this->inst), + GPU_BATCH_INST_VBO_MAX_LEN); /* SSBO Vertex fetch also passes vertex descriptor information into the shader. */ if (active_shader_->get_uses_ssbo_vertex_fetch()) { -- cgit v1.2.3 From 89525fae59eaac8fe1d63a948b454ac9ce921f05 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 17:09:29 +1100 Subject: Cleanup: CMake include paths Remove redundant separators & redundant references to parent paths. --- intern/cycles/app/CMakeLists.txt | 5 ++++- intern/ghost/CMakeLists.txt | 2 +- source/blender/compositor/realtime_compositor/CMakeLists.txt | 2 +- source/blender/io/stl/CMakeLists.txt | 2 +- source/blender/io/wavefront_obj/CMakeLists.txt | 4 ++-- source/blender/makesdna/intern/CMakeLists.txt | 2 +- source/blender/makesrna/intern/CMakeLists.txt | 2 +- source/blender/nodes/texture/CMakeLists.txt | 2 +- 8 files changed, 12 insertions(+), 9 deletions(-) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 0988b1c0ac4..1c7a861ea93 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -43,7 +43,10 @@ else() endif() if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) - list(APPEND INC_SYS ${Epoxy_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS}) + list(APPEND INC_SYS + ${Epoxy_INCLUDE_DIRS} + ${SDL2_INCLUDE_DIRS} + ) list(APPEND LIB ${Epoxy_LIBRARIES} ${SDL2_LIBRARIES}) endif() diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 2f8ea1f9065..72621648608 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -268,7 +268,7 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) if(WITH_GHOST_WAYLAND_DYNLOAD) list(APPEND INC_SYS - ../../intern/wayland_dynload/extern + ../wayland_dynload/extern ) list(APPEND LIB bf_intern_wayland_dynload diff --git a/source/blender/compositor/realtime_compositor/CMakeLists.txt b/source/blender/compositor/realtime_compositor/CMakeLists.txt index 90cbe0988ad..bab0b5385ec 100644 --- a/source/blender/compositor/realtime_compositor/CMakeLists.txt +++ b/source/blender/compositor/realtime_compositor/CMakeLists.txt @@ -2,7 +2,7 @@ set(INC . - ./algorithms + algorithms ../../blenkernel ../../blenlib ../../gpu diff --git a/source/blender/io/stl/CMakeLists.txt b/source/blender/io/stl/CMakeLists.txt index 3a21da5c579..f7eb933d198 100644 --- a/source/blender/io/stl/CMakeLists.txt +++ b/source/blender/io/stl/CMakeLists.txt @@ -2,7 +2,7 @@ set(INC . - ./importer + importer ../common ../../blenkernel ../../blenlib diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt b/source/blender/io/wavefront_obj/CMakeLists.txt index f7958ef4ec6..bfbc715a45f 100644 --- a/source/blender/io/wavefront_obj/CMakeLists.txt +++ b/source/blender/io/wavefront_obj/CMakeLists.txt @@ -2,8 +2,8 @@ set(INC . - ./exporter - ./importer + exporter + importer ../common ../../blenkernel ../../blenlib diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 0d04d7df067..50fd51e88a1 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -116,8 +116,8 @@ blender_add_lib(bf_dna "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") # ----------------------------------------------------------------------------- # Build bf_dna_blenlib library set(INC + .. ../../blenlib - ../../makesdna ../../../../intern/atomic ../../../../intern/guardedalloc ) diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 2b06daf34e3..f028b199098 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -200,7 +200,7 @@ set(INC ../../imbuf ../../makesdna ../../modifiers - ../../nodes/ + ../../nodes ../../sequencer ../../simulation ../../windowmanager diff --git a/source/blender/nodes/texture/CMakeLists.txt b/source/blender/nodes/texture/CMakeLists.txt index 77db71d4b1a..2d704ac2228 100644 --- a/source/blender/nodes/texture/CMakeLists.txt +++ b/source/blender/nodes/texture/CMakeLists.txt @@ -2,7 +2,7 @@ set(INC . - ../ + .. ../intern ../../editors/include ../../blenkernel -- cgit v1.2.3 From ec638d3108a18f7f955d72290a9c246d54edb3ef Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 21:33:59 +1100 Subject: GHOST/Wayland: only prioritize discrete scroll for mouse wheel events Smooth & discrete scrolling may both be set, instead of always prioritizing discrete, use discrete scrolling when the source is a mouse wheel, otherwise prioritize smooth scrolling. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 84 ++++++++++++++++++----------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 62f96e4e620..37049e646bd 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -141,8 +141,7 @@ static bool use_gnome_confine_hack = false; * \{ */ /** - * The event codes are used to - * to differentiate from which mouse button an event comes from. + * The event codes are used to differentiate from which mouse button an event comes from. */ #define BTN_LEFT 0x110 #define BTN_RIGHT 0x111 @@ -341,11 +340,6 @@ struct GWL_SeatStatePointer { */ wl_fixed_t xy[2] = {0, 0}; - /** Smooth scrolling (handled & reset with pointer "frame" callback). */ - wl_fixed_t scroll_xy[2] = {0, 0}; - /** Discrete scrolling (handled & reset with pointer "frame" callback). */ - int32_t scroll_discrete_xy[2] = {0, 0}; - /** Outputs on which the cursor is visible. */ std::unordered_set outputs; @@ -363,6 +357,19 @@ struct GWL_SeatStatePointer { GHOST_Buttons buttons = GHOST_Buttons(); }; +/** + * Scroll state, applying to pointer (not tablet) events. + * Otherwise this would be part of #GWL_SeatStatePointer. + */ +struct GWL_SeatStatePointerScroll { + /** Smooth scrolling (handled & reset with pointer "frame" callback). */ + wl_fixed_t smooth_xy[2] = {0, 0}; + /** Discrete scrolling (handled & reset with pointer "frame" callback). */ + int32_t discrete_xy[2] = {0, 0}; + /** The source of scroll event. */ + enum wl_pointer_axis_source axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; +}; + /** * State of the keyboard (in #GWL_Seat). */ @@ -433,6 +440,7 @@ struct GWL_Seat { uint32_t cursor_source_serial = 0; GWL_SeatStatePointer pointer; + GWL_SeatStatePointerScroll pointer_scroll; /** Mostly this can be interchanged with `pointer` however it can't be locked/confined. */ GWL_SeatStatePointer tablet; @@ -1756,10 +1764,11 @@ static void pointer_handle_enter(void *data, /* Resetting scroll events is likely unnecessary, * do this to avoid any possible problems as it's harmless. */ - seat->pointer.scroll_xy[0] = 0; - seat->pointer.scroll_xy[1] = 0; - seat->pointer.scroll_discrete_xy[0] = 0; - seat->pointer.scroll_discrete_xy[1] = 0; + seat->pointer_scroll.smooth_xy[0] = 0; + seat->pointer_scroll.smooth_xy[1] = 0; + seat->pointer_scroll.discrete_xy[0] = 0; + seat->pointer_scroll.discrete_xy[1] = 0; + seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; seat->pointer.wl_surface = wl_surface; @@ -1886,7 +1895,7 @@ static void pointer_handle_axis(void *data, return; } GWL_Seat *seat = static_cast(data); - seat->pointer.scroll_xy[index] = value; + seat->pointer_scroll.smooth_xy[index] = value; } static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) @@ -1894,29 +1903,39 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) CLOG_INFO(LOG, 2, "frame"); GWL_Seat *seat = static_cast(data); - /* Discrete steps may generate non-discrete scrolling, in this case, - * give the mouse wheel priority otherwise mouse wheel events would be recognized - * as touch-pad scrolling too. */ - if (seat->pointer.scroll_discrete_xy[0]) { - seat->pointer.scroll_xy[0] = 0; + /* Both discrete and smooth events may be set at once, never generate events for both + * as this will be handling the same event in to different ways. + * Prioritize discrete axis events for the mouse wheel, otherwise smooth scroll. */ + if (seat->pointer_scroll.axis_source == WL_POINTER_AXIS_SOURCE_WHEEL) { + if (seat->pointer_scroll.discrete_xy[0]) { + seat->pointer_scroll.smooth_xy[0] = 0; + } + if (seat->pointer_scroll.discrete_xy[1]) { + seat->pointer_scroll.smooth_xy[1] = 0; + } } - if (seat->pointer.scroll_discrete_xy[1]) { - seat->pointer.scroll_xy[1] = 0; + else { + if (seat->pointer_scroll.smooth_xy[0]) { + seat->pointer_scroll.discrete_xy[0] = 0; + } + if (seat->pointer_scroll.smooth_xy[1]) { + seat->pointer_scroll.discrete_xy[1] = 0; + } } /* Discrete X axis currently unsupported. */ - if (seat->pointer.scroll_discrete_xy[1]) { + if (seat->pointer_scroll.discrete_xy[1]) { if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); - const int32_t discrete = seat->pointer.scroll_discrete_xy[1]; + const int32_t discrete = seat->pointer_scroll.discrete_xy[1]; seat->system->pushEvent(new GHOST_EventWheel( seat->system->getMilliSeconds(), win, std::signbit(discrete) ? +1 : -1)); } - seat->pointer.scroll_discrete_xy[0] = 0; - seat->pointer.scroll_discrete_xy[1] = 0; + seat->pointer_scroll.discrete_xy[0] = 0; + seat->pointer_scroll.discrete_xy[1] = 0; } - if (seat->pointer.scroll_xy[0] || seat->pointer.scroll_xy[1]) { + if (seat->pointer_scroll.smooth_xy[0] || seat->pointer_scroll.smooth_xy[1]) { if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus); const wl_fixed_t scale = win->scale(); @@ -1926,21 +1945,26 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) GHOST_kTrackpadEventScroll, wl_fixed_to_int(scale * seat->pointer.xy[0]), wl_fixed_to_int(scale * seat->pointer.xy[1]), - wl_fixed_to_int(seat->pointer.scroll_xy[0]), - wl_fixed_to_int(seat->pointer.scroll_xy[1]), + /* NOTE: scaling the delta doesn't seem necessary. */ + wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]), + wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]), /* TODO: investigate a way to request this configuration from the system. */ true)); } - seat->pointer.scroll_xy[0] = 0; - seat->pointer.scroll_xy[1] = 0; + seat->pointer_scroll.smooth_xy[0] = 0; + seat->pointer_scroll.smooth_xy[1] = 0; } + + seat->pointer_scroll.axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; } -static void pointer_handle_axis_source(void * /*data*/, +static void pointer_handle_axis_source(void *data, struct wl_pointer * /*wl_pointer*/, uint32_t axis_source) { CLOG_INFO(LOG, 2, "axis_source (axis_source=%u)", axis_source); + GWL_Seat *seat = static_cast(data); + seat->pointer_scroll.axis_source = (enum wl_pointer_axis_source)axis_source; } static void pointer_handle_axis_stop(void * /*data*/, struct wl_pointer * /*wl_pointer*/, @@ -1962,7 +1986,7 @@ static void pointer_handle_axis_discrete(void *data, return; } GWL_Seat *seat = static_cast(data); - seat->pointer.scroll_discrete_xy[index] = discrete; + seat->pointer_scroll.discrete_xy[index] = discrete; } static const struct wl_pointer_listener pointer_listener = { -- cgit v1.2.3 From f0fba1a2d8deb7e92ccb217361a378f8fcc29d9b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 19 Oct 2022 21:48:42 +1100 Subject: GHOST/Wayland: invert touch-pad scrolling This should use the system preference for scroll direction eventually, for now default to a down-motion scrolling down (matching GTK & QT). --- intern/ghost/intern/GHOST_SystemWayland.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 37049e646bd..9f018d039b1 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1945,11 +1945,12 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/) GHOST_kTrackpadEventScroll, wl_fixed_to_int(scale * seat->pointer.xy[0]), wl_fixed_to_int(scale * seat->pointer.xy[1]), - /* NOTE: scaling the delta doesn't seem necessary. */ - wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]), - wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]), + /* NOTE: scaling the delta doesn't seem necessary. + * NOTE: inverting delta gives correct results, see: QTBUG-85767. */ + -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[0]), + -wl_fixed_to_int(seat->pointer_scroll.smooth_xy[1]), /* TODO: investigate a way to request this configuration from the system. */ - true)); + false)); } seat->pointer_scroll.smooth_xy[0] = 0; -- cgit v1.2.3 From 3ac2f15a04c5c5425e086427170b5d1b2f559e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 14:40:27 +0200 Subject: GL: Fix incorrect shader state after shader interface creation The interface needs to bind the shaders for some parameter setup. This program change wasn't reflected in the GPUContext. This was then conflicting with the next shader bind if the next shader was the same as the shader bound before the interface creation. Setting the state to the correct shader ensures a rebind if needed. Fix T101792 New hair curves do not render properly first time in EEVEE with motion blur enabled --- source/blender/gpu/opengl/gl_shader.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index dafcf4dbf33..f6f14932de7 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -1004,6 +1004,11 @@ bool GLShader::finalize(const shader::ShaderCreateInfo *info) else { interface = new GLShaderInterface(shader_program_); } + /** + * WORKAROUND: Creating the shader interface changes the active program. + * Make sure to update the context, otherwise we might have a missing bind. + */ + Context::get()->shader = this; return true; } -- cgit v1.2.3 From ead3fc4a075d24e3481dfebdc63d54e7143a027c Mon Sep 17 00:00:00 2001 From: Pratik Borhade Date: Wed, 19 Oct 2022 18:20:47 +0530 Subject: Fix T99997: Calling teleport without waiting for the previous event disables gravity During teleport event, gravity is disabled and WalkMethod is stored in `teleport.navigation_mode` which is used later to reset the status after execution. Calling teleport events consecutively will change the initial WalkMethod value. So update it only on the first call. Also remove `else condition` as it stops the previously running teleport when the new teleport call fails to find a hit point. Reviewed by: dfelinto, mano-wii Differential Revision: https://developer.blender.org/D15574 --- source/blender/editors/space_view3d/view3d_navigate_walk.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 3e0ce892b5a..aea322d73d9 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -849,11 +849,15 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event) if (ret) { WalkTeleport *teleport = &walk->teleport; + + /* Store the current navigation mode if we are not already teleporting. */ + if (teleport->state == WALK_TELEPORT_STATE_OFF) { + teleport->navigation_mode = walk->navigation_mode; + } teleport->state = WALK_TELEPORT_STATE_ON; teleport->initial_time = PIL_check_seconds_timer(); teleport->duration = U.walk_navigation.teleport_time; - teleport->navigation_mode = walk->navigation_mode; walk_navigation_mode_set(walk, WALK_MODE_FREE); copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]); @@ -864,9 +868,7 @@ static void walkEvent(WalkInfo *walk, const wmEvent *event) sub_v3_v3v3(teleport->direction, loc, teleport->origin); } - else { - walk->teleport.state = WALK_TELEPORT_STATE_OFF; - } + break; } -- cgit v1.2.3 From 3655eb7ff0e87c2cf6b17d0268253921fbeb8ea7 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 19 Oct 2022 15:13:15 +0200 Subject: Blender: Add command line argument to switch gpu backends. Add command line argument to switch gpu backend. Add `--gpu-backend` option to override the gpu backend selected by Blender. Values for this option that will be available in releases for now are: * opengl: Force blender to select OpenGL backend. During development and depending on compile options additional values can exist: * metal: Force Blender to select Metal backend. When this option isn't provided the internal logic for GPU backend selection will be used. Note that this is at the time of writing the same as always selecting the opengl backend. Reviewed By: fclem, brecht, MichaelPW Differential Revision: https://developer.blender.org/D16297 --- intern/ghost/GHOST_C-api.h | 2 - intern/ghost/GHOST_ISystem.h | 2 - intern/ghost/GHOST_Types.h | 12 ++++-- intern/ghost/intern/GHOST_C-api.cpp | 2 - intern/ghost/intern/GHOST_ContextCGL.h | 3 +- intern/ghost/intern/GHOST_ContextCGL.mm | 4 +- intern/ghost/intern/GHOST_System.cpp | 2 +- intern/ghost/intern/GHOST_SystemCocoa.h | 2 - intern/ghost/intern/GHOST_SystemCocoa.mm | 5 +-- intern/ghost/intern/GHOST_SystemHeadless.h | 3 +- intern/ghost/intern/GHOST_SystemSDL.cpp | 3 +- intern/ghost/intern/GHOST_SystemSDL.h | 1 - intern/ghost/intern/GHOST_SystemWayland.cpp | 3 +- intern/ghost/intern/GHOST_SystemWayland.h | 1 - intern/ghost/intern/GHOST_SystemWin32.cpp | 3 +- intern/ghost/intern/GHOST_SystemWin32.h | 2 - intern/ghost/intern/GHOST_SystemX11.cpp | 4 +- intern/ghost/intern/GHOST_SystemX11.h | 2 - intern/ghost/intern/GHOST_WindowCocoa.mm | 4 +- intern/ghost/test/gears/GHOST_Test.cpp | 21 +++------- source/blender/gpu/GPU_context.h | 2 + source/blender/gpu/intern/gpu_context.cc | 12 +++++- source/blender/gpu/intern/gpu_shader_builder.cc | 49 +++++++++++++++++++--- .../blender/gpu/intern/gpu_shader_builder_stubs.cc | 9 ++++ source/blender/windowmanager/intern/wm_playanim.c | 5 ++- source/blender/windowmanager/intern/wm_window.c | 21 +++++++++- .../windowmanager/intern/wm_window_private.h | 5 +++ source/creator/creator_args.c | 44 +++++++++++++++++++ 28 files changed, 166 insertions(+), 62 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 7fda535a7ac..62984c762c1 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -162,7 +162,6 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, * \param height: The height the window. * \param state: The state of the window when opened. * \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL options. * \return A handle to the new window ( == NULL if creation failed). */ @@ -175,7 +174,6 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, uint32_t height, GHOST_TWindowState state, bool is_dialog, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings); /** diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 9fb94ed1525..64b5f4ee496 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -232,7 +232,6 @@ class GHOST_ISystem { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized. @@ -245,7 +244,6 @@ class GHOST_ISystem { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 2645ce448b0..db4eeff3122 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -60,10 +60,6 @@ typedef struct { int hot_spot[2]; } GHOST_CursorBitmapRef; -typedef struct { - int flags; -} GHOST_GLSettings; - typedef enum { GHOST_glStereoVisual = (1 << 0), GHOST_glDebugContext = (1 << 1), @@ -157,6 +153,9 @@ typedef enum { #ifdef WIN32 GHOST_kDrawingContextTypeD3D, #endif +#ifdef __APPLE__ + GHOST_kDrawingContextTypeMetal, +#endif } GHOST_TDrawingContextType; typedef enum { @@ -598,6 +597,11 @@ typedef struct { uint32_t frequency; } GHOST_DisplaySetting; +typedef struct { + int flags; + GHOST_TDrawingContextType context_type; +} GHOST_GLSettings; + typedef enum { /** Axis that cursor grab will wrap. */ GHOST_kDebugDefault = (1 << 1), diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 158e979cdf2..aa2363c10b3 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -161,7 +161,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, uint32_t height, GHOST_TWindowState state, bool is_dialog, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; @@ -172,7 +171,6 @@ GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, width, height, state, - type, glSettings, false, is_dialog, diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h index 130b926f25c..d19fffffb43 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.h +++ b/intern/ghost/intern/GHOST_ContextCGL.h @@ -30,7 +30,8 @@ class GHOST_ContextCGL : public GHOST_Context { GHOST_ContextCGL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, - NSOpenGLView *openglView); + NSOpenGLView *openglView, + GHOST_TDrawingContextType type); /** * Destructor. diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index ff53ecdbbba..9dad337a5d6 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -46,8 +46,10 @@ int GHOST_ContextCGL::s_sharedCount = 0; GHOST_ContextCGL::GHOST_ContextCGL(bool stereoVisual, NSView *metalView, CAMetalLayer *metalLayer, - NSOpenGLView *openGLView) + NSOpenGLView *openGLView, + GHOST_TDrawingContextType type) : GHOST_Context(stereoVisual), + m_useMetalForRendering(type == GHOST_kDrawingContextTypeMetal), m_metalView(metalView), m_metalLayer(metalLayer), m_metalCmdQueue(nil), diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 94d021fd822..670ede35989 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -384,6 +384,7 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, if (stereoVisual) { glSettings.flags |= GHOST_glStereoVisual; } + glSettings.context_type = GHOST_kDrawingContextTypeOpenGL; /* NOTE: don't use #getCurrentDisplaySetting() because on X11 we may * be zoomed in and the desktop may be bigger than the viewport. */ GHOST_ASSERT(m_displayManager, @@ -395,7 +396,6 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, settings.xPixels, settings.yPixels, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, glSettings, true /* exclusive */); return (*window == nullptr) ? GHOST_kFailure : GHOST_kSuccess; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index dbb41c7fddf..0211694aad4 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -77,7 +77,6 @@ class GHOST_SystemCocoa : public GHOST_System { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent (embedder) window. @@ -89,7 +88,6 @@ class GHOST_SystemCocoa : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index bfa90114e4c..a1016dd4843 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -689,7 +689,6 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -719,7 +718,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, width, height, state, - type, + glSettings.context_type, glSettings.flags & GHOST_glStereoVisual, glSettings.flags & GHOST_glDebugContext, is_dialog, @@ -751,7 +750,7 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title, */ GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings) { - GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL); + GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL, glSettings.context_type); if (context->initializeDrawingContext()) return context; else diff --git a/intern/ghost/intern/GHOST_SystemHeadless.h b/intern/ghost/intern/GHOST_SystemHeadless.h index b02a82fc9eb..66af65f763d 100644 --- a/intern/ghost/intern/GHOST_SystemHeadless.h +++ b/intern/ghost/intern/GHOST_SystemHeadless.h @@ -142,7 +142,6 @@ class GHOST_SystemHeadless : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool /*exclusive*/, const bool /*is_dialog*/, @@ -155,7 +154,7 @@ class GHOST_SystemHeadless : public GHOST_System { height, state, parentWindow, - type, + glSettings.context_type, ((glSettings.flags & GHOST_glStereoVisual) != 0)); } diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index ad5c4dc85fb..9174664adc4 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -42,7 +42,6 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool /* is_dialog */, @@ -57,7 +56,7 @@ GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title, width, height, state, - type, + glSettings.context_type, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive, parentWindow); diff --git a/intern/ghost/intern/GHOST_SystemSDL.h b/intern/ghost/intern/GHOST_SystemSDL.h index bee277ba674..385bfb841e3 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.h +++ b/intern/ghost/intern/GHOST_SystemSDL.h @@ -71,7 +71,6 @@ class GHOST_SystemSDL : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 9f018d039b1..2d16fd4cff5 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -3813,7 +3813,6 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, const uint32_t width, const uint32_t height, const GHOST_TWindowState state, - const GHOST_TDrawingContextType type, const GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -3833,7 +3832,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, height, state, parentWindow, - type, + glSettings.context_type, is_dialog, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive); diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 5d2cfe45582..ca78ccb89ab 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -128,7 +128,6 @@ class GHOST_SystemWayland : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 667198241f0..54c892d296e 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -213,7 +213,6 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -227,7 +226,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(const char *title, width, height, state, - type, + glSettings.context_type, ((glSettings.flags & GHOST_glStereoVisual) != 0), false, (GHOST_WindowWin32 *)parentWindow, diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index f5cd0055b34..98a7e5dfb35 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -103,7 +103,6 @@ class GHOST_SystemWin32 : public GHOST_System { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent window. @@ -115,7 +114,6 @@ class GHOST_SystemWin32 : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 4523f6fa37c..5c89febe97c 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -308,7 +308,6 @@ void GHOST_SystemX11::getAllDisplayDimensions(uint32_t &width, uint32_t &height) * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL settings. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent window. @@ -320,7 +319,6 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const bool is_dialog, @@ -341,7 +339,7 @@ GHOST_IWindow *GHOST_SystemX11::createWindow(const char *title, height, state, (GHOST_WindowX11 *)parentWindow, - type, + glSettings.context_type, is_dialog, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive, diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 572be30174d..1f071da6da7 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -113,7 +113,6 @@ class GHOST_SystemX11 : public GHOST_System { * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. - * \param type: The type of drawing context installed in this window. * \param stereoVisual: Create a stereo visual for quad buffered stereo. * \param exclusive: Use to show the window on top and ignore others (used full-screen). * \param parentWindow: Parent (embedder) window. @@ -125,7 +124,6 @@ class GHOST_SystemX11 : public GHOST_System { uint32_t width, uint32_t height, GHOST_TWindowState state, - GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive = false, const bool is_dialog = false, diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 737fd64bdf0..bc1f1e99a3a 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -803,10 +803,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType type) { - if (type == GHOST_kDrawingContextTypeOpenGL) { + if (type == GHOST_kDrawingContextTypeOpenGL || type == GHOST_kDrawingContextTypeMetal) { GHOST_Context *context = new GHOST_ContextCGL( - m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView); + m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView, type); if (context->initializeDrawingContext()) return context; diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index 1891f1eca77..3c9206b2010 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -407,17 +407,12 @@ Application::Application(GHOST_ISystem *system) stereo(false) { GHOST_GLSettings glSettings = {0}; + glSettings.context_type = GHOST_kDrawingContextTypeOpenGL; fApp = this; // Create the main window - m_mainWindow = system->createWindow("gears - main window", - 10, - 64, - 320, - 200, - GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, - glSettings); + m_mainWindow = system->createWindow( + "gears - main window", 10, 64, 320, 200, GHOST_kWindowStateNormal, glSettings); if (!m_mainWindow) { std::cout << "could not create main window\n"; @@ -425,14 +420,8 @@ Application::Application(GHOST_ISystem *system) } // Create a secondary window - m_secondaryWindow = system->createWindow("gears - secondary window", - 340, - 64, - 320, - 200, - GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, - glSettings); + m_secondaryWindow = system->createWindow( + "gears - secondary window", 340, 64, 320, 200, GHOST_kWindowStateNormal, glSettings); if (!m_secondaryWindow) { std::cout << "could not create secondary window\n"; exit(-1); diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h index b59ea9e55d2..ac82774039a 100644 --- a/source/blender/gpu/GPU_context.h +++ b/source/blender/gpu/GPU_context.h @@ -21,6 +21,8 @@ extern "C" { * automatically initializes the back-end, and #GPU_context_discard frees it when there * are no more contexts. */ bool GPU_backend_supported(void); +void GPU_backend_type_selection_set(const eGPUBackendType backend); +eGPUBackendType GPU_backend_type_selection_get(void); eGPUBackendType GPU_backend_get_type(void); /** Opaque type hiding blender::gpu::Context. */ diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc index 48d7b2019c5..f6b88c4231c 100644 --- a/source/blender/gpu/intern/gpu_context.cc +++ b/source/blender/gpu/intern/gpu_context.cc @@ -223,9 +223,19 @@ void GPU_render_step() /* NOTE: To enable Metal API, we need to temporarily change this to `GPU_BACKEND_METAL`. * Until a global switch is added, Metal also needs to be enabled in GHOST_ContextCGL: * `m_useMetalForRendering = true`. */ -static const eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; +static eGPUBackendType g_backend_type = GPU_BACKEND_OPENGL; static GPUBackend *g_backend = nullptr; +void GPU_backend_type_selection_set(const eGPUBackendType backend) +{ + g_backend_type = backend; +} + +eGPUBackendType GPU_backend_type_selection_get() +{ + return g_backend_type; +} + bool GPU_backend_supported(void) { switch (g_backend_type) { diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc index 3aa2963ecd0..9a67ddde5e6 100644 --- a/source/blender/gpu/intern/gpu_shader_builder.cc +++ b/source/blender/gpu/intern/gpu_shader_builder.cc @@ -15,6 +15,8 @@ #include "GPU_init_exit.h" #include "gpu_shader_create_info_private.hh" +#include "BLI_vector.hh" + #include "CLG_log.h" namespace blender::gpu::shader_builder { @@ -41,6 +43,22 @@ void ShaderBuilder::init() CLG_init(); GHOST_GLSettings glSettings = {0}; + switch (GPU_backend_type_selection_get()) { + case GPU_BACKEND_OPENGL: + glSettings.context_type = GHOST_kDrawingContextTypeOpenGL; + break; + +#ifdef WITH_METAL_BACKEND + case GPU_BACKEND_METAL: + glSettings.context_type = GHOST_kDrawingContextTypeMetal; + break; +#endif + + default: + BLI_assert_unreachable(); + break; + } + ghost_system_ = GHOST_CreateSystem(); ghost_context_ = GHOST_CreateOpenGLContext(ghost_system_, glSettings); GHOST_ActivateOpenGLContext(ghost_context_); @@ -73,13 +91,32 @@ int main(int argc, const char *argv[]) int exit_code = 0; - blender::gpu::shader_builder::ShaderBuilder builder; - builder.init(); - if (!builder.bake_create_infos()) { - exit_code = 1; + struct NamedBackend { + std::string name; + eGPUBackendType backend; + }; + + blender::Vector backends_to_validate; + backends_to_validate.append({"OpenGL", GPU_BACKEND_OPENGL}); +#ifdef WITH_METAL_BACKEND + backends_to_validate.append({"Metal", GPU_BACKEND_METAL}); +#endif + for (NamedBackend &backend : backends_to_validate) { + GPU_backend_type_selection_set(backend.backend); + if (!GPU_backend_supported()) { + printf("%s isn't supported on this platform. Shader compilation is skipped\n", + backend.name.c_str()); + continue; + } + blender::gpu::shader_builder::ShaderBuilder builder; + builder.init(); + if (!builder.bake_create_infos()) { + printf("Shader compilation failed for %s backend\n", backend.name.c_str()); + exit_code = 1; + } + builder.exit(); + exit(exit_code); } - builder.exit(); - exit(exit_code); return exit_code; } diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc index 7a06ede5c6d..65bda7ba858 100644 --- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc +++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc @@ -46,6 +46,15 @@ void IMB_freeImBuf(ImBuf * /*ibuf*/) BLI_assert_unreachable(); } +struct ImBuf *IMB_allocImBuf(unsigned int /*x*/, + unsigned int /*y*/, + unsigned char /*planes*/, + unsigned int /*flags*/) +{ + BLI_assert_unreachable(); + return nullptr; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index bf793ee41a0..3e5399a6f56 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -59,6 +59,8 @@ #include "DEG_depsgraph.h" +#include "wm_window_private.h" + #include "WM_api.h" /* only for WM_main_playanim */ #ifdef WITH_AUDASPACE @@ -1340,6 +1342,8 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey) { GHOST_GLSettings glsettings = {0}; + const eGPUBackendType gpu_backend = GPU_backend_type_selection_get(); + glsettings.context_type = wm_ghost_drawing_context_type(gpu_backend); uint32_t scr_w, scr_h; GHOST_GetMainDisplayDimensions(g_WS.ghost_system, &scr_w, &scr_h); @@ -1356,7 +1360,6 @@ static void playanim_window_open(const char *title, int posx, int posy, int size /* Could optionally start full-screen. */ GHOST_kWindowStateNormal, false, - GHOST_kDrawingContextTypeOpenGL, glsettings); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index b1b13390932..6b925b23dcb 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -556,6 +556,9 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, glSettings.flags |= GHOST_glDebugContext; } + eGPUBackendType gpu_backend = GPU_backend_type_selection_get(); + glSettings.context_type = wm_ghost_drawing_context_type(gpu_backend); + int scr_w, scr_h; wm_get_desktopsize(&scr_w, &scr_h); int posy = (scr_h - win->posy - win->sizey); @@ -573,7 +576,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, win->sizey, (GHOST_TWindowState)win->windowstate, is_dialog, - GHOST_kDrawingContextTypeOpenGL, glSettings); if (ghostwin) { @@ -1615,6 +1617,23 @@ const char *WM_ghost_backend(void) #endif } +GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend) +{ + switch (gpu_backend) { + case GPU_BACKEND_NONE: + return GHOST_kDrawingContextTypeNone; + case GPU_BACKEND_ANY: + case GPU_BACKEND_OPENGL: + return GHOST_kDrawingContextTypeOpenGL; +#ifdef WITH_METAL_BACKEND + case GPU_BACKEND_METAL: + return GHOST_kDrawingContextTypeMetal; +#endif + } + BLI_assert_unreachable(); + return GHOST_kDrawingContextTypeNone; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_window_private.h b/source/blender/windowmanager/intern/wm_window_private.h index f68d4e3e693..dad3e749817 100644 --- a/source/blender/windowmanager/intern/wm_window_private.h +++ b/source/blender/windowmanager/intern/wm_window_private.h @@ -7,8 +7,11 @@ #pragma once #include "BLI_sys_types.h" + #include "GHOST_Types.h" +#include "GPU_context.h" + /* *************** Message box *************** */ /* `WM_ghost_show_message_box` is implemented in `wm_windows.c` it is * defined here as it was implemented to be used for showing @@ -21,3 +24,5 @@ void WM_ghost_show_message_box(const char *title, const char *continue_label, const char *link, GHOST_DialogOptions dialog_options); + +GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gpu_backend); diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 06b898587bf..4144603555b 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -42,6 +42,8 @@ # include "BKE_scene.h" # include "BKE_sound.h" +# include "GPU_context.h" + # ifdef WITH_FFMPEG # include "IMB_imbuf.h" # endif @@ -1111,6 +1113,44 @@ static int arg_handle_debug_gpu_set(int UNUSED(argc), return 0; } +static const char arg_handle_gpu_backend_set_doc[] = + "\n" + "\tForce to use a specific GPU backend. Valid options: " +# ifdef WITH_METAL_BACKEND + "'metal', " +# endif + "'opengl')."; +static int arg_handle_gpu_backend_set(int argc, const char **argv, void *UNUSED(data)) +{ + if (argc == 0) { + printf("\nError: GPU backend must follow '--gpu-backend'.\n"); + return 0; + } + + eGPUBackendType gpu_backend = GPU_BACKEND_NONE; + + if (STREQ(argv[1], "opengl")) { + gpu_backend = GPU_BACKEND_OPENGL; + } +# ifdef WITH_METAL_BACKEND + else if (STREQ(argv[1], "metal")) { + gpu_backend = GPU_BACKEND_METAL; + } +# endif + else { + printf("\nError: Unrecognized GPU backend for '--gpu-backend'.\n"); + return 0; + } + + GPU_backend_type_selection_set(gpu_backend); + if (!GPU_backend_supported()) { + printf("\nError: GPU backend not supported.\n"); + return 0; + } + + return 1; +} + static const char arg_handle_debug_fpe_set_doc[] = "\n\t" "Enable floating-point exceptions."; @@ -2074,6 +2114,10 @@ void main_args_setup(bContext *C, bArgs *ba) BLI_args_add(ba, NULL, "--log-show-timestamp", CB(arg_handle_log_show_timestamp_set), ba); BLI_args_add(ba, NULL, "--log-file", CB(arg_handle_log_file_set), ba); + /* GPU backend selection should be part of ARG_PASS_ENVIRONMENT for correct GPU context selection + * for anim player. */ + BLI_args_add(ba, NULL, "--gpu-backend", CB(arg_handle_gpu_backend_set), NULL); + /* Pass: Background Mode & Settings * * Also and commands that exit after usage. */ -- cgit v1.2.3 From 6165395927cdd86a3ba48e53a4f3c2152cee2c0a Mon Sep 17 00:00:00 2001 From: Philipp Oeser Date: Wed, 19 Oct 2022 11:33:19 +0200 Subject: Fix T101922: transforming surface points misses redraw Oversight in rBf8b1483566cc which resulted in fonts/surfaces not having their draw caches being tagged dirty. Not only OB_CURVES_LEGACY have their object data of type ID_CU_LEGACY, but also OB_SURF/OB_FONT objects. Maniphest Tasks: T101922 Differential Revision: https://developer.blender.org/D16298 --- source/blender/blenkernel/intern/object_update.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc index ceef6404bf0..e53090bcffe 100644 --- a/source/blender/blenkernel/intern/object_update.cc +++ b/source/blender/blenkernel/intern/object_update.cc @@ -292,6 +292,8 @@ void BKE_object_batch_cache_dirty_tag(Object *ob) BKE_lattice_batch_cache_dirty_tag((struct Lattice *)ob->data, BKE_LATTICE_BATCH_DIRTY_ALL); break; case OB_CURVES_LEGACY: + case OB_SURF: + case OB_FONT: BKE_curve_batch_cache_dirty_tag((struct Curve *)ob->data, BKE_CURVE_BATCH_DIRTY_ALL); break; case OB_MBALL: { -- cgit v1.2.3 From 425e7ca3421d3a17651701d305140f490f5d2afc Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Wed, 19 Oct 2022 10:56:33 -0300 Subject: Fix T101928: transform operator properties saving wrong snap values The check for the flags should be `== 0` since they are describing a negative state. Thanks to @lone_noel for pointing out the error. --- source/blender/editors/transform/transform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 34e5b78c48f..919f4e5b85c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1594,9 +1594,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) RNA_enum_set(op->ptr, "snap_target", t->tsnap.source_select); eSnapTargetSelect target = t->tsnap.target_select; - RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) != 0); - RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) != 0); - RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) != 0); + RNA_boolean_set(op->ptr, "use_snap_self", (target & SCE_SNAP_TARGET_NOT_ACTIVE) == 0); + RNA_boolean_set(op->ptr, "use_snap_edit", (target & SCE_SNAP_TARGET_NOT_EDITED) == 0); + RNA_boolean_set(op->ptr, "use_snap_nonedit", (target & SCE_SNAP_TARGET_NOT_NONEDITED) == 0); RNA_boolean_set( op->ptr, "use_snap_selectable", (target & SCE_SNAP_TARGET_ONLY_SELECTABLE) != 0); } -- cgit v1.2.3 From 5d67fb0f18291d3aa6ee2bde0972cf90881f187c Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 10:06:28 +0200 Subject: Cycles: oneAPI: fix MSVC_TOOLS_DIR for some build environments MSVC Tools version doesn't match MSVC Redist version on some systems and it's not populated when using Ninja outside of Visual Studio shell, trying another way. --- intern/cycles/kernel/CMakeLists.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 36c8b23d983..dfd21c4e675 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -819,12 +819,17 @@ if(WITH_CYCLES_DEVICE_ONEAPI) -DONEAPI_EXPORT) string(REPLACE /Redist/ /Tools/ MSVC_TOOLS_DIR ${MSVC_REDIST_DIR}) - if(NOT CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) # case for Ninja on Windows + # Version Folder between Redist and Tools can mismatch sometimes + if(NOT EXISTS ${MSVC_TOOLS_DIR}) + get_filename_component(cmake_ar_dir ${CMAKE_AR} DIRECTORY) + get_filename_component(MSVC_TOOLS_DIR "${cmake_ar_dir}/../../../" ABSOLUTE) + endif() + if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION) + set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}) + else() # case for Ninja on Windows get_filename_component(cmake_mt_dir ${CMAKE_MT} DIRECTORY) string(REPLACE /bin/ /Lib/ WINDOWS_KIT_DIR ${cmake_mt_dir}) get_filename_component(WINDOWS_KIT_DIR "${WINDOWS_KIT_DIR}/../" ABSOLUTE) - else() - set(WINDOWS_KIT_DIR ${WINDOWS_KITS_DIR}/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}) endif() list(APPEND sycl_compiler_flags -L "${MSVC_TOOLS_DIR}/lib/x64" -- cgit v1.2.3 From d816bae7bf38069ab3f6ad9043fde0294af79c82 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 10:15:57 +0200 Subject: Cycles: oneAPI: fix check_usm for debug builds --- intern/cycles/device/oneapi/device_impl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp index 91f53fd1eae..f14eada071d 100644 --- a/intern/cycles/device/oneapi/device_impl.cpp +++ b/intern/cycles/device/oneapi/device_impl.cpp @@ -432,7 +432,8 @@ void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_ assert(usm_type == sycl::usm::alloc::device || ((device_type == sycl::info::device_type::host || device_type == sycl::info::device_type::cpu || allow_host) && - usm_type == sycl::usm::alloc::host)); + usm_type == sycl::usm::alloc::host || + usm_type == sycl::usm::alloc::unknown)); # else /* Silence warning about unused arguments. */ (void)queue_; -- cgit v1.2.3 From 2943997d2a09ab0dec8691b5cd155af2c655a049 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 11:03:01 +0200 Subject: Cycles: oneAPI: include sycl/sycl.hpp instead of CL/sycl.hpp Since SYCL 2020 API, sycl/sycl.hpp is the way. --- intern/cycles/device/oneapi/device_impl.h | 2 +- intern/cycles/kernel/device/oneapi/kernel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/cycles/device/oneapi/device_impl.h b/intern/cycles/device/oneapi/device_impl.h index 62034150eac..197cf03d60d 100644 --- a/intern/cycles/device/oneapi/device_impl.h +++ b/intern/cycles/device/oneapi/device_impl.h @@ -3,7 +3,7 @@ #ifdef WITH_ONEAPI -# include +# include # include "device/device.h" # include "device/oneapi/device.h" diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp index 40e0b1f0b2b..d15d6509d6a 100644 --- a/intern/cycles/kernel/device/oneapi/kernel.cpp +++ b/intern/cycles/kernel/device/oneapi/kernel.cpp @@ -8,7 +8,7 @@ # include # include -# include +# include # include "kernel/device/oneapi/compat.h" # include "kernel/device/oneapi/globals.h" -- cgit v1.2.3 From 86bb79e756fee32aa2dd1608b89a3fb3b36fda6f Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Mon, 17 Oct 2022 16:02:26 +0200 Subject: Cycles: oneAPI: update dg2 target to acm-g10 "dg2" target is deprecated from the GPU compiler/ocloc. We switch to targeting acm-g10 instead, for which generated binaries are compatible with other Arc GPUs. --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 408cf819ce8..bffd761f941 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -492,7 +492,8 @@ if(NOT APPLE) option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF) # https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html - set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") + # acm-g10 is the architecture for the first Arc Alchemist GPUs. + set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "acm-g10" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for") mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) -- cgit v1.2.3 From 5bfce9a822efef9a841614156255030821df564c Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 12:46:23 +0200 Subject: Cycles: oneAPI: preload kernels only when not using prebuilt binaries sycl::build triggers compilation even if prebuilt binaries are available, we'll have to find a better way in this case. --- intern/cycles/kernel/CMakeLists.txt | 2 ++ intern/cycles/kernel/device/oneapi/kernel.cpp | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index dfd21c4e675..e5d1c3d6563 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -767,6 +767,8 @@ if(WITH_CYCLES_DEVICE_ONEAPI) string(PREPEND CYCLES_ONEAPI_SYCL_OPTIONS_spir64_gen "-device ${CYCLES_ONEAPI_SPIR64_GEN_DEVICES} ") if (WITH_CYCLES_ONEAPI_BINARIES) + # AoT binaries aren't currently reused when calling sycl::build. + list (APPEND sycl_compiler_flags -DSYCL_SKIP_KERNELS_PRELOAD) # Iterate over all targest and their options list (JOIN CYCLES_ONEAPI_SYCL_TARGETS "," targets_string) list (APPEND sycl_compiler_flags -fsycl-targets=${targets_string}) diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp index d15d6509d6a..1f32d3406ea 100644 --- a/intern/cycles/kernel/device/oneapi/kernel.cpp +++ b/intern/cycles/kernel/device/oneapi/kernel.cpp @@ -144,6 +144,10 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue, bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features) { +# ifdef SYCL_SKIP_KERNELS_PRELOAD + (void)queue_; + (void)requested_features; +# else assert(queue_); sycl::queue *queue = reinterpret_cast(queue_); @@ -175,7 +179,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features) sycl::kernel_bundle one_kernel_bundle = sycl::get_kernel_bundle(queue->get_context(), {kernel_id}); - sycl::build(one_kernel_bundle, {queue->get_device()}, sycl::property::queue::in_order()); + sycl::build(one_kernel_bundle); } } catch (sycl::exception const &e) { @@ -184,7 +188,7 @@ bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features) } return false; } - +# endif return true; } -- cgit v1.2.3 From 151b653bd5f3460363663a65eb389025e7f9c38a Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 12:51:16 +0200 Subject: Cycles: oneAPI: fix clean Windows ninja builds Previously, a first build using ninja would throw "ninja: error: 'intern/cycles/kernel/cycles_kernel_oneapi.lib', needed by 'bin/blender.exe', missing and no known rule to make it". --- intern/cycles/kernel/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index e5d1c3d6563..6140e90042b 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -715,6 +715,7 @@ endif() if(WITH_CYCLES_DEVICE_ONEAPI) if(WIN32) set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll) + set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.lib) else() set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi.so) endif() @@ -851,7 +852,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI) -Xclang --dependent-lib=${sycl_library_debug_name}) add_custom_command( - OUTPUT ${cycles_kernel_oneapi_lib} + OUTPUT ${cycles_kernel_oneapi_lib} ${cycles_kernel_oneapi_linker_lib} COMMAND ${CMAKE_COMMAND} -E env "LIB=${sycl_compiler_root}/../lib" # for compiler to find sycl.lib "PATH=${OCLOC_INSTALL_DIR}\;${sycl_compiler_root}" -- cgit v1.2.3 From d763e294fc68226af320b9fe17ad50e2b21287ce Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 12:31:17 +0200 Subject: Cycles: oneAPI: fix libsycl.so files harvesting was missing libsycl.so.5.7.0-16 when using such version. --- build_files/cmake/platform/platform_unix.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 695ea3d773e..7f3acb142ce 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -341,10 +341,10 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI) endif() file(GLOB _sycl_runtime_libraries ${SYCL_ROOT_DIR}/lib/libsycl.so - ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9] - ${SYCL_ROOT_DIR}/lib/libsycl.so.[0-9].[0-9].[0-9]-[0-9] + ${SYCL_ROOT_DIR}/lib/libsycl.so.* ${SYCL_ROOT_DIR}/lib/libpi_level_zero.so ) + list(FILTER _sycl_runtime_libraries EXCLUDE REGEX ".*\.py") list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries}) unset(_sycl_runtime_libraries) endif() -- cgit v1.2.3 From ceb0e7fceae52d317833ed05e6ee0b2852ad170d Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 19 Oct 2022 16:47:57 +0200 Subject: Fix (devs-reported) mistake in batch delete code in recent change. Mistake in own rB358155a8da60, change ended up discarding the case where we need to also delete IDs using a tagged-to-be-deleted ID in a 'never NULL' way. Typical example: Whene deleting a Mesh ID, one also needs to delete all the Objects using that mesh, since obdata pointer is of type 'never NULL'. Note that luckily, this fix does not affect the performance improvements from rB358155a8da60. Noted by Brecht and Clement because of failing unittests, shame on me. --- source/blender/blenkernel/intern/lib_id_delete.c | 29 ++++++++++++------------ 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index ae5dc75c36a..1a80376f482 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -218,6 +218,7 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) BKE_main_lock(bmain); if (do_tagged_deletion) { struct IDRemapper *id_remapper = BKE_id_remapper_create(); + BKE_layer_collection_resync_forbid(); /* Main idea of batch deletion is to remove all IDs to be deleted from Main database. * This means that we won't have to loop over all deleted IDs to remove usages @@ -253,22 +254,20 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion) } } } - } - - BKE_layer_collection_resync_forbid(); - /* Will tag 'never NULL' users of this ID too. - * - * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect - * links, this can lead to nasty crashing here in second, actual deleting loop. - * Also, this will also flag users of deleted data that cannot be unlinked - * (object using deleted obdata, etc.), so that they also get deleted. */ - BKE_libblock_remap_multiple_locked(bmain, - id_remapper, - ID_REMAP_FLAG_NEVER_NULL_USAGE | - ID_REMAP_FORCE_NEVER_NULL_USAGE | - ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS); - BKE_id_remapper_clear(id_remapper); + /* Will tag 'never NULL' users of this ID too. + * + * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect + * links, this can lead to nasty crashing here in second, actual deleting loop. + * Also, this will also flag users of deleted data that cannot be unlinked + * (object using deleted obdata, etc.), so that they also get deleted. */ + BKE_libblock_remap_multiple_locked(bmain, + id_remapper, + ID_REMAP_FLAG_NEVER_NULL_USAGE | + ID_REMAP_FORCE_NEVER_NULL_USAGE | + ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS); + BKE_id_remapper_clear(id_remapper); + } /* Since we removed IDs from Main, their own other IDs usages need to be removed 'manually'. */ LinkNode *cleanup_ids = NULL; -- cgit v1.2.3 From 3d878cd0df31ae89e1fc2a99b3f90e12c6db9c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 17:08:24 +0200 Subject: Fix T101896 Eevee: Custom object properties don't work in shader for Curves objects Move the material resources binding inside the `DRW_shgroup_curves_create_sub` so that `DRW_shgroup_call_no_cull` extracts the attributes. --- source/blender/draw/engines/eevee/eevee_materials.c | 6 ------ source/blender/draw/intern/draw_curves.cc | 5 +++++ source/blender/draw/intern/draw_hair.cc | 5 +++++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index b5f81f3a307..068b18f1117 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -924,17 +924,14 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata, if (matcache.depth_grp) { *matcache.depth_grp_p = DRW_shgroup_hair_create_sub( ob, psys, md, matcache.depth_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); } if (matcache.shading_grp) { *matcache.shading_grp_p = DRW_shgroup_hair_create_sub( ob, psys, md, matcache.shading_grp, matcache.shading_gpumat); - DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); } if (matcache.shadow_grp) { *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub( ob, psys, md, matcache.shadow_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); *cast_shadow = true; } @@ -954,16 +951,13 @@ void EEVEE_object_curves_cache_populate(EEVEE_Data *vedata, if (matcache.depth_grp) { *matcache.depth_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.depth_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); } if (matcache.shading_grp) { *matcache.shading_grp_p = DRW_shgroup_curves_create_sub( ob, matcache.shading_grp, matcache.shading_gpumat); - DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); } if (matcache.shadow_grp) { *matcache.shadow_grp_p = DRW_shgroup_curves_create_sub(ob, matcache.shadow_grp, NULL); - DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); *cast_shadow = true; } diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc index a61769e7a63..8847e3f6016 100644 --- a/source/blender/draw/intern/draw_curves.cc +++ b/source/blender/draw/intern/draw_curves.cc @@ -394,6 +394,11 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root); DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip); DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); + if (gpu_material) { + /* \note: This needs to happen before the drawcall to allow correct attribute extraction. + * (see T101896) */ + DRW_shgroup_add_material_resources(shgrp, gpu_material); + } /* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass * culling test. */ GPUBatch *geom = curves_cache->final[subdiv].proc_hairs[thickness_res - 1]; diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc index 4e44967e5e9..281e58ea230 100644 --- a/source/blender/draw/intern/draw_hair.cc +++ b/source/blender/draw/intern/draw_hair.cc @@ -293,6 +293,11 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root); DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip); DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); + if (gpu_material) { + /* \note: This needs to happen before the drawcall to allow correct attribute extraction. + * (see T101896) */ + DRW_shgroup_add_material_resources(shgrp, gpu_material); + } /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass * culling test. */ GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1]; -- cgit v1.2.3 From 96c085d4af151f0ff20f23f1fe0428e2d8fbdee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 17:19:18 +0200 Subject: Cleanup: WM: Fix missing enumerator case in switch --- source/blender/windowmanager/intern/wm_window.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 6b925b23dcb..ce573a9285b 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1625,13 +1625,14 @@ GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gp case GPU_BACKEND_ANY: case GPU_BACKEND_OPENGL: return GHOST_kDrawingContextTypeOpenGL; -#ifdef WITH_METAL_BACKEND case GPU_BACKEND_METAL: +#ifdef WITH_METAL_BACKEND return GHOST_kDrawingContextTypeMetal; +#else + BLI_assert_unreachable(); + return GHOST_kDrawingContextTypeNone; #endif } - BLI_assert_unreachable(); - return GHOST_kDrawingContextTypeNone; } /** \} */ -- cgit v1.2.3 From bad734081180ed31417ea382d5093f8e6fd35129 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 19 Oct 2022 17:31:56 +0200 Subject: Fix control reaches end of non-void function error --- source/blender/windowmanager/intern/wm_window.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index ce573a9285b..2ca7b5f470d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1633,6 +1633,11 @@ GHOST_TDrawingContextType wm_ghost_drawing_context_type(const eGPUBackendType gp return GHOST_kDrawingContextTypeNone; #endif } + + /* Avoid control reaches end of non-void function compilation warning, which could be promoted + * to error. */ + BLI_assert_unreachable(); + return GHOST_kDrawingContextTypeNone; } /** \} */ -- cgit v1.2.3 From 63aec82e8ae388c8ae0cf3717d18a1eb1e97395a Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Wed, 19 Oct 2022 17:47:21 +0200 Subject: Cycles: oneAPI: switch back target to dg2 Current version of IGC dependency doesn't yet support acm-g10 target. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bffd761f941..9134c7c1ed6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -492,8 +492,8 @@ if(NOT APPLE) option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF) # https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html - # acm-g10 is the architecture for the first Arc Alchemist GPUs. - set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "acm-g10" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") + # acm-g10 is the architecture for the first Arc Alchemist GPUs but we'll keep using dg2 until IGC dependency is updated to support acm-g10. + set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for") mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) -- cgit v1.2.3 From 053fc35b01593dbfa83858bf5a0debea39c5f1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Wed, 19 Oct 2022 17:55:18 +0200 Subject: EEVEE: Depth Of Field: Replace ambiguous select with manual check This is an attempt to remove a driver bug. --- .../blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl index 51a351babd3..5f04cdcebfa 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_scatter_vert.glsl @@ -95,7 +95,11 @@ void main() weights = dof_layer_weight(cocs) * dof_sample_weight(cocs); /* Filter NaNs. */ - weights = select(weights, vec4(0.0), equal(cocs, vec4(0.0))); + for (int i = 0; i < 4; i++) { + if (isnan(weights[i]) || isinf(weights[i])) { + weights[i] = 0.0; + } + } color1 = colors[0] * weights[0]; color2 = colors[1] * weights[1]; -- cgit v1.2.3 From e6902d19a0d8b034e65f28df6dba914a876b08df Mon Sep 17 00:00:00 2001 From: Morteza Mostajab Date: Wed, 19 Oct 2022 17:09:23 +0100 Subject: Cycles: Allow Intel GPUs under Metal Known Issues: - Command buffer failures when using binary archives (binary archives is disabled for Intel GPUs as a workaround) - Wrong texture sampler being applied (to be addressed in the future) Ref T92212 Reviewed By: brecht Maniphest Tasks: T92212 Differential Revision: https://developer.blender.org/D16253 --- intern/cycles/device/metal/device_impl.mm | 6 ++++ intern/cycles/device/metal/kernel.mm | 6 ++++ intern/cycles/device/metal/util.mm | 4 +++ intern/cycles/kernel/device/metal/context_begin.h | 37 ++++++++++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 6a16d4bb3b4..82ad5d55ecd 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -339,6 +339,12 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type) MTLCompileOptions *options = [[MTLCompileOptions alloc] init]; + if (@available(macos 13.0, *)) { + if (device_vendor == METAL_GPU_INTEL) { + [options setOptimizationLevel:MTLLibraryOptimizationLevelSize]; + } + } + options.fastMathEnabled = YES; if (@available(macOS 12.0, *)) { options.languageVersion = MTLLanguageVersion2_4; diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm index 5e0cb6d18f4..8ccc50e57a3 100644 --- a/intern/cycles/device/metal/kernel.mm +++ b/intern/cycles/device/metal/kernel.mm @@ -317,6 +317,12 @@ bool MetalKernelPipeline::should_use_binary_archive() const } } + /* Workaround for Intel GPU having issue using Binary Archives */ + MetalGPUVendor gpu_vendor = MetalInfo::get_device_vendor(mtlDevice); + if (gpu_vendor == METAL_GPU_INTEL) { + return false; + } + if (pso_type == PSO_GENERIC) { /* Archive the generic kernels. */ return true; diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm index 65c67c400fe..eb77aeb6a54 100644 --- a/intern/cycles/device/metal/util.mm +++ b/intern/cycles/device/metal/util.mm @@ -110,6 +110,10 @@ vector> const &MetalInfo::get_usable_devices() usable |= (vendor == METAL_GPU_AMD); } + if (@available(macos 13.0, *)) { + usable |= (vendor == METAL_GPU_INTEL); + } + if (usable) { metal_printf("- %s\n", device_name.c_str()); [device retain]; diff --git a/intern/cycles/kernel/device/metal/context_begin.h b/intern/cycles/kernel/device/metal/context_begin.h index 99cb1e3826e..e75ec9cadec 100644 --- a/intern/cycles/kernel/device/metal/context_begin.h +++ b/intern/cycles/kernel/device/metal/context_begin.h @@ -34,21 +34,48 @@ class MetalKernelContext { kernel_assert(0); return 0; } - + +#ifdef __KERNEL_METAL_INTEL__ + template + inline __attribute__((__always_inline__)) + auto ccl_gpu_tex_object_read_intel_workaround(TextureType texture_array, + const uint tid, const uint sid, + CoordsType coords) const + { + switch(sid) { + default: + case 0: return texture_array[tid].tex.sample(sampler(address::repeat, filter::nearest), coords); + case 1: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::nearest), coords); + case 2: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::nearest), coords); + case 3: return texture_array[tid].tex.sample(sampler(address::repeat, filter::linear), coords); + case 4: return texture_array[tid].tex.sample(sampler(address::clamp_to_edge, filter::linear), coords); + case 5: return texture_array[tid].tex.sample(sampler(address::clamp_to_zero, filter::linear), coords); + } + } +#endif + // texture2d template<> inline __attribute__((__always_inline__)) float4 ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)); +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y)); +#endif } template<> inline __attribute__((__always_inline__)) float ccl_gpu_tex_object_read_2D(ccl_gpu_tex_object_2D tex, float x, float y) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_2d[tid].tex.sample(metal_samplers[sid], float2(x, y)).x; +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_2d, tid, sid, float2(x, y)).x; +#endif } // texture3d @@ -57,14 +84,22 @@ class MetalKernelContext { float4 ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)); +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z)); +#endif } template<> inline __attribute__((__always_inline__)) float ccl_gpu_tex_object_read_3D(ccl_gpu_tex_object_3D tex, float x, float y, float z) const { const uint tid(tex); const uint sid(tex >> 32); +#ifndef __KERNEL_METAL_INTEL__ return metal_ancillaries->textures_3d[tid].tex.sample(metal_samplers[sid], float3(x, y, z)).x; +#else + return ccl_gpu_tex_object_read_intel_workaround(metal_ancillaries->textures_3d, tid, sid, float3(x, y, z)).x; +#endif } # include "kernel/device/gpu/image.h" -- cgit v1.2.3 From a803dbe7ed80df577b648f9e289aaed2a2cc1700 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 12:38:48 -0500 Subject: Geometry Nodes: Use common utility for copying attribute data Attribute copying often uses identical logic for copying selected elements or copying with an index map. Instead of reimplementing this in each file, use the common implementation in the array_utils namespace. This makes the commonality more obvious, gives improved performance (this implementation is multithreaded), reduces binary size (I observed a 173KB reduction), and probably reduces compile time. --- .../blender/blenkernel/intern/curves_geometry.cc | 13 +---- source/blender/blenkernel/intern/instances.cc | 25 +++------ source/blender/blenlib/BLI_array_utils.hh | 5 ++ source/blender/blenlib/intern/array_utils.cc | 5 ++ .../geometry/nodes/node_geo_delete_geometry.cc | 40 +++---------- .../nodes/geometry/nodes/node_geo_dual_mesh.cc | 46 +++++++-------- .../geometry/nodes/node_geo_duplicate_elements.cc | 25 +++------ .../nodes/geometry/nodes/node_geo_extrude_mesh.cc | 65 ++++++++-------------- .../geometry/nodes/node_geo_instance_on_points.cc | 14 +---- 9 files changed, 80 insertions(+), 158 deletions(-) diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 29f8d62545f..d65c31139fc 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -9,6 +9,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_array_utils.hh" #include "BLI_bounds.hh" #include "BLI_index_mask_ops.hh" #include "BLI_length_parameterize.hh" @@ -1111,21 +1112,11 @@ static void copy_between_buffers(const CPPType &type, src_range.size()); } -template -static void copy_with_map(const Span src, const Span map, MutableSpan dst) -{ - threading::parallel_for(map.index_range(), 1024, [&](const IndexRange range) { - for (const int i : range) { - dst[i] = src[map[i]]; - } - }); -} - static void copy_with_map(const GSpan src, const Span map, GMutableSpan dst) { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); - copy_with_map(src.typed(), map, dst.typed()); + array_utils::gather(src.typed(), map, dst.typed()); }); } diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc index 2f8acf477e2..4675562e927 100644 --- a/source/blender/blenkernel/intern/instances.cc +++ b/source/blender/blenkernel/intern/instances.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_cpp_type_make.hh" #include "BLI_rand.hh" #include "BLI_task.hh" @@ -107,18 +108,6 @@ blender::Span Instances::references() const return references_; } -template -static void copy_data_based_on_mask(Span src, MutableSpan dst, IndexMask mask) -{ - BLI_assert(src.data() != dst.data()); - using namespace blender; - threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) { - for (const int i : range) { - dst[i] = src[mask[i]]; - } - }); -} - void Instances::remove(const IndexMask mask) { using namespace blender; @@ -129,11 +118,14 @@ void Instances::remove(const IndexMask mask) return; } + const Span old_handles = this->reference_handles(); Vector new_handles(mask.size()); - copy_data_based_on_mask(this->reference_handles(), new_handles, mask); + array_utils::gather(old_handles, mask.indices(), new_handles.as_mutable_span()); reference_handles_ = std::move(new_handles); + + const Span old_tansforms = this->transforms(); Vector new_transforms(mask.size()); - copy_data_based_on_mask(this->transforms(), new_transforms, mask); + array_utils::gather(old_tansforms, mask.indices(), new_transforms.as_mutable_span()); transforms_ = std::move(new_transforms); const bke::CustomDataAttributes &src_attributes = attributes_; @@ -150,11 +142,8 @@ void Instances::remove(const IndexMask mask) GSpan src = *src_attributes.get_for_read(id); dst_attributes.create(id, meta_data.data_type); GMutableSpan dst = *dst_attributes.get_for_write(id); + array_utils::gather(src, mask.indices(), dst); - attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { - using T = decltype(dummy); - copy_data_based_on_mask(src.typed(), dst.typed(), mask); - }); return true; }, ATTR_DOMAIN_INSTANCE); diff --git a/source/blender/blenlib/BLI_array_utils.hh b/source/blender/blenlib/BLI_array_utils.hh index 95b3bde10f4..264ac00e034 100644 --- a/source/blender/blenlib/BLI_array_utils.hh +++ b/source/blender/blenlib/BLI_array_utils.hh @@ -39,6 +39,11 @@ inline void copy(const Span src, */ void gather(const GVArray &src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096); +/** + * Fill the destination span by gathering indexed values from the `src` array. + */ +void gather(GSpan src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096); + /** * Fill the destination span by gathering indexed values from the `src` array. */ diff --git a/source/blender/blenlib/intern/array_utils.cc b/source/blender/blenlib/intern/array_utils.cc index a837d6aceec..2a231228dcb 100644 --- a/source/blender/blenlib/intern/array_utils.cc +++ b/source/blender/blenlib/intern/array_utils.cc @@ -28,4 +28,9 @@ void gather(const GVArray &src, }); } +void gather(const GSpan src, const IndexMask indices, GMutableSpan dst, const int64_t grain_size) +{ + gather(GVArray::ForSpan(src), indices, dst, grain_size); +} + } // namespace blender::array_utils diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index a433a0df9b0..3e48a9fd923 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -4,6 +4,7 @@ #include "UI_resources.h" #include "BLI_array.hh" +#include "BLI_array_utils.hh" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -23,15 +24,9 @@ namespace blender::nodes::node_geo_delete_geometry_cc { using blender::bke::CustomDataAttributes; template -static void copy_data_based_on_mask(Span data, MutableSpan r_data, IndexMask mask) -{ - for (const int i_out : mask.index_range()) { - r_data[i_out] = data[mask[i_out]]; - } -} - -template -static void copy_data_based_on_map(Span src, MutableSpan dst, Span index_map) +static void copy_data_based_on_map(const Span src, + const Span index_map, + MutableSpan dst) { for (const int i_src : index_map.index_range()) { const int i_dst = index_map[i_src]; @@ -55,26 +50,17 @@ static void copy_attributes(const Map &attributes if (!attribute) { continue; } - /* Only copy if it is on a domain we want. */ if (!domains.contains(attribute.domain)) { continue; } const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); - GSpanAttributeWriter result_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, attribute.domain, data_type); - if (!result_attribute) { continue; } - - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { - using T = decltype(dummy); - VArraySpan span{attribute.varray.typed()}; - MutableSpan out_span = result_attribute.span.typed(); - out_span.copy_from(span); - }); + attribute.varray.materialize(result_attribute.span.data()); result_attribute.finish(); } } @@ -95,26 +81,19 @@ static void copy_attributes_based_on_mask(const Map span{attribute.varray.typed()}; - MutableSpan out_span = result_attribute.span.typed(); - copy_data_based_on_mask(span, out_span, mask); - }); + array_utils::gather(attribute.varray, mask, result_attribute.span); + result_attribute.finish(); } } @@ -131,16 +110,13 @@ static void copy_attributes_based_on_map(const Map span{attribute.varray.typed()}; MutableSpan out_span = result_attribute.span.typed(); - copy_data_based_on_map(span, out_span, index_map); + copy_data_based_on_map(span, index_map, out_span); }); result_attribute.finish(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 84e63845b84..9b1c13bf563 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_task.hh" #include "DNA_mesh_types.h" @@ -105,18 +106,6 @@ static void copy_data_based_on_pairs(Span data, } } -/* Copy using the map. */ -template -static void copy_data_based_on_new_to_old_map(Span data, - MutableSpan r_data, - const Span new_to_old_map) -{ - for (const int i : r_data.index_range()) { - const int old_i = new_to_old_map[i]; - r_data[i] = data[old_i]; - } -} - /** * Transfers the attributes from the original mesh to the new mesh using the following logic: * - If the attribute was on the face domain it is now on the point domain, and this is true @@ -168,7 +157,6 @@ static void transfer_attributes( src_attribute.varray.type()); GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( attribute_id, out_domain, data_type); - if (!dst_attribute) { continue; } @@ -177,20 +165,24 @@ static void transfer_attributes( using T = decltype(dummy); VArraySpan span{src_attribute.varray.typed()}; MutableSpan dst_span = dst_attribute.span.typed(); - if (src_attribute.domain == ATTR_DOMAIN_FACE) { - dst_span.take_front(span.size()).copy_from(span); - if (keep_boundaries) { - copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map); - } - } - else if (src_attribute.domain == ATTR_DOMAIN_POINT) { - copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries); - } - else if (src_attribute.domain == ATTR_DOMAIN_EDGE) { - copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_edges_map); - } - else { - copy_data_based_on_new_to_old_map(span, dst_span, new_to_old_face_corners_map); + switch (src_attribute.domain) { + case ATTR_DOMAIN_POINT: + copy_data_based_on_vertex_types(span, dst_span, vertex_types, keep_boundaries); + break; + case ATTR_DOMAIN_EDGE: + array_utils::gather(span, new_to_old_edges_map, dst_span); + break; + case ATTR_DOMAIN_FACE: + dst_span.take_front(span.size()).copy_from(span); + if (keep_boundaries) { + copy_data_based_on_pairs(span, dst_span, boundary_vertex_to_relevant_face_map); + } + break; + case ATTR_DOMAIN_CORNER: + array_utils::gather(span, new_to_old_face_corners_map, dst_span); + break; + default: + BLI_assert_unreachable(); } }); dst_attribute.finish(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 70583625a7a..486f900aca5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_map.hh" #include "BLI_noise.hh" #include "BLI_span.hh" @@ -105,16 +106,6 @@ static void threaded_slice_fill(Span offsets, }); } -template -static void threaded_mapped_copy(const Span mapping, const Span src, MutableSpan dst) -{ - threading::parallel_for(mapping.index_range(), 512, [&](IndexRange range) { - for (const int i : range) { - dst[i] = src[mapping[i]]; - } - }); -} - static void copy_hashed_ids(const Span src, const int hash, MutableSpan dst) { for (const int i : src.index_range()) { @@ -440,17 +431,17 @@ static void copy_face_attributes_without_id(GeometrySet &geometry_set, MutableSpan dst = dst_attribute.span.typed(); switch (out_domain) { - case ATTR_DOMAIN_FACE: - threaded_slice_fill(offsets, selection, src, dst); + case ATTR_DOMAIN_POINT: + array_utils::gather(src, vert_mapping, dst); break; case ATTR_DOMAIN_EDGE: - threaded_mapped_copy(edge_mapping, src, dst); + array_utils::gather(src, edge_mapping, dst); break; - case ATTR_DOMAIN_POINT: - threaded_mapped_copy(vert_mapping, src, dst); + case ATTR_DOMAIN_FACE: + threaded_slice_fill(offsets, selection, src, dst); break; case ATTR_DOMAIN_CORNER: - threaded_mapped_copy(loop_mapping, src, dst); + array_utils::gather(src, loop_mapping, dst); break; default: break; @@ -653,7 +644,7 @@ static void copy_edge_attributes_without_id(GeometrySet &geometry_set, threaded_slice_fill(offsets, selection, src, dst); break; case ATTR_DOMAIN_POINT: - threaded_mapped_copy(point_mapping, src, dst); + array_utils::gather(src, point_mapping, dst); break; default: break; diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index d348d886ad6..151ba3e59cc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_array_utils.hh" #include "BLI_disjoint_set.hh" #include "BLI_task.hh" #include "BLI_vector_set.hh" @@ -175,24 +176,6 @@ static MPoly new_poly(const int loopstart, const int totloop) return poly; } -template void copy_with_indices(MutableSpan dst, Span src, Span indices) -{ - BLI_assert(dst.size() == indices.size()); - for (const int i : dst.index_range()) { - dst[i] = src[indices[i]]; - } -} - -template void copy_with_mask(MutableSpan dst, Span src, IndexMask mask) -{ - BLI_assert(dst.size() == mask.size()); - threading::parallel_for(mask.index_range(), 512, [&](const IndexRange range) { - for (const int i : range) { - dst[i] = src[mask[i]]; - } - }); -} - /** * \param get_mix_indices_fn: Returns a Span of indices of the source points to mix for every * result point. @@ -265,26 +248,24 @@ static void extrude_mesh_vertices(Mesh &mesh, } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); - attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { - using T = decltype(dummy); - MutableSpan data = attribute.span.typed(); - switch (attribute.domain) { - case ATTR_DOMAIN_POINT: { - /* New vertices copy the attribute values from their source vertex. */ - copy_with_mask(data.slice(new_vert_range), data.as_span(), selection); - break; - } - case ATTR_DOMAIN_EDGE: { + switch (attribute.domain) { + case ATTR_DOMAIN_POINT: + /* New vertices copy the attribute values from their source vertex. */ + array_utils::gather(attribute.span, selection, attribute.span.slice(new_vert_range)); + break; + case ATTR_DOMAIN_EDGE: + attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { + using T = decltype(dummy); + MutableSpan data = attribute.span.typed(); /* New edge values are mixed from of all the edges connected to the source vertex. */ copy_with_mixing(data.slice(new_edge_range), data.as_span(), [&](const int i) { return vert_to_edge_map[selection[i]].as_span(); }); - break; - } - default: - BLI_assert_unreachable(); - } - }); + }); + break; + default: + BLI_assert_unreachable(); + } attribute.finish(); return true; @@ -524,13 +505,14 @@ static void extrude_mesh_edges(Mesh &mesh, switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attribute values from their source vertex. */ - copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices); + array_utils::gather( + data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range)); break; } case ATTR_DOMAIN_EDGE: { /* Edges parallel to original edges copy the edge attributes from the original edges. */ MutableSpan duplicate_data = data.slice(duplicate_edge_range); - copy_with_mask(duplicate_data, data.as_span(), edge_selection); + array_utils::gather(data.as_span(), edge_selection, duplicate_data); /* Edges connected to original vertices mix values of selected connected edges. */ MutableSpan connect_data = data.slice(connect_edge_range); @@ -910,17 +892,18 @@ static void extrude_mesh_face_regions(Mesh &mesh, switch (attribute.domain) { case ATTR_DOMAIN_POINT: { /* New vertices copy the attributes from their original vertices. */ - copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_indices); + array_utils::gather( + data.as_span(), new_vert_indices.as_span(), data.slice(new_vert_range)); break; } case ATTR_DOMAIN_EDGE: { /* Edges parallel to original edges copy the edge attributes from the original edges. */ MutableSpan boundary_data = data.slice(boundary_edge_range); - copy_with_indices(boundary_data, data.as_span(), boundary_edge_indices); + array_utils::gather(data.as_span(), boundary_edge_indices.as_span(), boundary_data); /* Edges inside of face regions also just duplicate their source data. */ MutableSpan new_inner_data = data.slice(new_inner_edge_range); - copy_with_indices(new_inner_data, data.as_span(), new_inner_edge_indices); + array_utils::gather(data.as_span(), new_inner_edge_indices.as_span(), new_inner_data); /* Edges connected to original vertices mix values of selected connected edges. */ MutableSpan connect_data = data.slice(connect_edge_range); @@ -932,8 +915,8 @@ static void extrude_mesh_face_regions(Mesh &mesh, case ATTR_DOMAIN_FACE: { /* New faces on the side of extrusions get the values from the corresponding selected * face. */ - copy_with_indices( - data.slice(side_poly_range), data.as_span(), edge_extruded_face_indices); + array_utils::gather( + data.as_span(), edge_extruded_face_indices.as_span(), data.slice(side_poly_range)); break; } case ATTR_DOMAIN_CORNER: { diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index affeb43e33b..64546684186 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -2,6 +2,7 @@ #include "DNA_collection_types.h" +#include "BLI_array_utils.hh" #include "BLI_hash.h" #include "BLI_task.hh" @@ -172,18 +173,7 @@ static void add_instances_from_component( dst_attribute_opt = instance_attributes.get_for_write(attribute_id); } BLI_assert(dst_attribute_opt); - const GMutableSpan dst_attribute = dst_attribute_opt->slice(start_len, select_len); - threading::parallel_for(selection.index_range(), 1024, [&](IndexRange selection_range) { - attribute_math::convert_to_static_type(attribute_kind.data_type, [&](auto dummy) { - using T = decltype(dummy); - VArray src = src_attribute.typed(); - MutableSpan dst = dst_attribute.typed(); - for (const int range_i : selection_range) { - const int i = selection[range_i]; - dst[range_i] = src[i]; - } - }); - }); + array_utils::gather(src_attribute, selection, dst_attribute_opt->slice(start_len, select_len)); } } -- cgit v1.2.3 From c14b1137464708cccc9034e8abfd509f55c8ca85 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 13:12:20 -0500 Subject: Fix: Geometry Nodes: Memory leak when deleting instances The instance attributes assignment operators were broken in multiple ways: there wasn't a move constructor (probably causing performance issues), and the destination attributes weren't freed before they were replaced. --- source/blender/blenkernel/BKE_attribute.hh | 2 ++ source/blender/blenkernel/intern/attribute_access.cc | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_attribute.hh b/source/blender/blenkernel/BKE_attribute.hh index 7b13b8a2b09..a4f9d73c31e 100644 --- a/source/blender/blenkernel/BKE_attribute.hh +++ b/source/blender/blenkernel/BKE_attribute.hh @@ -793,7 +793,9 @@ class CustomDataAttributes { ~CustomDataAttributes(); CustomDataAttributes(const CustomDataAttributes &other); CustomDataAttributes(CustomDataAttributes &&other); + CustomDataAttributes &operator=(const CustomDataAttributes &other); + CustomDataAttributes &operator=(CustomDataAttributes &&other); void reallocate(int size); diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index b86353bdb74..544427cfdd3 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -642,15 +642,26 @@ CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other) size_ = other.size_; data = other.data; CustomData_reset(&other.data); + other.size_ = 0; } CustomDataAttributes &CustomDataAttributes::operator=(const CustomDataAttributes &other) { - if (this != &other) { - CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, other.size_); - size_ = other.size_; + if (this == &other) { + return *this; } + this->~CustomDataAttributes(); + new (this) CustomDataAttributes(other); + return *this; +} +CustomDataAttributes &CustomDataAttributes::operator=(CustomDataAttributes &&other) +{ + if (this == &other) { + return *this; + } + this->~CustomDataAttributes(); + new (this) CustomDataAttributes(std::move(other)); return *this; } -- cgit v1.2.3 From c3d0ba3b333cb9cf09c94932edd98ae74d0b06a4 Mon Sep 17 00:00:00 2001 From: Yann Lanthony Date: Wed, 19 Oct 2022 19:49:15 +0200 Subject: Fix T101622: Sequencer channels not updating while panning view `V2D_VIEWSYNC_AREA_VERTICAL` flag was mistakenly set to the sequencer toolbar region instead of the channels region. Reviewed By: ISS Differential Revision: https://developer.blender.org/D16155 --- source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_300.cc | 23 ++++++++++++++++++++++ .../editors/space_sequencer/space_sequencer.c | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 96df8f7a443..806fff2099e 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -25,7 +25,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 4 +#define BLENDER_FILE_SUBVERSION 5 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index e2b98b2283f..a2bd7fd2fd1 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -3630,6 +3630,29 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 304, 5)) { + /* Fix for T101622 - update flags of sequence editor regions that were not initialized + * properly. */ + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : + &sl->regionbase; + if (sl->spacetype == SPACE_SEQ) { + LISTBASE_FOREACH (ARegion *, region, regionbase) { + if (region->regiontype == RGN_TYPE_TOOLS) { + region->v2d.flag &= ~V2D_VIEWSYNC_AREA_VERTICAL; + } + if (region->regiontype == RGN_TYPE_CHANNELS) { + region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL; + } + } + } + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 8b6d37caa41..1d20926d16c 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -129,7 +129,6 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce region->regiontype = RGN_TYPE_TOOLS; region->alignment = RGN_ALIGN_LEFT; region->flag = RGN_FLAG_HIDDEN; - region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL; /* Channels. */ region = MEM_callocN(sizeof(ARegion), "channels for sequencer"); @@ -137,6 +136,7 @@ static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *sce BLI_addtail(&sseq->regionbase, region); region->regiontype = RGN_TYPE_CHANNELS; region->alignment = RGN_ALIGN_LEFT; + region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL; /* Preview region. */ /* NOTE: if you change values here, also change them in sequencer_init_preview_region. */ -- cgit v1.2.3 From 193b456d2db87ac578a4dae25d654454ea0c03a0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 19 Oct 2022 20:31:12 +0200 Subject: Fix macOS build error after recent changes to enable Intel GPUs This will only work once we upgrade to the macOS 13 SDK. Ref D16253 --- intern/cycles/device/metal/device_impl.mm | 2 ++ intern/cycles/device/metal/util.mm | 2 ++ 2 files changed, 4 insertions(+) diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 82ad5d55ecd..4ec0ea065ab 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -339,11 +339,13 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type) MTLCompileOptions *options = [[MTLCompileOptions alloc] init]; +#if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { if (device_vendor == METAL_GPU_INTEL) { [options setOptimizationLevel:MTLLibraryOptimizationLevelSize]; } } +#endif options.fastMathEnabled = YES; if (@available(macOS 12.0, *)) { diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm index eb77aeb6a54..63f84a9df33 100644 --- a/intern/cycles/device/metal/util.mm +++ b/intern/cycles/device/metal/util.mm @@ -110,9 +110,11 @@ vector> const &MetalInfo::get_usable_devices() usable |= (vendor == METAL_GPU_AMD); } +#if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { usable |= (vendor == METAL_GPU_INTEL); } +#endif if (usable) { metal_printf("- %s\n", device_name.c_str()); -- cgit v1.2.3 From d046c8c9d756d5a22ed9aa5a8d0bf0b69d9deba6 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 13:39:23 -0500 Subject: Fix T101926: Curves: Remove type-specific attributes when deleting Remove NURBS or Bezier specific attributes after removing points or curves. In theory we could avoid copying those attributes in the first place, but that doesn't seem worth the extra complexity here, since we don't necessarily know the result curve type counts before copying attributes. --- source/blender/blenkernel/intern/curves_geometry.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index d65c31139fc..7c338480c71 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -1224,6 +1224,10 @@ static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves, attribute.dst.finish(); } + if (new_curves.curves_num() != curves.curves_num()) { + new_curves.remove_attributes_based_on_types(); + } + return new_curves; } @@ -1329,6 +1333,8 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves, attribute.dst.finish(); } + new_curves.remove_attributes_based_on_types(); + return new_curves; } -- cgit v1.2.3 From bf8d4a9bc6fb285011f74f5fb36c77b299893ba9 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Wed, 19 Oct 2022 21:06:07 +0200 Subject: Fix T101857: Crash when trying to build proxies on read-only filesystem Skip building if proxy file can't be created. --- source/blender/imbuf/intern/indexer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 8965700c08a..e8e4b80ef45 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -498,7 +498,9 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( rv->anim = anim; get_proxy_filepath(rv->anim, rv->proxy_size, filepath, true); - BLI_make_existing_file(filepath); + if (!BLI_make_existing_file(filepath)) { + return NULL; + } rv->of = avformat_alloc_context(); rv->of->oformat = av_guess_format("avi", NULL, NULL); @@ -905,6 +907,11 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, } } + if (context->proxy_ctx[0] == NULL && context->proxy_ctx[1] == NULL && + context->proxy_ctx[2] == NULL && context->proxy_ctx[3] == NULL) { + return NULL; /* Nothing to transcode. */ + } + for (i = 0; i < num_indexers; i++) { if (tcs_in_use & tc_types[i]) { char filepath[FILE_MAX]; -- cgit v1.2.3 From ba6f25dd1b6d746c361d78b9c6c898ff96fd50d4 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Thu, 20 Oct 2022 10:10:39 +1300 Subject: Fix T101907: restore snapping in node editor Regression from 1edebb794b76 --- source/blender/editors/transform/transform_snap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 553202b5798..06aec3b45a6 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -523,6 +523,10 @@ void applyGridAbsolute(TransInfo *t) float grid_size_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; float grid_size_z = grid_size_x; + if (grid_size_y == 0.0f) { + grid_size_y = grid_size_x; /* Just use `grid_size_x` when `grid_size_y` isn't set correctly. */ + } + /* Early exit on unusable grid size. */ if (grid_size_x == 0.0f || grid_size_y == 0.0f || grid_size_z == 0.0f) { return; -- cgit v1.2.3 From 1a11353d341aa46487ee8b4177cbb2d566bca932 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 Oct 2022 16:33:26 -0500 Subject: Cleanup: Remove unused grease pencil / RNA includes --- source/blender/editors/gpencil/annotate_paint.c | 3 --- source/blender/makesrna/intern/rna_gpencil_modifier.c | 14 ++------------ 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 677bf1bb392..2fd58a9cee0 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -13,9 +13,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_math_geom.h" #include "BLI_utildefines.h" #include "BLT_translation.h" diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 4a36443ca42..320ef169ae5 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -9,11 +9,8 @@ #include #include "DNA_armature_types.h" -#include "DNA_brush_types.h" -#include "DNA_cachefile_types.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" -#include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" @@ -21,20 +18,13 @@ #include "MEM_guardedalloc.h" -#include "BLI_math.h" -#include "BLI_rand.h" +#include "BLI_math_base.h" +#include "BLI_math_rotation.h" #include "BLI_string_utils.h" #include "BLT_translation.h" #include "BKE_animsys.h" -#include "BKE_data_transfer.h" -#include "BKE_dynamicpaint.h" -#include "BKE_effect.h" -#include "BKE_fluid.h" /* For BKE_fluid_modifier_free & BKE_fluid_modifier_create_type_data */ -#include "BKE_mesh_mapping.h" -#include "BKE_mesh_remap.h" -#include "BKE_multires.h" #include "RNA_access.h" #include "RNA_define.h" -- cgit v1.2.3 From c67975c6bb70c6f877b005bbefcef71f2045b34b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 08:48:45 +1100 Subject: Cleanup: use 'wl_' prefix for data_source Without this the local and wayland native types could be mixed up. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 2d16fd4cff5..c0c55fb4cfa 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -289,7 +289,7 @@ struct GWL_DataOffer { }; struct GWL_DataSource { - struct wl_data_source *data_source = nullptr; + struct wl_data_source *wl_data_source = nullptr; char *buffer_out = nullptr; }; @@ -616,8 +616,8 @@ static void display_destroy(GWL_Display *display) std::lock_guard lock{seat->data_source_mutex}; if (seat->data_source) { free(seat->data_source->buffer_out); - if (seat->data_source->data_source) { - wl_data_source_destroy(seat->data_source->data_source); + if (seat->data_source->wl_data_source) { + wl_data_source_destroy(seat->data_source->wl_data_source); } delete seat->data_source; } @@ -3580,18 +3580,18 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c data_source->buffer_out = static_cast(malloc(buffer_size)); std::memcpy(data_source->buffer_out, buffer, buffer_size); - data_source->data_source = wl_data_device_manager_create_data_source( + data_source->wl_data_source = wl_data_device_manager_create_data_source( display_->data_device_manager); - wl_data_source_add_listener(data_source->data_source, &data_source_listener, seat); + wl_data_source_add_listener(data_source->wl_data_source, &data_source_listener, seat); for (const std::string &type : mime_send) { - wl_data_source_offer(data_source->data_source, type.c_str()); + wl_data_source_offer(data_source->wl_data_source, type.c_str()); } if (seat->data_device) { wl_data_device_set_selection( - seat->data_device, data_source->data_source, seat->data_source_serial); + seat->data_device, data_source->wl_data_source, seat->data_source_serial); } } -- cgit v1.2.3 From 09e3ea49dbbec15a8fcc79cc609f6dc8c13bc91f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 08:51:24 +1100 Subject: GHOST/Wayland: clear data source pointer when canceled The external cancel callback destroyed the data source but didn't clear the pointer. While this didn't cause problems, avoid keeping references freed pointers. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c0c55fb4cfa..5b6963dde7a 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1277,9 +1277,14 @@ static void data_source_handle_send(void *data, close(fd); } -static void data_source_handle_cancelled(void * /*data*/, struct wl_data_source *wl_data_source) +static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_data_source) { CLOG_INFO(LOG, 2, "cancelled"); + GWL_Seat *seat = static_cast(data); + GWL_DataSource *data_source = seat->data_source; + GHOST_ASSERT(seat->data_source->wl_data_source == wl_data_source, "Data source mismatch!"); + data_source->wl_data_source = nullptr; + wl_data_source_destroy(wl_data_source); } -- cgit v1.2.3 From 21a1c332b00a63afaa82cce00ca5175b1b8dbd96 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 09:49:17 +1100 Subject: GHOST/Wayland: update code comment for Gnome-Shell workaround Note that the bug has been fixed upstream. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 5b6963dde7a..5c3f807d678 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -117,6 +117,8 @@ static bool use_gnome_confine_hack = false; * This define could be removed without changing any functionality, * it just means GNOME users will see verbose warning messages that alert them about * a known problem that needs to be fixed up-stream. + * + * This has been fixed for GNOME 43. Keep the workaround until support for gnome 42 is dropped. * See: https://gitlab.gnome.org/GNOME/mutter/-/issues/2457 */ #define USE_GNOME_KEYBOARD_SUPPRESS_WARNING -- cgit v1.2.3 From e3075f3cf7ce2fae086f3cd09867e4f0455e4115 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Thu, 20 Oct 2022 12:35:17 +1300 Subject: Cleanup: simplify uv packing api Part of a wider set of changes to migrate UV packing from uv_parametrizer.cc to uvedit_islands.cc. This allows UV packing improvements including margin calculation, correctness fixes such as support for non-manifold geometry, and new packing algorithms including speed and quality improvements. See for example c2256bf7f714, T82637 This change migrates UV.unwrap and Live UV Unwrap. Differential Revision: https://developer.blender.org/D16296 --- source/blender/editors/include/ED_uvedit.h | 2 + source/blender/editors/uvedit/uvedit_islands.cc | 26 +++++++- source/blender/editors/uvedit/uvedit_unwrap_ops.c | 75 +++++++++++------------ 3 files changed, 62 insertions(+), 41 deletions(-) diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index c8ffbb9acb1..b97cd6a9099 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -345,12 +345,14 @@ typedef enum { ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */ } eUVPackIsland_MarginMethod; +/** See also #UnwrapOptions. */ struct UVPackIsland_Params { uint rotate : 1; uint only_selected_uvs : 1; uint only_selected_faces : 1; uint use_seams : 1; uint correct_aspect : 1; + bool ignore_pinned; /* Ignore islands which have any pinned UVs. */ eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */ float margin; /* Additional space to add around each island. */ }; diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc index bdd05b06d94..92745667505 100644 --- a/source/blender/editors/uvedit/uvedit_islands.cc +++ b/source/blender/editors/uvedit/uvedit_islands.cc @@ -600,6 +600,22 @@ static BoxPack *pack_islands_params(const blender::Vector &island_ return box_array; } +static bool island_has_pins(FaceIsland *island) +{ + BMLoop *l; + BMIter iter; + const int cd_loop_uv_offset = island->cd_loop_uv_offset; + for (int i = 0; i < island->faces_len; i++) { + BM_ITER_ELEM (l, &iter, island->faces[i], BM_LOOPS_OF_FACE) { + MLoopUV *luv = static_cast(BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset)); + if (luv->flag & MLOOPUV_PINNED) { + return true; + } + } + } + return false; +} + /* -------------------------------------------------------------------- */ /** \name Public UV Island Packing * @@ -651,8 +667,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, aspect_y, cd_loop_uv_offset); - int index; - LISTBASE_FOREACH_INDEX (struct FaceIsland *, island, &island_list, index) { + /* Remove from linked list and append to blender::Vector. */ + LISTBASE_FOREACH_MUTABLE (struct FaceIsland *, island, &island_list) { + BLI_remlink(&island_list, island); + if (params->ignore_pinned && island_has_pins(island)) { + MEM_freeN(island->faces); + MEM_freeN(island); + continue; + } island_vector.append(island); } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 2c977552e72..ecaba3234a7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1050,31 +1050,6 @@ void UV_OT_minimize_stretch(wmOperatorType *ot) /** \name Pack UV Islands Operator * \{ */ -/** - * \warning Since this uses #ParamHandle it doesn't work with non-manifold meshes (see T82637). - * Use #ED_uvedit_pack_islands_multi for a more general solution. - * - * TODO: remove this function, in favor of #ED_uvedit_pack_islands_multi. - */ -static void uvedit_pack_islands_multi(const Scene *scene, - Object **objects, - const uint objects_len, - const UnwrapOptions *options, - bool rotate, - bool ignore_pinned) -{ - ParamHandle *handle = construct_param_handle_multi(scene, objects, objects_len, options); - GEO_uv_parametrizer_pack(handle, scene->toolsettings->uvcalc_margin, rotate, ignore_pinned); - GEO_uv_parametrizer_flush(handle); - GEO_uv_parametrizer_delete(handle); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); - WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data); - } -} - /* Packing targets. */ enum { PACK_UDIM_SRC_CLOSEST = 0, @@ -1119,16 +1094,22 @@ static int pack_islands_exec(bContext *C, wmOperator *op) const bool use_udim_params = ED_uvedit_udim_params_from_image_space( sima, use_active, &udim_params); - struct UVPackIsland_Params params = { + const struct UVPackIsland_Params pack_island_params = { .rotate = RNA_boolean_get(op->ptr, "rotate"), - .only_selected_uvs = true, - .only_selected_faces = true, - .correct_aspect = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = false, .margin_method = RNA_enum_get(op->ptr, "margin_method"), .margin = RNA_float_get(op->ptr, "margin"), }; - ED_uvedit_pack_islands_multi( - scene, objects, objects_len, NULL, use_udim_params ? &udim_params : NULL, ¶ms); + ED_uvedit_pack_islands_multi(scene, + objects, + objects_len, + NULL, + use_udim_params ? &udim_params : NULL, + &pack_island_params); MEM_freeN(objects); return OPERATOR_FINISHED; @@ -1889,12 +1870,19 @@ void ED_uvedit_live_unwrap(const Scene *scene, Object **objects, int objects_len .fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0, .correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0, }; - - bool rotate = true; - bool ignore_pinned = true; - uvedit_unwrap_multi(scene, objects, objects_len, &options, NULL); - uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned); + + const struct UVPackIsland_Params pack_island_params = { + .rotate = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = true, + .margin_method = ED_UVPACK_MARGIN_SCALED, + .margin = scene->toolsettings->uvcalc_margin, + }; + ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params); } } @@ -1926,8 +1914,6 @@ static int unwrap_exec(bContext *C, wmOperator *op) .correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"), }; - bool rotate = true; - bool ignore_pinned = true; if (CTX_wm_space_image(C)) { /* Inside the UV Editor, only unwrap selected UVs. */ options.only_selected_uvs = true; @@ -2032,7 +2018,18 @@ static int unwrap_exec(bContext *C, wmOperator *op) .count_failed = 0, }; uvedit_unwrap_multi(scene, objects, objects_len, &options, &result_info); - uvedit_pack_islands_multi(scene, objects, objects_len, &options, rotate, ignore_pinned); + + const struct UVPackIsland_Params pack_island_params = { + .rotate = true, + .only_selected_uvs = options.only_selected_uvs, + .only_selected_faces = options.only_selected_faces, + .use_seams = !options.topology_from_uvs || options.topology_from_uvs_use_seams, + .correct_aspect = options.correct_aspect, + .ignore_pinned = true, + .margin_method = RNA_enum_get(op->ptr, "margin_method"), + .margin = RNA_float_get(op->ptr, "margin"), + }; + ED_uvedit_pack_islands_multi(scene, objects, objects_len, NULL, NULL, &pack_island_params); MEM_freeN(objects); -- cgit v1.2.3 From 3411a96e74938afe9b7ffe64e61a225da5f2eb6a Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 19 Oct 2022 04:02:39 +0200 Subject: Fix T93382: Blender still generates subsurface render passes In T93382, the problem was that the Blender-side rendering code was still generating the subsurface passes because the old render pass flags were set, even though Cycles doesn't generate them anymore. After a closer look, it turns out that the entire hardcoded pass creation code can be removed. We already have an Engine API function to query the list of render passes from the engine, so we might as well just call that and create the returned passes. Turns out that Eevee already did this anyways. On the Cycles side, it allows to deduplicate a lot of `BlenderSync::sync_render_passes`. Before, passes were defined in engine.py and in sync.cpp. Now, all passes that engine.py returns are created automatically, so sync.cpp only needs to handle a few special cases. I'm not really concerned about affecting external renderer addons, since they already needed to handle the old "builtin passes" in their Engine API implementation anyways to make them show up in the compositor. So, unless they missed that for like 10 releases, they should not notice any difference. Differential Revision: https://developer.blender.org/D16295 --- intern/cycles/blender/addon/engine.py | 15 +- intern/cycles/blender/sync.cpp | 206 +++++++++----------------- source/blender/draw/intern/draw_manager.c | 18 --- source/blender/render/intern/engine.cc | 55 +++++-- source/blender/render/intern/render_result.cc | 87 ----------- 5 files changed, 128 insertions(+), 253 deletions(-) diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 794338fe78e..e33891fa7a2 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -209,22 +209,25 @@ def list_render_passes(scene, srl): yield ("Debug Sample Count", "X", 'VALUE') # Cryptomatte passes. - crypto_depth = (srl.pass_cryptomatte_depth + 1) // 2 + # NOTE: Name channels are lowercase RGBA so that compression rules check in OpenEXR DWA code + # uses lossless compression. Reportedly this naming is the only one which works good from the + # interoperability point of view. Using XYZW naming is not portable. + crypto_depth = (min(16, srl.pass_cryptomatte_depth) + 1) // 2 if srl.use_pass_cryptomatte_object: for i in range(0, crypto_depth): - yield ("CryptoObject" + '{:02d}'.format(i), "RGBA", 'COLOR') + yield ("CryptoObject" + '{:02d}'.format(i), "rgba", 'COLOR') if srl.use_pass_cryptomatte_material: for i in range(0, crypto_depth): - yield ("CryptoMaterial" + '{:02d}'.format(i), "RGBA", 'COLOR') + yield ("CryptoMaterial" + '{:02d}'.format(i), "rgba", 'COLOR') if srl.use_pass_cryptomatte_asset: for i in range(0, crypto_depth): - yield ("CryptoAsset" + '{:02d}'.format(i), "RGBA", 'COLOR') + yield ("CryptoAsset" + '{:02d}'.format(i), "rgba", 'COLOR') # Denoising passes. if scene.cycles.use_denoising and crl.use_denoising: yield ("Noisy Image", "RGBA", 'COLOR') if crl.use_pass_shadow_catcher: - yield ("Noisy Shadow Catcher", "RGBA", 'COLOR') + yield ("Noisy Shadow Catcher", "RGB", 'COLOR') if crl.denoising_store_passes: yield ("Denoising Normal", "XYZ", 'VECTOR') yield ("Denoising Albedo", "RGB", 'COLOR') @@ -232,6 +235,8 @@ def list_render_passes(scene, srl): # Custom AOV passes. for aov in srl.aovs: + if not aov.is_valid: + continue if aov.type == 'VALUE': yield (aov.name, "X", 'VALUE') else: diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index a69a94614d3..5251f0fee9c 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -575,68 +575,72 @@ void BlenderSync::sync_images() /* Passes */ -static PassType get_blender_pass_type(BL::RenderPass &b_pass) +static bool get_known_pass_type(BL::RenderPass &b_pass, PassType &type, PassMode &mode) { string name = b_pass.name(); -#define MAP_PASS(passname, passtype) \ +#define MAP_PASS(passname, passtype, noisy) \ if (name == passname) { \ - return passtype; \ + type = passtype; \ + mode = (noisy) ? PassMode::NOISY : PassMode::DENOISED; \ + return true; \ } \ ((void)0) - /* NOTE: Keep in sync with defined names from DNA_scene_types.h */ + /* NOTE: Keep in sync with defined names from engine.py */ - MAP_PASS("Combined", PASS_COMBINED); - MAP_PASS("Noisy Image", PASS_COMBINED); + MAP_PASS("Combined", PASS_COMBINED, false); + MAP_PASS("Noisy Image", PASS_COMBINED, true); - MAP_PASS("Depth", PASS_DEPTH); - MAP_PASS("Mist", PASS_MIST); - MAP_PASS("Position", PASS_POSITION); - MAP_PASS("Normal", PASS_NORMAL); - MAP_PASS("IndexOB", PASS_OBJECT_ID); - MAP_PASS("UV", PASS_UV); - MAP_PASS("Vector", PASS_MOTION); - MAP_PASS("IndexMA", PASS_MATERIAL_ID); + MAP_PASS("Depth", PASS_DEPTH, false); + MAP_PASS("Mist", PASS_MIST, false); + MAP_PASS("Position", PASS_POSITION, false); + MAP_PASS("Normal", PASS_NORMAL, false); + MAP_PASS("IndexOB", PASS_OBJECT_ID, false); + MAP_PASS("UV", PASS_UV, false); + MAP_PASS("Vector", PASS_MOTION, false); + MAP_PASS("IndexMA", PASS_MATERIAL_ID, false); - MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT); - MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT); - MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT); - MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT); + MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT, false); + MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT, false); + MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT, false); + MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT, false); - MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT); - MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT); - MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT); - MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT); + MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT, false); + MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT, false); + MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT, false); + MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT, false); - MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR); - MAP_PASS("GlossCol", PASS_GLOSSY_COLOR); - MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR); + MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR, false); + MAP_PASS("GlossCol", PASS_GLOSSY_COLOR, false); + MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR, false); - MAP_PASS("Emit", PASS_EMISSION); - MAP_PASS("Env", PASS_BACKGROUND); - MAP_PASS("AO", PASS_AO); - MAP_PASS("Shadow", PASS_SHADOW); + MAP_PASS("Emit", PASS_EMISSION, false); + MAP_PASS("Env", PASS_BACKGROUND, false); + MAP_PASS("AO", PASS_AO, false); + MAP_PASS("Shadow", PASS_SHADOW, false); - MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE); - MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL); + MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE, false); + MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL, false); - MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL); - MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO); - MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH); + MAP_PASS("Denoising Normal", PASS_DENOISING_NORMAL, true); + MAP_PASS("Denoising Albedo", PASS_DENOISING_ALBEDO, true); + MAP_PASS("Denoising Depth", PASS_DENOISING_DEPTH, true); - MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER); - MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER); + MAP_PASS("Shadow Catcher", PASS_SHADOW_CATCHER, false); + MAP_PASS("Noisy Shadow Catcher", PASS_SHADOW_CATCHER, true); - MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER); - MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT); + MAP_PASS("AdaptiveAuxBuffer", PASS_ADAPTIVE_AUX_BUFFER, false); + MAP_PASS("Debug Sample Count", PASS_SAMPLE_COUNT, false); if (string_startswith(name, cryptomatte_prefix)) { - return PASS_CRYPTOMATTE; + type = PASS_CRYPTOMATTE; + mode = PassMode::DENOISED; + return true; } #undef MAP_PASS - return PASS_NONE; + return false; } static Pass *pass_add(Scene *scene, @@ -655,8 +659,6 @@ static Pass *pass_add(Scene *scene, void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer) { - PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - /* Delete all existing passes. */ set clear_passes(scene->passes.begin(), scene->passes.end()); scene->delete_nodes(clear_passes); @@ -664,103 +666,23 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v /* Always add combined pass. */ pass_add(scene, PASS_COMBINED, "Combined"); - /* Blender built-in data and light passes. */ - for (BL::RenderPass &b_pass : b_rlay.passes) { - const PassType pass_type = get_blender_pass_type(b_pass); - - if (pass_type == PASS_NONE) { - LOG(ERROR) << "Unknown pass " << b_pass.name(); - continue; - } - - if (pass_type == PASS_MOTION && - (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) { - continue; - } - - pass_add(scene, pass_type, b_pass.name().c_str()); - } - - PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles"); - - /* Debug passes. */ - if (get_boolean(crl, "pass_debug_sample_count")) { - b_engine.add_pass("Debug Sample Count", 1, "X", b_view_layer.name().c_str()); - pass_add(scene, PASS_SAMPLE_COUNT, "Debug Sample Count"); - } - - /* Cycles specific passes. */ - if (get_boolean(crl, "use_pass_volume_direct")) { - b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_VOLUME_DIRECT, "VolumeDir"); - } - if (get_boolean(crl, "use_pass_volume_indirect")) { - b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_VOLUME_INDIRECT, "VolumeInd"); - } - if (get_boolean(crl, "use_pass_shadow_catcher")) { - b_engine.add_pass("Shadow Catcher", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_SHADOW_CATCHER, "Shadow Catcher"); - } - /* Cryptomatte stores two ID/weight pairs per RGBA layer. - * User facing parameter is the number of pairs. - * - * NOTE: Name channels lowercase RGBA so that compression rules check in OpenEXR DWA code uses - * lossless compression. Reportedly this naming is the only one which works good from the - * interoperability point of view. Using XYZW naming is not portable. */ + * User facing parameter is the number of pairs. */ int crypto_depth = divide_up(min(16, b_view_layer.pass_cryptomatte_depth()), 2); scene->film->set_cryptomatte_depth(crypto_depth); CryptomatteType cryptomatte_passes = CRYPT_NONE; if (b_view_layer.use_pass_cryptomatte_object()) { - for (int i = 0; i < crypto_depth; i++) { - string passname = cryptomatte_prefix + string_printf("Object%02d", i); - b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str()); - pass_add(scene, PASS_CRYPTOMATTE, passname.c_str()); - } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_OBJECT); } if (b_view_layer.use_pass_cryptomatte_material()) { - for (int i = 0; i < crypto_depth; i++) { - string passname = cryptomatte_prefix + string_printf("Material%02d", i); - b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str()); - pass_add(scene, PASS_CRYPTOMATTE, passname.c_str()); - } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_MATERIAL); } if (b_view_layer.use_pass_cryptomatte_asset()) { - for (int i = 0; i < crypto_depth; i++) { - string passname = cryptomatte_prefix + string_printf("Asset%02d", i); - b_engine.add_pass(passname.c_str(), 4, "rgba", b_view_layer.name().c_str()); - pass_add(scene, PASS_CRYPTOMATTE, passname.c_str()); - } cryptomatte_passes = (CryptomatteType)(cryptomatte_passes | CRYPT_ASSET); } scene->film->set_cryptomatte_passes(cryptomatte_passes); - /* Denoising passes. */ - const bool use_denoising = get_boolean(cscene, "use_denoising") && - get_boolean(crl, "use_denoising"); - const bool store_denoising_passes = get_boolean(crl, "denoising_store_passes"); - if (use_denoising) { - b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str()); - pass_add(scene, PASS_COMBINED, "Noisy Image", PassMode::NOISY); - if (get_boolean(crl, "use_pass_shadow_catcher")) { - b_engine.add_pass("Noisy Shadow Catcher", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_SHADOW_CATCHER, "Noisy Shadow Catcher", PassMode::NOISY); - } - } - if (store_denoising_passes) { - b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str()); - pass_add(scene, PASS_DENOISING_NORMAL, "Denoising Normal", PassMode::NOISY); - - b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str()); - pass_add(scene, PASS_DENOISING_ALBEDO, "Denoising Albedo", PassMode::NOISY); - - b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str()); - pass_add(scene, PASS_DENOISING_DEPTH, "Denoising Depth", PassMode::NOISY); - } - + /* Path guiding debug passes. */ #ifdef WITH_CYCLES_DEBUG b_engine.add_pass("Guiding Color", 3, "RGB", b_view_layer.name().c_str()); pass_add(scene, PASS_GUIDING_COLOR, "Guiding Color", PassMode::NOISY); @@ -772,6 +694,8 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v pass_add(scene, PASS_GUIDING_AVG_ROUGHNESS, "Guiding Average Roughness", PassMode::NOISY); #endif + unordered_set expected_passes; + /* Custom AOV passes. */ BL::ViewLayer::aovs_iterator b_aov_iter; for (b_view_layer.aovs.begin(b_aov_iter); b_aov_iter != b_view_layer.aovs.end(); ++b_aov_iter) { @@ -781,16 +705,10 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v } string name = b_aov.name(); - bool is_color = b_aov.type() == BL::AOV::type_COLOR; + PassType type = (b_aov.type() == BL::AOV::type_COLOR) ? PASS_AOV_COLOR : PASS_AOV_VALUE; - if (is_color) { - b_engine.add_pass(name.c_str(), 4, "RGBA", b_view_layer.name().c_str()); - pass_add(scene, PASS_AOV_COLOR, name.c_str()); - } - else { - b_engine.add_pass(name.c_str(), 1, "X", b_view_layer.name().c_str()); - pass_add(scene, PASS_AOV_VALUE, name.c_str()); - } + pass_add(scene, type, name.c_str()); + expected_passes.insert(name); } /* Light Group passes. */ @@ -802,9 +720,29 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v string name = string_printf("Combined_%s", b_lightgroup.name().c_str()); - b_engine.add_pass(name.c_str(), 3, "RGB", b_view_layer.name().c_str()); Pass *pass = pass_add(scene, PASS_COMBINED, name.c_str(), PassMode::NOISY); pass->set_lightgroup(ustring(b_lightgroup.name())); + expected_passes.insert(name); + } + + /* Sync the passes that were defined in engine.py. */ + for (BL::RenderPass &b_pass : b_rlay.passes) { + PassType pass_type = PASS_NONE; + PassMode pass_mode = PassMode::DENOISED; + + if (!get_known_pass_type(b_pass, pass_type, pass_mode)) { + if (!expected_passes.count(b_pass.name())) { + LOG(ERROR) << "Unknown pass " << b_pass.name(); + } + continue; + } + + if (pass_type == PASS_MOTION && + (b_view_layer.use_motion_blur() && b_scene.render().use_motion_blur())) { + continue; + } + + pass_add(scene, pass_type, b_pass.name().c_str(), pass_mode); } scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold()); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index da77845feb4..b9a9780e651 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1959,20 +1959,6 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph DST.buffer_finish_called = false; } -/* Callback function for RE_engine_update_render_passes to ensure all - * render passes are registered. */ -static void draw_render_result_ensure_pass_cb(void *user_data, - struct Scene *UNUSED(scene), - struct ViewLayer *view_layer, - const char *name, - int channels, - const char *chanid, - eNodeSocketDatatype UNUSED(type)) -{ - RenderEngine *engine = user_data; - RE_engine_add_pass(engine, name, channels, chanid, view_layer->name); -} - void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) { Scene *scene = DEG_get_evaluated_scene(depsgraph); @@ -2023,10 +2009,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* set default viewport */ GPU_viewport(0, 0, size[0], size[1]); - /* Update the render passes. This needs to be done before acquiring the render result. */ - RE_engine_update_render_passes( - engine, scene, view_layer, draw_render_result_ensure_pass_cb, engine); - /* Init render result. */ RenderResult *render_result = RE_engine_begin_result(engine, 0, diff --git a/source/blender/render/intern/engine.cc b/source/blender/render/intern/engine.cc index 5eb4db6faa4..b8757d33580 100644 --- a/source/blender/render/intern/engine.cc +++ b/source/blender/render/intern/engine.cc @@ -969,6 +969,40 @@ static void engine_render_view_layer(Render *re, engine_depsgraph_exit(engine); } +/* Callback function for engine_render_create_result to add all render passes to the result. */ +static void engine_render_add_result_pass_cb(void *user_data, + struct Scene *UNUSED(scene), + struct ViewLayer *view_layer, + const char *name, + int channels, + const char *chanid, + eNodeSocketDatatype UNUSED(type)) +{ + RenderResult *rr = (RenderResult *)user_data; + RE_create_render_pass(rr, name, channels, chanid, view_layer->name, RR_ALL_VIEWS, false); +} + +static RenderResult *engine_render_create_result(Render *re) +{ + RenderResult *rr = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); + if (rr == nullptr) { + return nullptr; + } + + FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) { + RE_engine_update_render_passes( + re->engine, re->scene, view_layer, engine_render_add_result_pass_cb, rr); + } + FOREACH_VIEW_LAYER_TO_RENDER_END; + + /* Preview does not support deferred render result allocation. */ + if (re->r.scemode & R_BUTS_PREVIEW) { + render_result_passes_allocated_ensure(rr); + } + + return rr; +} + bool RE_engine_render(Render *re, bool do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); @@ -1008,6 +1042,14 @@ bool RE_engine_render(Render *re, bool do_all) render_update_anim_renderdata(re, &re->scene->r, &re->scene->view_layers); } + /* Create engine. */ + RenderEngine *engine = re->engine; + + if (!engine) { + engine = RE_engine_create(type); + re->engine = engine; + } + /* create render result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW)) { @@ -1015,7 +1057,7 @@ bool RE_engine_render(Render *re, bool do_all) render_result_free(re->result); } - re->result = render_result_new(re, &re->disprect, RR_ALL_LAYERS, RR_ALL_VIEWS); + re->result = engine_render_create_result(re); } BLI_rw_mutex_unlock(&re->resultmutex); @@ -1024,6 +1066,9 @@ bool RE_engine_render(Render *re, bool do_all) if (re->draw_lock) { re->draw_lock(re->dlh, false); } + /* Free engine. */ + RE_engine_free(engine); + re->engine = nullptr; /* Too small image is handled earlier, here it could only happen if * there was no sufficient memory to allocate all passes. */ @@ -1036,14 +1081,6 @@ bool RE_engine_render(Render *re, bool do_all) re->i.cfra = re->scene->r.cfra; BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name)); - /* render */ - RenderEngine *engine = re->engine; - - if (!engine) { - engine = RE_engine_create(type); - re->engine = engine; - } - engine->flag |= RE_ENGINE_RENDERING; /* TODO: actually link to a parent which shouldn't happen */ diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index bd5c6a0f5c4..f9524fdbf05 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -290,90 +290,8 @@ RenderResult *render_result_new(Render *re, } } -#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \ - do { \ - if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id, false) == nullptr) { \ - render_result_free(rr); \ - return nullptr; \ - } \ - } while (false) - /* A render-layer should always have a "Combined" pass. */ render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA", false); - - if (view_layer->passflag & SCE_PASS_Z) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z"); - } - if (view_layer->passflag & SCE_PASS_VECTOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW"); - } - if (view_layer->passflag & SCE_PASS_NORMAL) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ"); - } - if (view_layer->passflag & SCE_PASS_POSITION) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_POSITION, view, "XYZ"); - } - if (view_layer->passflag & SCE_PASS_UV) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA"); - } - if (view_layer->passflag & SCE_PASS_EMIT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_AO) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_ENVIRONMENT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SHADOW) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_INDEXOB) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X"); - } - if (view_layer->passflag & SCE_PASS_INDEXMA) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X"); - } - if (view_layer->passflag & SCE_PASS_MIST) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z"); - } - if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_TRANSM_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB"); - } - if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) { - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB"); - } -#undef RENDER_LAYER_ADD_PASS_SAFE } } FOREACH_VIEW_LAYER_TO_RENDER_END; @@ -411,11 +329,6 @@ RenderResult *render_result_new(Render *re, rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2); rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2); - /* Preview does not support deferred render result allocation. */ - if (re->r.scemode & R_BUTS_PREVIEW) { - render_result_passes_allocated_ensure(rr); - } - return rr; } -- cgit v1.2.3 From 3915f5300ad2d2a3c12a8bb67bb97f60160953e7 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sun, 16 Oct 2022 00:57:09 +0200 Subject: Fix T99151: Cycles not updating on Object Type visibility change Differential Revision: https://developer.blender.org/D16259 --- source/blender/makesrna/intern/rna_internal.h | 4 +++- source/blender/makesrna/intern/rna_space.c | 10 +++++++++- source/blender/makesrna/intern/rna_space_api.c | 6 ++++-- source/blender/makesrna/intern/rna_xr.c | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 8e652753ec0..ea829e5cd86 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -322,7 +322,9 @@ void rna_object_vcollayer_name_set(struct PointerRNA *ptr, PointerRNA rna_object_shapekey_index_get(struct ID *id, int value); int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current); -void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag); +void rna_def_object_type_visibility_flags_common(StructRNA *srna, + int noteflag, + const char *update_func); int rna_object_type_visibility_icon_get_common(int object_type_exclude_viewport, const int *object_type_exclude_select); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5c192b80dc1..b2663b89333 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -990,6 +990,13 @@ static PointerRNA rna_SpaceView3D_region_3d_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_RegionView3D, regiondata); } +static void rna_SpaceView3D_object_type_visibility_update(Main *UNUSED(bmain), + Scene *scene, + PointerRNA *UNUSED(ptr)) +{ + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); +} + static void rna_SpaceView3D_region_quadviews_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { @@ -5086,7 +5093,8 @@ static void rna_def_space_view3d(BlenderRNA *brna) prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_mirror_xr_session_update"); rna_def_object_type_visibility_flags_common(srna, - NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING); + NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, + "rna_SpaceView3D_object_type_visibility_update"); /* Helper for drawing the icon. */ prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c index b3896919275..9790a85e1c8 100644 --- a/source/blender/makesrna/intern/rna_space_api.c +++ b/source/blender/makesrna/intern/rna_space_api.c @@ -119,7 +119,9 @@ void RNA_api_space_text(StructRNA *srna) RNA_def_function_output(func, parm); } -void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag) +void rna_def_object_type_visibility_flags_common(StructRNA *srna, + int noteflag, + const char *update_func) { PropertyRNA *prop; @@ -173,7 +175,7 @@ void rna_def_object_type_visibility_flags_common(StructRNA *srna, int noteflag) RNA_def_property_boolean_negative_sdna( prop, NULL, view_mask_member[mask_index], info[type_index].type_mask); RNA_def_property_ui_text(prop, info[type_index].name, ""); - RNA_def_property_update(prop, noteflag, NULL); + RNA_def_property_update(prop, noteflag, update_func); } } } diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index dcfa1bbca51..c803e5dc9a8 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -2052,7 +2052,7 @@ static void rna_def_xr_session_settings(BlenderRNA *brna) "Allow the VR tracking origin to be defined independently of the headset location"); RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL); - rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED); + rna_def_object_type_visibility_flags_common(srna, NC_WM | ND_XR_DATA_CHANGED, NULL); /* Helper for drawing the icon. */ prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE); -- cgit v1.2.3 From e2a93e9c7c5fece5ea7d46da949694ad2eca872e Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Thu, 20 Oct 2022 04:38:50 +0200 Subject: Fix T94136: Cycles: No Hair Shadows with Transparent BSDF --- intern/cycles/kernel/bvh/shadow_all.h | 2 +- intern/cycles/kernel/bvh/util.h | 8 +++----- intern/cycles/kernel/device/cpu/bvh.h | 2 +- intern/cycles/kernel/device/metal/kernel.metal | 2 +- intern/cycles/kernel/device/optix/bvh.h | 2 +- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/intern/cycles/kernel/bvh/shadow_all.h b/intern/cycles/kernel/bvh/shadow_all.h index 2ffe1496c72..b31ba479e4f 100644 --- a/intern/cycles/kernel/bvh/shadow_all.h +++ b/intern/cycles/kernel/bvh/shadow_all.h @@ -229,7 +229,7 @@ ccl_device_inline /* Always use baked shadow transparency for curves. */ if (isect.type & PRIMITIVE_CURVE) { *r_throughput *= intersection_curve_shadow_transparency( - kg, isect.object, isect.prim, isect.u); + kg, isect.object, isect.prim, isect.type, isect.u); if (*r_throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { return true; diff --git a/intern/cycles/kernel/bvh/util.h b/intern/cycles/kernel/bvh/util.h index a57703a8b8c..9ba787550c5 100644 --- a/intern/cycles/kernel/bvh/util.h +++ b/intern/cycles/kernel/bvh/util.h @@ -190,10 +190,8 @@ ccl_device_inline int intersection_find_attribute(KernelGlobals kg, /* Cut-off value to stop transparent shadow tracing when practically opaque. */ #define CURVE_SHADOW_TRANSPARENCY_CUTOFF 0.001f -ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, - const int object, - const int prim, - const float u) +ccl_device_inline float intersection_curve_shadow_transparency( + KernelGlobals kg, const int object, const int prim, const int type, const float u) { /* Find attribute. */ const int offset = intersection_find_attribute(kg, object, ATTR_STD_SHADOW_TRANSPARENCY); @@ -204,7 +202,7 @@ ccl_device_inline float intersection_curve_shadow_transparency(KernelGlobals kg, /* Interpolate transparency between curve keys. */ const KernelCurve kcurve = kernel_data_fetch(curves, prim); - const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(kcurve.type); + const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(type); const int k1 = k0 + 1; const float f0 = kernel_data_fetch(attributes_float, offset + k0); diff --git a/intern/cycles/kernel/device/cpu/bvh.h b/intern/cycles/kernel/device/cpu/bvh.h index d9267e1cd6d..2d7d8c2d704 100644 --- a/intern/cycles/kernel/device/cpu/bvh.h +++ b/intern/cycles/kernel/device/cpu/bvh.h @@ -252,7 +252,7 @@ ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArgum /* Always use baked shadow transparency for curves. */ if (current_isect.type & PRIMITIVE_CURVE) { ctx->throughput *= intersection_curve_shadow_transparency( - kg, current_isect.object, current_isect.prim, current_isect.u); + kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u); if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) { ctx->opaque_hit = true; diff --git a/intern/cycles/kernel/device/metal/kernel.metal b/intern/cycles/kernel/device/metal/kernel.metal index 5646c7446db..8b69ee025cd 100644 --- a/intern/cycles/kernel/device/metal/kernel.metal +++ b/intern/cycles/kernel/device/metal/kernel.metal @@ -228,7 +228,7 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal, /* Always use baked shadow transparency for curves. */ if (type & PRIMITIVE_CURVE) { float throughput = payload.throughput; - throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, u); + throughput *= context.intersection_curve_shadow_transparency(nullptr, object, prim, type, u); payload.throughput = throughput; payload.num_hits += 1; diff --git a/intern/cycles/kernel/device/optix/bvh.h b/intern/cycles/kernel/device/optix/bvh.h index fb9907709ce..6d81b44660c 100644 --- a/intern/cycles/kernel/device/optix/bvh.h +++ b/intern/cycles/kernel/device/optix/bvh.h @@ -202,7 +202,7 @@ extern "C" __global__ void __anyhit__kernel_optix_shadow_all_hit() /* Always use baked shadow transparency for curves. */ if (type & PRIMITIVE_CURVE) { float throughput = __uint_as_float(optixGetPayload_1()); - throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, u); + throughput *= intersection_curve_shadow_transparency(nullptr, object, prim, type, u); optixSetPayload_1(__float_as_uint(throughput)); optixSetPayload_2(uint16_pack_to_uint(num_recorded_hits, num_hits + 1)); -- cgit v1.2.3 From c58d6b30add69fc3c6004d2ad2a590d7d44cc83b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:51:33 +1100 Subject: GHOST/Wayland: correct assert from recent commit Error in [0], only clear the stored clipboard data source pointer if it matches the data being cleared. [0]: 09e3ea49dbbec15a8fcc79cc609f6dc8c13bc91f --- intern/ghost/intern/GHOST_SystemWayland.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 5c3f807d678..4b3f3ec5ef2 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1284,8 +1284,9 @@ static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_d CLOG_INFO(LOG, 2, "cancelled"); GWL_Seat *seat = static_cast(data); GWL_DataSource *data_source = seat->data_source; - GHOST_ASSERT(seat->data_source->wl_data_source == wl_data_source, "Data source mismatch!"); - data_source->wl_data_source = nullptr; + if (seat->data_source->wl_data_source == wl_data_source) { + data_source->wl_data_source = nullptr; + } wl_data_source_destroy(wl_data_source); } -- cgit v1.2.3 From f24dfdcd3cbd454ec62ef55f13ece4098b3fdda4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:53:34 +1100 Subject: Cleanup: format --- intern/cycles/device/metal/device_impl.mm | 4 ++-- intern/cycles/device/metal/util.mm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index 4ec0ea065ab..4b929b6bc0a 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -339,13 +339,13 @@ bool MetalDevice::compile_and_load(MetalPipelineType pso_type) MTLCompileOptions *options = [[MTLCompileOptions alloc] init]; -#if defined(MAC_OS_VERSION_13_0) +# if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { if (device_vendor == METAL_GPU_INTEL) { [options setOptimizationLevel:MTLLibraryOptimizationLevelSize]; } } -#endif +# endif options.fastMathEnabled = YES; if (@available(macOS 12.0, *)) { diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm index 63f84a9df33..f47638fac15 100644 --- a/intern/cycles/device/metal/util.mm +++ b/intern/cycles/device/metal/util.mm @@ -110,11 +110,11 @@ vector> const &MetalInfo::get_usable_devices() usable |= (vendor == METAL_GPU_AMD); } -#if defined(MAC_OS_VERSION_13_0) +# if defined(MAC_OS_VERSION_13_0) if (@available(macos 13.0, *)) { usable |= (vendor == METAL_GPU_INTEL); } -#endif +# endif if (usable) { metal_printf("- %s\n", device_name.c_str()); -- cgit v1.2.3 From d392e9afea569d4be065a31b208427e255cf1f8d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:55:34 +1100 Subject: Cleanup: correct prefix for internal wayland utility function --- intern/ghost/intern/GHOST_SystemWayland.cpp | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 4b3f3ec5ef2..a307dabb690 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -391,16 +391,16 @@ struct GWL_SeatStateKeyboard { * * Needed as #GWL_Seat.xkb_state doesn't store which modifier keys are held. */ -struct WGL_KeyboardDepressedState { +struct GWL_KeyboardDepressedState { int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0}; }; #ifdef WITH_GHOST_WAYLAND_LIBDECOR -struct WGL_LibDecor_System { +struct GWL_LibDecor_System { struct libdecor *context = nullptr; }; -static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor) +static void gwl_libdecor_system_destroy(GWL_LibDecor_System *decor) { if (decor->context) { libdecor_unref(decor->context); @@ -409,12 +409,12 @@ static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor) } #endif -struct WGL_XDG_Decor_System { +struct GWL_XDG_Decor_System { struct xdg_wm_base *shell = nullptr; struct zxdg_decoration_manager_v1 *manager = nullptr; }; -static void wgl_xdg_decor_system_destroy(WGL_XDG_Decor_System *decor) +static void gwl_xdg_decor_system_destroy(GWL_XDG_Decor_System *decor) { if (decor->manager) { zxdg_decoration_manager_v1_destroy(decor->manager); @@ -475,7 +475,7 @@ struct GWL_Seat { struct xkb_state *xkb_state_empty_with_numlock = nullptr; /** Keys held matching `xkb_state`. */ - struct WGL_KeyboardDepressedState key_depressed; + struct GWL_KeyboardDepressedState key_depressed; #ifdef USE_GNOME_KEYBOARD_SUPPRESS_WARNING struct { @@ -525,10 +525,10 @@ struct GWL_Display { struct wl_compositor *wl_compositor = nullptr; #ifdef WITH_GHOST_WAYLAND_LIBDECOR - WGL_LibDecor_System *libdecor = nullptr; + GWL_LibDecor_System *libdecor = nullptr; bool libdecor_required = false; #endif - WGL_XDG_Decor_System *xdg_decor = nullptr; + GWL_XDG_Decor_System *xdg_decor = nullptr; struct zxdg_output_manager_v1 *xdg_output_manager = nullptr; struct wl_shm *wl_shm = nullptr; @@ -702,14 +702,14 @@ static void display_destroy(GWL_Display *display) #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { if (display->libdecor) { - wgl_libdecor_system_destroy(display->libdecor); + gwl_libdecor_system_destroy(display->libdecor); } } else #endif { if (display->xdg_decor) { - wgl_xdg_decor_system_destroy(display->xdg_decor); + gwl_xdg_decor_system_destroy(display->xdg_decor); } } @@ -1082,7 +1082,7 @@ static void keyboard_depressed_state_key_event(GWL_Seat *seat, } static void keyboard_depressed_state_push_events_from_change( - GWL_Seat *seat, const WGL_KeyboardDepressedState &key_depressed_prev) + GWL_Seat *seat, const GWL_KeyboardDepressedState &key_depressed_prev) { GHOST_IWindow *win = ghost_wl_surface_user_data(seat->keyboard.wl_surface); GHOST_SystemWayland *system = seat->system; @@ -2576,7 +2576,7 @@ static void keyboard_handle_enter(void *data, /* If there are any keys held when activating the window, * modifiers will be compared against the seat state, * only enabling modifiers that were previously disabled. */ - WGL_KeyboardDepressedState key_depressed_prev = seat->key_depressed; + GWL_KeyboardDepressedState key_depressed_prev = seat->key_depressed; keyboard_depressed_state_reset(seat); uint32_t *key; @@ -3231,13 +3231,13 @@ static void global_handle_add(void *data, wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3)); } else if (STREQ(interface, xdg_wm_base_interface.name)) { - WGL_XDG_Decor_System &decor = *display->xdg_decor; + GWL_XDG_Decor_System &decor = *display->xdg_decor; decor.shell = static_cast( wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1)); xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr); } else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) { - WGL_XDG_Decor_System &decor = *display->xdg_decor; + GWL_XDG_Decor_System &decor = *display->xdg_decor; decor.manager = static_cast( wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1)); } @@ -3361,7 +3361,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di } /* This may be removed later if decorations are required, needed as part of registration. */ - display_->xdg_decor = new WGL_XDG_Decor_System; + display_->xdg_decor = new GWL_XDG_Decor_System; /* Register interfaces. */ struct wl_registry *registry = wl_display_get_registry(display_->wl_display); @@ -3374,7 +3374,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (display_->libdecor_required) { - wgl_xdg_decor_system_destroy(display_->xdg_decor); + gwl_xdg_decor_system_destroy(display_->xdg_decor); display_->xdg_decor = nullptr; if (!has_libdecor) { @@ -3395,8 +3395,8 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di #ifdef WITH_GHOST_WAYLAND_LIBDECOR if (use_libdecor) { - display_->libdecor = new WGL_LibDecor_System; - WGL_LibDecor_System &decor = *display_->libdecor; + display_->libdecor = new GWL_LibDecor_System; + GWL_LibDecor_System &decor = *display_->libdecor; decor.context = libdecor_new(display_->wl_display, &libdecor_interface); if (!decor.context) { display_destroy(display_); @@ -3406,7 +3406,7 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di else #endif { - WGL_XDG_Decor_System &decor = *display_->xdg_decor; + GWL_XDG_Decor_System &decor = *display_->xdg_decor; if (!decor.shell) { display_destroy(display_); throw std::runtime_error("Wayland: unable to access xdg_shell!"); @@ -3505,7 +3505,7 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co } #endif - /* Use local #WGL_KeyboardDepressedState to check which key is pressed. + /* Use local #GWL_KeyboardDepressedState to check which key is pressed. * Use XKB as the source of truth, if there is any discrepancy. */ for (int i = 0; i < MOD_INDEX_NUM; i++) { if (UNLIKELY(seat->xkb_keymap_mod_index[i] == XKB_MOD_INVALID)) { -- cgit v1.2.3 From 1e1b9eef1b1a424a1e9c0e53cf7a19db053b1f0c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 13:56:40 +1100 Subject: GHOST/Wayland: skip redundant strlen() sending the clipboard --- intern/ghost/intern/GHOST_SystemWayland.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index a307dabb690..b8b9fda8f74 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -293,6 +293,7 @@ struct GWL_DataOffer { struct GWL_DataSource { struct wl_data_source *wl_data_source = nullptr; char *buffer_out = nullptr; + size_t buffer_out_len = 0; }; /** @@ -1273,7 +1274,7 @@ static void data_source_handle_send(void *data, CLOG_INFO(LOG, 2, "send"); const char *const buffer = seat->data_source->buffer_out; - if (write(fd, buffer, strlen(buffer)) < 0) { + if (write(fd, buffer, seat->data_source->buffer_out_len) < 0) { GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl); } close(fd); @@ -3584,9 +3585,9 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c /* Copy buffer. */ free(data_source->buffer_out); - const size_t buffer_size = strlen(buffer) + 1; - data_source->buffer_out = static_cast(malloc(buffer_size)); - std::memcpy(data_source->buffer_out, buffer, buffer_size); + data_source->buffer_out_len = strlen(buffer); + data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); + std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); data_source->wl_data_source = wl_data_device_manager_create_data_source( display_->data_device_manager); -- cgit v1.2.3 From b0eff51fb73cfd9def696e3ede5ff23817f35784 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 14:02:32 +1100 Subject: GHOST/Wayland: primary clipboard support Match X11's primary clipboard support (typically used for MMB to paste the previous selection). --- intern/ghost/CMakeLists.txt | 4 + intern/ghost/intern/GHOST_SystemWayland.cpp | 341 +++++++++++++++++++++++++++- intern/ghost/intern/GHOST_SystemWayland.h | 3 + 3 files changed, 341 insertions(+), 7 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 72621648608..c05f2a327b1 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -376,6 +376,10 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) generate_protocol_bindings( "${WAYLAND_PROTOCOLS_DIR}/unstable/tablet/tablet-unstable-v2.xml" ) + # Primary-selection. + generate_protocol_bindings( + "${WAYLAND_PROTOCOLS_DIR}/unstable/primary-selection/primary-selection-unstable-v1.xml" + ) add_definitions(-DWITH_GHOST_WAYLAND) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index b8b9fda8f74..6db8b9d33f8 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -51,6 +51,7 @@ /* Generated by `wayland-scanner`. */ #include +#include #include #include #include @@ -426,6 +427,53 @@ static void gwl_xdg_decor_system_destroy(GWL_XDG_Decor_System *decor) delete decor; } +struct GWL_PrimarySelection_DataOffer { + struct zwp_primary_selection_offer_v1 *id = nullptr; + std::atomic in_use = false; + + std::unordered_set types; +}; + +struct GWL_PrimarySelection_DataSource { + struct zwp_primary_selection_source_v1 *wl_source = nullptr; + char *buffer_out = nullptr; + size_t buffer_out_len = 0; +}; + +/** Primary selection support. */ +struct GWL_PrimarySelection { + + GWL_PrimarySelection_DataSource *data_source = nullptr; + std::mutex data_source_mutex; + + GWL_PrimarySelection_DataOffer *data_offer = nullptr; + std::mutex data_offer_mutex; +}; + +static void gwl_primary_selection_discard_offer(GWL_PrimarySelection *primary) +{ + if (primary->data_offer == nullptr) { + return; + } + zwp_primary_selection_offer_v1_destroy(primary->data_offer->id); + delete primary->data_offer; + primary->data_offer = nullptr; +} + +static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary) +{ + GWL_PrimarySelection_DataSource *data_source = primary->data_source; + if (data_source == nullptr) { + return; + } + free(data_source->buffer_out); + if (data_source->wl_source) { + zwp_primary_selection_source_v1_destroy(data_source->wl_source); + } + delete primary->data_source; + primary->data_source = nullptr; +} + struct GWL_Seat { GHOST_SystemWayland *system = nullptr; @@ -515,6 +563,9 @@ struct GWL_Seat { struct GWL_DataSource *data_source = nullptr; std::mutex data_source_mutex; + struct zwp_primary_selection_device_v1 *primary_selection_device = nullptr; + struct GWL_PrimarySelection primary_selection; + /** Last device that was active. */ uint32_t data_source_serial = 0; }; @@ -540,6 +591,8 @@ struct GWL_Display { struct zwp_tablet_manager_v2 *tablet_manager = nullptr; struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; + + struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = nullptr; }; #undef LOG @@ -642,6 +695,22 @@ static void display_destroy(GWL_Display *display) } } + { + GWL_PrimarySelection *primary = &seat->primary_selection; + std::lock_guard lock{primary->data_offer_mutex}; + gwl_primary_selection_discard_offer(primary); + } + + { + GWL_PrimarySelection *primary = &seat->primary_selection; + std::lock_guard lock{primary->data_source_mutex}; + gwl_primary_selection_discard_source(primary); + } + + if (seat->primary_selection_device) { + zwp_primary_selection_device_v1_destroy(seat->primary_selection_device); + } + if (seat->data_device) { wl_data_device_release(seat->data_device); } @@ -696,6 +765,10 @@ static void display_destroy(GWL_Display *display) zwp_pointer_constraints_v1_destroy(display->pointer_constraints); } + if (display->primary_selection_device_manager) { + zwp_primary_selection_device_manager_v1_destroy(display->primary_selection_device_manager); + } + if (display->wl_compositor) { wl_compositor_destroy(display->wl_compositor); } @@ -1250,6 +1323,35 @@ static std::string read_pipe(GWL_DataOffer *data_offer, return data; } +static std::string read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, + const std::string mime_receive, + std::mutex *mutex) +{ + int pipefd[2]; + if (UNLIKELY(pipe(pipefd) != 0)) { + return {}; + } + zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + close(pipefd[1]); + + data_offer->in_use.store(false); + + if (mutex) { + mutex->unlock(); + } + /* WARNING: `data_offer_base` may be freed from now on. */ + + std::string data; + ssize_t len; + char buffer[4096]; + while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { + data.insert(data.end(), buffer, buffer + len); + } + close(pipefd[0]); + + return data; +} + /** * A target accepts an offered mime type. * @@ -2880,6 +2982,158 @@ static const struct wl_keyboard_listener keyboard_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (Primary Selection Offer), #zwp_primary_selection_offer_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_PRIMARY_SELECTION_OFFER = {"ghost.wl.handle.primary_selection_offer"}; +#define LOG (&LOG_WL_PRIMARY_SELECTION_OFFER) + +static void primary_selection_offer_offer(void *data, + struct zwp_primary_selection_offer_v1 *id, + const char *type) +{ + GWL_PrimarySelection_DataOffer *data_offer = static_cast(data); + if (data_offer->id != id) { + CLOG_INFO(LOG, 2, "offer: %p: offer for unknown selection %p of %s (skipped)", data, id, type); + return; + } + + data_offer->types.insert(std::string(type)); +} + +static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener = { + primary_selection_offer_offer, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Primary Selection Device), #zwp_primary_selection_device_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_PRIMARY_SELECTION_DEVICE = {"ghost.wl.handle.primary_selection_device"}; +#define LOG (&LOG_WL_PRIMARY_SELECTION_DEVICE) + +static void primary_selection_device_handle_data_offer( + void * /*data*/, + struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/, + struct zwp_primary_selection_offer_v1 *id) +{ + CLOG_INFO(LOG, 2, "data_offer"); + + GWL_PrimarySelection_DataOffer *data_offer = new GWL_PrimarySelection_DataOffer; + data_offer->id = id; + zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, data_offer); +} + +static void primary_selection_device_handle_selection( + void *data, + struct zwp_primary_selection_device_v1 * /*zwp_primary_selection_device_v1*/, + struct zwp_primary_selection_offer_v1 *id) +{ + GWL_PrimarySelection *primary = static_cast(data); + + std::lock_guard lock{primary->data_offer_mutex}; + + /* Delete old data offer. */ + if (primary->data_offer != nullptr) { + gwl_primary_selection_discard_offer(primary); + } + + if (id == nullptr) { + CLOG_INFO(LOG, 2, "selection: (skipped)"); + return; + } + CLOG_INFO(LOG, 2, "selection"); + /* Get new data offer. */ + GWL_PrimarySelection_DataOffer *data_offer = static_cast( + zwp_primary_selection_offer_v1_get_user_data(id)); + primary->data_offer = data_offer; + + auto read_selection_fn = [](GWL_PrimarySelection *primary) { + GHOST_SystemWayland *system = static_cast(GHOST_ISystem::getSystem()); + primary->data_offer_mutex.lock(); + + GWL_PrimarySelection_DataOffer *data_offer = primary->data_offer; + std::string mime_receive; + for (const std::string type : {mime_text_utf8, mime_text_plain}) { + if (data_offer->types.count(type)) { + mime_receive = type; + break; + } + } + const std::string data = read_pipe_primary( + data_offer, mime_receive, &primary->data_offer_mutex); + + { + std::lock_guard lock{system_clipboard_mutex}; + system->clipboard_primary_set(data); + } + }; + + std::thread read_thread(read_selection_fn, primary); + read_thread.detach(); +} + +static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { + primary_selection_device_handle_data_offer, + primary_selection_device_handle_selection, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Primary Selection Source), #zwp_primary_selection_source_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_PRIMARY_SELECTION_SOURCE = {"ghost.wl.handle.primary_selection_source"}; +#define LOG (&LOG_WL_PRIMARY_SELECTION_SOURCE) + +static void primary_selection_source_send(void *data, + struct zwp_primary_selection_source_v1 * /*source*/, + const char * /*mime_type*/, + int32_t fd) +{ + CLOG_INFO(LOG, 2, "send"); + + GWL_PrimarySelection *primary = static_cast(data); + + std::lock_guard lock{primary->data_source_mutex}; + GWL_PrimarySelection_DataSource *data_source = primary->data_source; + + const char *const buffer = data_source->buffer_out; + if (write(fd, buffer, data_source->buffer_out_len) < 0) { + GHOST_PRINT("error writing to primary clipboard: " << std::strerror(errno) << std::endl); + } + close(fd); +} + +static void primary_selection_source_cancelled(void *data, + struct zwp_primary_selection_source_v1 *source) +{ + CLOG_INFO(LOG, 2, "cancelled"); + + GWL_PrimarySelection *primary = static_cast(data); + + if (source == primary->data_source->wl_source) { + gwl_primary_selection_discard_source(primary); + } +} + +static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = { + primary_selection_source_send, + primary_selection_source_cancelled, +}; + +#undef LOG + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Seat), #wl_seat_listener * \{ */ @@ -2927,6 +3181,17 @@ static void seat_handle_capabilities(void *data, seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data); } + + if (seat->system) { + zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = + seat->system->wl_primary_selection_manager(); + seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + primary_selection_device_manager, seat->wl_seat); + + zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, + &primary_selection_device_listener, + &seat->primary_selection); + } } static void seat_handle_name(void *data, struct wl_seat * /*wl_seat*/, const char *name) @@ -3297,6 +3562,12 @@ static void global_handle_add(void *data, display->pointer_constraints = static_cast( wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); } + else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) { + display->primary_selection_device_manager = + static_cast(wl_registry_bind( + wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1)); + } + else { found = false; @@ -3564,20 +3835,52 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const return GHOST_kSuccess; } -char *GHOST_SystemWayland::getClipboard(bool /*selection*/) const +char *GHOST_SystemWayland::getClipboard(bool selection) const { - char *clipboard = static_cast(malloc(clipboard_.size() + 1)); - memcpy(clipboard, clipboard_.data(), clipboard_.size() + 1); + const std::string &buf = selection ? clipboard_primary_ : clipboard_; + char *clipboard = static_cast(malloc(buf.size() + 1)); + memcpy(clipboard, buf.data(), buf.size() + 1); return clipboard; } -void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) const +static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) { - if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) { + if (!display->primary_selection_device_manager) { return; } + GWL_Seat *seat = display->seats[0]; + GWL_PrimarySelection *primary = &seat->primary_selection; - GWL_Seat *seat = display_->seats[0]; + std::lock_guard lock{primary->data_source_mutex}; + + gwl_primary_selection_discard_source(primary); + + GWL_PrimarySelection_DataSource *data_source = new GWL_PrimarySelection_DataSource; + primary->data_source = data_source; + + data_source->buffer_out_len = strlen(buffer); + data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); + std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); + + data_source->wl_source = zwp_primary_selection_device_manager_v1_create_source( + display->primary_selection_device_manager); + + zwp_primary_selection_source_v1_add_listener( + data_source->wl_source, &primary_selection_source_listener, primary); + + for (const std::string &type : mime_send) { + zwp_primary_selection_source_v1_offer(data_source->wl_source, type.c_str()); + } + + if (seat->primary_selection_device) { + zwp_primary_selection_device_v1_set_selection( + seat->primary_selection_device, data_source->wl_source, seat->data_source_serial); + } +} + +static void system_clipboard_put(GWL_Display *display, const char *buffer) +{ + GWL_Seat *seat = display->seats[0]; std::lock_guard lock{seat->data_source_mutex}; @@ -3590,7 +3893,7 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); data_source->wl_data_source = wl_data_device_manager_create_data_source( - display_->data_device_manager); + display->data_device_manager); wl_data_source_add_listener(data_source->wl_data_source, &data_source_listener, seat); @@ -3604,6 +3907,20 @@ void GHOST_SystemWayland::putClipboard(const char *buffer, bool /*selection*/) c } } +void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const +{ + if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) { + return; + } + + if (selection) { + system_clipboard_put_primary_selection(display_, buffer); + } + else { + system_clipboard_put(display_, buffer); + } +} + uint8_t GHOST_SystemWayland::getNumDisplays() const { return display_ ? uint8_t(display_->outputs.size()) : 0; @@ -4345,6 +4662,11 @@ wl_compositor *GHOST_SystemWayland::wl_compositor() return display_->wl_compositor; } +struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wl_primary_selection_manager() +{ + return display_->primary_selection_device_manager; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *GHOST_SystemWayland::libdecor_context() @@ -4412,6 +4734,11 @@ void GHOST_SystemWayland::clipboard_set(const std::string &clipboard) clipboard_ = clipboard; } +void GHOST_SystemWayland::clipboard_primary_set(const std::string &clipboard) +{ + clipboard_primary_ = clipboard; +} + void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) { #define SURFACE_CLEAR_PTR(surface_test) \ diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index ca78ccb89ab..ddcd63610ef 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -158,6 +158,7 @@ class GHOST_SystemWayland : public GHOST_System { struct wl_display *wl_display(); struct wl_compositor *wl_compositor(); + struct zwp_primary_selection_device_manager_v1 *wl_primary_selection_manager(); #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *libdecor_context(); @@ -173,6 +174,7 @@ class GHOST_SystemWayland : public GHOST_System { /* WAYLAND utility functions. */ void clipboard_set(const std::string &clipboard); + void clipboard_primary_set(const std::string &clipboard); /** Clear all references to this surface to prevent accessing NULL pointers. */ void window_surface_unref(const wl_surface *wl_surface); @@ -192,4 +194,5 @@ class GHOST_SystemWayland : public GHOST_System { private: struct GWL_Display *display_; std::string clipboard_; + std::string clipboard_primary_; }; -- cgit v1.2.3 From 90686ff6f47ef14e96d94b7ad32f63a7015ca1c8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 20 Oct 2022 09:52:37 +0200 Subject: Fix WebM naming in the interface Use the official spelling of the WebM codec. Only affects the interface string and not the identifier used in the Python API. Should not even affect translations: the current msgstr's do no translate the original string. Reported by Anton Raves, thanks! --- source/blender/makesrna/intern/rna_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 8fc504f192e..0eb168ecd8e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5945,7 +5945,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) {AV_CODEC_ID_PNG, "PNG", 0, "PNG", ""}, {AV_CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""}, {AV_CODEC_ID_THEORA, "THEORA", 0, "Theora", ""}, - {AV_CODEC_ID_VP9, "WEBM", 0, "WEBM / VP9", ""}, + {AV_CODEC_ID_VP9, "WEBM", 0, "WebM / VP9", ""}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From ff157d7ebadc39cd027cbc75e67267d78cf1c80a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 20 Oct 2022 10:09:32 +0200 Subject: Fix incorrect shader state after shader interface creation Use store-current-and-restore-previous OpenGL program in the OpenGL Shader Interface. This is a better fix for the initial error, which additionally solves interface artifacts when opening non-default startyp files on macOS with AMD GPU. --- source/blender/gpu/opengl/gl_shader.cc | 5 ----- source/blender/gpu/opengl/gl_shader_interface.cc | 10 ++++++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index f6f14932de7..dafcf4dbf33 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -1004,11 +1004,6 @@ bool GLShader::finalize(const shader::ShaderCreateInfo *info) else { interface = new GLShaderInterface(shader_program_); } - /** - * WORKAROUND: Creating the shader interface changes the active program. - * Make sure to update the context, otherwise we might have a missing bind. - */ - Context::get()->shader = this; return true; } diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index c9432fca561..ef97d74bf81 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -200,6 +200,9 @@ static Type gpu_type_from_gl_type(int gl_type) GLShaderInterface::GLShaderInterface(GLuint program) { + GLuint last_program; + glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program); + /* Necessary to make #glUniform works. */ glUseProgram(program); @@ -385,6 +388,8 @@ GLShaderInterface::GLShaderInterface(GLuint program) // this->debug_print(); this->sort_inputs(); + + glUseProgram(last_program); } GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateInfo &info) @@ -442,6 +447,9 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI uint32_t name_buffer_offset = 0; /* Necessary to make #glUniform works. TODO(fclem) Remove. */ + GLuint last_program; + glGetIntegerv(GL_CURRENT_PROGRAM, (GLint *)&last_program); + glUseProgram(program); /* Attributes */ @@ -552,6 +560,8 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI this->sort_inputs(); // this->debug_print(); + + glUseProgram(last_program); } GLShaderInterface::~GLShaderInterface() -- cgit v1.2.3 From bd9d68e4dc6fcc840afa514cba7975a6bd86386d Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 20 Oct 2022 11:22:51 +0200 Subject: Fix (studio-reported) issue with overrides on library relocating. Liboverrides that were using a missing linked reference ID would not get their 'MISSING' tag properly cleared afer relocating, in case their linked reference is no more missing. Reported by Andy (@eyecandy) from Blender studio. --- source/blender/blenkernel/intern/blendfile_link_append.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index 394469e19a4..a937c74578a 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -1614,6 +1614,9 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, (id->tag & LIB_TAG_PRE_EXISTING) == 0) { continue; } + if ((id->override_library->reference->tag & LIB_TAG_MISSING) == 0) { + id->tag &= ~LIB_TAG_MISSING; + } if ((id->override_library->reference->tag & LIB_TAG_PRE_EXISTING) == 0) { BKE_lib_override_library_update(bmain, id); } -- cgit v1.2.3 From 40afb8ae6a036d904a10680530a89955248d0e06 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 20 Oct 2022 11:29:47 +0200 Subject: Lib reload/relocate: Improve performances. Reduce amounts of viewlayer updates during remapping while relocating libraries. Gives some improvements on relocating process, depending on complexity of existing scene and reloaded libraries, whether there is liboverrides to resync, etc., can give up to 10% speedup. --- source/blender/blenkernel/intern/blendfile_link_append.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index a937c74578a..4dd225c09ec 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -1494,6 +1494,7 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, * code is wrong, we need to redo it here after adding them back to main. */ BKE_main_id_refcount_recompute(bmain, false); + BKE_layer_collection_resync_forbid(); /* Note that in reload case, we also want to replace indirect usages. */ const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE); @@ -1523,6 +1524,8 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, id_us_plus_no_lib(&old_key->id); } } + BKE_layer_collection_resync_allow(); + BKE_main_collection_sync_remap(bmain); BKE_main_unlock(bmain); -- cgit v1.2.3 From 8a43bfd8fd8d08438c5cc58befdf3e661aa17297 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 20:44:03 +1100 Subject: GHOST/Wayland: refactor copy/paste buffer storage - Improve reporting when reading a file descriptor into a buffer fails, also check for failure to allocate memory. - Store buffers with size in a simple struct. - Use shared utility functions for simple buffer operations. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 217 ++++++++++++++++++++-------- intern/ghost/intern/GHOST_SystemWayland.h | 7 +- 2 files changed, 157 insertions(+), 67 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 6db8b9d33f8..42bfc6aa1e7 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -237,6 +237,43 @@ static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = { /** \name Private Types & Defines * \{ */ +struct GWL_SimpleBuffer { + /** Constant data, but may be freed. */ + const char *data = nullptr; + size_t data_size = 0; +}; + +static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer) +{ + free(const_cast(buffer->data)); + buffer->data = nullptr; + buffer->data_size = 0; +} + +static void gwl_simple_buffer_set(GWL_SimpleBuffer *buffer, const char *data, size_t data_size) +{ + free(const_cast(buffer->data)); + buffer->data = data; + buffer->data_size = data_size; +} + +static void gwl_simple_buffer_set_from_string(GWL_SimpleBuffer *buffer, const char *str) +{ + free(const_cast(buffer->data)); + buffer->data_size = strlen(str); + char *data = static_cast(malloc(buffer->data_size)); + std::memcpy(data, str, buffer->data_size); + buffer->data = data; +} + +static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) +{ + char *buffer_str = static_cast(malloc(buffer->data_size + 1)); + memcpy(buffer_str, buffer->data, buffer->data_size); + buffer_str[buffer->data_size] = '\0'; + return buffer_str; +} + /** * From XKB internals, use for converting a scan-code from WAYLAND to a #xkb_keycode_t. * Ideally this wouldn't need a local define. @@ -293,8 +330,7 @@ struct GWL_DataOffer { struct GWL_DataSource { struct wl_data_source *wl_data_source = nullptr; - char *buffer_out = nullptr; - size_t buffer_out_len = 0; + GWL_SimpleBuffer buffer_out; }; /** @@ -436,8 +472,7 @@ struct GWL_PrimarySelection_DataOffer { struct GWL_PrimarySelection_DataSource { struct zwp_primary_selection_source_v1 *wl_source = nullptr; - char *buffer_out = nullptr; - size_t buffer_out_len = 0; + GWL_SimpleBuffer buffer_out; }; /** Primary selection support. */ @@ -466,7 +501,7 @@ static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary) if (data_source == nullptr) { return; } - free(data_source->buffer_out); + gwl_simple_buffer_free_data(&data_source->buffer_out); if (data_source->wl_source) { zwp_primary_selection_source_v1_destroy(data_source->wl_source); } @@ -593,6 +628,9 @@ struct GWL_Display { struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = nullptr; + + GWL_SimpleBuffer clipboard; + GWL_SimpleBuffer clipboard_primary; }; #undef LOG @@ -671,7 +709,7 @@ static void display_destroy(GWL_Display *display) { std::lock_guard lock{seat->data_source_mutex}; if (seat->data_source) { - free(seat->data_source->buffer_out); + gwl_simple_buffer_free_data(&seat->data_source->buffer_out); if (seat->data_source->wl_data_source) { wl_data_source_destroy(seat->data_source->wl_data_source); } @@ -795,6 +833,9 @@ static void display_destroy(GWL_Display *display) wl_display_disconnect(display->wl_display); } + gwl_simple_buffer_free_data(&display->clipboard); + gwl_simple_buffer_free_data(&display->clipboard_primary); + delete display; } @@ -1294,9 +1335,74 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event) } } -static std::string read_pipe(GWL_DataOffer *data_offer, +/** + * Read from `fd` into a buffer which is returned. + * \return the buffer or null on failure. + */ +static const char *read_file_as_buffer(const int fd, size_t *r_len) +{ + struct ByteChunk { + ByteChunk *next; + char data[4096 - sizeof(ByteChunk *)]; + }; + ByteChunk *chunk_first = nullptr, **chunk_link_p = &chunk_first; + bool ok = true; + size_t len = 0; + while (true) { + ByteChunk *chunk = static_cast(malloc(sizeof(*chunk))); + if (UNLIKELY(chunk == nullptr)) { + CLOG_WARN(LOG, "unable to allocate chunk for file buffer"); + ok = false; + break; + } + chunk->next = nullptr; + const ssize_t len_chunk = read(fd, chunk->data, sizeof(chunk->data)); + if (len_chunk <= 0) { + if (UNLIKELY(len_chunk < 0)) { + CLOG_WARN(LOG, "error reading from pipe: %s", std::strerror(errno)); + ok = false; + } + free(chunk); + break; + } + if (chunk_first == nullptr) { + chunk_first = chunk; + } + *chunk_link_p = chunk; + chunk_link_p = &chunk->next; + len += len_chunk; + } + + char *buf = nullptr; + if (ok) { + buf = static_cast(malloc(len)); + if (UNLIKELY(buf == nullptr)) { + CLOG_WARN(LOG, "unable to allocate file buffer: %zu bytes", len); + ok = false; + } + } + + *r_len = ok ? len : 0; + char *buf_stride = buf; + while (chunk_first) { + if (ok) { + const size_t len_chunk = std::min(len, sizeof(chunk_first->data)); + memcpy(buf_stride, chunk_first->data, len_chunk); + buf_stride += len_chunk; + len -= len_chunk; + } + ByteChunk *chunk = chunk_first->next; + free(chunk_first); + chunk_first = chunk; + } + + return buf; +} + +static const char *read_pipe(GWL_DataOffer *data_offer, const std::string mime_receive, - std::mutex *mutex) + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { @@ -1312,20 +1418,15 @@ static std::string read_pipe(GWL_DataOffer *data_offer, } /* WARNING: `data_offer` may be freed from now on. */ - std::string data; - ssize_t len; - char buffer[4096]; - while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { - data.insert(data.end(), buffer, buffer + len); - } + const char *buf = read_file_as_buffer(pipefd[0], r_len); close(pipefd[0]); - - return data; + return buf; } -static std::string read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, +static const char *read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, const std::string mime_receive, - std::mutex *mutex) + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { @@ -1339,17 +1440,10 @@ static std::string read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, if (mutex) { mutex->unlock(); } - /* WARNING: `data_offer_base` may be freed from now on. */ - - std::string data; - ssize_t len; - char buffer[4096]; - while ((len = read(pipefd[0], buffer, sizeof(buffer))) > 0) { - data.insert(data.end(), buffer, buffer + len); - } + /* WARNING: `data_offer` may be freed from now on. */ + const char *buf = read_file_as_buffer(pipefd[0], r_len); close(pipefd[0]); - - return data; + return buf; } /** @@ -1375,9 +1469,9 @@ static void data_source_handle_send(void *data, CLOG_INFO(LOG, 2, "send"); - const char *const buffer = seat->data_source->buffer_out; - if (write(fd, buffer, seat->data_source->buffer_out_len) < 0) { - GHOST_PRINT("error writing to clipboard: " << std::strerror(errno) << std::endl); + const char *const buffer = seat->data_source->buffer_out.data; + if (UNLIKELY(write(fd, buffer, seat->data_source->buffer_out.data_size) < 0)) { + CLOG_WARN(LOG, "error writing to clipboard: %s", std::strerror(errno)); } close(fd); } @@ -1598,7 +1692,9 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat const std::string mime_receive) { const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; - const std::string data = read_pipe(data_offer, mime_receive, nullptr); + size_t data_buf_len = 0; + const char *data_buf = read_pipe(data_offer, mime_receive, nullptr, &data_buf_len); + std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; CLOG_INFO( LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str()); @@ -1713,12 +1809,15 @@ static void data_device_handle_selection(void *data, break; } } - const std::string data = read_pipe( - data_offer, mime_receive, &seat->data_offer_copy_paste_mutex); + + size_t data_len = 0; + const char *data = read_pipe( + data_offer, mime_receive, &seat->data_offer_copy_paste_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; - system->clipboard_set(data); + GWL_SimpleBuffer *buf = system->clipboard_data(false); + gwl_simple_buffer_set(buf, data, data_len); } }; @@ -3065,12 +3164,14 @@ static void primary_selection_device_handle_selection( break; } } - const std::string data = read_pipe_primary( - data_offer, mime_receive, &primary->data_offer_mutex); + size_t data_len = 0; + const char *data = read_pipe_primary( + data_offer, mime_receive, &primary->data_offer_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; - system->clipboard_primary_set(data); + GWL_SimpleBuffer *buf = system->clipboard_data(true); + gwl_simple_buffer_set(buf, data, data_len); } }; @@ -3106,9 +3207,9 @@ static void primary_selection_source_send(void *data, std::lock_guard lock{primary->data_source_mutex}; GWL_PrimarySelection_DataSource *data_source = primary->data_source; - const char *const buffer = data_source->buffer_out; - if (write(fd, buffer, data_source->buffer_out_len) < 0) { - GHOST_PRINT("error writing to primary clipboard: " << std::strerror(errno) << std::endl); + const char *const buffer = data_source->buffer_out.data; + if (UNLIKELY(write(fd, buffer, data_source->buffer_out.data_size) < 0)) { + CLOG_WARN(LOG, "error writing to primary clipboard: %s", std::strerror(errno)); } close(fd); } @@ -3837,10 +3938,11 @@ GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const char *GHOST_SystemWayland::getClipboard(bool selection) const { - const std::string &buf = selection ? clipboard_primary_ : clipboard_; - char *clipboard = static_cast(malloc(buf.size() + 1)); - memcpy(clipboard, buf.data(), buf.size() + 1); - return clipboard; + const GWL_SimpleBuffer *buf = clipboard_data(selection); + if (buf->data == nullptr) { + return nullptr; + } + return gwl_simple_buffer_as_string(buf); } static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) @@ -3858,9 +3960,8 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c GWL_PrimarySelection_DataSource *data_source = new GWL_PrimarySelection_DataSource; primary->data_source = data_source; - data_source->buffer_out_len = strlen(buffer); - data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); - std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); + /* Copy buffer. */ + gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); data_source->wl_source = zwp_primary_selection_device_manager_v1_create_source( display->primary_selection_device_manager); @@ -3887,10 +3988,7 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) GWL_DataSource *data_source = seat->data_source; /* Copy buffer. */ - free(data_source->buffer_out); - data_source->buffer_out_len = strlen(buffer); - data_source->buffer_out = static_cast(malloc(data_source->buffer_out_len)); - std::memcpy(data_source->buffer_out, buffer, data_source->buffer_out_len); + gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); data_source->wl_data_source = wl_data_device_manager_create_data_source( display->data_device_manager); @@ -4729,16 +4827,6 @@ GHOST_WindowWayland *ghost_wl_surface_user_data(struct wl_surface *wl_surface) * Functionality only used for the WAYLAND implementation. * \{ */ -void GHOST_SystemWayland::clipboard_set(const std::string &clipboard) -{ - clipboard_ = clipboard; -} - -void GHOST_SystemWayland::clipboard_primary_set(const std::string &clipboard) -{ - clipboard_primary_ = clipboard; -} - void GHOST_SystemWayland::window_surface_unref(const wl_surface *wl_surface) { #define SURFACE_CLEAR_PTR(surface_test) \ @@ -4939,6 +5027,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod return GHOST_kSuccess; } +struct GWL_SimpleBuffer *GHOST_SystemWayland::clipboard_data(bool selection) const +{ + return selection ? &display_->clipboard_primary : &display_->clipboard; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR bool GHOST_SystemWayland::use_libdecor_runtime() { diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index ddcd63610ef..4e77c5b9c0b 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -173,9 +173,6 @@ class GHOST_SystemWayland : public GHOST_System { /* WAYLAND utility functions. */ - void clipboard_set(const std::string &clipboard); - void clipboard_primary_set(const std::string &clipboard); - /** Clear all references to this surface to prevent accessing NULL pointers. */ void window_surface_unref(const wl_surface *wl_surface); @@ -187,12 +184,12 @@ class GHOST_SystemWayland : public GHOST_System { wl_surface *wl_surface, int scale); + struct GWL_SimpleBuffer *clipboard_data(bool selection) const; + #ifdef WITH_GHOST_WAYLAND_LIBDECOR static bool use_libdecor_runtime(); #endif private: struct GWL_Display *display_; - std::string clipboard_; - std::string clipboard_primary_; }; -- cgit v1.2.3 From c81bc09876f84753f3c69e024196b70a88c6cebe Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 20 Oct 2022 12:51:20 +0200 Subject: GPU: Avoid undocumented/fragile dependency on shader enumerator order Previously this was using `GPU_SHADER_TEXT` as default value indicating an "unset" state. This wasn't documented in the definition (and so D16284 added a new enumerator that broke this). Plus code was assuming this enumerator would always have the value 0 without specifying this in the definition either. In this case it's easy to not rely on the enum value at all, and just use `std::optional` to add a "unset" state. Differential Revision: https://developer.blender.org/D16303 --- source/blender/gpu/intern/gpu_immediate.cc | 11 +++++++---- source/blender/gpu/intern/gpu_immediate_private.hh | 8 +++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc index 3b4accf9cc5..81c0a65bb7c 100644 --- a/source/blender/gpu/intern/gpu_immediate.cc +++ b/source/blender/gpu/intern/gpu_immediate.cc @@ -45,7 +45,7 @@ void immBindShader(GPUShader *shader) BLI_assert(imm->shader == nullptr); imm->shader = shader; - imm->builtin_shader_bound = GPU_SHADER_TEXT; /* Default value. */ + imm->builtin_shader_bound = std::nullopt; if (!imm->vertex_format.packed) { VertexFormat_pack(&imm->vertex_format); @@ -125,9 +125,12 @@ static void wide_line_workaround_start(GPUPrimType prim_type) /* No need to change the shader. */ return; } + if (!imm->builtin_shader_bound) { + return; + } eGPUBuiltinShader polyline_sh; - switch (imm->builtin_shader_bound) { + switch (*imm->builtin_shader_bound) { case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR: polyline_sh = GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR; break; @@ -180,8 +183,8 @@ static void wide_line_workaround_end() } immUnbindProgram(); - immBindBuiltinProgram(imm->prev_builtin_shader); - imm->prev_builtin_shader = GPU_SHADER_TEXT; + immBindBuiltinProgram(*imm->prev_builtin_shader); + imm->prev_builtin_shader = std::nullopt; } } diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh index 74ebbdc7ae3..c4e11e7082b 100644 --- a/source/blender/gpu/intern/gpu_immediate_private.hh +++ b/source/blender/gpu/intern/gpu_immediate_private.hh @@ -9,6 +9,8 @@ #pragma once +#include + #include "GPU_batch.h" #include "GPU_primitive.h" #include "GPU_shader.h" @@ -42,9 +44,9 @@ class Immediate { /** Wide Line workaround. */ /** Previously bound shader to restore after drawing. */ - eGPUBuiltinShader prev_builtin_shader = GPU_SHADER_TEXT; - /** Builtin shader index. Used to test if the workaround can be done. */ - eGPUBuiltinShader builtin_shader_bound = GPU_SHADER_TEXT; + std::optional prev_builtin_shader; + /** Builtin shader index. Used to test if the line width workaround can be done. */ + std::optional builtin_shader_bound; /** Uniform color: Kept here to update the wide-line shader just before #immBegin. */ float uniform_color[4]; -- cgit v1.2.3 From a30128a3c1a2eb7767ec87b99a09f2893e1c5de7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 20 Oct 2022 22:25:19 +1100 Subject: Fix missing free in 8a43bfd8fd8d08438c5cc58befdf3e661aa17297 --- intern/ghost/intern/GHOST_SystemWayland.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 42bfc6aa1e7..264476f00bc 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1695,6 +1695,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat size_t data_buf_len = 0; const char *data_buf = read_pipe(data_offer, mime_receive, nullptr, &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; + free(const_cast(data_buf)); CLOG_INFO( LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str()); -- cgit v1.2.3 From 303dd263e2590f981ee1917554cd688dd951ee2c Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 13:33:08 +0200 Subject: Build: update OSL to version 1.12.6.2 Required changes to make OSL pick up the new oslnoise library. Ref D16269, T101403 --- build_files/build_environment/cmake/versions.cmake | 6 +++--- build_files/cmake/Modules/FindOSL.cmake | 15 +++++++++++++-- build_files/cmake/platform/platform_apple.cmake | 17 +++-------------- build_files/cmake/platform/platform_win32.cmake | 8 ++++++++ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index bfc6d27f74d..469988dab0c 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -189,9 +189,9 @@ set(TIFF_HASH_TYPE MD5) set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz) set(TIFF_CPE "cpe:2.3:a:libtiff:libtiff:${TIFF_VERSION}:*:*:*:*:*:*:*") -set(OSL_VERSION 1.11.17.0) -set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz) -set(OSL_HASH 63265472ce14548839ace2e21e401544) +set(OSL_VERSION 1.12.6.2) +set(OSL_URI https://github.com/AcademySoftwareFoundation/OpenShadingLanguage/archive/refs/tags/v${OSL_VERSION}.tar.gz) +set(OSL_HASH 6fef11548adfdd3e5b25c49d2dae96ee) set(OSL_HASH_TYPE MD5) set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz) diff --git a/build_files/cmake/Modules/FindOSL.cmake b/build_files/cmake/Modules/FindOSL.cmake index ab5de53d3c9..a8d8344ae66 100644 --- a/build_files/cmake/Modules/FindOSL.cmake +++ b/build_files/cmake/Modules/FindOSL.cmake @@ -20,6 +20,7 @@ IF(NOT OSL_ROOT_DIR AND NOT $ENV{OSL_ROOT_DIR} STREQUAL "") ENDIF() SET(_osl_FIND_COMPONENTS + oslnoise oslcomp oslexec oslquery @@ -39,7 +40,6 @@ FIND_PATH(OSL_INCLUDE_DIR include ) -SET(_osl_LIBRARIES) FOREACH(COMPONENT ${_osl_FIND_COMPONENTS}) STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) @@ -51,9 +51,20 @@ FOREACH(COMPONENT ${_osl_FIND_COMPONENTS}) PATH_SUFFIXES lib64 lib ) - LIST(APPEND _osl_LIBRARIES "${OSL_${UPPERCOMPONENT}_LIBRARY}") ENDFOREACH() +# Note linking order matters, and oslnoise existence depends on version. +SET(_osl_LIBRARIES ${OSL_OSLCOMP_LIBRARY}) +IF(APPLE) + list(APPEND _osl_LIBRARIES -force_load ${OSL_OSLEXEC_LIBRARY}) +ELSE() + list(APPEND _osl_LIBRARIES ${OSL_OSLEXEC_LIBRARY}) +ENDIF() +list(APPEND _osl_LIBRARIES ${OSL_OSLQUERY_LIBRARY}) +IF(OSL_OSLNOISE_LIBRARY) + list(APPEND _osl_LIBRARIES ${OSL_OSLNOISE_LIBRARY}) +ENDIF() + FIND_PROGRAM(OSL_COMPILER oslc HINTS ${_osl_SEARCH_DIRS} PATH_SUFFIXES bin) diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 04f5a312030..dbcaf9d02d3 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -331,20 +331,9 @@ if(WITH_LLVM) endif() if(WITH_CYCLES AND WITH_CYCLES_OSL) - set(CYCLES_OSL ${LIBDIR}/osl) - - find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) - find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) - # WARNING! depends on correct order of OSL libs linking - list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) - find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) - find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) - find_path(OSL_SHADER_DIR NAMES stdosl.h PATHS ${CYCLES_OSL}/share/OSL/shaders) - - if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR) - set(OSL_FOUND TRUE) - else() + find_package(OSL) + + if(NOT OSL_FOUND) message(WARNING "OSL not found, disabling WITH_CYCLES_OSL") set(WITH_CYCLES_OSL OFF) endif() diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index cfb8bf34b81..4478a2f8051 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -773,9 +773,11 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_NOISE NAMES oslnoise PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_EXEC_DEBUG NAMES oslexec_d PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP_DEBUG NAMES oslcomp_d PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY_DEBUG NAMES oslquery_d PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_NOISE_DEBUG NAMES oslnoise_d PATHS ${CYCLES_OSL}/lib) list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_COMP} optimized ${OSL_LIB_EXEC} @@ -785,6 +787,12 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) debug ${OSL_LIB_QUERY_DEBUG} ${PUGIXML_LIBRARIES} ) + if(OSL_LIB_NOISE) + list(APPEND OSL_LIBRARIES optimized ${OSL_LIB_NOISE}) + endif() + if(OSL_LIB_NOISE_DEBUG) + list(APPEND OSL_LIBRARIES debug ${OSL_LIB_NOISE_DEBUG}) + endif() find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) -- cgit v1.2.3 From debacbfe5c8fb38a01504463b70f590386a3f62c Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 13:37:18 +0200 Subject: Build: update OpenPGL hash for re-tagged version without symbols conflicts Ref D16269, T101403 --- build_files/build_environment/cmake/versions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 469988dab0c..6f358fd6f86 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -564,7 +564,7 @@ set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*") set(OPENPGL_VERSION v0.4.0-beta) set(OPENPGL_SHORT_VERSION 0.4.0) set(OPENPGL_URI https://github.com/OpenPathGuidingLibrary/openpgl/archive/refs/tags/${OPENPGL_VERSION}.tar.gz) -set(OPENPGL_HASH 58d5b65c533ce6cac3f7e1d51cf169a5411adf356abcd85f04049bbcaecc2e77) +set(OPENPGL_HASH 1f090f88ab2bad028e8b3619aa926f4f97cf7b2c175b904704d2fec8593dd3cd) set(OPENPGL_HASH_TYPE SHA256) set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz) -- cgit v1.2.3 From 21deba56aaeccf94d83024a9de4eef49ea05984f Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 13:25:54 +0200 Subject: Build: update various libraries for 3.4, fixing bugs and security issues THis is bumping dependencies to fix known CVEs, with the exception of OpenImageIO which also includes bugfixes for performance and correctness with some image types. zlib 1.2.12 -> 1.2.13 freetype 2.11.1 -> 2.12.1 openimageio 2.3.13.0 -> 2.3.20.0 python 3.10.2 -> 3.10.8 openjpeg 2.4.0 -> 2.5.0 ffmpeg 5.0 -> 5.1.2 sndfile 1.0.28 -> 1.1.0 xml2 2.9.10 -> 2.10.3 expat 2.4.4 -> 2.4.9 openssl 1.1.1g/i -> 1.1.1q sqlite 3.31.1 -> 3.37.2 Notable changes: * AOM: the hack we had in place to make it not detect pthreads on windows no longer worked with a more recent cmake version. Disabled pthreads with a diff on Windows. * Python: embedded copy of zlib 2.1.12 swapped out for our 2.1.13 copy with some folder manipulation on Windows. * Freetype: was harbouring a copy of zlib 2.1.12 as well, so that had to end. * FFmpeg: patch used to fix D11796 is no longer needed. Add new patch to deal with simple_idct.asm generating an object file with no sections in it, backport from upstream commit. * TinyXML: still being downloaded but no longer used by OpenColorIO, removed. * GMP applied upstream patch to fix CVE-2021-43618, as there is no release yet. * SQLite and Libsndfile patches no longer needed. Includes contributes by Ray Molenkamp, Campbell Barton and Brecht Van Lommel. Ref T101403 Differential Revision: https://developer.blender.org/D16269 --- build_files/build_environment/cmake/aom.cmake | 6 +- build_files/build_environment/cmake/download.cmake | 3 +- build_files/build_environment/cmake/ffmpeg.cmake | 6 - build_files/build_environment/cmake/freetype.cmake | 4 + build_files/build_environment/cmake/gmp.cmake | 1 + build_files/build_environment/cmake/llvm.cmake | 1 + build_files/build_environment/cmake/osl.cmake | 2 + build_files/build_environment/cmake/python.cmake | 17 ++- build_files/build_environment/cmake/sndfile.cmake | 7 -- build_files/build_environment/cmake/sqlite.cmake | 1 - build_files/build_environment/cmake/ssl.cmake | 1 + build_files/build_environment/cmake/tiff.cmake | 1 + build_files/build_environment/cmake/versions.cmake | 95 +++++++-------- build_files/build_environment/cmake/wayland.cmake | 8 +- build_files/build_environment/dependencies.dot | 120 ++++++++++-------- build_files/build_environment/patches/aom.diff | 18 +++ build_files/build_environment/patches/ffmpeg.diff | 40 ++---- build_files/build_environment/patches/gmp.diff | 15 +++ build_files/build_environment/patches/osl.diff | 135 +++++++++++++-------- .../build_environment/patches/python_windows.diff | 24 ---- build_files/build_environment/patches/sndfile.diff | 42 ------- build_files/build_environment/patches/sqlite.diff | 14 --- build_files/build_environment/patches/ssl.diff | 10 ++ build_files/cmake/platform/platform_win32.cmake | 8 +- 24 files changed, 290 insertions(+), 289 deletions(-) create mode 100644 build_files/build_environment/patches/aom.diff create mode 100644 build_files/build_environment/patches/gmp.diff delete mode 100644 build_files/build_environment/patches/python_windows.diff delete mode 100644 build_files/build_environment/patches/sndfile.diff delete mode 100644 build_files/build_environment/patches/sqlite.diff create mode 100644 build_files/build_environment/patches/ssl.diff diff --git a/build_files/build_environment/cmake/aom.cmake b/build_files/build_environment/cmake/aom.cmake index 9f64439771f..11c81c3f6e4 100644 --- a/build_files/build_environment/cmake/aom.cmake +++ b/build_files/build_environment/cmake/aom.cmake @@ -8,11 +8,6 @@ if(WIN32) # building with mingw, it'll have an unhappy time with that and # we need to clear them out. set(AOM_CMAKE_FLAGS ) - # CMake will correctly identify phreads being available, however - # we do not want to use them, as that gains a dependency on - # libpthreadswin.dll which we do not want. when pthreads is not - # available oam will use a pthreads emulation layer using win32 threads - set(AOM_EXTRA_ARGS_WIN32 -DCMAKE_HAVE_PTHREAD_H=OFF) else() set(AOM_GENERATOR "Unix Makefiles") set(AOM_CMAKE_FLAGS ${DEFAULT_CMAKE_FLAGS}) @@ -36,6 +31,7 @@ ExternalProject_Add(external_aom DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${AOM_HASH_TYPE}=${AOM_HASH} PREFIX ${BUILD_DIR}/aom + PATCH_COMMAND ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/aom/src/external_aom < ${PATCH_DIR}/aom.diff CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/aom/src/external_aom-build/ && ${CMAKE_COMMAND} -G "${AOM_GENERATOR}" -DCMAKE_INSTALL_PREFIX=${LIBDIR}/aom ${AOM_CMAKE_FLAGS} ${AOM_EXTRA_ARGS} ${BUILD_DIR}/aom/src/external_aom/ diff --git a/build_files/build_environment/cmake/download.cmake b/build_files/build_environment/cmake/download.cmake index 35bc028a1e3..8d75f0ff0ed 100644 --- a/build_files/build_environment/cmake/download.cmake +++ b/build_files/build_environment/cmake/download.cmake @@ -62,7 +62,7 @@ function(download_source dep) # since the actual build of the dep will notify the # platform maintainer if there is a problem with the # source package and refuse to build. - if(NOT PACKAGE_USE_UPSTREAM_SOURCES) + if(NOT PACKAGE_USE_UPSTREAM_SOURCES OR FORCE_CHECK_HASH) file(${TARGET_HASH_TYPE} ${TARGET_FILE} LOCAL_HASH) if(NOT ${TARGET_HASH} STREQUAL ${LOCAL_HASH}) message(FATAL_ERROR "${TARGET_FILE} ${TARGET_HASH_TYPE} mismatch\nExpected\t: ${TARGET_HASH}\nActual\t: ${LOCAL_HASH}") @@ -114,7 +114,6 @@ download_source(WEBP) download_source(SPNAV) download_source(JEMALLOC) download_source(XML2) -download_source(TINYXML) download_source(YAMLCPP) download_source(EXPAT) download_source(PUGIXML) diff --git a/build_files/build_environment/cmake/ffmpeg.cmake b/build_files/build_environment/cmake/ffmpeg.cmake index 7730607c514..e2b60e161f2 100644 --- a/build_files/build_environment/cmake/ffmpeg.cmake +++ b/build_files/build_environment/cmake/ffmpeg.cmake @@ -16,12 +16,6 @@ if(WIN32) --enable-libopenjpeg --disable-mediafoundation ) - if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4") - set(FFMPEG_EXTRA_FLAGS - ${FFMPEG_EXTRA_FLAGS} - --x86asmexe=yasm - ) - endif() else() set(FFMPEG_EXTRA_FLAGS ${FFMPEG_EXTRA_FLAGS} diff --git a/build_files/build_environment/cmake/freetype.cmake b/build_files/build_environment/cmake/freetype.cmake index b6f53ede2db..842e5c42e25 100644 --- a/build_files/build_environment/cmake/freetype.cmake +++ b/build_files/build_environment/cmake/freetype.cmake @@ -7,8 +7,11 @@ set(FREETYPE_EXTRA_ARGS -DFT_DISABLE_HARFBUZZ=ON -DFT_DISABLE_PNG=ON -DFT_REQUIRE_BROTLI=ON + -DFT_REQUIRE_ZLIB=ON -DPC_BROTLIDEC_INCLUDEDIR=${LIBDIR}/brotli/include -DPC_BROTLIDEC_LIBDIR=${LIBDIR}/brotli/lib + -DZLIB_LIBRARY=${LIBDIR}/zlib/lib/${ZLIB_LIBRARY} + -DZLIB_INCLUDE_DIR=${LIBDIR}/zlib/include ) ExternalProject_Add(external_freetype @@ -23,6 +26,7 @@ ExternalProject_Add(external_freetype add_dependencies( external_freetype external_brotli + external_zlib ) if(BUILD_MODE STREQUAL Release AND WIN32) diff --git a/build_files/build_environment/cmake/gmp.cmake b/build_files/build_environment/cmake/gmp.cmake index e624778869e..ddfdba6662d 100644 --- a/build_files/build_environment/cmake/gmp.cmake +++ b/build_files/build_environment/cmake/gmp.cmake @@ -27,6 +27,7 @@ ExternalProject_Add(external_gmp DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${GMP_HASH_TYPE}=${GMP_HASH} PREFIX ${BUILD_DIR}/gmp + PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/gmp/src/external_gmp < ${PATCH_DIR}/gmp.diff CONFIGURE_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/gmp ${GMP_OPTIONS} ${GMP_EXTRA_ARGS} BUILD_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make -j${MAKE_THREADS} INSTALL_COMMAND ${CONFIGURE_ENV_NO_PERL} && cd ${BUILD_DIR}/gmp/src/external_gmp/ && make install diff --git a/build_files/build_environment/cmake/llvm.cmake b/build_files/build_environment/cmake/llvm.cmake index e4ddc7db846..11f6bf7c218 100644 --- a/build_files/build_environment/cmake/llvm.cmake +++ b/build_files/build_environment/cmake/llvm.cmake @@ -9,6 +9,7 @@ endif() if(APPLE) set(LLVM_XML2_ARGS -DLIBXML2_LIBRARY=${LIBDIR}/xml2/lib/libxml2.a + -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2 ) set(LLVM_BUILD_CLANG_TOOLS_EXTRA ^^clang-tools-extra) set(BUILD_CLANG_TOOLS ON) diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake index 9719de94d47..8bac2c5c1ab 100644 --- a/build_files/build_environment/cmake/osl.cmake +++ b/build_files/build_environment/cmake/osl.cmake @@ -32,6 +32,8 @@ set(OSL_EXTRA_ARGS -DUSE_Qt5=OFF -DINSTALL_DOCS=OFF -Dpugixml_ROOT=${LIBDIR}/pugixml + -DTIFF_ROOT=${LIBDIR}/tiff + -DJPEG_ROOT=${LIBDIR}/jpeg -DUSE_PYTHON=OFF -DCMAKE_CXX_STANDARD=14 -DImath_ROOT=${LIBDIR}/imath diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake index 8fed10e9d72..72ae27ddfdb 100644 --- a/build_files/build_environment/cmake/python.cmake +++ b/build_files/build_environment/cmake/python.cmake @@ -15,9 +15,11 @@ if(WIN32) endmacro() set(PYTHON_EXTERNALS_FOLDER ${BUILD_DIR}/python/src/external_python/externals) + set(ZLIB_SOURCE_FOLDER ${BUILD_DIR}/zlib/src/external_zlib) set(DOWNLOADS_EXTERNALS_FOLDER ${DOWNLOAD_DIR}/externals) cmake_to_dos_path(${PYTHON_EXTERNALS_FOLDER} PYTHON_EXTERNALS_FOLDER_DOS) + cmake_to_dos_path(${ZLIB_SOURCE_FOLDER} ZLIB_SOURCE_FOLDER_DOS) cmake_to_dos_path(${DOWNLOADS_EXTERNALS_FOLDER} DOWNLOADS_EXTERNALS_FOLDER_DOS) ExternalProject_Add(external_python @@ -25,12 +27,21 @@ if(WIN32) DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${PYTHON_HASH_TYPE}=${PYTHON_HASH} PREFIX ${BUILD_DIR}/python - CONFIGURE_COMMAND "" + # Python will download its own deps and there's very little we can do about + # that beyond placing some code in their externals dir before it tries. + # the foldernames *HAVE* to match the ones inside pythons get_externals.cmd. + # python 3.10.8 still ships zlib 1.2.12, replace it with our 1.2.13 + # copy until they update. + CONFIGURE_COMMAND mkdir ${PYTHON_EXTERNALS_FOLDER_DOS} && + mklink /J ${PYTHON_EXTERNALS_FOLDER_DOS}\\zlib-1.2.12 ${ZLIB_SOURCE_FOLDER_DOS} && + ${CMAKE_COMMAND} -E copy ${ZLIB_SOURCE_FOLDER}/../external_zlib-build/zconf.h ${PYTHON_EXTERNALS_FOLDER}/zlib-1.2.12/zconf.h BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p x64 -c ${BUILD_MODE} - PATCH_COMMAND ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_windows.diff INSTALL_COMMAND ${PYTHON_BINARY_INTERNAL} ${PYTHON_SRC}/PC/layout/main.py -b ${PYTHON_SRC}/PCbuild/amd64 -s ${PYTHON_SRC} -t ${PYTHON_SRC}/tmp/ --include-stable --include-pip --include-dev --include-launchers --include-venv --include-symbols ${PYTHON_EXTRA_INSTLAL_FLAGS} --copy ${LIBDIR}/python ) - + add_dependencies( + external_python + external_zlib + ) else() if(APPLE) # Disable functions that can be in 10.13 sdk but aren't available on 10.9 target. diff --git a/build_files/build_environment/cmake/sndfile.cmake b/build_files/build_environment/cmake/sndfile.cmake index 192c25f5ed1..a2ac2a33779 100644 --- a/build_files/build_environment/cmake/sndfile.cmake +++ b/build_files/build_environment/cmake/sndfile.cmake @@ -11,18 +11,11 @@ else() set(SNDFILE_OPTIONS --enable-static --disable-shared ) endif() -if(UNIX) - set(SNDFILE_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/sndfile/src/external_sndfile < ${PATCH_DIR}/sndfile.diff) -else() - set(SNDFILE_PATCH_CMD) -endif() - ExternalProject_Add(external_sndfile URL file://${PACKAGE_DIR}/${SNDFILE_FILE} DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${SNDFILE_HASH_TYPE}=${SNDFILE_HASH} PREFIX ${BUILD_DIR}/sndfile - PATCH_COMMAND ${SNDFILE_PATCH_CMD} CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && ${SNDFILE_ENV} ${CONFIGURE_COMMAND} ${SNDFILE_OPTIONS} --prefix=${mingw_LIBDIR}/sndfile BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make -j${MAKE_THREADS} INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sndfile/src/external_sndfile/ && make install diff --git a/build_files/build_environment/cmake/sqlite.cmake b/build_files/build_environment/cmake/sqlite.cmake index c82d832574a..c151a495ff1 100644 --- a/build_files/build_environment/cmake/sqlite.cmake +++ b/build_files/build_environment/cmake/sqlite.cmake @@ -48,7 +48,6 @@ ExternalProject_Add(external_sqlite DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH ${SQLITE_HASH_TYPE}=${SQLITE_HASH} PREFIX ${BUILD_DIR}/sqlite - PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/sqlite/src/external_sqlite < ${PATCH_DIR}/sqlite.diff CONFIGURE_COMMAND ${SQLITE_CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/sqlite ${SQLITE_CONFIGURATION_ARGS} BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make -j${MAKE_THREADS} INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/sqlite/src/external_sqlite/ && make install diff --git a/build_files/build_environment/cmake/ssl.cmake b/build_files/build_environment/cmake/ssl.cmake index 21c4d2418c3..628187dc0ac 100644 --- a/build_files/build_environment/cmake/ssl.cmake +++ b/build_files/build_environment/cmake/ssl.cmake @@ -5,6 +5,7 @@ set(SSL_PATCH_CMD echo .) if(APPLE) set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}") + set(SSL_PATCH_CMD ${PATCH_CMD} --verbose -p 0 -d ${BUILD_DIR}/ssl/src/external_ssl < ${PATCH_DIR}/ssl.diff) else() if(BLENDER_PLATFORM_ARM) set(SSL_OS_COMPILER "blender-linux-aarch64") diff --git a/build_files/build_environment/cmake/tiff.cmake b/build_files/build_environment/cmake/tiff.cmake index 1f8e9442ae5..1ac2e4c6058 100644 --- a/build_files/build_environment/cmake/tiff.cmake +++ b/build_files/build_environment/cmake/tiff.cmake @@ -25,6 +25,7 @@ ExternalProject_Add(external_tiff add_dependencies( external_tiff external_zlib + external_jpeg ) if(WIN32) if(BUILD_MODE STREQUAL Release) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 6f358fd6f86..5fa138ff01b 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -8,9 +8,9 @@ # Not all of our dependencies are currently in the nvd database so not all # dependencies have one assigned. -set(ZLIB_VERSION 1.2.12) +set(ZLIB_VERSION 1.2.13) set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz) -set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78) +set(ZLIB_HASH 9b8aa094c4e5765dabf4da391f00d15c) set(ZLIB_HASH_TYPE MD5) set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz) set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*") @@ -88,9 +88,9 @@ else() set(OPENEXR_VERSION_POSTFIX) endif() -set(FREETYPE_VERSION 2.11.1) +set(FREETYPE_VERSION 2.12.1) set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz) -set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85) +set(FREETYPE_HASH 8bc5c9c9df7ac12c504f8918552a7cf2) set(FREETYPE_HASH_TYPE MD5) set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz) SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*") @@ -159,9 +159,9 @@ set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${ set(OPENMP_HASH_TYPE MD5) set(OPENMP_FILE openmp-${OPENMP_VERSION}.src.tar.xz) -set(OPENIMAGEIO_VERSION v2.3.13.0) +set(OPENIMAGEIO_VERSION v2.3.20.0) set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/refs/tags/${OPENIMAGEIO_VERSION}.tar.gz) -set(OPENIMAGEIO_HASH de45fb38501c4581062b522b53b6141c) +set(OPENIMAGEIO_HASH defb1fe7c8e64bac60eb3cacaf5c3736) set(OPENIMAGEIO_HASH_TYPE MD5) set(OPENIMAGEIO_FILE OpenImageIO-${OPENIMAGEIO_VERSION}.tar.gz) @@ -195,11 +195,11 @@ set(OSL_HASH 6fef11548adfdd3e5b25c49d2dae96ee) set(OSL_HASH_TYPE MD5) set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz) -set(PYTHON_VERSION 3.10.2) +set(PYTHON_VERSION 3.10.8) set(PYTHON_SHORT_VERSION 3.10) set(PYTHON_SHORT_VERSION_NO_DOTS 310) set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz) -set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9) +set(PYTHON_HASH e92356b012ed4d0e09675131d39b1bde) set(PYTHON_HASH_TYPE MD5) set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz) set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*") @@ -298,17 +298,17 @@ set(XVIDCORE_HASH abbdcbd39555691dd1c9b4d08f0a031376a3b211652c0d8b3b8aa9be1303ce set(XVIDCORE_HASH_TYPE SHA256) set(XVIDCORE_FILE xvidcore-${XVIDCORE_VERSION}.tar.gz) -set(OPENJPEG_VERSION 2.4.0) -set(OPENJPEG_SHORT_VERSION 2.4) +set(OPENJPEG_VERSION 2.5.0) +set(OPENJPEG_SHORT_VERSION 2.5) set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz) -set(OPENJPEG_HASH 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d) +set(OPENJPEG_HASH 0333806d6adecc6f7a91243b2b839ff4d2053823634d4f6ed7a59bc87409122a) set(OPENJPEG_HASH_TYPE SHA256) set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz) set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*") -set(FFMPEG_VERSION 5.0) +set(FFMPEG_VERSION 5.1.2) set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2) -set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9) +set(FFMPEG_HASH 39a0bcc8d98549f16c570624678246a6ac736c066cebdb409f9502e915b22f2b) set(FFMPEG_HASH_TYPE SHA256) set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2) set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*") @@ -325,9 +325,9 @@ set(ICONV_HASH 7d2a800b952942bb2880efb00cfd524c) set(ICONV_HASH_TYPE MD5) set(ICONV_FILE libiconv-${ICONV_VERSION}.tar.gz) -set(SNDFILE_VERSION 1.0.28) -set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_VERSION}.tar.gz) -set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c) +set(SNDFILE_VERSION 1.1.0) +set(SNDFILE_URI https://github.com/libsndfile/libsndfile/releases/download/1.1.0/libsndfile-${SNDFILE_VERSION}.tar.xz) +set(SNDFILE_HASH e63dead2b4f0aaf323687619d007ee6a) set(SNDFILE_HASH_TYPE MD5) set(SNDFILE_FILE libsndfile-${SNDFILE_VERSION}.tar.gz) set(SNDFILE_CPE "cpe:2.3:a:libsndfile_project:libsndfile:${SNDFILE_VERSION}:*:*:*:*:*:*:*") @@ -351,21 +351,13 @@ set(JEMALLOC_HASH 3d41fbf006e6ebffd489bdb304d009ae) set(JEMALLOC_HASH_TYPE MD5) set(JEMALLOC_FILE jemalloc-${JEMALLOC_VERSION}.tar.bz2) -set(XML2_VERSION 2.9.10) -set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz) -set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5) +set(XML2_VERSION 2.10.3) +set(XML2_URI https://download.gnome.org/sources/libxml2/2.10/libxml2-${XML2_VERSION}.tar.xz) +set(XML2_HASH f9edac7fac232b3657a003fd9a5bbe42) set(XML2_HASH_TYPE MD5) -set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz) +set(XML2_FILE libxml2-${XML2_VERSION}.tar.xz) set(XML2_CPE "cpe:2.3:a:xmlsoft:libxml2:${XML2_VERSION}:*:*:*:*:*:*:*") -set(TINYXML_VERSION 2_6_2) -set(TINYXML_VERSION_DOTS 2.6.2) -set(TINYXML_URI https://nchc.dl.sourceforge.net/project/tinyxml/tinyxml/${TINYXML_VERSION_DOTS}/tinyxml_${TINYXML_VERSION}.tar.gz) -set(TINYXML_HASH c1b864c96804a10526540c664ade67f0) -set(TINYXML_HASH_TYPE MD5) -set(TINYXML_FILE tinyxml_${TINYXML_VERSION}.tar.gz) -set(TINYXML_CPE "cpe:2.3:a:tinyxml_project:tinyxml:${TINYXML_VERSION_DOTS}:*:*:*:*:*:*:*") - set(YAMLCPP_VERSION 0.6.3) set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION}) set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2) @@ -379,10 +371,10 @@ set(PYSTRING_HASH f2c68786b359f5e4e62bed53bc4fb86d) set(PYSTRING_HASH_TYPE MD5) set(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz) -set(EXPAT_VERSION 2_4_4) -set(EXPAT_VERSION_DOTS 2.4.4) +set(EXPAT_VERSION 2_4_9) +set(EXPAT_VERSION_DOTS 2.4.9) set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz) -set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98) +set(EXPAT_HASH b59a2aa796be1ee177bbab3b7231dfa5) set(EXPAT_HASH_TYPE MD5) set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz) set(EXPAT_CPE "cpe:2.3:a:libexpat_project:libexpat:${EXPAT_VERSION_DOTS}:*:*:*:*:*:*:*") @@ -410,6 +402,10 @@ set(FLEX_FILE flex-${FLEX_VERSION}.tar.gz) # NOTE: bzip.org domain does no longer belong to BZip 2 project, so we download # sources from Debian packaging. +# +# NOTE 2: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there +# can be no exceptions to this. set(BZIP2_VERSION 1.0.8) set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERSION}.orig.tar.gz) set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269) @@ -417,6 +413,9 @@ set(BZIP2_HASH_TYPE SHA256) set(BZIP2_FILE bzip2_${BZIP2_VERSION}.orig.tar.gz) set(BZIP2_CPE "cpe:2.3:a:bzip:bzip2:${BZIP2_VERSION}:*:*:*:*:*:*:*") +# NOTE: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there +# can be no exceptions to this. set(FFI_VERSION 3.3) set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz) set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056) @@ -430,27 +429,25 @@ set(LZMA_HASH 5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df) set(LZMA_HASH_TYPE SHA256) set(LZMA_FILE xz-${LZMA_VERSION}.tar.bz2) -if(BLENDER_PLATFORM_ARM) - # Need at least 1.1.1i for aarch64 support (https://github.com/openssl/openssl/pull/13218) - set(SSL_VERSION 1.1.1i) - set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz) - set(SSL_HASH e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242) - set(SSL_HASH_TYPE SHA256) - set(SSL_FILE openssl-${SSL_VERSION}.tar.gz) -else() - set(SSL_VERSION 1.1.1g) - set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz) - set(SSL_HASH ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46) - set(SSL_HASH_TYPE SHA256) - set(SSL_FILE openssl-${SSL_VERSION}.tar.gz) -endif() +# NOTE: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat. For compliance reasons there +# can be no exceptions to this. +set(SSL_VERSION 1.1.1q) +set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz) +set(SSL_HASH d7939ce614029cdff0b6c20f0e2e5703158a489a72b2507b8bd51bf8c8fd10ca) +set(SSL_HASH_TYPE SHA256) +set(SSL_FILE openssl-${SSL_VERSION}.tar.gz) set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*") -set(SQLITE_VERSION 3.31.1) -set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip) -set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7) +# Note: This will *HAVE* to match the version python ships on windows which +# is hardcoded in pythons PCbuild/get_externals.bat for compliance reasons there +# can be no exceptions to this. +set(SQLITE_VERSION 3.37.2) +set(SQLLITE_LONG_VERSION 3370200) +set(SQLITE_URI https://www.sqlite.org/2022/sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz) +set(SQLITE_HASH e56faacadfb4154f8fbd0f2a3f827d13706b70a1) set(SQLITE_HASH_TYPE SHA1) -set(SQLITE_FILE sqlite-src-3240000.zip) +set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz) set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*") set(EMBREE_VERSION 3.13.4) diff --git a/build_files/build_environment/cmake/wayland.cmake b/build_files/build_environment/cmake/wayland.cmake index 799f2513da9..c73db1d10ff 100644 --- a/build_files/build_environment/cmake/wayland.cmake +++ b/build_files/build_environment/cmake/wayland.cmake @@ -7,10 +7,14 @@ ExternalProject_Add(external_wayland PREFIX ${BUILD_DIR}/wayland PATCH_COMMAND ${PATCH_CMD} -d ${BUILD_DIR}/wayland/src/external_wayland < ${PATCH_DIR}/wayland.diff # Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own LIBEXPAT & LIBXML2. - # Note that passing link args "ffi/lib" should not be needed, but + # + # NOTE: passing link args "ffi/lib" should not be needed, but # `pkgconfig` would incorrectly look in "ffi/lib/../lib64" otherwise. + # + # NOTE: `-lm` is needed for `libxml2` which is a static library that uses `libm.so`, + # without this, math symbols such as `floor` aren't found. CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig:${LIBDIR}/xml2/lib/pkgconfig:${LIBDIR}/ffi/lib/pkgconfig:$PKG_CONFIG_PATH - meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -Dc_link_args=-L${LIBDIR}/ffi/lib . ../external_wayland + meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland BUILD_COMMAND ninja INSTALL_COMMAND ninja install ) diff --git a/build_files/build_environment/dependencies.dot b/build_files/build_environment/dependencies.dot index 7e8637fbced..bb42856c3ac 100644 --- a/build_files/build_environment/dependencies.dot +++ b/build_files/build_environment/dependencies.dot @@ -1,96 +1,114 @@ strict graph { -graph[autosize = false, size = "25.7,8.3!", resolution = 300, overlap = false, splines = false, outputorder=edgesfirst ]; - node [style=filled fillcolor=white]; - external_alembic -- external_boost; - external_alembic -- external_zlib; +graph[autosize = false, size = "25.7,8.3!", resolution = 300]; external_alembic -- external_openexr; + external_alembic -- external_imath; external_blosc -- external_zlib; external_blosc -- external_pthreads; - external_boost -- Make_Python_Environment; - external_clang -- ll; + external_boost -- external_python; + external_boost -- external_numpy; + external_dpcpp -- external_python; + external_dpcpp -- external_python_site_packages; + external_dpcpp -- external_vcintrinsics; + external_dpcpp -- external_openclheaders; + external_dpcpp -- external_icdloader; + external_dpcpp -- external_mp11; + external_dpcpp -- external_level_zero; + external_dpcpp -- external_spirvheaders; + external_embree -- external_tbb; external_ffmpeg -- external_zlib; - external_ffmpeg -- external_faad; external_ffmpeg -- external_openjpeg; external_ffmpeg -- external_xvidcore; external_ffmpeg -- external_x264; + external_ffmpeg -- external_opus; external_ffmpeg -- external_vpx; external_ffmpeg -- external_theora; external_ffmpeg -- external_vorbis; external_ffmpeg -- external_ogg; external_ffmpeg -- external_lame; + external_ffmpeg -- external_aom; external_ffmpeg -- external_zlib_mingw; - external_numpy -- Make_Python_Environment; + external_ffmpeg -- external_nasm; + external_freetype -- external_brotli; + external_freetype -- external_zlib; + external_gmpxx -- external_gmp; + external_igc_llvm -- external_igc_opencl_clang; + external_igc_spirv_translator -- external_igc_opencl_clang; + external_igc -- external_igc_vcintrinsics; + external_igc -- external_igc_llvm; + external_igc -- external_igc_opencl_clang; + external_igc -- external_igc_vcintrinsics; + external_igc -- external_igc_spirv_headers; + external_igc -- external_igc_spirv_tools; + external_igc -- external_igc_spirv_translator; + external_igc -- external_flex; + external_ispc -- ll; + external_ispc -- external_python; + external_ispc -- external_flexbison; + external_ispc -- external_flex; + ll -- external_xml2; + ll -- external_python; + external_mesa -- ll; + external_numpy -- external_python; + external_numpy -- external_python_site_packages; + external_ocloc -- external_igc; + external_ocloc -- external_gmmlib; external_opencollada -- external_xml2; - external_opencolorio -- external_boost; - external_opencolorio -- external_tinyxml; external_opencolorio -- external_yamlcpp; + external_opencolorio -- external_expat; + external_opencolorio -- external_imath; + external_opencolorio -- external_pystring; external_openexr -- external_zlib; + external_openimagedenoise -- external_tbb; + external_openimagedenoise -- external_ispc; + external_openimagedenoise -- external_python; external_openimageio -- external_png; external_openimageio -- external_zlib; external_openimageio -- external_openexr; - external_openimageio -- external_openexr; + external_openimageio -- external_imath; external_openimageio -- external_jpeg; external_openimageio -- external_boost; external_openimageio -- external_tiff; - external_openimageio -- external_opencolorio; + external_openimageio -- external_pugixml; + external_openimageio -- external_fmt; + external_openimageio -- external_robinmap; external_openimageio -- external_openjpeg; external_openimageio -- external_webp; - external_openimageio -- external_opencolorio_extra; - external_openmp -- external_clang; + external_openmp -- ll; + external_openpgl -- external_tbb; external_opensubdiv -- external_tbb; openvdb -- external_tbb; openvdb -- external_boost; - openvdb -- external_openexr; - openvdb -- external_openexr; openvdb -- external_zlib; openvdb -- external_blosc; external_osl -- external_boost; external_osl -- ll; - external_osl -- external_clang; - external_osl -- external_openexr; external_osl -- external_openexr; external_osl -- external_zlib; - external_osl -- external_flexbison; external_osl -- external_openimageio; external_osl -- external_pugixml; + external_osl -- external_flexbison; + external_osl -- external_flex; external_png -- external_zlib; - external_python_site_packages -- Make_Python_Environment; + external_python -- external_bzip2; + external_python -- external_ffi; + external_python -- external_lzma; + external_python -- external_ssl; + external_python -- external_sqlite; + external_python -- external_zlib; + external_python_site_packages -- external_python; external_sndfile -- external_ogg; external_sndfile -- external_vorbis; external_sndfile -- external_flac; external_theora -- external_vorbis; external_theora -- external_ogg; external_tiff -- external_zlib; + external_usd -- external_tbb; + external_usd -- external_boost; + external_usd -- external_opensubdiv; external_vorbis -- external_ogg; - blender-- external_ffmpeg; - blender-- external_alembic; - blender-- external_openjpeg; - blender-- external_opencolorio; - blender-- external_openexr; - blender-- external_opensubdiv; - blender-- openvdb; - blender-- external_osl; - blender-- external_boost; - blender-- external_jpeg; - blender-- external_png; - blender-- external_python; - blender-- external_sndfile; - blender-- external_iconv; - blender-- external_fftw3; - external_python-- external_python_site_packages; - external_python_site_packages-- requests; - external_python_site_packages-- idna; - external_python_site_packages-- chardet; - external_python_site_packages-- urllib3; - external_python_site_packages-- certifi; - external_python-- external_numpy; - external_usd-- external_boost; - external_usd-- external_tbb; - blender-- external_opencollada; - blender-- external_sdl; - blender-- external_freetype; - blender-- external_pthreads; - blender-- external_zlib; - blender-- external_openal; - blender-- external_usd; + external_wayland -- external_expat; + external_wayland -- external_xml2; + external_wayland -- external_ffi; + external_wayland_protocols -- external_wayland; + external_x264 -- external_nasm; } diff --git a/build_files/build_environment/patches/aom.diff b/build_files/build_environment/patches/aom.diff new file mode 100644 index 00000000000..1611cff5dca --- /dev/null +++ b/build_files/build_environment/patches/aom.diff @@ -0,0 +1,18 @@ +diff -Naur libaom-3.4.0/build/cmake/aom_configure.cmake external_aom/build/cmake/aom_configure.cmake +--- libaom-3.4.0/build/cmake/aom_configure.cmake 2022-06-17 11:46:18 -0600 ++++ external_aom/build/cmake/aom_configure.cmake 2022-10-16 15:35:54 -0600 +@@ -15,8 +15,12 @@ + + include(FindGit) + include(FindPerl) +-include(FindThreads) +- ++# Blender: This will drag in a dep on libwinpthreads which we prefer ++# not to have, aom will fallback on a native win32 thread wrapper ++# if pthreads are not found. ++if(NOT WIN32) ++ include(FindThreads) ++endif() + include("${AOM_ROOT}/build/cmake/aom_config_defaults.cmake") + include("${AOM_ROOT}/build/cmake/aom_experiment_deps.cmake") + include("${AOM_ROOT}/build/cmake/aom_optimization.cmake") diff --git a/build_files/build_environment/patches/ffmpeg.diff b/build_files/build_environment/patches/ffmpeg.diff index c255f7c37a3..ac104a20ffe 100644 --- a/build_files/build_environment/patches/ffmpeg.diff +++ b/build_files/build_environment/patches/ffmpeg.diff @@ -68,34 +68,18 @@ + return ret; } ---- a/libavcodec/rl.c -+++ b/libavcodec/rl.c -@@ -71,17 +71,19 @@ - av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) - { - int i, q; -- VLC_TYPE table[1500][2] = {{0}}; -+ VLC_TYPE (*table)[2] = av_calloc(sizeof(VLC_TYPE), 1500 * 2); - VLC vlc = { .table = table, .table_allocated = static_size }; -- av_assert0(static_size <= FF_ARRAY_ELEMS(table)); -+ av_assert0(static_size < 1500); - init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); +diff --git a/libavcodec/x86/simple_idct.asm b/libavcodec/x86/simple_idct.asm +index dcf0da6df121..982b2f0bbba1 100644 +--- a/libavcodec/x86/simple_idct.asm ++++ b/libavcodec/x86/simple_idct.asm +@@ -25,9 +25,9 @@ - for (q = 0; q < 32; q++) { - int qmul = q * 2; - int qadd = (q - 1) | 1; + %include "libavutil/x86/x86util.asm" -- if (!rl->rl_vlc[q]) -+ if (!rl->rl_vlc[q]){ -+ av_free(table); - return; -+ } +-%if ARCH_X86_32 + SECTION_RODATA - if (q == 0) { - qmul = 1; -@@ -113,4 +115,5 @@ - rl->rl_vlc[q][i].run = run; - } - } -+ av_free(table); - } ++%if ARCH_X86_32 + cextern pb_80 + + wm1010: dw 0, 0xffff, 0, 0xffff diff --git a/build_files/build_environment/patches/gmp.diff b/build_files/build_environment/patches/gmp.diff new file mode 100644 index 00000000000..bf22f93bc4f --- /dev/null +++ b/build_files/build_environment/patches/gmp.diff @@ -0,0 +1,15 @@ +--- a/mpz/inp_raw.c Tue Dec 22 23:49:51 2020 +0100 ++++ b/mpz/inp_raw.c Thu Oct 21 19:06:49 2021 +0200 +@@ -88,8 +88,11 @@ + + abs_csize = ABS (csize); + ++ if (UNLIKELY (abs_csize > ~(mp_bitcnt_t) 0 / 8)) ++ return 0; /* Bit size overflows */ ++ + /* round up to a multiple of limbs */ +- abs_xsize = BITS_TO_LIMBS (abs_csize*8); ++ abs_xsize = BITS_TO_LIMBS ((mp_bitcnt_t) abs_csize * 8); + + if (abs_xsize != 0) + { diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff index 28e1d6e101d..3f4a485b037 100644 --- a/build_files/build_environment/patches/osl.diff +++ b/build_files/build_environment/patches/osl.diff @@ -1,67 +1,53 @@ -diff -Naur OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h ---- OpenShadingLanguage-Release-1.9.9/src/include/OSL/llvm_util.h 2018-05-01 16:39:02 -0600 -+++ external_osl/src/include/OSL/llvm_util.h 2018-08-25 14:05:00 -0600 -@@ -33,6 +33,8 @@ - - #include - -+#define OSL_HAS_BLENDER_CLEANUP_FIX -+ - #ifdef LLVM_NAMESPACE - namespace llvm = LLVM_NAMESPACE; - #endif -@@ -487,6 +489,7 @@ - std::string func_name (llvm::Function *f); - - static size_t total_jit_memory_held (); -+ static void Cleanup (); - - private: - class MemoryManager; -diff -Naur OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp ---- OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp 2018-05-01 16:39:02 -0600 -+++ external_osl/src/liboslexec/llvm_util.cpp 2018-08-25 14:04:27 -0600 -@@ -140,7 +140,10 @@ - }; - - -- -+void LLVM_Util::Cleanup () -+{ -+ if(jitmm_hold) jitmm_hold->clear(); -+} - - size_t - LLVM_Util::total_jit_memory_held () -diff -Naur org/CMakeLists.txt external_osl/CMakeLists.txt ---- org/CMakeLists.txt 2020-12-01 12:37:15 -0700 -+++ external_osl/CMakeLists.txt 2021-01-20 13:26:50 -0700 -@@ -84,6 +84,11 @@ +diff -Naur OpenShadingLanguage-1.12.6.2/CMakeLists.txt external_osl/CMakeLists.txt +--- OpenShadingLanguage-1.12.6.2/CMakeLists.txt 2022-09-30 17:43:53 -0600 ++++ external_osl/CMakeLists.txt 2022-10-15 14:49:26 -0600 +@@ -101,6 +101,11 @@ CACHE STRING "Directory where OptiX PTX files will be installed") set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "Library naming postfix for Debug builds (e.g., '_debug')") - + +set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static") +if (USE_OIIO_STATIC) + add_definitions ("-DOIIO_STATIC_BUILD=1") + add_definitions ("-DOIIO_STATIC_DEFINE=1") +endif () - + set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem") if (OSL_NO_DEFAULT_TEXTURESYSTEM) -diff -Naur external_osl_orig/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake ---- external_osl_orig/src/cmake/externalpackages.cmake 2021-06-01 13:44:18 -0600 -+++ external_osl/src/cmake/externalpackages.cmake 2021-06-28 07:44:32 -0600 -@@ -80,6 +80,7 @@ - - +diff -Naur OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake external_osl/src/cmake/externalpackages.cmake +--- OpenShadingLanguage-1.12.6.2/src/cmake/externalpackages.cmake 2022-09-30 17:43:53 -0600 ++++ external_osl/src/cmake/externalpackages.cmake 2022-10-15 14:49:26 -0600 +@@ -77,6 +77,7 @@ + + checked_find_package (ZLIB REQUIRED) # Needed by several packages +checked_find_package (PNG REQUIRED) # Needed since OIIO needs it - + # IlmBase & OpenEXR checked_find_package (OpenEXR REQUIRED -diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp ---- external_osl_orig/src/liboslcomp/oslcomp.cpp 2021-06-01 13:44:18 -0600 -+++ external_osl/src/liboslcomp/oslcomp.cpp 2021-06-28 09:11:06 -0600 +diff -Naur OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h external_osl/src/include/OSL/llvm_util.h +--- OpenShadingLanguage-1.12.6.2/src/include/OSL/llvm_util.h 2022-09-30 17:43:53 -0600 ++++ external_osl/src/include/OSL/llvm_util.h 2022-10-15 15:37:24 -0600 +@@ -9,6 +9,8 @@ + #include + #include + ++#define OSL_HAS_BLENDER_CLEANUP_FIX ++ + #ifdef LLVM_NAMESPACE + namespace llvm = LLVM_NAMESPACE; + #endif +@@ -455,7 +457,7 @@ + llvm::BasicBlock* masked_return_block() const; + + bool is_masking_required() const { return m_is_masking_required; } +- ++ static void Cleanup (); + struct ScopedMasking { + ScopedMasking() {} + +diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp external_osl/src/liboslcomp/oslcomp.cpp +--- OpenShadingLanguage-1.12.6.2/src/liboslcomp/oslcomp.cpp 2022-09-30 17:43:53 -0600 ++++ external_osl/src/liboslcomp/oslcomp.cpp 2022-10-15 14:49:26 -0600 @@ -21,6 +21,13 @@ #if !defined(__STDC_CONSTANT_MACROS) # define __STDC_CONSTANT_MACROS 1 @@ -76,3 +62,50 @@ diff -Naur external_osl_orig/src/liboslcomp/oslcomp.cpp external_osl/src/liboslc #include #include #include +diff -Naur OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp external_osl/src/liboslexec/llvm_util.cpp +--- OpenShadingLanguage-1.12.6.2/src/liboslexec/llvm_util.cpp 2022-09-30 17:43:53 -0600 ++++ external_osl/src/liboslexec/llvm_util.cpp 2022-10-15 15:53:11 -0600 +@@ -116,8 +116,6 @@ + return { A.data(), size_t(A.size()) }; + } + +- +- + namespace pvt { + + typedef llvm::SectionMemoryManager LLVMMemoryManager; +@@ -182,6 +180,13 @@ + ++jit_mem_hold_users; + } + ++void ++LLVM_Util::Cleanup() ++{ ++ if (jitmm_hold) ++ jitmm_hold->clear(); ++} ++ + + LLVM_Util::ScopedJitMemoryUser::~ScopedJitMemoryUser() + { +diff --git a/src/include/OSL/mask.h b/src/include/OSL/mask.h +index 24197af..b9275f6 100644 +--- a/src/include/OSL/mask.h ++++ b/src/include/OSL/mask.h +@@ -4,7 +4,6 @@ + + #pragma once + +-#include + #include + + #include +@@ -23,6 +22,8 @@ using std::countr_zero; + + #elif OSL_INTEL_CLASSIC_COMPILER_VERSION + ++#include ++ + OSL_FORCEINLINE int popcount(uint32_t x) noexcept { return _mm_popcnt_u32(x);} + OSL_FORCEINLINE int popcount(uint64_t x) noexcept { return _mm_popcnt_u64(x); } + OSL_FORCEINLINE int countr_zero(uint32_t x) noexcept { return _bit_scan_forward(x); } diff --git a/build_files/build_environment/patches/python_windows.diff b/build_files/build_environment/patches/python_windows.diff deleted file mode 100644 index f9c89a90fde..00000000000 --- a/build_files/build_environment/patches/python_windows.diff +++ /dev/null @@ -1,24 +0,0 @@ -diff -Naur orig/PCbuild/get_externals.bat Python-3.10.2/PCbuild/get_externals.bat ---- orig/PCbuild/get_externals.bat 2022-01-13 11:52:14 -0700 -+++ Python-3.10.2/PCbuild/get_externals.bat 2022-08-17 11:24:42 -0600 -@@ -51,7 +51,7 @@ - echo.Fetching external libraries... - - set libraries= --set libraries=%libraries% bzip2-1.0.6 -+set libraries=%libraries% bzip2-1.0.8 - if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0 - if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m - set libraries=%libraries% sqlite-3.35.5.0 - diff -Naur orig/PCbuild/python.props external_python/PCbuild/python.props ---- orig/PCbuild/python.props 2022-01-13 11:52:14 -0700 -+++ external_python/PCbuild/python.props 2022-08-17 11:38:38 -0600 -@@ -58,7 +58,7 @@ - $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) - $(ExternalsDir)\ - $(ExternalsDir)sqlite-3.35.5.0\ -- $(ExternalsDir)bzip2-1.0.6\ -+ $(ExternalsDir)bzip2-1.0.8\ - $(ExternalsDir)xz-5.2.2\ - $(ExternalsDir)libffi-3.3.0\ - $(ExternalsDir)libffi-3.3.0\$(ArchName)\ diff --git a/build_files/build_environment/patches/sndfile.diff b/build_files/build_environment/patches/sndfile.diff deleted file mode 100644 index ab43baa78df..00000000000 --- a/build_files/build_environment/patches/sndfile.diff +++ /dev/null @@ -1,42 +0,0 @@ ---- src/Makefile.in 2017-09-26 01:28:47.000000000 +0300 -+++ src/Makefile.in 2017-09-26 01:19:06.000000000 +0300 -@@ -513,7 +513,7 @@ - libcommon_la_SOURCES = common.c file_io.c command.c pcm.c ulaw.c alaw.c \ - float32.c double64.c ima_adpcm.c ms_adpcm.c gsm610.c dwvw.c vox_adpcm.c \ - interleave.c strings.c dither.c cart.c broadcast.c audio_detect.c \ -- ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \ -+ ima_oki_adpcm.c ima_oki_adpcm.h alac.c chunk.c ogg.c chanmap.c \ - windows.c id3.c $(WIN_VERSION_FILE) - - -@@ -719,10 +719,10 @@ - $(AM_V_CCLD)$(LINK) $(GSM610_libgsm_la_OBJECTS) $(GSM610_libgsm_la_LIBADD) $(LIBS) - - libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) $(EXTRA_libcommon_la_DEPENDENCIES) -- $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) -+ $(AM_V_CCLD)$(LINK) $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS) - - libsndfile.la: $(libsndfile_la_OBJECTS) $(libsndfile_la_DEPENDENCIES) $(EXTRA_libsndfile_la_DEPENDENCIES) -- $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS) -+ $(AM_V_CCLD)$(libsndfile_la_LINK) -rpath $(libdir) $(libsndfile_la_OBJECTS) $(libsndfile_la_LIBADD) $(LIBS) $(EXTERNAL_XIPH_LIBS) - - clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ -@@ -924,7 +924,7 @@ - @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-dwd.lo `test -f 'dwd.c' || echo '$(srcdir)/'`dwd.c - - libsndfile_la-flac.lo: flac.c --@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-flac.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-flac.Tpo -c -o libsndfile_la-flac.lo `test -f 'flac.c' || echo '$(srcdir)/'`flac.c - @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-flac.Tpo $(DEPDIR)/libsndfile_la-flac.Plo - @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='flac.c' object='libsndfile_la-flac.lo' libtool=yes @AMDEPBACKSLASH@ - @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@@ -1092,7 +1092,7 @@ - @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -c -o libsndfile_la-rf64.lo `test -f 'rf64.c' || echo '$(srcdir)/'`rf64.c - - libsndfile_la-ogg_vorbis.lo: ogg_vorbis.c --@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsndfile_la_CPPFLAGS) $(CPPFLAGS) $(libsndfile_la_CFLAGS) $(CFLAGS) $(EXTERNAL_XIPH_CFLAGS) -MT libsndfile_la-ogg_vorbis.lo -MD -MP -MF $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo -c -o libsndfile_la-ogg_vorbis.lo `test -f 'ogg_vorbis.c' || echo '$(srcdir)/'`ogg_vorbis.c - @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsndfile_la-ogg_vorbis.Tpo $(DEPDIR)/libsndfile_la-ogg_vorbis.Plo - @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ogg_vorbis.c' object='libsndfile_la-ogg_vorbis.lo' libtool=yes @AMDEPBACKSLASH@ - @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ diff --git a/build_files/build_environment/patches/sqlite.diff b/build_files/build_environment/patches/sqlite.diff deleted file mode 100644 index 80f1384f9cf..00000000000 --- a/build_files/build_environment/patches/sqlite.diff +++ /dev/null @@ -1,14 +0,0 @@ -Only in external_sqlite_orig: config.log -diff -ru external_sqlite_orig/config.sub external_sqlite/config.sub ---- external_sqlite_orig/config.sub 2020-07-10 14:06:42.000000000 +0200 -+++ external_sqlite/config.sub 2020-07-10 14:10:24.000000000 +0200 -@@ -314,6 +314,7 @@ - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ -+ | aarch64-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ -Only in external_sqlite: mksourceid -Only in external_sqlite: sqlite3session.h diff --git a/build_files/build_environment/patches/ssl.diff b/build_files/build_environment/patches/ssl.diff new file mode 100644 index 00000000000..7bb4413952c --- /dev/null +++ b/build_files/build_environment/patches/ssl.diff @@ -0,0 +1,10 @@ +--- ./test/v3ext.c 2022-07-05 11:08:33.000000000 +0200 ++++ ./test/v3ext.c 2022-10-18 13:58:05.000000000 +0200 +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include + #include + #include diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 4478a2f8051..5fb921fc97d 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -679,11 +679,11 @@ endif() if(WITH_IMAGE_OPENJPEG) set(OPENJPEG ${LIBDIR}/openjpeg) - set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4) + set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.5) if(NOT EXISTS "${OPENJPEG_INCLUDE_DIRS}") - # when not found, could be an older lib folder with openjpeg 2.3 - # to ease the transition period, fall back if 2.4 is not found. - set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.3) + # when not found, could be an older lib folder with openjpeg 2.4 + # to ease the transition period, fall back if 2.5 is not found. + set(OPENJPEG_INCLUDE_DIRS ${OPENJPEG}/include/openjpeg-2.4) endif() set(OPENJPEG_LIBRARIES ${OPENJPEG}/lib/openjp2.lib) endif() -- cgit v1.2.3 From 0d7065504effe3fe7f1483e79e39162249fa5099 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 20 Oct 2022 13:26:47 +0200 Subject: Build: mark remaining CVEs reported by cve_check as mitigated or ignored After the last library update cve_check still reported some false positives. One GMP issues was mitigated with a patch in the library update. The others are ignored, with a description explaining why they do not affect Blender. Ref D16269, T101403 --- .../build_environment/cmake/cve_check.cmake | 4 +++- .../build_environment/cmake/cve_check.csv.in | 23 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/build_files/build_environment/cmake/cve_check.cmake b/build_files/build_environment/cmake/cve_check.cmake index dfb190bcffa..ac42444aef1 100644 --- a/build_files/build_environment/cmake/cve_check.cmake +++ b/build_files/build_environment/cmake/cve_check.cmake @@ -27,10 +27,12 @@ get_cmake_property(_variableNames VARIABLES) foreach (_variableName ${_variableNames}) if(_variableName MATCHES "CPE$") string(REPLACE ":" ";" CPE_LIST ${${_variableName}}) + string(REPLACE "_CPE" "_ID" CPE_DEPNAME ${_variableName}) list(GET CPE_LIST 3 CPE_VENDOR) list(GET CPE_LIST 4 CPE_NAME) list(GET CPE_LIST 5 CPE_VERSION) - set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}\n") + set(${CPE_DEPNAME} "${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}") + set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION},,,\n") endif() endforeach() configure_file(${CMAKE_SOURCE_DIR}/cmake/cve_check.csv.in ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv @ONLY) diff --git a/build_files/build_environment/cmake/cve_check.csv.in b/build_files/build_environment/cmake/cve_check.csv.in index 6e7e8db5609..734a24f8c77 100644 --- a/build_files/build_environment/cmake/cve_check.csv.in +++ b/build_files/build_environment/cmake/cve_check.csv.in @@ -1,2 +1,23 @@ -vendor,product,version +vendor,product,version,cve_number,remarks,comment +@OPENJPEG_ID@,CVE-2016-9675,Ignored,issue in convert command line tool not used by blender +@PYTHON_ID@,CVE-2009-2940,Ignored,issue in pygresql not used by blender +@PYTHON_ID@,CVE-2020-29396,Ignored,issue in odoo not used by blender +@PYTHON_ID@,CVE-2021-32052,Ignored,issue in django not used by blender +@PYTHON_ID@,CVE-2009-3720,Ignored,already fixed in libexpat version used +@SSL_ID@,CVE-2009-1390,Ignored,issue in mutt not used by blender +@SSL_ID@,CVE-2009-3765,Ignored,issue in mutt not used by blender +@SSL_ID@,CVE-2009-3766,Ignored,issue in mutt not used by blender +@SSL_ID@,CVE-2009-3767,Ignored,issue in ldap not used by blender +@SSL_ID@,CVE-2019-0190,Ignored,issue in apache not used by blender +@TIFF_ID@,CVE-2022-2056,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2057,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2058,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2519,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2520,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2521,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-2953,Ignored,issue in tiff command line tool not used by blender +@TIFF_ID@,CVE-2022-34526,Ignored,issue in tiff command line tool not used by blender +@XML2_ID@,CVE-2016-3709,Ignored,not affecting blender and not considered a security issue upstream +@GMP_ID@,CVE-2021-43618,Mitigated,patched using upstream commit 561a9c25298e +@SQLITE_ID@,CVE-2022-35737,Ignored,only affects SQLITE_ENABLE_STAT4 compile option not used by blender or python @SBOMCONTENTS@ -- cgit v1.2.3 From fd7a3e262224e2936eee1216a8aa57e6e381aba6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 19 Oct 2022 15:33:42 +0200 Subject: Cleanup: compiler warnings --- intern/ghost/intern/GHOST_SystemWayland.cpp | 90 ++++++++++++++--------------- intern/ghost/intern/GHOST_SystemWayland.h | 6 +- 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 264476f00bc..fb69973eac6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -193,42 +193,42 @@ struct GWL_ModifierInfo { }; static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = { - [MOD_INDEX_SHIFT] = - { - .display_name = "Shift", - .xkb_id = XKB_MOD_NAME_SHIFT, - .key_l = GHOST_kKeyLeftShift, - .key_r = GHOST_kKeyRightShift, - .mod_l = GHOST_kModifierKeyLeftShift, - .mod_r = GHOST_kModifierKeyRightShift, - }, - [MOD_INDEX_ALT] = - { - .display_name = "Alt", - .xkb_id = XKB_MOD_NAME_ALT, - .key_l = GHOST_kKeyLeftAlt, - .key_r = GHOST_kKeyRightAlt, - .mod_l = GHOST_kModifierKeyLeftAlt, - .mod_r = GHOST_kModifierKeyRightAlt, - }, - [MOD_INDEX_CTRL] = - { - .display_name = "Control", - .xkb_id = XKB_MOD_NAME_CTRL, - .key_l = GHOST_kKeyLeftControl, - .key_r = GHOST_kKeyRightControl, - .mod_l = GHOST_kModifierKeyLeftControl, - .mod_r = GHOST_kModifierKeyRightControl, - }, - [MOD_INDEX_OS] = - { - .display_name = "OS", - .xkb_id = XKB_MOD_NAME_LOGO, - .key_l = GHOST_kKeyLeftOS, - .key_r = GHOST_kKeyRightOS, - .mod_l = GHOST_kModifierKeyLeftOS, - .mod_r = GHOST_kModifierKeyRightOS, - }, + /* MOD_INDEX_SHIFT */ + { + /* display_name */ "Shift", + /* xkb_id */ XKB_MOD_NAME_SHIFT, + /* key_l */ GHOST_kKeyLeftShift, + /* key_r */ GHOST_kKeyRightShift, + /* mod_l */ GHOST_kModifierKeyLeftShift, + /* mod_r */ GHOST_kModifierKeyRightShift, + }, + /* MOD_INDEX_ALT */ + { + /* display_name */ "Alt", + /* xkb_id */ XKB_MOD_NAME_ALT, + /* key_l */ GHOST_kKeyLeftAlt, + /* key_r */ GHOST_kKeyRightAlt, + /* mod_l */ GHOST_kModifierKeyLeftAlt, + /* mod_r */ GHOST_kModifierKeyRightAlt, + }, + /* MOD_INDEX_CTRL */ + { + /* display_name */ "Control", + /* xkb_id */ XKB_MOD_NAME_CTRL, + /* key_l */ GHOST_kKeyLeftControl, + /* key_r */ GHOST_kKeyRightControl, + /* mod_l */ GHOST_kModifierKeyLeftControl, + /* mod_r */ GHOST_kModifierKeyRightControl, + }, + /* MOD_INDEX_OS */ + { + /* display_name */ "OS", + /* xkb_id */ XKB_MOD_NAME_LOGO, + /* key_l */ GHOST_kKeyLeftOS, + /* key_r */ GHOST_kKeyRightOS, + /* mod_l */ GHOST_kModifierKeyLeftOS, + /* mod_r */ GHOST_kModifierKeyRightOS, + }, }; /** \} */ @@ -2989,11 +2989,10 @@ static void keyboard_handle_key(void *data, /* Start timer for repeating key, if applicable. */ if ((seat->key_repeat.rate > 0) && (etype == GHOST_kEventKeyDown) && xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb_state), key_code)) { - key_repeat_payload = new GWL_KeyRepeatPlayload({ - .seat = seat, - .key_code = key_code, - .key_data = {.gkey = gkey}, - }); + key_repeat_payload = new GWL_KeyRepeatPlayload(); + key_repeat_payload->seat = seat; + key_repeat_payload->key_code = key_code; + key_repeat_payload->key_data.gkey = gkey; } } @@ -4683,11 +4682,10 @@ static GWL_SeatStateGrab seat_grab_state_from_mode(const GHOST_TGrabCursorMode m const bool use_software_confine) { /* Initialize all members. */ - const struct GWL_SeatStateGrab grab_state = { - /* Warping happens to require software cursor which also hides. */ - .use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine, - .use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false), - }; + GWL_SeatStateGrab grab_state; + /* Warping happens to require software cursor which also hides. */ + grab_state.use_lock = ELEM(mode, GHOST_kGrabWrap, GHOST_kGrabHide) || use_software_confine; + grab_state.use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false); return grab_state; } diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 4e77c5b9c0b..23ffabf739e 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -88,7 +88,7 @@ class GHOST_SystemWayland : public GHOST_System { ~GHOST_SystemWayland() override; - GHOST_TSuccess init(); + GHOST_TSuccess init() override; bool processEvents(bool waitForEvent) override; @@ -149,8 +149,8 @@ class GHOST_SystemWayland : public GHOST_System { GHOST_TSuccess setCursorVisibility(bool visible); - bool supportsCursorWarp(); - bool supportsWindowPosition(); + bool supportsCursorWarp() override; + bool supportsWindowPosition() override; bool getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode); -- cgit v1.2.3 From 7f2cd2d969cb227fcde406f68492492d97d1322e Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Thu, 20 Oct 2022 15:02:41 +0200 Subject: Realtime Compositor: Implement Tone Map node This patch implements the tone map node for the realtime compositor based on the two papers: Reinhard, Erik, et al. "Photographic tone reproduction for digital images." Proceedings of the 29th annual conference on Computer graphics and interactive techniques. 2002. Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. The original implementation should be revisited later due to apparent incompatibilities with the reference papers, which makes the operation less useful. Differential Revision: https://developer.blender.org/D16306 Reviewed By: Clement Foucault --- .../algorithms/COM_algorithm_parallel_reduction.hh | 23 ++ .../intern/algorithm_parallel_reduction.cc | 66 ++++++ source/blender/gpu/CMakeLists.txt | 4 + .../compositor_tone_map_photoreceptor.glsl | 22 ++ .../compositor/compositor_tone_map_simple.glsl | 26 +++ .../infos/compositor_parallel_reduction_info.hh | 57 ++++- .../compositor_tone_map_photoreceptor_info.hh | 16 ++ .../infos/compositor_tone_map_simple_info.hh | 13 ++ source/blender/makesdna/DNA_node_types.h | 6 + .../composite/nodes/node_composite_tonemap.cc | 248 ++++++++++++++++++++- 10 files changed, 475 insertions(+), 6 deletions(-) create mode 100644 source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl create mode 100644 source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh diff --git a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh index 9d0851eff84..b094782c18e 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh +++ b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh @@ -27,6 +27,13 @@ float sum_blue(Context &context, GPUTexture *texture); * coefficients to compute the luminance. */ float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); +/* Computes the sum of the logarithm of the luminance of all pixels in the given texture, using the + * given luminance coefficients to compute the luminance. */ +float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); + +/* Computes the sum of the colors of all pixels in the given texture. */ +float4 sum_color(Context &context, GPUTexture *texture); + /* -------------------------------------------------------------------- * Sum Of Squared Difference Reductions. */ @@ -55,4 +62,20 @@ float sum_luminance_squared_difference(Context &context, float3 luminance_coefficients, float subtrahend); +/* -------------------------------------------------------------------- + * Maximum Reductions. + */ + +/* Computes the maximum luminance of all pixels in the given texture, using the given luminance + * coefficients to compute the luminance. */ +float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); + +/* -------------------------------------------------------------------- + * Minimum Reductions. + */ + +/* Computes the minimum luminance of all pixels in the given texture, using the given luminance + * coefficients to compute the luminance. */ +float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); + } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc index 3266ccd14eb..139c58bc190 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc +++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc @@ -134,6 +134,34 @@ float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coef return sum; } +float sum_log_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients) +{ + GPUShader *shader = context.shader_manager().get("compositor_sum_log_luminance"); + GPU_shader_bind(shader); + + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float sum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return sum; +} + +float4 sum_color(Context &context, GPUTexture *texture) +{ + GPUShader *shader = context.shader_manager().get("compositor_sum_color"); + GPU_shader_bind(shader); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_RGBA32F); + const float4 sum = float4(reduced_value); + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return sum; +} + /* -------------------------------------------------------------------- * Sum Of Squared Difference Reductions. */ @@ -202,4 +230,42 @@ float sum_luminance_squared_difference(Context &context, return sum; } +/* -------------------------------------------------------------------- + * Maximum Reductions. + */ + +float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients) +{ + GPUShader *shader = context.shader_manager().get("compositor_maximum_luminance"); + GPU_shader_bind(shader); + + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float maximum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return maximum; +} + +/* -------------------------------------------------------------------- + * Minimum Reductions. + */ + +float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients) +{ + GPUShader *shader = context.shader_manager().get("compositor_minimum_luminance"); + GPU_shader_bind(shader); + + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float minimum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return minimum; +} + } // namespace blender::realtime_compositor diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 5a1e0cde1d8..56031b2722b 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -357,6 +357,8 @@ set(GLSL_SRC shaders/compositor/compositor_split_viewer.glsl shaders/compositor/compositor_symmetric_blur.glsl shaders/compositor/compositor_symmetric_separable_blur.glsl + shaders/compositor/compositor_tone_map_photoreceptor.glsl + shaders/compositor/compositor_tone_map_simple.glsl shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl shaders/compositor/library/gpu_shader_compositor_blur_common.glsl @@ -639,6 +641,8 @@ set(SRC_SHADER_CREATE_INFOS shaders/compositor/infos/compositor_split_viewer_info.hh shaders/compositor/infos/compositor_symmetric_blur_info.hh shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh + shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh + shaders/compositor/infos/compositor_tone_map_simple_info.hh ) set(SRC_SHADER_CREATE_INFOS_MTL diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl new file mode 100644 index 00000000000..167006585ca --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_photoreceptor.glsl @@ -0,0 +1,22 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +/* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and (7) + * from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor + * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 input_color = texture_load(input_tx, texel); + float input_luminance = dot(input_color.rgb, luminance_coefficients); + + /* Trilinear interpolation between equations (6) and (7) from Reinhard's 2005 paper. */ + vec4 local_adaptation_level = mix(vec4(input_luminance), input_color, chromatic_adaptation); + vec4 adaptation_level = mix(global_adaptation_level, local_adaptation_level, light_adaptation); + + /* Equation (1) from Reinhard's 2005 paper, assuming Vmax is 1. */ + vec4 semi_saturation = pow(intensity * adaptation_level, vec4(contrast)); + vec4 tone_mapped_color = input_color / (input_color + semi_saturation); + + imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); +} diff --git a/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl new file mode 100644 index 00000000000..ce42d021dd1 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_tone_map_simple.glsl @@ -0,0 +1,26 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) + +/* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction + * for digital images." Proceedings of the 29th annual conference on Computer graphics and + * interactive techniques. 2002. */ +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 input_color = texture_load(input_tx, texel); + + /* Equation (2) from Reinhard's 2002 paper. */ + vec4 scaled_color = input_color * luminance_scale; + + /* Equation (3) from Reinhard's 2002 paper, but with the 1 replaced with the blend factor for + * more flexibility. See ToneMapOperation::compute_luminance_scale_blend_factor. */ + vec4 denominator = luminance_scale_blend_factor + scaled_color; + vec4 tone_mapped_color = safe_divide(scaled_color, denominator); + + if (inverse_gamma != 0.0) { + tone_mapped_color = pow(max(tone_mapped_color, vec4(0.0)), vec4(inverse_gamma)); + } + + imageStore(output_img, texel, vec4(tone_mapped_color.rgb, input_color.a)); +} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh index 2e661f280af..4a71bdc80e2 100644 --- a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh +++ b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh @@ -12,14 +12,17 @@ GPU_SHADER_CREATE_INFO(compositor_parallel_reduction_shared) * Sum Reductions. */ -GPU_SHADER_CREATE_INFO(compositor_sum_float_shared) +GPU_SHADER_CREATE_INFO(compositor_sum_shared) .additional_info("compositor_parallel_reduction_shared") - .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") - .define("TYPE", "float") .define("IDENTITY", "vec4(0.0)") - .define("LOAD(value)", "value.x") .define("REDUCE(lhs, rhs)", "lhs + rhs"); +GPU_SHADER_CREATE_INFO(compositor_sum_float_shared) + .additional_info("compositor_sum_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("TYPE", "float") + .define("LOAD(value)", "value.x"); + GPU_SHADER_CREATE_INFO(compositor_sum_red) .additional_info("compositor_sum_float_shared") .define("INITIALIZE(value)", "value.r") @@ -41,6 +44,20 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance) .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") .do_static_compilation(true); +GPU_SHADER_CREATE_INFO(compositor_sum_log_luminance) + .additional_info("compositor_sum_float_shared") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("INITIALIZE(value)", "log(max(dot(value.rgb, luminance_coefficients), 1e-5))") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_sum_color) + .additional_info("compositor_sum_shared") + .image(0, GPU_RGBA32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .define("TYPE", "vec4") + .define("INITIALIZE(value)", "value") + .define("LOAD(value)", "value") + .do_static_compilation(true); + /* -------------------------------------------------------------------- * Sum Of Squared Difference Reductions. */ @@ -74,3 +91,35 @@ GPU_SHADER_CREATE_INFO(compositor_sum_luminance_squared_difference) .push_constant(Type::VEC3, "luminance_coefficients") .define("INITIALIZE(value)", "pow(dot(value.rgb, luminance_coefficients) - subtrahend, 2.0)") .do_static_compilation(true); + +/* -------------------------------------------------------------------- + * Maximum Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_maximum_luminance) + .additional_info("compositor_parallel_reduction_shared") + .typedef_source("common_math_lib.glsl") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("TYPE", "float") + .define("IDENTITY", "vec4(FLT_MIN)") + .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "max(lhs, rhs)") + .do_static_compilation(true); + +/* -------------------------------------------------------------------- + * Minimum Reductions. + */ + +GPU_SHADER_CREATE_INFO(compositor_minimum_luminance) + .additional_info("compositor_parallel_reduction_shared") + .typedef_source("common_math_lib.glsl") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::VEC3, "luminance_coefficients") + .define("TYPE", "float") + .define("IDENTITY", "vec4(FLT_MAX)") + .define("INITIALIZE(value)", "dot(value.rgb, luminance_coefficients)") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "min(lhs, rhs)") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh new file mode 100644 index 00000000000..a460c9d58a6 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_photoreceptor_info.hh @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_tone_map_photoreceptor) + .local_group_size(16, 16) + .push_constant(Type::VEC4, "global_adaptation_level") + .push_constant(Type::FLOAT, "contrast") + .push_constant(Type::FLOAT, "intensity") + .push_constant(Type::FLOAT, "chromatic_adaptation") + .push_constant(Type::FLOAT, "light_adaptation") + .push_constant(Type::VEC3, "luminance_coefficients") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_tone_map_photoreceptor.glsl") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh new file mode 100644 index 00000000000..2b220af9460 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_tone_map_simple_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_tone_map_simple) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "luminance_scale") + .push_constant(Type::FLOAT, "luminance_scale_blend_factor") + .push_constant(Type::FLOAT, "inverse_gamma") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_tone_map_simple.glsl") + .do_static_compilation(true); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 315bcbd971c..c7962db8198 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -2083,6 +2083,12 @@ typedef enum CMPNodeLevelsChannel { CMP_NODE_LEVLES_LUMINANCE_BT709 = 5, } CMPNodeLevelsChannel; +/* Tone Map Node. Stored in NodeTonemap.type. */ +typedef enum CMPNodeToneMapType { + CMP_NODE_TONE_MAP_SIMPLE = 0, + CMP_NODE_TONE_MAP_PHOTORECEPTOR = 1, +} CMPNodeToneMapType; + /* Plane track deform node. */ enum { diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc index 2e06ad99df1..d26a01bb3c9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_tonemap.cc +++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.cc @@ -5,20 +5,35 @@ * \ingroup cmpnodes */ +#include + +#include "BLI_assert.h" +#include "BLI_math_base.hh" +#include "BLI_math_vec_types.hh" +#include "BLI_math_vector.hh" + #include "RNA_access.h" #include "UI_interface.h" #include "UI_resources.h" +#include "IMB_colormanagement.h" + +#include "COM_algorithm_parallel_reduction.hh" #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" namespace blender::nodes::node_composite_tonemap_cc { +NODE_STORAGE_FUNCS(NodeTonemap) + static void cmp_node_tonemap_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); + b.add_input(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); b.add_output(N_("Image")); } @@ -68,7 +83,236 @@ class ToneMapOperation : public NodeOperation { void execute() override { - get_input("Image").pass_through(get_result("Image")); + Result &input_image = get_input("Image"); + Result &output_image = get_result("Image"); + if (input_image.is_single_value()) { + input_image.pass_through(output_image); + return; + } + + switch (get_type()) { + case CMP_NODE_TONE_MAP_SIMPLE: + execute_simple(); + return; + case CMP_NODE_TONE_MAP_PHOTORECEPTOR: + execute_photoreceptor(); + return; + default: + BLI_assert_unreachable(); + return; + } + } + + /* Tone mapping based on equation (3) from Reinhard, Erik, et al. "Photographic tone reproduction + * for digital images." Proceedings of the 29th annual conference on Computer graphics and + * interactive techniques. 2002. */ + void execute_simple() + { + const float luminance_scale = compute_luminance_scale(); + const float luminance_scale_blend_factor = compute_luminance_scale_blend_factor(); + const float gamma = node_storage(bnode()).gamma; + const float inverse_gamma = gamma != 0.0f ? 1.0f / gamma : 0.0f; + + GPUShader *shader = shader_manager().get("compositor_tone_map_simple"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "luminance_scale", luminance_scale); + GPU_shader_uniform_1f(shader, "luminance_scale_blend_factor", luminance_scale_blend_factor); + GPU_shader_uniform_1f(shader, "inverse_gamma", inverse_gamma); + + const Result &input_image = get_input("Image"); + input_image.bind_as_texture(shader, "input_tx"); + + const Domain domain = compute_domain(); + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); + } + + /* Computes the scaling factor in equation (2) from Reinhard's 2002 paper. */ + float compute_luminance_scale() + { + const float geometric_mean = compute_geometric_mean_of_luminance(); + return geometric_mean != 0.0 ? node_storage(bnode()).key / geometric_mean : 0.0f; + } + + /* Computes equation (1) from Reinhard's 2002 paper. However, note that the equation in the paper + * is most likely wrong, and the intention is actually to compute the geometric mean through a + * logscale arithmetic mean, that is, the division should happen inside the exponential function, + * not outside of it. That's because the sum of the log luminance will be a very large negative + * number, whose exponential will almost always be zero, which is unexpected and useless. */ + float compute_geometric_mean_of_luminance() + { + return std::exp(compute_average_log_luminance()); + } + + /* Equation (3) from Reinhard's 2002 paper blends between high luminance scaling for high + * luminance values and low luminance scaling for low luminance values. This is done by adding 1 + * to the denominator, since for low luminance values, the denominator will be close to 1 and for + * high luminance values, the 1 in the denominator will be relatively insignificant. But the + * response of such function is not always ideal, so in this implementation, the 1 was exposed as + * a parameter to the user for more flexibility. */ + float compute_luminance_scale_blend_factor() + { + return node_storage(bnode()).offset; + } + + /* Tone mapping based on equation (1) and the trilinear interpolation between equations (6) and + * (7) from Reinhard, Erik, and Kate Devlin. "Dynamic range reduction inspired by photoreceptor + * physiology." IEEE transactions on visualization and computer graphics 11.1 (2005): 13-24. */ + void execute_photoreceptor() + { + const float4 global_adaptation_level = compute_global_adaptation_level(); + const float contrast = compute_contrast(); + const float intensity = compute_intensity(); + const float chromatic_adaptation = get_chromatic_adaptation(); + const float light_adaptation = get_light_adaptation(); + + GPUShader *shader = shader_manager().get("compositor_tone_map_photoreceptor"); + GPU_shader_bind(shader); + + GPU_shader_uniform_4fv(shader, "global_adaptation_level", global_adaptation_level); + GPU_shader_uniform_1f(shader, "contrast", contrast); + GPU_shader_uniform_1f(shader, "intensity", intensity); + GPU_shader_uniform_1f(shader, "chromatic_adaptation", chromatic_adaptation); + GPU_shader_uniform_1f(shader, "light_adaptation", light_adaptation); + + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients); + + const Result &input_image = get_input("Image"); + input_image.bind_as_texture(shader, "input_tx"); + + const Domain domain = compute_domain(); + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); + } + + /* Computes the global adaptation level from the trilinear interpolation equations constructed + * from equations (6) and (7) in Reinhard's 2005 paper. */ + float4 compute_global_adaptation_level() + { + const float4 average_color = compute_average_color(); + const float average_luminance = compute_average_luminance(); + const float chromatic_adaptation = get_chromatic_adaptation(); + return math::interpolate(float4(average_luminance), average_color, chromatic_adaptation); + } + + float4 compute_average_color() + { + /* The average color will reduce to zero if chromatic adaptation is zero, so just return zero + * in this case to avoid needlessly computing the average. See the trilinear interpolation + * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */ + if (get_chromatic_adaptation() == 0.0f) { + return float4(0.0f); + } + + const Result &input = get_input("Image"); + return sum_color(context(), input.texture()) / (input.domain().size.x * input.domain().size.y); + } + + float compute_average_luminance() + { + /* The average luminance will reduce to zero if chromatic adaptation is one, so just return + * zero in this case to avoid needlessly computing the average. See the trilinear interpolation + * equations constructed from equations (6) and (7) in Reinhard's 2005 paper. */ + if (get_chromatic_adaptation() == 1.0f) { + return 0.0f; + } + + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const Result &input = get_input("Image"); + float sum = sum_luminance(context(), input.texture(), luminance_coefficients); + return sum / (input.domain().size.x * input.domain().size.y); + } + + /* Computes equation (5) from Reinhard's 2005 paper. */ + float compute_intensity() + { + return std::exp(-node_storage(bnode()).f); + } + + /* If the contrast is not zero, return it, otherwise, a zero contrast denote automatic derivation + * of the contrast value based on equations (2) and (4) from Reinhard's 2005 paper. */ + float compute_contrast() + { + if (node_storage(bnode()).m != 0.0f) { + return node_storage(bnode()).m; + } + + const float log_maximum_luminance = compute_log_maximum_luminance(); + const float log_minimum_luminance = compute_log_minimum_luminance(); + + /* This is merely to guard against zero division later. */ + if (log_maximum_luminance == log_minimum_luminance) { + return 1.0f; + } + + const float average_log_luminance = compute_average_log_luminance(); + const float dynamic_range = log_maximum_luminance - log_minimum_luminance; + const float luminance_key = (log_maximum_luminance - average_log_luminance) / (dynamic_range); + + return 0.3f + 0.7f * std::pow(luminance_key, 1.4f); + } + + float compute_average_log_luminance() + { + const Result &input_image = get_input("Image"); + + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const float sum_of_log_luminance = sum_log_luminance( + context(), input_image.texture(), luminance_coefficients); + + return sum_of_log_luminance / (input_image.domain().size.x * input_image.domain().size.y); + } + + float compute_log_maximum_luminance() + { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const float maximum = maximum_luminance( + context(), get_input("Image").texture(), luminance_coefficients); + return std::log(math::max(maximum, 1e-5f)); + } + + float compute_log_minimum_luminance() + { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + const float minimum = minimum_luminance( + context(), get_input("Image").texture(), luminance_coefficients); + return std::log(math::max(minimum, 1e-5f)); + } + + float get_chromatic_adaptation() + { + return node_storage(bnode()).c; + } + + float get_light_adaptation() + { + return node_storage(bnode()).a; + } + + CMPNodeToneMapType get_type() + { + return static_cast(node_storage(bnode()).type); } }; -- cgit v1.2.3 From 7aaebf31df034397f3b28ab12daac9d3177c0950 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Thu, 20 Oct 2022 15:49:36 +0200 Subject: Cycles: replace (tm) with unicode equivalent in UI It was already done for (TM) which is present in some GPU names on Windows. Names on Linux ended up using (tm) instead: https://gitlab.freedesktop.org/mesa/mesa/-/commit/91fec2657a0dcf9bc2e6d080d84a114ecde44382 --- intern/cycles/blender/addon/properties.py | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index b7ce76d8f44..425d123e9e6 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1651,6 +1651,7 @@ class CyclesPreferences(bpy.types.AddonPreferences): box.prop( device, "use", text=device.name .replace('(TM)', unicodedata.lookup('TRADE MARK SIGN')) + .replace('(tm)', unicodedata.lookup('TRADE MARK SIGN')) .replace('(R)', unicodedata.lookup('REGISTERED SIGN')) .replace('(C)', unicodedata.lookup('COPYRIGHT SIGN')) ) -- cgit v1.2.3 From 66a166d2366b6f2070965b0872d48301aeba1354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Thu, 20 Oct 2022 16:07:08 +0200 Subject: GL: Make restart index consistent on older implementation This prevents weird quirks where the implementation might skip the ushort max index even in non-indexed draws. --- source/blender/gpu/opengl/gl_batch.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc index ff8867fe3e6..28105e326ee 100644 --- a/source/blender/gpu/opengl/gl_batch.cc +++ b/source/blender/gpu/opengl/gl_batch.cc @@ -272,8 +272,8 @@ void GLBatch::bind(int i_first) #if GPU_TRACK_INDEX_RANGE /* Can be removed if GL 4.3 is required. */ - if (!GLContext::fixed_restart_index_support && (elem != nullptr)) { - glPrimitiveRestartIndex(this->elem_()->restart_index()); + if (!GLContext::fixed_restart_index_support) { + glPrimitiveRestartIndex((elem != nullptr) ? this->elem_()->restart_index() : 0xFFFFFFFFu); } #endif -- cgit v1.2.3 From f017fdecefc41ffe796ccfe9a1cb05772a7ad315 Mon Sep 17 00:00:00 2001 From: Monique Dewanchand Date: Thu, 20 Oct 2022 16:14:03 +0200 Subject: ViewLayer: Reduce object duplication syncing During object duplication the syncing is temporarily disabled. With {D15885} this isn't useful as when disabled the view_layer is still accessed to locate bases. This can be improved by first locating the source bases, then duplicate and sync and locate the new bases. This patch removes the resync forbid and improve the times that resyncing actually must happen. Reviewed By: mont29 Maniphest Tasks: T73411 Differential Revision: https://developer.blender.org/D15886 --- source/blender/editors/object/object_add.cc | 197 ++++++++++++++++------------ 1 file changed, 112 insertions(+), 85 deletions(-) diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 3ce39b695e0..f6eee7c0c9e 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -3556,11 +3556,62 @@ void OBJECT_OT_convert(wmOperatorType *ot) /** \name Duplicate Object Operator * \{ */ +static void object_add_sync_base_collection( + Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base_src, Object *object_new) +{ + if ((base_src != nullptr) && (base_src->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { + BKE_collection_object_add_from(bmain, scene, base_src->object, object_new); + } + else { + LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); + BKE_collection_object_add(bmain, layer_collection->collection, object_new); + } +} + +static void object_add_sync_local_view(Base *base_src, Base *base_new) +{ + base_new->local_view_bits = base_src->local_view_bits; +} + +static void object_add_sync_rigid_body(Main *bmain, Object *object_src, Object *object_new) +{ + /* 1) duplis should end up in same collection as the original + * 2) Rigid Body sim participants MUST always be part of a collection... + */ + /* XXX: is 2) really a good measure here? */ + if (object_src->rigidbody_object || object_src->rigidbody_constraint) { + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_has_object(collection, object_src)) { + BKE_collection_object_add(bmain, collection, object_new); + } + } + } +} + /** * - Assumes `id.new` is correct. * - Leaves selection of base/object unaltered. * - Sets #ID.newid pointers. */ +static void object_add_duplicate_internal(Main *bmain, + Object *ob, + const eDupli_ID_Flags dupflag, + const eLibIDDuplicateFlags duplicate_options, + Object **r_ob_new) +{ + if (ob->mode & OB_MODE_POSE) { + return; + } + + Object *obn = static_cast( + ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options))); + if (r_ob_new) { + *r_ob_new = obn; + } + DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + return; +} + static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, @@ -3569,49 +3620,25 @@ static Base *object_add_duplicate_internal(Main *bmain, const eLibIDDuplicateFlags duplicate_options, Object **r_ob_new) { - Base *base, *basen = nullptr; - Object *obn; - - if (ob->mode & OB_MODE_POSE) { - /* nothing? */ + Object *object_new = nullptr; + object_add_duplicate_internal(bmain, ob, dupflag, duplicate_options, &object_new); + if (r_ob_new) { + *r_ob_new = object_new; + } + if (object_new == nullptr) { + return nullptr; } - else { - obn = static_cast( - ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options))); - if (r_ob_new) { - *r_ob_new = obn; - } - DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - - BKE_view_layer_synced_ensure(scene, view_layer); - base = BKE_view_layer_base_find(view_layer, ob); - if ((base != nullptr) && (base->flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT)) { - BKE_collection_object_add_from(bmain, scene, ob, obn); - } - else { - LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); - BKE_collection_object_add(bmain, layer_collection->collection, obn); - } - - BKE_view_layer_synced_ensure(scene, view_layer); - basen = BKE_view_layer_base_find(view_layer, obn); - if (base != nullptr && basen != nullptr) { - basen->local_view_bits = base->local_view_bits; - } - /* 1) duplis should end up in same collection as the original - * 2) Rigid Body sim participants MUST always be part of a collection... - */ - /* XXX: is 2) really a good measure here? */ - if (ob->rigidbody_object || ob->rigidbody_constraint) { - LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { - if (BKE_collection_has_object(collection, ob)) { - BKE_collection_object_add(bmain, collection, obn); - } - } - } + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_src = BKE_view_layer_base_find(view_layer, ob); + object_add_sync_base_collection(bmain, scene, view_layer, base_src, object_new); + BKE_view_layer_synced_ensure(scene, view_layer); + Base *base_new = BKE_view_layer_base_find(view_layer, object_new); + if (base_src && base_new) { + object_add_sync_local_view(base_src, base_new); } - return basen; + object_add_sync_rigid_body(bmain, ob, object_new); + return base_new; } Base *ED_object_add_duplicate( @@ -3665,70 +3692,70 @@ static int duplicate_exec(bContext *C, wmOperator *op) * we also want to remap pointers between those... */ BKE_main_id_newptr_and_tag_clear(bmain); - /* Do not do collection re-syncs for each object; will do it once afterwards. - * However this means we can't get to new duplicated Base's immediately, will - * have to process them after the sync. */ - BKE_layer_collection_resync_forbid(); - /* Duplicate the selected objects, remember data needed to process - * after the sync (the base of the original object, and the copy of the - * original object). */ - blender::Vector> source_bases_new_objects; - Object *ob_new_active = nullptr; + * after the sync. */ + struct DuplicateObjectLink { + Base *base_src = nullptr; + Object *object_new = nullptr; + + DuplicateObjectLink(Base *base_src) : base_src(base_src) + { + } + }; + blender::Vector object_base_links; CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Object *ob_new = nullptr; + object_base_links.append(DuplicateObjectLink(base)); + } + CTX_DATA_END; + + bool new_objects_created = false; + for (DuplicateObjectLink &link : object_base_links) { object_add_duplicate_internal(bmain, - scene, - view_layer, - base->object, + link.base_src->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID, - &ob_new); - if (ob_new == nullptr) { - continue; - } - source_bases_new_objects.append({base, ob_new}); - - /* note that this is safe to do with this context iterator, - * the list is made in advance */ - ED_object_base_select(base, BA_DESELECT); - - /* new object will become active */ - BKE_view_layer_synced_ensure(scene, view_layer); - if (BKE_view_layer_active_base_get(view_layer) == base) { - ob_new_active = ob_new; + &link.object_new); + if (link.object_new) { + new_objects_created = true; } } - CTX_DATA_END; - BKE_layer_collection_resync_allow(); - if (source_bases_new_objects.is_empty()) { + if (!new_objects_created) { return OPERATOR_CANCELLED; } - /* Sync the collection now, after everything is duplicated. */ - BKE_main_collection_sync(bmain); + /* Sync that could tag the view_layer out of sync. */ + for (DuplicateObjectLink &link : object_base_links) { + /* note that this is safe to do with this context iterator, + * the list is made in advance */ + ED_object_base_select(link.base_src, BA_DESELECT); + if (link.object_new) { + object_add_sync_base_collection(bmain, scene, view_layer, link.base_src, link.object_new); + object_add_sync_rigid_body(bmain, link.base_src->object, link.object_new); + } + } - /* After sync we can get to the new Base data, process it here. */ - for (const auto &item : source_bases_new_objects) { - Object *ob_new = item.second; - Base *base_source = item.first; - BKE_view_layer_synced_ensure(scene, view_layer); - Base *base_new = BKE_view_layer_base_find(view_layer, ob_new); - if (base_new == nullptr) { + /* Sync the view layer. Everything else should not tag the view_layer out of sync. */ + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *active_base = BKE_view_layer_active_base_get(view_layer); + for (DuplicateObjectLink &link : object_base_links) { + if (!link.object_new) { continue; } + + Base *base_new = BKE_view_layer_base_find(view_layer, link.object_new); + BLI_assert(base_new); ED_object_base_select(base_new, BA_SELECT); - if (ob_new == ob_new_active) { + if (active_base == link.base_src) { ED_object_base_activate(C, base_new); } - if (base_new->object->data) { - DEG_id_tag_update(static_cast(base_new->object->data), 0); + + if (link.object_new->data) { + DEG_id_tag_update(static_cast(link.object_new->data), 0); } - /* #object_add_duplicate_internal will not have done this, since - * before the collection sync it would not have found the new base yet. */ - base_new->local_view_bits = base_source->local_view_bits; + + object_add_sync_local_view(link.base_src, base_new); } /* Note that this will also clear newid pointers and tags. */ -- cgit v1.2.3 From 9d710374bda41359132f929286f5eea7340441b5 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 16:15:02 +0200 Subject: Fix T101645: division by zero in fillet node --- source/blender/geometry/intern/fillet_curves.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/geometry/intern/fillet_curves.cc b/source/blender/geometry/intern/fillet_curves.cc index 1bbbee6edef..2479458f88d 100644 --- a/source/blender/geometry/intern/fillet_curves.cc +++ b/source/blender/geometry/intern/fillet_curves.cc @@ -148,12 +148,14 @@ static float limit_radius(const float3 &position_prev, const float displacement_prev = radius_prev * std::tan(angle_prev / 2.0f); const float segment_length_prev = math::distance(position, position_prev); const float total_displacement_prev = displacement_prev + displacement; - const float factor_prev = std::clamp(segment_length_prev / total_displacement_prev, 0.0f, 1.0f); + const float factor_prev = std::clamp( + safe_divide(segment_length_prev, total_displacement_prev), 0.0f, 1.0f); const float displacement_next = radius_next * std::tan(angle_next / 2.0f); const float segment_length_next = math::distance(position, position_next); const float total_displacement_next = displacement_next + displacement; - const float factor_next = std::clamp(segment_length_next / total_displacement_next, 0.0f, 1.0f); + const float factor_next = std::clamp( + safe_divide(segment_length_next, total_displacement_next), 0.0f, 1.0f); return radius * std::min(factor_prev, factor_next); } -- cgit v1.2.3 From 58e25f11ae9eb805dd857fae56be1d1a43710091 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Thu, 20 Oct 2022 16:31:35 +0200 Subject: Realtime Compositor: Implement normalize node This patch implements the normalize node for the realtime compositor. Differential Revision: https://developer.blender.org/D16279 Reviewed By: Clement Foucault --- .../algorithms/COM_algorithm_parallel_reduction.hh | 22 ++++++++++ .../intern/algorithm_parallel_reduction.cc | 38 +++++++++++++++++ source/blender/gpu/CMakeLists.txt | 2 + .../shaders/compositor/compositor_normalize.glsl | 10 +++++ .../compositor/infos/compositor_normalize_info.hh | 12 ++++++ .../infos/compositor_parallel_reduction_info.hh | 24 +++++++++++ .../composite/nodes/node_composite_normalize.cc | 47 +++++++++++++++++++++- 7 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 source/blender/gpu/shaders/compositor/compositor_normalize.glsl create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh diff --git a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh index b094782c18e..f6d479f9bbe 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh +++ b/source/blender/compositor/realtime_compositor/algorithms/COM_algorithm_parallel_reduction.hh @@ -70,6 +70,17 @@ float sum_luminance_squared_difference(Context &context, * coefficients to compute the luminance. */ float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); +/* Computes the maximum float of all pixels in the given float texture, limited to the given range. + * Values outside of the given range are ignored. If non of the pixel values are in the range, the + * lower bound of the range is returned. For instance, if the given range is [-10, 10] and the + * image contains the values {2, 5, 11}, the maximum will be 5, since 11 is outside of the range. + * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite + * values, so enforcing an upper bound is beneficial. */ +float maximum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound); + /* -------------------------------------------------------------------- * Minimum Reductions. */ @@ -78,4 +89,15 @@ float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_ * coefficients to compute the luminance. */ float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients); +/* Computes the minimum float of all pixels in the given float texture, limited to the given range. + * Values outside of the given range are ignored. If non of the pixel values are in the range, the + * upper bound of the range is returned. For instance, if the given range is [-10, 10] and the + * image contains the values {-11, 2, 5}, the minimum will be 2, since -11 is outside of the range. + * This is particularly useful for Z Depth normalization, since Z Depth can contain near infinite + * values, so enforcing a lower bound is beneficial. */ +float minimum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound); + } // namespace blender::realtime_compositor diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc index 139c58bc190..9672431992d 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc +++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc @@ -249,6 +249,25 @@ float maximum_luminance(Context &context, GPUTexture *texture, float3 luminance_ return maximum; } +float maximum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound) +{ + GPUShader *shader = context.shader_manager().get("compositor_maximum_float_in_range"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "lower_bound", lower_bound); + GPU_shader_uniform_1f(shader, "upper_bound", upper_bound); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float maximum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return maximum; +} + /* -------------------------------------------------------------------- * Minimum Reductions. */ @@ -268,4 +287,23 @@ float minimum_luminance(Context &context, GPUTexture *texture, float3 luminance_ return minimum; } +float minimum_float_in_range(Context &context, + GPUTexture *texture, + float lower_bound, + float upper_bound) +{ + GPUShader *shader = context.shader_manager().get("compositor_minimum_float_in_range"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "lower_bound", lower_bound); + GPU_shader_uniform_1f(shader, "upper_bound", upper_bound); + + float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F); + const float minimum = *reduced_value; + MEM_freeN(reduced_value); + GPU_shader_unbind(); + + return minimum; +} + } // namespace blender::realtime_compositor diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 56031b2722b..1ede48a3265 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -349,6 +349,7 @@ set(GLSL_SRC shaders/compositor/compositor_morphological_distance_feather.glsl shaders/compositor/compositor_morphological_distance_threshold.glsl shaders/compositor/compositor_morphological_step.glsl + shaders/compositor/compositor_normalize.glsl shaders/compositor/compositor_parallel_reduction.glsl shaders/compositor/compositor_projector_lens_distortion.glsl shaders/compositor/compositor_realize_on_domain.glsl @@ -633,6 +634,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/compositor/infos/compositor_morphological_distance_info.hh shaders/compositor/infos/compositor_morphological_distance_threshold_info.hh shaders/compositor/infos/compositor_morphological_step_info.hh + shaders/compositor/infos/compositor_normalize_info.hh shaders/compositor/infos/compositor_parallel_reduction_info.hh shaders/compositor/infos/compositor_projector_lens_distortion_info.hh shaders/compositor/infos/compositor_realize_on_domain_info.hh diff --git a/source/blender/gpu/shaders/compositor/compositor_normalize.glsl b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl new file mode 100644 index 00000000000..53dfeb01730 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_normalize.glsl @@ -0,0 +1,10 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + float value = texture_load(input_tx, texel).x; + float normalized_value = (value - minimum) * scale; + float clamped_value = clamp(normalized_value, 0.0, 1.0); + imageStore(output_img, texel, vec4(clamped_value)); +} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh new file mode 100644 index 00000000000..02fdc424014 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_normalize_info.hh @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_normalize) + .local_group_size(16, 16) + .push_constant(Type::FLOAT, "minimum") + .push_constant(Type::FLOAT, "scale") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .image(0, GPU_R16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_normalize.glsl") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh index 4a71bdc80e2..e2252b14758 100644 --- a/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh +++ b/source/blender/gpu/shaders/compositor/infos/compositor_parallel_reduction_info.hh @@ -108,6 +108,18 @@ GPU_SHADER_CREATE_INFO(compositor_maximum_luminance) .define("REDUCE(lhs, rhs)", "max(lhs, rhs)") .do_static_compilation(true); +GPU_SHADER_CREATE_INFO(compositor_maximum_float_in_range) + .additional_info("compositor_parallel_reduction_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::FLOAT, "lower_bound") + .push_constant(Type::FLOAT, "upper_bound") + .define("TYPE", "float") + .define("IDENTITY", "vec4(lower_bound)") + .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : lower_bound") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "((rhs > lhs) && (rhs <= upper_bound)) ? rhs : lhs") + .do_static_compilation(true); + /* -------------------------------------------------------------------- * Minimum Reductions. */ @@ -123,3 +135,15 @@ GPU_SHADER_CREATE_INFO(compositor_minimum_luminance) .define("LOAD(value)", "value.x") .define("REDUCE(lhs, rhs)", "min(lhs, rhs)") .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(compositor_minimum_float_in_range) + .additional_info("compositor_parallel_reduction_shared") + .image(0, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .push_constant(Type::FLOAT, "lower_bound") + .push_constant(Type::FLOAT, "upper_bound") + .define("TYPE", "float") + .define("IDENTITY", "vec4(upper_bound)") + .define("INITIALIZE(v)", "((v.x <= upper_bound) && (v.x >= lower_bound)) ? v.x : upper_bound") + .define("LOAD(value)", "value.x") + .define("REDUCE(lhs, rhs)", "((rhs < lhs) && (rhs >= lower_bound)) ? rhs : lhs") + .do_static_compilation(true); diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.cc b/source/blender/nodes/composite/nodes/node_composite_normalize.cc index 21765825468..34fd63e5805 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normalize.cc +++ b/source/blender/nodes/composite/nodes/node_composite_normalize.cc @@ -5,7 +5,9 @@ * \ingroup cmpnodes */ +#include "COM_algorithm_parallel_reduction.hh" #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" @@ -15,19 +17,60 @@ namespace blender::nodes::node_composite_normalize_cc { static void cmp_node_normalize_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("Value")).default_value(1.0f).min(0.0f).max(1.0f); + b.add_input(N_("Value")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .compositor_domain_priority(0); b.add_output(N_("Value")); } using namespace blender::realtime_compositor; class NormalizeOperation : public NodeOperation { + private: + /* The normalize operation is specifically designed to normalize Z Depth information. But since Z + * Depth can contain near infinite values, normalization is limited to [-range_, range], meaning + * that values outside of that range will be ignored when computing the maximum and minimum for + * normalization and will eventually be 0 or 1 if they are less than or larger than the range + * respectively. */ + constexpr static float range_ = 10000.0f; + public: using NodeOperation::NodeOperation; void execute() override { - get_input("Value").pass_through(get_result("Value")); + Result &input_image = get_input("Value"); + Result &output_image = get_result("Value"); + if (input_image.is_single_value()) { + input_image.pass_through(output_image); + return; + } + + const float maximum = maximum_float_in_range( + context(), input_image.texture(), -range_, range_); + const float minimum = minimum_float_in_range( + context(), input_image.texture(), -range_, range_); + const float scale = (maximum != minimum) ? (1.0f / (maximum - minimum)) : 0.0f; + + GPUShader *shader = shader_manager().get("compositor_normalize"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1f(shader, "minimum", minimum); + GPU_shader_uniform_1f(shader, "scale", scale); + + input_image.bind_as_texture(shader, "input_tx"); + + const Domain domain = compute_domain(); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); } }; -- cgit v1.2.3 From 84825e4ed2e098954f0c46adee4d65c8c0ba0e99 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 20 Oct 2022 16:37:07 +0200 Subject: UI: Icon number indicator for data-blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the possibility of having a little number on top of icons. At the moment this is used for: * Outliner * Node Editor bread-crumb * Node Group node header For the outliner there is almost no functional change. It is mostly a refactor to handle the indicators as part of the icon shader instead of the outliner draw code. (note that this was already recently changed in a5d3b648e3e2). The difference is that now we use rounded border rectangle instead of circles, and we can go up to 999 elements. So for the outliner this shows the number of collapsed elements of a certain type (e.g., mesh objects inside a collapsed collection). For the node editors is being used to show the use count for the data-block. This is important for the node editor, so users know whether the node-group they are editing (or are about to edit) is used elsewhere. This is particularly important when the Node Options are hidden, which is the default for node groups appended from the asset libraries. --- Note: This can be easily enabled for ID templates which can then be part of T84669. It just need to call UI_but_icon_indicator_number_set in the function template_add_button_search_menu. --- Special thanks Clément Foucault for the help figuring out the shader, Julian Eisel for the help navigating the UI code, and Pablo Vazquez for the collaboration in this design solution. For images showing the result check the Differential Revision. Differential Revision: https://developer.blender.org/D16284 --- source/blender/blenlib/BLI_string.h | 22 ++++ source/blender/blenlib/intern/string.c | 30 +++++ source/blender/blenlib/tests/BLI_string_test.cc | 97 +++++++++++++++ source/blender/editors/include/UI_interface.h | 4 +- source/blender/editors/include/UI_interface.hh | 1 + .../blender/editors/include/UI_interface_icons.h | 12 +- source/blender/editors/interface/interface.cc | 5 + .../editors/interface/interface_context_path.cc | 14 ++- source/blender/editors/interface/interface_icons.c | 117 +++++++++++++++--- .../blender/editors/interface/interface_intern.h | 4 + .../blender/editors/interface/interface_layout.c | 4 +- .../blender/editors/interface/interface_panel.cc | 6 +- .../blender/editors/interface/interface_widgets.c | 15 ++- source/blender/editors/screen/area.c | 3 +- source/blender/editors/space_file/file_draw.c | 65 ++++++++-- source/blender/editors/space_info/textview.c | 3 +- source/blender/editors/space_node/node_draw.cc | 3 + .../editors/space_node/node_relationships.cc | 3 +- .../editors/space_outliner/outliner_draw.cc | 134 +++------------------ source/blender/gpu/CMakeLists.txt | 3 + source/blender/gpu/GPU_shader.h | 4 + source/blender/gpu/intern/gpu_shader_builtin.c | 5 + .../blender/gpu/shaders/gpu_shader_icon_frag.glsl | 42 +++++++ .../blender/gpu/shaders/gpu_shader_icon_vert.glsl | 37 ++++++ .../gpu/shaders/infos/gpu_interface_info.hh | 3 + .../gpu/shaders/infos/gpu_shader_icon_info.hh | 22 ++++ source/blender/windowmanager/intern/wm_dragdrop.cc | 3 +- 27 files changed, 499 insertions(+), 162 deletions(-) create mode 100644 source/blender/gpu/shaders/gpu_shader_icon_frag.glsl create mode 100644 source/blender/gpu/shaders/gpu_shader_icon_vert.glsl create mode 100644 source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 15926e8f2d2..17abcf52ecc 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -308,6 +308,28 @@ void BLI_str_format_byte_unit(char dst[15], long long int bytes, bool base_10) A * Length of 7 is the maximum of the resulting string, for example, `-15.5K\0`. */ void BLI_str_format_decimal_unit(char dst[7], int number_to_format) ATTR_NONNULL(); +/** + * Format a count to up to 3 places (plus minus sign, plus '\0' terminator) string using long + * number names abbreviations. Used to produce a compact representation of large numbers as + * integers. + * + * It shows a lower bound instead of rounding the number. + * + * 1 -> 1 + * 15 -> 15 + * 155 -> 155 + * 1555 -> 1K + * 15555 -> 15K + * 155555 -> .1M + * 1555555 -> 1M + * 15555555 -> 15M + * 155555555 -> .1B + * 1000000000 -> 1B + * ... + * + * Length of 5 is the maximum of the resulting string, for example, `-15K\0`. + */ +void BLI_str_format_integer_unit(char dst[5], int number_to_format) ATTR_NONNULL(); /** * Compare two strings without regard to case. * diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 89d31c5e93f..755d2dbd55d 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -1176,4 +1176,34 @@ void BLI_str_format_decimal_unit(char dst[7], int number_to_format) BLI_snprintf(dst, dst_len, "%.*f%s", decimals, number_to_format_converted, units[order]); } +void BLI_str_format_integer_unit(char dst[5], const int number_to_format) +{ + float number_to_format_converted = number_to_format; + int order = 0; + const float base = 1000; + const char *units[] = {"", "K", "M", "B"}; + const int units_num = ARRAY_SIZE(units); + + while ((fabsf(number_to_format_converted) >= base) && ((order + 1) < units_num)) { + number_to_format_converted /= base; + order++; + } + + const bool add_dot = (abs(number_to_format) > 99999) && fabsf(number_to_format_converted) > 99; + + if (add_dot) { + number_to_format_converted /= 100; + order++; + } + + const size_t dst_len = 5; + BLI_snprintf(dst, + dst_len, + "%s%s%d%s", + number_to_format < 0 ? "-" : "", + add_dot ? "." : "", + (int)floorf(fabsf(number_to_format_converted)), + units[order]); +} + /** \} */ diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index 9bdf6075c70..d726fbccf20 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -515,6 +515,103 @@ TEST(string, StrFormatDecimalUnits) EXPECT_STREQ("-2.1B", size_str); } +/* BLI_str_format_integer_unit */ +TEST(string, StrFormatIntegerUnits) +{ + char size_str[7]; + int size; + + BLI_str_format_integer_unit(size_str, size = 0); + EXPECT_STREQ("0", size_str); + BLI_str_format_integer_unit(size_str, size = 1); + EXPECT_STREQ("1", size_str); + BLI_str_format_integer_unit(size_str, size = 10); + EXPECT_STREQ("10", size_str); + BLI_str_format_integer_unit(size_str, size = 15); + EXPECT_STREQ("15", size_str); + BLI_str_format_integer_unit(size_str, size = 100); + EXPECT_STREQ("100", size_str); + BLI_str_format_integer_unit(size_str, size = 155); + EXPECT_STREQ("155", size_str); + BLI_str_format_integer_unit(size_str, size = 1000); + EXPECT_STREQ("1K", size_str); + BLI_str_format_integer_unit(size_str, size = 1555); + EXPECT_STREQ("1K", size_str); + BLI_str_format_integer_unit(size_str, size = 10000); + EXPECT_STREQ("10K", size_str); + BLI_str_format_integer_unit(size_str, size = 15555); + EXPECT_STREQ("15K", size_str); + BLI_str_format_integer_unit(size_str, size = 100000); + EXPECT_STREQ(".1M", size_str); + BLI_str_format_integer_unit(size_str, size = 155555); + EXPECT_STREQ(".1M", size_str); + BLI_str_format_integer_unit(size_str, size = 1000000); + EXPECT_STREQ("1M", size_str); + BLI_str_format_integer_unit(size_str, size = 1555555); + EXPECT_STREQ("1M", size_str); + BLI_str_format_integer_unit(size_str, size = 2555555); + EXPECT_STREQ("2M", size_str); + BLI_str_format_integer_unit(size_str, size = 10000000); + EXPECT_STREQ("10M", size_str); + BLI_str_format_integer_unit(size_str, size = 15555555); + EXPECT_STREQ("15M", size_str); + BLI_str_format_integer_unit(size_str, size = 100000000); + EXPECT_STREQ(".1B", size_str); + BLI_str_format_integer_unit(size_str, size = 155555555); + EXPECT_STREQ(".1B", size_str); + BLI_str_format_integer_unit(size_str, size = 255555555); + EXPECT_STREQ(".2B", size_str); + BLI_str_format_integer_unit(size_str, size = 1000000000); + EXPECT_STREQ("1B", size_str); + + /* Largest possible value. */ + BLI_str_format_integer_unit(size_str, size = INT32_MAX); + EXPECT_STREQ("2B", size_str); + + BLI_str_format_integer_unit(size_str, size = -0); + EXPECT_STREQ("0", size_str); + BLI_str_format_integer_unit(size_str, size = -1); + EXPECT_STREQ("-1", size_str); + BLI_str_format_integer_unit(size_str, size = -10); + EXPECT_STREQ("-10", size_str); + BLI_str_format_integer_unit(size_str, size = -15); + EXPECT_STREQ("-15", size_str); + BLI_str_format_integer_unit(size_str, size = -100); + EXPECT_STREQ("-100", size_str); + BLI_str_format_integer_unit(size_str, size = -155); + EXPECT_STREQ("-155", size_str); + BLI_str_format_integer_unit(size_str, size = -1000); + EXPECT_STREQ("-1K", size_str); + BLI_str_format_integer_unit(size_str, size = -1555); + EXPECT_STREQ("-1K", size_str); + BLI_str_format_integer_unit(size_str, size = -10000); + EXPECT_STREQ("-10K", size_str); + BLI_str_format_integer_unit(size_str, size = -15555); + EXPECT_STREQ("-15K", size_str); + BLI_str_format_integer_unit(size_str, size = -100000); + EXPECT_STREQ("-.1M", size_str); + BLI_str_format_integer_unit(size_str, size = -155555); + EXPECT_STREQ("-.1M", size_str); + BLI_str_format_integer_unit(size_str, size = -1000000); + EXPECT_STREQ("-1M", size_str); + BLI_str_format_integer_unit(size_str, size = -1555555); + EXPECT_STREQ("-1M", size_str); + BLI_str_format_integer_unit(size_str, size = -10000000); + EXPECT_STREQ("-10M", size_str); + BLI_str_format_integer_unit(size_str, size = -15555555); + EXPECT_STREQ("-15M", size_str); + BLI_str_format_integer_unit(size_str, size = -100000000); + EXPECT_STREQ("-.1B", size_str); + BLI_str_format_integer_unit(size_str, size = -155555555); + EXPECT_STREQ("-.1B", size_str); + BLI_str_format_integer_unit(size_str, size = -1000000000); + EXPECT_STREQ("-1B", size_str); + + /* Smallest possible value. */ + BLI_str_format_integer_unit(size_str, size = -INT32_MAX); + EXPECT_STREQ("-2B", size_str); +} + struct WordInfo { WordInfo() = default; WordInfo(int start, int end) : start(start), end(end) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 2a1941f0d9e..7e9422ff867 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1683,6 +1683,7 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name); * Adds a hint to the button which draws right aligned, grayed out and never clipped. */ void UI_but_hint_drawstr_set(uiBut *but, const char *string); +void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number); void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]); @@ -2788,7 +2789,8 @@ typedef struct uiPropertySplitWrapper { uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout); void uiItemL(uiLayout *layout, const char *name, int icon); /* label */ -void uiItemL_ex(uiLayout *layout, const char *name, int icon, bool highlight, bool redalert); +struct uiBut *uiItemL_ex( + uiLayout *layout, const char *name, int icon, bool highlight, bool redalert); /** * Helper to add a label and creates a property split layout if needed. */ diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh index 6c756984203..fc03b0218c0 100644 --- a/source/blender/editors/include/UI_interface.hh +++ b/source/blender/editors/include/UI_interface.hh @@ -35,6 +35,7 @@ struct ContextPathItem { std::string name; /* #BIFIconID */ int icon; + int icon_indicator_number; }; void context_path_add_generic(Vector &path, diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index a1a98a4b08c..9669e242dac 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -27,6 +27,12 @@ typedef struct IconFile { int index; } IconFile; +typedef struct IconTextOverlay { + char text[5]; +} IconTextOverlay; + +#define UI_NO_ICON_OVERLAY_TEXT NULL + #define ICON_DEFAULT_HEIGHT 16 #define ICON_DEFAULT_WIDTH 16 @@ -105,7 +111,8 @@ void UI_icon_draw_ex(float x, float alpha, float desaturate, const uchar mono_color[4], - bool mono_border); + bool mono_border, + const struct IconTextOverlay *text_overlay); void UI_icons_free(void); void UI_icons_free_drawinfo(void *drawinfo); @@ -124,6 +131,9 @@ int UI_icon_from_library(const struct ID *id); int UI_icon_from_object_mode(int mode); int UI_icon_color_from_collection(const struct Collection *collection); +void UI_icon_text_overlay_init_from_count(struct IconTextOverlay *text_overlay, + const int icon_indicator_number); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 422fc34aa50..1f88d25af2b 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -6452,6 +6452,11 @@ void UI_but_hint_drawstr_set(uiBut *but, const char *string) ui_but_add_shortcut(but, string, false); } +void UI_but_icon_indicator_number_set(uiBut *but, const int indicator_number) +{ + UI_icon_text_overlay_init_from_count(&but->icon_overlay_text, indicator_number); +} + void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4]) { but->flag |= UI_BUT_NODE_LINK; diff --git a/source/blender/editors/interface/interface_context_path.cc b/source/blender/editors/interface/interface_context_path.cc index e8f552e26a3..91b2f9613de 100644 --- a/source/blender/editors/interface/interface_context_path.cc +++ b/source/blender/editors/interface/interface_context_path.cc @@ -17,6 +17,8 @@ #include "UI_interface.hh" #include "UI_resources.h" +#include "RNA_prototypes.h" + #include "WM_api.h" namespace blender::ui { @@ -41,7 +43,13 @@ void context_path_add_generic(Vector &path, static_cast(RNA_struct_ui_icon(rna_ptr.type)) : icon_override; - path.append({name, int(icon)}); + if (&rna_type == &RNA_NodeTree) { + ID *id = (ID *)ptr; + path.append({name, int(icon), id->us}); + } + else { + path.append({name, int(icon), 1}); + } } /* -------------------------------------------------------------------- */ @@ -60,7 +68,9 @@ void template_breadcrumbs(uiLayout &layout, Span context_path) if (i > 0) { uiItemL(sub_row, "", ICON_RIGHTARROW_THIN); } - uiItemL(sub_row, context_path[i].name.c_str(), context_path[i].icon); + uiBut *but = uiItemL_ex( + sub_row, context_path[i].name.c_str(), context_path[i].icon, false, false); + UI_but_icon_indicator_number_set(but, context_path[i].icon_indicator_number); } } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index deb3d84ae66..9a4f98ebcd6 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -415,8 +415,15 @@ static void vicon_collection_color_draw( const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; - UI_icon_draw_ex( - x, y, ICON_OUTLINER_COLLECTION, aspect, 1.0f, 0.0f, collection_color->color, true); + UI_icon_draw_ex(x, + y, + ICON_OUTLINER_COLLECTION, + aspect, + 1.0f, + 0.0f, + collection_color->color, + true, + UI_NO_ICON_OVERLAY_TEXT); } # define DEF_ICON_COLLECTION_COLOR_DRAW(index, color) \ @@ -444,7 +451,8 @@ static void vicon_strip_color_draw( const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; - UI_icon_draw_ex(x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true); + UI_icon_draw_ex( + x, y, ICON_SNAP_FACE, aspect, 1.0f, 0.0f, strip_color->color, true, UI_NO_ICON_OVERLAY_TEXT); } # define DEF_ICON_STRIP_COLOR_DRAW(index, color) \ @@ -472,8 +480,15 @@ static void vicon_strip_color_draw_library_data_indirect( { const float aspect = (float)ICON_DEFAULT_WIDTH / (float)w; - UI_icon_draw_ex( - x, y, ICON_LIBRARY_DATA_DIRECT, aspect, ICON_INDIRECT_DATA_ALPHA * alpha, 0.0f, NULL, false); + UI_icon_draw_ex(x, + y, + ICON_LIBRARY_DATA_DIRECT, + aspect, + ICON_INDIRECT_DATA_ALPHA * alpha, + 0.0f, + NULL, + false, + UI_NO_ICON_OVERLAY_TEXT); } static void vicon_strip_color_draw_library_data_override_noneditable( @@ -488,7 +503,8 @@ static void vicon_strip_color_draw_library_data_override_noneditable( ICON_INDIRECT_DATA_ALPHA * alpha * 0.75f, 0.0f, NULL, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); } /* Dynamically render icon instead of rendering a plain color to a texture/buffer @@ -1716,9 +1732,47 @@ static void icon_draw_texture(float x, int ih, float alpha, const float rgb[3], - bool with_border) -{ - if (g_icon_draw_cache.enabled) { + bool with_border, + const IconTextOverlay *text_overlay) +{ + const float zoom_factor = w / UI_DPI_ICON_SIZE; + float text_width = 0.0f; + + /* No need to show if too zoomed out, otherwise it just adds noise. */ + const bool show_indicator = (text_overlay && text_overlay->text[0] != '\0') && + (zoom_factor > 0.7f); + + if (show_indicator) { + /* Handle the little numbers on top of the icon. */ + uchar text_color[4]; + UI_GetThemeColor3ubv(TH_TEXT, text_color); + text_color[3] = 255; + + uiFontStyle fstyle_small = *UI_FSTYLE_WIDGET; + fstyle_small.points *= zoom_factor; + fstyle_small.points *= 0.8f; + + rcti text_rect = { + .xmax = x + UI_UNIT_X * zoom_factor, + .xmin = x, + .ymax = y, + .ymin = y, + }; + + UI_fontstyle_draw(&fstyle_small, + &text_rect, + text_overlay->text, + sizeof(text_overlay->text), + text_color, + &(struct uiFontStyleDraw_Params){ + .align = UI_STYLE_TEXT_RIGHT, + }); + text_width = (float)UI_fontstyle_string_width(&fstyle_small, text_overlay->text) / UI_UNIT_X / + zoom_factor; + } + + /* Draw the actual icon. */ + if (!show_indicator && g_icon_draw_cache.enabled) { icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border); return; } @@ -1735,7 +1789,7 @@ static void icon_draw_texture(float x, GPUTexture *texture = with_border ? icongltex.tex[1] : icongltex.tex[0]; - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_ICON); GPU_shader_bind(shader); const int img_binding = GPU_shader_get_texture_binding(shader, "image"); @@ -1752,6 +1806,7 @@ static void icon_draw_texture(float x, GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, (float[4]){x1, y1, x2, y2}); GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, (float[4]){x, y, x + w, y + h}); + GPU_shader_uniform_1f(shader, "text_width", text_width); GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false); @@ -1786,7 +1841,8 @@ static void icon_draw_size(float x, int draw_size, const float desaturate, const uchar mono_rgba[4], - const bool mono_border) + const bool mono_border, + const IconTextOverlay *text_overlay) { bTheme *btheme = UI_GetTheme(); const float fdraw_size = (float)draw_size; @@ -1874,7 +1930,8 @@ static void icon_draw_size(float x, di->data.texture.h, alpha, NULL, - false); + false, + text_overlay); } else if (di->type == ICON_TYPE_MONO_TEXTURE) { /* Monochrome icon that uses text or theme color. */ @@ -1908,7 +1965,8 @@ static void icon_draw_size(float x, di->data.texture.h + 2 * border_texel, color[3], color, - with_border); + with_border, + text_overlay); } else if (di->type == ICON_TYPE_BUFFER) { @@ -2425,17 +2483,27 @@ int UI_icon_color_from_collection(const Collection *collection) void UI_icon_draw(float x, float y, int icon_id) { - UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false); + UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha) { - UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false); + UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false, UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size) { - icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false); + icon_draw_size(x, + y, + icon_id, + aspect, + alpha, + ICON_SIZE_PREVIEW, + size, + false, + NULL, + false, + UI_NO_ICON_OVERLAY_TEXT); } void UI_icon_draw_ex(float x, @@ -2445,7 +2513,8 @@ void UI_icon_draw_ex(float x, float alpha, float desaturate, const uchar mono_color[4], - const bool mono_border) + const bool mono_border, + const IconTextOverlay *text_overlay) { const int draw_size = get_draw_size(ICON_SIZE_ICON); icon_draw_size(x, @@ -2457,7 +2526,19 @@ void UI_icon_draw_ex(float x, draw_size, desaturate, mono_color, - mono_border); + mono_border, + text_overlay); +} + +void UI_icon_text_overlay_init_from_count(IconTextOverlay *text_overlay, + const int icon_indicator_number) +{ + /* The icon indicator is used as an aggregator, no need to show if it is 1. */ + if (icon_indicator_number < 2) { + text_overlay->text[0] = '\0'; + return; + } + BLI_str_format_integer_unit(text_overlay->text, icon_indicator_number); } /* ********** Alert Icons ********** */ diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6ef7d346418..6ef81ad897e 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -23,6 +23,7 @@ struct ARegion; struct AnimationEvalContext; struct CurveMapping; struct CurveProfile; +struct IconTextOverlay; struct ID; struct ImBuf; struct Main; @@ -275,6 +276,9 @@ struct uiBut { uiButPushedStateFunc pushed_state_func; const void *pushed_state_arg; + /** Little indicator (e.g., counter) displayed on top of some icons. */ + struct IconTextOverlay icon_overlay_text; + /* pointer back */ uiBlock *block; }; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index c906a5b36f1..496f72c089a 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -3235,7 +3235,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) return but; } -void uiItemL_ex( +uiBut *uiItemL_ex( uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert) { uiBut *but = uiItemL_(layout, name, icon); @@ -3248,6 +3248,8 @@ void uiItemL_ex( if (redalert) { UI_but_flag_enable(but, UI_BUT_REDALERT); } + + return but; } void uiItemL(uiLayout *layout, const char *name, int icon) diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index 7a69e2f9b2f..24d8281aad8 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -1112,7 +1112,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style, 0.7f, 0.0f, title_color, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } @@ -1140,7 +1141,8 @@ static void panel_draw_aligned_widgets(const uiStyle *style, 1.0f, 0.0f, title_color, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 6ba80e2e0d9..1bad9b34a72 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1420,21 +1420,25 @@ static void widget_draw_icon( /* to indicate draggable */ if (ui_but_drag_is_draggable(but) && (but->flag & UI_ACTIVE)) { - UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme, &but->icon_overlay_text); } else if (but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) { - UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text); } else if (!((but->icon != ICON_NONE) && UI_but_is_tool(but))) { if (has_theme) { alpha *= 0.8f; } - UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, alpha, 0.0f, color, has_theme, &but->icon_overlay_text); } else { const bTheme *btheme = UI_GetTheme(); const float desaturate = 1.0 - btheme->tui.icon_saturation; - UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme); + UI_icon_draw_ex( + xs, ys, icon, aspect, alpha, desaturate, color, has_theme, &but->icon_overlay_text); } } @@ -5426,7 +5430,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, GPU_blend(GPU_BLEND_ALPHA); /* XXX scale weak get from fstyle? */ - UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false); + UI_icon_draw_ex( + xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false, UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 39e3c7a2f0a..8db968cbb8a 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -187,7 +187,8 @@ static void area_draw_azone_fullscreen( min_ff(alpha, 0.75f), 0.0f, NULL, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); } /** diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index e4085bbe9cc..240901318b5 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -410,8 +410,15 @@ static void file_draw_preview(const SpaceFile *sfile, } icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f); icon_y = yco + (ey / 2.0f) - (icon_size * ((file->typeflag & FILE_TYPE_DIR) ? 0.78f : 0.75f)); - UI_icon_draw_ex( - icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false); + UI_icon_draw_ex(icon_x, + icon_y, + icon, + icon_aspect / U.dpi_fac, + icon_opacity, + 0.0f, + icon_color, + false, + UI_NO_ICON_OVERLAY_TEXT); } if (is_link || is_offline) { @@ -424,8 +431,24 @@ static void file_draw_preview(const SpaceFile *sfile, /* At very bottom-left if preview style. */ const uchar dark[4] = {0, 0, 0, 255}; const uchar light[4] = {255, 255, 255, 255}; - UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false); - UI_icon_draw_ex(icon_x, icon_y, arrow, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false); + UI_icon_draw_ex(icon_x + 1, + icon_y - 1, + arrow, + 1.0f / U.dpi_fac, + 0.2f, + 0.0f, + dark, + false, + UI_NO_ICON_OVERLAY_TEXT); + UI_icon_draw_ex(icon_x, + icon_y, + arrow, + 1.0f / U.dpi_fac, + 0.6f, + 0.0f, + light, + false, + UI_NO_ICON_OVERLAY_TEXT); } else { /* Link to folder or non-previewed file. */ @@ -433,8 +456,15 @@ static void file_draw_preview(const SpaceFile *sfile, UI_GetThemeColor4ubv(TH_BACK, icon_color); icon_x = xco + ((file->typeflag & FILE_TYPE_DIR) ? 0.14f : 0.23f) * scaledx; icon_y = yco + ((file->typeflag & FILE_TYPE_DIR) ? 0.24f : 0.14f) * scaledy; - UI_icon_draw_ex( - icon_x, icon_y, arrow, icon_aspect / U.dpi_fac * 1.8, 0.3f, 0.0f, icon_color, false); + UI_icon_draw_ex(icon_x, + icon_y, + arrow, + icon_aspect / U.dpi_fac * 1.8, + 0.3f, + 0.0f, + icon_color, + false, + UI_NO_ICON_OVERLAY_TEXT); } } else if (icon && !is_icon && !(file->typeflag & FILE_TYPE_FTFONT)) { @@ -444,8 +474,17 @@ static void file_draw_preview(const SpaceFile *sfile, const uchar light[4] = {255, 255, 255, 255}; icon_x = xco + (2.0f * UI_DPI_FAC); icon_y = yco + (2.0f * UI_DPI_FAC); - UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false); - UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false); + UI_icon_draw_ex(icon_x + 1, + icon_y - 1, + icon, + 1.0f / U.dpi_fac, + 0.2f, + 0.0f, + dark, + false, + UI_NO_ICON_OVERLAY_TEXT); + UI_icon_draw_ex( + icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false, UI_NO_ICON_OVERLAY_TEXT); } const bool is_current_main_data = filelist_file_get_id(file) != NULL; @@ -456,7 +495,15 @@ static void file_draw_preview(const SpaceFile *sfile, const uchar light[4] = {255, 255, 255, 255}; icon_x = xco + ex - UI_UNIT_X; icon_y = yco + ey - UI_UNIT_Y; - UI_icon_draw_ex(icon_x, icon_y, ICON_CURRENT_FILE, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false); + UI_icon_draw_ex(icon_x, + icon_y, + ICON_CURRENT_FILE, + 1.0f / U.dpi_fac, + 0.6f, + 0.0f, + light, + false, + UI_NO_ICON_OVERLAY_TEXT); } /* Contrasting outline around some preview types. */ diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index aee72860a0a..12ee6f45991 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -235,7 +235,8 @@ static bool textview_draw_string(TextViewDrawState *tds, 1.0f, 0.0f, icon_fg, - false); + false, + UI_NO_ICON_OVERLAY_TEXT); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index ee9ebd541a0..98b2cacd162 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -2145,6 +2145,9 @@ static void node_draw_basis(const bContext &C, 0, ""); UI_but_func_set(but, node_toggle_button_cb, &node, (void *)"NODE_OT_group_edit"); + if (node.id) { + UI_but_icon_indicator_number_set(but, node.id->us); + } UI_block_emboss_set(&block, UI_EMBOSS); } if (node.type == NODE_CUSTOM && node.typeinfo->ui_icon != ICON_NONE) { diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index b12afcb1faa..637c795d4d7 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -815,7 +815,8 @@ static void draw_draglink_tooltip(const bContext * /*C*/, ARegion * /*region*/, nldrag->cursor[0]; const float y = nldrag->cursor[1] - 2.0f * UI_DPI_FAC; - UI_icon_draw_ex(x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false); + UI_icon_draw_ex( + x, y, ICON_ADD, U.inv_dpi_fac, 1.0f, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); } static void draw_draglink_tooltip_activate(const ARegion ®ion, bNodeLinkDrag &nldrag) diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index e366c58349f..f76c0980c4f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -2877,7 +2877,8 @@ static bool tselem_draw_icon(uiBlock *block, TreeStoreElem *tselem, TreeElement *te, float alpha, - const bool is_clickable) + const bool is_clickable, + const int num_elements) { TreeElementIcon data = tree_element_get_icon(tselem, te); if (data.icon == 0) { @@ -2885,6 +2886,8 @@ static bool tselem_draw_icon(uiBlock *block, } const bool is_collection = outliner_is_collection_tree_element(te); + IconTextOverlay text_overlay; + UI_icon_text_overlay_init_from_count(&text_overlay, num_elements); /* Collection colors and icons covered by restrict buttons. */ if (!is_clickable || x >= xmax || is_collection) { @@ -2904,7 +2907,8 @@ static bool tselem_draw_icon(uiBlock *block, alpha, 0.0f, btheme->collection_color[collection->color_tag].color, - true); + true, + &text_overlay); return true; } } @@ -2915,10 +2919,10 @@ static bool tselem_draw_icon(uiBlock *block, /* Restrict column clip. it has been coded by simply overdrawing, doesn't work for buttons. */ uchar color[4]; if (UI_icon_get_theme_color(data.icon, color)) { - UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true); + UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true, &text_overlay); } else { - UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false); + UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, nullptr, false, &text_overlay); } } else { @@ -2941,104 +2945,6 @@ static bool tselem_draw_icon(uiBlock *block, return true; } -static bool outliner_is_main_row(const ARegion *region, const int ys) -{ - int ystart; - - ystart = int(region->v2d.tot.ymax); - ystart = UI_UNIT_Y * (ystart / (UI_UNIT_Y)) - OL_Y_OFFSET; - - return ((ys - ystart) / UI_UNIT_Y) % 2; -} - -/** - * Get the expected row background color to use for the data-block counter - * - * This reproduces some of the logic of outliner_draw_highlights. - * At the moment it doesn't implement the search match color since - * we don't draw the data-block counter in those cases. - */ -static void outliner_get_row_color(const ARegion *region, - const TreeElement *te, - int ys, - float r_color[4]) -{ - const TreeStoreElem *tselem = TREESTORE(te); - - if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) { - UI_GetThemeColor3fv(TH_ACTIVE, r_color); - } - else if (tselem->flag & TSE_SELECTED) { - UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, r_color); - } - else if (outliner_is_main_row(region, ys)) { - UI_GetThemeColor3fv(TH_BACK, r_color); - } - else { - float color_alternating[4]; - UI_GetThemeColor4fv(TH_ROW_ALTERNATE, color_alternating); - UI_GetThemeColorBlend3f(TH_BACK, TH_ROW_ALTERNATE, color_alternating[3], r_color); - } - - if (tselem->flag & TSE_HIGHLIGHTED) { - const float color_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f}; - interp_v3_v3v3(r_color, r_color, color_highlight, color_highlight[3]); - } - r_color[3] = 1.0f; -} - -/** - * For icon-only children of a collapsed tree, - * Draw small number over the icon to show how many items of this type are displayed. - */ -static void outliner_draw_iconrow_number(const ARegion *region, - const uiFontStyle *fstyle, - int offsx, - int ys, - const TreeElement *te_visible, - const int num_elements) -{ - float color[4]; - outliner_get_row_color(region, te_visible, ys, color); - - float ufac = 0.25f * UI_UNIT_X; - float offset_x = float(offsx) + UI_UNIT_X * 0.35f; - rctf rect{}; - BLI_rctf_init(&rect, - offset_x + ufac, - offset_x + UI_UNIT_X - ufac, - float(ys) - UI_UNIT_Y * 0.2f + ufac, - float(ys) - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac); - - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_4fv_ex( - &rect, color, NULL, 1.0f, color, U.pixelsize, float(UI_UNIT_Y) / 2.0f - ufac); - - /* Now the numbers. */ - uchar text_col[4]; - - UI_GetThemeColor3ubv(TH_TEXT, text_col); - text_col[3] = 255; - - uiFontStyle fstyle_small = *fstyle; - fstyle_small.points *= 0.8f; - - /* We treat +99 as 4 digits to make sure the (eyeballed) alignment looks nice. */ - int num_digits = 4; - char number_text[4] = "+99"; - if (num_elements < 100) { - BLI_snprintf(number_text, sizeof(number_text), "%d", num_elements); - num_digits = num_elements < 10 ? 1 : 2; - } - UI_fontstyle_draw_simple(&fstyle_small, - (offset_x + ufac + UI_UNIT_X * (2 - num_digits) * 0.12f), - float(ys) - UI_UNIT_Y * 0.095f + ufac, - number_text, - text_col); - UI_fontstyle_set(fstyle); - GPU_blend(GPU_BLEND_ALPHA); /* Round-box and text drawing disables. */ -} - static void outliner_icon_background_colors(float icon_color[4], float icon_border[4]) { float text[4]; @@ -3069,11 +2975,8 @@ static void outliner_draw_active_indicator(const float minx, GPU_blend(GPU_BLEND_ALPHA); /* Round-box disables. */ } -static void outliner_draw_iconrow_doit(const ARegion *region, - uiBlock *block, - TreeElement *te_visible, +static void outliner_draw_iconrow_doit(uiBlock *block, TreeElement *te, - const uiFontStyle *fstyle, int xmax, int *offsx, int ys, @@ -3102,13 +3005,13 @@ static void outliner_draw_iconrow_doit(const ARegion *region, if (tselem->flag & TSE_HIGHLIGHTED_ICON) { alpha_fac += 0.5; } - tselem_draw_icon(block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false); + tselem_draw_icon( + block, xmax, float(*offsx), float(ys), tselem, te, alpha_fac, false, num_elements); te->xs = *offsx; te->ys = ys; te->xend = short(*offsx) + UI_UNIT_X; if (num_elements > 1) { - outliner_draw_iconrow_number(region, fstyle, *offsx, ys, te_visible, num_elements); te->flag |= TE_ICONROW_MERGED; } else { @@ -3145,7 +3048,6 @@ static void outliner_draw_iconrow(bContext *C, const uiFontStyle *fstyle, const TreeViewContext *tvc, SpaceOutliner *space_outliner, - TreeElement *te_visible, ListBase *lb, int level, int xmax, @@ -3154,7 +3056,6 @@ static void outliner_draw_iconrow(bContext *C, float alpha_fac, MergedIconRow *merged) { - const ARegion *region = CTX_wm_region(C); eOLDrawState active = OL_DRAWSEL_NONE; LISTBASE_FOREACH (TreeElement *, te, lb) { @@ -3194,8 +3095,7 @@ static void outliner_draw_iconrow(bContext *C, TSE_POSE_CHANNEL, TSE_POSEGRP, TSE_DEFGROUP)) { - outliner_draw_iconrow_doit( - region, block, te_visible, te, fstyle, xmax, offsx, ys, alpha_fac, active, 1); + outliner_draw_iconrow_doit(block, te, xmax, offsx, ys, alpha_fac, active, 1); } else { const int index = tree_element_id_type_to_index(te); @@ -3214,7 +3114,6 @@ static void outliner_draw_iconrow(bContext *C, fstyle, tvc, space_outliner, - te, &te->subtree, level + 1, xmax, @@ -3236,11 +3135,8 @@ static void outliner_draw_iconrow(bContext *C, for (int j = 0; j < num_subtypes; j++) { const int index = index_base + j; if (merged->num_elements[index] != 0) { - outliner_draw_iconrow_doit(region, - block, - te_visible, + outliner_draw_iconrow_doit(block, merged->tree_element[index], - fstyle, xmax, offsx, ys, @@ -3429,7 +3325,8 @@ static void outliner_draw_tree_element(bContext *C, tselem, te, (tselem->flag & TSE_HIGHLIGHTED_ICON) ? alpha_fac + 0.5f : alpha_fac, - true)) { + true, + 1)) { offsx += UI_UNIT_X + 4 * ufac; } else { @@ -3478,7 +3375,6 @@ static void outliner_draw_tree_element(bContext *C, fstyle, tvc, space_outliner, - te, &te->subtree, 0, xmax, diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 1ede48a3265..58b1cd0a50b 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -282,6 +282,8 @@ set(GLSL_SRC shaders/gpu_shader_2D_image_vert.glsl shaders/gpu_shader_2D_image_rect_vert.glsl shaders/gpu_shader_2D_image_multi_rect_vert.glsl + shaders/gpu_shader_icon_frag.glsl + shaders/gpu_shader_icon_vert.glsl shaders/gpu_shader_image_frag.glsl shaders/gpu_shader_image_desaturate_frag.glsl shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -609,6 +611,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/infos/gpu_shader_3D_smooth_color_info.hh shaders/infos/gpu_shader_3D_uniform_color_info.hh shaders/infos/gpu_shader_gpencil_stroke_info.hh + shaders/infos/gpu_shader_icon_info.hh shaders/infos/gpu_shader_instance_varying_color_varying_size_info.hh shaders/infos/gpu_shader_keyframe_shape_info.hh shaders/infos/gpu_shader_line_dashed_uniform_color_info.hh diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 3f35db42eb9..1148207fc57 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -208,6 +208,10 @@ typedef enum eGPUBuiltinShader { GPU_SHADER_TEXT, GPU_SHADER_KEYFRAME_SHAPE, GPU_SHADER_SIMPLE_LIGHTING, + /** + * Draw an icon, leaving a semi-transparent rectangle on top of the icon. + */ + GPU_SHADER_ICON, /** * Take a 2D position and color for each vertex with linear interpolation in window space. * diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c index 8a6586e06f6..470643ba863 100644 --- a/source/blender/gpu/intern/gpu_shader_builtin.c +++ b/source/blender/gpu/intern/gpu_shader_builtin.c @@ -153,6 +153,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .create_info = "gpu_shader_2D_diag_stripes", }, + [GPU_SHADER_ICON] = + { + .name = "GPU_SHADER_ICON", + .create_info = "gpu_shader_icon", + }, [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] = { .name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE", diff --git a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl new file mode 100644 index 00000000000..ff56d772317 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl @@ -0,0 +1,42 @@ +/** + * Draw the icons, leaving a semi-transparent rectangle on top of the icon. + * + * The top-left corner of the rectangle is rounded and drawned with anti-alias. + * The anti-alias is done by transitioning from the outer to the inner radius of + * the rounded corner, and the rectangle sides. + */ + +void main() +{ + /* Top-left rounded corner parameters. */ + const float circle_radius_outer = 0.1; + const float circle_radius_inner = 0.075; + + /** + * Add a bit transparency to see a bit of the icon, without + * getting on the way of readability. */ + const float mask_transparency = 0.25; + + vec2 circle_center = vec2(circle_radius_outer - text_width, 0.5); + fragColor = texture(image, texCoord_interp) * color; + + /* radius in icon space (1 is the icon width). */ + float radius = length(mask_coord_interp - circle_center); + float mask = smoothstep(circle_radius_inner, circle_radius_outer, radius); + + bool lower_half = mask_coord_interp.y < circle_center.y; + bool right_half = mask_coord_interp.x > circle_center.x; + + if (right_half && mask_coord_interp.t < circle_center.y + circle_radius_outer) { + mask = smoothstep(circle_center.y + circle_radius_inner, + circle_center.y + circle_radius_outer, + mask_coord_interp.t); + } + if (lower_half && mask_coord_interp.s > circle_center.x - circle_radius_outer) { + mask = smoothstep(circle_center.x - circle_radius_inner, + circle_center.x - circle_radius_outer, + mask_coord_interp.s); + } + + fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask)); +} diff --git a/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl new file mode 100644 index 00000000000..25f64bfe0b6 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_icon_vert.glsl @@ -0,0 +1,37 @@ +/** + * Simple shader that just draw one icon at the specified location + * does not need any vertex input (producing less call to immBegin/End) + */ + +void main() +{ + vec2 uv; + vec2 co; + + if (gl_VertexID == 0) { + co = rect_geom.xw; + uv = rect_icon.xw; + mask_coord_interp = vec2(0, 1); + } + else if (gl_VertexID == 1) { + co = rect_geom.xy; + uv = rect_icon.xy; + mask_coord_interp = vec2(0, 0); + } + else if (gl_VertexID == 2) { + co = rect_geom.zw; + uv = rect_icon.zw; + mask_coord_interp = vec2(1, 1); + } + else { + co = rect_geom.zy; + uv = rect_icon.zy; + mask_coord_interp = vec2(1, 0); + } + + /* Put origin in lower right corner. */ + mask_coord_interp.x -= 1; + + gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f); + texCoord_interp = uv; +} diff --git a/source/blender/gpu/shaders/infos/gpu_interface_info.hh b/source/blender/gpu/shaders/infos/gpu_interface_info.hh index d77c65e48a7..060def16f81 100644 --- a/source/blender/gpu/shaders/infos/gpu_interface_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_interface_info.hh @@ -18,3 +18,6 @@ GPU_SHADER_INTERFACE_INFO(smooth_radii_outline_iface, "").smooth(Type::VEC4, "ra GPU_SHADER_INTERFACE_INFO(flat_color_smooth_tex_coord_interp_iface, "") .flat(Type::VEC4, "finalColor") .smooth(Type::VEC2, "texCoord_interp"); +GPU_SHADER_INTERFACE_INFO(smooth_icon_interp_iface, "") + .smooth(Type::VEC2, "texCoord_interp") + .smooth(Type::VEC2, "mask_coord_interp"); diff --git a/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh new file mode 100644 index 00000000000..3d4077bdb09 --- /dev/null +++ b/source/blender/gpu/shaders/infos/gpu_shader_icon_info.hh @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "gpu_interface_info.hh" +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(gpu_shader_icon) + .vertex_out(smooth_icon_interp_iface) + .fragment_out(0, Type::VEC4, "fragColor") + .push_constant(Type::MAT4, "ModelViewProjectionMatrix") + .push_constant(Type::VEC4, "color") + .push_constant(Type::VEC4, "rect_icon") + .push_constant(Type::VEC4, "rect_geom") + .push_constant(Type::FLOAT, "text_width") + .sampler(0, ImageType::FLOAT_2D, "image") + .vertex_source("gpu_shader_icon_vert.glsl") + .fragment_source("gpu_shader_icon_frag.glsl") + .do_static_compilation(true); diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc index 0896daec561..fb63abed9e9 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.cc +++ b/source/blender/windowmanager/intern/wm_dragdrop.cc @@ -853,7 +853,8 @@ static void wm_drag_draw_icon(bContext * /*C*/, wmWindow * /*win*/, wmDrag *drag y = xy[1] - 2 * UI_DPI_FAC; const uchar text_col[] = {255, 255, 255, 255}; - UI_icon_draw_ex(x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false); + UI_icon_draw_ex( + x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false, UI_NO_ICON_OVERLAY_TEXT); } } -- cgit v1.2.3 From 8415bc9c80aad878f7b85a48ffd2ae55150f9dc4 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 16:54:19 +0200 Subject: Fix T101554: disable viewer node when corresponding modifier is disabled --- source/blender/editors/util/ed_viewer_path.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index 5c03367cba8..4da1559b726 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -249,6 +249,9 @@ bool is_active_geometry_nodes_viewer(const bContext &C, if (md->type != eModifierType_Nodes) { return false; } + if ((md->mode & eModifierMode_Realtime) == 0) { + return false; + } modifier = reinterpret_cast(md); break; } -- cgit v1.2.3 From 3bac6f17f1c197d69387e45d0ca8a5f77e8274ac Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 20 Oct 2022 17:04:49 +0200 Subject: install_deps: Update Python, OIIO, openPGL and FFMPEG versions. Update libraries for Blender 3.4, according to T101403: * python: 3.10.8 * OIIO: 2.3.20.0 * OpenPGL: 0.4.0-beta * FFMpeg: 5.1.2 --- build_files/build_environment/install_deps.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index f913ac5e73c..ef72ad5b40b 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -394,7 +394,7 @@ CLANG_FORMAT_VERSION="10.0" CLANG_FORMAT_VERSION_MIN="6.0" CLANG_FORMAT_VERSION_MEX="14.0" -PYTHON_VERSION="3.10.2" +PYTHON_VERSION="3.10.8" PYTHON_VERSION_SHORT="3.10" PYTHON_VERSION_MIN="3.10" PYTHON_VERSION_MEX="3.12" @@ -505,7 +505,7 @@ OPENEXR_FORCE_REBUILD=false OPENEXR_SKIP=false _with_built_openexr=false -OIIO_VERSION="2.3.13.0" +OIIO_VERSION="2.3.20.0" OIIO_VERSION_SHORT="2.3" OIIO_VERSION_MIN="2.1.12" OIIO_VERSION_MEX="2.4.0" @@ -602,10 +602,10 @@ LEVEL_ZERO_FORCE_BUILD=false LEVEL_ZERO_FORCE_REBUILD=false LEVEL_ZERO_SKIP=false -OPENPGL_VERSION="0.3.1" -OPENPGL_VERSION_SHORT="0.3" +OPENPGL_VERSION="0.4.0" +OPENPGL_VERSION_SHORT="0.4" OPENPGL_VERSION_MIN="0.3.1" -OPENPGL_VERSION_MEX="0.3.2" +OPENPGL_VERSION_MEX="0.5" OPENPGL_FORCE_BUILD=false OPENPGL_FORCE_REBUILD=false OPENPGL_SKIP=false @@ -618,8 +618,8 @@ XR_OPENXR_FORCE_BUILD=false XR_OPENXR_FORCE_REBUILD=false XR_OPENXR_SKIP=false -FFMPEG_VERSION="5.0" -FFMPEG_VERSION_SHORT="5.0" +FFMPEG_VERSION="5.1.2" +FFMPEG_VERSION_SHORT="5.1" FFMPEG_VERSION_MIN="4.0" FFMPEG_VERSION_MEX="6.0" FFMPEG_FORCE_BUILD=false -- cgit v1.2.3 From 4b30ee773ce7f5e423830195e49ca06763ba230a Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 17:34:22 +0200 Subject: Fix T101316: workbench texture mode not working with geometry nodes The `ED_object_get_active_image` is used from the renderer which deals with evaluated objects. This means the material api for evaluated objects has to be used. --- source/blender/editors/uvedit/uvedit_ops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 5e2d9097abd..b65f4889347 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -37,6 +37,7 @@ #include "BKE_node.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "ED_image.h" #include "ED_mesh.h" @@ -113,7 +114,8 @@ bool ED_object_get_active_image(Object *ob, bNode **r_node, bNodeTree **r_ntree) { - Material *ma = BKE_object_material_get(ob, mat_nr); + Material *ma = DEG_is_evaluated_object(ob) ? BKE_object_material_get_eval(ob, mat_nr) : + BKE_object_material_get(ob, mat_nr); bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : NULL; bNode *node = (ntree) ? nodeGetActiveTexture(ntree) : NULL; -- cgit v1.2.3 From 24fd8f729a58b18159912a84525b910b0d4e7ef5 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Thu, 20 Oct 2022 17:54:29 +0200 Subject: Fix memory leak when proxy building fails Leak introduced in recent fix - bf8d4a9bc6fb28. --- source/blender/imbuf/intern/indexer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index e8e4b80ef45..eaa72441fb6 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -909,6 +909,9 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, if (context->proxy_ctx[0] == NULL && context->proxy_ctx[1] == NULL && context->proxy_ctx[2] == NULL && context->proxy_ctx[3] == NULL) { + avformat_close_input(&context->iFormatCtx); + avcodec_free_context(&context->iCodecCtx); + MEM_freeN(context); return NULL; /* Nothing to transcode. */ } -- cgit v1.2.3 From 5e0e5b13410350166553256272311774acd5aaa4 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Oct 2022 18:01:44 +0200 Subject: Fix T101215: Distribute Points in Volume node does not refresh on frame change --- .../blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc index 091337c28cf..3a021bfe2d7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc @@ -208,6 +208,7 @@ static void geo_node_distribute_points_in_volume_exec(GeoNodeExecParams params) } const VolumeComponent *component = geometry_set.get_component_for_read(); const Volume *volume = component->get_for_read(); + BKE_volume_load(volume, DEG_get_bmain(params.depsgraph())); Vector positions; -- cgit v1.2.3 From 8c361d6f66cf4d87f5fd220ff056ea563a7d8e07 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 11:46:42 -0600 Subject: deps_builder: fix missing png harvest on windows --- build_files/build_environment/cmake/png.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake index 890be673cb8..371f2608e2a 100644 --- a/build_files/build_environment/cmake/png.cmake +++ b/build_files/build_environment/cmake/png.cmake @@ -24,6 +24,14 @@ add_dependencies( external_zlib ) +if(WIN32 AND BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_png after_install + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static${LIBEXT} ${HARVEST_TARGET}/png/lib/libpng${LIBEXT} + DEPENDEES install + ) +endif() + if(WIN32 AND BUILD_MODE STREQUAL Debug) ExternalProject_Add_Step(external_png after_install COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_staticd${LIBEXT} ${LIBDIR}/png/lib/libpng16${LIBEXT} -- cgit v1.2.3 From bd1ff201b1dfb7bd382ed19079bcebddfc5e30d4 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 20 Oct 2022 21:06:44 +0200 Subject: Buildfix for 078e034 missing include --- .../nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc index 3a021bfe2d7..95173bd23a5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_in_volume.cc @@ -15,6 +15,8 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "DEG_depsgraph_query.h" + #include "node_geometry_util.hh" namespace blender::nodes { -- cgit v1.2.3 From 97f4e076c7fcd362c9803dcf1afb303c110c997e Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 20 Oct 2022 17:23:37 -0500 Subject: Fix: USD & Alembic importers might not initialize material indices f1c0249f34c4171ec incorrectly assumed that the importer functions that assigned material indices set all of the values, but that isn't true for all files. --- source/blender/io/alembic/intern/abc_reader_mesh.cc | 6 +++--- source/blender/io/usd/intern/usd_reader_mesh.cc | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index f08514dc45c..2531bd62609 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -763,7 +763,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, std::map mat_map; bke::MutableAttributeAccessor attributes = new_mesh->attributes_for_write(); bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + attributes.lookup_or_add_for_write_span("material_index", ATTR_DOMAIN_FACE); assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map); material_indices.finish(); } @@ -823,8 +823,8 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const ISampleSel { std::map mat_map; bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); - bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + bke::SpanAttributeWriter material_indices = attributes.lookup_or_add_for_write_span( + "material_index", ATTR_DOMAIN_FACE); assign_facesets_to_material_indices(sample_sel, material_indices.span, mat_map); material_indices.finish(); utils::assign_materials(bmain, m_object, mat_map); diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 77c79852141..01db6baeb5c 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -804,8 +804,8 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot std::map mat_map; bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); - bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + bke::SpanAttributeWriter material_indices = attributes.lookup_or_add_for_write_span( + "material_index", ATTR_DOMAIN_FACE); this->assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map); material_indices.finish(); /* Build material name map if it's not built yet. */ @@ -914,7 +914,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, std::map mat_map; bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write(); bke::SpanAttributeWriter material_indices = - attributes.lookup_or_add_for_write_only_span("material_index", ATTR_DOMAIN_FACE); + attributes.lookup_or_add_for_write_span("material_index", ATTR_DOMAIN_FACE); assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map); material_indices.finish(); } -- cgit v1.2.3 From ff8c0f062a6ac521b13ebbda3103cda4f9a4dc46 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 21 Oct 2022 10:00:09 +1100 Subject: GHOST/Wayland: code comments, minor improvements - Clarify how data_offer is used for both the clipboard & drag-and-drop. - Acquire the clipboards mutex lock before freeing. - Log a warning when creating a pipe fails. - Add doxy-sections. --- intern/ghost/intern/GHOST_SystemWayland.cpp | 203 ++++++++++++++++++---------- 1 file changed, 132 insertions(+), 71 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index fb69973eac6..68ad028631c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -234,7 +234,7 @@ static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = { /** \} */ /* -------------------------------------------------------------------- */ -/** \name Private Types & Defines +/** \name Internal #GWL_SimpleBuffer Type * \{ */ struct GWL_SimpleBuffer { @@ -250,7 +250,9 @@ static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer) buffer->data_size = 0; } -static void gwl_simple_buffer_set(GWL_SimpleBuffer *buffer, const char *data, size_t data_size) +static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer, + const char *data, + size_t data_size) { free(const_cast(buffer->data)); buffer->data = data; @@ -274,6 +276,12 @@ static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer) return buffer_str; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_Cursor Type + * \{ */ + /** * From XKB internals, use for converting a scan-code from WAYLAND to a #xkb_keycode_t. * Ideally this wouldn't need a local define. @@ -289,16 +297,26 @@ struct GWL_Cursor { * the hardware cursor is used. */ bool is_hardware = true; + /** When true, a custom image is used to display the cursor (stored in `wl_image`). */ bool is_custom = false; struct wl_surface *wl_surface = nullptr; struct wl_buffer *wl_buffer = nullptr; struct wl_cursor_image wl_image = {0}; struct wl_cursor_theme *wl_theme = nullptr; void *custom_data = nullptr; + /** The size of `custom_data` in bytes. */ size_t custom_data_size = 0; - int size = 0; + /** + * The name of the theme (loaded by DBUS, depends on #WITH_GHOST_WAYLAND_DBUS). + * When disabled, leave as an empty string and the default theme will be used. + */ std::string theme_name; - + /** + * The size of the cursor (when looking up a cursor theme). + * This must be scaled by the maximum output scale when passing to wl_cursor_theme_load. + * See #update_cursor_scale. + * */ + int theme_size = 0; int custom_scale = 1; }; @@ -309,6 +327,7 @@ struct GWL_Cursor { */ struct GWL_TabletTool { struct GWL_Seat *seat = nullptr; + /** Tablets have a separate cursor to the 'pointer', this surface is used for cursor drawing. */ struct wl_surface *wl_surface_cursor = nullptr; /** Used to delay clearing tablet focused wl_surface until the frame is handled. */ bool proximity = false; @@ -316,23 +335,51 @@ struct GWL_TabletTool { GHOST_TabletData data = GHOST_TABLET_DATA_NONE; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_DataOffer Type + * \{ */ + +/** + * Data storage used for clipboard paste & drag-and-drop. + */ struct GWL_DataOffer { - std::unordered_set types; - uint32_t source_actions = 0; - uint32_t dnd_action = 0; struct wl_data_offer *id = nullptr; + std::unordered_set types; std::atomic in_use = false; + struct { + /** + * Bit-mask with available drop options. + * #WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, #WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE.. etc. + * The application that initializes the drag may set these depending on modifiers held + * \note when dragging begins. Currently ghost doesn't make use of these. + */ + enum wl_data_device_manager_dnd_action source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; + enum wl_data_device_manager_dnd_action action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; /** Compatible with #GWL_Seat.xy coordinates. */ wl_fixed_t xy[2] = {0, 0}; } dnd; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_DataSource Type + * \{ */ + struct GWL_DataSource { - struct wl_data_source *wl_data_source = nullptr; + struct wl_data_source *wl_source = nullptr; GWL_SimpleBuffer buffer_out; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_Seat Type (#wl_seat wrapper & associated types) + * \{ */ + /** * Data used to implement client-side key-repeat. * @@ -605,6 +652,12 @@ struct GWL_Seat { uint32_t data_source_serial = 0; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal #GWL_Display Type (#wl_display & #wl_compositor wrapper) + * \{ */ + struct GWL_Display { GHOST_SystemWayland *system = nullptr; @@ -633,8 +686,6 @@ struct GWL_Display { GWL_SimpleBuffer clipboard_primary; }; -#undef LOG - /** \} */ /* -------------------------------------------------------------------- */ @@ -710,8 +761,8 @@ static void display_destroy(GWL_Display *display) std::lock_guard lock{seat->data_source_mutex}; if (seat->data_source) { gwl_simple_buffer_free_data(&seat->data_source->buffer_out); - if (seat->data_source->wl_data_source) { - wl_data_source_destroy(seat->data_source->wl_data_source); + if (seat->data_source->wl_source) { + wl_data_source_destroy(seat->data_source->wl_source); } delete seat->data_source; } @@ -833,8 +884,11 @@ static void display_destroy(GWL_Display *display) wl_display_disconnect(display->wl_display); } - gwl_simple_buffer_free_data(&display->clipboard); - gwl_simple_buffer_free_data(&display->clipboard_primary); + { + std::lock_guard lock{system_clipboard_mutex}; + gwl_simple_buffer_free_data(&display->clipboard); + gwl_simple_buffer_free_data(&display->clipboard_primary); + } delete display; } @@ -1399,16 +1453,17 @@ static const char *read_file_as_buffer(const int fd, size_t *r_len) return buf; } -static const char *read_pipe(GWL_DataOffer *data_offer, - const std::string mime_receive, - std::mutex *mutex, - size_t *r_len) +static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { - return {}; + CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + return nullptr; } - wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]); close(pipefd[1]); data_offer->in_use.store(false); @@ -1423,16 +1478,18 @@ static const char *read_pipe(GWL_DataOffer *data_offer, return buf; } -static const char *read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer, - const std::string mime_receive, - std::mutex *mutex, - size_t *r_len) +static const char *read_buffer_from_primary_selection_offer( + GWL_PrimarySelection_DataOffer *data_offer, + const char *mime_receive, + std::mutex *mutex, + size_t *r_len) { int pipefd[2]; if (UNLIKELY(pipe(pipefd) != 0)) { - return {}; + CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno)); + return nullptr; } - zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive.c_str(), pipefd[1]); + zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]); close(pipefd[1]); data_offer->in_use.store(false); @@ -1481,8 +1538,8 @@ static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_d CLOG_INFO(LOG, 2, "cancelled"); GWL_Seat *seat = static_cast(data); GWL_DataSource *data_source = seat->data_source; - if (seat->data_source->wl_data_source == wl_data_source) { - data_source->wl_data_source = nullptr; + if (seat->data_source->wl_source == wl_data_source) { + data_source->wl_source = nullptr; } wl_data_source_destroy(wl_data_source); @@ -1553,7 +1610,8 @@ static void data_offer_handle_offer(void *data, const char *mime_type) { CLOG_INFO(LOG, 2, "offer (mime_type=%s)", mime_type); - static_cast(data)->types.insert(mime_type); + GWL_DataOffer *data_offer = static_cast(data); + data_offer->types.insert(mime_type); } static void data_offer_handle_source_actions(void *data, @@ -1561,7 +1619,8 @@ static void data_offer_handle_source_actions(void *data, const uint32_t source_actions) { CLOG_INFO(LOG, 2, "source_actions (%u)", source_actions); - static_cast(data)->source_actions = source_actions; + GWL_DataOffer *data_offer = static_cast(data); + data_offer->dnd.source_actions = (enum wl_data_device_manager_dnd_action)source_actions; } static void data_offer_handle_action(void *data, @@ -1569,7 +1628,8 @@ static void data_offer_handle_action(void *data, const uint32_t dnd_action) { CLOG_INFO(LOG, 2, "actions (%u)", dnd_action); - static_cast(data)->dnd_action = dnd_action; + GWL_DataOffer *data_offer = static_cast(data); + data_offer->dnd.action = (enum wl_data_device_manager_dnd_action)dnd_action; } static const struct wl_data_offer_listener data_offer_listener = { @@ -1693,7 +1753,8 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)}; size_t data_buf_len = 0; - const char *data_buf = read_pipe(data_offer, mime_receive, nullptr, &data_buf_len); + const char *data_buf = read_buffer_from_data_offer( + data_offer, mime_receive.c_str(), nullptr, &data_buf_len); std::string data = data_buf ? std::string(data_buf, data_buf_len) : ""; free(const_cast(data_buf)); @@ -1812,13 +1873,13 @@ static void data_device_handle_selection(void *data, } size_t data_len = 0; - const char *data = read_pipe( - data_offer, mime_receive, &seat->data_offer_copy_paste_mutex, &data_len); + const char *data = read_buffer_from_data_offer( + data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; GWL_SimpleBuffer *buf = system->clipboard_data(false); - gwl_simple_buffer_set(buf, data, data_len); + gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); } }; @@ -1892,7 +1953,8 @@ static bool update_cursor_scale(GWL_Cursor &cursor, wl_surface_set_buffer_scale(wl_cursor_surface, scale); } wl_cursor_theme_destroy(cursor.wl_theme); - cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm); + cursor.wl_theme = wl_cursor_theme_load( + cursor.theme_name.c_str(), scale * cursor.theme_size, shm); return true; } return false; @@ -3165,13 +3227,13 @@ static void primary_selection_device_handle_selection( } } size_t data_len = 0; - const char *data = read_pipe_primary( - data_offer, mime_receive, &primary->data_offer_mutex, &data_len); + const char *data = read_buffer_from_primary_selection_offer( + data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len); { std::lock_guard lock{system_clipboard_mutex}; GWL_SimpleBuffer *buf = system->clipboard_data(true); - gwl_simple_buffer_set(buf, data, data_len); + gwl_simple_buffer_set_and_take_ownership(buf, data, data_len); } }; @@ -3262,9 +3324,9 @@ static void seat_handle_capabilities(void *data, seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); seat->cursor.visible = true; seat->cursor.wl_buffer = nullptr; - if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.size)) { + if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) { seat->cursor.theme_name = std::string(); - seat->cursor.size = default_cursor_size; + seat->cursor.theme_size = default_cursor_size; } wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data); @@ -3990,18 +4052,17 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) /* Copy buffer. */ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); - data_source->wl_data_source = wl_data_device_manager_create_data_source( - display->data_device_manager); + data_source->wl_source = wl_data_device_manager_create_data_source(display->data_device_manager); - wl_data_source_add_listener(data_source->wl_data_source, &data_source_listener, seat); + wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat); for (const std::string &type : mime_send) { - wl_data_source_offer(data_source->wl_data_source, type.c_str()); + wl_data_source_offer(data_source->wl_source, type.c_str()); } if (seat->data_device) { wl_data_device_set_selection( - seat->data_device, data_source->wl_data_source, seat->data_source_serial); + seat->data_device, data_source->wl_source, seat->data_source_serial); } } @@ -4284,22 +4345,22 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, */ static void cursor_buffer_show(const GWL_Seat *seat) { - const GWL_Cursor *c = &seat->cursor; + const GWL_Cursor *cursor = &seat->cursor; if (seat->wl_pointer) { - const int scale = c->is_custom ? c->custom_scale : seat->pointer.theme_scale; - const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; - const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + const int scale = cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale; + const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale; if (seat->wl_pointer) { wl_pointer_set_cursor( - seat->wl_pointer, seat->pointer.serial, c->wl_surface, hotspot_x, hotspot_y); + seat->wl_pointer, seat->pointer.serial, cursor->wl_surface, hotspot_x, hotspot_y); } } if (!seat->tablet_tools.empty()) { - const int scale = c->is_custom ? c->custom_scale : seat->tablet.theme_scale; - const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale; - const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale; + const int scale = cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale; + const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale; + const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale; for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) { GWL_TabletTool *tablet_tool = static_cast( zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2)); @@ -4362,21 +4423,21 @@ static void cursor_buffer_set_surface_impl(const GWL_Seat *seat, static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer) { - const GWL_Cursor *c = &seat->cursor; + const GWL_Cursor *cursor = &seat->cursor; const wl_cursor_image *wl_image = &seat->cursor.wl_image; - const bool visible = (c->visible && c->is_hardware); + const bool visible = (cursor->visible && cursor->is_hardware); /* This is a requirement of WAYLAND, when this isn't the case, * it causes Blender's window to close intermittently. */ if (seat->wl_pointer) { const int scale = cursor_buffer_compatible_scale_from_image( - wl_image, c->is_custom ? c->custom_scale : seat->pointer.theme_scale); + wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale); const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale; const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale; - cursor_buffer_set_surface_impl(seat, buffer, c->wl_surface, scale); + cursor_buffer_set_surface_impl(seat, buffer, cursor->wl_surface, scale); wl_pointer_set_cursor(seat->wl_pointer, seat->pointer.serial, - visible ? c->wl_surface : nullptr, + visible ? cursor->wl_surface : nullptr, hotspot_x, hotspot_y); } @@ -4384,7 +4445,7 @@ static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer) /* Set the cursor for all tablet tools as well. */ if (!seat->tablet_tools.empty()) { const int scale = cursor_buffer_compatible_scale_from_image( - wl_image, c->is_custom ? c->custom_scale : seat->tablet.theme_scale); + wl_image, cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale); const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale; const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale; for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) { @@ -4471,31 +4532,31 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s (*cursor_find).second; GWL_Seat *seat = display_->seats[0]; - GWL_Cursor *c = &seat->cursor; + GWL_Cursor *cursor = &seat->cursor; - if (!c->wl_theme) { + if (!cursor->wl_theme) { /* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */ - c->wl_theme = wl_cursor_theme_load( - c->theme_name.c_str(), c->size, display_->seats[0]->system->wl_shm()); + cursor->wl_theme = wl_cursor_theme_load( + cursor->theme_name.c_str(), cursor->theme_size, wl_shm()); } - wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name); + wl_cursor *wl_cursor = wl_cursor_theme_get_cursor(cursor->wl_theme, cursor_name); - if (!cursor) { + if (!wl_cursor) { GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl); return GHOST_kFailure; } - struct wl_cursor_image *image = cursor->images[0]; + struct wl_cursor_image *image = wl_cursor->images[0]; struct wl_buffer *buffer = wl_cursor_image_get_buffer(image); if (!buffer) { return GHOST_kFailure; } - c->visible = true; - c->is_custom = false; - c->wl_buffer = buffer; - c->wl_image = *image; + cursor->visible = true; + cursor->is_custom = false; + cursor->wl_buffer = buffer; + cursor->wl_image = *image; cursor_buffer_set(seat, buffer); -- cgit v1.2.3 From 65151779811bb68f9afa0fb5d3dfacbd9fd3d6cb Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 18:29:59 -0600 Subject: deps_builder: OpenCollada fixes for windows - build and use our version of libxml - the cli tools had a linker error due to it trying to link a shared version of libxml, disabled both and zlib 1.2.3 with a patch since we do not want/need them for blender. - postfix the libraries with _d for debug automatically so we don't have to fix that during the harvest. due to this only being windows changes no rebuild needed for the other platforms. --- build_files/build_environment/CMakeLists.txt | 3 +- .../build_environment/cmake/opencollada.cmake | 33 ++++++----- build_files/build_environment/cmake/xml2.cmake | 64 ++++++++++++++++------ .../build_environment/patches/opencollada.diff | 25 +++++++++ 4 files changed, 89 insertions(+), 36 deletions(-) diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index 4f40f44ad18..023d113b551 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -97,6 +97,8 @@ include(cmake/embree.cmake) include(cmake/openpgl.cmake) include(cmake/fmt.cmake) include(cmake/robinmap.cmake) +include(cmake/xml2.cmake) + if(NOT APPLE) include(cmake/xr_openxr.cmake) if(NOT WIN32 OR BUILD_MODE STREQUAL Release) @@ -149,7 +151,6 @@ if(NOT WIN32 OR ENABLE_MINGW64) endif() if(UNIX) include(cmake/flac.cmake) - include(cmake/xml2.cmake) if(NOT APPLE) include(cmake/spnav.cmake) include(cmake/jemalloc.cmake) diff --git a/build_files/build_environment/cmake/opencollada.cmake b/build_files/build_environment/cmake/opencollada.cmake index b2ae1a1a351..9473aafbe88 100644 --- a/build_files/build_environment/cmake/opencollada.cmake +++ b/build_files/build_environment/cmake/opencollada.cmake @@ -4,6 +4,16 @@ if(UNIX) set(OPENCOLLADA_EXTRA_ARGS -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2 -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2.a) +else() + set(OPENCOLLADA_EXTRA_ARGS + -DCMAKE_DEBUG_POSTFIX=_d + -DLIBXML2_INCLUDE_DIR=${LIBDIR}/xml2/include/libxml2 + ) + if(BUILD_MODE STREQUAL Release) + list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2s.lib) + else() + list(APPEND OPENCOLLADA_EXTRA_ARGS -DLIBXML2_LIBRARIES=${LIBDIR}/xml2/lib/libxml2sd.lib) + endif() endif() ExternalProject_Add(external_opencollada @@ -16,12 +26,11 @@ ExternalProject_Add(external_opencollada INSTALL_DIR ${LIBDIR}/opencollada ) -if(UNIX) - add_dependencies( - external_opencollada - external_xml2 - ) -endif() + +add_dependencies( + external_opencollada + external_xml2 +) if(WIN32) if(BUILD_MODE STREQUAL Release) @@ -32,17 +41,7 @@ if(WIN32) endif() if(BUILD_MODE STREQUAL Debug) ExternalProject_Add_Step(external_opencollada after_install - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/buffer.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/buffer_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/ftoa.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/ftoa_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/GeneratedSaxParser.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/GeneratedSaxParser_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/MathMLSolver.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/MathMLSolver_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADABaseUtils.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADABaseUtils_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAFramework.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAFramework_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADASaxFrameworkLoader_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/OpenCOLLADAStreamWriter_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/pcre.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/pcre_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/UTF.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/UTF_d.lib - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/opencollada/lib/opencollada/xml.lib ${HARVEST_TARGET}/opencollada/lib/opencollada/xml_d.lib + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/opencollada/lib ${HARVEST_TARGET}/opencollada/lib DEPENDEES install ) endif() diff --git a/build_files/build_environment/cmake/xml2.cmake b/build_files/build_environment/cmake/xml2.cmake index cd24fd836b0..3d31ec131bb 100644 --- a/build_files/build_environment/cmake/xml2.cmake +++ b/build_files/build_environment/cmake/xml2.cmake @@ -1,20 +1,48 @@ # SPDX-License-Identifier: GPL-2.0-or-later -ExternalProject_Add(external_xml2 - URL file://${PACKAGE_DIR}/${XML2_FILE} - DOWNLOAD_DIR ${DOWNLOAD_DIR} - URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH} - PREFIX ${BUILD_DIR}/xml2 - CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND} - --prefix=${LIBDIR}/xml2 - --disable-shared - --enable-static - --with-pic - --with-python=no - --with-lzma=no - --with-zlib=no - --with-iconv=no - BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS} - INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install - INSTALL_DIR ${LIBDIR}/xml2 -) +if(WIN32) + set(XML2_EXTRA_ARGS + -DLIBXML2_WITH_ZLIB=OFF + -DLIBXML2_WITH_LZMA=OFF + -DLIBXML2_WITH_PYTHON=OFF + -DLIBXML2_WITH_ICONV=OFF + -DLIBXML2_WITH_TESTS=OFF + -DLIBXML2_WITH_PROGRAMS=OFF + -DBUILD_SHARED_LIBS=OFF + ) + ExternalProject_Add(external_xml2 + URL file://${PACKAGE_DIR}/${XML2_FILE} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH} + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/xml2 ${DEFAULT_CMAKE_FLAGS} ${XML2_EXTRA_ARGS} + PREFIX ${BUILD_DIR}/xml2 + INSTALL_DIR ${LIBDIR}/xml2 + ) +else() + ExternalProject_Add(external_xml2 + URL file://${PACKAGE_DIR}/${XML2_FILE} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH ${XML2_HASH_TYPE}=${XML2_HASH} + PREFIX ${BUILD_DIR}/xml2 + CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && ${CONFIGURE_COMMAND} + --prefix=${LIBDIR}/xml2 + --disable-shared + --enable-static + --with-pic + --with-python=no + --with-lzma=no + --with-zlib=no + --with-iconv=no + BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make -j${MAKE_THREADS} + INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/xml2/src/external_xml2/ && make install + INSTALL_DIR ${LIBDIR}/xml2 + ) +endif() + +if(WIN32 AND BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_xml2 after_install + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/xml2/include ${HARVEST_TARGET}/xml2/include + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/xml2/lib/libxml2s.lib ${HARVEST_TARGET}/xml2/lib/libxml2s.lib + DEPENDEES install + ) +endif() diff --git a/build_files/build_environment/patches/opencollada.diff b/build_files/build_environment/patches/opencollada.diff index e8efc1a6909..02eab251a13 100644 --- a/build_files/build_environment/patches/opencollada.diff +++ b/build_files/build_environment/patches/opencollada.diff @@ -130,3 +130,28 @@ index 715d903..24423ce 100644 { string id = node.attribute("id").value(); size_t line = node.line(); +diff -Naur a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -274,7 +274,7 @@ + add_subdirectory(${EXTERNAL_LIBRARIES}/UTF) + add_subdirectory(common/libBuffer) + add_subdirectory(${EXTERNAL_LIBRARIES}/MathMLSolver) +-add_subdirectory(${EXTERNAL_LIBRARIES}/zlib) ++#add_subdirectory(${EXTERNAL_LIBRARIES}/zlib) + + # building OpenCOLLADA libs + add_subdirectory(COLLADABaseUtils) +@@ -284,10 +284,10 @@ + add_subdirectory(COLLADAStreamWriter) + + # building COLLADAValidator app +-add_subdirectory(COLLADAValidator) ++#add_subdirectory(COLLADAValidator) + + # DAE validator app +-add_subdirectory(DAEValidator) ++#add_subdirectory(DAEValidator) + + # Library export + install(EXPORT LibraryExport DESTINATION ${OPENCOLLADA_INST_CMAKECONFIG} FILE OpenCOLLADATargets.cmake) -- cgit v1.2.3 From dc09cc13ea49a0de72aafcb8a48d6189d13aa6d9 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Thu, 20 Oct 2022 18:31:15 -0600 Subject: deps_builder: add missing OSLNoise library on windows OSLNoise is a new library, was missing in the debug configuration on windows. --- build_files/build_environment/cmake/osl.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/build_files/build_environment/cmake/osl.cmake b/build_files/build_environment/cmake/osl.cmake index 8bac2c5c1ab..a5d000e4f44 100644 --- a/build_files/build_environment/cmake/osl.cmake +++ b/build_files/build_environment/cmake/osl.cmake @@ -83,6 +83,7 @@ if(WIN32) COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslcomp.lib ${HARVEST_TARGET}/osl/lib/oslcomp_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslexec.lib ${HARVEST_TARGET}/osl/lib/oslexec_d.lib COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslquery.lib ${HARVEST_TARGET}/osl/lib/oslquery_d.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/osl/lib/oslnoise.lib ${HARVEST_TARGET}/osl/lib/oslnoise_d.lib DEPENDEES install ) endif() -- cgit v1.2.3 From a0bbd65d57f38344fb71565c3c34396363a4be23 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 21 Oct 2022 16:11:07 +1100 Subject: Fix T66713: Walk mode doesn't take scene unit scale into account When changing a scene's unit scale from 1 to something else, 0.1 for e.g. walk navigation no longer worked properly. Whenever gravity is enabled, and the user starts to fall or jump, the view-port glitched out into low earth orbit. Reviewed By: campbellbarton Ref D16277 --- source/blender/editors/space_view3d/view3d_navigate_walk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index aea322d73d9..fcb4f549353 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -1231,11 +1231,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) /* keep moving if we were moving */ copy_v2_v2(dvec, walk->teleport.direction); - z_cur = walk->rv3d->viewinv[3][2]; - z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid; + z_cur = walk->rv3d->viewinv[3][2] / walk->grid; + z_new = (walk->teleport.origin[2] / walk->grid) - getFreeFallDistance(walk->gravity, t); /* jump */ - z_new += t * walk->speed_jump * walk->grid; + z_new += t * walk->speed_jump; /* duration is the jump duration */ if (t > walk->teleport.duration) { -- cgit v1.2.3 From 5814e35af115413d27dc6c777230452171ad19bd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 21 Oct 2022 08:50:08 +0200 Subject: install_deps: Update OSL for Blender 2.4 release. As requested by T101403, OSL version is now 1.12.6.2. --- build_files/build_environment/install_deps.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index ef72ad5b40b..5a191f7669b 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -523,8 +523,8 @@ LLVM_FORCE_REBUILD=false LLVM_SKIP=false # OSL needs to be compiled for now! -OSL_VERSION="1.11.17.0" -OSL_VERSION_SHORT="1.11" +OSL_VERSION="1.12.6.2" +OSL_VERSION_SHORT="1.12" OSL_VERSION_MIN="1.11" OSL_VERSION_MEX="2.0" OSL_FORCE_BUILD=false @@ -1139,7 +1139,7 @@ LLVM_SOURCE=( "$_LLVM_SOURCE_ROOT/llvm-$LLVM_VERSION.src.tar.xz" ) LLVM_CLANG_SOURCE=( "$_LLVM_SOURCE_ROOT/clang-$LLVM_VERSION.src.tar.xz" "$_LLVM_SOURCE_ROOT/cfe-$LLVM_VERSION.src.tar.xz" ) OSL_USE_REPO=false -OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/Release-$OSL_VERSION.tar.gz" ) +OSL_SOURCE=( "https://github.com/imageworks/OpenShadingLanguage/archive/v$OSL_VERSION.tar.gz" ) #~ OSL_SOURCE_REPO=( "https://github.com/imageworks/OpenShadingLanguage.git" ) #~ OSL_SOURCE_REPO_BRANCH="master" #~ OSL_SOURCE_REPO_UID="85179714e1bc69cd25ecb6bb711c1a156685d395" -- cgit v1.2.3 From 4bfb99e4d8f890a14cb2d1f584de11f0ac8bd1a7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 21 Oct 2022 12:19:54 +0200 Subject: Cycles: Bump versions of DPC++, IGC, and dependencies Patch by Xavier Hallade. Committing next to the actual libraries update in the svn. --- build_files/build_environment/cmake/versions.cmake | 44 +++++++++++----------- build_files/cmake/Modules/FindSYCL.cmake | 25 +++++++----- intern/cycles/device/CMakeLists.txt | 13 +++---- intern/cycles/kernel/CMakeLists.txt | 4 +- 4 files changed, 45 insertions(+), 41 deletions(-) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 5fa138ff01b..06a923e5c22 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -565,15 +565,15 @@ set(OPENPGL_HASH 1f090f88ab2bad028e8b3619aa926f4f97cf7b2c175b904704d2fec8593dd3c set(OPENPGL_HASH_TYPE SHA256) set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz) -set(LEVEL_ZERO_VERSION v1.7.15) +set(LEVEL_ZERO_VERSION v1.8.5) set(LEVEL_ZERO_URI https://github.com/oneapi-src/level-zero/archive/refs/tags/${LEVEL_ZERO_VERSION}.tar.gz) -set(LEVEL_ZERO_HASH c39bb05a8e5898aa6c444e1704105b93d3f1888b9c333f8e7e73825ffbfb2617) +set(LEVEL_ZERO_HASH b6e9663bbcc53c148d32376998298bec6f7c434ef2218c61fa708963e3a09394) set(LEVEL_ZERO_HASH_TYPE SHA256) set(LEVEL_ZERO_FILE level-zero-${LEVEL_ZERO_VERSION}.tar.gz) -set(DPCPP_VERSION 20220812) +set(DPCPP_VERSION 20221019) set(DPCPP_URI https://github.com/intel/llvm/archive/refs/tags/sycl-nightly/${DPCPP_VERSION}.tar.gz) -set(DPCPP_HASH 0e3c95346c295f5cf80f3a42d80b1c49481955898530242636ddc002627248d6) +set(DPCPP_HASH 2f533946e91ce3829431758ea17b0b834b960c1a796e9e4563c86e03eb9603a2) set(DPCPP_HASH_TYPE SHA256) set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz) @@ -586,9 +586,9 @@ set(DPCPP_FILE DPCPP-${DPCPP_VERSION}.tar.gz) # will take care of building them, unpack is being done in dpcpp_deps.cmake # Source llvm/lib/SYCLLowerIR/CMakeLists.txt -set(VCINTRINSICS_VERSION 984bb27baacce6ee5c716c2e64845f2a1928025b) +set(VCINTRINSICS_VERSION abce9184b7a3a7fe1b02289b9285610d9dc45465) set(VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/${VCINTRINSICS_VERSION}.tar.gz) -set(VCINTRINSICS_HASH abea415a15a0dd11fdc94dee8fb462910f2548311b787e02f42509789e1b0d7b) +set(VCINTRINSICS_HASH 3e9fd471246b87633b26f7e15e17ab7733d357458c53d5c5881c03929d6c551f) set(VCINTRINSICS_HASH_TYPE SHA256) set(VCINTRINSICS_FILE vc-intrinsics-${VCINTRINSICS_VERSION}.tar.gz) @@ -600,9 +600,9 @@ set(OPENCLHEADERS_HASH_TYPE SHA256) set(OPENCLHEADERS_FILE opencl_headers-${OPENCLHEADERS_VERSION}.tar.gz) # Source opencl/CMakeLists.txt -set(ICDLOADER_VERSION aec3952654832211636fc4af613710f80e203b0a) +set(ICDLOADER_VERSION 792682ad3d877ab38573b997808bab3b43902b70) set(ICDLOADER_URI https://github.com/KhronosGroup/OpenCL-ICD-Loader/archive/${ICDLOADER_VERSION}.tar.gz) -set(ICDLOADER_HASH e1880551d67bd8dc31d13de63b94bbfd6b1f315b6145dad1ffcd159b89bda93c) +set(ICDLOADER_HASH b33a0320d94bf300efa1da97931ded506d27813bd1148da6858fe79d412d1ea2) set(ICDLOADER_HASH_TYPE SHA256) set(ICDLOADER_FILE icdloader-${ICDLOADER_VERSION}.tar.gz) @@ -617,9 +617,9 @@ set(MP11_FILE mp11-${MP11_VERSION}.tar.gz) # Source llvm-spirv/CMakeLists.txt (repo) # Source llvm-spirv/spirv-headers-tag.conf (hash) -set(SPIRV_HEADERS_VERSION 36c0c1596225e728bd49abb7ef56a3953e7ed468) +set(SPIRV_HEADERS_VERSION 5a121866927a16ab9d49bed4788b532c7fcea766) set(SPIRV_HEADERS_URI https://github.com/KhronosGroup/SPIRV-Headers/archive/${SPIRV_HEADERS_VERSION}.tar.gz) -set(SPIRV_HEADERS_HASH 7a5c89633f8740456fe8adee052033e134476d267411d1336c0cb1e587a9229a) +set(SPIRV_HEADERS_HASH ec8ecb471a62672697846c436501638ab25447ae9d4a6761e0bfe8a9a839502a) set(SPIRV_HEADERS_HASH_TYPE SHA256) set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz) @@ -634,9 +634,9 @@ set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz) # compiler, the versions used are taken from the following location # https://github.com/intel/intel-graphics-compiler/releases -set(IGC_VERSION 1.0.11222) +set(IGC_VERSION 1.0.12149.1) set(IGC_URI https://github.com/intel/intel-graphics-compiler/archive/refs/tags/igc-${IGC_VERSION}.tar.gz) -set(IGC_HASH d92f0608dcbb52690855685f9447282e5c09c0ba98ae35fabf114fcf8b1e9fcf) +set(IGC_HASH 44f67f24e3bc5130f9f062533abf8154782a9d0a992bc19b498639a8521ae836) set(IGC_HASH_TYPE SHA256) set(IGC_FILE igc-${IGC_VERSION}.tar.gz) @@ -656,15 +656,15 @@ set(IGC_LLVM_FILE ${IGC_LLVM_VERSION}.tar.gz) # # WARNING WARNING WARNING -set(IGC_OPENCL_CLANG_VERSION bbdd1587f577397a105c900be114b56755d1f7dc) +set(IGC_OPENCL_CLANG_VERSION 363a5262d8c7cff3fb28f3bdb5d85c8d7e91c1bb) set(IGC_OPENCL_CLANG_URI https://github.com/intel/opencl-clang/archive/${IGC_OPENCL_CLANG_VERSION}.tar.gz) -set(IGC_OPENCL_CLANG_HASH d08315f1b0d8a6fef33de2b3e6aa7356534c324910634962c72523d970773efc) +set(IGC_OPENCL_CLANG_HASH aa8cf72bb239722ce8ce44f79413c6887ecc8ca18477dd520aa5c4809756da9a) set(IGC_OPENCL_CLANG_HASH_TYPE SHA256) set(IGC_OPENCL_CLANG_FILE opencl-clang-${IGC_OPENCL_CLANG_VERSION}.tar.gz) -set(IGC_VCINTRINSICS_VERSION v0.4.0) +set(IGC_VCINTRINSICS_VERSION v0.5.0) set(IGC_VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/refs/tags/${IGC_VCINTRINSICS_VERSION}.tar.gz) -set(IGC_VCINTRINSICS_HASH c8b92682ad5031cf9d5b82a40e7d5c0e763cd9278660adbcaa69aab988e4b589) +set(IGC_VCINTRINSICS_HASH 70bb47c5e32173cf61514941e83ae7c7eb4485e6d2fca60cfa1f50d4f42c41f2) set(IGC_VCINTRINSICS_HASH_TYPE SHA256) set(IGC_VCINTRINSICS_FILE vc-intrinsics-${IGC_VCINTRINSICS_VERSION}.tar.gz) @@ -680,9 +680,9 @@ set(IGC_SPIRV_TOOLS_HASH 6e19900e948944243024aedd0a201baf3854b377b9cc7a386553bc1 set(IGC_SPIRV_TOOLS_HASH_TYPE SHA256) set(IGC_SPIRV_TOOLS_FILE SPIR-V-Tools-${IGC_SPIRV_TOOLS_VERSION}.tar.gz) -set(IGC_SPIRV_TRANSLATOR_VERSION 99420daab98998a7e36858befac9c5ed109d4920) +set(IGC_SPIRV_TRANSLATOR_VERSION a31ffaeef77e23d500b3ea3d35e0c42ff5648ad9) set(IGC_SPIRV_TRANSLATOR_URI https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz) -set(IGC_SPIRV_TRANSLATOR_HASH 77dfb4ddb6bfb993535562c02ddea23f0a0d1c5a0258c1afe7e27c894ff783a8) +set(IGC_SPIRV_TRANSLATOR_HASH 9e26c96a45341b8f8af521bacea20e752623346340addd02af95d669f6e89252) set(IGC_SPIRV_TRANSLATOR_HASH_TYPE SHA256) set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz) @@ -690,15 +690,15 @@ set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}. ### Intel Graphics Compiler DEPS END ### ######################################## -set(GMMLIB_VERSION intel-gmmlib-22.1.2) +set(GMMLIB_VERSION intel-gmmlib-22.1.8) set(GMMLIB_URI https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz) -set(GMMLIB_HASH 3b9a6d5e7e3f5748b3d0a2fb0e980ae943907fece0980bd9c0508e71c838e334) +set(GMMLIB_HASH bf23e9a3742b4fb98c7666c9e9b29f3219e4b2fb4d831aaf4eed71f5e2d17368) set(GMMLIB_HASH_TYPE SHA256) set(GMMLIB_FILE ${GMMLIB_VERSION}.tar.gz) -set(OCLOC_VERSION 22.20.23198) +set(OCLOC_VERSION 22.38.24278) set(OCLOC_URI https://github.com/intel/compute-runtime/archive/refs/tags/${OCLOC_VERSION}.tar.gz) -set(OCLOC_HASH ab22b8bf2560a57fdd3def0e35a62ca75991406f959c0263abb00cd6cd9ae998) +set(OCLOC_HASH db0c542fccd651e6404b15a74d46027f1ce0eda8dc9e25a40cbb6c0faef257ee) set(OCLOC_HASH_TYPE SHA256) set(OCLOC_FILE ocloc-${OCLOC_VERSION}.tar.gz) diff --git a/build_files/cmake/Modules/FindSYCL.cmake b/build_files/cmake/Modules/FindSYCL.cmake index 139ebad46b1..7abf074fb7f 100644 --- a/build_files/cmake/Modules/FindSYCL.cmake +++ b/build_files/cmake/Modules/FindSYCL.cmake @@ -30,6 +30,7 @@ SET(_sycl_search_dirs # dpcpp binary. FIND_PROGRAM(SYCL_COMPILER NAMES + icpx dpcpp clang++ HINTS @@ -45,6 +46,7 @@ FIND_PROGRAM(SYCL_COMPILER if(NOT SYCL_COMPILER) FIND_PROGRAM(SYCL_COMPILER NAMES + icpx dpcpp HINTS ${_sycl_search_dirs} @@ -55,6 +57,8 @@ endif() FIND_LIBRARY(SYCL_LIBRARY NAMES + sycl7 + sycl6 sycl HINTS ${_sycl_search_dirs} @@ -63,20 +67,25 @@ FIND_LIBRARY(SYCL_LIBRARY ) if(WIN32) - string(REPLACE ".lib" "d.lib" SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY}) - set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY_DEBUG} CACHE FILEPATH "Path to SYCL debug library") -else() - set(SYCL_LIBRARY_DEBUG ${SYCL_LIBRARY} CACHE FILEPATH "Path to SYCL debug library") + FIND_LIBRARY(SYCL_LIBRARY_DEBUG + NAMES + sycl7d + sycl6d + sycld + HINTS + ${_sycl_search_dirs} + PATH_SUFFIXES + lib64 lib + ) endif() FIND_PATH(SYCL_INCLUDE_DIR NAMES - CL/sycl.hpp + sycl/sycl.hpp HINTS ${_sycl_search_dirs} PATH_SUFFIXES include - include/sycl ) INCLUDE(FindPackageHandleStandardArgs) @@ -84,13 +93,11 @@ INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL DEFAULT_MSG SYCL_LIBRARY SYCL_INCLUDE_DIR) IF(SYCL_FOUND) - get_filename_component(_SYCL_INCLUDE_PARENT_DIR ${SYCL_INCLUDE_DIR} DIRECTORY) - SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${_SYCL_INCLUDE_PARENT_DIR}) + SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl) ELSE() SET(SYCL_SYCL_FOUND FALSE) ENDIF() MARK_AS_ADVANCED( _SYCL_INCLUDE_PARENT_DIR - SYCL_LIBRARY_DEBUG ) diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 5516e97f34f..9c0de57f203 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -192,13 +192,12 @@ if (WITH_CYCLES_DEVICE_ONEAPI) else() set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi.so) endif() - list(APPEND LIB - ${cycles_kernel_oneapi_lib} - "$<$:${SYCL_LIBRARY_DEBUG}>" - "$<$:${SYCL_LIBRARY}>" - "$<$:${SYCL_LIBRARY}>" - "$<$:${SYCL_LIBRARY}>" - ) + list(APPEND LIB ${cycles_kernel_oneapi_lib}) + if(WIN32) + list(APPEND LIB debug ${SYCL_LIBRARY_DEBUG} optimized ${SYCL_LIBRARY}) + else() + list(APPEND LIB ${SYCL_LIBRARY}) + endif() add_definitions(-DWITH_ONEAPI) list(APPEND SRC ${SRC_ONEAPI} diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 6140e90042b..1e69d14b1b7 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -844,12 +844,10 @@ if(WITH_CYCLES_DEVICE_ONEAPI) set(sycl_compiler_flags_RelWithDebInfo ${sycl_compiler_flags}) set(sycl_compiler_flags_MinSizeRel ${sycl_compiler_flags}) list(APPEND sycl_compiler_flags_RelWithDebInfo -g) - get_filename_component(sycl_library_debug_name ${SYCL_LIBRARY_DEBUG} NAME_WE) list(APPEND sycl_compiler_flags_Debug -g -D_DEBUG - -nostdlib -Xclang --dependent-lib=msvcrtd - -Xclang --dependent-lib=${sycl_library_debug_name}) + -nostdlib -Xclang --dependent-lib=msvcrtd) add_custom_command( OUTPUT ${cycles_kernel_oneapi_lib} ${cycles_kernel_oneapi_linker_lib} -- cgit v1.2.3 From 26f181c6b7b28cd1d6f035a82e7a17d4424807eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Fri, 21 Oct 2022 13:11:31 +0200 Subject: EEVEE: Fix ill defined blend in cubemap array workaround This fixes some firefly issues on corners of the cubemaps where the blending factors would go above 1 or below 0. --- source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl index 90272400915..5af317b7398 100644 --- a/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/cubemap_lib.glsl @@ -96,7 +96,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod) /* Mix all colors to get the corner color. */ vec4 col3 = (col + col1 + col2) / 3.0; - vec2 mix_fac = uv_border * 0.5; + vec2 mix_fac = saturate(uv_border * 0.5); return mix(mix(col, col2, mix_fac.x), mix(col1, col3, mix_fac.x), mix_fac.y); } else if (any(border)) { @@ -108,7 +108,7 @@ vec4 cubemap_seamless(sampler2DArray tex, vec4 cubevec, float lod) uv = cubemap_face_coord(cubevec.xyz, face); coord = vec3(uv, cubevec.w * 6.0 + face); - float mix_fac = max(uv_border.x, uv_border.y) * 0.5; + float mix_fac = saturate(max(uv_border.x, uv_border.y) * 0.5); return mix(col, textureLod(tex, coord, lod), mix_fac); } else { -- cgit v1.2.3 From 899d4ddbd08cdb8130894c9de8533d5bb98214be Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 21 Oct 2022 14:05:19 +0200 Subject: Fix: Bokeh blur node flips its bokeh input The bokeh blur node flipped its bokeh input due to the conceptual difference between the search window space and the weights texture space. This patches fixes that by inverting the weights texture to match the search window. The variable size option actually flips the bokeh input for the CPU compositor. It is unclear if this is expected, so we deviate from that behavior for now. --- .../gpu/shaders/compositor/compositor_blur.glsl | 21 ++++++++++++++++----- .../compositor/compositor_blur_variable_size.glsl | 21 ++++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/source/blender/gpu/shaders/compositor/compositor_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_blur.glsl index 4f981c84f59..c7ac620f99b 100644 --- a/source/blender/gpu/shaders/compositor/compositor_blur.glsl +++ b/source/blender/gpu/shaders/compositor/compositor_blur.glsl @@ -18,13 +18,24 @@ vec4 load_input(ivec2 texel) } /* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from - * the weights texture, where the texel (0, 0) is considered the center of weights texture. */ + * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. + * Note that we load the weights texture inverted along both directions to maintain the shape of + * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D + * weights texture whose right half is all ones and whose left half is all zeros. Further, consider + * that we are blurring a single white pixel on a black background. When computing the value of a + * pixel that is to the right of the white pixel, the white pixel will be in the left region of the + * search window, and consequently, without inversion, a zero will be sampled from the left side of + * the weights texture and result will be zero. However, what we expect is that pixels to the right + * of the white pixel will be white, that is, they should sample a weight of 1 from the right side + * of the weights texture, hence the need for inversion. */ vec4 load_weight(ivec2 texel) { - /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper - * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the - * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */ - return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1)); + /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 + * to sample at the center of the pixels, then divide by the upper bound plus one to transform + * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, + * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as + * mentioned in the function description. */ + return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); } void main() diff --git a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl index e7e5aac12a5..9383bbf9825 100644 --- a/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl +++ b/source/blender/gpu/shaders/compositor/compositor_blur_variable_size.glsl @@ -2,7 +2,16 @@ #pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) /* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from - * the weights texture, where the texel (0, 0) is considered the center of weights texture. */ + * the weights texture, where the given texel (0, 0) corresponds the center of weights texture. + * Note that we load the weights texture inverted along both directions to maintain the shape of + * the weights if it was not symmetrical. To understand why inversion makes sense, consider a 1D + * weights texture whose right half is all ones and whose left half is all zeros. Further, consider + * that we are blurring a single white pixel on a black background. When computing the value of a + * pixel that is to the right of the white pixel, the white pixel will be in the left region of the + * search window, and consequently, without inversion, a zero will be sampled from the left side of + * the weights texture and result will be zero. However, what we expect is that pixels to the right + * of the white pixel will be white, that is, they should sample a weight of 1 from the right side + * of the weights texture, hence the need for inversion. */ vec4 load_weight(ivec2 texel, float radius) { /* The center zero texel is always assigned a unit weight regardless of the corresponding weight @@ -12,10 +21,12 @@ vec4 load_weight(ivec2 texel, float radius) return vec4(1.0); } - /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper - * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the - * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */ - return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1)); + /* Add the radius to transform the texel into the range [0, radius * 2], with an additional 0.5 + * to sample at the center of the pixels, then divide by the upper bound plus one to transform + * the texel into the normalized range [0, 1] needed to sample the weights sampler. Finally, + * invert the textures coordinates by subtracting from 1 to maintain the shape of the weights as + * mentioned in the function description. */ + return texture(weights_tx, 1.0 - ((texel + vec2(radius + 0.5)) / (radius * 2 + 1))); } void main() -- cgit v1.2.3 From f0ebf696cbbb521f956c5b612037f4d11e87cb0d Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 21 Oct 2022 09:52:53 -0300 Subject: Fix T101964: Edge and face snapping no locking to axis In rBed6c8d82b804 it was wrongly assumed that the constraint functions always apply the transformations. But that is not the case for when axes are aligned. The `mul_m3_v3(t->con.pmtx, out)` fallback is still required. --- source/blender/editors/transform/transform_constraints.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index fa56456d8e7..7abf0e5c00c 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -404,9 +404,11 @@ static void applyAxisConstraintVec(const TransInfo *t, } } + /* Fallback for when axes are aligned. */ + mul_m3_v3(t->con.pmtx, out); + if (is_snap_to_point) { - /* With snap points, a projection is alright, no adjustments needed. */ - mul_m3_v3(t->con.pmtx, out); + /* Pass. With snap points, a projection is alright, no adjustments needed. */ } else { const int dims = getConstraintSpaceDimension(t); @@ -422,14 +424,9 @@ static void applyAxisConstraintVec(const TransInfo *t, /* Disabled, as it has not proven to be really useful. (See T82386). */ // constraint_snap_plane_to_face(t, plane, out); } - else { + else if (!isPlaneProjectionViewAligned(t, plane)) { /* View alignment correction. */ - if (!isPlaneProjectionViewAligned(t, plane)) { - planeProjection(t, plane, in, out); - } - else { - mul_m3_v3(t->con.pmtx, out); - } + planeProjection(t, plane, in, out); } } } -- cgit v1.2.3 From 3225bc2e7fb6100c74788acbaba9849a77c93ef2 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 14:36:25 +0200 Subject: GPU: Fix Metal GLSL compilation errors due to recent changes. vec.st is legacy OpenGL and should not be used. --- source/blender/gpu/shaders/gpu_shader_icon_frag.glsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl index ff56d772317..4452349f23c 100644 --- a/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_icon_frag.glsl @@ -27,15 +27,15 @@ void main() bool lower_half = mask_coord_interp.y < circle_center.y; bool right_half = mask_coord_interp.x > circle_center.x; - if (right_half && mask_coord_interp.t < circle_center.y + circle_radius_outer) { + if (right_half && mask_coord_interp.y < circle_center.y + circle_radius_outer) { mask = smoothstep(circle_center.y + circle_radius_inner, circle_center.y + circle_radius_outer, - mask_coord_interp.t); + mask_coord_interp.y); } - if (lower_half && mask_coord_interp.s > circle_center.x - circle_radius_outer) { + if (lower_half && mask_coord_interp.x > circle_center.x - circle_radius_outer) { mask = smoothstep(circle_center.x - circle_radius_inner, circle_center.x - circle_radius_outer, - mask_coord_interp.s); + mask_coord_interp.x); } fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask)); -- cgit v1.2.3 From e8c4411035234696742b9cd97525fe094fd3f4ac Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 14:38:30 +0200 Subject: GPU: Add gpu.platform.backend_type_get function. Function returns the active GPU backend type. --- source/blender/python/gpu/gpu_py_platform.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c index b877e3ceb98..51366d199b0 100644 --- a/source/blender/python/gpu/gpu_py_platform.c +++ b/source/blender/python/gpu/gpu_py_platform.c @@ -11,6 +11,7 @@ #include "BLI_utildefines.h" +#include "GPU_context.h" #include "GPU_platform.h" #include "gpu_py_platform.h" /* Own include. */ @@ -83,6 +84,28 @@ static PyObject *pygpu_platform_device_type_get(PyObject *UNUSED(self)) return PyUnicode_FromString("UNKNOWN"); } +PyDoc_STRVAR(pygpu_platform_backend_type_get_doc, + ".. function:: backend_type_get()\n" + "\n" + " Get actuve GPU backend.\n" + "\n" + " :return: Backend type ('OPENGL', 'METAL', 'NONE', 'UNKNOWN').\n" + " :rtype: str\n"); +static PyObject *pygpu_platform_backend_type_get(PyObject *UNUSED(self)) +{ + switch (GPU_backend_get_type()) { + case GPU_BACKEND_METAL: + return PyUnicode_FromString("METAL"); + case GPU_BACKEND_NONE: + return PyUnicode_FromString("NONE"); + case GPU_BACKEND_OPENGL: + return PyUnicode_FromString("OPENGL"); + case GPU_BACKEND_ANY: + break; + } + return PyUnicode_FromString("UNKNOWN"); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -106,6 +129,10 @@ static struct PyMethodDef pygpu_platform__tp_methods[] = { (PyCFunction)pygpu_platform_device_type_get, METH_NOARGS, pygpu_platform_device_type_get_doc}, + {"backend_type_get", + (PyCFunction)pygpu_platform_backend_type_get, + METH_NOARGS, + pygpu_platform_backend_type_get_doc}, {NULL, NULL, 0, NULL}, }; -- cgit v1.2.3 From d39f2eed980dc97de2180d29a7f8c45f4233e70c Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 14:57:54 +0200 Subject: GPU: Don't exit after first GPUBackend. --- source/blender/gpu/intern/gpu_shader_builder.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_shader_builder.cc b/source/blender/gpu/intern/gpu_shader_builder.cc index 9a67ddde5e6..abb45ca074a 100644 --- a/source/blender/gpu/intern/gpu_shader_builder.cc +++ b/source/blender/gpu/intern/gpu_shader_builder.cc @@ -115,8 +115,8 @@ int main(int argc, const char *argv[]) exit_code = 1; } builder.exit(); - exit(exit_code); } + exit(exit_code); return exit_code; } -- cgit v1.2.3 From 3ccec478414eda8eafebaead302eadbd9453d558 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 21 Oct 2022 07:04:21 -0600 Subject: cmake/windows: Prepare for 3.4 library changes for opencollada The opencollada dependency will be using an external xml2 library for 3.4. This change allows to build against both old and new style lib folders. As it is a C library it did not need a special debug version. --- build_files/cmake/platform/platform_win32.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 5fb921fc97d..32c467b4b46 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -358,7 +358,6 @@ if(WITH_OPENCOLLADA) optimized ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter.lib optimized ${OPENCOLLADA}/lib/opencollada/MathMLSolver.lib optimized ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser.lib - optimized ${OPENCOLLADA}/lib/opencollada/xml.lib optimized ${OPENCOLLADA}/lib/opencollada/buffer.lib optimized ${OPENCOLLADA}/lib/opencollada/ftoa.lib @@ -368,10 +367,14 @@ if(WITH_OPENCOLLADA) debug ${OPENCOLLADA}/lib/opencollada/OpenCOLLADAStreamWriter_d.lib debug ${OPENCOLLADA}/lib/opencollada/MathMLSolver_d.lib debug ${OPENCOLLADA}/lib/opencollada/GeneratedSaxParser_d.lib - debug ${OPENCOLLADA}/lib/opencollada/xml_d.lib debug ${OPENCOLLADA}/lib/opencollada/buffer_d.lib debug ${OPENCOLLADA}/lib/opencollada/ftoa_d.lib ) + if(EXISTS ${LIBDIR}/xml2/lib/libxml2s.lib) # 3.4 libraries + list(APPEND OPENCOLLADA_LIBRARIES ${LIBDIR}/xml2/lib/libxml2s.lib) + else() + list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/xml.lib) + endif() list(APPEND OPENCOLLADA_LIBRARIES ${OPENCOLLADA}/lib/opencollada/UTF.lib) -- cgit v1.2.3 From ec60c8abe76e4473f45d783010be92114c0ed608 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 21 Oct 2022 15:03:21 +0200 Subject: SystemInfo: Add active GPU backend. For debugging it is useful to known the active GPU backend. Although it could be determined from looking at the extensions, this is easier to understand when not activly working in this area. --- release/scripts/modules/sys_info.py | 1 + 1 file changed, 1 insertion(+) diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py index 7f6d0b1e9bf..5bd38acb19c 100644 --- a/release/scripts/modules/sys_info.py +++ b/release/scripts/modules/sys_info.py @@ -184,6 +184,7 @@ def write_sysinfo(filepath): output.write("vendor:\t\t%r\n" % gpu.platform.vendor_get()) output.write("version:\t%r\n" % gpu.platform.version_get()) output.write("device type:\t%r\n" % gpu.platform.device_type_get()) + output.write("backend type:\t%r\n" % gpu.platform.backend_type_get()) output.write("extensions:\n") glext = sorted(gpu.capabilities.extensions_get()) -- cgit v1.2.3 From 4776a74bf7f1ed60efee22290c5fea732d7e2e5a Mon Sep 17 00:00:00 2001 From: Edward Date: Fri, 21 Oct 2022 15:35:20 +0200 Subject: Fix T101974: Potential memoryleak GHOST_WindowWayland.newDrawingContext Reviewed By: jbakker Maniphest Tasks: T101974 Differential Revision: https://developer.blender.org/D16309 --- intern/ghost/intern/GHOST_WindowWayland.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index b29c5efd8d4..986e18d7a87 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -946,7 +946,12 @@ GHOST_Context *GHOST_WindowWayland::newDrawingContext(GHOST_TDrawingContextType EGL_OPENGL_API); } - return (context->initializeDrawingContext() == GHOST_kSuccess) ? context : nullptr; + if (context->initializeDrawingContext()) { + return context; + } + + delete context; + return nullptr; } /** \} */ -- cgit v1.2.3 From 305b92e05f748a0fd9cb62b9829791d717ba2d57 Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Fri, 21 Oct 2022 14:10:25 +0200 Subject: Cycles: oneAPI: remove use of SYCL host device Host device is deprecated in SYCL 2020 spec, cpu device or standard C++ should be used instead. --- CMakeLists.txt | 2 - intern/cycles/device/oneapi/device.cpp | 4 +- intern/cycles/device/oneapi/device_impl.cpp | 30 +++------------ intern/cycles/kernel/CMakeLists.txt | 4 -- .../kernel/device/gpu/parallel_active_index.h | 33 +++------------- intern/cycles/kernel/device/oneapi/compat.h | 45 +++++----------------- intern/cycles/kernel/device/oneapi/globals.h | 9 ----- intern/cycles/kernel/device/oneapi/kernel.cpp | 7 ---- 8 files changed, 21 insertions(+), 113 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9134c7c1ed6..a3ea162d040 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -489,14 +489,12 @@ endif() if(NOT APPLE) option(WITH_CYCLES_DEVICE_ONEAPI "Enable Cycles oneAPI compute support" OFF) option(WITH_CYCLES_ONEAPI_BINARIES "Enable Ahead-Of-Time compilation for Cycles oneAPI device" OFF) - option(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED "Enable use of SYCL host (CPU) device execution by oneAPI implementation. This option is for debugging purposes and impacts GPU execution." OFF) # https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html # acm-g10 is the architecture for the first Arc Alchemist GPUs but we'll keep using dg2 until IGC dependency is updated to support acm-g10. set(CYCLES_ONEAPI_SPIR64_GEN_DEVICES "dg2" CACHE STRING "oneAPI Intel GPU architectures to build binaries for") set(CYCLES_ONEAPI_SYCL_TARGETS spir64 spir64_gen CACHE STRING "oneAPI targets to build AOT binaries for") - mark_as_advanced(WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) mark_as_advanced(CYCLES_ONEAPI_SPIR64_GEN_DEVICES) mark_as_advanced(CYCLES_ONEAPI_SYCL_TARGETS) endif() diff --git a/intern/cycles/device/oneapi/device.cpp b/intern/cycles/device/oneapi/device.cpp index f303ab41627..66d6f749e30 100644 --- a/intern/cycles/device/oneapi/device.cpp +++ b/intern/cycles/device/oneapi/device.cpp @@ -39,7 +39,7 @@ bool device_oneapi_init() _putenv_s("SYCL_CACHE_THRESHOLD", "0"); } if (getenv("SYCL_DEVICE_FILTER") == nullptr) { - _putenv_s("SYCL_DEVICE_FILTER", "host,level_zero"); + _putenv_s("SYCL_DEVICE_FILTER", "level_zero"); } if (getenv("SYCL_ENABLE_PCI") == nullptr) { _putenv_s("SYCL_ENABLE_PCI", "1"); @@ -50,7 +50,7 @@ bool device_oneapi_init() # elif __linux__ setenv("SYCL_CACHE_PERSISTENT", "1", false); setenv("SYCL_CACHE_THRESHOLD", "0", false); - setenv("SYCL_DEVICE_FILTER", "host,level_zero", false); + setenv("SYCL_DEVICE_FILTER", "level_zero", false); setenv("SYCL_ENABLE_PCI", "1", false); setenv("SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE_FOR_IN_ORDER_QUEUE", "0", false); # endif diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp index f14eada071d..4e7849e6b9a 100644 --- a/intern/cycles/device/oneapi/device_impl.cpp +++ b/intern/cycles/device/oneapi/device_impl.cpp @@ -430,8 +430,7 @@ void OneapiDevice::check_usm(SyclQueue *queue_, const void *usm_ptr, bool allow_ sycl::usm::alloc usm_type = get_pointer_type(usm_ptr, queue->get_context()); (void)usm_type; assert(usm_type == sycl::usm::alloc::device || - ((device_type == sycl::info::device_type::host || - device_type == sycl::info::device_type::cpu || allow_host) && + ((device_type == sycl::info::device_type::cpu || allow_host) && usm_type == sycl::usm::alloc::host || usm_type == sycl::usm::alloc::unknown)); # else @@ -672,14 +671,6 @@ std::vector OneapiDevice::available_devices() if (getenv("CYCLES_ONEAPI_ALL_DEVICES") != nullptr) allow_all_devices = true; - /* Host device is useful only for debugging at the moment - * so we hide this device with default build settings. */ -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED - bool allow_host = true; -# else - bool allow_host = false; -# endif - const std::vector &oneapi_platforms = sycl::platform::get_platforms(); std::vector available_devices; @@ -691,17 +682,11 @@ std::vector OneapiDevice::available_devices() } const std::vector &oneapi_devices = - (allow_all_devices || allow_host) ? platform.get_devices(sycl::info::device_type::all) : - platform.get_devices(sycl::info::device_type::gpu); + (allow_all_devices) ? platform.get_devices(sycl::info::device_type::all) : + platform.get_devices(sycl::info::device_type::gpu); for (const sycl::device &device : oneapi_devices) { - if (allow_all_devices) { - /* still filter out host device if build doesn't support it. */ - if (allow_host || !device.is_host()) { - available_devices.push_back(device); - } - } - else { + if (!allow_all_devices) { bool filter_out = false; /* For now we support all Intel(R) Arc(TM) devices and likely any future GPU, @@ -733,9 +718,6 @@ std::vector OneapiDevice::available_devices() } } } - else if (!allow_host && device.is_host()) { - filter_out = true; - } else if (!allow_all_devices) { filter_out = true; } @@ -798,9 +780,7 @@ char *OneapiDevice::device_capabilities() GET_NUM_ATTR(native_vector_width_double) GET_NUM_ATTR(native_vector_width_half) - size_t max_clock_frequency = - (size_t)(device.is_host() ? (size_t)0 : - device.get_info()); + size_t max_clock_frequency = device.get_info(); WRITE_ATTR("max_clock_frequency", max_clock_frequency) GET_NUM_ATTR(address_bits) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 1e69d14b1b7..b6a53117a3b 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -752,10 +752,6 @@ if(WITH_CYCLES_DEVICE_ONEAPI) ${SYCL_CPP_FLAGS} ) - if (WITH_CYCLES_ONEAPI_SYCL_HOST_ENABLED) - list(APPEND sycl_compiler_flags -DWITH_ONEAPI_SYCL_HOST_ENABLED) - endif() - # Set defaults for spir64 and spir64_gen options if (NOT DEFINED CYCLES_ONEAPI_SYCL_OPTIONS_spir64) set(CYCLES_ONEAPI_SYCL_OPTIONS_spir64 "-options '-ze-opt-large-register-file -ze-opt-regular-grf-kernel integrator_intersect'") diff --git a/intern/cycles/kernel/device/gpu/parallel_active_index.h b/intern/cycles/kernel/device/gpu/parallel_active_index.h index c1df49c4f49..38cdcb572eb 100644 --- a/intern/cycles/kernel/device/gpu/parallel_active_index.h +++ b/intern/cycles/kernel/device/gpu/parallel_active_index.h @@ -23,22 +23,6 @@ CCL_NAMESPACE_BEGIN * and keep device specific code in compat.h */ #ifdef __KERNEL_ONEAPI__ -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED -template -void cpu_serial_active_index_array_impl(const uint num_states, - ccl_global int *ccl_restrict indices, - ccl_global int *ccl_restrict num_indices, - IsActiveOp is_active_op) -{ - int write_index = 0; - for (int state_index = 0; state_index < num_states; state_index++) { - if (is_active_op(state_index)) - indices[write_index++] = state_index; - } - *num_indices = write_index; - return; -} -# endif /* WITH_ONEAPI_SYCL_HOST_ENABLED */ template void gpu_parallel_active_index_array_impl(const uint num_states, @@ -182,18 +166,11 @@ __device__ num_simd_groups, \ simdgroup_offset) #elif defined(__KERNEL_ONEAPI__) -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED -# define gpu_parallel_active_index_array( \ - blocksize, num_states, indices, num_indices, is_active_op) \ - if (ccl_gpu_global_size_x() == 1) \ - cpu_serial_active_index_array_impl(num_states, indices, num_indices, is_active_op); \ - else \ - gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op); -# else -# define gpu_parallel_active_index_array( \ - blocksize, num_states, indices, num_indices, is_active_op) \ - gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op) -# endif + +# define gpu_parallel_active_index_array( \ + blocksize, num_states, indices, num_indices, is_active_op) \ + gpu_parallel_active_index_array_impl(num_states, indices, num_indices, is_active_op) + #else # define gpu_parallel_active_index_array( \ diff --git a/intern/cycles/kernel/device/oneapi/compat.h b/intern/cycles/kernel/device/oneapi/compat.h index 8ae40b0612e..dfaec65130c 100644 --- a/intern/cycles/kernel/device/oneapi/compat.h +++ b/intern/cycles/kernel/device/oneapi/compat.h @@ -55,18 +55,6 @@ #define ccl_gpu_kernel(block_num_threads, thread_num_registers) #define ccl_gpu_kernel_threads(block_num_threads) -#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED -# define KG_ND_ITEMS \ - kg->nd_item_local_id_0 = item.get_local_id(0); \ - kg->nd_item_local_range_0 = item.get_local_range(0); \ - kg->nd_item_group_0 = item.get_group(0); \ - kg->nd_item_group_range_0 = item.get_group_range(0); \ - kg->nd_item_global_id_0 = item.get_global_id(0); \ - kg->nd_item_global_range_0 = item.get_global_range(0); -#else -# define KG_ND_ITEMS -#endif - #define ccl_gpu_kernel_signature(name, ...) \ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \ size_t kernel_global_size, \ @@ -76,8 +64,7 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \ (kg); \ cgh.parallel_for( \ sycl::nd_range<1>(kernel_global_size, kernel_local_size), \ - [=](sycl::nd_item<1> item) { \ - KG_ND_ITEMS + [=](sycl::nd_item<1> item) { #define ccl_gpu_kernel_postfix \ }); \ @@ -95,31 +82,17 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \ } ccl_gpu_kernel_lambda_pass((ONEAPIKernelContext *)kg) /* GPU thread, block, grid size and index */ -#ifndef WITH_ONEAPI_SYCL_HOST_ENABLED -# define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0)) -# define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0)) -# define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0)) -# define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0)) -# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0]) -# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp)) - -# define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0)) -# define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0)) -#else -# define ccl_gpu_thread_idx_x (kg->nd_item_local_id_0) -# define ccl_gpu_block_dim_x (kg->nd_item_local_range_0) -# define ccl_gpu_block_idx_x (kg->nd_item_group_0) -# define ccl_gpu_grid_dim_x (kg->nd_item_group_range_0) -# define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0]) -# define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp)) - -# define ccl_gpu_global_id_x() (kg->nd_item_global_id_0) -# define ccl_gpu_global_size_x() (kg->nd_item_global_range_0) -#endif +#define ccl_gpu_thread_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_id(0)) +#define ccl_gpu_block_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_local_range(0)) +#define ccl_gpu_block_idx_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group(0)) +#define ccl_gpu_grid_dim_x (sycl::ext::oneapi::experimental::this_nd_item<1>().get_group_range(0)) +#define ccl_gpu_warp_size (sycl::ext::oneapi::experimental::this_sub_group().get_local_range()[0]) +#define ccl_gpu_thread_mask(thread_warp) uint(0xFFFFFFFF >> (ccl_gpu_warp_size - thread_warp)) +#define ccl_gpu_global_id_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_id(0)) +#define ccl_gpu_global_size_x() (sycl::ext::oneapi::experimental::this_nd_item<1>().get_global_range(0)) /* GPU warp synchronization */ - #define ccl_gpu_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier() #define ccl_gpu_local_syncthreads() sycl::ext::oneapi::experimental::this_nd_item<1>().barrier(sycl::access::fence_space::local_space) #ifdef __SYCL_DEVICE_ONLY__ diff --git a/intern/cycles/kernel/device/oneapi/globals.h b/intern/cycles/kernel/device/oneapi/globals.h index d60f4f135ba..116620eb725 100644 --- a/intern/cycles/kernel/device/oneapi/globals.h +++ b/intern/cycles/kernel/device/oneapi/globals.h @@ -23,15 +23,6 @@ typedef struct KernelGlobalsGPU { #undef KERNEL_DATA_ARRAY IntegratorStateGPU *integrator_state; const KernelData *__data; -#ifdef WITH_ONEAPI_SYCL_HOST_ENABLED - size_t nd_item_local_id_0; - size_t nd_item_local_range_0; - size_t nd_item_group_0; - size_t nd_item_group_range_0; - - size_t nd_item_global_id_0; - size_t nd_item_global_range_0; -#endif } KernelGlobalsGPU; typedef ccl_global KernelGlobalsGPU *ccl_restrict KernelGlobals; diff --git a/intern/cycles/kernel/device/oneapi/kernel.cpp b/intern/cycles/kernel/device/oneapi/kernel.cpp index 1f32d3406ea..525ae288f0c 100644 --- a/intern/cycles/kernel/device/oneapi/kernel.cpp +++ b/intern/cycles/kernel/device/oneapi/kernel.cpp @@ -230,13 +230,6 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context, /* NOTE(@nsirgien): As for now non-uniform work-groups don't work on most oneAPI devices, * we extend work size to fit uniformity requirements. */ global_size = groups_count * local_size; - -# ifdef WITH_ONEAPI_SYCL_HOST_ENABLED - if (queue->get_device().is_host()) { - global_size = 1; - local_size = 1; - } -# endif } /* Let the compiler throw an error if there are any kernels missing in this implementation. */ -- cgit v1.2.3 From 0cfac5b0432b619294b3d38fb74e4f7b295ef1cc Mon Sep 17 00:00:00 2001 From: Xavier Hallade Date: Fri, 21 Oct 2022 13:58:16 +0200 Subject: Cycles: oneAPI: migrate from deprecated APIs, require libSYCL 6.0+ sycl::info::device::ext_intel_* descriptors are deprecated, replaced with sycl::ext::intel::info::device:: that are available from 6.0+, for which we now check version in CMake. --- build_files/cmake/Modules/FindSYCL.cmake | 16 +++++++++++++++- intern/cycles/cmake/external_libs.cmake | 5 ++--- intern/cycles/device/oneapi/device_impl.cpp | 12 ++++++------ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/build_files/cmake/Modules/FindSYCL.cmake b/build_files/cmake/Modules/FindSYCL.cmake index 7abf074fb7f..1ccbee179fb 100644 --- a/build_files/cmake/Modules/FindSYCL.cmake +++ b/build_files/cmake/Modules/FindSYCL.cmake @@ -88,9 +88,23 @@ FIND_PATH(SYCL_INCLUDE_DIR include ) +IF(EXISTS "${SYCL_INCLUDE_DIR}/sycl/version.hpp") + FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_major_version REGEX "^#define __LIBSYCL_MAJOR_VERSION[ \t].*$") + STRING(REGEX MATCHALL "[0-9]+" _libsycl_major_version ${_libsycl_major_version}) + FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_minor_version REGEX "^#define __LIBSYCL_MINOR_VERSION[ \t].*$") + STRING(REGEX MATCHALL "[0-9]+" _libsycl_minor_version ${_libsycl_minor_version}) + FILE(STRINGS "${SYCL_INCLUDE_DIR}/sycl/version.hpp" _libsycl_patch_version REGEX "^#define __LIBSYCL_PATCH_VERSION[ \t].*$") + STRING(REGEX MATCHALL "[0-9]+" _libsycl_patch_version ${_libsycl_patch_version}) + + SET(SYCL_VERSION "${_libsycl_major_version}.${_libsycl_minor_version}.${_libsycl_patch_version}") +ENDIF() + INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL DEFAULT_MSG SYCL_LIBRARY SYCL_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL + REQUIRED_VARS SYCL_LIBRARY SYCL_INCLUDE_DIR + VERSION_VAR SYCL_VERSION +) IF(SYCL_FOUND) SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl) diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 9524cda54f5..65a38625e0a 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -663,8 +663,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI) find_package(SYCL) find_package(LevelZero) - if(SYCL_FOUND AND LEVEL_ZERO_FOUND) - message(STATUS "Found oneAPI: ${SYCL_LIBRARY}") + if(SYCL_FOUND AND SYCL_VERSION VERSION_GREATER_EQUAL 6.0 AND LEVEL_ZERO_FOUND) message(STATUS "Found Level Zero: ${LEVEL_ZERO_LIBRARY}") if(WITH_CYCLES_ONEAPI_BINARIES) @@ -681,7 +680,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI) endif() endif() else() - message(STATUS "oneAPI or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI") + message(STATUS "SYCL 6.0+ or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI") set(WITH_CYCLES_DEVICE_ONEAPI OFF) endif() endif() diff --git a/intern/cycles/device/oneapi/device_impl.cpp b/intern/cycles/device/oneapi/device_impl.cpp index 4e7849e6b9a..3588b75713b 100644 --- a/intern/cycles/device/oneapi/device_impl.cpp +++ b/intern/cycles/device/oneapi/device_impl.cpp @@ -698,11 +698,11 @@ std::vector OneapiDevice::available_devices() int number_of_eus = 96; int threads_per_eu = 7; if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) { - number_of_eus = device.get_info(); + number_of_eus = device.get_info(); } if (device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) { threads_per_eu = - device.get_info(); + device.get_info(); } /* This filters out all Level-Zero supported GPUs from older generation than Arc. */ if (number_of_eus <= 96 && threads_per_eu == 7) { @@ -818,7 +818,7 @@ void OneapiDevice::iterate_devices(OneAPIDeviceIteratorCallback cb, void *user_p std::string name = device.get_info(); std::string id = "ONEAPI_" + platform_name + "_" + name; if (device.has(sycl::aspect::ext_intel_pci_address)) { - id.append("_" + device.get_info()); + id.append("_" + device.get_info()); } (cb)(id.c_str(), name.c_str(), num, user_ptr); num++; @@ -836,7 +836,7 @@ int OneapiDevice::get_num_multiprocessors() { const sycl::device &device = reinterpret_cast(device_queue_)->get_device(); if (device.has(sycl::aspect::ext_intel_gpu_eu_count)) { - return device.get_info(); + return device.get_info(); } else return 0; @@ -847,8 +847,8 @@ int OneapiDevice::get_max_num_threads_per_multiprocessor() const sycl::device &device = reinterpret_cast(device_queue_)->get_device(); if (device.has(sycl::aspect::ext_intel_gpu_eu_simd_width) && device.has(sycl::aspect::ext_intel_gpu_hw_threads_per_eu)) { - return device.get_info() * - device.get_info(); + return device.get_info() * + device.get_info(); } else return 0; -- cgit v1.2.3 From 048f1a1b8b7ccf5b3d618a76a947941bf5d534f2 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 21 Oct 2022 11:57:42 -0300 Subject: GPU: remove unused member from FrameBuffer Accidentally added in rB2510bd3a5f35d14f5e0e098c79a776916d273223 --- source/blender/gpu/intern/gpu_framebuffer_private.hh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index 76e816e7f65..5afcc102e44 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -94,11 +94,6 @@ class FrameBuffer { void **py_ref = nullptr; #endif - public: - /* Reference of a pointer that needs to be cleaned when deallocating the frame-buffer. - * Points to #BPyGPUFrameBuffer::fb */ - void **ref = nullptr; - public: FrameBuffer(const char *name); virtual ~FrameBuffer(); -- cgit v1.2.3 From 2c108d55031f2b6b5f83810f7f560d1ed81bdc5c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 21 Oct 2022 15:57:53 +0200 Subject: Avoid re-compilation of oneAPI AoT kernels when configuration changes Buildbot infrastructure relies on the fact that it can enable and disable `WITH_CYCLES__BINARIES` without affecting speed of incremental builds. This allows buildbot to skip GPU kernels when doing CI regression tests which do not need GPU kernels, as well as it allows to move GPU kernels compilation to a separate step where all the resources are available to the GPU kernel builders. For the oneAPI compute enabling and disabling AoT kernels has much higher implications due to the kernels being a part of the device implementation from the build target perspective. This change makes it so different target names are used for JIT and AoT configurations, which allows CMake to more fully benefit from "caching" the compiled result. The end goal of this change is to make it so sequential build of the same code base on the buildbot happens super fast, Blender binary still needs to be re-linked when the AOT of oneAPI option is toggled, but that's already the case in the buildbot due to the WITH_BUILDINFO. Differential Revision: https://developer.blender.org/D16312 --- intern/cycles/device/CMakeLists.txt | 9 +++++++-- intern/cycles/kernel/CMakeLists.txt | 12 +++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 9c0de57f203..5296d819e42 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -187,10 +187,15 @@ if(WITH_CYCLES_DEVICE_METAL) ) endif() if (WITH_CYCLES_DEVICE_ONEAPI) + if(WITH_CYCLES_ONEAPI_BINARIES) + set(cycles_kernel_oneapi_lib_suffix "_aot") + else() + set(cycles_kernel_oneapi_lib_suffix "_jit") + endif() if(WIN32) - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi.lib) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib) else() - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi.so) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so) endif() list(APPEND LIB ${cycles_kernel_oneapi_lib}) if(WIN32) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index b6a53117a3b..81c5f593974 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -713,11 +713,17 @@ endif() # oneAPI module if(WITH_CYCLES_DEVICE_ONEAPI) + if(WITH_CYCLES_ONEAPI_BINARIES) + set(cycles_kernel_oneapi_lib_suffix "_aot") + else() + set(cycles_kernel_oneapi_lib_suffix "_jit") + endif() + if(WIN32) - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll) - set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.lib) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.dll) + set(cycles_kernel_oneapi_linker_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.lib) else() - set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi.so) + set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so) endif() set(cycles_oneapi_kernel_sources -- cgit v1.2.3 From 116d7b0042bba7d6cabd8e04c7d020ac3816caf3 Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 21 Oct 2022 09:50:14 -0600 Subject: make.bat: update the libraries before calling update_sources.py The issue we ran into a lot is we have a python script that updates git+SVN. Which works fine most of the time, except when we have a python update in SVN, or worse a python version change. Python really doesn't enjoy having its files being deleted or changed while it is running and users generally end up with a corrupted lib folder. This change updates the library folder using svn.exe first before letting the python script run sidestepping the issue in most cases. The python script will still run and do the more elaborate work like updating git and switching SVN branches which could still run into issues cause python still doesn't like being changed while running but there's not a whole lot we can about that, for *most* people however things will just work now. --- build_files/windows/svn_update.cmd | 24 ++++++++++++++++++++++++ make.bat | 10 +++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 build_files/windows/svn_update.cmd diff --git a/build_files/windows/svn_update.cmd b/build_files/windows/svn_update.cmd new file mode 100644 index 00000000000..f91f03f15b3 --- /dev/null +++ b/build_files/windows/svn_update.cmd @@ -0,0 +1,24 @@ +if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15 +if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15 + +set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST% +set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%" + +cd %BUILD_VS_LIBDIR% +:RETRY +"%SVN%" update +if errorlevel 1 ( + set /p LibRetry= "Error during update, retry? y/n" + if /I "!LibRetry!"=="Y" ( + "%SVN%" cleanup + goto RETRY + ) + echo. + echo Error: Download of external libraries failed. + echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in + echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build + echo. + exit /b 1 +) + +cd %BLENDER_DIR% \ No newline at end of file diff --git a/make.bat b/make.bat index ff8059b0754..0be70053ce1 100644 --- a/make.bat +++ b/make.bat @@ -62,9 +62,17 @@ if "%SVN_FIX%" == "1" ( ) if "%BUILD_UPDATE%" == "1" ( + REM First see if the SVN libs are there and check them out if they are not. call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" if errorlevel 1 goto EOF - + REM Then update SVN platform libraries, since updating python while python is + REM running tends to be problematic. The python script that update_sources + REM calls later on may still try to switch branches and run into trouble, + REM but for *most* people this will side step the problem. + call "%BLENDER_DIR%\build_files\windows\svn_update.cmd" + REM Finally call the python script shared between all platforms that updates git + REM and does any other SVN work like update the tests or branch switches + REM if required. call "%BLENDER_DIR%\build_files\windows\update_sources.cmd" goto EOF ) -- cgit v1.2.3 From 9c20eda0add3e223cd473eb883806a04522d345b Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 21 Oct 2022 14:24:18 -0300 Subject: Fix T101244: Empty point list in shader batch creation cause error Allow empty VBOs in Python GPUBatch creation. --- release/scripts/modules/gpu_extras/batch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/modules/gpu_extras/batch.py b/release/scripts/modules/gpu_extras/batch.py index ba8e3879a8e..6c9ab52c1a3 100644 --- a/release/scripts/modules/gpu_extras/batch.py +++ b/release/scripts/modules/gpu_extras/batch.py @@ -34,13 +34,13 @@ def batch_for_shader(shader, type, content, *, indices=None): return 'I32' def recommended_attr_len(attr_name): - item = content[attr_name][0] attr_len = 1 try: + item = content[attr_name][0] while True: attr_len *= len(item) item = item[0] - except TypeError: + except (TypeError, IndexError): pass return attr_len -- cgit v1.2.3 From 56d1f0772dd0e2b77abef1ad071e2e893cf3bc0a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 30 Sep 2022 18:48:21 +0200 Subject: Fix missing OpenMP in Linux builds OpenSubdiv OpenMP detection was interfering, but we don't use it there anymore so just remove that code. --- build_files/cmake/Modules/FindOpenSubdiv.cmake | 15 --------------- build_files/cmake/platform/platform_win32.cmake | 6 ------ intern/opensubdiv/CMakeLists.txt | 6 ------ 3 files changed, 27 deletions(-) diff --git a/build_files/cmake/Modules/FindOpenSubdiv.cmake b/build_files/cmake/Modules/FindOpenSubdiv.cmake index 37a2cddf3de..66d3b435c46 100644 --- a/build_files/cmake/Modules/FindOpenSubdiv.cmake +++ b/build_files/cmake/Modules/FindOpenSubdiv.cmake @@ -71,21 +71,6 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenSubdiv DEFAULT_MSG IF(OPENSUBDIV_FOUND) SET(OPENSUBDIV_LIBRARIES ${_opensubdiv_LIBRARIES}) SET(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR}) - - # Find available compute controllers. - - FIND_PACKAGE(OpenMP) - IF(OPENMP_FOUND) - SET(OPENSUBDIV_HAS_OPENMP TRUE) - ELSE() - SET(OPENSUBDIV_HAS_OPENMP FALSE) - ENDIF() - - OPENSUBDIV_CHECK_CONTROLLER("tbbEvaluator.h" OPENSUBDIV_HAS_TBB) - OPENSUBDIV_CHECK_CONTROLLER("clEvaluator.h" OPENSUBDIV_HAS_OPENCL) - OPENSUBDIV_CHECK_CONTROLLER("cudaEvaluator.h" OPENSUBDIV_HAS_CUDA) - OPENSUBDIV_CHECK_CONTROLLER("glXFBEvaluator.h" OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) - OPENSUBDIV_CHECK_CONTROLLER("glComputeEvaluator.h" OPENSUBDIV_HAS_GLSL_COMPUTE) ENDIF() MARK_AS_ADVANCED( diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 32c467b4b46..2816446164a 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -703,12 +703,6 @@ if(WITH_OPENSUBDIV) debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib ) - set(OPENSUBDIV_HAS_OPENMP TRUE) - set(OPENSUBDIV_HAS_TBB FALSE) - set(OPENSUBDIV_HAS_OPENCL TRUE) - set(OPENSUBDIV_HAS_CUDA FALSE) - set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE) - set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE) endif() endif() diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt index 1dddd70928a..920b8d5c542 100644 --- a/intern/opensubdiv/CMakeLists.txt +++ b/intern/opensubdiv/CMakeLists.txt @@ -81,12 +81,6 @@ if(WITH_OPENSUBDIV) ) endif() - opensubdiv_define_component(OPENSUBDIV_HAS_OPENMP) - opensubdiv_define_component(OPENSUBDIV_HAS_OPENCL) - opensubdiv_define_component(OPENSUBDIV_HAS_CUDA) - opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) - opensubdiv_define_component(OPENSUBDIV_HAS_GLSL_COMPUTE) - if(WIN32) add_definitions(-DNOMINMAX) add_definitions(-D_USE_MATH_DEFINES) -- cgit v1.2.3 From ebe231969294924ff057f5d999d05986f9c97352 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 30 Sep 2022 18:50:03 +0200 Subject: Build: disable JACK option in macOS releases It has not actually been enabled there for a long time in official releases, so this just fixes the warning. Making it work again would be good, but for now JACK is only supported on Linux. --- CMakeLists.txt | 6 ++---- build_files/cmake/config/blender_full.cmake | 4 +--- build_files/cmake/config/blender_release.cmake | 4 +--- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3ea162d040..e922a3b059a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -336,11 +336,9 @@ if(APPLE) else() set(WITH_COREAUDIO OFF) endif() -if(NOT WIN32) +if(UNIX AND NOT APPLE) option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ON) - if(UNIX AND NOT APPLE) - option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) - endif() + option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) else() set(WITH_JACK OFF) endif() diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index 958eb17522b..95304bd64c7 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -66,13 +66,11 @@ set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE) if(APPLE) set(WITH_COREAUDIO ON CACHE BOOL "" FORCE) endif() -if(NOT WIN32) - set(WITH_JACK ON CACHE BOOL "" FORCE) -endif() if(WIN32) set(WITH_WASAPI ON CACHE BOOL "" FORCE) endif() if(UNIX AND NOT APPLE) + set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index d5f5230862b..74bbcb223c3 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -67,13 +67,11 @@ if(APPLE) set(WITH_COREAUDIO ON CACHE BOOL "" FORCE) set(WITH_CYCLES_DEVICE_METAL ON CACHE BOOL "" FORCE) endif() -if(NOT WIN32) - set(WITH_JACK ON CACHE BOOL "" FORCE) -endif() if(WIN32) set(WITH_WASAPI ON CACHE BOOL "" FORCE) endif() if(UNIX AND NOT APPLE) + set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_PULSEAUDIO ON CACHE BOOL "" FORCE) -- cgit v1.2.3 From e7a6917617fbb4f3c224ad89e6a63bedf56e6553 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 29 Sep 2022 19:01:35 +0200 Subject: Build: add option to error when features can't be enabled This is to help ensure buildbot builds are correct, while still gracefully disabling features in user/developer builds. * Add WITH_STRICT_BUILD_OPTIONS to give an error when features can't be enabled due to missing libraries or other reasons. Add new macro set_and_warn_library_found used everywhere features were being automatically disabled. * Remove code from Windows and macOS for various libraries that would automatically disable features. set_and_warn_library_found could be used here also, but we are generally assuming the precompiled libraries are complete and only test for availability when libraries are just added. Differential Revision: https://developer.blender.org/D16104 --- CMakeLists.txt | 22 ++- build_files/cmake/macros.cmake | 18 ++- build_files/cmake/platform/platform_apple.cmake | 89 ++-------- build_files/cmake/platform/platform_unix.cmake | 205 +++++++----------------- build_files/cmake/platform/platform_win32.cmake | 59 ++----- intern/cycles/CMakeLists.txt | 6 +- intern/cycles/cmake/external_libs.cmake | 51 +++--- 7 files changed, 143 insertions(+), 307 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e922a3b059a..f2f34ca3dd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -777,6 +777,8 @@ endif() # ----------------------------------------------------------------------------- # Check for Conflicting/Unsupported Configurations +option(WITH_STRICT_BUILD_OPTIONS "When requirements for a build option are not met, error instead of disabling the option" OFF) + if(NOT WITH_BLENDER AND NOT WITH_CYCLES_STANDALONE AND NOT WITH_CYCLES_HYDRA_RENDER_DELEGATE) message(FATAL_ERROR "At least one of WITH_BLENDER or WITH_CYCLES_STANDALONE " @@ -892,10 +894,7 @@ endif() if(WITH_BUILDINFO) find_package(Git) - if(NOT GIT_FOUND) - message(WARNING "Git was not found, disabling WITH_BUILDINFO") - set(WITH_BUILDINFO OFF) - endif() + set_and_warn_library_found("Git" GIT_FOUND WITH_BUILDINFO) endif() if(WITH_AUDASPACE) @@ -935,9 +934,10 @@ if(WITH_INTERNATIONAL) WARNING "Translation path '${CMAKE_SOURCE_DIR}/release/datafiles/locale' is missing, " "This is a 'git submodule', which are known not to work with bridges to other version " - "control systems, disabling 'WITH_INTERNATIONAL'." + "control systems." ) - set(WITH_INTERNATIONAL OFF) + set(TRANSLATIONS_FOUND OFF) + set_and_warn_library_found("Translations" TRANSLATIONS_FOUND WITH_INTERNATIONAL) endif() endif() @@ -1242,6 +1242,8 @@ if(WITH_OPENMP) find_package(OpenMP) endif() + set_and_warn_library_found("OpenMP" OPENMP_FOUND WITH_OPENMP) + if(OPENMP_FOUND) if(NOT WITH_OPENMP_STATIC) string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}") @@ -1257,9 +1259,6 @@ if(WITH_OPENMP) find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) endif() - else() - message(STATUS "OpenMP not found, disabling WITH_OPENMP") - set(WITH_OPENMP OFF) endif() mark_as_advanced( @@ -1274,10 +1273,7 @@ endif() if(WITH_BULLET AND WITH_SYSTEM_BULLET) find_package(Bullet) - if(NOT BULLET_FOUND) - message(STATUS "Bullet not found, disabling WITH_BULLET") - set(WITH_BULLET OFF) - endif() + set_and_warn_library_found("Bullet" BULLET_FOUND WITH_BULLET) else() set(BULLET_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/extern/bullet2/src") # set(BULLET_LIBRARIES "") diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 3acea19079b..8af45690862 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -1205,11 +1205,27 @@ macro(set_and_warn_dependency _dependency _setting _val) # when $_dependency is disabled, forces $_setting = $_val if(NOT ${${_dependency}} AND ${${_setting}}) - message(STATUS "'${_dependency}' is disabled: forcing 'set(${_setting} ${_val})'") + if(WITH_STRICT_BUILD_OPTIONS) + message(SEND_ERROR "${_dependency} disabled but required by ${_setting}") + else() + message(STATUS "${_dependency} is disabled, setting ${_setting}=${_val}") + endif() set(${_setting} ${_val}) endif() endmacro() +macro(set_and_warn_library_found + _library_name _library_found _setting) + if(NOT ${${_library_found}} AND ${${_setting}}) + if(WITH_STRICT_BUILD_OPTIONS) + message(SEND_ERROR "${_library_name} required but not found") + else() + message(STATUS "${_library_name} not found, disabling ${_setting}") + endif() + set(${_setting} OFF) + endif() +endmacro() + macro(without_system_libs_begin) set(CMAKE_IGNORE_PATH "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES};${CMAKE_SYSTEM_INCLUDE_PATH};${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES};${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}") endmacro() diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index dbcaf9d02d3..c5fe3c908de 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -43,22 +43,18 @@ find_package(BZip2 REQUIRED) list(APPEND ZLIB_LIBRARIES ${BZIP2_LIBRARIES}) if(WITH_OPENAL) - find_package(OpenAL) - if(NOT OPENAL_FOUND) - message(WARNING "OpenAL not found, disabling WITH_OPENAL") - set(WITH_OPENAL OFF) - endif() + find_package(OpenAL REQUIRED) endif() if(WITH_JACK) find_library(JACK_FRAMEWORK NAMES jackmp ) - if(NOT JACK_FRAMEWORK) - message(STATUS "JACK not found, disabling WITH_JACK") - set(WITH_JACK OFF) - else() + + if(JACK_FRAMEWORK) set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + else() + set_and_warn_library_found("JACK" JACK_FRAMEWORK WITH_JACK) endif() endif() @@ -101,11 +97,7 @@ if(WITH_ALEMBIC) endif() if(WITH_USD) - find_package(USD) - if(NOT USD_FOUND) - message(STATUS "USD not found, disabling WITH_USD") - set(WITH_USD OFF) - endif() + find_package(USD REQUIRED) endif() if(WITH_OPENSUBDIV) @@ -227,20 +219,12 @@ find_package(JPEG REQUIRED) if(WITH_IMAGE_TIFF) set(TIFF_ROOT ${LIBDIR}/tiff) - find_package(TIFF) - if(NOT TIFF_FOUND) - message(WARNING "TIFF not found, disabling WITH_IMAGE_TIFF") - set(WITH_IMAGE_TIFF OFF) - endif() + find_package(TIFF REQUIRED) endif() if(WITH_IMAGE_WEBP) set(WEBP_ROOT_DIR ${LIBDIR}/webp) - find_package(WebP) - if(NOT WEBP_FOUND) - message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP") - set(WITH_IMAGE_WEBP OFF) - endif() + find_package(WebP REQUIRED) endif() if(WITH_BOOST) @@ -270,11 +254,7 @@ if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG) endif() if(WITH_PUGIXML) - find_package(PugiXML) - if(NOT PUGIXML_FOUND) - message(WARNING "PugiXML not found, disabling WITH_PUGIXML") - set(WITH_PUGIXML OFF) - endif() + find_package(PugiXML REQUIRED) endif() if(WITH_OPENIMAGEIO) @@ -292,12 +272,7 @@ if(WITH_OPENIMAGEIO) endif() if(WITH_OPENCOLORIO) - find_package(OpenColorIO 2.0.0) - - if(NOT OPENCOLORIO_FOUND) - set(WITH_OPENCOLORIO OFF) - message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO") - endif() + find_package(OpenColorIO 2.0.0 REQUIRED) endif() if(WITH_OPENVDB) @@ -331,12 +306,7 @@ if(WITH_LLVM) endif() if(WITH_CYCLES AND WITH_CYCLES_OSL) - find_package(OSL) - - if(NOT OSL_FOUND) - message(WARNING "OSL not found, disabling WITH_CYCLES_OSL") - set(WITH_CYCLES_OSL OFF) - endif() + find_package(OSL REQUIRED) endif() if(WITH_CYCLES AND WITH_CYCLES_EMBREE) @@ -354,28 +324,15 @@ if(WITH_CYCLES AND WITH_CYCLES_EMBREE) endif() if(WITH_OPENIMAGEDENOISE) - find_package(OpenImageDenoise) - - if(NOT OPENIMAGEDENOISE_FOUND) - set(WITH_OPENIMAGEDENOISE OFF) - message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE") - endif() + find_package(OpenImageDenoise REQUIRED) endif() if(WITH_TBB) - find_package(TBB) - if(NOT TBB_FOUND) - message(WARNING "TBB not found, disabling WITH_TBB") - set(WITH_TBB OFF) - endif() + find_package(TBB REQUIRED) endif() if(WITH_POTRACE) - find_package(Potrace) - if(NOT POTRACE_FOUND) - message(WARNING "potrace not found, disabling WITH_POTRACE") - set(WITH_POTRACE OFF) - endif() + find_package(Potrace REQUIRED) endif() # CMake FindOpenMP doesn't know about AppleClang before 3.12, so provide custom flags. @@ -395,27 +352,15 @@ if(WITH_OPENMP) endif() if(WITH_XR_OPENXR) - find_package(XR_OpenXR_SDK) - if(NOT XR_OPENXR_SDK_FOUND) - message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR") - set(WITH_XR_OPENXR OFF) - endif() + find_package(XR_OpenXR_SDK REQUIRED) endif() if(WITH_GMP) - find_package(GMP) - if(NOT GMP_FOUND) - message(WARNING "GMP not found, disabling WITH_GMP") - set(WITH_GMP OFF) - endif() + find_package(GMP REQUIRED) endif() if(WITH_HARU) - find_package(Haru) - if(NOT HARU_FOUND) - message(WARNING "Haru not found, disabling WITH_HARU") - set(WITH_HARU OFF) - endif() + find_package(Haru REQUIRED) endif() if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index 7f3acb142ce..424926afe39 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -174,32 +174,24 @@ endif() if(WITH_IMAGE_OPENEXR) find_package_wrapper(OpenEXR) # our own module - if(NOT OPENEXR_FOUND) - set(WITH_IMAGE_OPENEXR OFF) - endif() + set_and_warn_library_found("OpenEXR" OPENEXR_FOUND WITH_IMAGE_OPENEXR) endif() if(WITH_IMAGE_OPENJPEG) find_package_wrapper(OpenJPEG) - if(NOT OPENJPEG_FOUND) - set(WITH_IMAGE_OPENJPEG OFF) - endif() + set_and_warn_library_found("OpenJPEG" OPENJPEG_FOUND WITH_IMAGE_OPENJPEG) endif() if(WITH_IMAGE_TIFF) # XXX Linking errors with debian static tiff :/ # find_package_wrapper(TIFF) find_package(TIFF) - if(NOT TIFF_FOUND) - set(WITH_IMAGE_TIFF OFF) - endif() + set_and_warn_library_found("TIFF" TIFF_FOUND WITH_IMAGE_TIFF) endif() if(WITH_OPENAL) find_package_wrapper(OpenAL) - if(NOT OPENAL_FOUND) - set(WITH_OPENAL OFF) - endif() + set_and_warn_library_found("OpenAL" OPENAL_FOUND WITH_OPENAL) endif() if(WITH_SDL) @@ -221,18 +213,14 @@ if(WITH_SDL) SDL_LIBRARY ) # unset(SDLMAIN_LIBRARY CACHE) - if(NOT SDL_FOUND) - set(WITH_SDL OFF) - endif() + set_and_warn_library_found("SDL" SDL_FOUND WITH_SDL) endif() endif() # Codecs if(WITH_CODEC_SNDFILE) find_package_wrapper(SndFile) - if(NOT SNDFILE_FOUND) - set(WITH_CODEC_SNDFILE OFF) - endif() + set_and_warn_library_found("libsndfile" SNDFILE_FOUND WITH_CODEC_SNDFILE) endif() if(WITH_CODEC_FFMPEG) @@ -260,17 +248,12 @@ if(WITH_CODEC_FFMPEG) endif() find_package(FFmpeg) - if(NOT FFMPEG_FOUND) - set(WITH_CODEC_FFMPEG OFF) - message(STATUS "FFmpeg not found, disabling it") - endif() + set_and_warn_library_found("FFmpeg" FFMPEG_FOUND WITH_CODEC_FFMPEG) endif() if(WITH_FFTW3) find_package_wrapper(Fftw3) - if(NOT FFTW3_FOUND) - set(WITH_FFTW3 OFF) - endif() + set_and_warn_library_found("fftw3" FFTW3_FOUND WITH_FFTW3) endif() if(WITH_OPENCOLLADA) @@ -285,25 +268,23 @@ if(WITH_OPENCOLLADA) endif() find_package_wrapper(XML2) else() - set(WITH_OPENCOLLADA OFF) + set_and_warn_library_found("OpenCollada" OPENCOLLADA_FOUND WITH_OPENCOLLADA) endif() endif() if(WITH_MEM_JEMALLOC) find_package_wrapper(JeMalloc) - if(NOT JEMALLOC_FOUND) - set(WITH_MEM_JEMALLOC OFF) - endif() + set_and_warn_library_found("JeMalloc" JEMALLOC_FOUND WITH_MEM_JEMALLOC) endif() if(WITH_INPUT_NDOF) find_package_wrapper(Spacenav) + set_and_warn_library_found("SpaceNav" SPACENAV_FOUND WITH_INPUT_NDOF) + if(SPACENAV_FOUND) # use generic names within blenders buildsystem. set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS}) set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES}) - else() - set(WITH_INPUT_NDOF OFF) endif() endif() @@ -313,6 +294,8 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) set(OSL_ROOT ${CYCLES_OSL}) endif() find_package_wrapper(OSL) + set_and_warn_library_found("OSL" OSL_FOUND WITH_CYCLES_OSL) + if(OSL_FOUND) if(${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6") # Note: --whole-archive is needed to force loading of all symbols in liboslexec, @@ -323,9 +306,6 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) -Wl,--no-whole-archive ${OSL_OSLQUERY_LIBRARY} ) endif() - else() - message(STATUS "OSL not found, disabling it from Cycles") - set(WITH_CYCLES_OSL OFF) endif() endif() @@ -351,25 +331,17 @@ endif() if(WITH_OPENVDB) find_package_wrapper(OpenVDB) - find_package_wrapper(Blosc) - - if(NOT OPENVDB_FOUND) - set(WITH_OPENVDB OFF) - set(WITH_OPENVDB_BLOSC OFF) - message(STATUS "OpenVDB not found, disabling it") - elseif(NOT BLOSC_FOUND) - set(WITH_OPENVDB_BLOSC OFF) - message(STATUS "Blosc not found, disabling it for OpenVBD") + set_and_warn_library_found("OpenVDB" OPENVDB_FOUND WITH_OPENVDB) + + if(OPENVDB_FOUND) + find_package_wrapper(Blosc) + set_and_warn_library_found("Blosc" BLOSC_FOUND WITH_OPENVDB_BLOSC) endif() endif() if(WITH_NANOVDB) find_package_wrapper(NanoVDB) - - if(NOT NANOVDB_FOUND) - set(WITH_NANOVDB OFF) - message(STATUS "NanoVDB not found, disabling it") - endif() + set_and_warn_library_found("NanoVDB" NANOVDB_FOUND WITH_NANOVDB) endif() if(WITH_CPU_SIMD AND SUPPORT_NEON_BUILD) @@ -378,18 +350,12 @@ endif() if(WITH_ALEMBIC) find_package_wrapper(Alembic) - - if(NOT ALEMBIC_FOUND) - set(WITH_ALEMBIC OFF) - endif() + set_and_warn_library_found("Alembic" ALEMBIC_FOUND WITH_ALEMBIC) endif() if(WITH_USD) find_package_wrapper(USD) - - if(NOT USD_FOUND) - set(WITH_USD OFF) - endif() + set_and_warn_library_found("USD" USD_FOUND WITH_USD) endif() if(WITH_BOOST) @@ -442,20 +408,13 @@ endif() if(WITH_PUGIXML) find_package_wrapper(PugiXML) - - if(NOT PUGIXML_FOUND) - set(WITH_PUGIXML OFF) - message(STATUS "PugiXML not found, disabling WITH_PUGIXML") - endif() + set_and_warn_library_found("PugiXML" PUGIXML_FOUND WITH_PUGIXML) endif() if(WITH_IMAGE_WEBP) set(WEBP_ROOT_DIR ${LIBDIR}/webp) find_package_wrapper(WebP) - if(NOT WEBP_FOUND) - set(WITH_IMAGE_WEBP OFF) - message(WARNING "WebP not found, disabling WITH_IMAGE_WEBP") - endif() + set_and_warn_library_found("WebP" WEBP_FOUND WITH_IMAGE_WEBP) endif() if(WITH_OPENIMAGEIO) @@ -480,10 +439,7 @@ if(WITH_OPENIMAGEIO) list(APPEND OPENIMAGEIO_LIBRARIES "${WEBP_LIBRARIES}") endif() - if(NOT OPENIMAGEIO_FOUND) - set(WITH_OPENIMAGEIO OFF) - message(STATUS "OpenImageIO not found, disabling WITH_CYCLES") - endif() + set_and_warn_library_found("OPENIMAGEIO" OPENIMAGEIO_FOUND WITH_OPENIMAGEIO) endif() if(WITH_OPENCOLORIO) @@ -493,10 +449,7 @@ if(WITH_OPENCOLORIO) set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere set(OPENCOLORIO_DEFINITIONS) - if(NOT OPENCOLORIO_FOUND) - set(WITH_OPENCOLORIO OFF) - message(STATUS "OpenColorIO not found") - endif() + set_and_warn_library_found("OpenColorIO" OPENCOLORIO_FOUND WITH_OPENCOLORIO) endif() if(WITH_CYCLES AND WITH_CYCLES_EMBREE) @@ -505,11 +458,7 @@ endif() if(WITH_OPENIMAGEDENOISE) find_package_wrapper(OpenImageDenoise) - - if(NOT OPENIMAGEDENOISE_FOUND) - set(WITH_OPENIMAGEDENOISE OFF) - message(STATUS "OpenImageDenoise not found") - endif() + set_and_warn_library_found("OpenImageDenoise" OPENIMAGEDENOISE_FOUND WITH_OPENIMAGEDENOISE) endif() if(WITH_LLVM) @@ -518,24 +467,19 @@ if(WITH_LLVM) endif() find_package_wrapper(LLVM) - if(WITH_CLANG) - find_package_wrapper(Clang) - endif() - # Symbol conflicts with same UTF library used by OpenCollada - if(EXISTS ${LIBDIR}) - if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0")) - list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY}) + set_and_warn_library_found("LLVM" LLVM_FOUND WITH_LLVM) + + if(LLVM_FOUND) + if(WITH_CLANG) + find_package_wrapper(Clang) + set_and_warn_library_found("Clang" CLANG_FOUND WITH_CLANG) endif() - endif() - if(NOT LLVM_FOUND) - set(WITH_LLVM OFF) - set(WITH_CLANG OFF) - message(STATUS "LLVM not found") - else() - if(NOT CLANG_FOUND) - set(WITH_CLANG OFF) - message(STATUS "Clang not found") + # Symbol conflicts with same UTF library used by OpenCollada + if(EXISTS ${LIBDIR}) + if(WITH_OPENCOLLADA AND (${LLVM_VERSION} VERSION_LESS "4.0.0")) + list(REMOVE_ITEM OPENCOLLADA_LIBRARIES ${OPENCOLLADA_UTF_LIBRARY}) + endif() endif() endif() endif() @@ -546,50 +490,32 @@ if(WITH_OPENSUBDIV) set(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARIES}) set(OPENSUBDIV_LIBPATH) # TODO, remove and reference the absolute path everywhere - if(NOT OPENSUBDIV_FOUND) - set(WITH_OPENSUBDIV OFF) - message(STATUS "OpenSubdiv not found") - endif() + set_and_warn_library_found("OpenSubdiv" OPENSUBDIV_FOUND WITH_OPENSUBDIV) endif() if(WITH_TBB) find_package_wrapper(TBB) - if(NOT TBB_FOUND) - message(WARNING "TBB not found, disabling WITH_TBB") - set(WITH_TBB OFF) - endif() + set_and_warn_library_found("TBB" TBB_FOUND WITH_TBB) endif() if(WITH_XR_OPENXR) find_package(XR_OpenXR_SDK) - if(NOT XR_OPENXR_SDK_FOUND) - message(WARNING "OpenXR-SDK not found, disabling WITH_XR_OPENXR") - set(WITH_XR_OPENXR OFF) - endif() + set_and_warn_library_found("OpenXR-SDK" XR_OPENXR_SDK_FOUND WITH_XR_OPENXR) endif() if(WITH_GMP) find_package_wrapper(GMP) - if(NOT GMP_FOUND) - message(WARNING "GMP not found, disabling WITH_GMP") - set(WITH_GMP OFF) - endif() + set_and_warn_library_found("GMP" GMP_FOUND WITH_GMP) endif() if(WITH_POTRACE) find_package_wrapper(Potrace) - if(NOT POTRACE_FOUND) - message(WARNING "potrace not found, disabling WITH_POTRACE") - set(WITH_POTRACE OFF) - endif() + set_and_warn_library_found("Potrace" POTRACE_FOUND WITH_POTRACE) endif() if(WITH_HARU) find_package_wrapper(Haru) - if(NOT HARU_FOUND) - message(WARNING "Haru not found, disabling WITH_HARU") - set(WITH_HARU OFF) - endif() + set_and_warn_library_found("Haru" HARU_FOUND WITH_HARU) endif() if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) @@ -676,25 +602,20 @@ endif() # Jack is intended to use the system library. if(WITH_JACK) find_package_wrapper(Jack) - if(NOT JACK_FOUND) - set(WITH_JACK OFF) - endif() + set_and_warn_library_found("JACK" JACK_FOUND WITH_JACK) endif() # Pulse is intended to use the system library. if(WITH_PULSEAUDIO) find_package_wrapper(Pulse) - if(NOT PULSE_FOUND) - set(WITH_PULSEAUDIO OFF) - endif() + set_and_warn_library_found("PulseAudio" PULSE_FOUND WITH_PULSEAUDIO) endif() # Audio IO if(WITH_SYSTEM_AUDASPACE) find_package_wrapper(Audaspace) - if(NOT AUDASPACE_FOUND OR NOT AUDASPACE_C_FOUND) - message(FATAL_ERROR "Audaspace external library not found!") - endif() + set(AUDASPACE_FOUND ${AUDASPACE_FOUND} AND ${AUDASPACE_C_FOUND}) + set_and_warn_library_found("External Audaspace" AUDASPACE_FOUND WITH_SYSTEM_AUDASPACE) endif() if(WITH_GHOST_WAYLAND) @@ -740,30 +661,12 @@ if(WITH_GHOST_WAYLAND) set(wayland-cursor_FOUND ON) endif() - if (NOT wayland-client_FOUND) - message(STATUS "wayland-client not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-egl_FOUND) - message(STATUS "wayland-egl not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-scanner_FOUND) - message(STATUS "wayland-scanner not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-cursor_FOUND) - message(STATUS "wayland-cursor not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT wayland-protocols_FOUND) - message(STATUS "wayland-protocols not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() - if (NOT xkbcommon_FOUND) - message(STATUS "xkbcommon not found, disabling WITH_GHOST_WAYLAND") - set(WITH_GHOST_WAYLAND OFF) - endif() + set_and_warn_library_found("wayland-client" wayland-client_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-egl" wayland-egl_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-scanner" wayland-scanner_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-cursor" wayland-cursor_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("wayland-protocols" wayland-protocols_FOUND WITH_GHOST_WAYLAND) + set_and_warn_library_found("xkbcommon" xkbcommon_FOUND WITH_GHOST_WAYLAND) if(WITH_GHOST_WAYLAND) if(WITH_GHOST_WAYLAND_DBUS) diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 2816446164a..3818076634a 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -326,18 +326,10 @@ if(WITH_FFTW3) endif() if(WITH_IMAGE_WEBP) - windows_find_package(WebP) - if(NOT WEBP_FOUND) - if(EXISTS ${LIBDIR}/webp) - set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include) - set(WEBP_ROOT_DIR ${LIBDIR}/webp) - set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib) - set(WEBP_FOUND ON) - else() - message(STATUS "WITH_IMAGE_WEBP is ON but WEBP libraries are not found, setting WITH_IMAGE_WEBP=OFF") - set(WITH_IMAGE_WEBP OFF) - endif() - endif() + set(WEBP_INCLUDE_DIRS ${LIBDIR}/webp/include) + set(WEBP_ROOT_DIR ${LIBDIR}/webp) + set(WEBP_LIBRARIES ${LIBDIR}/webp/lib/webp.lib ${LIBDIR}/webp/lib/webpdemux.lib ${LIBDIR}/webp/lib/webpmux.lib) + set(WEBP_FOUND ON) endif() if(WITH_OPENCOLLADA) @@ -792,13 +784,6 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL) endif() find_path(OSL_INCLUDE_DIR OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) - - if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER) - set(OSL_FOUND TRUE) - else() - message(STATUS "OSL not found") - set(WITH_CYCLES_OSL OFF) - endif() endif() if(WITH_CYCLES AND WITH_CYCLES_EMBREE) @@ -898,21 +883,16 @@ if(WINDOWS_PYTHON_DEBUG) endif() if(WITH_XR_OPENXR) - if(EXISTS ${LIBDIR}/xr_openxr_sdk) - set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk) - set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib) - set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include) - # This is the old name of this library, it is checked to - # support the transition between the old and new lib versions - # this can be removed after the next lib update. - if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) - set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) - else() - set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib) - endif() + set(XR_OPENXR_SDK ${LIBDIR}/xr_openxr_sdk) + set(XR_OPENXR_SDK_LIBPATH ${LIBDIR}/xr_openxr_sdk/lib) + set(XR_OPENXR_SDK_INCLUDE_DIR ${XR_OPENXR_SDK}/include) + # This is the old name of this library, it is checked to + # support the transition between the old and new lib versions + # this can be removed after the next lib update. + if(EXISTS ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) + set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loader_d.lib) else() - message(WARNING "OpenXR-SDK was not found, disabling WITH_XR_OPENXR") - set(WITH_XR_OPENXR OFF) + set(XR_OPENXR_SDK_LIBRARIES optimized ${XR_OPENXR_SDK_LIBPATH}/openxr_loader.lib debug ${XR_OPENXR_SDK_LIBPATH}/openxr_loaderd.lib) endif() endif() @@ -930,15 +910,10 @@ if(WITH_POTRACE) endif() if(WITH_HARU) - if(EXISTS ${LIBDIR}/haru) - set(HARU_FOUND ON) - set(HARU_ROOT_DIR ${LIBDIR}/haru) - set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include) - set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib) - else() - message(WARNING "Haru was not found, disabling WITH_HARU") - set(WITH_HARU OFF) - endif() + set(HARU_FOUND ON) + set(HARU_ROOT_DIR ${LIBDIR}/haru) + set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include) + set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib) endif() if(WITH_CYCLES AND WITH_CYCLES_PATH_GUIDING) diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index f619e6b104e..329aa3990f6 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -263,8 +263,7 @@ if(WITH_CYCLES_DEVICE_OPTIX) ${OPTIX_INCLUDE_DIR} ) else() - message(STATUS "OptiX not found, disabling it from Cycles") - set(WITH_CYCLES_DEVICE_OPTIX OFF) + set_and_warn_library_found("OptiX" OPTIX_FOUND WITH_CYCLES_DEVICE_OPTIX) endif() endif() @@ -387,8 +386,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif() if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_USD)) - message(STATUS "USD not found, disabling WITH_CYCLES_HYDRA_RENDER_DELEGATE") - set(WITH_CYCLES_HYDRA_RENDER_DELEGATE OFF) + set_and_warn_library_found("USD" WITH_USD WITH_CYCLES_HYDRA_RENDER_DELEGATE) endif() if(WITH_CYCLES_HYDRA_RENDER_DELEGATE AND (NOT WITH_BLENDER) AND (NOT WITH_CYCLES_STANDALONE)) set(CYCLES_INSTALL_PATH ${CYCLES_INSTALL_PATH}/hdCycles/resources) diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 65a38625e0a..44542a08156 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -289,8 +289,7 @@ if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_PATH_GUIDING) endif() get_target_property(OPENPGL_INCLUDE_DIR openpgl::openpgl INTERFACE_INCLUDE_DIRECTORIES) else() - set(WITH_CYCLES_PATH_GUIDING OFF) - message(STATUS "OpenPGL not found, disabling WITH_CYCLES_PATH_GUIDING") + set_and_warn_library_found("OpenPGL" openpgl_FOUND WITH_CYCLES_PATH_GUIDING) endif() endif() @@ -588,16 +587,14 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) # We can't use the version from the Blender precompiled libraries because # it does not include the video subsystem. find_package(SDL2 REQUIRED) + set_and_warn_library_found("SDL" SDL2_FOUND WITH_CYCLES_STANDALONE_GUI) - if(NOT SDL2_FOUND) - set(WITH_CYCLES_STANDALONE_GUI OFF) - message(STATUS "SDL not found, disabling Cycles standalone GUI") + if(SDL2_FOUND) + include_directories( + SYSTEM + ${SDL2_INCLUDE_DIRS} + ) endif() - - include_directories( - SYSTEM - ${SDL2_INCLUDE_DIRS} - ) endif() ########################################################################### @@ -606,11 +603,11 @@ endif() if(WITH_CYCLES_DEVICE_CUDA AND (WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD)) find_package(CUDA) # Try to auto locate CUDA toolkit + set_and_warn_library_found("CUDA compiler" CUDA_FOUND WITH_CYCLES_CUDA_BINARIES) + if(CUDA_FOUND) message(STATUS "Found CUDA ${CUDA_NVCC_EXECUTABLE} (${CUDA_VERSION})") else() - message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES") - set(WITH_CYCLES_CUDA_BINARIES OFF) if(NOT WITH_CUDA_DYNLOAD) message(STATUS "Additionally falling back to dynamic CUDA load") set(WITH_CUDA_DYNLOAD ON) @@ -624,11 +621,10 @@ endif() if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP) find_package(HIP) + set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES) + if(HIP_FOUND) message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})") - else() - message(STATUS "HIP compiler not found, disabling WITH_CYCLES_HIP_BINARIES") - set(WITH_CYCLES_HIP_BINARIES OFF) endif() endif() @@ -644,13 +640,17 @@ if(WITH_CYCLES_DEVICE_METAL) find_library(METAL_LIBRARY Metal) # This file was added in the 12.0 SDK, use it as a way to detect the version. - if(METAL_LIBRARY AND NOT EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h") - message(STATUS "Metal version too old, must be SDK 12.0 or newer, disabling WITH_CYCLES_DEVICE_METAL") - set(WITH_CYCLES_DEVICE_METAL OFF) - elseif(NOT METAL_LIBRARY) - message(STATUS "Metal not found, disabling WITH_CYCLES_DEVICE_METAL") - set(WITH_CYCLES_DEVICE_METAL OFF) - else() + if(METAL_LIBRARY) + if(EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h") + set(METAL_FOUND ON) + else() + message(STATUS "Metal version too old, must be SDK 12.0 or newer") + set(METAL_FOUND OFF) + endif() + endif() + + set_and_warn_library_found("Metal" METAL_FOUND WITH_CYCLES_DEVICE_METAL) + if(METAL_FOUND) message(STATUS "Found Metal: ${METAL_LIBRARY}") endif() endif() @@ -662,6 +662,8 @@ endif() if(WITH_CYCLES_DEVICE_ONEAPI) find_package(SYCL) find_package(LevelZero) + set_and_warn_library_found("oneAPI" SYCL_FOUND WITH_CYCLES_DEVICE_ONEAPI) + set_and_warn_library_found("Level Zero" LEVEL_ZERO_FOUND WITH_CYCLES_DEVICE_ONEAPI) if(SYCL_FOUND AND SYCL_VERSION VERSION_GREATER_EQUAL 6.0 AND LEVEL_ZERO_FOUND) message(STATUS "Found Level Zero: ${LEVEL_ZERO_LIBRARY}") @@ -674,9 +676,10 @@ if(WITH_CYCLES_DEVICE_ONEAPI) endif() if(NOT EXISTS ${OCLOC_INSTALL_DIR}) - message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}, disabling WITH_CYCLES_ONEAPI_BINARIES." + set(OCLOC_FOUND OFF) + message(STATUS "oneAPI ocloc not found in ${OCLOC_INSTALL_DIR}." " A different ocloc directory can be set using OCLOC_INSTALL_DIR cmake variable.") - set(WITH_CYCLES_ONEAPI_BINARIES OFF) + set_and_warn_library_found("ocloc" OCLOC_FOUND WITH_CYCLES_ONEAPI_BINARIES) endif() endif() else() -- cgit v1.2.3 From 04eab0fd01e8c416ce45c95b9e32db4e0ff03d7b Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 21 Oct 2022 12:48:17 -0600 Subject: deps_builder: expose FORCE_CHECK_HASH as an option The check was already there, but given it was not exposed as an option it didn't show up in my cmakecache and i got tired of having to lookup the exact name all the time. --- build_files/build_environment/cmake/options.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake index 6e5f9df20b4..9058e945f6d 100644 --- a/build_files/build_environment/cmake/options.cmake +++ b/build_files/build_environment/cmake/options.cmake @@ -3,6 +3,7 @@ if(WIN32) option(ENABLE_MINGW64 "Enable building of ffmpeg/iconv/libsndfile/fftw3 by installing mingw64" ON) endif() +option(FORCE_CHECK_HASH "Force a check of all hashses during CMake the configure phase" OFF) option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF) cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_LOGICAL_CORES) set(MAKE_THREADS ${NUM_CORES} CACHE STRING "Number of threads to run make with") -- cgit v1.2.3 From ea571ddc29e4e7be441a9b58bef50190a4a35c04 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 22 Oct 2022 02:51:52 +0200 Subject: Fix T101969: Crash when using large texture with nonstandard colorspace When the image colorspace is not data, linear or sRGB, the image will be converted to float (and colorspace-converted) during loading. However, if it also needs to be rescaled (due to exceeding the GPU texture size limit), the resizing assumed that it's still a byte texture. --- source/blender/imbuf/intern/util_gpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index dd509677d8d..5ed6b2b9843 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -174,6 +174,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, /* Other colorspace, store as float texture to avoid precision loss. */ data_rect = MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__); *r_freedata = freedata = true; + is_float_rect = true; if (data_rect == NULL) { return NULL; -- cgit v1.2.3 From 59a0b49c100b8444a15f4713409004eade9fd321 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 21 Oct 2022 20:10:17 -0600 Subject: Video rendering: FFMpeg AV1 codec encoding support Previously, the Blender video renderer did not have support for encoding video to AV1 (not to be confused with the container AVI). The proposed solution is to leverage the existing FFMpeg renderer to encode to AV1. Note that avcodec_find_encoder(AV_CODEC_ID_AV1) usually returns "libaom-av1" which is the "reference implementation" for AV1 encoding (the default for FFMpeg, and is slow). "libsvtav1" is faster and preferred so there is extra handling when fetching the AV1 codec for encoding such that "libsvtav1" is used when possible. This commit should only affect the options available for video rendering, which includes the additional AV1 codec to choose from, and setting "-crf". Also note that the current release of FFMpeg for ArchLinux does not support "-crf" for "libsvtav1", but the equivalent option "-qp" is supported and used as a fallback when "libsvtav1" is used (as mentioned here: https://trac.ffmpeg.org/wiki/Encode/AV1#SVT-AV1 ). (Actually, both "-crf" and "-qp" is specified with the same value in the code. When a release of FFMpeg obtains support for "-crf" for "libsvtav1" is released, the code shouldn't be needed to change.) The usage of the AV1 codec should be very similar to the usage of the H264 codec, but is limited to the "mp4" and "mkv" containers. This patch pertains to the "VFX & Video" module, as its main purpose is to supplement the Video Sequencer tool with the additional AV1 codec for encoded video output. Differential Revision: https://developer.blender.org/D14920 Reviewed By: sergey , ISS, zeddb --- intern/ffmpeg/tests/ffmpeg_codecs.cc | 7 + release/scripts/startup/bl_ui/properties_output.py | 16 +- source/blender/blenkernel/BKE_writeffmpeg.h | 2 + source/blender/blenkernel/intern/image_format.cc | 7 +- source/blender/blenkernel/intern/writeavi.c | 3 +- source/blender/blenkernel/intern/writeffmpeg.c | 236 ++++++++++++++++++++- source/blender/makesdna/DNA_scene_types.h | 1 + source/blender/makesrna/intern/rna_scene.c | 1 + 8 files changed, 266 insertions(+), 7 deletions(-) diff --git a/intern/ffmpeg/tests/ffmpeg_codecs.cc b/intern/ffmpeg/tests/ffmpeg_codecs.cc index d0c40736884..e5c33202417 100644 --- a/intern/ffmpeg/tests/ffmpeg_codecs.cc +++ b/intern/ffmpeg/tests/ffmpeg_codecs.cc @@ -130,6 +130,7 @@ FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_DVVIDEO, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG1VIDEO, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG2VIDEO, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_FLV1, AV_PIX_FMT_YUV420P) +FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_AV1, AV_PIX_FMT_YUV420P) /* Audio codecs */ @@ -149,6 +150,12 @@ FFMPEG_TEST_VCODEC_NAME(libx264, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_NAME(libvpx, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_NAME(libopenjpeg, AV_PIX_FMT_YUV420P) FFMPEG_TEST_VCODEC_NAME(libxvid, AV_PIX_FMT_YUV420P) +/* aom's AV1 encoder is "libaom-av1". FFMPEG_TEST_VCODEC_NAME(libaom-av1, ...) + * will not work because the dash will not work with the test macro. */ +TEST(ffmpeg, libaom_av1_AV_PIX_FMT_YUV420P) +{ + EXPECT_TRUE(test_codec_video_by_name("libaom-av1", AV_PIX_FMT_YUV420P)); +} FFMPEG_TEST_ACODEC_NAME(libvorbis, AV_SAMPLE_FMT_FLTP) FFMPEG_TEST_ACODEC_NAME(libopus, AV_SAMPLE_FMT_FLT) FFMPEG_TEST_ACODEC_NAME(libmp3lame, AV_SAMPLE_FMT_FLTP) diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py index ca0e698500e..61384f25afb 100644 --- a/release/scripts/startup/bl_ui/properties_output.py +++ b/release/scripts/startup/bl_ui/properties_output.py @@ -380,7 +380,14 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel): layout = self.layout ffmpeg = context.scene.render.ffmpeg - needs_codec = ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4', 'WEBM'} + needs_codec = ffmpeg.format in { + 'AVI', + 'QUICKTIME', + 'MKV', + 'OGG', + 'MPEG4', + 'WEBM' + } if needs_codec: layout.prop(ffmpeg, "codec") @@ -391,7 +398,12 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel): layout.prop(ffmpeg, "use_lossless_output") # Output quality - use_crf = needs_codec and ffmpeg.codec in {'H264', 'MPEG4', 'WEBM'} + use_crf = needs_codec and ffmpeg.codec in { + 'H264', + 'MPEG4', + 'WEBM', + 'AV1' + } if use_crf: layout.prop(ffmpeg, "constant_rate_factor") diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 736f7548bb4..cfe246eb470 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -27,6 +27,7 @@ enum { FFMPEG_OGG = 10, FFMPEG_INVALID = 11, FFMPEG_WEBM = 12, + FFMPEG_AV1 = 13, }; enum { @@ -38,6 +39,7 @@ enum { FFMPEG_PRESET_H264 = 5, FFMPEG_PRESET_THEORA = 6, FFMPEG_PRESET_XVID = 7, + FFMPEG_PRESET_AV1 = 8, }; struct RenderData; diff --git a/source/blender/blenkernel/intern/image_format.cc b/source/blender/blenkernel/intern/image_format.cc index 8d1aeac76fb..5b861eff166 100644 --- a/source/blender/blenkernel/intern/image_format.cc +++ b/source/blender/blenkernel/intern/image_format.cc @@ -201,6 +201,7 @@ bool BKE_imtype_is_movie(const char imtype) case R_IMF_IMTYPE_H264: case R_IMF_IMTYPE_THEORA: case R_IMF_IMTYPE_XVID: + case R_IMF_IMTYPE_AV1: return true; } return false; @@ -433,7 +434,8 @@ static bool do_add_image_extension(char *string, R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, - R_IMF_IMTYPE_XVID)) { + R_IMF_IMTYPE_XVID, + R_IMF_IMTYPE_AV1)) { if (!BLI_path_extension_check(string, extension_test = ".png")) { extension = extension_test; } @@ -627,7 +629,8 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf) R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_THEORA, - R_IMF_IMTYPE_XVID)) { + R_IMF_IMTYPE_XVID, + R_IMF_IMTYPE_AV1)) { ibuf->ftype = IMB_FTYPE_PNG; if (imtype == R_IMF_IMTYPE_PNG) { diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index dbdf8cc395d..de2e196c163 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -122,7 +122,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) R_IMF_IMTYPE_FFMPEG, R_IMF_IMTYPE_H264, R_IMF_IMTYPE_XVID, - R_IMF_IMTYPE_THEORA)) { + R_IMF_IMTYPE_THEORA, + R_IMF_IMTYPE_AV1)) { mh.start_movie = BKE_ffmpeg_start; mh.append_movie = BKE_ffmpeg_append; mh.end_movie = BKE_ffmpeg_end; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 99df07b6105..0d3a790ba00 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -299,6 +299,10 @@ static const char **get_file_extensions(int format) static const char *rv[] = {".webm", NULL}; return rv; } + case FFMPEG_AV1: { + static const char *rv[] = {".mp4", ".mkv", NULL}; + return rv; + } default: return NULL; } @@ -455,6 +459,204 @@ static AVRational calc_time_base(uint den, double num, int codec_id) return time_base; } +static const AVCodec *get_av1_encoder( + FFMpegContext *context, RenderData *rd, AVDictionary **opts, int rectx, int recty) +{ + /* There are three possible encoders for AV1: libaom-av1, librav1e, and libsvtav1. librav1e tends + * to give the best compression quality while libsvtav1 tends to be the fastest encoder. One of + * each will be picked based on the preset setting, and if a particular encoder is not available, + * then use the default returned by FFMpeg. */ + const AVCodec *codec = NULL; + switch (context->ffmpeg_preset) { + case FFM_PRESET_BEST: + /* Default to libaom-av1 for BEST preset due to it performing better than rav1e in terms of + * video quality (VMAF scores). Fallback to rav1e if libaom-av1 isn't available. */ + codec = avcodec_find_encoder_by_name("libaom-av1"); + if (!codec) { + codec = avcodec_find_encoder_by_name("librav1e"); + } + break; + case FFM_PRESET_REALTIME: + codec = avcodec_find_encoder_by_name("libsvtav1"); + break; + case FFM_PRESET_GOOD: + default: + codec = avcodec_find_encoder_by_name("libaom-av1"); + break; + } + + /* Use the default AV1 encoder if the specified encoder wasn't found. */ + if (!codec) { + codec = avcodec_find_encoder(AV_CODEC_ID_AV1); + } + + /* Apply AV1 encoder specific settings. */ + if (codec) { + if (strcmp(codec->name, "librav1e") == 0) { + /* Set "tiles" to 8 to enable multi-threaded encoding. */ + if (rd->threads > 8) { + ffmpeg_dict_set_int(opts, "tiles", rd->threads); + } + else { + ffmpeg_dict_set_int(opts, "tiles", 8); + } + + /* Use a reasonable speed setting based on preset. Speed ranges from 0-10. + * Must check context->ffmpeg_preset again in case this encoder was selected due to the + * absence of another. */ + switch (context->ffmpeg_preset) { + case FFM_PRESET_BEST: + ffmpeg_dict_set_int(opts, "speed", 4); + break; + case FFM_PRESET_REALTIME: + ffmpeg_dict_set_int(opts, "speed", 10); + break; + case FFM_PRESET_GOOD: + default: + ffmpeg_dict_set_int(opts, "speed", 6); + break; + } + if (context->ffmpeg_crf >= 0) { + /* librav1e does not use -crf, but uses -qp in the range of 0-255. Calculates the roughly + * equivalent float, and truncates it to an integer. */ + unsigned int qp_value = ((float)context->ffmpeg_crf) * 255.0F / 51.0F; + if (qp_value > 255) { + qp_value = 255; + } + ffmpeg_dict_set_int(opts, "qp", qp_value); + } + /* Set gop_size as rav1e's "--keyint". */ + char buffer[64]; + BLI_snprintf(buffer, sizeof(buffer), "keyint=%d", context->ffmpeg_gop_size); + av_dict_set(opts, "rav1e-params", buffer, 0); + } + else if (strcmp(codec->name, "libsvtav1") == 0) { + /* Set preset value based on ffmpeg_preset. + * Must check context->ffmpeg_preset again in case this encoder was selected due to the + * absence of another. */ + switch (context->ffmpeg_preset) { + case FFM_PRESET_REALTIME: + ffmpeg_dict_set_int(opts, "preset", 8); + break; + case FFM_PRESET_BEST: + ffmpeg_dict_set_int(opts, "preset", 3); + break; + case FFM_PRESET_GOOD: + default: + ffmpeg_dict_set_int(opts, "preset", 5); + break; + } + if (context->ffmpeg_crf >= 0) { + /* libsvtav1 does not support crf until FFmpeg builds since 2022-02-24, use qp as fallback. + */ + ffmpeg_dict_set_int(opts, "qp", context->ffmpeg_crf); + } + } + else if (strcmp(codec->name, "libaom-av1") == 0) { + /* Speed up libaom-av1 encoding by enabling multithreading and setting tiles. */ + ffmpeg_dict_set_int(opts, "row-mt", 1); + const char *tiles_string = NULL; + bool tiles_string_is_dynamic = false; + if (rd->threads > 0) { + /* See if threads is a square. */ + int threads_sqrt = sqrtf(rd->threads); + if (threads_sqrt < 4) { + /* Ensure a default minimum. */ + threads_sqrt = 4; + } + if (is_power_of_2_i(threads_sqrt) && threads_sqrt * threads_sqrt == rd->threads) { + /* Is a square num, therefore just do "sqrt x sqrt" for tiles parameter. */ + int digits = 0; + for (int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) { + ++digits; + } + /* A char array need only an alignment of 1. */ + char *tiles_string_mut = (char *)calloc(digits * 2 + 2, 1); + BLI_snprintf(tiles_string_mut, digits * 2 + 2, "%dx%d", threads_sqrt, threads_sqrt); + tiles_string_is_dynamic = true; + tiles_string = tiles_string_mut; + } + else { + /* Is not a square num, set greater side based on longer side, or use a square if both + sides are equal. */ + int sqrt_p2 = power_of_2_min_i(threads_sqrt); + if (sqrt_p2 < 2) { + /* Ensure a default minimum. */ + sqrt_p2 = 2; + } + int sqrt_p2_next = power_of_2_min_i((int)rd->threads / sqrt_p2); + if (sqrt_p2_next < 1) { + sqrt_p2_next = 1; + } + if (sqrt_p2 > sqrt_p2_next) { + /* Ensure sqrt_p2_next is greater or equal to sqrt_p2. */ + int temp = sqrt_p2; + sqrt_p2 = sqrt_p2_next; + sqrt_p2_next = temp; + } + int combined_digits = 0; + for (int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) { + ++combined_digits; + } + for (int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) { + ++combined_digits; + } + /* A char array need only an alignment of 1. */ + char *tiles_string_mut = (char *)calloc(combined_digits + 2, 1); + if (rectx > recty) { + BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2_next, sqrt_p2); + } + else if (rectx < recty) { + BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2_next); + } + else { + BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2); + } + tiles_string_is_dynamic = true; + tiles_string = tiles_string_mut; + } + } + else { + /* Thread count unknown, default to 8. */ + if (rectx > recty) { + tiles_string = "4x2"; + } + else if (rectx < recty) { + tiles_string = "2x4"; + } + else { + tiles_string = "2x2"; + } + } + av_dict_set(opts, "tiles", tiles_string, 0); + if (tiles_string_is_dynamic) { + free((void *)tiles_string); + } + /* libaom-av1 uses "cpu-used" instead of "preset" for defining compression quality. + * This value is in a range from 0-8. 0 and 8 are extremes, but we will allow 8. + * Must check context->ffmpeg_preset again in case this encoder was selected due to the + * absence of another. */ + switch (context->ffmpeg_preset) { + case FFM_PRESET_REALTIME: + ffmpeg_dict_set_int(opts, "cpu-used", 8); + break; + case FFM_PRESET_BEST: + ffmpeg_dict_set_int(opts, "cpu-used", 4); + break; + case FFM_PRESET_GOOD: + default: + ffmpeg_dict_set_int(opts, "cpu-used", 6); + break; + } + + /* CRF related settings is similar to H264 for libaom-av1, so we will rely on those settings + * applied later. */ + } + } + + return codec; +} + /* prepare a video stream for the output file */ static AVStream *alloc_video_stream(FFMpegContext *context, @@ -480,7 +682,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context, /* Set up the codec context */ - codec = avcodec_find_encoder(codec_id); + if (codec_id == AV_CODEC_ID_AV1) { + /* Use get_av1_encoder() to get the ideal (hopefully) encoder for AV1 based + * on given parameters, and also set up opts. */ + codec = get_av1_encoder(context, rd, &opts, rectx, recty); + } + else { + codec = avcodec_find_encoder(codec_id); + } if (!codec) { fprintf(stderr, "Couldn't find valid video codec\n"); context->video_codec = NULL; @@ -568,7 +777,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context, default: printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset); } - if (preset_name != NULL) { + /* "codec_id != AV_CODEC_ID_AV1" is required due to "preset" already being set by an AV1 codec. + */ + if (preset_name != NULL && codec_id != AV_CODEC_ID_AV1) { av_dict_set(&opts, "preset", preset_name, 0); } if (deadline_name != NULL) { @@ -951,6 +1162,9 @@ static int start_ffmpeg_impl(FFMpegContext *context, case FFMPEG_FLV: video_codec = AV_CODEC_ID_FLV1; break; + case FFMPEG_AV1: + video_codec = AV_CODEC_ID_AV1; + break; default: /* These containers are not restricted to any specific codec types. * Currently we expect these to be .avi, .mov, .mkv, and .mp4. @@ -1481,6 +1695,18 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset) rd->ffcodecdata.rc_buffer_size = 224 * 8; rd->ffcodecdata.mux_packet_size = 2048; rd->ffcodecdata.mux_rate = 10080000; + break; + case FFMPEG_PRESET_AV1: + rd->ffcodecdata.type = FFMPEG_AV1; + rd->ffcodecdata.codec = AV_CODEC_ID_AV1; + rd->ffcodecdata.video_bitrate = 6000; + rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224 * 8; + rd->ffcodecdata.mux_packet_size = 2048; + rd->ffcodecdata.mux_rate = 10080000; + break; } } @@ -1521,6 +1747,12 @@ void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf) audio = 1; } } + else if (imf->imtype == R_IMF_IMTYPE_AV1) { + if (rd->ffcodecdata.codec != AV_CODEC_ID_AV1) { + BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_AV1); + audio = 1; + } + } if (audio && rd->ffcodecdata.audio_codec < 0) { rd->ffcodecdata.audio_codec = AV_CODEC_ID_NONE; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 5fa5d4c7787..28359038be5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -472,6 +472,7 @@ typedef struct ImageFormatData { #define R_IMF_IMTYPE_THEORA 33 #define R_IMF_IMTYPE_PSD 34 #define R_IMF_IMTYPE_WEBP 35 +#define R_IMF_IMTYPE_AV1 36 #define R_IMF_IMTYPE_INVALID 255 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 0eb168ecd8e..58455ff7de5 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5928,6 +5928,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) {FFMPEG_MKV, "MKV", 0, "Matroska", ""}, {FFMPEG_FLV, "FLASH", 0, "Flash", ""}, {FFMPEG_WEBM, "WEBM", 0, "WebM", ""}, + {AV_CODEC_ID_AV1, "AV1", 0, "AV1", ""}, {0, NULL, 0, NULL, NULL}, }; -- cgit v1.2.3 From 23c05a916c286a6ec9149b69f7ca5651c2522136 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 22 Oct 2022 16:49:05 +1100 Subject: GHOST/Wayland: support changing seat capabilities at run-time --- intern/ghost/intern/GHOST_SystemWayland.cpp | 162 +++++++++++++++++++--------- 1 file changed, 114 insertions(+), 48 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 68ad028631c..6eef9a48e07 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -84,6 +84,10 @@ static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat); static void output_handle_done(void *data, struct wl_output *wl_output); +static void gwl_seat_capability_pointer_disable(GWL_Seat *seat); +static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat); +static void gwl_seat_capability_touch_disable(GWL_Seat *seat); + /* -------------------------------------------------------------------- */ /** \name Local Defines * @@ -808,28 +812,14 @@ static void display_destroy(GWL_Display *display) munmap(seat->cursor.custom_data, seat->cursor.custom_data_size); } - if (seat->wl_pointer) { - if (seat->cursor.wl_surface) { - wl_surface_destroy(seat->cursor.wl_surface); - } - if (seat->cursor.wl_theme) { - wl_cursor_theme_destroy(seat->cursor.wl_theme); - } - if (seat->wl_pointer) { - wl_pointer_destroy(seat->wl_pointer); - } - } - - if (seat->wl_touch) { - wl_touch_destroy(seat->wl_touch); - } - - if (seat->wl_keyboard) { - if (seat->key_repeat.timer) { - keyboard_handle_key_repeat_cancel(seat); - } - wl_keyboard_destroy(seat->wl_keyboard); - } + /* Disable all capabilities as a way to free: + * - `seat.wl_pointer` (and related cursor variables). + * - `seat.wl_touch`. + * - `seat.wl_keyboard`. + */ + gwl_seat_capability_pointer_disable(seat); + gwl_seat_capability_keyboard_disable(seat); + gwl_seat_capability_touch_disable(seat); /* Un-referencing checks for NULL case. */ xkb_state_unref(seat->xkb_state); @@ -3304,6 +3294,83 @@ static const struct zwp_primary_selection_source_v1_listener primary_selection_s static CLG_LogRef LOG_WL_SEAT = {"ghost.wl.handle.seat"}; #define LOG (&LOG_WL_SEAT) +static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) +{ + if (seat->wl_pointer) { + return; + } + seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat); + seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); + seat->cursor.visible = true; + seat->cursor.wl_buffer = nullptr; + if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) { + seat->cursor.theme_name = std::string(); + seat->cursor.theme_size = default_cursor_size; + } + wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); + + wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, seat); + ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); +} + +static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) +{ + if (!seat->wl_pointer) { + return; + } + if (seat->cursor.wl_surface) { + wl_surface_destroy(seat->cursor.wl_surface); + seat->cursor.wl_surface = nullptr; + } + if (seat->cursor.wl_theme) { + wl_cursor_theme_destroy(seat->cursor.wl_theme); + seat->cursor.wl_theme = nullptr; + } + + wl_pointer_destroy(seat->wl_pointer); + seat->wl_pointer = nullptr; +} + +static void gwl_seat_capability_keyboard_enable(GWL_Seat *seat) +{ + if (seat->wl_keyboard) { + return; + } + seat->wl_keyboard = wl_seat_get_keyboard(seat->wl_seat); + wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, seat); +} + +static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat) +{ + if (!seat->wl_keyboard) { + return; + } + if (seat->key_repeat.timer) { + keyboard_handle_key_repeat_cancel(seat); + } + wl_keyboard_destroy(seat->wl_keyboard); + seat->wl_keyboard = nullptr; +} + +static void gwl_seat_capability_touch_enable(GWL_Seat *seat) +{ + if (seat->wl_touch) { + return; + } + seat->wl_touch = wl_seat_get_touch(seat->wl_seat); + wl_touch_set_user_data(seat->wl_touch, seat); + wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat); +} + +static void gwl_seat_capability_touch_disable(GWL_Seat *seat) +{ + if (!seat->wl_touch) { + return; + } + wl_touch_destroy(seat->wl_touch); + seat->wl_touch = nullptr; +} + static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, const uint32_t capabilities) @@ -3316,44 +3383,43 @@ static void seat_handle_capabilities(void *data, (capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0); GWL_Seat *seat = static_cast(data); - seat->wl_pointer = nullptr; - seat->wl_keyboard = nullptr; + GHOST_ASSERT(seat->wl_seat == wl_seat, "Seat mismatch"); if (capabilities & WL_SEAT_CAPABILITY_POINTER) { - seat->wl_pointer = wl_seat_get_pointer(wl_seat); - seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor()); - seat->cursor.visible = true; - seat->cursor.wl_buffer = nullptr; - if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) { - seat->cursor.theme_name = std::string(); - seat->cursor.theme_size = default_cursor_size; - } - wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data); + gwl_seat_capability_pointer_enable(seat); + } + else { + gwl_seat_capability_pointer_disable(seat); + } - wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, data); - ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); + if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { + gwl_seat_capability_keyboard_enable(seat); + } + else { + gwl_seat_capability_keyboard_disable(seat); } if (capabilities & WL_SEAT_CAPABILITY_TOUCH) { - seat->wl_touch = wl_seat_get_touch(wl_seat); - wl_touch_set_user_data(seat->wl_touch, seat); - wl_touch_add_listener(seat->wl_touch, &touch_seat_listener, seat); + gwl_seat_capability_touch_enable(seat); } - - if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) { - seat->wl_keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(seat->wl_keyboard, &keyboard_listener, data); + else { + gwl_seat_capability_touch_disable(seat); } + /* TODO(@campbellbarton): this could be moved out elsewhere. */ if (seat->system) { zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = seat->system->wl_primary_selection_manager(); - seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( - primary_selection_device_manager, seat->wl_seat); - - zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, - &primary_selection_device_listener, - &seat->primary_selection); + if (primary_selection_device_manager) { + if (seat->primary_selection_device == nullptr) { + seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + primary_selection_device_manager, seat->wl_seat); + + zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, + &primary_selection_device_listener, + &seat->primary_selection); + } + } } } -- cgit v1.2.3 From e54ea0f90ee22396147ad6d17d0263bf6b965fd7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 22 Oct 2022 16:49:07 +1100 Subject: Cleanup: use wl_/wp_ prefix to match native Wayland types --- intern/ghost/intern/GHOST_SystemWayland.cpp | 166 ++++++++++++++-------------- intern/ghost/intern/GHOST_SystemWayland.h | 2 +- 2 files changed, 85 insertions(+), 83 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 6eef9a48e07..39f392e62b9 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -522,7 +522,7 @@ struct GWL_PrimarySelection_DataOffer { }; struct GWL_PrimarySelection_DataSource { - struct zwp_primary_selection_source_v1 *wl_source = nullptr; + struct zwp_primary_selection_source_v1 *wp_source = nullptr; GWL_SimpleBuffer buffer_out; }; @@ -553,8 +553,8 @@ static void gwl_primary_selection_discard_source(GWL_PrimarySelection *primary) return; } gwl_simple_buffer_free_data(&data_source->buffer_out); - if (data_source->wl_source) { - zwp_primary_selection_source_v1_destroy(data_source->wl_source); + if (data_source->wp_source) { + zwp_primary_selection_source_v1_destroy(data_source->wp_source); } delete primary->data_source; primary->data_source = nullptr; @@ -568,7 +568,7 @@ struct GWL_Seat { struct wl_pointer *wl_pointer = nullptr; struct wl_touch *wl_touch = nullptr; struct wl_keyboard *wl_keyboard = nullptr; - struct zwp_tablet_seat_v2 *tablet_seat = nullptr; + struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr; /** All currently active tablet tools (needed for changing the cursor). */ std::unordered_set tablet_tools; @@ -592,9 +592,9 @@ struct GWL_Seat { struct GWL_Cursor cursor; - struct zwp_relative_pointer_v1 *relative_pointer = nullptr; - struct zwp_locked_pointer_v1 *locked_pointer = nullptr; - struct zwp_confined_pointer_v1 *confined_pointer = nullptr; + struct zwp_relative_pointer_v1 *wp_relative_pointer = nullptr; + struct zwp_locked_pointer_v1 *wp_locked_pointer = nullptr; + struct zwp_confined_pointer_v1 *wp_confined_pointer = nullptr; struct xkb_context *xkb_context = nullptr; @@ -637,7 +637,7 @@ struct GWL_Seat { struct wl_surface *wl_surface_focus_dnd = nullptr; - struct wl_data_device *data_device = nullptr; + struct wl_data_device *wl_data_device = nullptr; /** Drag & Drop. */ struct GWL_DataOffer *data_offer_dnd = nullptr; std::mutex data_offer_dnd_mutex; @@ -649,7 +649,7 @@ struct GWL_Seat { struct GWL_DataSource *data_source = nullptr; std::mutex data_source_mutex; - struct zwp_primary_selection_device_v1 *primary_selection_device = nullptr; + struct zwp_primary_selection_device_v1 *wp_primary_selection_device = nullptr; struct GWL_PrimarySelection primary_selection; /** Last device that was active. */ @@ -679,12 +679,12 @@ struct GWL_Display { std::vector outputs; std::vector seats; - struct wl_data_device_manager *data_device_manager = nullptr; - struct zwp_tablet_manager_v2 *tablet_manager = nullptr; - struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr; - struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr; + struct wl_data_device_manager *wl_data_device_manager = nullptr; + struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr; + struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr; + struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr; - struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = nullptr; + struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; GWL_SimpleBuffer clipboard; GWL_SimpleBuffer clipboard_primary; @@ -744,12 +744,12 @@ static GWL_SeatStatePointer *seat_state_pointer_from_cursor_surface(GWL_Seat *se static void display_destroy(GWL_Display *display) { - if (display->data_device_manager) { - wl_data_device_manager_destroy(display->data_device_manager); + if (display->wl_data_device_manager) { + wl_data_device_manager_destroy(display->wl_data_device_manager); } - if (display->tablet_manager) { - zwp_tablet_manager_v2_destroy(display->tablet_manager); + if (display->wp_tablet_manager) { + zwp_tablet_manager_v2_destroy(display->wp_tablet_manager); } for (GWL_Output *output : display->outputs) { @@ -800,12 +800,12 @@ static void display_destroy(GWL_Display *display) gwl_primary_selection_discard_source(primary); } - if (seat->primary_selection_device) { - zwp_primary_selection_device_v1_destroy(seat->primary_selection_device); + if (seat->wp_primary_selection_device) { + zwp_primary_selection_device_v1_destroy(seat->wp_primary_selection_device); } - if (seat->data_device) { - wl_data_device_release(seat->data_device); + if (seat->wl_data_device) { + wl_data_device_release(seat->wl_data_device); } if (seat->cursor.custom_data) { @@ -836,16 +836,16 @@ static void display_destroy(GWL_Display *display) wl_shm_destroy(display->wl_shm); } - if (display->relative_pointer_manager) { - zwp_relative_pointer_manager_v1_destroy(display->relative_pointer_manager); + if (display->wp_relative_pointer_manager) { + zwp_relative_pointer_manager_v1_destroy(display->wp_relative_pointer_manager); } - if (display->pointer_constraints) { - zwp_pointer_constraints_v1_destroy(display->pointer_constraints); + if (display->wp_pointer_constraints) { + zwp_pointer_constraints_v1_destroy(display->wp_pointer_constraints); } - if (display->primary_selection_device_manager) { - zwp_primary_selection_device_manager_v1_destroy(display->primary_selection_device_manager); + if (display->wp_primary_selection_device_manager) { + zwp_primary_selection_device_manager_v1_destroy(display->wp_primary_selection_device_manager); } if (display->wl_compositor) { @@ -1033,9 +1033,9 @@ static int pointer_axis_as_index(const uint32_t axis) } } -static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wl_tablet_tool_type) +static GHOST_TTabletMode tablet_tool_map_type(enum zwp_tablet_tool_v2_type wp_tablet_tool_type) { - switch (wl_tablet_tool_type) { + switch (wp_tablet_tool_type) { case ZWP_TABLET_TOOL_V2_TYPE_ERASER: { return GHOST_kTabletModeEraser; } @@ -3273,7 +3273,7 @@ static void primary_selection_source_cancelled(void *data, GWL_PrimarySelection *primary = static_cast(data); - if (source == primary->data_source->wl_source) { + if (source == primary->data_source->wp_source) { gwl_primary_selection_discard_source(primary); } } @@ -3409,13 +3409,13 @@ static void seat_handle_capabilities(void *data, /* TODO(@campbellbarton): this could be moved out elsewhere. */ if (seat->system) { zwp_primary_selection_device_manager_v1 *primary_selection_device_manager = - seat->system->wl_primary_selection_manager(); + seat->system->wp_primary_selection_manager(); if (primary_selection_device_manager) { - if (seat->primary_selection_device == nullptr) { - seat->primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( + if (seat->wp_primary_selection_device == nullptr) { + seat->wp_primary_selection_device = zwp_primary_selection_device_manager_v1_get_device( primary_selection_device_manager, seat->wl_seat); - zwp_primary_selection_device_v1_add_listener(seat->primary_selection_device, + zwp_primary_selection_device_v1_add_listener(seat->wp_primary_selection_device, &primary_selection_device_listener, &seat->primary_selection); } @@ -3776,23 +3776,23 @@ static void global_handle_add(void *data, wl_registry_bind(wl_registry, name, &wl_shm_interface, 1)); } else if (STREQ(interface, wl_data_device_manager_interface.name)) { - display->data_device_manager = static_cast( + display->wl_data_device_manager = static_cast( wl_registry_bind(wl_registry, name, &wl_data_device_manager_interface, 3)); } else if (STREQ(interface, zwp_tablet_manager_v2_interface.name)) { - display->tablet_manager = static_cast( + display->wp_tablet_manager = static_cast( wl_registry_bind(wl_registry, name, &zwp_tablet_manager_v2_interface, 1)); } else if (STREQ(interface, zwp_relative_pointer_manager_v1_interface.name)) { - display->relative_pointer_manager = static_cast( + display->wp_relative_pointer_manager = static_cast( wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1)); } else if (STREQ(interface, zwp_pointer_constraints_v1_interface.name)) { - display->pointer_constraints = static_cast( + display->wp_pointer_constraints = static_cast( wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); } else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) { - display->primary_selection_device_manager = + display->wp_primary_selection_device_manager = static_cast(wl_registry_bind( wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1)); } @@ -3915,19 +3915,19 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), display_(new GWL_Di } /* Register data device per seat for IPC between Wayland clients. */ - if (display_->data_device_manager) { + if (display_->wl_data_device_manager) { for (GWL_Seat *seat : display_->seats) { - seat->data_device = wl_data_device_manager_get_data_device(display_->data_device_manager, - seat->wl_seat); - wl_data_device_add_listener(seat->data_device, &data_device_listener, seat); + seat->wl_data_device = wl_data_device_manager_get_data_device( + display_->wl_data_device_manager, seat->wl_seat); + wl_data_device_add_listener(seat->wl_data_device, &data_device_listener, seat); } } - if (display_->tablet_manager) { + if (display_->wp_tablet_manager) { for (GWL_Seat *seat : display_->seats) { - seat->tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->tablet_manager, - seat->wl_seat); - zwp_tablet_seat_v2_add_listener(seat->tablet_seat, &tablet_seat_listener, seat); + seat->wp_tablet_seat = zwp_tablet_manager_v2_get_tablet_seat(display_->wp_tablet_manager, + seat->wl_seat); + zwp_tablet_seat_v2_add_listener(seat->wp_tablet_seat, &tablet_seat_listener, seat); } } } @@ -4075,7 +4075,7 @@ char *GHOST_SystemWayland::getClipboard(bool selection) const static void system_clipboard_put_primary_selection(GWL_Display *display, const char *buffer) { - if (!display->primary_selection_device_manager) { + if (!display->wp_primary_selection_device_manager) { return; } GWL_Seat *seat = display->seats[0]; @@ -4091,19 +4091,19 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c /* Copy buffer. */ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); - data_source->wl_source = zwp_primary_selection_device_manager_v1_create_source( - display->primary_selection_device_manager); + data_source->wp_source = zwp_primary_selection_device_manager_v1_create_source( + display->wp_primary_selection_device_manager); zwp_primary_selection_source_v1_add_listener( - data_source->wl_source, &primary_selection_source_listener, primary); + data_source->wp_source, &primary_selection_source_listener, primary); for (const std::string &type : mime_send) { - zwp_primary_selection_source_v1_offer(data_source->wl_source, type.c_str()); + zwp_primary_selection_source_v1_offer(data_source->wp_source, type.c_str()); } - if (seat->primary_selection_device) { + if (seat->wp_primary_selection_device) { zwp_primary_selection_device_v1_set_selection( - seat->primary_selection_device, data_source->wl_source, seat->data_source_serial); + seat->wp_primary_selection_device, data_source->wp_source, seat->data_source_serial); } } @@ -4118,7 +4118,8 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) /* Copy buffer. */ gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer); - data_source->wl_source = wl_data_device_manager_create_data_source(display->data_device_manager); + data_source->wl_source = wl_data_device_manager_create_data_source( + display->wl_data_device_manager); wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat); @@ -4126,15 +4127,15 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer) wl_data_source_offer(data_source->wl_source, type.c_str()); } - if (seat->data_device) { + if (seat->wl_data_device) { wl_data_device_set_selection( - seat->data_device, data_source->wl_source, seat->data_source_serial); + seat->wl_data_device, data_source->wl_source, seat->data_source_serial); } } void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const { - if (UNLIKELY(!display_->data_device_manager || display_->seats.empty())) { + if (UNLIKELY(!display_->wl_data_device_manager || display_->seats.empty())) { return; } @@ -4171,7 +4172,7 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat, /* NOTE: WAYLAND doesn't support warping the cursor. * However when grab is enabled, we already simulate a cursor location * so that can be set to a new location. */ - if (!seat->relative_pointer) { + if (!seat->wp_relative_pointer) { return GHOST_kFailure; } const wl_fixed_t scale = win->scale(); @@ -4886,9 +4887,9 @@ wl_compositor *GHOST_SystemWayland::wl_compositor() return display_->wl_compositor; } -struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wl_primary_selection_manager() +struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wp_primary_selection_manager() { - return display_->primary_selection_device_manager; + return display_->wp_primary_selection_device_manager; } #ifdef WITH_GHOST_WAYLAND_LIBDECOR @@ -4980,7 +4981,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod const int scale) { /* Ignore, if the required protocols are not supported. */ - if (UNLIKELY(!display_->relative_pointer_manager || !display_->pointer_constraints)) { + if (UNLIKELY(!display_->wp_relative_pointer_manager || !display_->wp_pointer_constraints)) { return GHOST_kFailure; } @@ -5019,11 +5020,11 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod * in this case disable the current locks as it makes logic confusing, * postpone changing the cursor to avoid flickering. */ if (!grab_state_next.use_lock) { - if (seat->relative_pointer) { - zwp_relative_pointer_v1_destroy(seat->relative_pointer); - seat->relative_pointer = nullptr; + if (seat->wp_relative_pointer) { + zwp_relative_pointer_v1_destroy(seat->wp_relative_pointer); + seat->wp_relative_pointer = nullptr; } - if (seat->locked_pointer) { + if (seat->wp_locked_pointer) { /* Potentially add a motion event so the application has updated X/Y coordinates. */ int32_t xy_motion[2] = {0, 0}; bool xy_motion_create_event = false; @@ -5052,7 +5053,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod seat->pointer.xy[0] = xy_next[0]; seat->pointer.xy[1] = xy_next[1]; - zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next)); + zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, UNPACK2(xy_next)); wl_surface_commit(wl_surface); } else if (mode_current == GHOST_kGrabHide) { @@ -5062,7 +5063,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod wl_fixed_from_int(init_grab_xy[0]) / scale, wl_fixed_from_int(init_grab_xy[1]) / scale, }; - zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, UNPACK2(xy_next)); + zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, + UNPACK2(xy_next)); wl_surface_commit(wl_surface); /* NOTE(@campbellbarton): The new cursor position is a hint, @@ -5076,7 +5078,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod #ifdef USE_GNOME_CONFINE_HACK else if (mode_current == GHOST_kGrabNormal) { if (was_software_confine) { - zwp_locked_pointer_v1_set_cursor_position_hint(seat->locked_pointer, + zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer, UNPACK2(seat->pointer.xy)); wl_surface_commit(wl_surface); } @@ -5092,15 +5094,15 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod GHOST_TABLET_DATA_NONE)); } - zwp_locked_pointer_v1_destroy(seat->locked_pointer); - seat->locked_pointer = nullptr; + zwp_locked_pointer_v1_destroy(seat->wp_locked_pointer); + seat->wp_locked_pointer = nullptr; } } if (!grab_state_next.use_confine) { - if (seat->confined_pointer) { - zwp_confined_pointer_v1_destroy(seat->confined_pointer); - seat->confined_pointer = nullptr; + if (seat->wp_confined_pointer) { + zwp_confined_pointer_v1_destroy(seat->wp_confined_pointer); + seat->wp_confined_pointer = nullptr; } } @@ -5111,12 +5113,12 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod * possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates. * An alternative could be to draw the cursor in software (and hide the real cursor), * or just accept a locked cursor on WAYLAND. */ - seat->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( - display_->relative_pointer_manager, seat->wl_pointer); + seat->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer( + display_->wp_relative_pointer_manager, seat->wl_pointer); zwp_relative_pointer_v1_add_listener( - seat->relative_pointer, &relative_pointer_listener, seat); - seat->locked_pointer = zwp_pointer_constraints_v1_lock_pointer( - display_->pointer_constraints, + seat->wp_relative_pointer, &relative_pointer_listener, seat); + seat->wp_locked_pointer = zwp_pointer_constraints_v1_lock_pointer( + display_->wp_pointer_constraints, wl_surface, seat->wl_pointer, nullptr, @@ -5133,8 +5135,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod } else if (grab_state_next.use_confine) { if (!grab_state_prev.use_confine) { - seat->confined_pointer = zwp_pointer_constraints_v1_confine_pointer( - display_->pointer_constraints, + seat->wp_confined_pointer = zwp_pointer_constraints_v1_confine_pointer( + display_->wp_pointer_constraints, wl_surface, seat->wl_pointer, nullptr, diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 23ffabf739e..c19791fd792 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -158,7 +158,7 @@ class GHOST_SystemWayland : public GHOST_System { struct wl_display *wl_display(); struct wl_compositor *wl_compositor(); - struct zwp_primary_selection_device_manager_v1 *wl_primary_selection_manager(); + struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_manager(); #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *libdecor_context(); -- cgit v1.2.3 From 8bb211a771642144ac75ba6be0c1897c836a6276 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 22 Oct 2022 16:49:09 +1100 Subject: GHOST/Wayland: multi-touch gesture support Add support for zoom & rotate gestures, hold and swipe may be used in the future although swipe maps to 2D smooth-scroll for Gnome & KDE. Tested to work with Apple track-pad & Wacom tablet on Gnome & KDE. --- intern/ghost/CMakeLists.txt | 4 + intern/ghost/intern/GHOST_SystemWayland.cpp | 322 +++++++++++++++++++++++++++- intern/ghost/intern/GHOST_SystemWayland.h | 1 + 3 files changed, 325 insertions(+), 2 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index c05f2a327b1..fb10530bfae 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -372,6 +372,10 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND) generate_protocol_bindings( "${WAYLAND_PROTOCOLS_DIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml" ) + # Pointer-gestures (multi-touch). + generate_protocol_bindings( + "${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml" + ) # Tablet. generate_protocol_bindings( "${WAYLAND_PROTOCOLS_DIR}/unstable/tablet/tablet-unstable-v2.xml" diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 39f392e62b9..442e51d4f7c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -51,6 +51,7 @@ /* Generated by `wayland-scanner`. */ #include +#include #include #include #include @@ -461,6 +462,39 @@ struct GWL_SeatStatePointerScroll { enum wl_pointer_axis_source axis_source = WL_POINTER_AXIS_SOURCE_WHEEL; }; +/** + * Utility struct to access rounded values from a scaled `wl_fixed_t`, + * without loosing information. + * + * As the rounded result is rounded to a lower precision integer, + * the high precision value is accumulated and converted to an integer to + * prevent the accumulation of rounded values giving an inaccurate result. + * + * \note This is simple but doesn't read well when expanded multiple times inline. + */ +struct GWL_ScaledFixedT { + wl_fixed_t value = 0; + wl_fixed_t factor = 1; +}; + +static int gwl_scaled_fixed_t_add_and_calc_rounded_delta(GWL_ScaledFixedT *sf, + const wl_fixed_t add) +{ + const int result_prev = wl_fixed_to_int(sf->value * sf->factor); + sf->value += add; + const int result_curr = wl_fixed_to_int(sf->value * sf->factor); + return result_curr - result_prev; +} + +/** + * Gesture state. + * This is needed so the gesture values can be converted to deltas. + */ +struct GWL_SeatStatePointerGesture_Pinch { + GWL_ScaledFixedT scale; + GWL_ScaledFixedT rotation; +}; + /** * State of the keyboard (in #GWL_Seat). */ @@ -570,6 +604,10 @@ struct GWL_Seat { struct wl_keyboard *wl_keyboard = nullptr; struct zwp_tablet_seat_v2 *wp_tablet_seat = nullptr; + struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold = nullptr; + struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch = nullptr; + struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe = nullptr; + /** All currently active tablet tools (needed for changing the cursor). */ std::unordered_set tablet_tools; @@ -578,6 +616,7 @@ struct GWL_Seat { GWL_SeatStatePointer pointer; GWL_SeatStatePointerScroll pointer_scroll; + GWL_SeatStatePointerGesture_Pinch pointer_gesture_pinch; /** Mostly this can be interchanged with `pointer` however it can't be locked/confined. */ GWL_SeatStatePointer tablet; @@ -683,6 +722,7 @@ struct GWL_Display { struct zwp_tablet_manager_v2 *wp_tablet_manager = nullptr; struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr; struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr; + struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr; struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr; @@ -844,8 +884,8 @@ static void display_destroy(GWL_Display *display) zwp_pointer_constraints_v1_destroy(display->wp_pointer_constraints); } - if (display->wp_primary_selection_device_manager) { - zwp_primary_selection_device_manager_v1_destroy(display->wp_primary_selection_device_manager); + if (display->wp_pointer_gestures) { + zwp_pointer_gestures_v1_destroy(display->wp_pointer_gestures); } if (display->wl_compositor) { @@ -2269,6 +2309,223 @@ static const struct wl_pointer_listener pointer_listener = { /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Listener (Pointer Gesture: Hold), #zwp_pointer_gesture_hold_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_POINTER_GESTURE_HOLD = {"ghost.wl.handle.pointer_gesture.hold"}; +#define LOG (&LOG_WL_POINTER_GESTURE_HOLD) + +static void gesture_hold_handle_begin( + void * /*data*/, + struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*surface*/, + uint32_t fingers) +{ + CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers); +} + +static void gesture_hold_handle_end( + void * /*data*/, + struct zwp_pointer_gesture_hold_v1 * /*zwp_pointer_gesture_hold_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t cancelled) +{ + CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled); +} + +static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener = { + gesture_hold_handle_begin, + gesture_hold_handle_end, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Pointer Gesture: Pinch), #zwp_pointer_gesture_pinch_v1_listener + * \{ */ + +static CLG_LogRef LOG_WL_POINTER_GESTURE_PINCH = {"ghost.wl.handle.pointer_gesture.pinch"}; +#define LOG (&LOG_WL_POINTER_GESTURE_PINCH) + +static void gesture_pinch_handle_begin(void *data, + struct zwp_pointer_gesture_pinch_v1 * /*pinch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*surface*/, + uint32_t fingers) +{ + CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers); + GWL_Seat *seat = static_cast(data); + /* Reset defaults. */ + seat->pointer_gesture_pinch = GWL_SeatStatePointerGesture_Pinch{}; + + GHOST_WindowWayland *win = nullptr; + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + win = ghost_wl_surface_user_data(wl_surface_focus); + } + const wl_fixed_t win_scale = win ? win->scale() : 1; + + /* NOTE(@campbellbarton): Scale factors match Blender's operators & default preferences. + * For these values to work correctly, operator logic will need to be changed not to scale input + * by the region size (as with 3D view zoom) or preference for 3D view orbit sensitivity. + * + * By working "correctly" I mean that a rotation action where the users fingers rotate to + * opposite locations should always rotate the viewport 180d, since users will expect the + * physical location of their fingers to match the viewport. + * Similarly with zoom, the scale value from the pinch action can be mapped to a zoom level + * although unlike rotation, an inexact mapping is less noticeable. + * Users may even prefer the zoom level to be scaled - which could be a preference. */ + seat->pointer_gesture_pinch.scale.value = wl_fixed_from_int(1); + /* The value 300 matches a value used in clip & image zoom operators. + * It seems OK for the 3D view too. */ + seat->pointer_gesture_pinch.scale.factor = 300 * win_scale; + /* The value 5 is used on macOS and roughly maps 1:1 with turntable rotation, + * although preferences can scale the sensitivity (which would be skipped ideally). */ + seat->pointer_gesture_pinch.rotation.factor = 5 * win_scale; +} + +static void gesture_pinch_handle_update(void *data, + struct zwp_pointer_gesture_pinch_v1 * /*pinch*/, + uint32_t /*time*/, + wl_fixed_t dx, + wl_fixed_t dy, + wl_fixed_t scale, + wl_fixed_t rotation) +{ + CLOG_INFO(LOG, + 2, + "update (dx=%.3f, dy=%.3f, scale=%.3f, rotation=%.3f)", + wl_fixed_to_double(dx), + wl_fixed_to_double(dy), + wl_fixed_to_double(scale), + wl_fixed_to_double(rotation)); + + GWL_Seat *seat = static_cast(data); + + GHOST_WindowWayland *win = nullptr; + + if (wl_surface *wl_surface_focus = seat->pointer.wl_surface) { + win = ghost_wl_surface_user_data(wl_surface_focus); + } + + /* Scale defaults to `wl_fixed_from_int(1)` which may change while pinching. + * This needs to be converted to a delta. */ + const wl_fixed_t scale_delta = scale - seat->pointer_gesture_pinch.scale.value; + const int scale_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta( + &seat->pointer_gesture_pinch.scale, scale_delta); + + /* Rotation in degrees, unlike scale this is a delta. */ + const int rotation_as_delta_px = gwl_scaled_fixed_t_add_and_calc_rounded_delta( + &seat->pointer_gesture_pinch.rotation, rotation); + + if (win) { + const wl_fixed_t win_scale = win->scale(); + const int32_t event_xy[2] = { + wl_fixed_to_int(win_scale * seat->pointer.xy[0]), + wl_fixed_to_int(win_scale * seat->pointer.xy[1]), + }; + if (scale_as_delta_px) { + seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(), + win, + GHOST_kTrackpadEventMagnify, + event_xy[0], + event_xy[1], + scale_as_delta_px, + 0, + false)); + } + + if (rotation_as_delta_px) { + seat->system->pushEvent(new GHOST_EventTrackpad(seat->system->getMilliSeconds(), + win, + GHOST_kTrackpadEventRotate, + event_xy[0], + event_xy[1], + rotation_as_delta_px, + 0, + false)); + } + } +} + +static void gesture_pinch_handle_end(void * /*data*/, + struct zwp_pointer_gesture_pinch_v1 * /*pinch*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t cancelled) +{ + CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled); +} + +static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_listener = { + gesture_pinch_handle_begin, + gesture_pinch_handle_update, + gesture_pinch_handle_end, +}; + +#undef LOG + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Listener (Pointer Gesture: Swipe), #zwp_pointer_gesture_swipe_v1 + * + * \note In both Gnome-Shell & KDE this gesture isn't emitted at time of writing, + * instead, high resolution 2D #wl_pointer_listener.axis data is generated which works well. + * There may be some situations where WAYLAND compositors generate this gesture + * (swiping with 3+ fingers, for e.g.). So keep this to allow logging & testing gestures. + * \{ */ + +static CLG_LogRef LOG_WL_POINTER_GESTURE_SWIPE = {"ghost.wl.handle.pointer_gesture.swipe"}; +#define LOG (&LOG_WL_POINTER_GESTURE_SWIPE) + +static void gesture_swipe_handle_begin( + void * /*data*/, + struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + struct wl_surface * /*surface*/, + uint32_t fingers) +{ + CLOG_INFO(LOG, 2, "begin (fingers=%u)", fingers); +} + +static void gesture_swipe_handle_update( + void * /*data*/, + struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/, + uint32_t /*time*/, + wl_fixed_t dx, + wl_fixed_t dy) +{ + CLOG_INFO(LOG, 2, "update (dx=%.3f, dy=%.3f)", wl_fixed_to_double(dx), wl_fixed_to_double(dy)); +} + +static void gesture_swipe_handle_end( + void * /*data*/, + struct zwp_pointer_gesture_swipe_v1 * /*zwp_pointer_gesture_swipe_v1*/, + uint32_t /*serial*/, + uint32_t /*time*/, + int32_t cancelled) +{ + CLOG_INFO(LOG, 2, "end (cancelled=%i)", cancelled); +} + +static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener = { + gesture_swipe_handle_begin, + gesture_swipe_handle_update, + gesture_swipe_handle_end, +}; + +#undef LOG + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Listener (Touch Seat), #wl_touch_listener * @@ -3311,6 +3568,31 @@ static void gwl_seat_capability_pointer_enable(GWL_Seat *seat) wl_surface_add_listener(seat->cursor.wl_surface, &cursor_surface_listener, seat); ghost_wl_surface_tag_cursor_pointer(seat->cursor.wl_surface); + + zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures(); + if (pointer_gestures) { + { /* Hold gesture. */ + struct zwp_pointer_gesture_hold_v1 *gesture = zwp_pointer_gestures_v1_get_hold_gesture( + pointer_gestures, seat->wl_pointer); + zwp_pointer_gesture_hold_v1_set_user_data(gesture, seat); + zwp_pointer_gesture_hold_v1_add_listener(gesture, &gesture_hold_listener, seat); + seat->wp_pointer_gesture_hold = gesture; + } + { /* Pinch gesture. */ + struct zwp_pointer_gesture_pinch_v1 *gesture = zwp_pointer_gestures_v1_get_pinch_gesture( + pointer_gestures, seat->wl_pointer); + zwp_pointer_gesture_pinch_v1_set_user_data(gesture, seat); + zwp_pointer_gesture_pinch_v1_add_listener(gesture, &gesture_pinch_listener, seat); + seat->wp_pointer_gesture_pinch = gesture; + } + { /* Swipe gesture. */ + struct zwp_pointer_gesture_swipe_v1 *gesture = zwp_pointer_gestures_v1_get_swipe_gesture( + pointer_gestures, seat->wl_pointer); + zwp_pointer_gesture_swipe_v1_set_user_data(gesture, seat); + zwp_pointer_gesture_swipe_v1_add_listener(gesture, &gesture_swipe_listener, seat); + seat->wp_pointer_gesture_swipe = gesture; + } + } } static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) @@ -3318,6 +3600,32 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat) if (!seat->wl_pointer) { return; } + + zwp_pointer_gestures_v1 *pointer_gestures = seat->system->wp_pointer_gestures(); + if (pointer_gestures) { + { /* Hold gesture. */ + struct zwp_pointer_gesture_hold_v1 **gesture_p = &seat->wp_pointer_gesture_hold; + if (*gesture_p) { + zwp_pointer_gesture_hold_v1_destroy(*gesture_p); + *gesture_p = nullptr; + } + } + { /* Pinch gesture. */ + struct zwp_pointer_gesture_pinch_v1 **gesture_p = &seat->wp_pointer_gesture_pinch; + if (*gesture_p) { + zwp_pointer_gesture_pinch_v1_destroy(*gesture_p); + *gesture_p = nullptr; + } + } + { /* Swipe gesture. */ + struct zwp_pointer_gesture_swipe_v1 **gesture_p = &seat->wp_pointer_gesture_swipe; + if (*gesture_p) { + zwp_pointer_gesture_swipe_v1_destroy(*gesture_p); + *gesture_p = nullptr; + } + } + } + if (seat->cursor.wl_surface) { wl_surface_destroy(seat->cursor.wl_surface); seat->cursor.wl_surface = nullptr; @@ -3791,6 +4099,11 @@ static void global_handle_add(void *data, display->wp_pointer_constraints = static_cast( wl_registry_bind(wl_registry, name, &zwp_pointer_constraints_v1_interface, 1)); } + else if (STREQ(interface, zwp_pointer_gestures_v1_interface.name)) { + display->wp_pointer_gestures = static_cast( + wl_registry_bind(wl_registry, name, &zwp_pointer_gestures_v1_interface, 3)); + } + else if (!strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name)) { display->wp_primary_selection_device_manager = static_cast(wl_registry_bind( @@ -4892,6 +5205,11 @@ struct zwp_primary_selection_device_manager_v1 *GHOST_SystemWayland::wp_primary_ return display_->wp_primary_selection_device_manager; } +struct zwp_pointer_gestures_v1 *GHOST_SystemWayland::wp_pointer_gestures() +{ + return display_->wp_pointer_gestures; +} + #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *GHOST_SystemWayland::libdecor_context() diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index c19791fd792..f08e9fdcf9c 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -159,6 +159,7 @@ class GHOST_SystemWayland : public GHOST_System { struct wl_display *wl_display(); struct wl_compositor *wl_compositor(); struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_manager(); + struct zwp_pointer_gestures_v1 *wp_pointer_gestures(); #ifdef WITH_GHOST_WAYLAND_LIBDECOR libdecor *libdecor_context(); -- cgit v1.2.3 From 9f560219751240cc15a8de0b2e485e1538fee642 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 22 Oct 2022 17:19:55 +0200 Subject: Fix T101930: NLA Actions Stash remove doesn't work on overriden linked data. Code adding stash track was clearing out track flags, instead of editing them as it should have... Note that there are a lot of other weaknesses in action stash code (like relying on the (translated!!!!!!) name of the track to know whether it's a stah or not). --- source/blender/blenkernel/intern/nla.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index ba63cdff917..24663d6db05 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1918,7 +1918,7 @@ bool BKE_nla_action_stash(AnimData *adt, const bool is_liboverride) * NOTE: this must be done *after* adding the strip to the track, or else * the strip locking will prevent the strip from getting added */ - nlt->flag = (NLATRACK_MUTED | NLATRACK_PROTECTED); + nlt->flag |= (NLATRACK_MUTED | NLATRACK_PROTECTED); strip->flag &= ~(NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE); /* also mark the strip for auto syncing the length, so that the strips accurately -- cgit v1.2.3 From a7aa0f1a0c240724e533a5b815c8c4d75b117902 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 12:00:01 -0300 Subject: Fix T101991: "Absolute Grid Snap" not working Error introduced in rB1edebb794b76. In that commit it was kind of forgotten that the snap to grid is also used in 3D views. Also a refactoring and cleanup was applied to simplify the code. --- source/blender/editors/transform/transform.c | 28 ++++++++---------- source/blender/editors/transform/transform.h | 9 ++++-- .../editors/transform/transform_mode_translate.c | 3 +- source/blender/editors/transform/transform_snap.c | 34 +++++++++++----------- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 919f4e5b85c..9fe8cd3df2e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1721,13 +1721,17 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } -static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2]) +static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precision) { + /* Default values. */ + r_snap[0] = r_snap[1] = 1.0f; + r_snap[1] = 0.0f; + *r_snap_precision = 0.1f; + if (t->spacetype == SPACE_VIEW3D) { if (t->region->regiondata) { View3D *v3d = t->area->spacedata.first; - r_snap[0] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL) * 1.0f; - r_snap[1] = r_snap[0] * 0.1f; + r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL); } } else if (t->spacetype == SPACE_IMAGE) { @@ -1741,24 +1745,16 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2], float r_snap_y[2]) ED_space_image_grid_steps(sima, grid_steps_x, grid_steps_y, grid_size); /* Snapping value based on what type of grid is used (adaptive-subdividing or custom-grid). */ r_snap[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_x, zoom_factor); - r_snap[1] = r_snap[0] / 2.0f; - r_snap_y[0] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor); - r_snap_y[1] = r_snap_y[0] / 2.0f; + r_snap[1] = ED_space_image_increment_snap_value(grid_size, grid_steps_y, zoom_factor); + *r_snap_precision = 0.5f; } else if (t->spacetype == SPACE_CLIP) { - r_snap[0] = 0.125f; - r_snap[1] = 0.0625f; + r_snap[0] = r_snap[1] = 0.125f; + *r_snap_precision = 0.5f; } else if (t->spacetype == SPACE_NODE) { r_snap[0] = r_snap[1] = ED_node_grid_size(); } - else if (t->spacetype == SPACE_GRAPH) { - r_snap[0] = 1.0; - r_snap[1] = 0.1f; - } - else { - r_snap[0] = r_snap[1] = 1.0f; - } } bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode) @@ -1898,7 +1894,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initSnapping(t, op); /* Initialize snapping data AFTER mode flags */ - initSnapSpatial(t, t->snap_spatial_x, t->snap_spatial_y); + initSnapSpatial(t, t->snap_spatial, &t->snap_spatial_precision); /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. * will be removed (ton) */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 95686f12fe2..90f2795184b 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -555,9 +555,12 @@ typedef struct TransInfo { /** Snapping Gears. */ float snap[2]; /** Spatial snapping gears(even when rotating, scaling... etc). */ - float snap_spatial_x[2]; - /** Spatial snapping in the Y coordinate, for non-uniform grid in UV Editor. */ - float snap_spatial_y[2]; + float snap_spatial[3]; + /** + * Precision factor that is multiplied to snap_spatial when precision + * modifier is enabled for snap to grid or incremental snap. + */ + float snap_spatial_precision; /** Mouse side of the current frame, 'L', 'R' or 'B' */ char frame_side; diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 91388ecd661..b7ffba6ad58 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -590,7 +590,8 @@ void initTranslation(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - copy_v2_v2(t->snap, t->snap_spatial_x); + t->snap[0] = 1.0; + t->snap[1] = t->snap_spatial_precision; copy_v3_fl(t->num.val_inc, t->snap[0]); t->num.unit_sys = t->scene->unit.system; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 06aec3b45a6..0d27fc1efd4 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -519,16 +519,14 @@ void applyGridAbsolute(TransInfo *t) return; } - float grid_size_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0]; - float grid_size_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; - float grid_size_z = grid_size_x; - - if (grid_size_y == 0.0f) { - grid_size_y = grid_size_x; /* Just use `grid_size_x` when `grid_size_y` isn't set correctly. */ + float grid_size[3]; + copy_v3_v3(grid_size, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_size, t->snap_spatial_precision); } /* Early exit on unusable grid size. */ - if (grid_size_x == 0.0f || grid_size_y == 0.0f || grid_size_z == 0.0f) { + if (is_zero_v3(grid_size)) { return; } @@ -554,9 +552,9 @@ void applyGridAbsolute(TransInfo *t) copy_v3_v3(iloc, td->ob->obmat[3]); } - loc[0] = roundf(iloc[0] / grid_size_x) * grid_size_x; - loc[1] = roundf(iloc[1] / grid_size_y) * grid_size_y; - loc[2] = roundf(iloc[2] / grid_size_z) * grid_size_z; + loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; + loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; + loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; sub_v3_v3v3(tvec, loc, iloc); mul_m3_v3(td->smtx, tvec); @@ -1660,8 +1658,7 @@ bool snapNodesTransform( static void snap_grid_apply(TransInfo *t, const int max_index, - const float grid_dist_x, - const float grid_dist_y, + const float grid_dist[3], const float loc[3], float r_out[3]) { @@ -1680,7 +1677,7 @@ static void snap_grid_apply(TransInfo *t, } for (int i = 0; i <= max_index; i++) { - const float iter_fac = ((i == 1) ? grid_dist_y : grid_dist_x) * asp[i]; + const float iter_fac = grid_dist[i] * asp[i]; r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; } } @@ -1705,15 +1702,18 @@ bool transform_snap_grid(TransInfo *t, float *val) return false; } - float grid_dist_x = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_x[1] : t->snap_spatial_x[0]; - float grid_dist_y = (t->modifiers & MOD_PRECISION) ? t->snap_spatial_y[1] : t->snap_spatial_y[0]; + float grid_dist[3]; + copy_v3_v3(grid_dist, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_dist, t->snap_spatial_precision); + } /* Early bailing out if no need to snap */ - if (grid_dist_x == 0.0f || grid_dist_y == 0.0f) { + if (is_zero_v3(grid_dist)) { return false; } - snap_grid_apply(t, t->idx_max, grid_dist_x, grid_dist_y, val, val); + snap_grid_apply(t, t->idx_max, grid_dist, val, val); t->tsnap.snapElem = SCE_SNAP_MODE_GRID; return true; } -- cgit v1.2.3 From e16cea019ee184156a5c1849f2b7f2b762dc9a6e Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 12:27:59 -0300 Subject: Cleanup: move grid snap functions to files where they are used --- .../editors/transform/transform_convert_node.cc | 55 +++++++- .../editors/transform/transform_mode_translate.c | 100 ++++++++++++++- source/blender/editors/transform/transform_snap.c | 140 +-------------------- source/blender/editors/transform/transform_snap.h | 3 +- 4 files changed, 155 insertions(+), 143 deletions(-) diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc index eb5eb822d69..0b5dc73a051 100644 --- a/source/blender/editors/transform/transform_convert_node.cc +++ b/source/blender/editors/transform/transform_convert_node.cc @@ -16,6 +16,7 @@ #include "BKE_context.h" #include "BKE_node.h" #include "BKE_node_tree_update.h" +#include "BKE_object.h" #include "BKE_report.h" #include "ED_node.h" @@ -155,9 +156,61 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Node Transform Creation +/** \name Flush Transform Nodes * \{ */ +static void applyGridAbsolute(TransInfo *t) +{ + int i; + + if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) { + return; + } + + float grid_size[3]; + copy_v3_v3(grid_size, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_size, t->snap_spatial_precision); + } + + /* Early exit on unusable grid size. */ + if (is_zero_v3(grid_size)) { + return; + } + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td; + + for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { + float iloc[3], loc[3], tvec[3]; + if (td->flag & TD_SKIP) { + continue; + } + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { + continue; + } + + copy_v3_v3(iloc, td->loc); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, iloc); + } + else if (t->options & CTX_OBJECT) { + BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); + copy_v3_v3(iloc, td->ob->obmat[3]); + } + + loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; + loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; + loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; + + sub_v3_v3v3(tvec, loc, iloc); + mul_m3_v3(td->smtx, tvec); + add_v3_v3(td->loc, tvec); + } + } +} + static void flushTransNodes(TransInfo *t) { using namespace blender::ed; diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index b7ffba6ad58..6461182afc1 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -170,7 +170,7 @@ static void transdata_elem_translate_fn(void *__restrict iter_data_v, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Transform (Translation) +/** \name Transform (Translation) Header * \{ */ static void translate_dist_to_str(char *r_str, @@ -341,6 +341,96 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Translation) Snapping + * \{ */ + +static void translate_snap_target_grid_ensure(TransInfo *t) +{ + /* Only need to calculate once. */ + if ((t->tsnap.status & TARGET_GRID_INIT) == 0) { + if (t->data_type == &TransConvertType_Cursor3D) { + /* Use a fallback when transforming the cursor. + * In this case the center is _not_ derived from the cursor which is being transformed. */ + copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc); + } + else if (t->around == V3D_AROUND_CURSOR) { + /* Use a fallback for cursor selection, + * this isn't useful as a global center for absolute grid snapping + * since its not based on the position of the selection. */ + tranform_snap_target_median_calc(t, t->tsnap.snapTargetGrid); + } + else { + copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global); + } + t->tsnap.status |= TARGET_GRID_INIT; + } +} + +static void translate_snap_grid_apply(TransInfo *t, + const int max_index, + const float grid_dist[3], + const float loc[3], + float r_out[3]) +{ + BLI_assert(max_index <= 2); + translate_snap_target_grid_ensure(t); + const float *center_global = t->tsnap.snapTargetGrid; + const float *asp = t->aspect; + + float in[3]; + if (t->con.mode & CON_APPLY) { + BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE); + t->con.applyVec(t, NULL, NULL, loc, in); + } + else { + copy_v3_v3(in, loc); + } + + for (int i = 0; i <= max_index; i++) { + const float iter_fac = grid_dist[i] * asp[i]; + r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; + } +} + +static bool translate_snap_grid(TransInfo *t, float *val) +{ + if (!activeSnap(t)) { + return false; + } + + if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) { + /* Don't do grid snapping if there is a valid snap point. */ + return false; + } + + /* Don't do grid snapping if not in 3D viewport or UV editor */ + if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) { + return false; + } + + if (t->mode != TFM_TRANSLATION) { + return false; + } + + float grid_dist[3]; + copy_v3_v3(grid_dist, t->snap_spatial); + if (t->modifiers & MOD_PRECISION) { + mul_v3_fl(grid_dist, t->snap_spatial_precision); + } + + /* Early bailing out if no need to snap */ + if (is_zero_v3(grid_dist)) { + return false; + } + + translate_snap_grid_apply(t, t->idx_max, grid_dist, val, val); + t->tsnap.snapElem = SCE_SNAP_MODE_GRID; + return true; +} + static void ApplySnapTranslation(TransInfo *t, float vec[3]) { float point[3]; @@ -372,6 +462,12 @@ static void ApplySnapTranslation(TransInfo *t, float vec[3]) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Translation) + * \{ */ + static void applyTranslationValue(TransInfo *t, const float vec[3]) { struct TranslateCustomData *custom_data = t->custom.mode.data; @@ -514,7 +610,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) t->tsnap.snapElem = SCE_SNAP_MODE_NONE; applySnappingAsGroup(t, global_dir); - transform_snap_grid(t, global_dir); + translate_snap_grid(t, global_dir); if (t->con.mode & CON_APPLY) { float in[3]; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 0d27fc1efd4..672d947936d 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -511,58 +511,6 @@ void applySnappingIndividual(TransInfo *t) } } -void applyGridAbsolute(TransInfo *t) -{ - int i; - - if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) { - return; - } - - float grid_size[3]; - copy_v3_v3(grid_size, t->snap_spatial); - if (t->modifiers & MOD_PRECISION) { - mul_v3_fl(grid_size, t->snap_spatial_precision); - } - - /* Early exit on unusable grid size. */ - if (is_zero_v3(grid_size)) { - return; - } - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td; - - for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], tvec[3]; - if (td->flag & TD_SKIP) { - continue; - } - - if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { - continue; - } - - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->options & CTX_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } - - loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; - loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; - loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; - - sub_v3_v3v3(tvec, loc, iloc); - mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); - } - } -} - void applySnappingAsGroup(TransInfo *t, float *vec) { if (!activeSnap_SnappingAsGroup(t)) { @@ -1189,7 +1137,7 @@ static void snap_calc_sequencer_fn(TransInfo *t, float *UNUSED(vec)) /** \name Target * \{ */ -static void snap_target_median_impl(TransInfo *t, float r_median[3]) +void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]) { int i_accum = 0; @@ -1225,28 +1173,6 @@ static void snap_target_median_impl(TransInfo *t, float r_median[3]) // TargetSnapOffset(t, NULL); } -static void snap_target_grid_ensure(TransInfo *t) -{ - /* Only need to calculate once. */ - if ((t->tsnap.status & TARGET_GRID_INIT) == 0) { - if (t->data_type == &TransConvertType_Cursor3D) { - /* Use a fallback when transforming the cursor. - * In this case the center is _not_ derived from the cursor which is being transformed. */ - copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc); - } - else if (t->around == V3D_AROUND_CURSOR) { - /* Use a fallback for cursor selection, - * this isn't useful as a global center for absolute grid snapping - * since its not based on the position of the selection. */ - snap_target_median_impl(t, t->tsnap.snapTargetGrid); - } - else { - copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global); - } - t->tsnap.status |= TARGET_GRID_INIT; - } -} - static void TargetSnapOffset(TransInfo *t, TransData *td) { if (t->spacetype == SPACE_NODE && td != NULL) { @@ -1318,7 +1244,7 @@ static void TargetSnapMedian(TransInfo *t) { /* Only need to calculate once. */ if ((t->tsnap.status & TARGET_INIT) == 0) { - snap_target_median_impl(t, t->tsnap.snapTarget); + tranform_snap_target_median_calc(t, t->tsnap.snapTarget); t->tsnap.status |= TARGET_INIT; } } @@ -1656,68 +1582,6 @@ bool snapNodesTransform( /** \name snap Grid * \{ */ -static void snap_grid_apply(TransInfo *t, - const int max_index, - const float grid_dist[3], - const float loc[3], - float r_out[3]) -{ - BLI_assert(max_index <= 2); - snap_target_grid_ensure(t); - const float *center_global = t->tsnap.snapTargetGrid; - const float *asp = t->aspect; - - float in[3]; - if (t->con.mode & CON_APPLY) { - BLI_assert(t->tsnap.snapElem == SCE_SNAP_MODE_NONE); - t->con.applyVec(t, NULL, NULL, loc, in); - } - else { - copy_v3_v3(in, loc); - } - - for (int i = 0; i <= max_index; i++) { - const float iter_fac = grid_dist[i] * asp[i]; - r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; - } -} - -bool transform_snap_grid(TransInfo *t, float *val) -{ - if (!activeSnap(t)) { - return false; - } - - if (!(t->tsnap.mode & SCE_SNAP_MODE_GRID) || validSnap(t)) { - /* Don't do grid snapping if there is a valid snap point. */ - return false; - } - - /* Don't do grid snapping if not in 3D viewport or UV editor */ - if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) { - return false; - } - - if (t->mode != TFM_TRANSLATION) { - return false; - } - - float grid_dist[3]; - copy_v3_v3(grid_dist, t->snap_spatial); - if (t->modifiers & MOD_PRECISION) { - mul_v3_fl(grid_dist, t->snap_spatial_precision); - } - - /* Early bailing out if no need to snap */ - if (is_zero_v3(grid_dist)) { - return false; - } - - snap_grid_apply(t, t->idx_max, grid_dist, val, val); - t->tsnap.snapElem = SCE_SNAP_MODE_GRID; - return true; -} - static void snap_increment_apply_ex(const TransInfo *UNUSED(t), const int max_index, const float increment_val, diff --git a/source/blender/editors/transform/transform_snap.h b/source/blender/editors/transform/transform_snap.h index 2b78c554ad8..16d9062e978 100644 --- a/source/blender/editors/transform/transform_snap.h +++ b/source/blender/editors/transform/transform_snap.h @@ -38,10 +38,10 @@ bool snapNodesTransform(struct TransInfo *t, bool transformModeUseSnap(const TransInfo *t); +void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3]); bool transform_snap_increment_ex(const TransInfo *t, bool use_local_space, float *r_val); bool transform_snap_increment(const TransInfo *t, float *val); float transform_snap_increment_get(const TransInfo *t); -bool transform_snap_grid(TransInfo *t, float *val); bool activeSnap(const TransInfo *t); bool activeSnap_SnappingIndividual(const TransInfo *t); @@ -52,7 +52,6 @@ bool validSnap(const TransInfo *t); void initSnapping(struct TransInfo *t, struct wmOperator *op); void freeSnapping(struct TransInfo *t); void applySnappingIndividual(TransInfo *t); -void applyGridAbsolute(TransInfo *t); void applySnappingAsGroup(TransInfo *t, float *vec); void resetSnapping(TransInfo *t); eRedrawFlag handleSnapping(TransInfo *t, const struct wmEvent *event); -- cgit v1.2.3 From 588db6152aaa8b8db55f8f3180787befc4238684 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 12:52:22 -0300 Subject: Transform: remove unreachable code The node grid snap only works with 2D coordinates, no transformation matrix and no Objects. Also rename `applyGridAbsolute` to `node_snap_grid_apply`. --- .../editors/transform/transform_convert_node.cc | 30 ++++++++-------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/source/blender/editors/transform/transform_convert_node.cc b/source/blender/editors/transform/transform_convert_node.cc index 0b5dc73a051..6ab0e1fe701 100644 --- a/source/blender/editors/transform/transform_convert_node.cc +++ b/source/blender/editors/transform/transform_convert_node.cc @@ -16,7 +16,6 @@ #include "BKE_context.h" #include "BKE_node.h" #include "BKE_node_tree_update.h" -#include "BKE_object.h" #include "BKE_report.h" #include "ED_node.h" @@ -159,7 +158,7 @@ static void createTransNodeData(bContext * /*C*/, TransInfo *t) /** \name Flush Transform Nodes * \{ */ -static void applyGridAbsolute(TransInfo *t) +static void node_snap_grid_apply(TransInfo *t) { int i; @@ -167,14 +166,14 @@ static void applyGridAbsolute(TransInfo *t) return; } - float grid_size[3]; - copy_v3_v3(grid_size, t->snap_spatial); + float grid_size[2]; + copy_v2_v2(grid_size, t->snap_spatial); if (t->modifiers & MOD_PRECISION) { - mul_v3_fl(grid_size, t->snap_spatial_precision); + mul_v2_fl(grid_size, t->snap_spatial_precision); } /* Early exit on unusable grid size. */ - if (is_zero_v3(grid_size)) { + if (is_zero_v2(grid_size)) { return; } @@ -182,7 +181,7 @@ static void applyGridAbsolute(TransInfo *t) TransData *td; for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], tvec[3]; + float iloc[2], loc[2], tvec[2]; if (td->flag & TD_SKIP) { continue; } @@ -191,22 +190,13 @@ static void applyGridAbsolute(TransInfo *t) continue; } - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->options & CTX_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } + copy_v2_v2(iloc, td->loc); loc[0] = roundf(iloc[0] / grid_size[0]) * grid_size[0]; loc[1] = roundf(iloc[1] / grid_size[1]) * grid_size[1]; - loc[2] = grid_size[2] ? roundf(iloc[2] / grid_size[2]) * grid_size[2] : iloc[2]; - sub_v3_v3v3(tvec, loc, iloc); - mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); + sub_v2_v2v2(tvec, loc, iloc); + add_v2_v2(td->loc, tvec); } } } @@ -244,7 +234,7 @@ static void flushTransNodes(TransInfo *t) } FOREACH_TRANS_DATA_CONTAINER (t, tc) { - applyGridAbsolute(t); + node_snap_grid_apply(t); /* flush to 2d vector from internally used 3d vector */ for (int i = 0; i < tc->data_len; i++) { -- cgit v1.2.3 From 21fdb0d92b6697cba252a1e8080b19012efa8383 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 22 Oct 2022 18:15:02 +0200 Subject: Fix T101329: EXR 'JPG Preview' doesn't use color space anymore For the JPG preview, the only thing that was changed in the image format was the format itself. However, the colorspace code now also checks the bitdepth through BKE_image_format_is_byte, so the depth needs to be explicitly set to 8-bit for the JPG preview output. --- source/blender/blenkernel/intern/image_save.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc index 4e47e71fb2b..003211e6288 100644 --- a/source/blender/blenkernel/intern/image_save.cc +++ b/source/blender/blenkernel/intern/image_save.cc @@ -968,6 +968,7 @@ bool BKE_image_render_write(ReportList *reports, /* optional preview images for exr */ if (ok && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { image_format.imtype = R_IMF_IMTYPE_JPEG90; + image_format.depth = R_IMF_CHAN_DEPTH_8; if (BLI_path_extension_check(filepath, ".exr")) { filepath[strlen(filepath) - 4] = 0; @@ -1025,6 +1026,7 @@ bool BKE_image_render_write(ReportList *reports, /* optional preview images for exr */ if (ok && is_exr_rr && (image_format.flag & R_IMF_FLAG_PREVIEW_JPG)) { image_format.imtype = R_IMF_IMTYPE_JPEG90; + image_format.depth = R_IMF_CHAN_DEPTH_8; if (BLI_path_extension_check(filepath, ".exr")) { filepath[strlen(filepath) - 4] = 0; -- cgit v1.2.3 From afec1cd33385109ac1ca41177426e7b72e174cda Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Sat, 22 Oct 2022 18:32:06 +0200 Subject: Cleanup: clang-format --- source/blender/editors/transform/transform.c | 3 ++- source/blender/editors/transform/transform_mode_translate.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 9fe8cd3df2e..5b194ae7237 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1731,7 +1731,8 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3], float *r_snap_precisi if (t->spacetype == SPACE_VIEW3D) { if (t->region->regiondata) { View3D *v3d = t->area->spacedata.first; - r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL); + r_snap[0] = r_snap[1] = r_snap[2] = ED_view3d_grid_view_scale( + t->scene, v3d, t->region, NULL); } } else if (t->spacetype == SPACE_IMAGE) { diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 6461182afc1..c751a68092f 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -370,10 +370,10 @@ static void translate_snap_target_grid_ensure(TransInfo *t) } static void translate_snap_grid_apply(TransInfo *t, - const int max_index, - const float grid_dist[3], - const float loc[3], - float r_out[3]) + const int max_index, + const float grid_dist[3], + const float loc[3], + float r_out[3]) { BLI_assert(max_index <= 2); translate_snap_target_grid_ensure(t); -- cgit v1.2.3 From b70bbfadfecec049ad1ac2de7a949198ca6c15bc Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Sat, 22 Oct 2022 19:31:57 -0300 Subject: Fix T102000: Curve Shrink Fatten doesn't work for zero radius Kind of intentional regression on rB2d1fe736fabd. But the solution now is (theoretically) better than adding a hard coded threshold. For cases with zero radius, the new radius is now the offset of the ratio projected onto the plane of the origin point. --- .../transform/transform_mode_curveshrinkfatten.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index f7f9e14b8ac..76ce7b29619 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -8,6 +8,7 @@ #include #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_string.h" #include "BKE_context.h" @@ -62,7 +63,14 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } if (td->val) { - *td->val = td->ival * ratio; + if (td->ival == 0.0f && ratio > 1.0f) { + /* Allow Shrink/Fatten for zero radius. */ + *td->val = (ratio - 1.0f) * uint_as_float(POINTER_AS_UINT(t->custom.mode.data)); + } + else { + *td->val = td->ival * ratio; + } + /* apply PET */ *td->val = interpf(*td->val, td->ival, td->factor); CLAMP_MIN(*td->val, 0.0f); @@ -92,6 +100,13 @@ void initCurveShrinkFatten(TransInfo *t) t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_CONSTRAINT; + + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + /* Save a factor to multiply the ratio and use in zero radius cases. */ + RegionView3D *rv3d = t->region->regiondata; + float scale_factor = rv3d->pixsize * t->mouse.factor * t->zfac; + t->custom.mode.data = POINTER_FROM_UINT(float_as_uint(scale_factor)); + } } /** \} */ -- cgit v1.2.3