diff options
Diffstat (limited to 'source')
199 files changed, 3933 insertions, 1752 deletions
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index ac927dd388d..3fd0dd95ef8 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -33,7 +33,6 @@ set(INC ) set(INC_SYS - ${GLEW_INCLUDE_PATH} ${FREETYPE_INCLUDE_DIRS} ) @@ -75,6 +74,5 @@ if(WITH_PYTHON) ) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_blenfont "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index d21fe5afa7e..fea9bbe9bb5 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -570,9 +570,9 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap, /* .blend file I/O */ void CustomData_blend_write_prepare(struct CustomData *data, - struct CustomDataLayer **r_write_layers, - struct CustomDataLayer *write_layers_buff, - size_t write_layers_size); + struct CustomDataLayer **r_write_layers, + struct CustomDataLayer *write_layers_buff, + size_t write_layers_size); void CustomData_blend_write(struct BlendWriter *writer, struct CustomData *data, diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 88eef40ebd2..f1912b14e8c 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -48,6 +48,7 @@ struct bGPDlayer_Mask; struct bGPDspoint; struct bGPDstroke; struct bGPdata; +struct BlendDataReader; #define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)) #define GPENCIL_SIMPLIFY_ONPLAY(playing) \ @@ -281,6 +282,8 @@ void BKE_gpencil_parent_matrix_get(const struct Depsgraph *depsgraph, void BKE_gpencil_update_layer_parent(const struct Depsgraph *depsgraph, struct Object *ob); +void BKE_gpencil_blend_read_data(struct BlendDataReader *reader, struct bGPdata *gpd); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 5e8b371e604..3421aa9e900 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -254,23 +254,23 @@ typedef struct bNodeType { * \note Used as a fallback when #bNode.label isn't set. */ void (*labelfunc)(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); - /// Optional custom resize handle polling. + /** Optional custom resize handle polling. */ int (*resize_area_func)(struct bNode *node, int x, int y); - /// Optional selection area polling. + /** Optional selection area polling. */ int (*select_area_func)(struct bNode *node, int x, int y); - /// Optional tweak area polling (for grabbing). + /** Optional tweak area polling (for grabbing). */ int (*tweak_area_func)(struct bNode *node, int x, int y); - /// Called when the node is updated in the editor. + /** Called when the node is updated in the editor. */ void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node); - /// Check and update if internal ID data has changed. + /** Check and update if internal ID data has changed. */ void (*group_update_func)(struct bNodeTree *ntree, struct bNode *node); - /// Initialize a new node instance of this type after creation. + /** Initialize a new node instance of this type after creation. */ void (*initfunc)(struct bNodeTree *ntree, struct bNode *node); - /// Free the node instance. + /** Free the node instance. */ void (*freefunc)(struct bNode *node); - /// Make a copy of the node instance. + /** Make a copy of the node instance. */ void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index cf43d0fe845..cc5226a1ab7 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -57,7 +57,6 @@ set(INC ) set(INC_SYS - ${GLEW_INCLUDE_PATH} ${ZLIB_INCLUDE_DIRS} ) @@ -457,7 +456,6 @@ if(WITH_BINRELOC) add_definitions(-DWITH_BINRELOC) endif() -add_definitions(${GL_DEFINITIONS}) if(WIN32) list(APPEND INC diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index f3386df03c8..9475ba7efcf 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -39,6 +39,7 @@ #include "BLT_translation.h" +#include "BKE_anim_data.h" #include "BKE_cachefile.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" @@ -48,6 +49,8 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + #ifdef WITH_ALEMBIC # include "ABC_alembic.h" #endif @@ -85,6 +88,37 @@ static void cache_file_free_data(ID *id) BLI_freelistN(&cache_file->object_paths); } +static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + CacheFile *cache_file = (CacheFile *)id; + if (cache_file->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed datablocks. */ + BLI_listbase_clear(&cache_file->object_paths); + cache_file->handle = NULL; + memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath)); + cache_file->handle_readers = NULL; + + BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id); + + if (cache_file->adt) { + BKE_animdata_blend_write(writer, cache_file->adt); + } + } +} + +static void cache_file_blend_read_data(BlendDataReader *reader, ID *id) +{ + CacheFile *cache_file = (CacheFile *)id; + BLI_listbase_clear(&cache_file->object_paths); + cache_file->handle = NULL; + cache_file->handle_filepath[0] = '\0'; + cache_file->handle_readers = NULL; + + /* relink animdata */ + BLO_read_data_address(reader, &cache_file->adt); + BKE_animdata_blend_read_data(reader, cache_file->adt); +} + IDTypeInfo IDType_ID_CF = { .id_code = ID_CF, .id_filter = FILTER_ID_CF, @@ -102,8 +136,8 @@ IDTypeInfo IDType_ID_CF = { .foreach_id = NULL, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, + .blend_write = cache_file_blend_write, + .blend_read_data = cache_file_blend_read_data, .blend_read_lib = NULL, .blend_read_expand = NULL, }; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e7fe10cf19c..fc1b4d82c20 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -845,7 +845,8 @@ static void childof_new_data(void *cdata) bChildOfConstraint *data = (bChildOfConstraint *)cdata; data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ | CHILDOF_ROTX | CHILDOF_ROTY | - CHILDOF_ROTZ | CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ); + CHILDOF_ROTZ | CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ | + CHILDOF_SET_INVERSE); unit_m4(data->invmat); } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 1e37ae3892b..03ac7e622e1 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -40,12 +40,16 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include "DNA_gpencil_types.h" #include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_space_types.h" #include "BKE_action.h" +#include "BKE_anim_data.h" #include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_deform.h" @@ -64,6 +68,10 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + +#include "BKE_gpencil.h" + static CLG_LogRef LOG = {"bke.gpencil"}; static void greasepencil_copy_data(Main *UNUSED(bmain), @@ -111,6 +119,154 @@ static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + bGPdata *gpd = (bGPdata *)id; + if (gpd->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ + /* XXX not sure why the whole run-time data is not cleared in reading code, + * for now mimicking it here. */ + gpd->runtime.sbuffer = NULL; + gpd->runtime.sbuffer_used = 0; + gpd->runtime.sbuffer_size = 0; + gpd->runtime.tot_cp_points = 0; + + /* write gpd data block to file */ + BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id); + BKE_id_blend_write(writer, &gpd->id); + + if (gpd->adt) { + BKE_animdata_blend_write(writer, gpd->adt); + } + + BLO_write_pointer_array(writer, gpd->totcol, gpd->mat); + + /* write grease-pencil layers to file */ + BLO_write_struct_list(writer, bGPDlayer, &gpd->layers); + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* Write mask list. */ + BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers); + /* write this layer's frames to file */ + BLO_write_struct_list(writer, bGPDframe, &gpl->frames); + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + /* write strokes */ + BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes); + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points); + BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles); + BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert); + } + } + } + } +} + +void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd) +{ + /* we must firstly have some grease-pencil data to link! */ + if (gpd == NULL) { + return; + } + + /* relink animdata */ + BLO_read_data_address(reader, &gpd->adt); + BKE_animdata_blend_read_data(reader, gpd->adt); + + /* Ensure full objectmode for linked grease pencil. */ + if (gpd->id.lib != NULL) { + gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; + gpd->flag &= ~GP_DATA_STROKE_EDITMODE; + gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; + gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; + gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE; + } + + /* init stroke buffer */ + gpd->runtime.sbuffer = NULL; + gpd->runtime.sbuffer_used = 0; + gpd->runtime.sbuffer_size = 0; + gpd->runtime.tot_cp_points = 0; + + /* relink palettes (old palettes deprecated, only to convert old files) */ + BLO_read_list(reader, &gpd->palettes); + if (gpd->palettes.first != NULL) { + LISTBASE_FOREACH (Palette *, palette, &gpd->palettes) { + BLO_read_list(reader, &palette->colors); + } + } + + /* materials */ + BLO_read_pointer_array(reader, (void **)&gpd->mat); + + /* relink layers */ + BLO_read_list(reader, &gpd->layers); + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* relink frames */ + BLO_read_list(reader, &gpl->frames); + + BLO_read_data_address(reader, &gpl->actframe); + + gpl->runtime.icon_id = 0; + + /* Relink masks. */ + BLO_read_list(reader, &gpl->mask_layers); + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + /* relink strokes (and their points) */ + BLO_read_list(reader, &gpf->strokes); + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* relink stroke points array */ + BLO_read_data_address(reader, &gps->points); + /* Relink geometry*/ + BLO_read_data_address(reader, &gps->triangles); + + /* relink weight data */ + if (gps->dvert) { + BLO_read_data_address(reader, &gps->dvert); + BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert); + } + } + } + } +} + +static void greasepencil_blend_read_data(BlendDataReader *reader, ID *id) +{ + bGPdata *gpd = (bGPdata *)id; + BKE_gpencil_blend_read_data(reader, gpd); +} + +static void greasepencil_blend_read_lib(BlendLibReader *reader, ID *id) +{ + bGPdata *gpd = (bGPdata *)id; + + /* Relink all data-lock linked by GP data-lock */ + /* Layers */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* Layer -> Parent References */ + BLO_read_id_address(reader, gpd->id.lib, &gpl->parent); + } + + /* materials */ + for (int a = 0; a < gpd->totcol; a++) { + BLO_read_id_address(reader, gpd->id.lib, &gpd->mat[a]); + } +} + +static void greasepencil_blend_read_expand(BlendExpander *expander, ID *id) +{ + bGPdata *gpd = (bGPdata *)id; + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + BLO_expand(expander, gpl->parent); + } + + for (int a = 0; a < gpd->totcol; a++) { + BLO_expand(expander, gpd->mat[a]); + } +} + IDTypeInfo IDType_ID_GD = { .id_code = ID_GD, .id_filter = FILTER_ID_GD, @@ -128,10 +284,10 @@ IDTypeInfo IDType_ID_GD = { .foreach_id = greasepencil_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = greasepencil_blend_write, + .blend_read_data = greasepencil_blend_read_data, + .blend_read_lib = greasepencil_blend_read_lib, + .blend_read_expand = greasepencil_blend_read_expand, }; /* ************************************************** */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 83e3a3098e9..a9b0eede055 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -2264,17 +2264,16 @@ static int gpencil_material_find_index_by_name(Object *ob, const char *name) return -1; } -/* Create the name with the object name and a subfix. */ -static void make_element_name(char *obname, char *name, const int maxlen, char *r_name) +/** + * Create the name with the object name and a suffix. + */ +static void make_element_name(const char *obname, const char *name, const int maxlen, char *r_name) { char str[256]; - sprintf(str, "%s_%s", obname, name); + SNPRINTF(str, "%s_%s", obname, name); + /* Replace any point by underscore. */ - char *current_pos = strchr(str, '.'); - while (current_pos) { - *current_pos = '_'; - current_pos = strchr(current_pos, '.'); - } + BLI_str_replace_char(str, '.', '_'); BLI_strncpy_utf8(r_name, str, maxlen); } diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 314b7228373..57997eaf3a1 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -47,8 +47,10 @@ #include "DEG_depsgraph_query.h" -const char *HAIR_ATTR_POSITION = "Position"; -const char *HAIR_ATTR_RADIUS = "Radius"; +#include "BLO_read_write.h" + +static const char *HAIR_ATTR_POSITION = "Position"; +static const char *HAIR_ATTR_RADIUS = "Radius"; /* Hair datablock */ @@ -109,6 +111,69 @@ static void hair_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Hair *hair = (Hair *)id; + if (hair->id.us > 0 || BLO_write_is_undo(writer)) { + CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff)); + + /* Write LibData */ + BLO_write_id_struct(writer, Hair, id_address, &hair->id); + BKE_id_blend_write(writer, &hair->id); + + /* Direct data */ + CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id); + CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id); + + BLO_write_pointer_array(writer, hair->totcol, hair->mat); + if (hair->adt) { + BKE_animdata_blend_write(writer, hair->adt); + } + + /* Remove temporary data. */ + if (players && players != players_buff) { + MEM_freeN(players); + } + if (clayers && clayers != clayers_buff) { + MEM_freeN(clayers); + } + } +} + +static void hair_blend_read_data(BlendDataReader *reader, ID *id) +{ + Hair *hair = (Hair *)id; + BLO_read_data_address(reader, &hair->adt); + BKE_animdata_blend_read_data(reader, hair->adt); + + /* Geometry */ + CustomData_blend_read(reader, &hair->pdata, hair->totpoint); + CustomData_blend_read(reader, &hair->cdata, hair->totcurve); + BKE_hair_update_customdata_pointers(hair); + + /* Materials */ + BLO_read_pointer_array(reader, (void **)&hair->mat); +} + +static void hair_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Hair *hair = (Hair *)id; + for (int a = 0; a < hair->totcol; a++) { + BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]); + } +} + +static void hair_blend_read_expand(BlendExpander *expander, ID *id) +{ + Hair *hair = (Hair *)id; + for (int a = 0; a < hair->totcol; a++) { + BLO_expand(expander, hair->mat[a]); + } +} + IDTypeInfo IDType_ID_HA = { .id_code = ID_HA, .id_filter = FILTER_ID_HA, @@ -126,10 +191,10 @@ IDTypeInfo IDType_ID_HA = { .foreach_id = hair_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = hair_blend_write, + .blend_read_data = hair_blend_read_data, + .blend_read_lib = hair_blend_read_lib, + .blend_read_expand = hair_blend_read_expand, }; static void hair_random(Hair *hair) diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c index d4a1c1e2c46..f37e038e69e 100644 --- a/source/blender/blenkernel/intern/image_gpu.c +++ b/source/blender/blenkernel/intern/image_gpu.c @@ -272,6 +272,13 @@ static GPUTexture *image_get_gpu_texture(Image *ima, * context and might as well ensure we have as much space free as possible. */ gpu_free_unused_buffers(); + /* Free GPU textures when requesting a different render pass/layer. */ + if (ima->gpu_pass != iuser->pass || ima->gpu_layer != iuser->layer) { + ima->gpu_pass = iuser->pass; + ima->gpu_layer = iuser->layer; + ima->gpuflag |= IMA_GPU_REFRESH; + } + /* currently, gpu refresh tagging is used by ima sequences */ if (ima->gpuflag & IMA_GPU_REFRESH) { image_free_gpu(ima, true); @@ -282,7 +289,10 @@ static GPUTexture *image_get_gpu_texture(Image *ima, BKE_image_tag_time(ima); /* Test if we already have a texture. */ - GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, iuser ? iuser->multiview_eye : 0); + const int current_view = iuser ? ((iuser->flag & IMA_SHOW_STEREO) != 0 ? iuser->multiview_eye : + iuser->view) : + 0; + GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, current_view); if (*tex) { return *tex; } diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index 087bf123575..6ec305a971c 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -47,12 +47,14 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + /* PointCloud datablock */ static void pointcloud_random(PointCloud *pointcloud); -const char *POINTCLOUD_ATTR_POSITION = "Position"; -const char *POINTCLOUD_ATTR_RADIUS = "Radius"; +static const char *POINTCLOUD_ATTR_POSITION = "Position"; +static const char *POINTCLOUD_ATTR_RADIUS = "Radius"; static void pointcloud_init_data(ID *id) { @@ -111,6 +113,64 @@ static void pointcloud_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + PointCloud *pointcloud = (PointCloud *)id; + if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) { + CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_blend_write_prepare( + &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + + /* Write LibData */ + BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id); + BKE_id_blend_write(writer, &pointcloud->id); + + /* Direct data */ + CustomData_blend_write( + writer, &pointcloud->pdata, players, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id); + + BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat); + if (pointcloud->adt) { + BKE_animdata_blend_write(writer, pointcloud->adt); + } + + /* Remove temporary data. */ + if (players && players != players_buff) { + MEM_freeN(players); + } + } +} + +static void pointcloud_blend_read_data(BlendDataReader *reader, ID *id) +{ + PointCloud *pointcloud = (PointCloud *)id; + BLO_read_data_address(reader, &pointcloud->adt); + BKE_animdata_blend_read_data(reader, pointcloud->adt); + + /* Geometry */ + CustomData_blend_read(reader, &pointcloud->pdata, pointcloud->totpoint); + BKE_pointcloud_update_customdata_pointers(pointcloud); + + /* Materials */ + BLO_read_pointer_array(reader, (void **)&pointcloud->mat); +} + +static void pointcloud_blend_read_lib(BlendLibReader *reader, ID *id) +{ + PointCloud *pointcloud = (PointCloud *)id; + for (int a = 0; a < pointcloud->totcol; a++) { + BLO_read_id_address(reader, pointcloud->id.lib, &pointcloud->mat[a]); + } +} + +static void pointcloud_blend_read_expand(BlendExpander *expander, ID *id) +{ + PointCloud *pointcloud = (PointCloud *)id; + for (int a = 0; a < pointcloud->totcol; a++) { + BLO_expand(expander, pointcloud->mat[a]); + } +} + IDTypeInfo IDType_ID_PT = { .id_code = ID_PT, .id_filter = FILTER_ID_PT, @@ -128,10 +188,10 @@ IDTypeInfo IDType_ID_PT = { .foreach_id = pointcloud_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = pointcloud_blend_write, + .blend_read_data = pointcloud_blend_read_data, + .blend_read_lib = pointcloud_blend_read_lib, + .blend_read_expand = pointcloud_blend_read_expand, }; static void pointcloud_random(PointCloud *pointcloud) diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index 9dc1f073e2a..f08051510db 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -63,6 +63,8 @@ #include "SIM_simulation_update.hh" +#include "BLO_read_write.h" + using StateInitFunction = void (*)(SimulationState *state); using StateResetFunction = void (*)(SimulationState *state); using StateRemoveFunction = void (*)(SimulationState *state); @@ -145,6 +147,94 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void simulation_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Simulation *simulation = (Simulation *)id; + if (simulation->id.us > 0 || BLO_write_is_undo(writer)) { + BLO_write_id_struct(writer, Simulation, id_address, &simulation->id); + BKE_id_blend_write(writer, &simulation->id); + + if (simulation->adt) { + BKE_animdata_blend_write(writer, simulation->adt); + } + + /* nodetree is integral part of simulation, no libdata */ + if (simulation->nodetree) { + BLO_write_struct(writer, bNodeTree, simulation->nodetree); + ntreeBlendWrite(writer, simulation->nodetree); + } + + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + BLO_write_string(writer, state->name); + BLO_write_string(writer, state->type); + /* TODO: Decentralize this part. */ + if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + + CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + CustomData_blend_write_prepare( + &particle_state->attributes, &players, players_buff, ARRAY_SIZE(players_buff)); + + BLO_write_struct(writer, ParticleSimulationState, particle_state); + + CustomData_blend_write(writer, + &particle_state->attributes, + players, + particle_state->tot_particles, + CD_MASK_ALL, + &simulation->id); + + /* Remove temporary data. */ + if (players && players != players_buff) { + MEM_freeN(players); + } + } + else if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER)) { + ParticleMeshEmitterSimulationState *emitter_state = (ParticleMeshEmitterSimulationState *) + state; + BLO_write_struct(writer, ParticleMeshEmitterSimulationState, emitter_state); + } + } + + BLO_write_struct_list(writer, SimulationDependency, &simulation->dependencies); + } +} + +static void simulation_blend_read_data(BlendDataReader *reader, ID *id) +{ + Simulation *simulation = (Simulation *)id; + BLO_read_data_address(reader, &simulation->adt); + BKE_animdata_blend_read_data(reader, simulation->adt); + + BLO_read_list(reader, &simulation->states); + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + BLO_read_data_address(reader, &state->name); + BLO_read_data_address(reader, &state->type); + if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { + ParticleSimulationState *particle_state = (ParticleSimulationState *)state; + CustomData_blend_read(reader, &particle_state->attributes, particle_state->tot_particles); + } + } + + BLO_read_list(reader, &simulation->dependencies); +} + +static void simulation_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Simulation *simulation = (Simulation *)id; + LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { + BLO_read_id_address(reader, simulation->id.lib, &dependency->id); + } +} + +static void simulation_blend_read_expand(BlendExpander *expander, ID *id) +{ + Simulation *simulation = (Simulation *)id; + LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { + BLO_expand(expander, dependency->id); + } +} + IDTypeInfo IDType_ID_SIM = { /* id_code */ ID_SIM, /* id_filter */ FILTER_ID_SIM, @@ -162,10 +252,10 @@ IDTypeInfo IDType_ID_SIM = { /* foreach_id */ simulation_foreach_id, /* foreach_cache */ NULL, - /* blend_write */ NULL, - /* blend_read_data */ NULL, - /* blend_read_lib */ NULL, - /* blend_read_expand */ NULL, + /* blend_write */ simulation_blend_write, + /* blend_read_data */ simulation_blend_read_data, + /* blend_read_lib */ simulation_blend_read_lib, + /* blend_read_expand */ simulation_blend_read_expand, }; void *BKE_simulation_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 88b32e194cf..9cf5ef85850 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3014,7 +3014,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob) * * a: never ever make tangent handles (sub) and or (ob)ject to collision. * b: rather calculate them using some C2 - * (C2= continuous in second derivate -> no jump in bending ) condition. + * (C2= continuous in second derivative -> no jump in bending ) condition. * * Not too hard to do, but needs some more code to care for; * some one may want look at it (JOW 2010/06/12). */ diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 8ee6a3627dc..c8a31b51500 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -33,6 +33,9 @@ #include "BLT_translation.h" +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_packedFile_types.h" @@ -63,6 +66,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + static void sound_free_audio(bSound *sound); static void sound_copy_data(Main *UNUSED(bmain), @@ -126,6 +131,64 @@ static void sound_foreach_cache(ID *id, function_callback(id, &key, &sound->waveform, 0, user_data); } +static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + bSound *sound = (bSound *)id; + if (sound->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed datablocks. */ + sound->tags = 0; + sound->handle = NULL; + sound->playback_handle = NULL; + sound->spinlock = NULL; + + /* write LibData */ + BLO_write_id_struct(writer, bSound, id_address, &sound->id); + BKE_id_blend_write(writer, &sound->id); + + BKE_packedfile_blend_write(writer, sound->packedfile); + } +} + +static void sound_blend_read_data(BlendDataReader *reader, ID *id) +{ + bSound *sound = (bSound *)id; + sound->tags = 0; + sound->handle = NULL; + sound->playback_handle = NULL; + + /* versioning stuff, if there was a cache, then we enable caching: */ + if (sound->cache) { + sound->flags |= SOUND_FLAGS_CACHING; + sound->cache = NULL; + } + + if (BLO_read_data_is_undo(reader)) { + sound->tags |= SOUND_TAGS_WAVEFORM_NO_RELOAD; + } + + sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); + BLI_spin_init(sound->spinlock); + + /* clear waveform loading flag */ + sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING; + + BKE_packedfile_blend_read(reader, &sound->packedfile); + BKE_packedfile_blend_read(reader, &sound->newpackedfile); +} + +static void sound_blend_read_lib(BlendLibReader *reader, ID *id) +{ + bSound *sound = (bSound *)id; + BLO_read_id_address( + reader, sound->id.lib, &sound->ipo); // XXX deprecated - old animation system +} + +static void sound_blend_read_expand(BlendExpander *expander, ID *id) +{ + bSound *snd = (bSound *)id; + BLO_expand(expander, snd->ipo); // XXX deprecated - old animation system +} + IDTypeInfo IDType_ID_SO = { .id_code = ID_SO, .id_filter = FILTER_ID_SO, @@ -144,10 +207,10 @@ IDTypeInfo IDType_ID_SO = { .foreach_id = NULL, .foreach_cache = sound_foreach_cache, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = sound_blend_write, + .blend_read_data = sound_blend_read_data, + .blend_read_lib = sound_blend_read_lib, + .blend_read_expand = sound_blend_read_expand, }; #ifdef WITH_AUDASPACE diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 9e176f355d3..698f6b8cffd 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -36,6 +36,9 @@ #include "BLT_translation.h" +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include "DNA_brush_types.h" #include "DNA_color_types.h" #include "DNA_defaults.h" @@ -50,6 +53,7 @@ #include "BKE_main.h" +#include "BKE_anim_data.h" #include "BKE_colorband.h" #include "BKE_colortools.h" #include "BKE_icons.h" @@ -65,6 +69,8 @@ #include "RE_shader_ext.h" +#include "BLO_read_write.h" + static void texture_init_data(ID *id) { Tex *texture = (Tex *)id; @@ -134,6 +140,62 @@ static void texture_foreach_id(ID *id, LibraryForeachIDData *data) BKE_LIB_FOREACHID_PROCESS(data, texture->ima, IDWALK_CB_USER); } +static void texture_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Tex *tex = (Tex *)id; + if (tex->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + BLO_write_id_struct(writer, Tex, id_address, &tex->id); + BKE_id_blend_write(writer, &tex->id); + + if (tex->adt) { + BKE_animdata_blend_write(writer, tex->adt); + } + + /* direct data */ + if (tex->coba) { + BLO_write_struct(writer, ColorBand, tex->coba); + } + + /* nodetree is integral part of texture, no libdata */ + if (tex->nodetree) { + BLO_write_struct(writer, bNodeTree, tex->nodetree); + ntreeBlendWrite(writer, tex->nodetree); + } + + BKE_previewimg_blend_write(writer, tex->preview); + } +} + +static void texture_blend_read_data(BlendDataReader *reader, ID *id) +{ + Tex *tex = (Tex *)id; + BLO_read_data_address(reader, &tex->adt); + BKE_animdata_blend_read_data(reader, tex->adt); + + BLO_read_data_address(reader, &tex->coba); + + BLO_read_data_address(reader, &tex->preview); + BKE_previewimg_blend_read(reader, tex->preview); + + tex->iuser.ok = 1; + tex->iuser.scene = NULL; +} + +static void texture_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Tex *tex = (Tex *)id; + BLO_read_id_address(reader, tex->id.lib, &tex->ima); + BLO_read_id_address(reader, tex->id.lib, &tex->ipo); // XXX deprecated - old animation system +} + +static void texture_blend_read_expand(BlendExpander *expander, ID *id) +{ + Tex *tex = (Tex *)id; + BLO_expand(expander, tex->ima); + BLO_expand(expander, tex->ipo); // XXX deprecated - old animation system +} + IDTypeInfo IDType_ID_TE = { .id_code = ID_TE, .id_filter = FILTER_ID_TE, @@ -151,10 +213,10 @@ IDTypeInfo IDType_ID_TE = { .foreach_id = texture_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = texture_blend_write, + .blend_read_data = texture_blend_read_data, + .blend_read_lib = texture_blend_read_lib, + .blend_read_expand = texture_blend_read_expand, }; /* Utils for all IDs using those texture slots. */ diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index f99be2f6aee..eb871e41f8e 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -51,6 +51,8 @@ #include "DEG_depsgraph_query.h" +#include "BLO_read_write.h" + #include "CLG_log.h" #ifdef WITH_OPENVDB @@ -509,6 +511,61 @@ static void volume_foreach_cache(ID *id, function_callback(id, &key, (void **)&volume->runtime.grids, 0, user_data); } +static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + Volume *volume = (Volume *)id; + if (volume->id.us > 0 || BLO_write_is_undo(writer)) { + /* Clean up, important in undo case to reduce false detection of changed datablocks. */ + volume->runtime.grids = 0; + + /* write LibData */ + BLO_write_id_struct(writer, Volume, id_address, &volume->id); + BKE_id_blend_write(writer, &volume->id); + + /* direct data */ + BLO_write_pointer_array(writer, volume->totcol, volume->mat); + if (volume->adt) { + BKE_animdata_blend_write(writer, volume->adt); + } + + BKE_packedfile_blend_write(writer, volume->packedfile); + } +} + +static void volume_blend_read_data(BlendDataReader *reader, ID *id) +{ + Volume *volume = (Volume *)id; + BLO_read_data_address(reader, &volume->adt); + BKE_animdata_blend_read_data(reader, volume->adt); + + BKE_packedfile_blend_read(reader, &volume->packedfile); + volume->runtime.frame = 0; + + /* materials */ + BLO_read_pointer_array(reader, (void **)&volume->mat); +} + +static void volume_blend_read_lib(BlendLibReader *reader, ID *id) +{ + Volume *volume = (Volume *)id; + /* Needs to be done *after* cache pointers are restored (call to + * `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in + * lib_link... */ + BKE_volume_init_grids(volume); + + for (int a = 0; a < volume->totcol; a++) { + BLO_read_id_address(reader, volume->id.lib, &volume->mat[a]); + } +} + +static void volume_blend_read_expand(BlendExpander *expander, ID *id) +{ + Volume *volume = (Volume *)id; + for (int a = 0; a < volume->totcol; a++) { + BLO_expand(expander, volume->mat[a]); + } +} + IDTypeInfo IDType_ID_VO = { /* id_code */ ID_VO, /* id_filter */ FILTER_ID_VO, @@ -526,10 +583,10 @@ IDTypeInfo IDType_ID_VO = { /* foreach_id */ volume_foreach_id, /* foreach_cache */ volume_foreach_cache, - /* blend_write */ NULL, - /* blend_read_data */ NULL, - /* blend_read_lib */ NULL, - /* blend_read_expand */ NULL, + /* blend_write */ volume_blend_write, + /* blend_read_data */ volume_blend_read_data, + /* blend_read_lib */ volume_blend_read_lib, + /* blend_read_expand */ volume_blend_read_expand, }; void BKE_volume_init_grids(Volume *volume) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index f030a733752..73f8c2717b0 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -202,7 +202,7 @@ const float bvhtree_kdop_axes[13][3] = { }; /* Used to correct the epsilon and thus match the overlap distance. */ -const float bvhtree_kdop_axes_length[13] = { +static const float bvhtree_kdop_axes_length[13] = { 1.0f, 1.0f, 1.0f, diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index 3a0cea182ba..ba18bb73850 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -48,7 +48,7 @@ MINLINE unsigned int bitscan_forward_uint64(unsigned long long a) _BitScanForward64(&ctz, a); return ctz; #else - return (unsigned int)__builtin_ctz(a); + return (unsigned int)__builtin_ctzll(a); #endif } diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 08c7d3b1e91..6727e6a337d 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -2616,9 +2616,9 @@ void print_m4(const char *str, const float m[4][4]) * * Compute the Single Value Decomposition of an arbitrary matrix A * That is compute the 3 matrices U,W,V with U column orthogonal (m,n) - * ,W a diagonal matrix and V an orthogonal square matrix s.t. - * A = U.W.Vt. From this decomposition it is trivial to compute the - * (pseudo-inverse) of A as Ainv = V.Winv.tranpose(U). + * ,W a diagonal matrix and V an orthogonal square matrix `s.t.A = U.W.Vt`. + * From this decomposition it is trivial to compute the (pseudo-inverse) + * of `A` as `Ainv = V.Winv.transpose(U)`. */ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 18a6e8a3525..6328c887063 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1300,7 +1300,7 @@ void BLI_setenv_if_new(const char *env, const char *val) /** * Get an env var, result has to be used immediately. * -* On windows getenv gets its variables from a static copy of the environment variables taken at + * On windows getenv gets its variables from a static copy of the environment variables taken at * process start-up, causing it to not pick up on environment variables created during runtime. * This function uses an alternative method to get environment variables that does pick up on * runtime environment variables. diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h index e05c1046b95..8a6811444af 100644 --- a/source/blender/blenloader/BLO_read_write.h +++ b/source/blender/blenloader/BLO_read_write.h @@ -210,7 +210,7 @@ bool BLO_read_data_is_undo(BlendDataReader *reader); ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, struct ID *id); #define BLO_read_id_address(reader, lib, id_ptr_p) \ - *(id_ptr_p) = (void *)BLO_read_get_new_id_address((reader), (lib), (ID *)*(id_ptr_p)) + *((void **)id_ptr_p) = (void *)BLO_read_get_new_id_address((reader), (lib), (ID *)*(id_ptr_p)) /* Misc. */ bool BLO_read_lib_is_undo(BlendLibReader *reader); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 095fee74f39..d013006b602 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -127,6 +127,7 @@ #include "BKE_fcurve_driver.h" #include "BKE_fluid.h" #include "BKE_global.h" // for G +#include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_hair.h" #include "BKE_icons.h" @@ -2537,28 +2538,6 @@ static void lib_link_constraint_channels(BlendLibReader *reader, ID *id, ListBas /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: CacheFiles - * \{ */ - -static void lib_link_cachefiles(BlendLibReader *UNUSED(reader), CacheFile *UNUSED(cache_file)) -{ -} - -static void direct_link_cachefile(BlendDataReader *reader, CacheFile *cache_file) -{ - BLI_listbase_clear(&cache_file->object_paths); - cache_file->handle = NULL; - cache_file->handle_filepath[0] = '\0'; - cache_file->handle_readers = NULL; - - /* relink animdata */ - BLO_read_data_address(reader, &cache_file->adt); - BKE_animdata_blend_read_data(reader, cache_file->adt); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read ID: WorkSpace * \{ */ @@ -2804,32 +2783,6 @@ void blo_do_versions_key_uidgen(Key *key) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: Texture - * \{ */ - -static void lib_link_texture(BlendLibReader *reader, Tex *tex) -{ - BLO_read_id_address(reader, tex->id.lib, &tex->ima); - BLO_read_id_address(reader, tex->id.lib, &tex->ipo); // XXX deprecated - old animation system -} - -static void direct_link_texture(BlendDataReader *reader, Tex *tex) -{ - BLO_read_data_address(reader, &tex->adt); - BKE_animdata_blend_read_data(reader, tex->adt); - - BLO_read_data_address(reader, &tex->coba); - - BLO_read_data_address(reader, &tex->preview); - BKE_previewimg_blend_read(reader, tex->preview); - - tex->iuser.ok = 1; - tex->iuser.scene = NULL; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read ID: Particle Settings * \{ */ @@ -4947,100 +4900,6 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: Grease Pencil - * \{ */ - -/* relink's grease pencil data's refs */ -static void lib_link_gpencil(BlendLibReader *reader, bGPdata *gpd) -{ - /* Relink all data-lock linked by GP data-lock */ - /* Layers */ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* Layer -> Parent References */ - BLO_read_id_address(reader, gpd->id.lib, &gpl->parent); - } - - /* materials */ - for (int a = 0; a < gpd->totcol; a++) { - BLO_read_id_address(reader, gpd->id.lib, &gpd->mat[a]); - } -} - -/* relinks grease-pencil data - used for direct_link and old file linkage */ -static void direct_link_gpencil(BlendDataReader *reader, bGPdata *gpd) -{ - /* we must firstly have some grease-pencil data to link! */ - if (gpd == NULL) { - return; - } - - /* relink animdata */ - BLO_read_data_address(reader, &gpd->adt); - BKE_animdata_blend_read_data(reader, gpd->adt); - - /* Ensure full objectmode for linked grease pencil. */ - if (gpd->id.lib != NULL) { - gpd->flag &= ~GP_DATA_STROKE_PAINTMODE; - gpd->flag &= ~GP_DATA_STROKE_EDITMODE; - gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE; - gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE; - gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE; - } - - /* init stroke buffer */ - gpd->runtime.sbuffer = NULL; - gpd->runtime.sbuffer_used = 0; - gpd->runtime.sbuffer_size = 0; - gpd->runtime.tot_cp_points = 0; - - /* relink palettes (old palettes deprecated, only to convert old files) */ - BLO_read_list(reader, &gpd->palettes); - if (gpd->palettes.first != NULL) { - LISTBASE_FOREACH (Palette *, palette, &gpd->palettes) { - BLO_read_list(reader, &palette->colors); - } - } - - /* materials */ - BLO_read_pointer_array(reader, (void **)&gpd->mat); - - /* relink layers */ - BLO_read_list(reader, &gpd->layers); - - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* relink frames */ - BLO_read_list(reader, &gpl->frames); - - BLO_read_data_address(reader, &gpl->actframe); - - gpl->runtime.icon_id = 0; - - /* Relink masks. */ - BLO_read_list(reader, &gpl->mask_layers); - - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - /* relink strokes (and their points) */ - BLO_read_list(reader, &gpf->strokes); - - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* relink stroke points array */ - BLO_read_data_address(reader, &gps->points); - /* Relink geometry*/ - BLO_read_data_address(reader, &gps->triangles); - - /* relink weight data */ - if (gps->dvert) { - BLO_read_data_address(reader, &gps->dvert); - BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert); - } - } - } - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read Screen Area/Region (Screen Data) * \{ */ @@ -5185,7 +5044,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) if (v3d->gpd) { BLO_read_data_address(reader, &v3d->gpd); - direct_link_gpencil(reader, v3d->gpd); + BKE_gpencil_blend_read_data(reader, v3d->gpd); } BLO_read_data_address(reader, &v3d->localvd); @@ -5257,7 +5116,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) #if 0 sima->gpd = newdataadr(fd, sima->gpd); if (sima->gpd) { - direct_link_gpencil(fd, sima->gpd); + BKE_gpencil_blend_read_data(fd, sima->gpd); } #endif } @@ -5266,7 +5125,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) if (snode->gpd) { BLO_read_data_address(reader, &snode->gpd); - direct_link_gpencil(reader, snode->gpd); + BKE_gpencil_blend_read_data(reader, snode->gpd); } BLO_read_list(reader, &snode->treepath); @@ -5291,7 +5150,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) #if 0 if (sseq->gpd) { sseq->gpd = newdataadr(fd, sseq->gpd); - direct_link_gpencil(fd, sseq->gpd); + BKE_gpencil_blend_read_data(fd, sseq->gpd); } #endif sseq->scopes.reference_ibuf = NULL; @@ -6324,158 +6183,6 @@ static void fix_relpaths_library(const char *basepath, Main *main) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Read ID: Sound - * \{ */ - -static void direct_link_sound(BlendDataReader *reader, bSound *sound) -{ - sound->tags = 0; - sound->handle = NULL; - sound->playback_handle = NULL; - - /* versioning stuff, if there was a cache, then we enable caching: */ - if (sound->cache) { - sound->flags |= SOUND_FLAGS_CACHING; - sound->cache = NULL; - } - - if (BLO_read_data_is_undo(reader)) { - sound->tags |= SOUND_TAGS_WAVEFORM_NO_RELOAD; - } - - sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); - BLI_spin_init(sound->spinlock); - - /* clear waveform loading flag */ - sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING; - - BKE_packedfile_blend_read(reader, &sound->packedfile); - BKE_packedfile_blend_read(reader, &sound->newpackedfile); -} - -static void lib_link_sound(BlendLibReader *reader, bSound *sound) -{ - BLO_read_id_address( - reader, sound->id.lib, &sound->ipo); // XXX deprecated - old animation system -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Hair - * \{ */ - -static void lib_link_hair(BlendLibReader *reader, Hair *hair) -{ - for (int a = 0; a < hair->totcol; a++) { - BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]); - } -} - -static void direct_link_hair(BlendDataReader *reader, Hair *hair) -{ - BLO_read_data_address(reader, &hair->adt); - BKE_animdata_blend_read_data(reader, hair->adt); - - /* Geometry */ - CustomData_blend_read(reader, &hair->pdata, hair->totpoint); - CustomData_blend_read(reader, &hair->cdata, hair->totcurve); - BKE_hair_update_customdata_pointers(hair); - - /* Materials */ - BLO_read_pointer_array(reader, (void **)&hair->mat); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Point Cloud - * \{ */ - -static void lib_link_pointcloud(BlendLibReader *reader, PointCloud *pointcloud) -{ - for (int a = 0; a < pointcloud->totcol; a++) { - BLO_read_id_address(reader, pointcloud->id.lib, &pointcloud->mat[a]); - } -} - -static void direct_link_pointcloud(BlendDataReader *reader, PointCloud *pointcloud) -{ - BLO_read_data_address(reader, &pointcloud->adt); - BKE_animdata_blend_read_data(reader, pointcloud->adt); - - /* Geometry */ - CustomData_blend_read(reader, &pointcloud->pdata, pointcloud->totpoint); - BKE_pointcloud_update_customdata_pointers(pointcloud); - - /* Materials */ - BLO_read_pointer_array(reader, (void **)&pointcloud->mat); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Volume - * \{ */ - -static void lib_link_volume(BlendLibReader *reader, Volume *volume) -{ - /* Needs to be done *after* cache pointers are restored (call to - * `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in - * lib_link... */ - BKE_volume_init_grids(volume); - - for (int a = 0; a < volume->totcol; a++) { - BLO_read_id_address(reader, volume->id.lib, &volume->mat[a]); - } -} - -static void direct_link_volume(BlendDataReader *reader, Volume *volume) -{ - BLO_read_data_address(reader, &volume->adt); - BKE_animdata_blend_read_data(reader, volume->adt); - - BKE_packedfile_blend_read(reader, &volume->packedfile); - volume->runtime.frame = 0; - - /* materials */ - BLO_read_pointer_array(reader, (void **)&volume->mat); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Read ID: Simulation - * \{ */ - -static void lib_link_simulation(BlendLibReader *reader, Simulation *simulation) -{ - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { - BLO_read_id_address(reader, simulation->id.lib, &dependency->id); - } -} - -static void direct_link_simulation(BlendDataReader *reader, Simulation *simulation) -{ - BLO_read_data_address(reader, &simulation->adt); - BKE_animdata_blend_read_data(reader, simulation->adt); - - BLO_read_list(reader, &simulation->states); - LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { - BLO_read_data_address(reader, &state->name); - BLO_read_data_address(reader, &state->type); - if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - CustomData_blend_read(reader, &particle_state->attributes, particle_state->tot_particles); - } - } - - BLO_read_list(reader, &simulation->dependencies); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Read Library Data Block * \{ */ @@ -6634,45 +6341,21 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * case ID_OB: direct_link_object(&reader, (Object *)id); break; - case ID_TE: - direct_link_texture(&reader, (Tex *)id); - break; case ID_IP: direct_link_ipo(&reader, (Ipo *)id); break; case ID_LI: direct_link_library(fd, (Library *)id, main); break; - case ID_SO: - direct_link_sound(&reader, (bSound *)id); - break; case ID_GR: direct_link_collection(&reader, (Collection *)id); break; case ID_PA: direct_link_particlesettings(&reader, (ParticleSettings *)id); break; - case ID_GD: - direct_link_gpencil(&reader, (bGPdata *)id); - break; - case ID_CF: - direct_link_cachefile(&reader, (CacheFile *)id); - break; case ID_WS: direct_link_workspace(&reader, (WorkSpace *)id, main); break; - case ID_HA: - direct_link_hair(&reader, (Hair *)id); - break; - case ID_PT: - direct_link_pointcloud(&reader, (PointCloud *)id); - break; - case ID_VO: - direct_link_volume(&reader, (Volume *)id); - break; - case ID_SIM: - direct_link_simulation(&reader, (Simulation *)id); - break; case ID_ME: case ID_LT: case ID_AC: @@ -6696,6 +6379,14 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * case ID_AR: case ID_LP: case ID_KE: + case ID_TE: + case ID_GD: + case ID_HA: + case ID_PT: + case ID_VO: + case ID_SIM: + case ID_SO: + case ID_CF: /* Do nothing. Handled by IDTypeInfo callback. */ break; } @@ -7315,8 +7006,8 @@ static void lib_link_all(FileData *fd, Main *bmain) lib_link_object(&reader, (Object *)id); break; case ID_SCR: - /* DO NOT skip screens here, - * 3D viewport may contains pointers to other ID data (like bgpic)! See T41411. */ + /* DO NOT skip screens here, 3D viewport may contains pointers + * to other ID data (like #View3D.ob_center)! See T41411. */ lib_link_screen(&reader, (bScreen *)id); break; case ID_PA: @@ -7325,30 +7016,6 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_GR: lib_link_collection(&reader, (Collection *)id); break; - case ID_SO: - lib_link_sound(&reader, (bSound *)id); - break; - case ID_CF: - lib_link_cachefiles(&reader, (CacheFile *)id); - break; - case ID_HA: - lib_link_hair(&reader, (Hair *)id); - break; - case ID_PT: - lib_link_pointcloud(&reader, (PointCloud *)id); - break; - case ID_VO: - lib_link_volume(&reader, (Volume *)id); - break; - case ID_TE: - lib_link_texture(&reader, (Tex *)id); - break; - case ID_GD: - lib_link_gpencil(&reader, (bGPdata *)id); - break; - case ID_SIM: - lib_link_simulation(&reader, (Simulation *)id); - break; case ID_IP: /* XXX deprecated... still needs to be maintained for version patches still. */ lib_link_ipo(&reader, (Ipo *)id); @@ -7379,6 +7046,14 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_AR: case ID_LP: case ID_KE: + case ID_TE: + case ID_GD: + case ID_HA: + case ID_PT: + case ID_VO: + case ID_SIM: + case ID_SO: + case ID_CF: /* Do nothing. Handled by IDTypeInfo callback. */ break; } @@ -8064,12 +7739,6 @@ static void expand_collection(BlendExpander *expander, Collection *collection) #endif } -static void expand_texture(BlendExpander *expander, Tex *tex) -{ - BLO_expand(expander, tex->ima); - BLO_expand(expander, tex->ipo); // XXX deprecated - old animation system -} - /* callback function used to expand constraint ID-links */ static void expand_constraint_cb(bConstraint *UNUSED(con), ID **idpoin, @@ -8312,26 +7981,6 @@ static void expand_scene(BlendExpander *expander, Scene *sce) } } -static void expand_cachefile(BlendExpander *UNUSED(expander), CacheFile *UNUSED(cache_file)) -{ -} - -static void expand_sound(BlendExpander *expander, bSound *snd) -{ - BLO_expand(expander, snd->ipo); // XXX deprecated - old animation system -} - -static void expand_gpencil(BlendExpander *expander, bGPdata *gpd) -{ - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - BLO_expand(expander, gpl->parent); - } - - for (int a = 0; a < gpd->totcol; a++) { - BLO_expand(expander, gpd->mat[a]); - } -} - static void expand_workspace(BlendExpander *expander, WorkSpace *workspace) { LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) { @@ -8339,34 +7988,6 @@ static void expand_workspace(BlendExpander *expander, WorkSpace *workspace) } } -static void expand_hair(BlendExpander *expander, Hair *hair) -{ - for (int a = 0; a < hair->totcol; a++) { - BLO_expand(expander, hair->mat[a]); - } -} - -static void expand_pointcloud(BlendExpander *expander, PointCloud *pointcloud) -{ - for (int a = 0; a < pointcloud->totcol; a++) { - BLO_expand(expander, pointcloud->mat[a]); - } -} - -static void expand_volume(BlendExpander *expander, Volume *volume) -{ - for (int a = 0; a < volume->totcol; a++) { - BLO_expand(expander, volume->mat[a]); - } -} - -static void expand_simulation(BlendExpander *expander, Simulation *simulation) -{ - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { - BLO_expand(expander, dependency->id); - } -} - /** * Set the callback func used over all ID data found by \a BLO_expand_main func. * @@ -8416,12 +8037,6 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_SCE: expand_scene(&expander, (Scene *)id); break; - case ID_TE: - expand_texture(&expander, (Tex *)id); - break; - case ID_SO: - expand_sound(&expander, (bSound *)id); - break; case ID_GR: expand_collection(&expander, (Collection *)id); break; @@ -8431,27 +8046,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_PA: expand_particlesettings(&expander, (ParticleSettings *)id); break; - case ID_GD: - expand_gpencil(&expander, (bGPdata *)id); - break; - case ID_CF: - expand_cachefile(&expander, (CacheFile *)id); - break; case ID_WS: expand_workspace(&expander, (WorkSpace *)id); break; - case ID_HA: - expand_hair(&expander, (Hair *)id); - break; - case ID_PT: - expand_pointcloud(&expander, (PointCloud *)id); - break; - case ID_VO: - expand_volume(&expander, (Volume *)id); - break; - case ID_SIM: - expand_simulation(&expander, (Simulation *)id); - break; default: break; } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 5c1bf3b022a..876d122b082 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -234,6 +234,8 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) * the outliner's, and it's less disruptive to just copy them. */ copy_v4_v4_uchar(btheme->space_file.back, btheme->space_outliner.back); copy_v4_v4_uchar(btheme->space_file.row_alternate, btheme->space_outliner.row_alternate); + + FROM_DEFAULT_V4_UCHAR(space_image.grid); } #undef FROM_DEFAULT_V4_UCHAR diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d4e3f4646d6..b3e937a29b2 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -95,9 +95,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" -#include "DNA_brush_types.h" #include "DNA_cachefile_types.h" -#include "DNA_camera_types.h" #include "DNA_cloth_types.h" #include "DNA_collection_types.h" #include "DNA_constraint_types.h" @@ -106,45 +104,23 @@ #include "DNA_fileglobal_types.h" #include "DNA_fluid_types.h" #include "DNA_genfile.h" -#include "DNA_gpencil_modifier_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_hair_types.h" -#include "DNA_key_types.h" -#include "DNA_lattice_types.h" -#include "DNA_layer_types.h" -#include "DNA_light_types.h" #include "DNA_lightprobe_types.h" -#include "DNA_linestyle_types.h" -#include "DNA_mask_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "DNA_meta_types.h" #include "DNA_movieclip_types.h" -#include "DNA_node_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" -#include "DNA_packedFile_types.h" #include "DNA_particle_types.h" #include "DNA_pointcache_types.h" -#include "DNA_pointcloud_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" -#include "DNA_simulation_types.h" -#include "DNA_sound_types.h" #include "DNA_space_types.h" -#include "DNA_speaker_types.h" -#include "DNA_text_types.h" -#include "DNA_vfont_types.h" #include "DNA_view3d_types.h" -#include "DNA_volume_types.h" #include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" -#include "DNA_world_types.h" #include "BLI_bitmap.h" #include "BLI_blenlib.h" @@ -160,7 +136,6 @@ #include "BKE_collection.h" #include "BKE_colortools.h" #include "BKE_constraint.h" -#include "BKE_curve.h" #include "BKE_curveprofile.h" #include "BKE_deform.h" #include "BKE_fcurve.h" @@ -1393,32 +1368,6 @@ static void write_object(BlendWriter *writer, Object *ob, const void *id_address } } -static void write_texture(BlendWriter *writer, Tex *tex, const void *id_address) -{ - if (tex->id.us > 0 || BLO_write_is_undo(writer)) { - /* write LibData */ - BLO_write_id_struct(writer, Tex, id_address, &tex->id); - BKE_id_blend_write(writer, &tex->id); - - if (tex->adt) { - BKE_animdata_blend_write(writer, tex->adt); - } - - /* direct data */ - if (tex->coba) { - BLO_write_struct(writer, ColorBand, tex->coba); - } - - /* nodetree is integral part of texture, no libdata */ - if (tex->nodetree) { - BLO_write_struct(writer, bNodeTree, tex->nodetree); - ntreeBlendWrite(writer, tex->nodetree); - } - - BKE_previewimg_blend_write(writer, tex->preview); - } -} - static void write_collection_nolib(BlendWriter *writer, Collection *collection) { /* Shared function for collection data-blocks and scene master collection. */ @@ -1791,47 +1740,6 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address) BLI_assert(sce->layer_properties == NULL); } -static void write_gpencil(BlendWriter *writer, bGPdata *gpd, const void *id_address) -{ - if (gpd->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed data-blocks. */ - /* XXX not sure why the whole run-time data is not cleared in reading code, - * for now mimicking it here. */ - gpd->runtime.sbuffer = NULL; - gpd->runtime.sbuffer_used = 0; - gpd->runtime.sbuffer_size = 0; - gpd->runtime.tot_cp_points = 0; - - /* write gpd data block to file */ - BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id); - BKE_id_blend_write(writer, &gpd->id); - - if (gpd->adt) { - BKE_animdata_blend_write(writer, gpd->adt); - } - - BLO_write_pointer_array(writer, gpd->totcol, gpd->mat); - - /* write grease-pencil layers to file */ - BLO_write_struct_list(writer, bGPDlayer, &gpd->layers); - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* Write mask list. */ - BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers); - /* write this layer's frames to file */ - BLO_write_struct_list(writer, bGPDframe, &gpl->frames); - LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { - /* write strokes */ - BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes); - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points); - BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles); - BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert); - } - } - } - } -} - static void write_wm_xr_data(BlendWriter *writer, wmXrData *xr_data) { write_view3dshading(writer, &xr_data->session_settings.shading); @@ -2122,40 +2030,6 @@ static void write_screen(BlendWriter *writer, bScreen *screen, const void *id_ad } } -static void write_sound(BlendWriter *writer, bSound *sound, const void *id_address) -{ - if (sound->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed datablocks. */ - sound->tags = 0; - sound->handle = NULL; - sound->playback_handle = NULL; - sound->spinlock = NULL; - - /* write LibData */ - BLO_write_id_struct(writer, bSound, id_address, &sound->id); - BKE_id_blend_write(writer, &sound->id); - - BKE_packedfile_blend_write(writer, sound->packedfile); - } -} - -static void write_cachefile(BlendWriter *writer, CacheFile *cache_file, const void *id_address) -{ - if (cache_file->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed datablocks. */ - BLI_listbase_clear(&cache_file->object_paths); - cache_file->handle = NULL; - memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath)); - cache_file->handle_readers = NULL; - - BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id); - - if (cache_file->adt) { - BKE_animdata_blend_write(writer, cache_file->adt); - } - } -} - static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const void *id_address) { BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id); @@ -2171,136 +2045,6 @@ static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const voi } } -static void write_hair(BlendWriter *writer, Hair *hair, const void *id_address) -{ - if (hair->id.us > 0 || BLO_write_is_undo(writer)) { - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); - CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff)); - - /* Write LibData */ - BLO_write_id_struct(writer, Hair, id_address, &hair->id); - BKE_id_blend_write(writer, &hair->id); - - /* Direct data */ - CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id); - CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id); - - BLO_write_pointer_array(writer, hair->totcol, hair->mat); - if (hair->adt) { - BKE_animdata_blend_write(writer, hair->adt); - } - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - if (clayers && clayers != clayers_buff) { - MEM_freeN(clayers); - } - } -} - -static void write_pointcloud(BlendWriter *writer, PointCloud *pointcloud, const void *id_address) -{ - if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) { - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare( - &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); - - /* Write LibData */ - BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id); - BKE_id_blend_write(writer, &pointcloud->id); - - /* Direct data */ - CustomData_blend_write( - writer, &pointcloud->pdata, players, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id); - - BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat); - if (pointcloud->adt) { - BKE_animdata_blend_write(writer, pointcloud->adt); - } - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - } -} - -static void write_volume(BlendWriter *writer, Volume *volume, const void *id_address) -{ - if (volume->id.us > 0 || BLO_write_is_undo(writer)) { - /* Clean up, important in undo case to reduce false detection of changed datablocks. */ - volume->runtime.grids = 0; - - /* write LibData */ - BLO_write_id_struct(writer, Volume, id_address, &volume->id); - BKE_id_blend_write(writer, &volume->id); - - /* direct data */ - BLO_write_pointer_array(writer, volume->totcol, volume->mat); - if (volume->adt) { - BKE_animdata_blend_write(writer, volume->adt); - } - - BKE_packedfile_blend_write(writer, volume->packedfile); - } -} - -static void write_simulation(BlendWriter *writer, Simulation *simulation, const void *id_address) -{ - if (simulation->id.us > 0 || BLO_write_is_undo(writer)) { - BLO_write_id_struct(writer, Simulation, id_address, &simulation->id); - BKE_id_blend_write(writer, &simulation->id); - - if (simulation->adt) { - BKE_animdata_blend_write(writer, simulation->adt); - } - - /* nodetree is integral part of simulation, no libdata */ - if (simulation->nodetree) { - BLO_write_struct(writer, bNodeTree, simulation->nodetree); - ntreeBlendWrite(writer, simulation->nodetree); - } - - LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { - BLO_write_string(writer, state->name); - BLO_write_string(writer, state->type); - /* TODO: Decentralize this part. */ - if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomData_blend_write_prepare( - &particle_state->attributes, &players, players_buff, ARRAY_SIZE(players_buff)); - - BLO_write_struct(writer, ParticleSimulationState, particle_state); - - CustomData_blend_write(writer, - &particle_state->attributes, - players, - particle_state->tot_particles, - CD_MASK_ALL, - &simulation->id); - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - } - else if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER)) { - ParticleMeshEmitterSimulationState *emitter_state = (ParticleMeshEmitterSimulationState *) - state; - BLO_write_struct(writer, ParticleMeshEmitterSimulationState, emitter_state); - } - } - - BLO_write_struct_list(writer, SimulationDependency, &simulation->dependencies); - } -} - /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { @@ -2571,39 +2315,15 @@ static bool write_file_handle(Main *mainvar, case ID_SCE: write_scene(&writer, (Scene *)id_buffer, id); break; - case ID_SO: - write_sound(&writer, (bSound *)id_buffer, id); - break; case ID_GR: write_collection(&writer, (Collection *)id_buffer, id); break; case ID_OB: write_object(&writer, (Object *)id_buffer, id); break; - case ID_TE: - write_texture(&writer, (Tex *)id_buffer, id); - break; case ID_PA: write_particlesettings(&writer, (ParticleSettings *)id_buffer, id); break; - case ID_GD: - write_gpencil(&writer, (bGPdata *)id_buffer, id); - break; - case ID_CF: - write_cachefile(&writer, (CacheFile *)id_buffer, id); - break; - case ID_HA: - write_hair(&writer, (Hair *)id_buffer, id); - break; - case ID_PT: - write_pointcloud(&writer, (PointCloud *)id_buffer, id); - break; - case ID_VO: - write_volume(&writer, (Volume *)id_buffer, id); - break; - case ID_SIM: - write_simulation(&writer, (Simulation *)id_buffer, id); - break; case ID_ME: case ID_LT: case ID_AC: @@ -2627,6 +2347,14 @@ static bool write_file_handle(Main *mainvar, case ID_AR: case ID_LP: case ID_KE: + case ID_TE: + case ID_GD: + case ID_HA: + case ID_PT: + case ID_VO: + case ID_SIM: + case ID_SO: + case ID_CF: /* Do nothing, handled in IDTypeInfo callback. */ break; case ID_LI: diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 5f5d6baaba2..9199801d1a1 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -41,7 +41,7 @@ * \subsection bm_faces Faces * * Faces in BMesh are stored as a circular linked list of loops. Loops store per-face-vertex data - * (amongst other things outlined later in this document), and define the face boundary. + * (among other things outlined later in this document), and define the face boundary. * \subsection bm_loop The Loop * * Loops can be thought of as a *face-corner*, since faces don't reference verts or edges directly. diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index e5dfee7d0cd..08f794d7eba 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -198,13 +198,13 @@ void ExecutionGroup::execute(ExecutionSystem *graph) const bNodeTree *bTree = context.getbNodeTree(); if (this->m_width == 0 || this->m_height == 0) { return; - } /// \note Break out... no pixels to calculate. + } /** \note Break out... no pixels to calculate. */ if (bTree->test_break && bTree->test_break(bTree->tbh)) { return; - } /// \note Early break out for blur and preview nodes. + } /** \note Early break out for blur and preview nodes. */ if (this->m_numberOfChunks == 0) { return; - } /// \note Early break out. + } /** \note Early break out. */ unsigned int chunkNumber; this->m_executionStartTime = PIL_check_seconds_timer(); diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp index 01dd662ad11..fe680f61a90 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.cpp +++ b/source/blender/compositor/intern/COM_NodeGraph.cpp @@ -184,7 +184,7 @@ NodeOutput *NodeGraph::find_output(const NodeRange &node_range, bNodeSocket *b_s void NodeGraph::add_bNodeLink(const NodeRange &node_range, bNodeLink *b_nodelink) { - /// \note Ignore invalid links. + /** \note Ignore invalid links. */ if (!(b_nodelink->flag & NODE_LINK_VALID)) { return; } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 06929f0037e..570e1eeba20 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -44,26 +44,26 @@ # error COM_CURRENT_THREADING_MODEL No threading model selected #endif -/// \brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is created +/** \brief list of all CPUDevices. for every hardware thread an instance of CPUDevice is created */ static vector<CPUDevice *> g_cpudevices; static ThreadLocal(CPUDevice *) g_thread_device; #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE -/// \brief list of all thread for every CPUDevice in cpudevices a thread exists +/** \brief list of all thread for every CPUDevice in cpudevices a thread exists. */ static ListBase g_cputhreads; static bool g_cpuInitialized = false; -/// \brief all scheduled work for the cpu +/** \brief all scheduled work for the cpu */ static ThreadQueue *g_cpuqueue; static ThreadQueue *g_gpuqueue; # ifdef COM_OPENCL_ENABLED static cl_context g_context; static cl_program g_program; -/// \brief list of all OpenCLDevices. for every OpenCL GPU device an instance of OpenCLDevice is -/// created +/** \brief list of all OpenCLDevices. for every OpenCL GPU device an instance of OpenCLDevice is + * created. */ static vector<OpenCLDevice *> g_gpudevices; -/// \brief list of all thread for every GPUDevice in cpudevices a thread exists +/** \brief list of all thread for every GPUDevice in cpudevices a thread exists. */ static ListBase g_gputhreads; -/// \brief all scheduled work for the gpu +/** \brief all scheduled work for the GPU. */ static bool g_openclActive = false; static bool g_openclInitialized = false; # endif diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index 3dbd3773247..c178722a23f 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -72,7 +72,7 @@ NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter, void ImageNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const { - /// Image output + /** Image output */ NodeOutput *outputImage = this->getOutputSocket(0); bNode *editorNode = this->getbNode(); Image *image = (Image *)editorNode->id; diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp index 70aaab560cd..99cc9f5dd01 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp @@ -41,7 +41,7 @@ void ReadBufferOperation::determineResolution(unsigned int resolution[2], operation->determineResolution(resolution, preferredResolution); operation->setResolution(resolution); - /// \todo: may not occur!, but does with blur node + /** \todo: may not occur!, but does with blur node */ if (this->m_memoryProxy->getExecutor()) { this->m_memoryProxy->getExecutor()->setResolution(resolution); } diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index 3d5d50e1c7f..e1d891559a7 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -190,7 +190,7 @@ void ViewerOperation::updateImage(rcti *rect) rect->ymin, rect->xmax, rect->ymax); - + this->m_image->gpuflag |= IMA_GPU_REFRESH; this->updateDraw(); } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc index bc73700e1ba..0b8203ab05f 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.cc +++ b/source/blender/depsgraph/intern/depsgraph_physics.cc @@ -96,7 +96,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph, if (hash == nullptr) { return nullptr; } - /* Note: nullptr is a valid loolup key here as it means that the relation is not bound to a + /* Note: nullptr is a valid lookup key here as it means that the relation is not bound to a * specific collection. */ ID *collection_orig = DEG_get_original_id(object_id_safe(collection)); return hash->lookup_default(collection_orig, nullptr); diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 8aea2f8e969..1344d390871 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -44,10 +44,6 @@ set(INC ../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC intern/draw_cache.c intern/draw_cache_extract_mesh.c @@ -77,6 +73,8 @@ set(SRC intern/draw_select_buffer.c intern/draw_view.c engines/basic/basic_engine.c + engines/image/image_engine.c + engines/image/image_shader.c engines/eevee/eevee_bloom.c engines/eevee/eevee_data.c engines/eevee/eevee_depth_of_field.c @@ -132,6 +130,7 @@ set(SRC engines/overlay/overlay_edit_curve.c engines/overlay/overlay_edit_mesh.c engines/overlay/overlay_edit_text.c + engines/overlay/overlay_edit_uv.c engines/overlay/overlay_engine.c engines/overlay/overlay_extra.c engines/overlay/overlay_facing.c @@ -319,6 +318,7 @@ data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC) data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC) data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/common_overlay_lib.glsl SRC) data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/armature_dof_vert.glsl SRC) @@ -362,6 +362,15 @@ data_to_c_simple(engines/overlay/shaders/edit_mesh_skin_root_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_mesh_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_particle_strand_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/edit_particle_point_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_edges_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_edges_geom.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_edges_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_verts_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_verts_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_faces_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_face_dots_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_stretching_vert.glsl SRC) +data_to_c_simple(engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/extra_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/extra_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/extra_groundline_vert.glsl SRC) @@ -402,6 +411,9 @@ data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/wireframe_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/xray_fade_frag.glsl SRC) +data_to_c_simple(engines/image/shaders/engine_image_frag.glsl SRC) +data_to_c_simple(engines/image/shaders/engine_image_vert.glsl SRC) + list(APPEND INC ) @@ -426,7 +438,6 @@ if(WITH_GTESTS) endif() endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 6db3bb39643..ca5c2c94b40 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -99,6 +99,10 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, const bool do_color_management, struct GPUOffScreen *ofs, struct GPUViewport *viewport); +void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, + struct ARegion *region, + struct GPUViewport *viewport, + const struct bContext *evil_C); void DRW_draw_select_loop(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 8216d2545ac..e731ed071b2 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -84,9 +84,7 @@ extern struct DrawEngineType draw_engine_eevee_type; #define EEVEE_PROBE_MAX min_ii(MAX_PROBE, GPU_max_texture_layers() / 6) #define EEVEE_VELOCITY_TILE_SIZE 32 -#define USE_VOLUME_OPTI \ - (GLEW_ARB_shader_image_load_store && GLEW_ARB_shading_language_420pack && \ - !GPU_crappy_amd_driver()) +#define USE_VOLUME_OPTI (GPU_shader_image_load_store_support()) #define SWAP_DOUBLE_BUFFERS() \ { \ diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 69b916244b5..93701887b51 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -601,6 +601,10 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); + if (USE_VOLUME_OPTI) { + DRW_shgroup_uniform_image_ref(grp, "finalScattering_img", &txl->volume_scatter_history); + DRW_shgroup_uniform_image_ref(grp, "finalTransmittance_img", &txl->volume_transmit_history); + } DRW_shgroup_call_procedural_triangles( grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]); @@ -610,6 +614,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter); DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit); DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); @@ -714,15 +719,7 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_draw_pass(psl->volumetric_scatter_ps); if (USE_VOLUME_OPTI) { - int tex_scatter = GPU_texture_opengl_bindcode(txl->volume_scatter_history); - int tex_transmit = GPU_texture_opengl_bindcode(txl->volume_transmit_history); - /* TODO(fclem) Encapsulate these GL calls into DRWManager. */ - glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - /* Subtlety here! we need to tell the GL that the texture is layered (GL_TRUE) - * in order to bind the full 3D texture and not just a 2D slice. */ - glBindImageTexture(0, tex_scatter, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R11F_G11F_B10F); - glBindImageTexture(1, tex_transmit, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R11F_G11F_B10F); - + /* Avoid feedback loop assert. */ GPU_framebuffer_bind(fbl->volumetric_fb); } else { @@ -731,13 +728,6 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_draw_pass(psl->volumetric_integration_ps); - if (USE_VOLUME_OPTI) { - glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); - - glBindImageTexture(0, 0, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R11F_G11F_B10F); - glBindImageTexture(1, 0, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R11F_G11F_B10F); - } - SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb); SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history); SWAP(GPUTexture *, txl->volume_transmit, txl->volume_transmit_history); @@ -763,6 +753,10 @@ void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); e_data.depth_src = dtxl->depth; + if (USE_VOLUME_OPTI) { + GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); + } + /* Apply for opaque geometry. */ GPU_framebuffer_bind(fbl->main_color_fb); DRW_draw_pass(psl->volumetric_resolve_ps); diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl index f4276bd61bd..12b7d8acbea 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl @@ -11,8 +11,8 @@ uniform sampler3D volumeScattering; /* Result of the scatter step */ uniform sampler3D volumeExtinction; #ifdef USE_VOLUME_OPTI -uniform layout(binding = 0, r11f_g11f_b10f) writeonly restrict image3D finalScattering_img; -uniform layout(binding = 1, r11f_g11f_b10f) writeonly restrict image3D finalTransmittance_img; +uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalScattering_img; +uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalTransmittance_img; vec3 finalScattering; vec3 finalTransmittance; diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c new file mode 100644 index 00000000000..9f1278b473b --- /dev/null +++ b/source/blender/draw/engines/image/image_engine.c @@ -0,0 +1,304 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_editors + * + * Draw engine to draw the Image/UV editor + */ + +#include "DRW_render.h" + +#include "BKE_image.h" +#include "BKE_object.h" + +#include "DNA_camera_types.h" + +#include "IMB_imbuf_types.h" + +#include "ED_image.h" + +#include "GPU_batch.h" + +#include "image_engine.h" +#include "image_private.h" + +#define SIMA_DRAW_FLAG_SHOW_ALPHA (1 << 0) +#define SIMA_DRAW_FLAG_APPLY_ALPHA (1 << 1) +#define SIMA_DRAW_FLAG_SHUFFLING (1 << 2) +#define SIMA_DRAW_FLAG_DEPTH (1 << 3) +#define SIMA_DRAW_FLAG_TILED (1 << 4) +#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5) + +static void image_cache_image_add(DRWShadingGroup *grp, Image *image) +{ + const bool is_tiled_texture = image && image->source == IMA_SRC_TILED; + float obmat[4][4]; + unit_m4(obmat); + + GPUBatch *geom = DRW_cache_quad_get(); + + if (is_tiled_texture) { + LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) { + const int tile_x = ((tile->tile_number - 1001) % 10); + const int tile_y = ((tile->tile_number - 1001) / 10); + obmat[3][1] = (float)tile_y; + obmat[3][0] = (float)tile_x; + DRW_shgroup_call_obmat(grp, geom, obmat); + } + } + else { + DRW_shgroup_call_obmat(grp, geom, obmat); + } +} + +static void image_gpu_texture_get(Image *image, + ImageUser *iuser, + ImBuf *ibuf, + GPUTexture **r_gpu_texture, + bool *r_owns_texture, + GPUTexture **r_tex_tile_data) +{ + + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + if (image) { + if (BKE_image_is_multilayer(image)) { + /* update multiindex and pass for the current eye */ + BKE_image_multilayer_index(image->rr, &sima->iuser); + } + else { + BKE_image_multiview_index(image, &sima->iuser); + } + + if (ibuf) { + if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { + if (ibuf->zbuf) { + BLI_assert(!"Integer based depth buffers not supported"); + } + else if (ibuf->zbuf_float) { + *r_gpu_texture = GPU_texture_create_2d( + __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->zbuf_float); + *r_owns_texture = true; + } + else if (ibuf->rect_float && ibuf->channels == 1) { + *r_gpu_texture = GPU_texture_create_2d( + __func__, ibuf->x, ibuf->y, 0, GPU_R16F, ibuf->rect_float); + *r_owns_texture = true; + } + } + else if (image->source == IMA_SRC_TILED) { + *r_gpu_texture = BKE_image_get_gpu_tiles(image, iuser, ibuf); + *r_tex_tile_data = BKE_image_get_gpu_tilemap(image, iuser, NULL); + *r_owns_texture = false; + } + else { + *r_gpu_texture = BKE_image_get_gpu_texture(image, iuser, ibuf); + *r_owns_texture = false; + } + } + } +} + +static void image_cache_image(IMAGE_Data *vedata, Image *image, ImageUser *iuser, ImBuf *ibuf) +{ + IMAGE_PassList *psl = vedata->psl; + IMAGE_StorageList *stl = vedata->stl; + IMAGE_PrivateData *pd = stl->pd; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene = draw_ctx->scene; + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + GPUTexture *tex_tile_data = NULL; + image_gpu_texture_get(image, iuser, ibuf, &pd->texture, &pd->owns_texture, &tex_tile_data); + + if (pd->texture) { + static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + static float shuffle[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + static float far_near[2] = {100.0f, 0.0f}; + + if (scene->camera && scene->camera->type == OB_CAMERA) { + far_near[1] = ((Camera *)scene->camera->data)->clip_start; + far_near[0] = ((Camera *)scene->camera->data)->clip_end; + } + + const bool use_premul_alpha = image->alpha_mode == IMA_ALPHA_PREMUL; + const bool is_tiled_texture = tex_tile_data != NULL; + const bool do_repeat = (!is_tiled_texture) && ((sima->flag & SI_DRAW_TILE) != 0); + const bool is_zoom_out = sima->zoom < 1.0f; + + /* use interpolation filtering when zooming out */ + eGPUSamplerState state = 0; + SET_FLAG_FROM_TEST(state, is_zoom_out, GPU_SAMPLER_FILTER); + + int draw_flags = 0; + SET_FLAG_FROM_TEST(draw_flags, do_repeat, SIMA_DRAW_FLAG_DO_REPEAT); + + if ((sima->flag & SI_USE_ALPHA) != 0) { + /* Show RGBA */ + draw_flags |= SIMA_DRAW_FLAG_SHOW_ALPHA | SIMA_DRAW_FLAG_APPLY_ALPHA; + } + else if ((sima->flag & SI_SHOW_ALPHA) != 0) { + draw_flags |= SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 0.0f, 0.0f, 0.0f, 1.0f); + } + else if ((sima->flag & SI_SHOW_ZBUF) != 0) { + draw_flags |= SIMA_DRAW_FLAG_DEPTH | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f); + } + else if ((sima->flag & SI_SHOW_R) != 0) { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 1.0f, 0.0f, 0.0f, 0.0f); + } + else if ((sima->flag & SI_SHOW_G) != 0) { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 0.0f, 1.0f, 0.0f, 0.0f); + } + else if ((sima->flag & SI_SHOW_B) != 0) { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA | SIMA_DRAW_FLAG_SHUFFLING; + copy_v4_fl4(shuffle, 0.0f, 0.0f, 1.0f, 0.0f); + } + else /* RGB */ { + draw_flags |= SIMA_DRAW_FLAG_APPLY_ALPHA; + } + + GPUShader *shader = IMAGE_shader_image_get(); + DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass); + if (tex_tile_data != NULL) { + draw_flags |= SIMA_DRAW_FLAG_TILED; + DRW_shgroup_uniform_texture_ex(shgrp, "imageTileArray", pd->texture, state); + DRW_shgroup_uniform_texture(shgrp, "imageTileData", tex_tile_data); + } + else { + DRW_shgroup_uniform_texture_ex(shgrp, "imageTexture", pd->texture, state); + } + DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", far_near); + DRW_shgroup_uniform_vec4_copy(shgrp, "color", color); + DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", shuffle); + DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", draw_flags); + DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", use_premul_alpha); + image_cache_image_add(shgrp, image); + } +} + +/* -------------------------------------------------------------------- */ +/** \name Engine Callbacks + * \{ */ +static void IMAGE_engine_init(void *ved) +{ + IMAGE_shader_library_ensure(); + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_StorageList *stl = vedata->stl; + if (!stl->pd) { + stl->pd = MEM_callocN(sizeof(IMAGE_PrivateData), __func__); + } + IMAGE_PrivateData *pd = stl->pd; + + pd->ibuf = NULL; + pd->lock = NULL; + pd->texture = NULL; +} + +static void IMAGE_cache_init(void *ved) +{ + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_StorageList *stl = vedata->stl; + IMAGE_PrivateData *pd = stl->pd; + IMAGE_PassList *psl = vedata->psl; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + { + /* Write depth is needed for background overlay rendering. Near depth is used for + * transparency checker and Far depth is used for indicating the image size. */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | + DRW_STATE_BLEND_ALPHA_PREMUL; + psl->image_pass = DRW_pass_create("Image", state); + } + + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + GPU_framebuffer_bind(dfbl->default_fb); + static float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color_depth(dfbl->default_fb, clear_col, 1.0); + + { + Image *image = ED_space_image(sima); + ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &pd->lock, 0); + image_cache_image(vedata, image, &sima->iuser, ibuf); + pd->ibuf = ibuf; + } +} + +static void IMAGE_cache_populate(void *UNUSED(vedata), Object *UNUSED(ob)) +{ + /* Function intentional left empty. `cache_populate` is required to be implemented. */ +} + +static void image_draw_finish(IMAGE_Data *ved) +{ + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_StorageList *stl = vedata->stl; + IMAGE_PrivateData *pd = stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + + ED_space_image_release_buffer(sima, pd->ibuf, pd->lock); + + if (pd->texture && pd->owns_texture) { + GPU_texture_free(pd->texture); + pd->owns_texture = false; + } + pd->texture = NULL; +} + +static void IMAGE_draw_scene(void *ved) +{ + IMAGE_Data *vedata = (IMAGE_Data *)ved; + IMAGE_PassList *psl = vedata->psl; + + DRW_draw_pass(psl->image_pass); + + image_draw_finish(vedata); +} + +static void IMAGE_engine_free(void) +{ + IMAGE_shader_free(); +} + +/* \} */ +static const DrawEngineDataSize IMAGE_data_size = DRW_VIEWPORT_DATA_SIZE(IMAGE_Data); + +DrawEngineType draw_engine_image_type = { + NULL, /* next */ + NULL, /* prev */ + N_("UV/Image"), /* idname */ + &IMAGE_data_size, /* vedata_size */ + &IMAGE_engine_init, /* engine_init */ + &IMAGE_engine_free, /* engine_free */ + &IMAGE_cache_init, /* cache_init */ + &IMAGE_cache_populate, /* cache_populate */ + NULL, /* cache_finish */ + &IMAGE_draw_scene, /* draw_scene */ + NULL, /* view_update */ + NULL, /* id_update */ + NULL, /* render_to_image */ +}; diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/draw/engines/image/image_engine.h index 09dc02c0fc6..0098d863ef9 100644 --- a/source/blender/gpu/GPU_debug.h +++ b/source/blender/draw/engines/image/image_engine.h @@ -13,23 +13,13 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. + * Copyright 2020, Blender Foundation. */ /** \file - * \ingroup gpu + * \ingroup draw_editors */ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - -/* prints something if debug mode is active only */ -void GPU_print_error_debug(const char *str); - -#ifdef __cplusplus -} -#endif +extern DrawEngineType draw_engine_image_type; diff --git a/source/blender/draw/engines/image/image_private.h b/source/blender/draw/engines/image/image_private.h new file mode 100644 index 00000000000..d11d868d4d2 --- /dev/null +++ b/source/blender/draw/engines/image/image_private.h @@ -0,0 +1,69 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct rcti; +struct GPUBatch; +struct Image; +struct ImBuf; +struct GPUTexture; + +/* *********** LISTS *********** */ + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct IMAGE_PassList { + DRWPass *image_pass; +} IMAGE_PassList; + +typedef struct IMAGE_PrivateData { + void *lock; + struct ImBuf *ibuf; + + struct GPUTexture *texture; + bool owns_texture; +} IMAGE_PrivateData; + +typedef struct IMAGE_StorageList { + IMAGE_PrivateData *pd; +} IMAGE_StorageList; + +typedef struct IMAGE_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + IMAGE_PassList *psl; + IMAGE_StorageList *stl; +} IMAGE_Data; + +/* image_shader.c */ +GPUShader *IMAGE_shader_image_get(void); +void IMAGE_shader_library_ensure(void); +void IMAGE_shader_free(void); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/draw/engines/image/image_shader.c b/source/blender/draw/engines/image/image_shader.c new file mode 100644 index 00000000000..433c79e20cf --- /dev/null +++ b/source/blender/draw/engines/image/image_shader.c @@ -0,0 +1,77 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" + +#include "GPU_batch.h" + +#include "image_engine.h" +#include "image_private.h" + +extern char datatoc_common_colormanagement_lib_glsl[]; +extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; + +extern char datatoc_engine_image_frag_glsl[]; +extern char datatoc_engine_image_vert_glsl[]; + +typedef struct IMAGE_Shaders { + GPUShader *image_sh; +} IMAGE_Shaders; + +static struct { + IMAGE_Shaders shaders; + DRWShaderLibrary *lib; +} e_data = {0}; /* Engine data */ + +void IMAGE_shader_library_ensure(void) +{ + if (e_data.lib == NULL) { + e_data.lib = DRW_shader_library_create(); + /* NOTE: Theses needs to be ordered by dependencies. */ + DRW_SHADER_LIB_ADD(e_data.lib, common_colormanagement_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); + } +} + +GPUShader *IMAGE_shader_image_get(void) +{ + IMAGE_Shaders *sh_data = &e_data.shaders; + if (!sh_data->image_sh) { + sh_data->image_sh = DRW_shader_create_with_shaderlib( + datatoc_engine_image_vert_glsl, NULL, datatoc_engine_image_frag_glsl, e_data.lib, NULL); + } + return sh_data->image_sh; +} + +void IMAGE_shader_free(void) +{ + GPUShader **sh_data_as_array = (GPUShader **)&e_data.shaders; + for (int i = 0; i < (sizeof(IMAGE_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + + DRW_SHADER_LIB_FREE_SAFE(e_data.lib); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/image/shaders/engine_image_frag.glsl b/source/blender/draw/engines/image/shaders/engine_image_frag.glsl new file mode 100644 index 00000000000..5c5d9362dfc --- /dev/null +++ b/source/blender/draw/engines/image/shaders/engine_image_frag.glsl @@ -0,0 +1,91 @@ +#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl) + +/* Keep in sync with image_engine.c */ +#define SIMA_DRAW_FLAG_SHOW_ALPHA (1 << 0) +#define SIMA_DRAW_FLAG_APPLY_ALPHA (1 << 1) +#define SIMA_DRAW_FLAG_SHUFFLING (1 << 2) +#define SIMA_DRAW_FLAG_DEPTH (1 << 3) +#define SIMA_DRAW_FLAG_TILED (1 << 4) +#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5) + +uniform sampler2DArray imageTileArray; +uniform sampler1DArray imageTileData; +uniform sampler2D imageTexture; + +uniform bool imgPremultiplied; +uniform int drawFlags; +uniform vec2 farNearDistances; +uniform vec4 color; +uniform vec4 shuffle; + +#define FAR_DISTANCE farNearDistances.x +#define NEAR_DISTANCE farNearDistances.y + +in vec2 uvs; + +out vec4 fragColor; + +/* TODO(fclem) deduplicate code. */ +bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map) +{ + vec2 tile_pos = floor(co.xy); + + if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) { + return false; + } + + float tile = 10.0 * tile_pos.y + tile_pos.x; + if (tile >= textureSize(map, 0).x) { + return false; + } + + /* Fetch tile information. */ + float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x; + if (tile_layer < 0.0) { + return false; + } + + vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0); + + co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer); + return true; +} + +void main() +{ + vec4 tex_color; + /* Read texture */ + if ((drawFlags & SIMA_DRAW_FLAG_TILED) != 0) { + vec3 co = vec3(uvs, 0.0); + if (node_tex_tile_lookup(co, imageTileArray, imageTileData)) { + tex_color = texture(imageTileArray, co); + } + else { + tex_color = vec4(1.0, 0.0, 1.0, 1.0); + } + } + else { + vec2 uvs_clamped = ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) ? + fract(uvs) : + clamp(uvs, vec2(0.0), vec2(1.0)); + tex_color = texture(imageTexture, uvs_clamped); + } + + if ((drawFlags & SIMA_DRAW_FLAG_APPLY_ALPHA) != 0) { + if (!imgPremultiplied && tex_color.a != 0.0 && tex_color.a != 1.0) { + tex_color.rgb *= tex_color.a; + } + } + if ((drawFlags & SIMA_DRAW_FLAG_DEPTH) != 0) { + tex_color = smoothstep(FAR_DISTANCE, NEAR_DISTANCE, tex_color); + } + + if ((drawFlags & SIMA_DRAW_FLAG_SHUFFLING) != 0) { + tex_color = color * dot(tex_color, shuffle); + } + if ((drawFlags & SIMA_DRAW_FLAG_SHOW_ALPHA) == 0) { + tex_color.a = 1.0; + } + + fragColor = tex_color; +} diff --git a/source/blender/draw/engines/image/shaders/engine_image_vert.glsl b/source/blender/draw/engines/image/shaders/engine_image_vert.glsl new file mode 100644 index 00000000000..3f1fb154d44 --- /dev/null +++ b/source/blender/draw/engines/image/shaders/engine_image_vert.glsl @@ -0,0 +1,31 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +#define SIMA_DRAW_FLAG_DO_REPEAT (1 << 5) + +uniform int drawFlags; + +in vec3 pos; +out vec2 uvs; + +void main() +{ + /* `pos` contains the coordinates of a quad (-1..1). but we need the coordinates of an image + * plane (0..1) */ + vec3 image_pos = pos * 0.5 + 0.5; + + if ((drawFlags & SIMA_DRAW_FLAG_DO_REPEAT) != 0) { + gl_Position = vec4(pos.xy, 0.0, 1.0); + uvs = point_view_to_object(image_pos).xy; + } + else { + vec3 world_pos = point_object_to_world(image_pos); + vec4 position = point_world_to_ndc(world_pos); + /* Move drawn pixels to the front. In the overlay engine the depth is used + * to detect if a transparency texture or the background color should be drawn. + * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4 + * actual pixels are at 0.75, 1.0 is used for the background. */ + position.z = 0.75; + gl_Position = position; + uvs = world_pos.xy; + } +} diff --git a/source/blender/draw/engines/overlay/overlay_background.c b/source/blender/draw/engines/overlay/overlay_background.c index f52ae691a35..cb09d916a0f 100644 --- a/source/blender/draw/engines/overlay/overlay_background.c +++ b/source/blender/draw/engines/overlay/overlay_background.c @@ -31,6 +31,7 @@ #define BG_GRADIENT 1 #define BG_CHECKER 2 #define BG_RADIAL 3 +#define BG_SOLID_CHECKER 4 void OVERLAY_background_cache_init(OVERLAY_Data *vedata) { @@ -40,7 +41,7 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene = draw_ctx->scene; const RegionView3D *rv3d = draw_ctx->rv3d; - const BoundBox *bb = rv3d->clipbb; + const BoundBox *bb = rv3d ? rv3d->clipbb : NULL; const View3D *v3d = draw_ctx->v3d; bool draw_clipping_bounds = (pd->clipping_state != 0); @@ -50,9 +51,11 @@ void OVERLAY_background_cache_init(OVERLAY_Data *vedata) if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) { background_type = BG_SOLID; - zero_v3(color_override); color_override[3] = 1.0f; } + else if (pd->is_image_editor) { + background_type = BG_SOLID_CHECKER; + } else if (!DRW_state_draw_background()) { background_type = BG_CHECKER; } diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c new file mode 100644 index 00000000000..109db6433e0 --- /dev/null +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c @@ -0,0 +1,394 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ +#include "DRW_render.h" + +#include "draw_cache_impl.h" +#include "draw_manager_text.h" + +#include "BKE_image.h" + +#include "DNA_mesh_types.h" + +#include "ED_image.h" + +#include "GPU_batch.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "overlay_private.h" + +typedef struct OVERLAY_StretchingAreaTotals { + void *next, *prev; + float *total_area; + float *total_area_uv; +} OVERLAY_StretchingAreaTotals; + +static OVERLAY_UVLineStyle edit_uv_line_style_from_space_image(const SpaceImage *sima) +{ + const bool is_uv_editor = sima->mode == SI_MODE_UV; + if (is_uv_editor) { + switch (sima->dt_uv) { + case SI_UVDT_OUTLINE: + return OVERLAY_UV_LINE_STYLE_OUTLINE; + case SI_UVDT_BLACK: + return OVERLAY_UV_LINE_STYLE_BLACK; + case SI_UVDT_WHITE: + return OVERLAY_UV_LINE_STYLE_WHITE; + case SI_UVDT_DASH: + return OVERLAY_UV_LINE_STYLE_DASH; + default: + return OVERLAY_UV_LINE_STYLE_BLACK; + } + } + else { + return OVERLAY_UV_LINE_STYLE_SHADOW; + } +} + +/* -------------------------------------------------------------------- */ +/** \name Internal API + * \{ */ + +void OVERLAY_edit_uv_init(OVERLAY_Data *vedata) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + const Scene *scene = draw_ctx->scene; + const ToolSettings *ts = scene->toolsettings; + + Image *image = sima->image; + /* By design no image is an image type. This so editor shows UV's by default. */ + const bool is_image_type = + (image == NULL) || ELEM(image->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER, IMA_TYPE_UV_TEST); + const bool is_uv_editor = sima->mode == SI_MODE_UV; + const bool has_edit_object = (draw_ctx->object_edit) != NULL; + const bool is_paint_mode = sima->mode == SI_MODE_PAINT; + const bool is_view_mode = sima->mode == SI_MODE_VIEW; + const bool is_edit_mode = draw_ctx->object_mode == OB_MODE_EDIT; + const bool do_uv_overlay = is_image_type && is_uv_editor && has_edit_object; + const bool show_modified_uvs = sima->flag & SI_DRAWSHADOW; + const bool is_tiled_image = image && (image->source == IMA_SRC_TILED); + const bool do_faces = ((sima->flag & SI_NO_DRAWFACES) == 0); + const bool do_face_dots = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode & SCE_SELECT_FACE) != 0 : + (ts->uv_selectmode == UV_SELECT_FACE); + const bool do_uvstretching_overlay = is_image_type && is_uv_editor && is_edit_mode && + ((sima->flag & SI_DRAW_STRETCH) != 0); + pd->edit_uv.do_faces = do_faces && !do_uvstretching_overlay; + pd->edit_uv.do_face_dots = do_faces && do_face_dots; + + pd->edit_uv.do_uv_overlay = do_uv_overlay; + pd->edit_uv.do_uv_shadow_overlay = + is_image_type && + ((is_paint_mode && + ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_EDIT)) != 0)) || + (is_view_mode && ((draw_ctx->object_mode & (OB_MODE_TEXTURE_PAINT)) != 0)) || + (do_uv_overlay && (show_modified_uvs))); + pd->edit_uv.do_uv_stretching_overlay = do_uvstretching_overlay; + pd->edit_uv.uv_opacity = sima->uv_opacity; + pd->edit_uv.do_tiled_image_overlay = is_image_type && is_tiled_image; + + pd->edit_uv.dash_length = 4.0f * UI_DPI_FAC; + pd->edit_uv.line_style = edit_uv_line_style_from_space_image(sima); + pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) > 0); + + pd->edit_uv.draw_type = sima->dt_uvstretch; + BLI_listbase_clear(&pd->edit_uv.totals); + pd->edit_uv.total_area_ratio = 0.0f; + pd->edit_uv.total_area_ratio_inv = 0.0f; + + ED_space_image_get_uv_aspect(sima, &pd->edit_uv.aspect[0], &pd->edit_uv.aspect[1]); +} + +void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->edit_uv.do_uv_overlay || pd->edit_uv.do_uv_shadow_overlay) { + /* uv edges */ + { + DRW_PASS_CREATE(psl->edit_uv_edges_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND_ALPHA); + GPUShader *sh = OVERLAY_shader_edit_uv_edges_get(); + if (pd->edit_uv.do_uv_shadow_overlay) { + pd->edit_uv_shadow_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps); + DRW_shgroup_uniform_block(pd->edit_uv_shadow_edges_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_int_copy( + pd->edit_uv_shadow_edges_grp, "lineStyle", OVERLAY_UV_LINE_STYLE_SHADOW); + DRW_shgroup_uniform_float_copy( + pd->edit_uv_shadow_edges_grp, "alpha", pd->edit_uv.uv_opacity); + DRW_shgroup_uniform_float( + pd->edit_uv_shadow_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1); + DRW_shgroup_uniform_bool( + pd->edit_uv_shadow_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1); + } + + if (pd->edit_uv.do_uv_overlay) { + pd->edit_uv_edges_grp = DRW_shgroup_create(sh, psl->edit_uv_edges_ps); + DRW_shgroup_uniform_block(pd->edit_uv_edges_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_int_copy(pd->edit_uv_edges_grp, "lineStyle", pd->edit_uv.line_style); + DRW_shgroup_uniform_float_copy(pd->edit_uv_edges_grp, "alpha", pd->edit_uv.uv_opacity); + DRW_shgroup_uniform_float( + pd->edit_uv_edges_grp, "dashLength", &pd->edit_uv.dash_length, 1); + DRW_shgroup_uniform_bool( + pd->edit_uv_edges_grp, "doSmoothWire", &pd->edit_uv.do_smooth_wire, 1); + } + } + } + + if (pd->edit_uv.do_uv_overlay) { + /* uv verts */ + { + DRW_PASS_CREATE(psl->edit_uv_verts_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND_ALPHA); + GPUShader *sh = OVERLAY_shader_edit_uv_verts_get(); + pd->edit_uv_verts_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps); + + const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE); + + DRW_shgroup_uniform_block(pd->edit_uv_verts_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float_copy( + pd->edit_uv_verts_grp, "pointSize", (point_size + 1.5f) * M_SQRT2); + DRW_shgroup_uniform_float_copy(pd->edit_uv_verts_grp, "outlineWidth", 0.75f); + } + + /* uv faces */ + if (pd->edit_uv.do_faces) { + DRW_PASS_CREATE(psl->edit_uv_faces_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA); + GPUShader *sh = OVERLAY_shader_edit_uv_face_get(); + pd->edit_uv_faces_grp = DRW_shgroup_create(sh, psl->edit_uv_faces_ps); + DRW_shgroup_uniform_block(pd->edit_uv_faces_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float(pd->edit_uv_faces_grp, "uvOpacity", &pd->edit_uv.uv_opacity, 1); + } + + /* uv face dots */ + if (pd->edit_uv.do_face_dots) { + const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE); + GPUShader *sh = OVERLAY_shader_edit_uv_face_dots_get(); + pd->edit_uv_face_dots_grp = DRW_shgroup_create(sh, psl->edit_uv_verts_ps); + DRW_shgroup_uniform_block(pd->edit_uv_face_dots_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float_copy(pd->edit_uv_face_dots_grp, "pointSize", point_size); + } + } + + /* uv stretching */ + if (pd->edit_uv.do_uv_stretching_overlay) { + DRW_PASS_CREATE(psl->edit_uv_stretching_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA); + if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) { + GPUShader *sh = OVERLAY_shader_edit_uv_stretching_angle_get(); + pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps); + DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_vec2_copy(pd->edit_uv_stretching_grp, "aspect", pd->edit_uv.aspect); + } + else /* SI_UVDT_STRETCH_AREA */ { + GPUShader *sh = OVERLAY_shader_edit_uv_stretching_area_get(); + pd->edit_uv_stretching_grp = DRW_shgroup_create(sh, psl->edit_uv_stretching_ps); + DRW_shgroup_uniform_block(pd->edit_uv_stretching_grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float( + pd->edit_uv_stretching_grp, "totalAreaRatio", &pd->edit_uv.total_area_ratio, 1); + DRW_shgroup_uniform_float( + pd->edit_uv_stretching_grp, "totalAreaRatioInv", &pd->edit_uv.total_area_ratio_inv, 1); + } + } + + if (pd->edit_uv.do_tiled_image_overlay) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + Image *image = sima->image; + GPUBatch *geom = DRW_cache_quad_wires_get(); + float obmat[4][4]; + unit_m4(obmat); + + DRW_PASS_CREATE(psl->edit_uv_tiled_image_borders_ps, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS); + GPUShader *sh = OVERLAY_shader_edit_uv_tiled_image_borders_get(); + + float theme_color[4], selected_color[4]; + UI_GetThemeColorShade4fv(TH_BACK, 60, theme_color); + UI_GetThemeColor4fv(TH_FACE_SELECT, selected_color); + srgb_to_linearrgb_v4(theme_color, theme_color); + srgb_to_linearrgb_v4(selected_color, selected_color); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps); + DRW_shgroup_uniform_vec4_copy(grp, "color", theme_color); + DRW_shgroup_uniform_vec3_copy(grp, "offset", (float[3]){0.0f, 0.0f, 0.0f}); + + LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) { + const int tile_x = ((tile->tile_number - 1001) % 10); + const int tile_y = ((tile->tile_number - 1001) / 10); + obmat[3][1] = (float)tile_y; + obmat[3][0] = (float)tile_x; + DRW_shgroup_call_obmat(grp, geom, obmat); + } + + /* Active tile border */ + ImageTile *active_tile = BLI_findlink(&image->tiles, image->active_tile_index); + obmat[3][0] = (float)((active_tile->tile_number - 1001) % 10); + obmat[3][1] = (float)((active_tile->tile_number - 1001) / 10); + grp = DRW_shgroup_create(sh, psl->edit_uv_tiled_image_borders_ps); + DRW_shgroup_uniform_vec4_copy(grp, "color", selected_color); + DRW_shgroup_call_obmat(grp, geom, obmat); + + struct DRWTextStore *dt = DRW_text_cache_ensure(); + uchar color[4]; + /* Color Management: Exception here as texts are drawn in sRGB space directly. */ + UI_GetThemeColorShade4ubv(TH_BACK, 60, color); + char text[16]; + LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) { + BLI_snprintf(text, 5, "%d", tile->tile_number); + float tile_location[3] = { + ((tile->tile_number - 1001) % 10), ((tile->tile_number - 1001) / 10), 0.0f}; + DRW_text_cache_add(dt, + tile_location, + text, + strlen(text), + 10, + 10, + DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII, + color); + } + } +} + +void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + GPUBatch *geom; + const bool is_edit_object = DRW_object_is_in_edit_mode(ob); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const bool draw_shadows = (draw_ctx->object_mode != OB_MODE_OBJECT) && + (ob->mode == draw_ctx->object_mode); + if (is_edit_object) { + if (pd->edit_uv.do_uv_overlay) { + geom = DRW_mesh_batch_cache_get_edituv_edges(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_edges_grp, geom, NULL); + } + geom = DRW_mesh_batch_cache_get_edituv_verts(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_verts_grp, geom, NULL); + } + if (pd->edit_uv.do_faces) { + geom = DRW_mesh_batch_cache_get_edituv_faces(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_faces_grp, geom, NULL); + } + } + if (pd->edit_uv.do_face_dots) { + geom = DRW_mesh_batch_cache_get_edituv_facedots(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_face_dots_grp, geom, NULL); + } + } + } + + if (pd->edit_uv.do_uv_stretching_overlay) { + Mesh *me = ob->data; + + if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) { + geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(me); + } + else /* SI_UVDT_STRETCH_AREA */ { + OVERLAY_StretchingAreaTotals *totals = MEM_mallocN(sizeof(OVERLAY_StretchingAreaTotals), + __func__); + BLI_addtail(&pd->edit_uv.totals, totals); + geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_area( + me, &totals->total_area, &totals->total_area_uv); + } + + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_stretching_grp, geom, NULL); + } + } + } + + if (draw_shadows) { + if (pd->edit_uv.do_uv_shadow_overlay) { + geom = DRW_mesh_batch_cache_get_uv_edges(ob->data); + if (geom) { + DRW_shgroup_call_obmat(pd->edit_uv_shadow_edges_grp, geom, NULL); + } + } + } +} + +static void edit_uv_stretching_update_ratios(OVERLAY_Data *vedata) +{ + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_AREA) { + float total_area = 0.0f; + float total_area_uv = 0.0f; + + LISTBASE_FOREACH (OVERLAY_StretchingAreaTotals *, totals, &pd->edit_uv.totals) { + total_area += *totals->total_area; + total_area_uv += *totals->total_area_uv; + } + + if (total_area > FLT_EPSILON && total_area_uv > FLT_EPSILON) { + pd->edit_uv.total_area_ratio = total_area / total_area_uv; + pd->edit_uv.total_area_ratio_inv = total_area_uv / total_area; + } + } + BLI_freelistN(&pd->edit_uv.totals); +} + +void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + + if (pd->edit_uv.do_tiled_image_overlay) { + DRW_draw_pass(psl->edit_uv_tiled_image_borders_ps); + } + + if (pd->edit_uv.do_uv_stretching_overlay) { + edit_uv_stretching_update_ratios(vedata); + DRW_draw_pass(psl->edit_uv_stretching_ps); + } + if (pd->edit_uv.do_uv_overlay) { + if (pd->edit_uv.do_faces) { + DRW_draw_pass(psl->edit_uv_faces_ps); + } + DRW_draw_pass(psl->edit_uv_edges_ps); + + DRW_draw_pass(psl->edit_uv_verts_ps); + } + else if (pd->edit_uv.do_uv_shadow_overlay) { + DRW_draw_pass(psl->edit_uv_edges_ps); + } +} + +/* \{ */ diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index 1312408498a..9cdd371ec4e 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -29,9 +29,13 @@ #include "ED_view3d.h" +#include "UI_interface.h" + #include "BKE_object.h" #include "BKE_paint.h" +#include "DNA_space_types.h" + #include "overlay_engine.h" #include "overlay_private.h" @@ -48,6 +52,10 @@ static void OVERLAY_engine_init(void *vedata) const View3D *v3d = draw_ctx->v3d; const Scene *scene = draw_ctx->scene; const ToolSettings *ts = scene->toolsettings; + const SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + BLI_assert(v3d || sima); + + OVERLAY_shader_library_ensure(); if (!stl->pd) { /* Alloc transient pointers */ @@ -55,6 +63,14 @@ static void OVERLAY_engine_init(void *vedata) } OVERLAY_PrivateData *pd = stl->pd; + pd->is_image_editor = sima != NULL; + + if (pd->is_image_editor) { + pd->clipping_state = 0; + OVERLAY_grid_init(data); + OVERLAY_edit_uv_init(data); + return; + } pd->hide_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) != 0; pd->ctx_mode = CTX_data_mode_enum_ex( @@ -122,6 +138,13 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_StorageList *stl = data->stl; OVERLAY_PrivateData *pd = stl->pd; + if (pd->is_image_editor) { + OVERLAY_background_cache_init(vedata); + OVERLAY_grid_cache_init(vedata); + OVERLAY_edit_uv_cache_init(vedata); + return; + } + switch (pd->ctx_mode) { case CTX_MODE_EDIT_MESH: OVERLAY_edit_mesh_cache_init(vedata); @@ -240,6 +263,14 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) { OVERLAY_Data *data = vedata; OVERLAY_PrivateData *pd = data->stl->pd; + + if (pd->is_image_editor) { + if (ob->type == OB_MESH) { + OVERLAY_edit_uv_cache_populate(vedata, ob); + } + return; + } + const DRWContextState *draw_ctx = DRW_context_state_get(); const bool is_select = DRW_state_is_select(); const bool renderable = DRW_object_is_renderable(ob); @@ -414,6 +445,12 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) static void OVERLAY_cache_finish(void *vedata) { + OVERLAY_Data *data = vedata; + OVERLAY_PrivateData *pd = data->stl->pd; + if (pd->is_image_editor) { + return; + } + /* TODO(fclem) Only do this when really needed. */ { /* HACK we allocate the in front depth here to avoid the overhead when if is not needed. */ @@ -445,6 +482,16 @@ static void OVERLAY_draw_scene(void *vedata) GPU_framebuffer_clear_color(dfbl->overlay_only_fb, clear_col); } + if (pd->is_image_editor) { + OVERLAY_background_draw(data); + OVERLAY_grid_draw(data); + if (DRW_state_is_fbo()) { + GPU_framebuffer_bind(dfbl->overlay_fb); + } + OVERLAY_edit_uv_draw(data); + return; + } + OVERLAY_image_background_draw(vedata); OVERLAY_background_draw(vedata); diff --git a/source/blender/draw/engines/overlay/overlay_grid.c b/source/blender/draw/engines/overlay/overlay_grid.c index e3079870d8f..7445dfc2e3d 100644 --- a/source/blender/draw/engines/overlay/overlay_grid.c +++ b/source/blender/draw/engines/overlay/overlay_grid.c @@ -26,6 +26,7 @@ #include "DEG_depsgraph_query.h" +#include "ED_image.h" #include "ED_view3d.h" #include "overlay_private.h" @@ -42,14 +43,31 @@ enum { CLIP_ZNEG = (1 << 8), GRID_BACK = (1 << 9), GRID_CAMERA = (1 << 10), + PLANE_IMAGE = (1 << 11), }; void OVERLAY_grid_init(OVERLAY_Data *vedata) { OVERLAY_PrivateData *pd = vedata->stl->pd; OVERLAY_ShadingData *shd = &pd->shdata; - const DRWContextState *draw_ctx = DRW_context_state_get(); + + shd->grid_flag = 0; + shd->zneg_flag = 0; + shd->zpos_flag = 0; + shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; + + if (pd->is_image_editor) { + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + shd->grid_flag = ED_space_image_has_buffer(sima) ? 0 : PLANE_IMAGE | SHOW_GRID; + shd->grid_distance = 1.0f; + shd->grid_mesh_size = 1.0f; + for (int step = 0; step < 8; step++) { + shd->grid_steps[step] = powf(4, step) * (1.0f / 16.0f); + } + return; + } + View3D *v3d = draw_ctx->v3d; Scene *scene = draw_ctx->scene; RegionView3D *rv3d = draw_ctx->rv3d; @@ -60,10 +78,6 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata) const bool show_floor = (pd->v3d_gridflag & V3D_SHOW_FLOOR) != 0; const bool show_ortho_grid = (pd->v3d_gridflag & V3D_SHOW_ORTHO_GRID) != 0; - shd->grid_flag = 0; - shd->zneg_flag = 0; - shd->zpos_flag = 0; - if (pd->hide_overlays || !(pd->v3d_gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z | V3D_SHOW_FLOOR | V3D_SHOW_ORTHO_GRID))) { return; @@ -163,14 +177,16 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata) } shd->grid_distance = dist / 2.0f; - shd->grid_line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; ED_view3d_grid_steps(scene, v3d, rv3d, shd->grid_steps); } void OVERLAY_grid_cache_init(OVERLAY_Data *vedata) { - OVERLAY_ShadingData *shd = &vedata->stl->pd->shdata; + OVERLAY_StorageList *stl = vedata->stl; + OVERLAY_PrivateData *pd = stl->pd; + OVERLAY_ShadingData *shd = &pd->shdata; + OVERLAY_PassList *psl = vedata->psl; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -182,12 +198,29 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA; DRW_PASS_CREATE(psl->grid_ps, state); - - GPUShader *sh = OVERLAY_shader_grid(); + DRWShadingGroup *grp; + GPUShader *sh; struct GPUBatch *geom = DRW_cache_grid_get(); + if (pd->is_image_editor) { + /* add quad background */ + sh = OVERLAY_shader_grid_image(); + grp = DRW_shgroup_create(sh, psl->grid_ps); + DRW_shgroup_call(grp, DRW_cache_quad_get(), NULL); + float color_back[4]; + interp_v4_v4v4(color_back, G_draw.block.colorBackground, G_draw.block.colorGrid, 0.5); + DRW_shgroup_uniform_vec4_copy(grp, "color", color_back); + + /* add wire border */ + grp = DRW_shgroup_create(sh, psl->grid_ps); + DRW_shgroup_call(grp, DRW_cache_quad_wires_get(), NULL); + DRW_shgroup_uniform_vec4_copy(grp, "color", G_draw.block.colorGrid); + } + + sh = OVERLAY_shader_grid(); + /* Create 3 quads to render ordered transparency Z axis */ - DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->grid_ps); + grp = DRW_shgroup_create(sh, psl->grid_ps); DRW_shgroup_uniform_int(grp, "gridFlag", &shd->zneg_flag, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", shd->zplane_axes, 1); DRW_shgroup_uniform_float(grp, "gridDistance", &shd->grid_distance, 1); diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index c9d29af91e6..c8b29c6bbbb 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -34,6 +34,9 @@ extern "C" { # define USE_GEOM_SHADER_WORKAROUND 0 #endif +/* Needed for eSpaceImage_UVDT_Stretch */ +#include "DNA_space_types.h" + typedef struct OVERLAY_FramebufferList { struct GPUFrameBuffer *overlay_default_fb; struct GPUFrameBuffer *overlay_line_fb; @@ -55,6 +58,14 @@ typedef struct OVERLAY_TextureList { #define NOT_IN_FRONT 0 #define IN_FRONT 1 +typedef enum OVERLAY_UVLineStyle { + OVERLAY_UV_LINE_STYLE_OUTLINE = 0, + OVERLAY_UV_LINE_STYLE_DASH = 1, + OVERLAY_UV_LINE_STYLE_BLACK = 2, + OVERLAY_UV_LINE_STYLE_WHITE = 3, + OVERLAY_UV_LINE_STYLE_SHADOW = 4, +} OVERLAY_UVLineStyle; + typedef struct OVERLAY_PassList { DRWPass *antialiasing_ps; DRWPass *armature_ps[2]; @@ -78,6 +89,11 @@ typedef struct OVERLAY_PassList { DRWPass *edit_text_overlay_ps; DRWPass *edit_text_darken_ps; DRWPass *edit_text_wire_ps[2]; + DRWPass *edit_uv_edges_ps; + DRWPass *edit_uv_verts_ps; + DRWPass *edit_uv_faces_ps; + DRWPass *edit_uv_stretching_ps; + DRWPass *edit_uv_tiled_image_borders_ps; DRWPass *extra_ps[2]; DRWPass *extra_blend_ps; DRWPass *extra_centers_ps; @@ -244,6 +260,12 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *edit_particle_point_grp; DRWShadingGroup *edit_text_overlay_grp; DRWShadingGroup *edit_text_wire_grp[2]; + DRWShadingGroup *edit_uv_verts_grp; + DRWShadingGroup *edit_uv_edges_grp; + DRWShadingGroup *edit_uv_shadow_edges_grp; + DRWShadingGroup *edit_uv_faces_grp; + DRWShadingGroup *edit_uv_face_dots_grp; + DRWShadingGroup *edit_uv_stretching_grp; DRWShadingGroup *extra_grid_grp; DRWShadingGroup *facing_grp[2]; DRWShadingGroup *motion_path_lines_grp; @@ -286,6 +308,7 @@ typedef struct OVERLAY_PrivateData { View3DOverlay overlay; enum eContextObjectMode ctx_mode; + bool is_image_editor; bool clear_in_front; bool use_in_front; bool wireframe_mode; @@ -325,6 +348,29 @@ typedef struct OVERLAY_PrivateData { int select_mode; } edit_particle; struct { + bool do_uv_overlay; + bool do_uv_shadow_overlay; + bool do_uv_stretching_overlay; + bool do_tiled_image_overlay; + + bool do_faces; + bool do_face_dots; + + float uv_opacity; + /* edge drawing */ + OVERLAY_UVLineStyle line_style; + float dash_length; + int do_smooth_wire; + + /* stretching overlay */ + float aspect[2]; + eSpaceImage_UVDT_Stretch draw_type; + ListBase totals; + float total_area_ratio; + float total_area_ratio_inv; + + } edit_uv; + struct { bool transparent; bool show_relations; bool do_pose_xray; @@ -472,6 +518,11 @@ void OVERLAY_edit_particle_cache_init(OVERLAY_Data *vedata); void OVERLAY_edit_particle_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_edit_particle_draw(OVERLAY_Data *vedata); +void OVERLAY_edit_uv_init(OVERLAY_Data *vedata); +void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata); +void OVERLAY_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob); +void OVERLAY_edit_uv_draw(OVERLAY_Data *vedata); + void OVERLAY_extra_cache_init(OVERLAY_Data *vedata); void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_extra_blend_draw(OVERLAY_Data *vedata); @@ -570,6 +621,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, void OVERLAY_wireframe_draw(OVERLAY_Data *vedata); void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *vedata); +void OVERLAY_shader_library_ensure(void); GPUShader *OVERLAY_shader_antialiasing(void); GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire(void); GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid(void); @@ -599,6 +651,13 @@ GPUShader *OVERLAY_shader_edit_mesh_skin_root(void); GPUShader *OVERLAY_shader_edit_mesh_vert(void); GPUShader *OVERLAY_shader_edit_particle_strand(void); GPUShader *OVERLAY_shader_edit_particle_point(void); +GPUShader *OVERLAY_shader_edit_uv_edges_get(void); +GPUShader *OVERLAY_shader_edit_uv_face_get(void); +GPUShader *OVERLAY_shader_edit_uv_face_dots_get(void); +GPUShader *OVERLAY_shader_edit_uv_verts_get(void); +GPUShader *OVERLAY_shader_edit_uv_stretching_area_get(void); +GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get(void); +GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get(void); GPUShader *OVERLAY_shader_extra(bool is_select); GPUShader *OVERLAY_shader_extra_groundline(void); GPUShader *OVERLAY_shader_extra_wire(bool use_object, bool is_select); @@ -607,6 +666,7 @@ GPUShader *OVERLAY_shader_extra_point(void); GPUShader *OVERLAY_shader_facing(void); GPUShader *OVERLAY_shader_gpencil_canvas(void); GPUShader *OVERLAY_shader_grid(void); +GPUShader *OVERLAY_shader_grid_image(void); GPUShader *OVERLAY_shader_image(void); GPUShader *OVERLAY_shader_motion_path_line(void); GPUShader *OVERLAY_shader_motion_path_vert(void); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index e3cb052890b..4530d6e8adf 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -70,6 +70,15 @@ extern char datatoc_edit_mesh_analysis_vert_glsl[]; extern char datatoc_edit_mesh_analysis_frag_glsl[]; extern char datatoc_edit_particle_strand_vert_glsl[]; extern char datatoc_edit_particle_point_vert_glsl[]; +extern char datatoc_edit_uv_verts_vert_glsl[]; +extern char datatoc_edit_uv_verts_frag_glsl[]; +extern char datatoc_edit_uv_edges_vert_glsl[]; +extern char datatoc_edit_uv_edges_geom_glsl[]; +extern char datatoc_edit_uv_edges_frag_glsl[]; +extern char datatoc_edit_uv_faces_vert_glsl[]; +extern char datatoc_edit_uv_face_dots_vert_glsl[]; +extern char datatoc_edit_uv_stretching_vert_glsl[]; +extern char datatoc_edit_uv_tiled_image_borders_vert_glsl[]; extern char datatoc_extra_frag_glsl[]; extern char datatoc_extra_vert_glsl[]; extern char datatoc_extra_groundline_vert_glsl[]; @@ -113,6 +122,7 @@ extern char datatoc_xray_fade_frag_glsl[]; extern char datatoc_gpu_shader_depth_only_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; +extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[]; @@ -120,6 +130,7 @@ extern char datatoc_gpu_shader_common_obinfos_lib_glsl[]; extern char datatoc_gpencil_common_lib_glsl[]; +extern char datatoc_common_overlay_lib_glsl[]; extern char datatoc_common_colormanagement_lib_glsl[]; extern char datatoc_common_fullscreen_vert_glsl[]; extern char datatoc_common_fxaa_lib_glsl[]; @@ -164,6 +175,13 @@ typedef struct OVERLAY_Shaders { GPUShader *edit_mesh_analysis; GPUShader *edit_particle_strand; GPUShader *edit_particle_point; + GPUShader *edit_uv_verts; + GPUShader *edit_uv_faces; + GPUShader *edit_uv_edges; + GPUShader *edit_uv_face_dots; + GPUShader *edit_uv_stretching_angle; + GPUShader *edit_uv_stretching_area; + GPUShader *edit_uv_tiled_image_borders; GPUShader *extra; GPUShader *extra_select; GPUShader *extra_groundline; @@ -175,6 +193,7 @@ typedef struct OVERLAY_Shaders { GPUShader *facing; GPUShader *gpencil_canvas; GPUShader *grid; + GPUShader *grid_image; GPUShader *image; GPUShader *motion_path_line; GPUShader *motion_path_vert; @@ -203,8 +222,20 @@ typedef struct OVERLAY_Shaders { static struct { OVERLAY_Shaders sh_data[GPU_SHADER_CFG_LEN]; + DRWShaderLibrary *lib; } e_data = {{{NULL}}}; +void OVERLAY_shader_library_ensure(void) +{ + if (e_data.lib == NULL) { + e_data.lib = DRW_shader_library_create(); + /* NOTE: Theses needs to be ordered by dependencies. */ + DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_overlay_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); + } +} + GPUShader *OVERLAY_shader_antialiasing(void) { OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; @@ -1012,6 +1043,20 @@ GPUShader *OVERLAY_shader_grid(void) return sh_data->grid; } +GPUShader *OVERLAY_shader_grid_image(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->grid_image) { + sh_data->grid_image = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_tiled_image_borders_vert_glsl, + NULL, + datatoc_gpu_shader_uniform_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->grid_image; +} + GPUShader *OVERLAY_shader_image(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -1449,6 +1494,108 @@ GPUShader *OVERLAY_shader_xray_fade(void) return sh_data->xray_fade; } +/* -------------------------------------------------------------------- */ +/** \name Edit UV shaders + * \{ */ + +GPUShader *OVERLAY_shader_edit_uv_edges_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_edges) { + sh_data->edit_uv_edges = DRW_shader_create_with_shaderlib(datatoc_edit_uv_edges_vert_glsl, + datatoc_edit_uv_edges_geom_glsl, + datatoc_edit_uv_edges_frag_glsl, + e_data.lib, + NULL); + } + return sh_data->edit_uv_edges; +} + +GPUShader *OVERLAY_shader_edit_uv_face_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_faces) { + sh_data->edit_uv_faces = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_faces_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->edit_uv_faces; +} + +GPUShader *OVERLAY_shader_edit_uv_face_dots_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_face_dots) { + sh_data->edit_uv_face_dots = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_face_dots_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->edit_uv_face_dots; +} + +GPUShader *OVERLAY_shader_edit_uv_verts_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_verts) { + sh_data->edit_uv_verts = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_verts_vert_glsl, NULL, datatoc_edit_uv_verts_frag_glsl, e_data.lib, NULL); + } + + return sh_data->edit_uv_verts; +} + +GPUShader *OVERLAY_shader_edit_uv_stretching_area_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_stretching_area) { + sh_data->edit_uv_stretching_area = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_stretching_vert_glsl, + NULL, + datatoc_gpu_shader_2D_smooth_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + + return sh_data->edit_uv_stretching_area; +} + +GPUShader *OVERLAY_shader_edit_uv_stretching_angle_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_stretching_angle) { + sh_data->edit_uv_stretching_angle = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_stretching_vert_glsl, + NULL, + datatoc_gpu_shader_2D_smooth_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n#define STRETCH_ANGLE\n"); + } + + return sh_data->edit_uv_stretching_angle; +} + +GPUShader *OVERLAY_shader_edit_uv_tiled_image_borders_get(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->edit_uv_tiled_image_borders) { + sh_data->edit_uv_tiled_image_borders = DRW_shader_create_with_shaderlib( + datatoc_edit_uv_tiled_image_borders_vert_glsl, + NULL, + datatoc_gpu_shader_uniform_color_frag_glsl, + e_data.lib, + "#define blender_srgb_to_framebuffer_space(a) a\n"); + } + return sh_data->edit_uv_tiled_image_borders; +} + +/* \} */ + static OVERLAY_InstanceFormats g_formats = {NULL}; OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) @@ -1521,6 +1668,8 @@ OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) void OVERLAY_shader_free(void) { + DRW_SHADER_LIB_FREE_SAFE(e_data.lib); + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { OVERLAY_Shaders *sh_data = &e_data.sh_data[sh_data_index]; GPUShader **sh_data_as_array = (GPUShader **)sh_data; diff --git a/source/blender/draw/engines/overlay/shaders/background_frag.glsl b/source/blender/draw/engines/overlay/shaders/background_frag.glsl index d5aaaf75b79..71bfd2f8e73 100644 --- a/source/blender/draw/engines/overlay/shaders/background_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/background_frag.glsl @@ -13,6 +13,7 @@ out vec4 fragColor; #define BG_GRADIENT 1 #define BG_CHECKER 2 #define BG_RADIAL 3 +#define BG_SOLID_CHECKER 4 #define SQRT2 1.4142135623730950488 /* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ @@ -43,7 +44,11 @@ void main() vec3 col_high; vec3 col_low; - switch (bgType) { + /* BG_SOLID_CHECKER selects BG_SOLID when no pixel has been drawn otherwise use the BG_CHERKER. + */ + int bg_type = bgType == BG_SOLID_CHECKER ? (depth == 1.0 ? BG_SOLID : BG_CHECKER) : bgType; + + switch (bg_type) { case BG_SOLID: bg_col = colorBackground.rgb; break; diff --git a/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl b/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl new file mode 100644 index 00000000000..65aeb81a4ef --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/common_overlay_lib.glsl @@ -0,0 +1,5 @@ +#define OVERLAY_UV_LINE_STYLE_OUTLINE 0 +#define OVERLAY_UV_LINE_STYLE_DASH 1 +#define OVERLAY_UV_LINE_STYLE_BLACK 2 +#define OVERLAY_UV_LINE_STYLE_WHITE 3 +#define OVERLAY_UV_LINE_STYLE_SHADOW 4 diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl new file mode 100644 index 00000000000..b81fdd2c712 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_frag.glsl @@ -0,0 +1,77 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_overlay_lib.glsl) + +uniform int lineStyle; +uniform bool doSmoothWire; +uniform float alpha; +uniform float dashLength; + +in float selectionFac_f; +noperspective in float edgeCoord_f; +noperspective in vec2 stipplePos_f; +flat in vec2 stippleStart_f; + +layout(location = 0) out vec4 fragColor; + +#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */ + +/** + * We want to know how much a pixel is covered by a line. + * We replace the square pixel with acircle of the same area and try to find the intersection area. + * The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment + * The formula for the area uses inverse trig function and is quite complexe. Instead, + * we approximate it by using the smoothstep function and a 1.05 factor to the disc radius. + */ +#define DISC_RADIUS (M_1_SQRTPI * 1.05) +#define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS) +#define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS) + +void main() +{ + vec4 inner_color = vec4(vec3(0.0), 1.0); + vec4 outer_color = vec4(0.0); + + vec2 dd = fwidth(stipplePos_f); + float line_distance = distance(stipplePos_f, stippleStart_f) / max(dd.x, dd.y); + + if (lineStyle == OVERLAY_UV_LINE_STYLE_OUTLINE) { + inner_color = mix(colorWireEdit, colorEdgeSelect, selectionFac_f); + outer_color = vec4(vec3(0.0), 1.0); + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_DASH) { + if (fract(line_distance / dashLength) < 0.5) { + inner_color = mix(vec4(1.0), colorEdgeSelect, selectionFac_f); + } + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_BLACK) { + vec4 base_color = vec4(vec3(0.0), 1.0); + inner_color = mix(base_color, colorEdgeSelect, selectionFac_f); + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_WHITE) { + vec4 base_color = vec4(1.0); + inner_color = mix(base_color, colorEdgeSelect, selectionFac_f); + } + else if (lineStyle == OVERLAY_UV_LINE_STYLE_SHADOW) { + inner_color = colorUVShadow; + } + + float dist = abs(edgeCoord_f) - max(sizeEdge - 0.5, 0.0); + float dist_outer = dist - max(sizeEdge, 1.0); + float mix_w; + float mix_w_outer; + + if (doSmoothWire) { + mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist); + mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer); + } + else { + mix_w = step(0.5, dist); + mix_w_outer = step(0.5, dist_outer); + } + + vec4 final_color = mix(outer_color, inner_color, 1.0 - mix_w * outer_color.a); + final_color.a *= 1.0 - (outer_color.a > 0.0 ? mix_w_outer : mix_w); + final_color.a *= alpha; + + fragColor = final_color; +}
\ No newline at end of file diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl new file mode 100644 index 00000000000..4f8d553a220 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_geom.glsl @@ -0,0 +1,63 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_overlay_lib.glsl) + +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; + +in float selectionFac[2]; +flat in vec2 stippleStart[2]; +noperspective in vec2 stipplePos[2]; + +uniform int lineStyle; +uniform bool doSmoothWire; + +out float selectionFac_f; +noperspective out float edgeCoord_f; +noperspective out vec2 stipplePos_f; +flat out vec2 stippleStart_f; + +void do_vertex( + vec4 pos, float selection_fac, vec2 stipple_start, vec2 stipple_pos, float coord, vec2 offset) +{ + selectionFac_f = selection_fac; + edgeCoord_f = coord; + stippleStart_f = stipple_start; + stipplePos_f = stipple_pos; + + gl_Position = pos; + /* Multiply offset by 2 because gl_Position range is [-1..1]. */ + gl_Position.xy += offset * 2.0; + EmitVertex(); +} + +void main() +{ + vec2 ss_pos[2]; + vec4 pos0 = gl_in[0].gl_Position; + vec4 pos1 = gl_in[1].gl_Position; + ss_pos[0] = pos0.xy / pos0.w; + ss_pos[1] = pos1.xy / pos1.w; + + float half_size = sizeEdge; + /* Enlarge edge for outline drawing. */ + /* Factor of 3.0 out of nowhere! Seems to fix issues with float imprecision. */ + half_size += (lineStyle == OVERLAY_UV_LINE_STYLE_OUTLINE) ? + max(sizeEdge * (doSmoothWire ? 1.0 : 3.0), 1.0) : + 0.0; + /* Add 1 px for AA */ + if (doSmoothWire) { + half_size += 0.5; + } + + vec2 line = ss_pos[0] - ss_pos[1]; + vec2 line_dir = normalize(line); + vec2 line_perp = vec2(-line_dir.y, line_dir.x); + vec2 edge_ofs = line_perp * sizeViewportInv * ceil(half_size); + + do_vertex(pos0, selectionFac[0], stippleStart[0], stipplePos[0], half_size, edge_ofs.xy); + do_vertex(pos0, selectionFac[0], stippleStart[0], stipplePos[0], -half_size, -edge_ofs.xy); + do_vertex(pos1, selectionFac[1], stippleStart[1], stipplePos[1], half_size, edge_ofs.xy); + do_vertex(pos1, selectionFac[1], stippleStart[1], stipplePos[1], -half_size, -edge_ofs.xy); + + EndPrimitive(); +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl new file mode 100644 index 00000000000..4661cf248e6 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_edges_vert.glsl @@ -0,0 +1,32 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +in vec3 pos; +in vec2 u; +in int flag; + +out float selectionFac; +noperspective out vec2 stipplePos; +flat out vec2 stippleStart; + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + /* Snap vertices to the pixel grid to reduce artifacts. */ + vec2 half_viewport_res = sizeViewport.xy * 0.5; + vec2 half_pixel_offset = sizeViewportInv * 0.5; + gl_Position.xy = floor(gl_Position.xy * half_viewport_res) / half_viewport_res + + half_pixel_offset; + + bool is_select = (flag & VERT_UV_SELECT) != 0; + selectionFac = is_select ? 1.0 : 0.0; + /* Move selected edges to the top + * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4 + * actual pixels are at 0.75, 1.0 is used for the background. */ + float depth = is_select ? 0.25 : 0.35; + gl_Position.z = depth; + + /* Avoid precision loss. */ + stippleStart = stipplePos = 500.0 + 500.0 * (gl_Position.xy / gl_Position.w); +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl new file mode 100644 index 00000000000..61152c83a29 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_face_dots_vert.glsl @@ -0,0 +1,18 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform float pointSize; + +in vec2 u; +in int flag; + +flat out vec4 finalColor; + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + + finalColor = ((flag & FACE_UV_SELECT) != 0) ? colorVertexSelect : vec4(colorWire.rgb, 1.0); + gl_PointSize = pointSize; +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl new file mode 100644 index 00000000000..cf1018ae5f9 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_faces_vert.glsl @@ -0,0 +1,22 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform float uvOpacity; + +in vec2 u; +in int flag; + +flat out vec4 finalColor; + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + + bool is_selected = (flag & FACE_UV_SELECT) != 0; + bool is_active = (flag & FACE_UV_ACTIVE) != 0; + + finalColor = (is_selected) ? colorFaceSelect : colorFace; + finalColor = (is_active) ? colorEditMeshActive : finalColor; + finalColor.a *= uvOpacity; +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl new file mode 100644 index 00000000000..ce97f1e27ac --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_stretching_vert.glsl @@ -0,0 +1,98 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform vec2 aspect; +in vec2 pos; + +#ifdef STRETCH_ANGLE +in vec2 uv_angles; +in float angle; + +#else +in float ratio; +uniform float totalAreaRatio; +uniform float totalAreaRatioInv; + +#endif + +noperspective out vec4 finalColor; + +vec3 weight_to_rgb(float weight) +{ + vec3 r_rgb; + float blend = ((weight / 2.0) + 0.5); + + if (weight <= 0.25) { /* blue->cyan */ + r_rgb[0] = 0.0; + r_rgb[1] = blend * weight * 4.0; + r_rgb[2] = blend; + } + else if (weight <= 0.50) { /* cyan->green */ + r_rgb[0] = 0.0; + r_rgb[1] = blend; + r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0)); + } + else if (weight <= 0.75) { /* green->yellow */ + r_rgb[0] = blend * ((weight - 0.50) * 4.0); + r_rgb[1] = blend; + r_rgb[2] = 0.0; + } + else if (weight <= 1.0) { /* yellow->red */ + r_rgb[0] = blend; + r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0)); + r_rgb[2] = 0.0; + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb[0] = 1.0; + r_rgb[1] = 0.0; + r_rgb[2] = 1.0; + } + + return r_rgb; +} + +#define M_PI 3.1415926535897932 + +vec2 angle_to_v2(float angle) +{ + return vec2(cos(angle), sin(angle)); +} + +/* Adapted from BLI_math_vector.h */ +float angle_normalized_v2v2(vec2 v1, vec2 v2) +{ + v1 = normalize(v1 * aspect); + v2 = normalize(v2 * aspect); + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ + bool q = (dot(v1, v2) >= 0.0); + vec2 v = (q) ? (v1 - v2) : (v1 + v2); + float a = 2.0 * asin(length(v) / 2.0); + return (q) ? a : M_PI - a; +} + +float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_tot_ratio) +{ + ratio *= (ratio > 0.0f) ? tot_ratio : -inv_tot_ratio; + return (ratio > 1.0f) ? (1.0f / ratio) : ratio; +} + +void main() +{ + vec3 world_pos = point_object_to_world(vec3(pos, 0.0)); + gl_Position = point_world_to_ndc(world_pos); + +#ifdef STRETCH_ANGLE + vec2 v1 = angle_to_v2(uv_angles.x * M_PI); + vec2 v2 = angle_to_v2(uv_angles.y * M_PI); + float uv_angle = angle_normalized_v2v2(v1, v2) / M_PI; + float stretch = 1.0 - abs(uv_angle - angle); + stretch = stretch; + stretch = 1.0 - stretch * stretch; +#else + float stretch = 1.0 - area_ratio_to_stretch(ratio, totalAreaRatio, totalAreaRatioInv); + +#endif + + finalColor = vec4(weight_to_rgb(stretch), 1.0); +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl new file mode 100644 index 00000000000..c762858a910 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_tiled_image_borders_vert.glsl @@ -0,0 +1,12 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +in vec3 pos; + +void main() +{ + /* `pos` contains the coordinates of a quad (-1..1). but we need the coordinates of an image + * plane (0..1) */ + vec3 image_pos = pos * 0.5 + 0.5; + vec4 position = point_object_to_ndc(image_pos); + gl_Position = position; +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl new file mode 100644 index 00000000000..11694de38ca --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_frag.glsl @@ -0,0 +1,33 @@ + +uniform vec4 outlineColor; + +in vec4 radii; +in vec4 fillColor; +out vec4 fragColor; + +void main() +{ + float dist = length(gl_PointCoord - vec2(0.5)); + + // transparent outside of point + // --- 0 --- + // smooth transition + // --- 1 --- + // pure outline color + // --- 2 --- + // smooth transition + // --- 3 --- + // pure fill color + // ... + // dist = 0 at center of point + + float midStroke = 0.5 * (radii[1] + radii[2]); + + if (dist > midStroke) { + fragColor.rgb = outlineColor.rgb; + fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); + } + else { + fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist)); + } +} diff --git a/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl new file mode 100644 index 00000000000..327a35ce6b2 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/edit_uv_verts_vert.glsl @@ -0,0 +1,44 @@ +#pragma BLENDER_REQUIRE(common_globals_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform float pointSize; +uniform float outlineWidth; + +in vec2 u; +in int flag; + +out vec4 fillColor; +out vec4 outlineColor; +out vec4 radii; + +/* TODO Theme? */ +const vec4 pinned_col = vec4(1.0, 0.0, 0.0, 1.0); + +void main() +{ + bool is_selected = (flag & (VERT_UV_SELECT | FACE_UV_SELECT)) != 0; + bool is_pinned = (flag & VERT_UV_PINNED) != 0; + vec4 deselect_col = (is_pinned) ? pinned_col : vec4(colorWire.rgb, 1.0); + fillColor = (is_selected) ? colorVertexSelect : deselect_col; + outlineColor = (is_pinned) ? pinned_col : vec4(fillColor.rgb, 0.0); + + vec3 world_pos = point_object_to_world(vec3(u, 0.0)); + /* Move selected vertices to the top + * Vertices are between 0.0 and 0.2, Edges between 0.2 and 0.4 + * actual pixels are at 0.75, 1.0 is used for the background. */ + float depth = is_selected ? 0.05 : 0.15; + gl_Position = vec4(point_world_to_ndc(world_pos).xy, depth, 1.0); + gl_PointSize = pointSize; + + // calculate concentric radii in pixels + float radius = 0.5 * pointSize; + + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - outlineWidth; + radii[3] = radius - outlineWidth - 1.0; + + // convert to PointCoord units + radii /= pointSize; +} diff --git a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl index dd0e771ad93..6df4ead9f2a 100644 --- a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl @@ -12,7 +12,7 @@ uniform int gridFlag; #define PLANE_YZ (1 << 6) #define CLIP_Z_POS (1 << 7) #define CLIP_Z_NEG (1 << 8) - +#define PLANE_IMAGE (1 << 11) in vec3 pos; out vec3 local_pos; @@ -28,9 +28,12 @@ void main() else if ((gridFlag & PLANE_XZ) != 0) { vert_pos = vec3(pos.x, 0.0, pos.y); } - else { + else if ((gridFlag & PLANE_YZ) != 0) { vert_pos = vec3(0.0, pos.x, pos.y); } + else /* PLANE_IMAGE */ { + vert_pos = vec3(pos.xy * 0.5 + 0.5, 0.0); + } local_pos = vert_pos; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index e154a52b32f..30c6f0ad4dc 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -557,6 +557,9 @@ void DRW_shgroup_uniform_ivec4(DRWShadingGroup *shgroup, int arraysize); void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float (*value)[3]); void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float (*value)[4]); +/* Only to be used when image load store is supported (GPU_shader_image_load_store_support()). */ +void DRW_shgroup_uniform_image(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex); +void DRW_shgroup_uniform_image_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex); /* Store value instead of referencing it. */ void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value); void DRW_shgroup_uniform_ivec2_copy(DRWShadingGroup *shgroup, const char *name, const int *value); @@ -736,9 +739,11 @@ bool DRW_state_draw_background(void); /* Avoid too many lookups while drawing */ typedef struct DRWContextState { - struct ARegion *region; /* 'CTX_wm_region(C)' */ - struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */ - struct View3D *v3d; /* 'CTX_wm_view3d(C)' */ + + struct ARegion *region; /* 'CTX_wm_region(C)' */ + struct RegionView3D *rv3d; /* 'CTX_wm_region_view3d(C)' */ + struct View3D *v3d; /* 'CTX_wm_view3d(C)' */ + struct SpaceLink *space_data; /* 'CTX_wm_space_data(C)' */ struct Scene *scene; /* 'CTX_data_scene(C)' */ struct ViewLayer *view_layer; /* 'CTX_data_view_layer(C)' */ diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index ea5421f3965..56f31a69396 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -178,6 +178,9 @@ void DRW_globals_update(void) UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, gb->colorOutline); UI_GetThemeColorShadeAlpha4fv(TH_LIGHT, 0, 255, gb->colorLightNoAlpha); + /* UV colors */ + UI_GetThemeColor4fv(TH_UV_SHADOW, gb->colorUVShadow); + gb->sizePixel = U.pixelsize; gb->sizeObjectCenter = (UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.0f) * U.pixelsize; gb->sizeLightCenter = (UI_GetThemeValuef(TH_OBCENTER_DIA) + 1.5f) * U.pixelsize; @@ -210,7 +213,7 @@ void DRW_globals_update(void) /* TODO more accurate transform. */ srgb_to_linearrgb_v4(color, color); color += 4; - } while (color != gb->UBO_LAST_COLOR); + } while (color <= gb->UBO_LAST_COLOR); } if (G_draw.block_ubo == NULL) { diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 645848e7fe0..e3967678319 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -33,7 +33,7 @@ struct RegionView3D; struct ViewLayer; #define UBO_FIRST_COLOR colorWire -#define UBO_LAST_COLOR colorFaceFront +#define UBO_LAST_COLOR colorUVShadow /* Used as ubo but colors can be directly referenced as well */ /* Keep in sync with: common_globals_lib.glsl (globalsBlock) */ @@ -141,6 +141,8 @@ typedef struct GlobalsUboStorage { float colorFaceBack[4]; float colorFaceFront[4]; + float colorUVShadow[4]; + /* NOTE! Put all color before UBO_LAST_COLOR */ float screenVecs[2][4]; /* padded as vec4 */ float sizeViewport[2], sizeViewportInv[2]; /* packed as vec4 in glsl */ diff --git a/source/blender/draw/intern/draw_fluid.c b/source/blender/draw/intern/draw_fluid.c index af14f11e6e9..809512bd7dd 100644 --- a/source/blender/draw/intern/draw_fluid.c +++ b/source/blender/draw/intern/draw_fluid.c @@ -183,6 +183,10 @@ static GPUTexture *create_volume_texture(const int dim[3], GPUTexture *tex = NULL; int final_dim[3] = {UNPACK3(dim)}; + if (data == NULL) { + return NULL; + } + while (1) { tex = GPU_texture_create_3d("volume", UNPACK3(final_dim), 1, format, NULL); @@ -292,6 +296,10 @@ static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres) data = manta_smoke_get_density(fds->fluid); } + if (data == NULL) { + return NULL; + } + GPUTexture *tex = create_volume_texture(dim, GPU_R8, data); swizzle_texture_channel_single(tex); return tex; diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 9b503e00b36..cc0aa09ed97 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -346,10 +346,10 @@ void DRW_hair_update(void) GPU_framebuffer_read_color(fb, 0, 0, width, height, 4, 0, GPU_DATA_FLOAT, data); /* Upload back to VBO. */ GPU_vertbuf_use(pr_call->vbo); - glBufferSubData(GL_ARRAY_BUFFER, - sizeof(float[4]) * g_tf_id_offset, - sizeof(float[4]) * max_read_px_len, - data); + GPU_vertbuf_update_sub(pr_call->vbo, + sizeof(float[4]) * g_tf_id_offset, + sizeof(float[4]) * max_read_px_len, + data); g_tf_id_offset += max_read_px_len; pr_call->vert_len -= max_read_px_len; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index e6d51bce54e..834505ca349 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -78,6 +78,7 @@ #include "RE_pipeline.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "WM_api.h" #include "wm_window.h" @@ -94,6 +95,7 @@ #include "engines/eevee/eevee_engine.h" #include "engines/external/external_engine.h" #include "engines/gpencil/gpencil_engine.h" +#include "engines/image/image_engine.h" #include "engines/overlay/overlay_engine.h" #include "engines/select/select_engine.h" #include "engines/workbench/workbench_engine.h" @@ -126,6 +128,25 @@ static void drw_state_ensure_not_reused(DRWManager *dst) } #endif +static bool drw_draw_show_annotation(void) +{ + if (DST.draw_ctx.space_data == NULL) { + View3D *v3d = DST.draw_ctx.v3d; + return (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) && + ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0)); + } + + switch (DST.draw_ctx.space_data->spacetype) { + case SPACE_IMAGE: { + SpaceImage *sima = (SpaceImage *)DST.draw_ctx.space_data; + return (sima->flag & SI_SHOW_GPENCIL) != 0; + } + default: + BLI_assert(""); + return false; + } +} + /* -------------------------------------------------------------------- */ /** \name Threading * \{ */ @@ -287,6 +308,7 @@ struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob)) /** \name Color Management * \{ */ +/* TODO(fclem) This should be a render engine callback to determine if we need CM or not. */ static void drw_viewport_colormanagement_set(void) { Scene *scene = DST.draw_ctx.scene; @@ -296,21 +318,43 @@ static void drw_viewport_colormanagement_set(void) ColorManagedViewSettings view_settings; float dither = 0.0f; - /* TODO(fclem) This should be a render engine callback to determine if we need CM or not. */ - bool use_workbench = BKE_scene_uses_blender_workbench(scene); - - bool use_scene_lights = (!v3d || - ((v3d->shading.type == OB_MATERIAL) && - (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS)) || - ((v3d->shading.type == OB_RENDER) && - (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS_RENDER))); - bool use_scene_world = - (!v3d || - ((v3d->shading.type == OB_MATERIAL) && (v3d->shading.flag & V3D_SHADING_SCENE_WORLD)) || - ((v3d->shading.type == OB_RENDER) && (v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER))); - bool use_view_transform = v3d && (v3d->shading.type >= OB_MATERIAL); - bool use_render_settings = v3d && ((use_workbench && use_view_transform) || use_scene_lights || - use_scene_world); + bool use_render_settings = false; + bool use_view_transform = false; + + if (v3d) { + bool use_workbench = BKE_scene_uses_blender_workbench(scene); + + bool use_scene_lights = (!v3d || + ((v3d->shading.type == OB_MATERIAL) && + (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS)) || + ((v3d->shading.type == OB_RENDER) && + (v3d->shading.flag & V3D_SHADING_SCENE_LIGHTS_RENDER))); + bool use_scene_world = (!v3d || + ((v3d->shading.type == OB_MATERIAL) && + (v3d->shading.flag & V3D_SHADING_SCENE_WORLD)) || + ((v3d->shading.type == OB_RENDER) && + (v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER))); + use_view_transform = v3d && (v3d->shading.type >= OB_MATERIAL); + use_render_settings = v3d && ((use_workbench && use_view_transform) || use_scene_lights || + use_scene_world); + } + else if (DST.draw_ctx.space_data && DST.draw_ctx.space_data->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)DST.draw_ctx.space_data; + Image *image = sima->image; + + /* Use inverse logic as there isn't a setting for `Color And Alpha`. */ + const eSpaceImage_Flag display_channels_mode = sima->flag; + const bool display_color_channel = (display_channels_mode & (SI_SHOW_ALPHA | SI_SHOW_ZBUF)) == + 0; + if (display_color_channel && image && (image->source != IMA_SRC_GENERATED) && + ((image->flag & IMA_VIEW_AS_RENDER) != 0)) { + use_render_settings = true; + } + } + else { + use_render_settings = true; + use_view_transform = false; + } if (use_render_settings) { /* Use full render settings, for renders with scene lighting. */ @@ -495,6 +539,8 @@ static void draw_unit_state_create(void) static void drw_viewport_var_init(void) { RegionView3D *rv3d = DST.draw_ctx.rv3d; + ARegion *region = DST.draw_ctx.region; + /* Refresh DST.size */ if (DST.viewport) { int size[2]; @@ -585,6 +631,24 @@ static void drw_viewport_var_init(void) DST.view_active = DST.view_default; DST.view_previous = NULL; } + else if (region) { + View2D *v2d = ®ion->v2d; + float viewmat[4][4]; + float winmat[4][4]; + + rctf region_space = {0.0f, 1.0f, 0.0f, 1.0f}; + BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, ®ion_space, viewmat); + + unit_m4(winmat); + winmat[0][0] = 2.0f; + winmat[1][1] = 2.0f; + winmat[3][0] = -1.0f; + winmat[3][1] = -1.0f; + + DST.view_default = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + DST.view_active = DST.view_default; + DST.view_previous = NULL; + } else { zero_v3(DST.screenvecs[0]); zero_v3(DST.screenvecs[1]); @@ -596,7 +660,7 @@ static void drw_viewport_var_init(void) } /* fclem: Is this still needed ? */ - if (DST.draw_ctx.object_edit) { + if (DST.draw_ctx.object_edit && rv3d) { ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d); } @@ -1163,6 +1227,19 @@ static void drw_engines_enable_basic(void) use_drw_engine(&draw_engine_basic_type); } +static void drw_engines_enable_editors(void) +{ + SpaceLink *space_data = DST.draw_ctx.space_data; + if (!space_data) { + return; + } + + if (space_data->spacetype == SPACE_IMAGE) { + use_drw_engine(&draw_engine_image_type); + use_drw_engine(&draw_engine_overlay_type); + } +} + static void drw_engines_enable(ViewLayer *UNUSED(view_layer), RenderEngineType *engine_type, bool gpencil_engine_needed) @@ -1288,6 +1365,8 @@ void DRW_draw_callbacks_pre_scene(void) if (DST.draw_ctx.evil_C) { ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_PRE_VIEW); + /* Callback can be nasty and do whatever they want with the state. + * Don't trust them! */ DRW_state_reset(); } } @@ -1299,8 +1378,7 @@ void DRW_draw_callbacks_post_scene(void) View3D *v3d = DST.draw_ctx.v3d; Depsgraph *depsgraph = DST.draw_ctx.depsgraph; - const bool do_annotations = (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) && - ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0)); + const bool do_annotations = drw_draw_show_annotation(); if (DST.draw_ctx.evil_C) { DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); @@ -1324,6 +1402,9 @@ void DRW_draw_callbacks_post_scene(void) drw_debug_draw(); GPU_depth_test(GPU_DEPTH_NONE); + /* Apply state for callbacks. */ + GPU_apply_state(); + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW); /* Callback can be nasty and do whatever they want with the state. @@ -1387,21 +1468,30 @@ struct DRWTextStore *DRW_text_cache_ensure(void) * for each relevant engine / mode engine. */ void DRW_draw_view(const bContext *C) { - Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C); - ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); - Scene *scene = DEG_get_evaluated_scene(depsgraph); - RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); - GPUViewport *viewport = WM_draw_region_get_bound_viewport(region); + if (v3d) { + Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C); + ARegion *region = CTX_wm_region(C); + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); + GPUViewport *viewport = WM_draw_region_get_bound_viewport(region); - /* Reset before using it. */ - drw_state_prepare_clean_for_draw(&DST); - DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && - (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0); - DST.options.draw_background = (scene->r.alphamode == R_ADDSKY) || - (v3d->shading.type != OB_RENDER); - DST.options.do_color_management = true; - DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, viewport, C); + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && + (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0); + DST.options.draw_background = (scene->r.alphamode == R_ADDSKY) || + (v3d->shading.type != OB_RENDER); + DST.options.do_color_management = true; + DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, viewport, C); + } + else { + Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C); + ARegion *ar = CTX_wm_region(C); + GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar); + drw_state_prepare_clean_for_draw(&DST); + DRW_draw_render_loop_2d_ex(depsgraph, ar, viewport, C); + } } /** @@ -1909,6 +1999,171 @@ void DRW_cache_restart(void) copy_v2_v2(DST.inv_size, inv_size); } +void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, + ARegion *region, + GPUViewport *viewport, + const bContext *evil_C) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + + DST.draw_ctx.evil_C = evil_C; + DST.viewport = viewport; + + /* Setup viewport */ + DST.draw_ctx = (DRWContextState){ + .region = region, + .scene = scene, + .view_layer = view_layer, + .obact = OBACT(view_layer), + .depsgraph = depsgraph, + .space_data = CTX_wm_space_data(evil_C), + + /* reuse if caller sets */ + .evil_C = DST.draw_ctx.evil_C, + }; + + drw_context_state_init(); + drw_viewport_var_init(); + drw_viewport_colormanagement_set(); + + /* TODO(jbakker): Only populate when editor needs to draw object. + * for the image editor this is when showing UV's.*/ + const bool do_populate_loop = true; + const bool do_annotations = drw_draw_show_annotation(); + + /* Get list of enabled engines */ + drw_engines_enable_editors(); + drw_engines_data_validate(); + + /* Update ubos */ + DRW_globals_update(); + + drw_debug_init(); + + /* No framebuffer allowed before drawing. */ + BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get()); + GPU_framebuffer_bind(DST.default_framebuffer); + GPU_framebuffer_clear_depth_stencil(DST.default_framebuffer, 1.0f, 0xFF); + + /* Init engines */ + drw_engines_init(); + drw_task_graph_init(); + + /* Cache filling */ + { + PROFILE_START(stime); + drw_engines_cache_init(); + + /* Only iterate over objects when overlay uses object data. */ + if (do_populate_loop) { + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) { + drw_engines_cache_populate(ob); + } + DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; + } + + drw_engines_cache_finish(); + + DRW_render_instance_buffer_finish(); + +#ifdef USE_PROFILE + double *cache_time = GPU_viewport_cache_time_get(DST.viewport); + PROFILE_END_UPDATE(*cache_time, stime); +#endif + } + drw_task_graph_deinit(); + + DRW_stats_begin(); + + GPU_framebuffer_bind(DST.default_framebuffer); + + /* Start Drawing */ + DRW_state_reset(); + + if (DST.draw_ctx.evil_C) { + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_PRE_VIEW); + } + + drw_engines_draw_scene(); + + /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */ + GPU_flush(); + + if (DST.draw_ctx.evil_C) { + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DRW_state_reset(); + + GPU_framebuffer_bind(dfbl->overlay_fb); + + if (do_annotations) { + GPU_depth_test(false); + GPU_matrix_push_projection(); + wmOrtho2( + region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, region->v2d.cur.ymax); + ED_annotation_draw_view2d(DST.draw_ctx.evil_C, true); + GPU_matrix_pop_projection(); + + GPU_depth_test(true); + } + + GPU_depth_test(false); + ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW); + GPU_depth_test(true); + /* Callback can be nasty and do whatever they want with the state. + * Don't trust them! */ + DRW_state_reset(); + + GPU_depth_test(false); + drw_engines_draw_text(); + GPU_depth_test(true); + + if (do_annotations) { + GPU_depth_test(false); + ED_annotation_draw_view2d(DST.draw_ctx.evil_C, false); + GPU_depth_test(true); + } + } + + DRW_draw_cursor_2d(); + ED_region_pixelspace(DST.draw_ctx.region); + + { + GPU_depth_test(false); + DRW_draw_gizmo_2d(); + GPU_depth_test(true); + } + + DRW_stats_reset(); + + if (G.debug_value > 20 && G.debug_value < 30) { + GPU_depth_test(false); + /* local coordinate visible rect inside region, to accommodate overlapping ui */ + const rcti *rect = ED_region_visible_rect(DST.draw_ctx.region); + DRW_stats_draw(rect); + GPU_depth_test(true); + } + + if (WM_draw_region_get_bound_viewport(region)) { + /* Don't unbind the framebuffer yet in this case and let + * GPU_viewport_unbind do it, so that we can still do further + * drawing of action zones on top. */ + } + else { + GPU_framebuffer_restore(); + } + + DRW_state_reset(); + drw_engines_disable(); + + drw_viewport_cache_resize(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif +} + static struct DRWSelectBuffer { struct GPUFrameBuffer *framebuffer_depth_only; struct GPUTexture *texture_depth; @@ -2637,6 +2892,8 @@ void DRW_engines_register(void) DRW_engine_register(&draw_engine_select_type); DRW_engine_register(&draw_engine_basic_type); + DRW_engine_register(&draw_engine_image_type); + /* setup callbacks */ { BKE_mball_batch_cache_dirty_tag_cb = DRW_mball_batch_cache_dirty_tag; diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index c0bcb0e679f..9f6a970ea22 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -278,6 +278,8 @@ typedef enum { DRW_UNIFORM_FLOAT_COPY, DRW_UNIFORM_TEXTURE, DRW_UNIFORM_TEXTURE_REF, + DRW_UNIFORM_IMAGE, + DRW_UNIFORM_IMAGE_REF, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_REF, DRW_UNIFORM_TFEEDBACK_TARGET, diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index a4fc44e9571..81842f5d2ec 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -199,10 +199,12 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, case DRW_UNIFORM_BLOCK_REF: uni->block_ref = (GPUUniformBuf **)value; break; + case DRW_UNIFORM_IMAGE: case DRW_UNIFORM_TEXTURE: uni->texture = (GPUTexture *)value; uni->sampler_state = sampler_state; break; + case DRW_UNIFORM_IMAGE_REF: case DRW_UNIFORM_TEXTURE_REF: uni->texture_ref = (GPUTexture **)value; uni->sampler_state = sampler_state; @@ -261,6 +263,20 @@ void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, DRW_shgroup_uniform_texture_ref_ex(shgroup, name, tex, GPU_SAMPLER_MAX); } +void DRW_shgroup_uniform_image(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex) +{ + BLI_assert(tex != NULL); + int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_IMAGE, tex, 0, 0, 1); +} + +void DRW_shgroup_uniform_image_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex) +{ + BLI_assert(tex != NULL); + int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_IMAGE_REF, tex, 0, 0, 1); +} + void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuf *ubo) diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 79d74e1f67d..84f618c1c15 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -596,6 +596,12 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, case DRW_UNIFORM_TEXTURE_REF: GPU_texture_bind_ex(*uni->texture_ref, uni->sampler_state, uni->location, false); break; + case DRW_UNIFORM_IMAGE: + GPU_texture_image_bind(uni->texture, uni->location); + break; + case DRW_UNIFORM_IMAGE_REF: + GPU_texture_image_bind(*uni->texture_ref, uni->location); + break; case DRW_UNIFORM_BLOCK: GPU_uniformbuf_bind(uni->block, uni->location); break; diff --git a/source/blender/draw/intern/draw_manager_profiling.c b/source/blender/draw/intern/draw_manager_profiling.c index 57887c11c02..f8587555480 100644 --- a/source/blender/draw/intern/draw_manager_profiling.c +++ b/source/blender/draw/intern/draw_manager_profiling.c @@ -44,8 +44,8 @@ #define GPU_TIMER_FALLOFF 0.1 typedef struct DRWTimer { - GLuint query[2]; - GLuint64 time_average; + uint32_t query[2]; + uint64_t time_average; char name[MAX_TIMER_NAME]; int lvl; /* Hierarchy level for nested timer. */ bool is_query; /* Does this timer actually perform queries or is it just a group. */ @@ -64,10 +64,10 @@ static struct DRWTimerPool { void DRW_stats_free(void) { if (DTP.timers != NULL) { - for (int i = 0; i < DTP.timer_count; i++) { - DRWTimer *timer = &DTP.timers[i]; - glDeleteQueries(2, timer->query); - } + // for (int i = 0; i < DTP.timer_count; i++) { + // DRWTimer *timer = &DTP.timers[i]; + // glDeleteQueries(2, timer->query); + // } MEM_freeN(DTP.timers); DTP.timers = NULL; } @@ -117,12 +117,12 @@ static void drw_stats_timer_start_ex(const char *name, const bool is_query) BLI_assert(!DTP.is_querying); if (timer->is_query) { if (timer->query[0] == 0) { - glGenQueries(1, timer->query); + // glGenQueries(1, timer->query); } - glFinish(); + // glFinish(); /* Issue query for the next frame */ - glBeginQuery(GL_TIME_ELAPSED, timer->query[0]); + // glBeginQuery(GL_TIME_ELAPSED, timer->query[0]); DTP.is_querying = true; } } @@ -154,7 +154,7 @@ void DRW_stats_query_end(void) if (DTP.is_recording) { DTP.end_increment++; BLI_assert(DTP.is_querying); - glEndQuery(GL_TIME_ELAPSED); + // glEndQuery(GL_TIME_ELAPSED); DTP.is_querying = false; } } @@ -167,19 +167,19 @@ void DRW_stats_reset(void) "You forgot a DRW_stats_group/query_start somewhere!"); if (DTP.is_recording) { - GLuint64 lvl_time[MAX_NESTED_TIMER] = {0}; + uint64_t lvl_time[MAX_NESTED_TIMER] = {0}; /* Swap queries for the next frame and sum up each lvl time. */ for (int i = DTP.timer_increment - 1; i >= 0; i--) { DRWTimer *timer = &DTP.timers[i]; - SWAP(GLuint, timer->query[0], timer->query[1]); + SWAP(uint32_t, timer->query[0], timer->query[1]); BLI_assert(timer->lvl < MAX_NESTED_TIMER); if (timer->is_query) { - GLuint64 time; + uint64_t time = 0; if (timer->query[0] != 0) { - glGetQueryObjectui64v(timer->query[0], GL_QUERY_RESULT, &time); + // glGetQueryObjectui64v(timer->query[0], GL_QUERY_RESULT, &time); } else { time = 1000000000; /* 1ms default */ diff --git a/source/blender/draw/intern/draw_manager_text.c b/source/blender/draw/intern/draw_manager_text.c index adcac15ab85..e3d0dab6767 100644 --- a/source/blender/draw/intern/draw_manager_text.c +++ b/source/blender/draw/intern/draw_manager_text.c @@ -24,6 +24,7 @@ #include "BLI_math.h" #include "BLI_memiter.h" +#include "BLI_rect.h" #include "BLI_string.h" #include "BKE_editmesh.h" @@ -122,76 +123,105 @@ void DRW_text_cache_add(DRWTextStore *dt, } } -void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d) +static void drw_text_cache_draw_ex(DRWTextStore *dt, ARegion *region) { - RegionView3D *rv3d = region->regiondata; ViewCachedString *vos; - int tot = 0; - - /* project first and test */ BLI_memiter_handle it; - BLI_memiter_iter_init(dt->cache_strings, &it); - while ((vos = BLI_memiter_iter_step(&it))) { - if (ED_view3d_project_short_ex( - region, - (vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob, - (vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0, - vos->vec, - vos->sco, - V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == - V3D_PROJ_RET_OK) { - tot++; - } - else { - vos->sco[0] = IS_CLIPPED; - } - } + int col_pack_prev = 0; - if (tot) { - int col_pack_prev = 0; + float original_proj[4][4]; + GPU_matrix_projection_get(original_proj); + wmOrtho2_region_pixelspace(region); - /* Disable clipping for text */ - if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - GPU_clip_distances(0); - } + GPU_matrix_push(); + GPU_matrix_identity_set(); - float original_proj[4][4]; - GPU_matrix_projection_get(original_proj); - wmOrtho2_region_pixelspace(region); + const int font_id = BLF_default(); - GPU_matrix_push(); - GPU_matrix_identity_set(); + const uiStyle *style = UI_style_get(); - const int font_id = BLF_default(); + BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi); - const uiStyle *style = UI_style_get(); + BLI_memiter_iter_init(dt->cache_strings, &it); + while ((vos = BLI_memiter_iter_step(&it))) { + if (vos->sco[0] != IS_CLIPPED) { + if (col_pack_prev != vos->col.pack) { + BLF_color4ubv(font_id, vos->col.ub); + col_pack_prev = vos->col.pack; + } + + BLF_position( + font_id, (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1] + vos->yoffs), 2.0f); + + ((vos->flag & DRW_TEXT_CACHE_ASCII) ? BLF_draw_ascii : BLF_draw)( + font_id, + (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str, + vos->str_len); + } + } - BLF_size(font_id, style->widget.points * U.pixelsize, U.dpi); + GPU_matrix_pop(); + GPU_matrix_projection_set(original_proj); +} +void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d) +{ + ViewCachedString *vos; + if (v3d) { + RegionView3D *rv3d = region->regiondata; + int tot = 0; + /* project first and test */ + BLI_memiter_handle it; BLI_memiter_iter_init(dt->cache_strings, &it); while ((vos = BLI_memiter_iter_step(&it))) { - if (vos->sco[0] != IS_CLIPPED) { - if (col_pack_prev != vos->col.pack) { - BLF_color4ubv(font_id, vos->col.ub); - col_pack_prev = vos->col.pack; - } + if (ED_view3d_project_short_ex( + region, + (vos->flag & DRW_TEXT_CACHE_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob, + (vos->flag & DRW_TEXT_CACHE_LOCALCLIP) != 0, + vos->vec, + vos->sco, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == + V3D_PROJ_RET_OK) { + tot++; + } + else { + vos->sco[0] = IS_CLIPPED; + } + } - BLF_position( - font_id, (float)(vos->sco[0] + vos->xoffs), (float)(vos->sco[1] + vos->yoffs), 2.0f); + if (tot) { + /* Disable clipping for text */ + const bool rv3d_clipping_enabled = RV3D_CLIPPING_ENABLED(v3d, rv3d); + if (rv3d_clipping_enabled) { + GPU_clip_distances(0); + } + + drw_text_cache_draw_ex(dt, region); - ((vos->flag & DRW_TEXT_CACHE_ASCII) ? BLF_draw_ascii : BLF_draw)( - font_id, - (vos->flag & DRW_TEXT_CACHE_STRING_PTR) ? *((const char **)vos->str) : vos->str, - vos->str_len); + if (rv3d_clipping_enabled) { + GPU_clip_distances(6); } } + } + else { + /* project first */ + BLI_memiter_handle it; + BLI_memiter_iter_init(dt->cache_strings, &it); + View2D *v2d = ®ion->v2d; + float viewmat[4][4]; + rctf region_space = {0.0f, region->winx, 0.0f, region->winy}; + BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, ®ion_space, viewmat); - GPU_matrix_pop(); - GPU_matrix_projection_set(original_proj); + while ((vos = BLI_memiter_iter_step(&it))) { + float p[3]; + copy_v3_v3(p, vos->vec); + mul_m4_v3(viewmat, p); - if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - GPU_clip_distances(6); + vos->sco[0] = p[0]; + vos->sco[1] = p[1]; } + + drw_text_cache_draw_ex(dt, region); } } diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index d01e1a51080..3033cf70b29 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -35,6 +35,7 @@ #include "GPU_shader.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "WM_types.h" @@ -196,6 +197,65 @@ void DRW_draw_cursor(void) } } +/* -------------------------------------------------------------------- */ + +/** \name 2D Cursor + * \{ */ + +static bool is_cursor_visible_2d(const DRWContextState *draw_ctx) +{ + SpaceInfo *space_data = (SpaceInfo *)draw_ctx->space_data; + if (space_data == NULL) { + return false; + } + if (space_data->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + return sima->mode == SI_MODE_UV; + } + return false; +} + +void DRW_draw_cursor_2d(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ARegion *region = draw_ctx->region; + + GPU_color_mask(true, true, true, true); + GPU_depth_mask(false); + GPU_depth_test(GPU_DEPTH_NONE); + + if (is_cursor_visible_2d(draw_ctx)) { + SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; + int co[2]; + UI_view2d_view_to_region(®ion->v2d, sima->cursor[0], sima->cursor[1], &co[0], &co[1]); + + /* Draw nice Anti Aliased cursor. */ + GPU_line_width(1.0f); + GPU_blend(true); + GPU_line_smooth(true); + + /* Draw lines */ + float original_proj[4][4]; + GPU_matrix_projection_get(original_proj); + GPU_matrix_push(); + ED_region_pixelspace(region); + GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f); + GPU_matrix_scale_2f(U.widget_unit, U.widget_unit); + + GPUBatch *cursor_batch = DRW_cache_cursor_get(true); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR); + GPU_batch_set_shader(cursor_batch, shader); + + GPU_batch_draw(cursor_batch); + + GPU_blend(false); + GPU_line_smooth(false); + GPU_matrix_pop(); + GPU_matrix_projection_set(original_proj); + } +} +/* \} */ + /* **************************** 3D Gizmo ******************************** */ void DRW_draw_gizmo_3d(void) diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h index a01a2d0dcce..24fabaae05e 100644 --- a/source/blender/draw/intern/draw_view.h +++ b/source/blender/draw/intern/draw_view.h @@ -25,5 +25,6 @@ void DRW_draw_region_info(void); void DRW_clear_background(void); void DRW_draw_cursor(void); +void DRW_draw_cursor_2d(void); void DRW_draw_gizmo_3d(void); void DRW_draw_gizmo_2d(void); diff --git a/source/blender/draw/intern/shaders/common_globals_lib.glsl b/source/blender/draw/intern/shaders/common_globals_lib.glsl index bd1b1fb6f3a..691f1d5e519 100644 --- a/source/blender/draw/intern/shaders/common_globals_lib.glsl +++ b/source/blender/draw/intern/shaders/common_globals_lib.glsl @@ -103,6 +103,8 @@ layout(std140) uniform globalsBlock vec4 colorFaceBack; vec4 colorFaceFront; + vec4 colorUVShadow; + vec4 screenVecs[2]; vec4 sizeViewport; /* Inverted size in zw. */ diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc index b73c94208b5..8feccc9588e 100644 --- a/source/blender/draw/tests/shaders_test.cc +++ b/source/blender/draw/tests/shaders_test.cc @@ -11,6 +11,7 @@ #include "engines/eevee/eevee_private.h" #include "engines/gpencil/gpencil_engine.h" +#include "engines/image/image_private.h" #include "engines/overlay/overlay_private.h" #include "engines/workbench/workbench_private.h" @@ -151,8 +152,19 @@ TEST_F(DrawTest, gpencil_glsl_shaders) GPENCIL_shader_free(); } +TEST_F(DrawTest, image_glsl_shaders) +{ + IMAGE_shader_library_ensure(); + + EXPECT_NE(IMAGE_shader_image_get(), nullptr); + + IMAGE_shader_free(); +} + TEST_F(DrawTest, overlay_glsl_shaders) { + OVERLAY_shader_library_ensure(); + for (int i = 0; i < 2; i++) { eGPUShaderConfig sh_cfg = i == 0 ? GPU_SHADER_CFG_DEFAULT : GPU_SHADER_CFG_CLIPPED; DRW_draw_state_init_gtests(sh_cfg); @@ -189,6 +201,13 @@ TEST_F(DrawTest, overlay_glsl_shaders) EXPECT_NE(OVERLAY_shader_edit_mesh_vert(), nullptr); EXPECT_NE(OVERLAY_shader_edit_particle_strand(), nullptr); EXPECT_NE(OVERLAY_shader_edit_particle_point(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_edges_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_face_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_face_dots_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_verts_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_stretching_area_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_stretching_angle_get(), nullptr); + EXPECT_NE(OVERLAY_shader_edit_uv_tiled_image_borders_get(), nullptr); EXPECT_NE(OVERLAY_shader_extra(false), nullptr); EXPECT_NE(OVERLAY_shader_extra(true), nullptr); EXPECT_NE(OVERLAY_shader_extra_groundline(), nullptr); @@ -201,6 +220,7 @@ TEST_F(DrawTest, overlay_glsl_shaders) EXPECT_NE(OVERLAY_shader_facing(), nullptr); EXPECT_NE(OVERLAY_shader_gpencil_canvas(), nullptr); EXPECT_NE(OVERLAY_shader_grid(), nullptr); + EXPECT_NE(OVERLAY_shader_grid_image(), nullptr); EXPECT_NE(OVERLAY_shader_image(), nullptr); EXPECT_NE(OVERLAY_shader_motion_path_line(), nullptr); EXPECT_NE(OVERLAY_shader_motion_path_vert(), nullptr); diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt index ce6778a1ff9..1ca9a844feb 100644 --- a/source/blender/editors/animation/CMakeLists.txt +++ b/source/blender/editors/animation/CMakeLists.txt @@ -30,9 +30,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC anim_channels_defines.c @@ -69,6 +66,5 @@ if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt index 71c7febe192..98c050950be 100644 --- a/source/blender/editors/armature/CMakeLists.txt +++ b/source/blender/editors/armature/CMakeLists.txt @@ -31,10 +31,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC armature_add.c armature_edit.c @@ -67,6 +63,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_armature "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt index ff80c47baa8..877c2d99102 100644 --- a/source/blender/editors/curve/CMakeLists.txt +++ b/source/blender/editors/curve/CMakeLists.txt @@ -31,10 +31,6 @@ set(INC ../../../../extern/curve_fit_nd ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC curve_ops.c editcurve.c @@ -59,6 +55,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_curve "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 2b3df79476a..e6815582a04 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -3640,9 +3640,8 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) * degree of the functions used to build the NURB. The * expression * - * degree = #knots - #controlpoints + 1 (J Walter piece) - * degree = #knots - #controlpoints (Blender - * implementation) + * `degree = knots - controlpoints + 1` (J Walter piece) + * `degree = knots - controlpoints` (Blender implementation) * ( this is confusing.... what is true? Another concern * is that the JW piece allows the curve to become * explicitly 1st order derivative discontinuous, while @@ -3651,12 +3650,12 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) * is an invariant for a single NURB curve. Raising the degree * of the NURB is done elsewhere; the degree is assumed * constant during this operation. Degree is a property shared - * by all controlpoints in a curve (even though it is stored + * by all control-points in a curve (even though it is stored * per control point - this can be misleading). * Adding a knot is done by searching for the place in the * knot vector where a certain knot value must be inserted, or * by picking an appropriate knot value between two existing - * ones. The number of controlpoints that is influenced by the + * ones. The number of control-points that is influenced by the * insertion depends on the order of the curve. A certain * minimum number of knots is needed to form high-order * curves, as can be seen from the equation above. In Blender, diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 19b05f0af0c..4d72e90b89b 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -508,7 +508,10 @@ Nurb *ED_curve_add_nurbs_primitive( static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) { - Object *obedit = CTX_data_edit_object(C); + struct Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); ListBase *editnurb; Nurb *nu; bool newob = false; @@ -565,7 +568,7 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); diff --git a/source/blender/editors/gizmo_library/CMakeLists.txt b/source/blender/editors/gizmo_library/CMakeLists.txt index 1f3edf31b19..eeb1e60166b 100644 --- a/source/blender/editors/gizmo_library/CMakeLists.txt +++ b/source/blender/editors/gizmo_library/CMakeLists.txt @@ -32,10 +32,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC gizmo_draw_utils.c gizmo_geometry.h @@ -59,6 +55,5 @@ set(SRC set(LIB ) -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_gizmo_library "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt index 735ad8bc039..20408327105 100644 --- a/source/blender/editors/gpencil/CMakeLists.txt +++ b/source/blender/editors/gpencil/CMakeLists.txt @@ -31,10 +31,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC annotate_draw.c annotate_paint.c @@ -75,6 +71,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_gpencil "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 47b8eb543f4..341f97943a5 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -150,6 +150,7 @@ int ED_file_extension_icon(const char *path); void ED_file_read_bookmarks(void); +void ED_file_change_dir_ex(struct bContext *C, struct bScreen *screen, struct ScrArea *area); void ED_file_change_dir(struct bContext *C); void ED_file_path_button(struct bScreen *screen, diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index ad9446f92c7..64b4a058ca2 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -2374,10 +2374,7 @@ 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, const bool highlight, const bool redalert); -uiBut *uiItemL_respect_property_split(uiLayout *layout, - const char *text, - int icon, - uiLayout **r_layout); +uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon); /* label icon for dragging */ void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon); /* menu */ diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index e4fb0631f06..680cf3ea01a 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -34,10 +34,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC interface.c interface_align.c @@ -113,6 +109,5 @@ if(WIN32) endif() endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_interface "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 8c564ecd1d4..b0530c797a8 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -6700,7 +6700,7 @@ static void operator_enum_search_update_fn(const struct bContext *C, } } - MEM_freeN(filtered_items); + MEM_freeN((void *)filtered_items); BLI_string_search_free(search); if (do_free) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c91b4d826a7..d22ddb5f2b7 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -256,7 +256,7 @@ static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc) /* Utilities */ -static void viconutil_set_point(GLint pt[2], int x, int y) +static void viconutil_set_point(int pt[2], int x, int y) { pt[0] = x; pt[1] = y; @@ -264,7 +264,7 @@ static void viconutil_set_point(GLint pt[2], int x, int y) static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float alpha) { - GLint pts[3][2]; + int pts[3][2]; const int cx = x + w / 2 - 4; const int cy = y + w / 2; const int d = w / 5, d2 = w / 7; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index a423f0705bb..ac5230c551a 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -275,14 +275,6 @@ struct uiBut { uiButPushedStateFunc pushed_state_func; void *pushed_state_arg; - /** - * Used for property search, so that a button's label and decorator can be filtered and - * unfiltered along with it. Due to the sometimes arbitrary nature of which button to choose - * for these values, they aren't always filled. - */ - uiBut *label_but; - uiBut *decorator_but; - /* pointer back */ uiBlock *block; }; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 613e91fc03a..59807dce8be 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -80,6 +80,17 @@ /* uiLayoutRoot */ +/** + * A group of button references, used by property search to keep track of sets of buttons that + * should be searched together. For example, in property split layouts number buttons and their + * labels (and even their decorators) are separate buttons, but they must be searched and + * highlighted together. + */ +typedef struct uiButtonGroup { + void *next, *prev; + ListBase buttons; /* #LinkData with #uiBut data field. */ +} uiButtonGroup; + typedef struct uiLayoutRoot { struct uiLayoutRoot *next, *prev; @@ -93,6 +104,8 @@ typedef struct uiLayoutRoot { */ bool search_only; + ListBase button_groups; /* #uiButtonGroup. */ + int emw, emh; int padding; @@ -227,8 +240,6 @@ typedef struct uiLayoutItemRoot { /** \} */ -static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon); - /* -------------------------------------------------------------------- */ /** \name Item * \{ */ @@ -424,6 +435,43 @@ static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Button Groups + * \{ */ + +/** + * Every function that adds a set of buttons must create another group, + * then #ui_def_but adds buttons to the current group (the last). + */ +static void layout_root_new_button_group(uiLayoutRoot *root) +{ + uiButtonGroup *new_group = MEM_mallocN(sizeof(uiButtonGroup), __func__); + BLI_listbase_clear(&new_group->buttons); + BLI_addtail(&root->button_groups, new_group); +} + +static void button_group_add_but(uiLayoutRoot *root, uiBut *but) +{ + BLI_assert(root != NULL); + + uiButtonGroup *current_button_group = root->button_groups.last; + BLI_assert(current_button_group != NULL); + + /* We can't use the button directly because adding it to + * this list would mess with its prev and next pointers. */ + LinkData *button_link = MEM_mallocN(sizeof(LinkData), __func__); + button_link->data = but; + BLI_addtail(¤t_button_group->buttons, button_link); +} + +static void button_group_free(uiButtonGroup *button_group) +{ + BLI_freelistN(&button_group->buttons); + MEM_freeN(button_group); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Special RNA Items * \{ */ @@ -504,8 +552,7 @@ static void ui_item_array(uiLayout *layout, int toggle, bool icon_only, bool compact, - bool show_text, - uiBut *label_but) + bool show_text) { const uiStyle *style = layout->root->style; uiBut *but; @@ -670,10 +717,7 @@ static void ui_item_array(uiLayout *layout, /* special case, boolean array in a menu, this could be used in a more generic way too */ if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand && ELEM(len, 3, 4)) { - but = uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y); - if (label_but != NULL) { - but->label_but = label_but; - } + uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y); } else { bool *boolarr = NULL; @@ -724,13 +768,6 @@ static void ui_item_array(uiLayout *layout, if ((a == 0) && (subtype == PROP_AXISANGLE)) { UI_but_unit_type_set(but, PROP_UNIT_ROTATION); } - - /* Set the label button for the array item. */ - if (label_but != NULL) { - but->label_but = label_but; - label_but = label_but->next; - BLI_assert(label_but != NULL); - } } if (boolarr) { @@ -773,8 +810,7 @@ static void ui_item_enum_expand_elem_exec(uiLayout *layout, const eButType but_type, const bool icon_only, const EnumPropertyItem *item, - const bool is_first, - uiBut *label_but) + const bool is_first) { const char *name = (!uiname || uiname[0]) ? item->name : ""; const int icon = item->icon; @@ -813,10 +849,6 @@ static void ui_item_enum_expand_elem_exec(uiLayout *layout, if (but_type == UI_BTYPE_TAB) { but->flag |= UI_BUT_DRAG_LOCK; } - - if (label_but != NULL) { - but->label_but = label_but; - } } static void ui_item_enum_expand_exec(uiLayout *layout, @@ -826,8 +858,7 @@ static void ui_item_enum_expand_exec(uiLayout *layout, const char *uiname, const int h, const eButType but_type, - const bool icon_only, - uiBut *label_but) + const bool icon_only) { /* XXX: The way this function currently handles uiname parameter * is insane and inconsistent with general UI API: @@ -903,7 +934,7 @@ static void ui_item_enum_expand_exec(uiLayout *layout, } ui_item_enum_expand_elem_exec( - layout, block, ptr, prop, uiname, h, but_type, icon_only, item, is_first, label_but); + layout, block, ptr, prop, uiname, h, but_type, icon_only, item, is_first); } UI_block_layout_set_current(block, layout); @@ -918,11 +949,9 @@ static void ui_item_enum_expand(uiLayout *layout, PropertyRNA *prop, const char *uiname, const int h, - const bool icon_only, - uiBut *label_but) + const bool icon_only) { - ui_item_enum_expand_exec( - layout, block, ptr, prop, uiname, h, UI_BTYPE_ROW, icon_only, label_but); + ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_ROW, icon_only); } static void ui_item_enum_expand_tabs(uiLayout *layout, bContext *C, @@ -935,7 +964,7 @@ static void ui_item_enum_expand_tabs(uiLayout *layout, { uiBut *last = block->buttons.last; - ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only, NULL); + ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only); BLI_assert(last != block->buttons.last); for (uiBut *tab = last ? last->next : block->buttons.first; tab; tab = tab->next) { UI_but_drawflag_enable(tab, ui_but_align_opposite_to_area_align_get(CTX_wm_region(C))); @@ -974,12 +1003,10 @@ static uiBut *ui_item_with_label(uiLayout *layout, { uiLayout *sub = layout; uiBut *but = NULL; - uiBut *label_but = NULL; PropertyType type; PropertySubType subtype; int prop_but_width = w_hint; #ifdef UI_PROP_DECORATE - uiBut *decorator_but = NULL; uiLayout *layout_prop_decorate = NULL; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); const bool use_prop_decorate = use_prop_sep && (layout->item.flag & UI_ITEM_PROP_DECORATE) && @@ -1000,7 +1027,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, #ifdef UI_PROP_DECORATE if (name[0]) { if (use_prop_sep) { - label_but = uiItemL_respect_property_split(layout, name, 0, &layout_prop_decorate); + layout_prop_decorate = uiItemL_respect_property_split(layout, name, 0); } else #endif @@ -1016,8 +1043,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, else { w_label = w_hint / 3; } - label_but = uiDefBut( - block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, ""); } } @@ -1095,15 +1121,10 @@ static uiBut *ui_item_with_label(uiLayout *layout, #ifdef UI_PROP_DECORATE /* Only for alignment. */ if (use_prop_decorate) { /* Note that sep flag may have been unset meanwhile. */ - decorator_but = uiItemL_(layout_prop_decorate ? layout_prop_decorate : sub, NULL, ICON_BLANK1); + uiItemL(layout_prop_decorate ? layout_prop_decorate : sub, NULL, ICON_BLANK1); } #endif /* UI_PROP_DECORATE */ - /* Set the button's label and decorator even if they are NULL. They can be changed - * further with the return value of this function anyway. */ - but->label_but = label_but; - but->decorator_but = decorator_but; - UI_block_layout_set_current(block, layout); return but; } @@ -1942,34 +1963,28 @@ static uiLayout *ui_layout_heading_find(uiLayout *cur_layout) return NULL; } -/** - * \return The label button added. - */ -static uiBut *ui_layout_heading_label_add(uiLayout *layout, - uiLayout *heading_layout, - bool right_align, - bool respect_prop_split) +static void ui_layout_heading_label_add(uiLayout *layout, + uiLayout *heading_layout, + bool right_align, + bool respect_prop_split) { const int prev_alignment = layout->alignment; - uiBut *label_but = NULL; if (right_align) { uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_RIGHT); } if (respect_prop_split) { - label_but = uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE, NULL); + uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE); } else { - label_but = uiItemL_(layout, heading_layout->heading, ICON_NONE); + uiItemL(layout, heading_layout->heading, ICON_NONE); } /* After adding the heading label, we have to mark it somehow as added, so it's not added again * for other items in this layout. For now just clear it. */ heading_layout->heading[0] = '\0'; layout->alignment = prev_alignment; - - return label_but; } /** @@ -2030,6 +2045,7 @@ void uiItemFullR(uiLayout *layout, #endif /* UI_PROP_DECORATE */ UI_block_layout_set_current(block, layout); + layout_root_new_button_group(layout->root); /* retrieve info */ const PropertyType type = RNA_property_type(prop); @@ -2151,10 +2167,6 @@ void uiItemFullR(uiLayout *layout, } uiBut *but = NULL; - /* Store the label to assign it to the button afterwards. This is the first - * label button if the item is an array and there are a series of buttons. - * Decorators are assigned as they are built later on. */ - uiBut *label_but = NULL; /* Split the label / property. */ uiLayout *layout_parent = layout; @@ -2174,7 +2186,7 @@ void uiItemFullR(uiLayout *layout, layout = uiLayoutColumn(layout_row ? layout_row : layout, true); layout->space = 0; if (heading_layout) { - label_but = ui_layout_heading_label_add(layout, heading_layout, false, false); + ui_layout_heading_label_add(layout, heading_layout, false, false); } } else { @@ -2201,43 +2213,39 @@ void uiItemFullR(uiLayout *layout, *s++ = str[0]; *s++ = '\0'; } - uiBut *new_label = uiDefBut(block, - UI_BTYPE_LABEL, - 0, - use_prefix ? name_with_suffix : str, - 0, - 0, - w, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0, - 0, - ""); - new_label->drawflag |= UI_BUT_TEXT_RIGHT; - new_label->drawflag &= ~UI_BUT_TEXT_LEFT; - - if (a == 0) { - label_but = new_label; - } + but = uiDefBut(block, + UI_BTYPE_LABEL, + 0, + use_prefix ? name_with_suffix : str, + 0, + 0, + w, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0, + 0, + ""); + but->drawflag |= UI_BUT_TEXT_RIGHT; + but->drawflag &= ~UI_BUT_TEXT_LEFT; + label_added = true; } } else { if (name) { - label_but = uiDefBut( + but = uiDefBut( block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); - label_but->drawflag |= UI_BUT_TEXT_RIGHT; - label_but->drawflag &= ~UI_BUT_TEXT_LEFT; + but->drawflag |= UI_BUT_TEXT_RIGHT; + but->drawflag &= ~UI_BUT_TEXT_LEFT; label_added = true; } } if (!label_added && heading_layout) { - label_but = ui_layout_heading_label_add(layout_sub, heading_layout, true, false); - label_added = true; + ui_layout_heading_label_add(layout_sub, heading_layout, true, false); } layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split); @@ -2280,7 +2288,7 @@ void uiItemFullR(uiLayout *layout, else if (heading_layout) { /* Could not add heading to split layout, fallback to inserting it to the layout with the * heading itself. */ - label_but = ui_layout_heading_label_add(heading_layout, heading_layout, false, false); + ui_layout_heading_label_add(heading_layout, heading_layout, false, false); } /* array property */ @@ -2307,29 +2315,26 @@ void uiItemFullR(uiLayout *layout, toggle, icon_only, compact, - !use_prop_sep_split_label, - label_but); + !use_prop_sep_split_label); } /* enum item */ else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) { if (icon && name[0] && !icon_only) { - but = uiDefIconTextButR_prop( + uiDefIconTextButR_prop( block, UI_BTYPE_ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL); } else if (icon) { - but = uiDefIconButR_prop( + uiDefIconButR_prop( block, UI_BTYPE_ROW, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL); } else { - but = uiDefButR_prop( + uiDefButR_prop( block, UI_BTYPE_ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL); } - BLI_assert(but != NULL); - but->label_but = label_but; } /* expanded enum */ else if (type == PROP_ENUM && expand) { - ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only, label_but); + ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only); } /* property with separate label */ else if (type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) { @@ -2343,8 +2348,6 @@ void uiItemFullR(uiLayout *layout, if (layout->activate_init) { UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); } - BLI_assert(but != NULL); - but->label_but = label_but; } /* single button */ else { @@ -2378,8 +2381,6 @@ void uiItemFullR(uiLayout *layout, if (layout->activate_init) { UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); } - - but->label_but = label_but; } /* The resulting button may have the icon set since boolean button drawing @@ -2415,16 +2416,13 @@ void uiItemFullR(uiLayout *layout, /* The icons are set in 'ui_but_anim_flag' */ uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex); - uiBut *decorator = block->buttons.last; - but_decorate->decorator_but = decorator; + but = block->buttons.last; /* Order the decorator after the button we decorate, this is used so we can always * do a quick lookup. */ - BLI_remlink(&block->buttons, decorator); - BLI_insertlinkafter(&block->buttons, but_decorate, decorator); - - /* Assign decorator to the property's button so that they can be filtered together. */ - but_decorate = decorator->next; + BLI_remlink(&block->buttons, but); + BLI_insertlinkafter(&block->buttons, but_decorate, but); + but_decorate = but->next; } BLI_assert(ELEM(i, 1, ui_decorate.len)); @@ -2798,6 +2796,8 @@ void uiItemPointerR_prop(uiLayout *layout, char namestr[UI_MAX_NAME_STR]; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); + layout_root_new_button_group(layout->root); + type = RNA_property_type(prop); if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) { RNA_warning("Property %s.%s must be a pointer, string or enum", @@ -2903,6 +2903,7 @@ static uiBut *ui_item_menu(uiLayout *layout, int w, h; UI_block_layout_set_current(block, layout); + layout_root_new_button_group(layout->root); if (!name) { name = ""; @@ -3170,6 +3171,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon) int w; UI_block_layout_set_current(block, layout); + layout_root_new_button_group(layout->root); if (!name) { name = ""; @@ -3253,42 +3255,29 @@ uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout) return split_wrapper; } -/** +/* * Helper to add a label and creates a property split layout if needed. - * - * \param r_layout: Returns a column to put decorators in if property separate is on, otherwise - * returns the original layout. */ -uiBut *uiItemL_respect_property_split(uiLayout *layout, - const char *text, - int icon, - uiLayout **r_layout) +uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon) { - uiBut *label_but; if (layout->item.flag & UI_ITEM_PROP_SEP) { uiBlock *block = uiLayoutGetBlock(layout); const uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(layout); /* Further items added to 'layout' will automatically be added to split_wrapper.property_row */ - label_but = uiItemL_(split_wrapper.label_column, text, icon); + uiItemL_(split_wrapper.label_column, text, icon); UI_block_layout_set_current(block, split_wrapper.property_row); - if (r_layout != NULL) { - *r_layout = split_wrapper.decorate_column; - } + return split_wrapper.decorate_column; } - else { - char namestr[UI_MAX_NAME_STR]; - if (text) { - text = ui_item_name_add_colon(text, namestr); - } - label_but = uiItemL_(layout, text, icon); - if (r_layout != NULL) { - *r_layout = layout; - } + char namestr[UI_MAX_NAME_STR]; + if (text) { + text = ui_item_name_add_colon(text, namestr); } - return label_but; + uiItemL_(layout, text, icon); + + return layout; } void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon) @@ -5220,38 +5209,43 @@ static bool button_matches_search_filter(uiBut *but, const char *search_filter) } /** - * Apply the search filter, tagging all buttons with whether they match or not. + * Test for a search result within the a specific button group. */ -static bool block_search_filter_tag_buttons(uiBlock *block) +static bool button_group_has_search_match(uiButtonGroup *button_group, const char *search_filter) { - bool has_result = false; - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - /* First match regular buttons. */ - if (!ELEM(but->type, UI_BTYPE_LABEL) && - button_matches_search_filter(but, block->search_filter)) { - has_result = true; - but->flag |= UI_SEARCH_FILTER_MATCHES; - } - /* Then match their labels. */ - if (but->label_but != NULL && - button_matches_search_filter(but->label_but, block->search_filter)) { - has_result = true; - but->flag |= UI_SEARCH_FILTER_MATCHES; + LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) { + uiBut *but = link->data; + if (button_matches_search_filter(but, search_filter)) { + return true; } } - /* Remove filter from labels and decorators that correspond to un-filtered buttons. */ - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - if (but->flag & UI_SEARCH_FILTER_MATCHES) { - if (but->label_but != NULL) { - but->label_but->flag |= UI_SEARCH_FILTER_MATCHES; - } - if (but->decorator_but != NULL) { - but->decorator_but->flag |= UI_SEARCH_FILTER_MATCHES; + return false; +} + +/** + * Apply the search filter, tagging all buttons with whether they match or not. + * Tag every button in the group as a search match if any button matches. + * + * \note It would be great to return early here if we found a match, but because + * the results could be visible we have to continue searching the entire block. + * + * \return Whether the block has any search results. + */ +static bool block_search_filter_tag_buttons(uiBlock *block) +{ + bool has_result = false; + LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) { + LISTBASE_FOREACH (uiButtonGroup *, button_group, &root->button_groups) { + if (button_group_has_search_match(button_group, block->search_filter)) { + LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) { + uiBut *but = link->data; + but->flag |= UI_SEARCH_FILTER_MATCHES; + } + has_result = true; } } } - return has_result; } @@ -5534,6 +5528,16 @@ static void ui_layout_free(uiLayout *layout) MEM_freeN(layout); } +static void layout_root_free(uiLayoutRoot *root) +{ + ui_layout_free(root->layout); + + LISTBASE_FOREACH_MUTABLE (uiButtonGroup *, button_group, &root->button_groups) { + button_group_free(button_group); + } + MEM_freeN(root); +} + static void ui_layout_add_padding_button(uiLayoutRoot *root) { if (root->padding) { @@ -5568,6 +5572,9 @@ uiLayout *UI_block_layout(uiBlock *block, root->padding = padding; root->opcontext = WM_OP_INVOKE_REGION_WIN; + BLI_listbase_clear(&root->button_groups); + layout_root_new_button_group(root); + layout = MEM_callocN(sizeof(uiLayout), "uiLayout"); layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT; @@ -5652,6 +5659,8 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but) if (layout->emboss != UI_EMBOSS_UNDEFINED) { but->emboss = layout->emboss; } + + button_group_add_but(layout->root, but); } bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but) @@ -5717,7 +5726,7 @@ void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y) block->curlayout = NULL; - LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) { + LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) { /* Seach only roots should be removed by #UI_block_apply_search_filter. */ BLI_assert(!root->search_only); @@ -5725,10 +5734,10 @@ void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y) /* NULL in advance so we don't interfere when adding button */ ui_layout_end(block, root->layout, r_x, r_y); - ui_layout_free(root->layout); + layout_root_free(root); } - BLI_freelistN(&block->layouts); + BLI_listbase_clear(&block->layouts); /* XXX silly trick, interface_templates.c doesn't get linked * because it's not used by other files in this module? */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9141a46499e..77a9d9f549a 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -897,7 +897,7 @@ static void template_ID(const bContext *C, if (text) { /* Add label resepecting the separated layout property split state. */ - uiItemL_respect_property_split(layout, text, ICON_NONE, NULL); + uiItemL_respect_property_split(layout, text, ICON_NONE); } if (flag & UI_ID_BROWSE) { diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index 66c055d9426..dd04732a814 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -30,10 +30,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC mask_add.c mask_draw.c @@ -51,6 +47,5 @@ set(SRC set(LIB ) -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_mask "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 589b51ce942..035af772a55 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -35,10 +35,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC editface.c editmesh_add.c @@ -97,6 +93,5 @@ if(WITH_GMP) add_definitions(-DWITH_GMP) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_mesh "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 3c426e5d2b1..b7bf6230f22 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -104,7 +104,7 @@ static void make_prim_finish(bContext *C, /* userdef */ if (exit_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(CTX_data_main(C), CTX_data_scene(C), obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); } diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index 953ef8114f9..be6c0658b1f 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -39,10 +39,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC object_add.c object_bake.c @@ -81,7 +77,6 @@ set(LIB bf_windowmanager ) -add_definitions(${GL_DEFINITIONS}) if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 4de48fba494..fa1d147dc5e 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -529,9 +529,12 @@ Object *ED_object_add_type_with_obdata(bContext *C, ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob; - /* for as long scene has editmode... */ - if (CTX_data_edit_object(C)) { - ED_object_editmode_exit(C, EM_FREEDATA); + /* For as long scene has editmode... */ + { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obedit != NULL) { + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); + } } /* deselects all, sets active object */ @@ -778,18 +781,20 @@ static int effector_add_exec(bContext *C, wmOperator *op) dia = RNA_float_get(op->ptr, "radius"); if (type == PFIELD_GUIDE) { + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); Curve *cu; ob = ED_object_add_type( C, OB_CURVE, get_effector_defname(type), loc, rot, false, local_view_bits); cu = ob->data; cu->flag |= CU_PATH | CU_3D; - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, ob, 0); ED_object_new_primitive_matrix(C, ob, loc, rot, mat); BLI_addtail(&cu->editnurb->nurbs, ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia)); if (!enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); } } else { @@ -900,7 +905,10 @@ void OBJECT_OT_camera_add(wmOperatorType *ot) static int object_metaball_add_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); bool newob = false; bool enter_editmode; ushort local_view_bits; @@ -931,7 +939,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -1017,7 +1025,11 @@ void OBJECT_OT_text_add(wmOperatorType *ot) static int object_armature_add_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + RegionView3D *rv3d = CTX_wm_region_view3d(C); bool newob = false; bool enter_editmode; @@ -1032,7 +1044,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) } if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) { obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits); - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, obedit, 0); newob = true; } else { @@ -1049,7 +1061,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 8b10a865a68..85522209e29 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -80,8 +80,10 @@ /** \name Constraint Data Accessors * \{ */ -/* If object is in posemode, return active bone constraints, else object constraints. No - * constraints are returned for a bone on an inactive bonelayer. */ +/** + * If object is in pose-mode, return active bone constraints, else object constraints. + * No constraints are returned for a bone on an inactive bone-layer. + */ ListBase *ED_object_constraint_active_list(Object *ob) { if (ob == NULL) { @@ -103,8 +105,10 @@ ListBase *ED_object_constraint_active_list(Object *ob) return NULL; } -/* Get the constraints for the active pose bone. Bone may be on an inactive bonelayer (unlike - * ED_object_constraint_active_list, such constraints are not excluded here). */ +/** + * Get the constraints for the active pose bone. Bone may be on an inactive bone-layer + * (unlike #ED_object_constraint_active_list, such constraints are not excluded here). + */ ListBase *ED_object_pose_constraint_list(const bContext *C) { bPoseChannel *pose_bone = CTX_data_pointer_get(C, "active_pose_bone").data; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 966aeed75ab..7e0df736228 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -769,14 +769,14 @@ bool ED_object_editmode_enter(bContext *C, int flag) static int editmode_toggle_exec(bContext *C, wmOperator *op) { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - const int mode_flag = OB_MODE_EDIT; - const bool is_mode_set = (CTX_data_edit_object(C) != NULL); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Object *obact = OBACT(view_layer); + const int mode_flag = OB_MODE_EDIT; + const bool is_mode_set = (obact->mode & mode_flag) != 0; + struct wmMsgBus *mbus = CTX_wm_message_bus(C); if (!is_mode_set) { if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) { @@ -785,7 +785,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) } if (!is_mode_set) { - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, obact, 0); if (obact->mode & mode_flag) { FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) { if ((ob != obact) && (ob->type == obact->type)) { @@ -796,7 +796,8 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) } } else { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obact, EM_FREEDATA); + if ((obact->mode & mode_flag) == 0) { FOREACH_OBJECT_BEGIN (view_layer, ob) { if ((ob != obact) && (ob->type == obact->type)) { @@ -859,6 +860,9 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) static int posemode_exec(bContext *C, wmOperator *op) { struct wmMsgBus *mbus = CTX_wm_message_bus(C); + struct Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Base *base = CTX_data_active_base(C); /* If the base is NULL it means we have an active object, but the object itself is hidden. */ @@ -880,16 +884,17 @@ static int posemode_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } - if (obact == CTX_data_edit_object(C)) { - ED_object_editmode_exit(C, EM_FREEDATA); - is_mode_set = false; + { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obact == obedit) { + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); + is_mode_set = false; + } } if (is_mode_set) { bool ok = ED_object_posemode_exit(C, obact); if (ok) { - struct Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); FOREACH_OBJECT_BEGIN (view_layer, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) { ED_object_posemode_exit_ex(bmain, ob); @@ -901,9 +906,7 @@ static int posemode_exec(bContext *C, wmOperator *op) else { bool ok = ED_object_posemode_enter(C, obact); if (ok) { - struct Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); + const View3D *v3d = CTX_wm_view3d(C); FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) && (!ID_IS_LINKED(ob))) { diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index 0998280c381..2b9d9aaa0e1 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -30,10 +30,6 @@ set(INC ../../../../intern/mantaflow/extern ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC dynamicpaint_ops.c particle_boids.c @@ -74,6 +70,5 @@ if(WITH_BULLET) add_definitions(-DWITH_BULLET) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_physics "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/render/CMakeLists.txt b/source/blender/editors/render/CMakeLists.txt index 7f7748bf52f..642e92592f1 100644 --- a/source/blender/editors/render/CMakeLists.txt +++ b/source/blender/editors/render/CMakeLists.txt @@ -34,10 +34,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC render_internal.c render_opengl.c @@ -61,7 +57,6 @@ else() ) endif() -add_definitions(${GL_DEFINITIONS}) if(WITH_FREESTYLE) list(APPEND INC diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 25b4ddc15fd..509097c7a70 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -604,6 +604,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL) { image_buffer_rect_update(rj, rr, ibuf, &rj->iuser, renrect, viewname); } + ima->gpuflag |= IMA_GPU_REFRESH; /* make jobs timer to send notifier */ *(rj->do_update) = true; diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index dc355148ad3..1de5ad729c5 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -33,10 +33,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC area.c area_query.c @@ -64,6 +60,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_screen "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 51cfb912722..930f9890dd9 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -36,10 +36,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC paint_cursor.c paint_curve.c @@ -90,6 +86,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_sculpt_paint "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 3d8c718c8a9..55abb269660 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -142,7 +142,7 @@ typedef struct LoadTexData { ViewContext *vc; MTex *mtex; - GLubyte *buffer; + uchar *buffer; bool col; struct ImagePool *pool; @@ -160,7 +160,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata, ViewContext *vc = data->vc; MTex *mtex = data->mtex; - GLubyte *buffer = data->buffer; + uchar *buffer = data->buffer; const bool col = data->col; struct ImagePool *pool = data->pool; @@ -230,7 +230,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata, /* Clamp to avoid precision overflow. */ CLAMP(avg, 0.0f, 1.0f); - buffer[index] = 255 - (GLubyte)(255 * avg); + buffer[index] = 255 - (uchar)(255 * avg); } } else { @@ -254,7 +254,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex; ePaintOverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags(); - GLubyte *buffer = NULL; + uchar *buffer = NULL; int size; bool refresh; @@ -309,10 +309,10 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima target->old_col = col; } if (col) { - buffer = MEM_mallocN(sizeof(GLubyte) * size * size * 4, "load_tex"); + buffer = MEM_mallocN(sizeof(uchar) * size * size * 4, "load_tex"); } else { - buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex"); + buffer = MEM_mallocN(sizeof(uchar) * size * size, "load_tex"); } pool = BKE_image_pool_new(); @@ -381,7 +381,7 @@ static void load_tex_cursor_task_cb(void *__restrict userdata, LoadTexData *data = userdata; Brush *br = data->br; - GLubyte *buffer = data->buffer; + uchar *buffer = data->buffer; const int size = data->size; @@ -398,7 +398,7 @@ static void load_tex_cursor_task_cb(void *__restrict userdata, /* Falloff curve. */ float avg = BKE_brush_curve_strength_clamped(br, len, 1.0f); - buffer[index] = (GLubyte)(255 * avg); + buffer[index] = (uchar)(255 * avg); } else { buffer[index] = 0; @@ -411,7 +411,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) bool init; ePaintOverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags(); - GLubyte *buffer = NULL; + uchar *buffer = NULL; int size; const bool refresh = !cursor_snap.overlay_texture || @@ -452,7 +452,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) cursor_snap.size = size; } - buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex"); + buffer = MEM_mallocN(sizeof(uchar) * size * size, "load_tex"); BKE_curvemapping_init(br->curve); diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c index f07d22ed639..9b4b5b8d1e2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c @@ -36,6 +36,7 @@ #include "BKE_brush.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" @@ -58,6 +59,7 @@ #include "ED_object.h" #include "ED_screen.h" #include "ED_sculpt.h" +#include "ED_undo.h" #include "ED_view3d.h" #include "paint_intern.h" #include "sculpt_intern.h" @@ -285,11 +287,17 @@ void sculpt_dynamic_topology_disable_with_undo(Main *bmain, Object *ob) { SculptSession *ss = ob->sculpt; - if (ss->bm) { - SCULPT_undo_push_begin("Dynamic topology disable"); - SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END); + if (ss->bm != NULL) { + /* May be false in background mode. */ + const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true; + if (use_undo) { + SCULPT_undo_push_begin("Dynamic topology disable"); + SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END); + } SCULPT_dynamic_topology_disable_ex(bmain, depsgraph, scene, ob, NULL); - SCULPT_undo_push_end(); + if (use_undo) { + SCULPT_undo_push_end(); + } } } @@ -300,10 +308,16 @@ static void sculpt_dynamic_topology_enable_with_undo(Main *bmain, { SculptSession *ss = ob->sculpt; if (ss->bm == NULL) { - SCULPT_undo_push_begin("Dynamic topology enable"); + /* May be false in background mode. */ + const bool use_undo = G.background ? (ED_undo_stack_get() != NULL) : true; + if (use_undo) { + SCULPT_undo_push_begin("Dynamic topology enable"); + } SCULPT_dynamic_topology_enable_ex(bmain, depsgraph, scene, ob); - SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); - SCULPT_undo_push_end(); + if (use_undo) { + SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); + SCULPT_undo_push_end(); + } } } diff --git a/source/blender/editors/space_action/CMakeLists.txt b/source/blender/editors/space_action/CMakeLists.txt index 6c43f8b9549..10dcc77fc24 100644 --- a/source/blender/editors/space_action/CMakeLists.txt +++ b/source/blender/editors/space_action/CMakeLists.txt @@ -28,10 +28,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC action_buttons.c action_data.c @@ -49,6 +45,5 @@ set(LIB bf_blenlib ) -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_action "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_api/CMakeLists.txt b/source/blender/editors/space_api/CMakeLists.txt index d948d84f1c3..573afb76f0e 100644 --- a/source/blender/editors/space_api/CMakeLists.txt +++ b/source/blender/editors/space_api/CMakeLists.txt @@ -20,6 +20,7 @@ set(INC ../io ../../blenkernel ../../blenlib + ../../gpu ../../makesdna ../../makesrna ../../windowmanager diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 29ad314cd65..2a18ffafc6c 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -33,6 +33,8 @@ #include "BKE_context.h" #include "BKE_screen.h" +#include "GPU_state.h" + #include "UI_interface.h" #include "UI_view2d.h" @@ -269,12 +271,18 @@ void ED_region_draw_cb_exit(ARegionType *art, void *handle) void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type) { RegionDrawCB *rdc; + bool has_drawn_something = false; for (rdc = region->type->drawcalls.first; rdc; rdc = rdc->next) { if (rdc->type == type) { rdc->draw(C, region, rdc->customdata); + has_drawn_something = true; } } + if (has_drawn_something) { + /* This is needed until we get rid of BGL which can change the states we are tracking. */ + GPU_force_state(); + } } /* ********************* space template *********************** */ diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt index 75d91174470..ce0787dbdb9 100644 --- a/source/blender/editors/space_buttons/CMakeLists.txt +++ b/source/blender/editors/space_buttons/CMakeLists.txt @@ -28,10 +28,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC buttons_context.c buttons_ops.c @@ -48,7 +44,6 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index 2ea4bc97d18..8c7f59d61dd 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -33,10 +33,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC clip_buttons.c clip_dopesheet_draw.c @@ -68,7 +64,6 @@ set(LIB bf_blenlib ) -add_definitions(${GL_DEFINITIONS}) if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) diff --git a/source/blender/editors/space_console/CMakeLists.txt b/source/blender/editors/space_console/CMakeLists.txt index 33934832ccc..e5aedd0d0de 100644 --- a/source/blender/editors/space_console/CMakeLists.txt +++ b/source/blender/editors/space_console/CMakeLists.txt @@ -28,10 +28,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC console_draw.c console_ops.c @@ -49,6 +45,5 @@ if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_console "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt index 84df11ea39c..dcacf5e2504 100644 --- a/source/blender/editors/space_file/CMakeLists.txt +++ b/source/blender/editors/space_file/CMakeLists.txt @@ -33,10 +33,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC file_draw.c file_ops.c @@ -95,7 +91,6 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 44131693628..b459c02d9e5 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -39,6 +39,7 @@ struct View2D; void file_calc_previews(const bContext *C, ARegion *region); void file_draw_list(const bContext *C, ARegion *region); +void file_draw_check_ex(bContext *C, struct ScrArea *area); void file_draw_check(bContext *C); void file_draw_check_cb(bContext *C, void *arg1, void *arg2); bool file_draw_check_exists(SpaceFile *sfile); @@ -80,13 +81,13 @@ void file_filename_enter_handle(bContext *C, void *arg_unused, void *arg_but); int file_highlight_set(struct SpaceFile *sfile, struct ARegion *region, int mx, int my); void file_sfile_filepath_set(struct SpaceFile *sfile, const char *filepath); -void file_sfile_to_operator_ex(bContext *C, +void file_sfile_to_operator_ex(struct Main *bmain, struct wmOperator *op, struct SpaceFile *sfile, char *filepath); -void file_sfile_to_operator(bContext *C, struct wmOperator *op, struct SpaceFile *sfile); +void file_sfile_to_operator(struct Main *bmain, struct wmOperator *op, struct SpaceFile *sfile); -void file_operator_to_sfile(bContext *C, struct SpaceFile *sfile, struct wmOperator *op); +void file_operator_to_sfile(struct Main *bmain, struct SpaceFile *sfile, struct wmOperator *op); /* filesel.c */ void fileselect_file_set(SpaceFile *sfile, const int index); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 8c4b2a1b8a6..b3587fc7f97 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -1432,9 +1432,8 @@ void FILE_OT_cancel(struct wmOperatorType *ot) /** \name Operator Utilities * \{ */ -void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, char *filepath) +void file_sfile_to_operator_ex(Main *bmain, wmOperator *op, SpaceFile *sfile, char *filepath) { - Main *bmain = CTX_data_main(C); PropertyRNA *prop; /* XXX, not real length */ @@ -1507,16 +1506,15 @@ void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, ch } } } -void file_sfile_to_operator(bContext *C, wmOperator *op, SpaceFile *sfile) +void file_sfile_to_operator(Main *bmain, wmOperator *op, SpaceFile *sfile) { - char filepath[FILE_MAX]; + char filepath_dummy[FILE_MAX]; - file_sfile_to_operator_ex(C, op, sfile, filepath); + file_sfile_to_operator_ex(bmain, op, sfile, filepath_dummy); } -void file_operator_to_sfile(bContext *C, SpaceFile *sfile, wmOperator *op) +void file_operator_to_sfile(Main *bmain, SpaceFile *sfile, wmOperator *op) { - Main *bmain = CTX_data_main(C); PropertyRNA *prop; /* If neither of the above are set, split the filepath back */ @@ -1569,25 +1567,37 @@ void file_sfile_filepath_set(SpaceFile *sfile, const char *filepath) } } -void file_draw_check(bContext *C) +void file_draw_check_ex(bContext *C, ScrArea *area) { - SpaceFile *sfile = CTX_wm_space_file(C); + /* May happen when manipulating non-active spaces. */ + if (UNLIKELY(area->spacetype != SPACE_FILE)) { + return; + } + SpaceFile *sfile = area->spacedata.first; wmOperator *op = sfile->op; if (op) { /* fail on reload */ if (op->type->check) { - file_sfile_to_operator(C, op, sfile); + Main *bmain = CTX_data_main(C); + file_sfile_to_operator(bmain, op, sfile); /* redraw */ if (op->type->check(C, op)) { - file_operator_to_sfile(C, sfile, op); + file_operator_to_sfile(bmain, sfile, op); /* redraw, else the changed settings wont get updated */ - ED_area_tag_redraw(CTX_wm_area(C)); + ED_area_tag_redraw(area); } } } } +void file_draw_check(bContext *C) +{ + SpaceFile *sfile = CTX_wm_space_file(C); + ScrArea *area = CTX_wm_area(C); + file_draw_check_ex(C, area); +} + /* for use with; UI_block_func_set */ void file_draw_check_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) { @@ -1675,7 +1685,7 @@ static int file_exec(bContext *C, wmOperator *exec_op) sfile->op = NULL; - file_sfile_to_operator_ex(C, op, sfile, filepath); + file_sfile_to_operator_ex(bmain, op, sfile, filepath); if (BLI_exists(sfile->params->dir)) { fsmenu_insert_entry(ED_fsmenu_get(), @@ -2091,6 +2101,7 @@ void FILE_OT_smoothscroll(wmOperatorType *ot) static int filepath_drop_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); if (sfile) { @@ -2105,7 +2116,7 @@ static int filepath_drop_exec(bContext *C, wmOperator *op) file_sfile_filepath_set(sfile, filepath); if (sfile->op) { - file_sfile_to_operator(C, sfile->op, sfile); + file_sfile_to_operator(bmain, sfile->op, sfile); file_draw_check(C); } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 306d6cba50e..9fc4e8936f4 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -828,13 +828,23 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *region) return sfile->layout; } -void ED_file_change_dir(bContext *C) +/** + * Support updating the directory even when this isn't the active space + * needed so RNA properties update function isn't context sensitive, see T70255. + */ +void ED_file_change_dir_ex(bContext *C, bScreen *screen, ScrArea *area) { - wmWindowManager *wm = CTX_wm_manager(C); - SpaceFile *sfile = CTX_wm_space_file(C); - + /* May happen when manipulating non-active spaces. */ + if (UNLIKELY(area->spacetype != SPACE_FILE)) { + return; + } + SpaceFile *sfile = area->spacedata.first; if (sfile->params) { - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + wmWindowManager *wm = CTX_wm_manager(C); + Scene *scene = WM_windows_scene_get_from_screen(wm, screen); + if (LIKELY(scene != NULL)) { + ED_fileselect_clear(wm, scene, sfile); + } /* Clear search string, it is very rare to want to keep that filter while changing dir, * and usually very annoying to keep it actually! */ @@ -853,10 +863,17 @@ void ED_file_change_dir(bContext *C) folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - file_draw_check(C); + file_draw_check_ex(C, area); } } +void ED_file_change_dir(bContext *C) +{ + bScreen *screen = CTX_wm_screen(C); + ScrArea *area = CTX_wm_area(C); + ED_file_change_dir_ex(C, screen, area); +} + int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file) { int match = 0; diff --git a/source/blender/editors/space_graph/CMakeLists.txt b/source/blender/editors/space_graph/CMakeLists.txt index 8170c920990..fd5c5863608 100644 --- a/source/blender/editors/space_graph/CMakeLists.txt +++ b/source/blender/editors/space_graph/CMakeLists.txt @@ -29,10 +29,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC graph_buttons.c graph_draw.c @@ -67,6 +63,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_graph "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index ba3ed620ff1..47f910402fe 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -423,7 +423,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) col = uiLayoutColumn(layout, true); /* keyframe itself */ { - uiItemL_respect_property_split(col, IFACE_("Key Frame"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Key Frame"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -441,7 +441,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) 0, NULL); - uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -468,7 +468,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) { col = uiLayoutColumn(layout, true); - uiItemL_respect_property_split(col, IFACE_("Left Handle Type"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Left Handle Type"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, @@ -487,7 +487,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) "Type of left handle"); UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); - uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -506,7 +506,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) NULL); UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); - uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -532,7 +532,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) /* NOTE: special update callbacks are needed on the coords here due to T39911 */ col = uiLayoutColumn(layout, true); - uiItemL_respect_property_split(col, IFACE_("Right Handle Type"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Right Handle Type"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, @@ -551,7 +551,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) "Type of right handle"); UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); - uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, @@ -570,7 +570,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) NULL); UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); - uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE, NULL); + uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index 24ec7a89397..96aab8b5d1a 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -35,10 +35,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC image_buttons.c image_draw.c @@ -81,6 +77,5 @@ if(WITH_IMAGE_CINEON) add_definitions(-DWITH_CINEON) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_image "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 058436a46bf..60dd134646d 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -55,6 +55,7 @@ #include "BIF_glutil.h" +#include "GPU_framebuffer.h" #include "GPU_immediate.h" #include "GPU_immediate_util.h" #include "GPU_matrix.h" @@ -570,7 +571,8 @@ static void draw_image_buffer(const bContext *C, float zoomy) { /* Image are still drawn in display space. */ - glDisable(GL_FRAMEBUFFER_SRGB); + GPUFrameBuffer *fb = GPU_framebuffer_active_get(); + GPU_framebuffer_bind_no_srgb(fb); int x, y; int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf); @@ -660,7 +662,7 @@ static void draw_image_buffer(const bContext *C, } } - glEnable(GL_FRAMEBUFFER_SRGB); + GPU_framebuffer_bind(fb); } static void draw_image_buffer_repeated(const bContext *C, @@ -865,7 +867,7 @@ void draw_image_main(const bContext *C, ARegion *region) Image *ima; ImBuf *ibuf; float zoomx, zoomy; - bool show_viewer, show_render, show_paint, show_stereo3d, show_multilayer; + bool show_viewer, show_stereo3d, show_multilayer; void *lock; /* XXX can we do this in refresh? */ @@ -898,9 +900,6 @@ void draw_image_main(const bContext *C, ARegion *region) } show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0; - show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0; - show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && - (show_render == false)); show_stereo3d = (ima && BKE_image_is_stereo(ima) && (sima->iuser.flag & IMA_SHOW_STEREO)); show_multilayer = ima && BKE_image_is_multilayer(ima); @@ -998,16 +997,32 @@ void draw_image_main(const bContext *C, ARegion *region) } draw_udim_tile_grids(region, sima, ima); - - /* paint helpers */ - if (show_paint) { - draw_image_paint_helpers(C, region, scene, zoomx, zoomy); - } + draw_image_main_helpers(C, region); if (show_viewer) { BLI_thread_unlock(LOCK_DRAW_IMAGE); } +} + +void draw_image_main_helpers(const bContext *C, ARegion *region) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + Image *ima; + float zoomx, zoomy; + bool show_viewer, show_render, show_paint; + ima = ED_space_image(sima); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); + + show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0; + show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0; + show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) && + (show_render == false)); + /* paint helpers */ + if (show_paint) { + draw_image_paint_helpers(C, region, scene, zoomx, zoomy); + } /* render info */ if (ima && show_render) { draw_render_info(C, sima->iuser.scene, ima, region, zoomx, zoomy); diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index e6f5988aed8..100556ad29a 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -37,6 +37,7 @@ extern const char *image_context_dir[]; /* doc access */ /* image_draw.c */ void draw_image_main(const struct bContext *C, struct ARegion *region); +void draw_image_main_helpers(const struct bContext *C, struct ARegion *region); void draw_image_cache(const struct bContext *C, struct ARegion *region); void draw_image_grease_pencil(struct bContext *C, bool onlyv2d); void draw_image_sample_line(struct SpaceImage *sima); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index aa3f6446d51..f1becd5f027 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -76,6 +76,7 @@ #include "GPU_framebuffer.h" #include "GPU_viewport.h" +#include "DRW_engine.h" #include "DRW_engine_types.h" #include "image_intern.h" @@ -638,8 +639,6 @@ static void image_main_region_draw(const bContext *C, ARegion *region) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View2D *v2d = ®ion->v2d; - // View2DScrollers *scrollers; - float col[3]; GPUViewport *viewport = WM_draw_region_get_viewport(region); GPUFrameBuffer *framebuffer_default, *framebuffer_overlay; @@ -647,35 +646,14 @@ static void image_main_region_draw(const bContext *C, ARegion *region) framebuffer_default = GPU_viewport_framebuffer_default_get(viewport); framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport); - GPU_framebuffer_bind(framebuffer_default); - GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); - - GPU_framebuffer_bind(framebuffer_overlay); - /* XXX not supported yet, disabling for now */ scene->r.scemode &= ~R_COMP_CROP; - /* clear and setup matrix */ - UI_GetThemeColor3fv(TH_BACK, col); - srgb_to_linearrgb_v3_v3(col, col); - GPU_clear_color(col[0], col[1], col[2], 1.0f); - GPU_depth_test(GPU_DEPTH_NONE); - image_user_refresh_scene(C, sima); /* we set view2d from own zoom and offset each time */ image_main_region_set_view2d(sima, region); - /* we draw image in pixelspace */ - draw_image_main(C, region); - - /* and uvs in 0.0-1.0 space */ - UI_view2d_view_ortho(v2d); - - ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW); - - ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph); - /* check for mask (delay draw) */ if (ED_space_image_show_uvedit(sima, obedit)) { show_uvedit = true; @@ -687,21 +665,52 @@ static void image_main_region_draw(const bContext *C, ARegion *region) show_curve = true; } - ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); + /* we draw image in pixelspace */ + if (!U.experimental.use_image_editor_legacy_drawing) { + DRW_draw_view(C); + draw_image_main_helpers(C, region); - if (sima->flag & SI_SHOW_GPENCIL) { - /* Grease Pencil too (in addition to UV's) */ - draw_image_grease_pencil((bContext *)C, true); + /* sample line */ + UI_view2d_view_ortho(v2d); + draw_image_sample_line(sima); + UI_view2d_view_restore(C); } + else { + GPU_framebuffer_bind(framebuffer_default); + GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); + + GPU_framebuffer_bind(framebuffer_overlay); + + float col[3]; + /* clear and setup matrix */ + UI_GetThemeColor3fv(TH_BACK, col); + srgb_to_linearrgb_v3_v3(col, col); + GPU_clear_color(col[0], col[1], col[2], 1.0f); + GPU_depth_test(GPU_DEPTH_NONE); + draw_image_main(C, region); + + /* and uvs in 0.0-1.0 space */ + UI_view2d_view_ortho(v2d); + + ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW); - /* sample line */ - draw_image_sample_line(sima); + ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph); - UI_view2d_view_restore(C); + ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); - if (sima->flag & SI_SHOW_GPENCIL) { - /* draw Grease Pencil - screen space only */ - draw_image_grease_pencil((bContext *)C, false); + if (sima->flag & SI_SHOW_GPENCIL) { + /* Grease Pencil too (in addition to UV's) */ + draw_image_grease_pencil((bContext *)C, true); + } + /* sample line */ + draw_image_sample_line(sima); + + UI_view2d_view_restore(C); + + if (sima->flag & SI_SHOW_GPENCIL) { + /* draw Grease Pencil - screen space only */ + draw_image_grease_pencil((bContext *)C, false); + } } if (mask) { @@ -741,7 +750,7 @@ static void image_main_region_draw(const bContext *C, ARegion *region) C); } - if (show_uvedit || mask || show_curve) { + if ((show_uvedit || mask || show_curve) && U.experimental.use_image_editor_legacy_drawing) { UI_view2d_view_ortho(v2d); ED_image_draw_cursor(region, sima->cursor); UI_view2d_view_restore(C); diff --git a/source/blender/editors/space_info/CMakeLists.txt b/source/blender/editors/space_info/CMakeLists.txt index ad410e0aade..b6df07eec4e 100644 --- a/source/blender/editors/space_info/CMakeLists.txt +++ b/source/blender/editors/space_info/CMakeLists.txt @@ -33,10 +33,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC info_draw.c info_ops.c @@ -56,6 +52,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_info "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_nla/CMakeLists.txt b/source/blender/editors/space_nla/CMakeLists.txt index 60152bffaf4..9a94d28c604 100644 --- a/source/blender/editors/space_nla/CMakeLists.txt +++ b/source/blender/editors/space_nla/CMakeLists.txt @@ -29,9 +29,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC nla_buttons.c @@ -54,6 +51,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_nla "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index f8c30f9a688..fc831bf8490 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -34,9 +34,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC drawnode.c @@ -75,6 +72,5 @@ if(WITH_OPENIMAGEDENOISE) add_definitions(-DWITH_OPENIMAGEDENOISE) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index 616915dbc2c..db38839f959 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -30,9 +30,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC outliner_collections.c @@ -60,6 +57,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_outliner "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_script/CMakeLists.txt b/source/blender/editors/space_script/CMakeLists.txt index 0bd2a01a151..f2dd39ea13d 100644 --- a/source/blender/editors/space_script/CMakeLists.txt +++ b/source/blender/editors/space_script/CMakeLists.txt @@ -27,9 +27,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC script_edit.c @@ -49,6 +46,5 @@ if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_script "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index 8105891e157..caf75349454 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -32,9 +32,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC sequencer_add.c @@ -73,6 +70,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_sequencer "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_statusbar/CMakeLists.txt b/source/blender/editors/space_statusbar/CMakeLists.txt index ad4c060a1f6..a0f3afecaf9 100644 --- a/source/blender/editors/space_statusbar/CMakeLists.txt +++ b/source/blender/editors/space_statusbar/CMakeLists.txt @@ -29,9 +29,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC space_statusbar.c @@ -42,6 +39,5 @@ set(LIB bf_blenlib ) -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_statusbar "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt index 740fc9948ef..abd7620ea2b 100644 --- a/source/blender/editors/space_text/CMakeLists.txt +++ b/source/blender/editors/space_text/CMakeLists.txt @@ -29,9 +29,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC space_text.c @@ -56,7 +53,6 @@ set(LIB bf_blenlib ) -add_definitions(${GL_DEFINITIONS}) if(WITH_PYTHON) list(APPEND INC diff --git a/source/blender/editors/space_topbar/CMakeLists.txt b/source/blender/editors/space_topbar/CMakeLists.txt index d56e1da334d..15e71e2296d 100644 --- a/source/blender/editors/space_topbar/CMakeLists.txt +++ b/source/blender/editors/space_topbar/CMakeLists.txt @@ -29,9 +29,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC space_topbar.c @@ -40,6 +37,5 @@ set(SRC set(LIB ) -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_topbar "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index f2536cfac62..f4d6f7e322c 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -38,9 +38,6 @@ set(INC ${CMAKE_CURRENT_BINARY_DIR}/../../makesdna/intern ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC drawobject.c @@ -85,7 +82,6 @@ if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() -add_definitions(${GL_DEFINITIONS}) if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index f3300f21628..0b5daece556 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1065,7 +1065,7 @@ static void draw_rotation_guide(const RegionView3D *rv3d) float o[3]; /* center of rotation */ float end[3]; /* endpoints for drawing */ - GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */ + uchar color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */ negate_v3_v3(o, rv3d->ofs); diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index b284ba0af2d..f905e96dbdd 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -33,9 +33,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC transform.c @@ -125,6 +122,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 84eac3bbf8f..0eaae7f17cd 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -163,41 +163,6 @@ void constraintNumInput(TransInfo *t, float vec[3]) } } -static void postConstraintChecks(TransInfo *t, float vec[3]) -{ - mul_m3_v3(t->spacemtx_inv, vec); - - transform_snap_increment(t, vec); - - if (t->flag & T_NULL_ONE) { - if (!(t->con.mode & CON_AXIS0)) { - vec[0] = 1.0f; - } - - if (!(t->con.mode & CON_AXIS1)) { - vec[1] = 1.0f; - } - - if (!(t->con.mode & CON_AXIS2)) { - vec[2] = 1.0f; - } - } - - if (applyNumInput(&t->num, vec)) { - constraintNumInput(t, vec); - removeAspectRatio(t, vec); - } - - /* If `t->values` is operator param, use that directly but not if snapping is forced */ - if (t->flag & T_INPUT_IS_VALUES_FINAL && (t->tsnap.status & SNAP_FORCED) == 0) { - copy_v3_v3(vec, t->values); - constraintValuesFinal(t, vec); - /* inverse transformation at the end */ - } - - mul_m3_v3(t->spacemtx, vec); -} - static void viewAxisCorrectCenter(const TransInfo *t, float t_con_center[3]) { if (t->spacetype == SPACE_VIEW3D) { @@ -432,15 +397,22 @@ static void applyAxisConstraintVec( { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { + bool is_snap_to_point = false, is_snap_to_edge = false, is_snap_to_face = false; mul_m3_v3(t->con.pmtx, out); - bool is_snap_to_edge = false, is_snap_to_face = false; + if (activeSnap(t)) { - is_snap_to_edge = (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) != 0; - is_snap_to_face = (t->tsnap.snapElem & SCE_SNAP_MODE_FACE) != 0; + if (validSnap(t)) { + is_snap_to_point = (t->tsnap.snapElem & SCE_SNAP_MODE_VERTEX) != 0; + is_snap_to_edge = (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE) != 0; + is_snap_to_face = (t->tsnap.snapElem & SCE_SNAP_MODE_FACE) != 0; + } + else if (t->tsnap.snapElem & SCE_SNAP_MODE_GRID) { + is_snap_to_point = true; + } } /* With snap points, a projection is alright, no adjustments needed. */ - if (!validSnap(t) || is_snap_to_edge || is_snap_to_face) { + if (!is_snap_to_point || is_snap_to_edge || is_snap_to_face) { const int dims = getConstraintSpaceDimension(t); if (dims == 2) { if (!is_zero_v3(out)) { @@ -486,7 +458,6 @@ static void applyAxisConstraintVec( } } } - postConstraintChecks(t, out); } } diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 7ad54a56545..06ab60d992c 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1296,6 +1296,9 @@ void mesh_customdatacorrect_init(TransInfo *t) use_merge_group = (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_KEEP_CONNECTED) != 0; } } + else { + return; + } FOREACH_TRANS_DATA_CONTAINER (t, tc) { mesh_customdatacorrect_init_container(tc, use_merge_group); diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 141f9acdeb4..d2474d78387 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -93,22 +93,29 @@ static void applySeqSlideValue(TransInfo *t, const float val[2]) static void applySeqSlide(TransInfo *t, const int mval[2]) { char str[UI_MAX_DRAW_STR]; + float values_final[3]; snapSequenceBounds(t, mval); - - if (t->con.mode & CON_APPLY) { - float tvec[3]; - t->con.applyVec(t, NULL, NULL, t->values, tvec); - copy_v3_v3(t->values_final, tvec); + if (applyNumInput(&t->num, values_final)) { + if (t->con.mode & CON_APPLY) { + if (t->con.mode & CON_AXIS0) { + /* Do nothing. */ + } + else { + mul_v2_v2fl(values_final, t->spacemtx[1], values_final[0]); + } + } + } + else if (t->con.mode & CON_APPLY) { + t->con.applyVec(t, NULL, NULL, t->values, values_final); } else { - // transform_snap_increment(t, t->values); - applyNumInput(&t->num, t->values); - copy_v3_v3(t->values_final, t->values); + copy_v2_v2(values_final, t->values); } - t->values_final[0] = floorf(t->values_final[0] + 0.5f); - t->values_final[1] = floorf(t->values_final[1] + 0.5f); + values_final[0] = floorf(values_final[0] + 0.5f); + values_final[1] = floorf(values_final[1] + 0.5f); + copy_v2_v2(t->values_final, values_final); headerSeqSlide(t, t->values_final, str); applySeqSlideValue(t, t->values_final); diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 866b9d921c8..758a6d04f11 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -360,42 +360,49 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) if (t->flag & T_INPUT_IS_VALUES_FINAL) { mul_v3_m3v3(global_dir, t->spacemtx, t->values); } + else if (applyNumInput(&t->num, global_dir)) { + if (t->con.mode & CON_APPLY) { + if (t->con.mode & CON_AXIS0) { + /* Do nothing. */ + } + else if (t->con.mode & CON_AXIS1) { + mul_v3_v3fl(global_dir, t->spacemtx[1], global_dir[0]); + } + else if (t->con.mode & CON_AXIS2) { + mul_v3_v3fl(global_dir, t->spacemtx[2], global_dir[0]); + } + } + } else { copy_v3_v3(global_dir, t->values); - if (applyNumInput(&t->num, global_dir)) { - removeAspectRatio(t, global_dir); + + t->tsnap.snapElem = 0; + applySnapping(t, global_dir); + transform_snap_grid(t, global_dir); + + if (t->con.mode & CON_APPLY) { + float in[3]; + copy_v3_v3(in, global_dir); + t->con.applyVec(t, NULL, NULL, in, global_dir); } - else { - applySnapping(t, global_dir); - if (!validSnap(t) && !(t->con.mode & CON_APPLY)) { - float dist_sq = FLT_MAX; - if (transform_snap_grid(t, global_dir)) { - dist_sq = len_squared_v3v3(t->values, global_dir); - } + float incr_dir[3]; + mul_v3_m3v3(incr_dir, t->spacemtx_inv, global_dir); + if (transform_snap_increment(t, incr_dir)) { + mul_v3_m3v3(incr_dir, t->spacemtx, incr_dir); - /* Check the snap distance to the initial value to work with mixed snap. */ - float increment_loc[3]; - copy_v3_v3(increment_loc, t->values); - if (transform_snap_increment(t, increment_loc)) { - if ((dist_sq == FLT_MAX) || (len_squared_v3v3(t->values, increment_loc) < dist_sq)) { - copy_v3_v3(global_dir, increment_loc); - } - } + /* Test for mixed snap with grid. */ + float snap_dist_sq = FLT_MAX; + if (t->tsnap.snapElem != 0) { + snap_dist_sq = len_squared_v3v3(t->values, global_dir); + } + if ((snap_dist_sq == FLT_MAX) || (len_squared_v3v3(global_dir, incr_dir) < snap_dist_sq)) { + copy_v3_v3(global_dir, incr_dir); } } } - if (t->con.mode & CON_APPLY) { - float in[3]; - copy_v3_v3(in, global_dir); - t->con.applyVec(t, NULL, NULL, in, global_dir); - headerTranslation(t, global_dir, str); - } - else { - headerTranslation(t, global_dir, str); - } - + headerTranslation(t, global_dir, str); applyTranslationValue(t, global_dir); /* evil hack - redo translation if clipping needed */ diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 1813acadb9e..a546aabd095 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -464,6 +464,7 @@ void applySnapping(TransInfo *t, float *vec) void resetSnapping(TransInfo *t) { t->tsnap.status = 0; + t->tsnap.snapElem = 0; t->tsnap.align = false; t->tsnap.project = 0; t->tsnap.mode = 0; @@ -1412,12 +1413,12 @@ void snapSequenceBounds(TransInfo *t, const int mval[2]) t->values[0] = frame_near - frame_snap; } -static void snap_grid_apply_ex( +static void snap_grid_apply( TransInfo *t, const int max_index, const float grid_dist, const float loc[3], float r_out[3]) { + BLI_assert(max_index <= 2); const float *center_global = t->center_global; const float *asp = t->aspect; - bool use_local_axis = false; /* use a fallback for cursor selection, * this isn't useful as a global center for absolute grid snapping @@ -1427,74 +1428,27 @@ static void snap_grid_apply_ex( center_global = cd->global; } - if (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) { - use_local_axis = true; + float in[3]; + if (t->con.mode & CON_APPLY) { + BLI_assert(t->tsnap.snapElem == 0); + t->con.applyVec(t, NULL, NULL, loc, in); + } + else { + copy_v3_v3(in, loc); } for (int i = 0; i <= max_index; i++) { - /* do not let unconstrained axis jump to absolute grid increments */ - if (!(t->con.mode & CON_APPLY) || t->con.mode & (CON_AXIS0 << i)) { - const float iter_fac = grid_dist * asp[i]; - - if (use_local_axis) { - float local_axis[3]; - float pos_on_axis[3]; - - copy_v3_v3(local_axis, t->spacemtx[i]); - copy_v3_v3(pos_on_axis, t->spacemtx[i]); - - /* amount of movement on axis from initial pos */ - mul_v3_fl(pos_on_axis, loc[i]); - - /* actual global position on axis */ - add_v3_v3(pos_on_axis, center_global); - - float min_dist = INFINITY; - for (int j = 0; j < 3; j++) { - if (fabs(local_axis[j]) < 0.01f) { - /* Ignore very small (normalized) axis changes */ - continue; - } - - /* closest point on grid */ - float grid_p = iter_fac * roundf(pos_on_axis[j] / iter_fac); - float dist_p = fabs((grid_p - pos_on_axis[j]) / local_axis[j]); - - /* The amount of distance needed to travel along the - * local axis to snap to the closest grid point */ - /* in the global j axis direction */ - float move_dist = (grid_p - center_global[j]) / local_axis[j]; - - if (dist_p < min_dist) { - min_dist = dist_p; - r_out[i] = move_dist; - } - } - } - else { - r_out[i] = iter_fac * roundf((loc[i] + center_global[i]) / iter_fac) - center_global[i]; - } - } + const float iter_fac = grid_dist * asp[i]; + r_out[i] = iter_fac * roundf((in[i] + center_global[i]) / iter_fac) - center_global[i]; } } -static void snap_grid_apply(TransInfo *t, int max_index, const float grid_dist, float *r_val) +bool transform_snap_grid(TransInfo *t, float *val) { - BLI_assert(t->tsnap.mode & SCE_SNAP_MODE_GRID); - BLI_assert(max_index <= 2); - - /* Early bailing out if no need to snap */ - if (grid_dist == 0.0f) { - return; + if (!activeSnap(t)) { + return false; } - /* absolute snapping on grid based on global center. - * for now only 3d view (others can be added if we want) */ - snap_grid_apply_ex(t, max_index, grid_dist, r_val, r_val); -} - -bool transform_snap_grid(TransInfo *t, float *val) -{ if ((!(t->tsnap.mode & SCE_SNAP_MODE_GRID)) || validSnap(t)) { /* Don't do grid snapping if there is a valid snap point. */ return false; @@ -1508,10 +1462,15 @@ bool transform_snap_grid(TransInfo *t, float *val) return false; } - float grid_dist = activeSnap(t) ? (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1] : - t->snap[0]; + float grid_dist = (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1]; + + /* Early bailing out if no need to snap */ + if (grid_dist == 0.0f) { + return false; + } - snap_grid_apply(t, t->idx_max, grid_dist, val); + snap_grid_apply(t, t->idx_max, grid_dist, val, val); + t->tsnap.snapElem = SCE_SNAP_MODE_GRID; return true; } diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 207606c2dcd..e05d1fedf6d 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -33,9 +33,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC ed_transverts.c @@ -106,7 +103,6 @@ set(SRC set(LIB ) -add_definitions(${GL_DEFINITIONS}) if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index a39234561c2..f1751ef8d27 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -31,9 +31,6 @@ set(INC ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC uvedit_buttons.c @@ -58,6 +55,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_uvedit "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index 497cb4a10a5..22f8f01be4b 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -76,6 +76,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_gpencil_modifiers "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 72dc610f3c8..b7ffa59538a 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -62,7 +62,6 @@ set(SRC intern/gpu_capabilities.cc intern/gpu_codegen.c intern/gpu_context.cc - intern/gpu_debug.cc intern/gpu_drawlist.cc intern/gpu_framebuffer.cc intern/gpu_immediate.cc @@ -113,10 +112,8 @@ set(SRC GPU_capabilities.h GPU_common.h GPU_context.h - GPU_debug.h GPU_drawlist.h GPU_framebuffer.h - GPU_glew.h GPU_immediate.h GPU_immediate_util.h GPU_index_buffer.h diff --git a/source/blender/gpu/GPU_capabilities.h b/source/blender/gpu/GPU_capabilities.h index b8a48735548..9d55fe73708 100644 --- a/source/blender/gpu/GPU_capabilities.h +++ b/source/blender/gpu/GPU_capabilities.h @@ -45,6 +45,8 @@ bool GPU_depth_blitting_workaround(void); bool GPU_use_main_context_workaround(void); bool GPU_crappy_amd_driver(void); +bool GPU_shader_image_load_store_support(void); + bool GPU_mem_stats_supported(void); void GPU_mem_stats_get(int *totalmem, int *freemem); diff --git a/source/blender/gpu/GPU_common.h b/source/blender/gpu/GPU_common.h index 8fd1baba2f7..1be74701176 100644 --- a/source/blender/gpu/GPU_common.h +++ b/source/blender/gpu/GPU_common.h @@ -32,10 +32,6 @@ # define TRUST_NO_ONE 1 #endif -#if defined(WITH_OPENGL) -# include <GL/glew.h> -#endif - #include "BLI_sys_types.h" #include <stdbool.h> #include <stdint.h> diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h index 5e872001267..a857736acd5 100644 --- a/source/blender/gpu/GPU_state.h +++ b/source/blender/gpu/GPU_state.h @@ -35,6 +35,14 @@ typedef enum eGPUWriteMask { ENUM_OPERATORS(eGPUWriteMask) +typedef enum eGPUBarrier { + GPU_BARRIER_NONE = 0, + GPU_BARRIER_SHADER_IMAGE_ACCESS = (1 << 0), + GPU_BARRIER_TEXTURE_FETCH = (1 << 1), +} eGPUBarrier; + +ENUM_OPERATORS(eGPUBarrier) + /** * Defines the fixed pipeline blending equation. * SRC is the output color from the shader. @@ -151,6 +159,10 @@ eGPUStencilTest GPU_stencil_test_get(void); void GPU_flush(void); void GPU_finish(void); +void GPU_apply_state(void); +void GPU_force_state(void); + +void GPU_memory_barrier(eGPUBarrier barrier); #ifdef __cplusplus } diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 2ce2ba093cf..99a7c6a5f0c 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -243,6 +243,10 @@ void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, cons void GPU_texture_unbind(GPUTexture *tex); void GPU_texture_unbind_all(void); +void GPU_texture_image_bind(GPUTexture *tex, int unit); +void GPU_texture_image_unbind(GPUTexture *tex); +void GPU_texture_image_unbind_all(void); + void GPU_texture_copy(GPUTexture *dst, GPUTexture *src); void GPU_texture_generate_mipmap(GPUTexture *tex); @@ -253,7 +257,6 @@ void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter); void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp); void GPU_texture_swizzle_set(GPUTexture *tex, const char swizzle[4]); -int GPU_texture_target(const GPUTexture *tex); int GPU_texture_width(const GPUTexture *tex); int GPU_texture_height(const GPUTexture *tex); int GPU_texture_orig_width(const GPUTexture *tex); diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h index 2af9929db35..36caee10072 100644 --- a/source/blender/gpu/GPU_vertex_buffer.h +++ b/source/blender/gpu/GPU_vertex_buffer.h @@ -139,6 +139,9 @@ GPUVertBufStatus GPU_vertbuf_get_status(const GPUVertBuf *verts); void GPU_vertbuf_use(GPUVertBuf *); +/* XXX do not use. */ +void GPU_vertbuf_update_sub(GPUVertBuf *verts, uint start, uint len, void *data); + /* Metrics */ uint GPU_vertbuf_get_memory_usage(void); diff --git a/source/blender/gpu/intern/gpu_capabilities.cc b/source/blender/gpu/intern/gpu_capabilities.cc index a79ce27ba63..63e29654e1c 100644 --- a/source/blender/gpu/intern/gpu_capabilities.cc +++ b/source/blender/gpu/intern/gpu_capabilities.cc @@ -102,6 +102,11 @@ bool GPU_crappy_amd_driver(void) return GCaps.broken_amd_driver; } +bool GPU_shader_image_load_store_support(void) +{ + return GCaps.shader_image_load_store_support; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/intern/gpu_capabilities_private.hh b/source/blender/gpu/intern/gpu_capabilities_private.hh index a51525fa932..abe5b706a7d 100644 --- a/source/blender/gpu/intern/gpu_capabilities_private.hh +++ b/source/blender/gpu/intern/gpu_capabilities_private.hh @@ -42,6 +42,7 @@ struct GPUCapabilities { int max_textures_geom = 0; int max_textures_frag = 0; bool mem_stats_support = false; + bool shader_image_load_store_support = false; /* OpenGL related workarounds. */ bool mip_render_workaround = false; bool depth_blitting_workaround = false; @@ -52,4 +53,4 @@ struct GPUCapabilities { extern GPUCapabilities GCaps; -} // namespace blender::gpu
\ No newline at end of file +} // namespace blender::gpu diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh index bc07bea4bb1..38f94b8dde9 100644 --- a/source/blender/gpu/intern/gpu_context_private.hh +++ b/source/blender/gpu/intern/gpu_context_private.hh @@ -46,7 +46,7 @@ class Context { Shader *shader = NULL; FrameBuffer *active_fb = NULL; GPUMatrixState *matrix_state = NULL; - GPUStateManager *state_manager = NULL; + StateManager *state_manager = NULL; Immediate *imm = NULL; /** diff --git a/source/blender/gpu/intern/gpu_debug.cc b/source/blender/gpu/intern/gpu_debug.cc deleted file mode 100644 index f179a241926..00000000000 --- a/source/blender/gpu/intern/gpu_debug.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2005 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup gpu - */ - -#include "BLI_compiler_attrs.h" -#include "BLI_sys_types.h" -#include "BLI_system.h" -#include "BLI_utildefines.h" - -#include "BKE_global.h" - -#include "GPU_debug.h" -#include "GPU_glew.h" -#include "intern/gpu_private.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -void GPU_print_error_debug(const char *str) -{ - if (G.debug & G_DEBUG) { - fprintf(stderr, "GPU: %s\n", str); - } -} diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc index 9c3a88e30f0..8d781978857 100644 --- a/source/blender/gpu/intern/gpu_immediate.cc +++ b/source/blender/gpu/intern/gpu_immediate.cc @@ -416,7 +416,7 @@ static void immEndVertex(void) /* and move on to the next vertex */ printf("copying %s from vertex %u to %u\n", a->name, imm->vertex_idx - 1, imm->vertex_idx); #endif - GLubyte *data = imm->vertex_data + a->offset; + uchar *data = imm->vertex_data + a->offset; memcpy(data, data - imm->vertex_format.stride, a->sz); /* TODO: consolidate copy of adjacent attributes */ } diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index 769b52bf593..c76ce0f1094 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -28,7 +28,6 @@ #include <string.h> #include "GPU_framebuffer.h" -#include "GPU_glew.h" #include "GPU_immediate.h" #include "GPU_select.h" #include "GPU_state.h" diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh index f76339d3adb..fce6fda5f14 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.hh +++ b/source/blender/gpu/intern/gpu_shader_interface.hh @@ -63,6 +63,7 @@ class ShaderInterface { /** Enabled bindpoints that needs to be fed with data. */ uint16_t enabled_attr_mask_ = 0; uint16_t enabled_ubo_mask_ = 0; + uint8_t enabled_ima_mask_ = 0; uint64_t enabled_tex_mask_ = 0; /** Location of builtin uniforms. Fast access, no lookup needed. */ int32_t builtins_[GPU_NUM_UNIFORMS]; diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index be523020e8a..b63abb3d57f 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -30,7 +30,6 @@ #include "BKE_global.h" -#include "GPU_glew.h" #include "GPU_state.h" #include "gpu_context_private.hh" @@ -41,7 +40,7 @@ using namespace blender::gpu; #define SET_STATE(_prefix, _state, _value) \ do { \ - GPUStateManager *stack = Context::get()->state_manager; \ + StateManager *stack = Context::get()->state_manager; \ auto &state_object = stack->_prefix##state; \ state_object._state = (_value); \ } while (0) @@ -105,7 +104,7 @@ void GPU_write_mask(eGPUWriteMask mask) void GPU_color_mask(bool r, bool g, bool b, bool a) { - GPUStateManager *stack = Context::get()->state_manager; + StateManager *stack = Context::get()->state_manager; auto &state = stack->state; uint32_t write_mask = state.write_mask; SET_FLAG_FROM_TEST(write_mask, r, (uint32_t)GPU_WRITE_RED); @@ -117,7 +116,7 @@ void GPU_color_mask(bool r, bool g, bool b, bool a) void GPU_depth_mask(bool depth) { - GPUStateManager *stack = Context::get()->state_manager; + StateManager *stack = Context::get()->state_manager; auto &state = stack->state; uint32_t write_mask = state.write_mask; SET_FLAG_FROM_TEST(write_mask, depth, (uint32_t)GPU_WRITE_DEPTH); @@ -142,7 +141,7 @@ void GPU_state_set(eGPUWriteMask write_mask, eGPUStencilOp stencil_op, eGPUProvokingVertex provoking_vert) { - GPUStateManager *stack = Context::get()->state_manager; + StateManager *stack = Context::get()->state_manager; auto &state = stack->state; state.write_mask = (uint32_t)write_mask; state.blend = (uint32_t)blend; @@ -161,7 +160,7 @@ void GPU_state_set(eGPUWriteMask write_mask, void GPU_depth_range(float near, float far) { - GPUStateManager *stack = Context::get()->state_manager; + StateManager *stack = Context::get()->state_manager; auto &state = stack->mutable_state; copy_v2_fl2(state.depth_range, near, far); } @@ -173,7 +172,7 @@ void GPU_line_width(float width) void GPU_point_size(float size) { - GPUStateManager *stack = Context::get()->state_manager; + StateManager *stack = Context::get()->state_manager; auto &state = stack->mutable_state; /* Keep the sign of point_size since it represents the enable state. */ state.point_size = size * ((state.point_size > 0.0) ? 1.0f : -1.0f); @@ -185,7 +184,7 @@ void GPU_point_size(float size) /* TODO remove and use program point size everywhere */ void GPU_program_point_size(bool enable) { - GPUStateManager *stack = Context::get()->state_manager; + StateManager *stack = Context::get()->state_manager; auto &state = stack->mutable_state; /* Set point size sign negative to disable. */ state.point_size = fabsf(state.point_size) * (enable ? 1 : -1); @@ -306,18 +305,35 @@ void GPU_finish(void) Context::get()->finish(); } +void GPU_apply_state(void) +{ + Context::get()->state_manager->apply_state(); +} + +/* Will set all the states regardless of the current ones. */ +void GPU_force_state(void) +{ + Context::get()->state_manager->force_state(); +} + /** \} */ /* -------------------------------------------------------------------- */ -/** \name Default OpenGL State - * - * This is called on startup, for opengl offscreen render. - * Generally we should always return to this state when - * temporarily modifying the state for drawing, though that are (undocumented) - * exceptions that we should try to get rid of. +/** \name Synchronisation Utils + * \{ */ + +void GPU_memory_barrier(eGPUBarrier barrier) +{ + Context::get()->state_manager->issue_barrier(barrier); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Default State * \{ */ -GPUStateManager::GPUStateManager(void) +StateManager::StateManager(void) { /* Set default state. */ state.write_mask = GPU_WRITE_COLOR; diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh index 9fee45e7bd4..b8d247ec175 100644 --- a/source/blender/gpu/intern/gpu_state_private.hh +++ b/source/blender/gpu/intern/gpu_state_private.hh @@ -98,9 +98,6 @@ union GPUStateMutable { /* Viewport State */ /** TODO remove */ float depth_range[2]; - /** TODO remove, use explicit clear calls. */ - float clear_color[4]; - float clear_depth; /** Negative if using program point size. */ /* TODO(fclem) should be passed as uniform to all shaders. */ float point_size; @@ -152,21 +149,28 @@ inline GPUStateMutable operator~(const GPUStateMutable &a) * State manager keeping track of the draw state and applying it before drawing. * Base class which is then specialized for each implementation (GL, VK, ...). **/ -class GPUStateManager { +class StateManager { public: GPUState state; GPUStateMutable mutable_state; public: - GPUStateManager(); - virtual ~GPUStateManager(){}; + StateManager(); + virtual ~StateManager(){}; virtual void apply_state(void) = 0; + virtual void force_state(void) = 0; + + virtual void issue_barrier(eGPUBarrier barrier_bits) = 0; virtual void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) = 0; virtual void texture_unbind(Texture *tex) = 0; virtual void texture_unbind_all(void) = 0; + virtual void image_bind(Texture *tex, int unit) = 0; + virtual void image_unbind(Texture *tex) = 0; + virtual void image_unbind_all(void) = 0; + virtual void texture_unpack_row_length_set(uint len) = 0; }; diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc index b22fd53f0f6..eb6881164b2 100644 --- a/source/blender/gpu/intern/gpu_texture.cc +++ b/source/blender/gpu/intern/gpu_texture.cc @@ -418,6 +418,21 @@ void GPU_texture_unbind_all(void) Context::get()->state_manager->texture_unbind_all(); } +void GPU_texture_image_bind(GPUTexture *tex, int unit) +{ + Context::get()->state_manager->image_bind(unwrap(tex), unit); +} + +void GPU_texture_image_unbind(GPUTexture *tex) +{ + Context::get()->state_manager->image_unbind(unwrap(tex)); +} + +void GPU_texture_image_unbind_all(void) +{ + Context::get()->state_manager->image_unbind_all(); +} + void GPU_texture_generate_mipmap(GPUTexture *tex) { reinterpret_cast<Texture *>(tex)->generate_mipmap(); @@ -498,12 +513,6 @@ void GPU_texture_ref(GPUTexture *tex) reinterpret_cast<Texture *>(tex)->refcount++; } -/* TODO(fclem) Remove! This is broken as it is! */ -int GPU_texture_target(const GPUTexture *UNUSED(tex)) -{ - return GL_TEXTURE_2D; -} - int GPU_texture_width(const GPUTexture *tex) { return reinterpret_cast<const Texture *>(tex)->width_get(); diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc index 4cc2af889e6..ea149aaa254 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.cc +++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc @@ -324,4 +324,11 @@ void GPU_vertbuf_use(GPUVertBuf *verts) unwrap(verts)->upload(); } +/* XXX this is just a wrapper for the use of the Hair refine workaround. + * To be used with GPU_vertbuf_use(). */ +void GPU_vertbuf_update_sub(GPUVertBuf *verts, uint start, uint len, void *data) +{ + unwrap(verts)->update_sub(start, len, data); +} + /** \} */
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh index f1de0a2ac96..3cce7e79857 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh @@ -95,6 +95,8 @@ class VertBuf { } } + virtual void update_sub(uint start, uint len, void *data) = 0; + protected: virtual void acquire_data(void) = 0; virtual void resize_data(void) = 0; diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index ac8439167e3..3b0aa055588 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -70,7 +70,7 @@ static uint comp_sz(GPUVertCompType type) #if TRUST_NO_ONE assert(type <= GPU_COMP_F32); /* other types have irregular sizes (not bytes) */ #endif - const GLubyte sizes[] = {1, 1, 2, 2, 4, 4, 4}; + const uint sizes[] = {1, 1, 2, 2, 4, 4, 4}; return sizes[type]; } diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index edaa84cdcf8..46e048d7f7c 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -210,6 +210,7 @@ static void detect_workarounds(void) GLContext::debug_layer_workaround = true; GLContext::unused_fb_slot_workaround = true; /* Turn off extensions. */ + GCaps.shader_image_load_store_support = false; GLContext::base_instance_support = false; GLContext::clear_texture_support = false; GLContext::copy_image_support = false; @@ -250,17 +251,20 @@ static void detect_workarounds(void) (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") || strstr(version, "4.5.13422"))) { GLContext::unused_fb_slot_workaround = true; + GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; } /* We have issues with this specific renderer. (see T74024) */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && strstr(renderer, "AMD VERDE")) { GLContext::unused_fb_slot_workaround = true; + GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; } /* Fix slowdown on this particular driver. (see T77641) */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && strstr(version, "Mesa 19.3.4")) { + GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; } /* There is an issue with the #glBlitFramebuffer on MacOS with radeon pro graphics. @@ -349,10 +353,10 @@ static void detect_workarounds(void) } /** Internal capabilities. */ -GLint GLContext::max_texture_3d_size; -GLint GLContext::max_cubemap_size; -GLint GLContext::max_ubo_size; -GLint GLContext::max_ubo_binds; +GLint GLContext::max_cubemap_size = 0; +GLint GLContext::max_texture_3d_size = 0; +GLint GLContext::max_ubo_binds = 0; +GLint GLContext::max_ubo_size = 0; /** Extensions. */ bool GLContext::base_instance_support = false; bool GLContext::clear_texture_support = false; @@ -383,6 +387,7 @@ void GLBackend::capabilities_init(void) glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_geom); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GCaps.max_textures); GCaps.mem_stats_support = GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo; + GCaps.shader_image_load_store_support = GLEW_ARB_shader_image_load_store; /* GL specific capabilities. */ glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GLContext::max_texture_3d_size); glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GLContext::max_cubemap_size); @@ -413,4 +418,4 @@ void GLBackend::capabilities_init(void) /** \} */ -} // namespace blender::gpu
\ No newline at end of file +} // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh index 9822c842ce7..4d9c2470db0 100644 --- a/source/blender/gpu/opengl/gl_context.hh +++ b/source/blender/gpu/opengl/gl_context.hh @@ -56,8 +56,8 @@ class GLSharedOrphanLists { class GLContext : public Context { public: /** Capabilities. */ - static GLint max_texture_3d_size; static GLint max_cubemap_size; + static GLint max_texture_3d_size; static GLint max_ubo_size; static GLint max_ubo_binds; /** Extensions. */ diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index de88fdc154c..747d8ee2e3e 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -200,13 +200,16 @@ void check_gl_resources(const char *info) * be big enough to feed the data range the shader awaits. */ uint16_t ubo_needed = interface->enabled_ubo_mask_; ubo_needed &= ~ctx->bound_ubo_slots; - /* NOTE: This only check binding. To be valid, the bound texture needs to * be the same format/target the shader expects. */ uint64_t tex_needed = interface->enabled_tex_mask_; tex_needed &= ~GLContext::state_manager_active_get()->bound_texture_slots(); + /* NOTE: This only check binding. To be valid, the bound image needs to + * be the same format/target the shader expects. */ + uint8_t ima_needed = interface->enabled_ima_mask_; + ima_needed &= ~GLContext::state_manager_active_get()->bound_image_slots(); - if (ubo_needed == 0 && tex_needed == 0) { + if (ubo_needed == 0 && tex_needed == 0 && ima_needed == 0) { return; } @@ -223,6 +226,7 @@ void check_gl_resources(const char *info) for (int i = 0; tex_needed != 0; i++, tex_needed >>= 1) { if ((tex_needed & 1) != 0) { + /* FIXME: texture_get might return an image input instead. */ const ShaderInput *tex_input = interface->texture_get(i); const char *tex_name = interface->input_name_get(tex_input); const char *sh_name = ctx->shader->name_get(); @@ -231,6 +235,18 @@ void check_gl_resources(const char *info) debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL); } } + + for (int i = 0; ima_needed != 0; i++, ima_needed >>= 1) { + if ((ima_needed & 1) != 0) { + /* FIXME: texture_get might return a texture input instead. */ + const ShaderInput *tex_input = interface->texture_get(i); + const char *tex_name = interface->input_name_get(tex_input); + const char *sh_name = ctx->shader->name_get(); + char msg[256]; + SNPRINTF(msg, "Missing Image bind at slot %d : %s > %s : %s", i, sh_name, tex_name, info); + debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL); + } + } } void raise_gl_error(const char *info) @@ -243,7 +259,7 @@ void raise_gl_error(const char *info) /* -------------------------------------------------------------------- */ /** \name Object Label * - * Useful for debugging through renderdoc. Only defined if using --debug-gpu. + * Useful for debugging through render-doc. Only defined if using `--debug-gpu`. * Make sure to bind the object first so that it gets defined by the GL implementation. * \{ */ diff --git a/source/blender/gpu/opengl/gl_drawlist.hh b/source/blender/gpu/opengl/gl_drawlist.hh index 3a731559e3a..5c1e698c0a1 100644 --- a/source/blender/gpu/opengl/gl_drawlist.hh +++ b/source/blender/gpu/opengl/gl_drawlist.hh @@ -31,7 +31,6 @@ #include "BLI_sys_types.h" #include "GPU_batch.h" -#include "GPU_glew.h" #include "gpu_drawlist_private.hh" diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index d611efcd975..2d55c222e9c 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -100,6 +100,31 @@ static inline int sampler_binding(int32_t program, return -1; } } + +static inline int image_binding(int32_t program, + uint32_t uniform_index, + int32_t uniform_location, + int *image_len) +{ + /* Identify image uniforms and asign image units to them. */ + GLint type; + glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type); + + switch (type) { + case GL_IMAGE_1D: + case GL_IMAGE_2D: + case GL_IMAGE_3D: { + /* For now just assign a consecutive index. In the future, we should set it in + * the shader using layout(binding = i) and query its value. */ + int binding = *image_len; + glUniform1i(uniform_location, binding); + (*image_len)++; + return binding; + } + default: + return -1; + } +} /** \} */ /* -------------------------------------------------------------------- */ @@ -207,8 +232,8 @@ GLShaderInterface::GLShaderInterface(GLuint program) enabled_ubo_mask_ |= (1 << input->binding); } - /* Uniforms */ - for (int i = 0, sampler = 0; i < active_uniform_len; i++) { + /* Uniforms & samplers & images */ + for (int i = 0, sampler = 0, image = 0; i < active_uniform_len; i++) { if (BLI_BITMAP_TEST(uniforms_from_blocks, i)) { continue; } @@ -224,6 +249,12 @@ GLShaderInterface::GLShaderInterface(GLuint program) name_buffer_offset += this->set_input_name(input, name, name_len); enabled_tex_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu; + + if (input->binding == -1) { + input->binding = image_binding(program, i, input->location, &image); + + enabled_ima_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu; + } } /* Builtin Uniforms */ @@ -296,4 +327,4 @@ void GLShaderInterface::ref_remove(GLVaoCache *ref) /** \} */ -} // namespace blender::gpu
\ No newline at end of file +} // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc index 1678760e9cd..cd24fa0e0e4 100644 --- a/source/blender/gpu/opengl/gl_state.cc +++ b/source/blender/gpu/opengl/gl_state.cc @@ -42,7 +42,7 @@ namespace blender::gpu { /** \name GLStateManager * \{ */ -GLStateManager::GLStateManager(void) : GPUStateManager() +GLStateManager::GLStateManager(void) : StateManager() { /* Set other states that never change. */ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); @@ -76,9 +76,21 @@ void GLStateManager::apply_state(void) this->set_state(this->state); this->set_mutable_state(this->mutable_state); this->texture_bind_apply(); + this->image_bind_apply(); active_fb->apply_state(); }; +void GLStateManager::force_state(void) +{ + /* Little exception for clip distances since they need to keep the old count correct. */ + uint32_t clip_distances = current_.clip_distances; + current_ = ~this->state; + current_.clip_distances = clip_distances; + current_mutable_ = ~this->mutable_state; + this->set_state(this->state); + this->set_mutable_state(this->mutable_state); +}; + void GLStateManager::set_state(const GPUState &state) { GPUState changed = state ^ current_; @@ -538,4 +550,98 @@ uint64_t GLStateManager::bound_texture_slots(void) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Image Binding (from image load store) + * \{ */ + +void GLStateManager::image_bind(Texture *tex_, int unit) +{ + /* Minimum support is 8 image in the fragment shader. No image for other stages. */ + BLI_assert(GPU_shader_image_load_store_support() && unit < 8); + GLTexture *tex = static_cast<GLTexture *>(tex_); + if (G.debug & G_DEBUG_GPU) { + tex->check_feedback_loop(); + } + images_[unit] = tex->tex_id_; + formats_[unit] = to_gl_internal_format(tex->format_); + tex->is_bound_ = true; + dirty_image_binds_ |= 1ULL << unit; +} + +void GLStateManager::image_unbind(Texture *tex_) +{ + GLTexture *tex = static_cast<GLTexture *>(tex_); + if (!tex->is_bound_) { + return; + } + + GLuint tex_id = tex->tex_id_; + for (int i = 0; i < ARRAY_SIZE(images_); i++) { + if (images_[i] == tex_id) { + images_[i] = 0; + dirty_image_binds_ |= 1ULL << i; + } + } + tex->is_bound_ = false; +} + +void GLStateManager::image_unbind_all(void) +{ + for (int i = 0; i < ARRAY_SIZE(images_); i++) { + if (images_[i] != 0) { + images_[i] = 0; + dirty_image_binds_ |= 1ULL << i; + } + } + this->image_bind_apply(); +} + +void GLStateManager::image_bind_apply(void) +{ + if (dirty_image_binds_ == 0) { + return; + } + uint32_t dirty_bind = dirty_image_binds_; + dirty_image_binds_ = 0; + + int first = bitscan_forward_uint(dirty_bind); + int last = 32 - bitscan_reverse_uint(dirty_bind); + int count = last - first; + + if (GLContext::multi_bind_support) { + glBindImageTextures(first, count, images_ + first); + } + else { + for (int unit = first; unit < last; unit++) { + if ((dirty_bind >> unit) & 1UL) { + glBindImageTexture(unit, images_[unit], 0, GL_TRUE, 0, GL_READ_WRITE, formats_[unit]); + } + } + } +} + +uint8_t GLStateManager::bound_image_slots(void) +{ + uint8_t bound_slots = 0; + for (int i = 0; i < ARRAY_SIZE(images_); i++) { + if (images_[i] != 0) { + bound_slots |= 1ULL << i; + } + } + return bound_slots; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Memory barrier + * \{ */ + +void GLStateManager::issue_barrier(eGPUBarrier barrier_bits) +{ + glMemoryBarrier(to_gl(barrier_bits)); +} + +/** \} */ + } // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_state.hh b/source/blender/gpu/opengl/gl_state.hh index fb2ed3403f7..cab654006c6 100644 --- a/source/blender/gpu/opengl/gl_state.hh +++ b/source/blender/gpu/opengl/gl_state.hh @@ -40,7 +40,7 @@ class GLTexture; * State manager keeping track of the draw state and applying it before drawing. * Opengl Implementation. **/ -class GLStateManager : public GPUStateManager { +class GLStateManager : public StateManager { public: /** Anothter reference to the active framebuffer. */ GLFrameBuffer *active_fb = nullptr; @@ -64,19 +64,31 @@ class GLStateManager : public GPUStateManager { GLuint samplers_[64] = {0}; uint64_t dirty_texture_binds_ = 0; + GLuint images_[8] = {0}; + GLenum formats_[8] = {0}; + uint8_t dirty_image_binds_ = 0; + public: GLStateManager(); void apply_state(void) override; + void force_state(void) override; + + void issue_barrier(eGPUBarrier barrier_bits) override; void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) override; void texture_bind_temp(GLTexture *tex); void texture_unbind(Texture *tex) override; void texture_unbind_all(void) override; + void image_bind(Texture *tex, int unit) override; + void image_unbind(Texture *tex) override; + void image_unbind_all(void) override; + void texture_unpack_row_length_set(uint len) override; uint64_t bound_texture_slots(void); + uint8_t bound_image_slots(void); private: static void set_write_mask(const eGPUWriteMask value); @@ -95,9 +107,22 @@ class GLStateManager : public GPUStateManager { void set_mutable_state(const GPUStateMutable &state); void texture_bind_apply(void); + void image_bind_apply(void); MEM_CXX_CLASS_ALLOC_FUNCS("GLStateManager") }; +static inline GLbitfield to_gl(eGPUBarrier barrier_bits) +{ + GLbitfield barrier = 0; + if (barrier_bits & GPU_BARRIER_SHADER_IMAGE_ACCESS) { + barrier |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; + } + if (barrier_bits & GPU_BARRIER_TEXTURE_FETCH) { + barrier |= GL_TEXTURE_FETCH_BARRIER_BIT; + } + return barrier; +} + } // namespace gpu } // namespace blender diff --git a/source/blender/gpu/opengl/gl_vertex_buffer.cc b/source/blender/gpu/opengl/gl_vertex_buffer.cc index a724c94775e..d97fc2c1600 100644 --- a/source/blender/gpu/opengl/gl_vertex_buffer.cc +++ b/source/blender/gpu/opengl/gl_vertex_buffer.cc @@ -106,4 +106,9 @@ void GLVertBuf::bind(void) } } +void GLVertBuf::update_sub(uint start, uint len, void *data) +{ + glBufferSubData(GL_ARRAY_BUFFER, start, len, data); +} + } // namespace blender::gpu
\ No newline at end of file diff --git a/source/blender/gpu/opengl/gl_vertex_buffer.hh b/source/blender/gpu/opengl/gl_vertex_buffer.hh index eee5222f467..e2bf6cd00e8 100644 --- a/source/blender/gpu/opengl/gl_vertex_buffer.hh +++ b/source/blender/gpu/opengl/gl_vertex_buffer.hh @@ -45,6 +45,8 @@ class GLVertBuf : public VertBuf { public: void bind(void); + void update_sub(uint start, uint len, void *data) override; + protected: void acquire_data(void) override; void resize_data(void) override; diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index ba096653e0f..c7d8a8b3723 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -583,8 +583,8 @@ static void free_posetree(PoseTree *tree) MEM_freeN(tree); } -///---------------------------------------- -/// Plugin API for legacy iksolver +/* ------------------------------ + * Plugin API for legacy iksolver */ void iksolver_initialize_tree(struct Depsgraph *UNUSED(depsgraph), struct Scene *UNUSED(scene), diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index 1fbe7b46963..8978b823e2a 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -247,14 +247,14 @@ void BlockDXT1::setIndices(const int *idx) } } -/// Flip DXT1 block vertically. +/** Flip DXT1 block vertically. */ inline void BlockDXT1::flip4() { swap(row[0], row[3]); swap(row[1], row[2]); } -/// Flip half DXT1 block vertically. +/** Flip half DXT1 block vertically. */ inline void BlockDXT1::flip2() { swap(row[0], row[1]); @@ -299,27 +299,27 @@ void AlphaBlockDXT3::decodeBlock(ColorBlock *block) const block->color(0xF).a = (alphaF << 4) | alphaF; } -/// Flip DXT3 alpha block vertically. +/** Flip DXT3 alpha block vertically. */ void AlphaBlockDXT3::flip4() { swap(row[0], row[3]); swap(row[1], row[2]); } -/// Flip half DXT3 alpha block vertically. +/** Flip half DXT3 alpha block vertically. */ void AlphaBlockDXT3::flip2() { swap(row[0], row[1]); } -/// Flip DXT3 block vertically. +/** Flip DXT3 block vertically. */ void BlockDXT3::flip4() { alpha.flip4(); color.flip4(); } -/// Flip half DXT3 block vertically. +/** Flip half DXT3 block vertically. */ void BlockDXT3::flip2() { alpha.flip2(); @@ -458,21 +458,21 @@ void BlockDXT5::decodeBlockNV5x(ColorBlock *block) const alpha.decodeBlock(block); } -/// Flip DXT5 block vertically. +/** Flip DXT5 block vertically. */ void BlockDXT5::flip4() { alpha.flip4(); color.flip4(); } -/// Flip half DXT5 block vertically. +/** Flip half DXT5 block vertically. */ void BlockDXT5::flip2() { alpha.flip2(); color.flip2(); } -/// Decode ATI1 block. +/** Decode ATI1 block. */ void BlockATI1::decodeBlock(ColorBlock *block) const { uint8 alpha_array[8]; @@ -488,19 +488,19 @@ void BlockATI1::decodeBlock(ColorBlock *block) const } } -/// Flip ATI1 block vertically. +/** Flip ATI1 block vertically. */ void BlockATI1::flip4() { alpha.flip4(); } -/// Flip half ATI1 block vertically. +/** Flip half ATI1 block vertically. */ void BlockATI1::flip2() { alpha.flip2(); } -/// Decode ATI2 block. +/** Decode ATI2 block. */ void BlockATI2::decodeBlock(ColorBlock *block) const { uint8 alpha_array[8]; @@ -525,14 +525,14 @@ void BlockATI2::decodeBlock(ColorBlock *block) const } } -/// Flip ATI2 block vertically. +/** Flip ATI2 block vertically. */ void BlockATI2::flip4() { x.flip4(); y.flip4(); } -/// Flip half ATI2 block vertically. +/** Flip half ATI2 block vertically. */ void BlockATI2::flip2() { x.flip2(); @@ -586,14 +586,14 @@ void BlockCTX1::setIndices(const int *idx) } } -/// Flip CTX1 block vertically. +/** Flip CTX1 block vertically. */ inline void BlockCTX1::flip4() { swap(row[0], row[3]); swap(row[1], row[2]); } -/// Flip half CTX1 block vertically. +/** Flip half CTX1 block vertically. */ inline void BlockCTX1::flip2() { swap(row[0], row[1]); diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 70ec8808c61..83cc147c76c 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -55,7 +55,7 @@ #include <Common.h> #include <Stream.h> -/// DXT1 block. +/** DXT1 block. */ struct BlockDXT1 { Color16 col0; Color16 col1; @@ -81,13 +81,13 @@ struct BlockDXT1 { void flip2(); }; -/// Return true if the block uses four color mode, false otherwise. +/** Return true if the block uses four color mode, false otherwise. */ inline bool BlockDXT1::isFourColorMode() const { return col0.u > col1.u; } -/// DXT3 alpha block with explicit alpha. +/** DXT3 alpha block with explicit alpha. */ struct AlphaBlockDXT3 { union { struct { @@ -117,7 +117,7 @@ struct AlphaBlockDXT3 { void flip2(); }; -/// DXT3 block. +/** DXT3 block. */ struct BlockDXT3 { AlphaBlockDXT3 alpha; BlockDXT1 color; @@ -129,7 +129,7 @@ struct BlockDXT3 { void flip2(); }; -/// DXT5 alpha block. +/** DXT5 alpha block. */ struct AlphaBlockDXT5 { // uint64 unions do not compile on all platforms #if 0 @@ -245,7 +245,7 @@ struct AlphaBlockDXT5 { void flip2(); }; -/// DXT5 block. +/** DXT5 block. */ struct BlockDXT5 { AlphaBlockDXT5 alpha; BlockDXT1 color; @@ -257,7 +257,7 @@ struct BlockDXT5 { void flip2(); }; -/// ATI1 block. +/** ATI1 block. */ struct BlockATI1 { AlphaBlockDXT5 alpha; @@ -267,7 +267,7 @@ struct BlockATI1 { void flip2(); }; -/// ATI2 block. +/** ATI2 block. */ struct BlockATI2 { AlphaBlockDXT5 x; AlphaBlockDXT5 y; @@ -278,7 +278,7 @@ struct BlockATI2 { void flip2(); }; -/// CTX1 block. +/** CTX1 block. */ struct BlockCTX1 { uint8 col0[2]; uint8 col1[2]; diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h index d0b67d4638c..4a9202617f5 100644 --- a/source/blender/imbuf/intern/dds/Color.h +++ b/source/blender/imbuf/intern/dds/Color.h @@ -29,7 +29,7 @@ #pragma once -/// 32 bit color stored as BGRA. +/** 32 bit color stored as BGRA. */ class Color32 { public: Color32() @@ -93,7 +93,7 @@ class Color32 { }; }; -/// 16 bit 565 BGR color. +/** 16 bit 565 BGR color. */ class Color16 { public: Color16() diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 69757d797b5..f2e8e0b0313 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -46,12 +46,12 @@ inline static uint colorDistance(Color32 c0, Color32 c1) } #endif -/// Default constructor. +/** Default constructor. */ ColorBlock::ColorBlock() { } -/// Init the color block from an array of colors. +/** Init the color block from an array of colors. */ ColorBlock::ColorBlock(const uint *linearImage) { for (uint i = 0; i < 16; i++) { @@ -59,7 +59,7 @@ ColorBlock::ColorBlock(const uint *linearImage) } } -/// Init the color block with the contents of the given block. +/** Init the color block with the contents of the given block. */ ColorBlock::ColorBlock(const ColorBlock &block) { for (uint i = 0; i < 16; i++) { @@ -67,7 +67,7 @@ ColorBlock::ColorBlock(const ColorBlock &block) } } -/// Initialize this color block. +/** Initialize this color block. */ ColorBlock::ColorBlock(const Image *img, uint x, uint y) { init(img, x, y); @@ -159,7 +159,7 @@ void ColorBlock::swizzle(uint x, uint y, uint z, uint w) } } -/// Returns true if the block has a single color. +/** Returns true if the block has a single color. */ bool ColorBlock::isSingleColor(Color32 mask /*= Color32(0xFF, 0xFF, 0xFF, 0x00)*/) const { uint u = m_color[0].u & mask.u; @@ -174,7 +174,7 @@ bool ColorBlock::isSingleColor(Color32 mask /*= Color32(0xFF, 0xFF, 0xFF, 0x00)* } #if 0 -/// Returns true if the block has a single color, ignoring transparent pixels. +/** Returns true if the block has a single color, ignoring transparent pixels. */ bool ColorBlock::isSingleColorNoAlpha() const { Color32 c; @@ -199,7 +199,7 @@ bool ColorBlock::isSingleColorNoAlpha() const #endif #if 0 -/// Count number of unique colors in this color block. +/** Count number of unique colors in this color block. */ uint ColorBlock::countUniqueColors() const { uint count = 0; @@ -223,7 +223,7 @@ uint ColorBlock::countUniqueColors() const #endif #if 0 -/// Get average color of the block. +/** Get average color of the block. */ Color32 ColorBlock::averageColor() const { uint r, g, b, a; @@ -240,7 +240,7 @@ Color32 ColorBlock::averageColor() const } #endif -/// Return true if the block is not fully opaque. +/** Return true if the block is not fully opaque. */ bool ColorBlock::hasAlpha() const { for (uint i = 0; i < 16; i++) { @@ -253,7 +253,7 @@ bool ColorBlock::hasAlpha() const #if 0 -/// Get diameter color range. +/** Get diameter color range. */ void ColorBlock::diameterRange(Color32 *start, Color32 *end) const { Color32 c0, c1; @@ -274,7 +274,7 @@ void ColorBlock::diameterRange(Color32 *start, Color32 *end) const *end = c1; } -/// Get luminance color range. +/** Get luminance color range. */ void ColorBlock::luminanceRange(Color32 *start, Color32 *end) const { Color32 minColor, maxColor; @@ -299,7 +299,7 @@ void ColorBlock::luminanceRange(Color32 *start, Color32 *end) const *end = maxColor; } -/// Get color range based on the bounding box. +/** Get color range based on the bounding box. */ void ColorBlock::boundsRange(Color32 *start, Color32 *end) const { Color32 minColor(255, 255, 255); @@ -344,7 +344,7 @@ void ColorBlock::boundsRange(Color32 *start, Color32 *end) const *end = maxColor; } -/// Get color range based on the bounding box. +/** Get color range based on the bounding box. */ void ColorBlock::boundsRangeAlpha(Color32 *start, Color32 *end) const { Color32 minColor(255, 255, 255, 255); @@ -400,7 +400,7 @@ void ColorBlock::boundsRangeAlpha(Color32 *start, Color32 *end) const #endif #if 0 -/// Sort colors by abosolute value in their 16 bit representation. +/** Sort colors by abosolute value in their 16 bit representation. */ void ColorBlock::sortColorsByAbsoluteValue() { // Dummy selection sort. @@ -422,7 +422,7 @@ void ColorBlock::sortColorsByAbsoluteValue() #endif #if 0 -/// Find extreme colors in the given axis. +/** Find extreme colors in the given axis. */ void ColorBlock::computeRange(Vector3::Arg axis, Color32 *start, Color32 *end) const { @@ -452,7 +452,7 @@ void ColorBlock::computeRange(Vector3::Arg axis, Color32 *start, Color32 *end) c #endif #if 0 -/// Sort colors in the given axis. +/** Sort colors in the given axis. */ void ColorBlock::sortColors(const Vector3 &axis) { float luma_array[16]; @@ -477,7 +477,7 @@ void ColorBlock::sortColors(const Vector3 &axis) #endif #if 0 -/// Get the volume of the color block. +/** Get the volume of the color block. */ float ColorBlock::volume() const { Box bounds; diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index dd63286e230..98b4c9cb40a 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -32,7 +32,7 @@ #include <Color.h> #include <Image.h> -/// Uncompressed 4x4 color block. +/** Uncompressed 4x4 color block. */ struct ColorBlock { ColorBlock(); ColorBlock(const uint *linearImage); @@ -61,31 +61,31 @@ struct ColorBlock { Color32 m_color[4 * 4]; }; -/// Get pointer to block colors. +/** Get pointer to block colors. */ inline const Color32 *ColorBlock::colors() const { return m_color; } -/// Get block color. +/** Get block color. */ inline Color32 ColorBlock::color(uint i) const { return m_color[i]; } -/// Get block color. +/** Get block color. */ inline Color32 &ColorBlock::color(uint i) { return m_color[i]; } -/// Get block color. +/** Get block color. */ inline Color32 ColorBlock::color(uint x, uint y) const { return m_color[y * 4 + x]; } -/// Get block color. +/** Get block color. */ inline Color32 &ColorBlock::color(uint x, uint y) { return m_color[y * 4 + x]; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index ac7f893fddd..373d5974a5e 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -73,7 +73,7 @@ struct DDSCaps { uint caps4; }; -/// DDS file header for DX10. +/** DDS file header for DX10. */ struct DDSHeader10 { uint dxgiFormat; uint resourceDimension; @@ -82,7 +82,7 @@ struct DDSHeader10 { uint reserved; }; -/// DDS file header. +/** DDS file header. */ struct DDSHeader { uint fourcc; uint size; @@ -132,7 +132,7 @@ struct DDSHeader { uint d3d9Format() const; }; -/// DirectDraw Surface. (DDS) +/** DirectDraw Surface. (DDS) */ class DirectDrawSurface { public: DirectDrawSurface(unsigned char *mem, uint size); diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h index 4ccfec99445..0f977641d89 100644 --- a/source/blender/imbuf/intern/dds/Image.h +++ b/source/blender/imbuf/intern/dds/Image.h @@ -32,7 +32,7 @@ #include "Color.h" #include "Common.h" -/// 32 bit RGBA image. +/** 32 bit RGBA image. */ class Image { public: enum Format { diff --git a/source/blender/makesdna/DNA_image_defaults.h b/source/blender/makesdna/DNA_image_defaults.h index ce1296d681f..93ff8792dfa 100644 --- a/source/blender/makesdna/DNA_image_defaults.h +++ b/source/blender/makesdna/DNA_image_defaults.h @@ -36,6 +36,8 @@ .gen_type = IMA_GENTYPE_GRID, \ \ .gpuframenr = INT_MAX, \ + .gpu_pass = SHRT_MAX, \ + .gpu_layer = SHRT_MAX, \ } /** \} */ diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 749bc55fcb9..4a05d7ba319 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -147,9 +147,11 @@ typedef struct Image { int lastframe; /* GPU texture flag. */ - short gpuflag; - char _pad2[2]; int gpuframenr; + short gpuflag; + short gpu_pass; + short gpu_layer; + char _pad2[6]; /** Deprecated. */ struct PackedFile *packedfile DNA_DEPRECATED; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index a4b379bff15..c92665d4ac2 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -623,9 +623,10 @@ typedef struct UserDef_Experimental { char use_new_hair_type; char use_cycles_debug; char use_sculpt_vertex_colors; + char use_image_editor_legacy_drawing; char use_tools_missing_icons; /** `makesdna` does not allow empty structs. */ - char _pad[2]; + char _pad[1]; } UserDef_Experimental; #define USER_EXPERIMENTAL_TEST(userdef, member) \ diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 0387f83d695..976035b9886 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -385,10 +385,6 @@ blender_include_dirs( ../../../../intern/mantaflow/extern ) -blender_include_dirs_sys( - "${GLEW_INCLUDE_PATH}" -) - add_cc_flags_custom_test(makesrna) setup_platform_linker_flags() @@ -443,7 +439,6 @@ set(LIB bf_editor_undo ) -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_rna "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index eab6349317a..13b068c2be5 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -243,35 +243,87 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu } } +/* Helper function which returns index of the given hair_key in particle which owns it. + * Works with cases when hair_key is coming from the particle which was passed here, and from the + * original particle of the given one. + * + * Such trickery is needed to allow modification of hair keys in the original object using + * evaluated particle and object to access proper hair matrix. */ +static int hair_key_index_get(/*const*/ HairKey *hair_key, + /*const*/ ParticleSystemModifierData *modifier, + /*const*/ ParticleData *particle) +{ + if (ARRAY_HAS_ITEM(hair_key, particle->hair, particle->totkey)) { + return hair_key - particle->hair; + } + + const ParticleSystem *particle_system = modifier->psys; + const int particle_index = particle - particle_system->particles; + + const ParticleSystemModifierData *original_modifier = (ParticleSystemModifierData *) + BKE_modifier_get_original(&modifier->modifier); + const ParticleSystem *original_particle_system = original_modifier->psys; + const ParticleData *original_particle = &original_particle_system->particles[particle_index]; + + if (ARRAY_HAS_ITEM(hair_key, original_particle->hair, original_particle->totkey)) { + return hair_key - original_particle->hair; + } + + return -1; +} + +/* Set hair_key->co to the given coordinate in object space (the given coordinate will be + * converted to the proper space). + * + * The hair_key can be coming from both original and evaluated object. Object, modifier and + * particle are to be from evaluated object, so that all the data needed for hair matrix is + * present. */ +static void hair_key_location_object_set(HairKey *hair_key, + Object *object, + ParticleSystemModifierData *modifier, + ParticleData *particle, + const float src_co[3]) +{ + Mesh *hair_mesh = (modifier->psys->flag & PSYS_HAIR_DYNAMICS) ? modifier->psys->hair_out_mesh : + NULL; + + if (hair_mesh != NULL) { + const int hair_key_index = hair_key_index_get(hair_key, modifier, particle); + if (hair_key_index == -1) { + return; + } + + MVert *mvert = &hair_mesh->mvert[particle->hair_index + (hair_key_index)]; + copy_v3_v3(mvert->co, src_co); + return; + } + + float hairmat[4][4]; + psys_mat_hair_to_object( + object, modifier->mesh_final, modifier->psys->part->from, particle, hairmat); + + float imat[4][4]; + invert_m4_m4(imat, hairmat); + + copy_v3_v3(hair_key->co, src_co); + mul_m4_v3(imat, hair_key->co); +} + static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float *values) { HairKey *hkey = (HairKey *)ptr->data; Object *ob = (Object *)ptr->owner_id; + ParticleSystemModifierData *psmd; ParticleData *pa; - rna_ParticleHairKey_location_object_info(ptr, &psmd, &pa); - if (pa) { - Mesh *hair_mesh = (psmd->psys->flag & PSYS_HAIR_DYNAMICS) ? psmd->psys->hair_out_mesh : NULL; - - if (hair_mesh) { - MVert *mvert = &hair_mesh->mvert[pa->hair_index + (hkey - pa->hair)]; - copy_v3_v3(mvert->co, values); - } - else { - float hairmat[4][4]; - float imat[4][4]; - - psys_mat_hair_to_object(ob, psmd->mesh_final, psmd->psys->part->from, pa, hairmat); - invert_m4_m4(imat, hairmat); - copy_v3_v3(hkey->co, values); - mul_m4_v3(imat, hkey->co); - } - } - else { + if (pa == NULL) { zero_v3(hkey->co); + return; } + + hair_key_location_object_set(hkey, ob, psmd, pa, values); } static void rna_ParticleHairKey_co_object(HairKey *hairkey, @@ -301,6 +353,31 @@ static void rna_ParticleHairKey_co_object(HairKey *hairkey, } } +static void rna_ParticleHairKey_co_object_set(ID *id, + HairKey *hair_key, + Object *object, + ParticleSystemModifierData *modifier, + ParticleData *particle, + float co[3]) +{ + + if (particle == NULL) { + return; + } + + /* Mark particle system as edited, so then particle_system_update() does not reset the hair + * keys from path. This behavior is similar to how particle edit mode sets flags. */ + ParticleSystemModifierData *orig_modifier = (ParticleSystemModifierData *) + modifier->modifier.orig_modifier_data; + orig_modifier->psys->flag |= PSYS_EDITED; + + hair_key_location_object_set(hair_key, object, modifier, particle, co); + + /* Tag similar to brushes in particle edit mode, so the modifier stack is properly evaluated + * with the same particle system recalc flags as during combing. */ + DEG_id_tag_update(id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO); +} + static void rna_Particle_uv_on_emitter(ParticleData *particle, ReportList *reports, ParticleSystemModifierData *modifier, @@ -1651,6 +1728,19 @@ static void rna_def_particle_hair_key(BlenderRNA *brna) func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", "Exported hairkey location", -1e4, 1e4); RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); RNA_def_function_output(func, parm); + + func = RNA_def_function(srna, "co_object_set", "rna_ParticleHairKey_co_object_set"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_ui_description(func, "Set hairkey location with particle and modifier data"); + parm = RNA_def_pointer(func, "object", "Object", "", "Object"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "particle", "Particle", "", "hair particle"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float_vector( + func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", "Specified hairkey location", -1e4, 1e4); + RNA_def_parameter_flags(parm, PROP_THICK_WRAP, PARM_REQUIRED); } static void rna_def_particle_key(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 1a911494f09..13b316a9d5d 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2617,9 +2617,10 @@ static void rna_FileBrowser_FSMenu_active_range(PointerRNA *UNUSED(ptr), *max = *softmax = ED_fsmenu_get_nentries(fsmenu, category) - 1; } -static void rna_FileBrowser_FSMenu_active_update(struct bContext *C, PointerRNA *UNUSED(ptr)) +static void rna_FileBrowser_FSMenu_active_update(struct bContext *C, PointerRNA *ptr) { - ED_file_change_dir(C); + ScrArea *area = rna_area_from_space(ptr); + ED_file_change_dir_ex(C, (bScreen *)ptr->owner_id, area); } static int rna_FileBrowser_FSMenuSystem_active_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 99f0f53907e..0cbad9fb0c8 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3066,6 +3066,11 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Metadata Text", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Grid", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + rna_def_userdef_theme_spaces_curves(srna, false, false, false, true); rna_def_userdef_theme_spaces_paint_curves(srna); @@ -6123,6 +6128,11 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_vertex_colors", 1); RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "Use the new Vertex Painting system"); + prop = RNA_def_property(srna, "use_image_editor_legacy_drawing", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "use_image_editor_legacy_drawing", 1); + RNA_def_property_ui_text( + prop, "Legacy Image Editor Drawing", "Use legacy UV/Image editor drawing"); + prop = RNA_def_property(srna, "use_tools_missing_icons", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "use_tools_missing_icons", 1); RNA_def_property_ui_text(prop, "Tools with Missing Icons", "Show tools with missing icons"); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 01770abeca0..7f65e72bf3e 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -178,7 +178,6 @@ if(WITH_GMP) endif() # So we can have special tricks in modifier system. -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_modifiers "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c index cb150976ff5..d216c14ab43 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c +++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c @@ -65,13 +65,13 @@ static bool meshcache_read_mdd_head(FILE *fp, *err_str = "Invalid frame total"; return false; } - /* intentionally dont seek back */ + /* Intentionally don't seek back. */ return true; } /** - * Gets the index frange and factor + * Gets the index range and factor. */ static bool meshcache_read_mdd_range(FILE *fp, const int verts_tot, diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 33b95d50cc0..4172dc06a9f 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -41,9 +41,6 @@ set(INC ../../../intern/sky/include ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC composite/nodes/node_composite_alphaOver.c @@ -343,7 +340,6 @@ if(WITH_COMPOSITOR) add_definitions(-DWITH_COMPOSITOR) endif() -add_definitions(${GL_DEFINITIONS}) if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index 89fe9f8c6aa..8a5c4f4a11b 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -27,12 +27,12 @@ #include <Python.h> #include "BLI_utildefines.h" - -#include "GPU_glew.h" #include "MEM_guardedalloc.h" #include "../generic/py_capi_utils.h" +#include "glew-mx.h" + #include "bgl.h" /* -------------------------------------------------------------------- */ diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 15c39de990b..31440dadd03 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -157,6 +157,7 @@ static PyObject *bpygpu_offscreen_bind(BPyGPUOffScreen *self, PyObject *args, Py } GPU_offscreen_bind(self->ofs, save); + GPU_apply_state(); self->is_saved = save; Py_INCREF(self); @@ -185,6 +186,7 @@ static PyObject *bpygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, } GPU_offscreen_unbind(self->ofs, restore); + GPU_apply_state(); Py_RETURN_NONE; } diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index f9ff0558570..55753e91f14 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -607,12 +607,12 @@ PyDoc_STRVAR( " ``GL_ARB_texture_gather``, ``GL_ARB_texture_cube_map_array`` and " "``GL_ARB_shader_draw_parameters``.\n" "\n" - " To debug shaders, use the --debug-gpu-shaders command line option" - " to see full GLSL shader compilation and linking errors.\n" + " To debug shaders, use the ``--debug-gpu-shaders`` command line option " + "to see full GLSL shader compilation and linking errors.\n" "\n" " For drawing user interface elements and gizmos, use " - " ``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)``" - " to transform the output sRGB colors to the framebuffer colorspace." + "``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)`` " + "to transform the output sRGB colors to the frame-buffer color-space." "\n" " :param vertexcode: Vertex shader code.\n" " :type vertexcode: str\n" diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 6c3f422d3f0..febb0d1cad5 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -341,6 +341,5 @@ if(WITH_XR_OPENXR) add_definitions(-DWITH_XR_OPENXR) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/python/intern/bpy_rna_ui.c b/source/blender/python/intern/bpy_rna_ui.c index 9f37b8300db..27e4cb069ce 100644 --- a/source/blender/python/intern/bpy_rna_ui.c +++ b/source/blender/python/intern/bpy_rna_ui.c @@ -29,6 +29,7 @@ #include "UI_interface.h" #include "bpy_rna.h" +#include "bpy_rna_ui.h" PyDoc_STRVAR(bpy_rna_uilayout_introspect_doc, ".. method:: introspect()\n" diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index e3c3cf712f9..2652ec2f8cb 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -39,9 +39,6 @@ set(INC ../../../intern/mantaflow/extern ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) set(SRC intern/source/bake_api.c @@ -108,6 +105,5 @@ if(APPLE) endif() endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib_nolist(bf_render "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/shader_fx/CMakeLists.txt b/source/blender/shader_fx/CMakeLists.txt index a12f36f9713..a68b343d416 100644 --- a/source/blender/shader_fx/CMakeLists.txt +++ b/source/blender/shader_fx/CMakeLists.txt @@ -67,6 +67,5 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_shader_fx "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 7c749c60168..b9efc0e386a 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -46,7 +46,6 @@ set(INC set(INC_SYS ${ZLIB_INCLUDE_DIRS} - ${GLEW_INCLUDE_PATH} ) set(SRC @@ -131,7 +130,6 @@ if(WITH_AUDASPACE) ) endif() -add_definitions(${GL_DEFINITIONS}) if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 1d3db3e7609..eb5f8ca5ef1 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -396,9 +396,6 @@ static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen) /* Setup offscreen color texture for drawing. */ GPUTexture *texture = GPU_offscreen_color_texture(offscreen); - /* We don't support multisample textures here. */ - BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D); - /* No mipmaps or filtering. */ GPU_texture_mipmap_mode(texture, false, false); } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index b85bf8cb323..5a22e990218 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -190,8 +190,6 @@ void WM_init_opengl(void) GPU_pass_cache_init(); - BKE_subdiv_init(); - opengl_is_init = true; } @@ -323,6 +321,8 @@ void WM_init(bContext *C, int argc, const char **argv) UI_init(); } + BKE_subdiv_init(); + ED_spacemacros_init(); /* note: there is a bug where python needs initializing before loading the diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index d00285adb02..2798cec8c58 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -51,9 +51,6 @@ if(WITH_TBB) list(INSERT LIB 0 bf_blenkernel) endif() -add_definitions(${GL_DEFINITIONS}) -blender_include_dirs("${GLEW_INCLUDE_PATH}") - if(WIN32) blender_include_dirs(../../intern/utfconv) endif() |