diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2011-12-28 22:31:32 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2011-12-28 22:31:32 +0400 |
commit | c2ae77e5bdd60e4cfe9b1f9d3d54e66f8089245c (patch) | |
tree | 505b5270122ec50302f6f824088b43318d13a296 | |
parent | fd134927dd23047237c6e490c09454487ba19a4a (diff) | |
parent | fe2131367b3f1ca1f974d1d6160cfc8a1a220abe (diff) |
Merging r42896 through r42944 from trunk into soc-2911-tomato
67 files changed, 2118 insertions, 807 deletions
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py index 1272d81872d..64ff1c0f007 100644 --- a/release/scripts/modules/sys_info.py +++ b/release/scripts/modules/sys_info.py @@ -94,6 +94,16 @@ def write_sysinfo(op): output.write('autosave: {}\n'.format(bpy.utils.user_resource('AUTOSAVE'))) output.write('tempdir: {}\n'.format(bpy.app.tempdir)) + output.write('\nFFmpeg:\n') + output.write(lilies) + ffmpeg = bpy.app.ffmpeg + if ffmpeg.supported: + for lib in ['avcodec', 'avdevice', 'avformat', 'avutil', 'swscale']: + output.write('{}:{}{}\n'.format(lib, " "*(10-len(lib)), + getattr(ffmpeg, lib + '_version_string'))) + else: + output.write('Blender was built without FFmpeg support\n') + if bpy.app.background: output.write('\nOpenGL: missing, background mode\n') else: diff --git a/release/scripts/presets/ffmpeg/DV.py b/release/scripts/presets/ffmpeg/DV.py index 926fb241747..241d6938a5f 100644 --- a/release/scripts/presets/ffmpeg/DV.py +++ b/release/scripts/presets/ffmpeg/DV.py @@ -11,4 +11,4 @@ else: bpy.context.scene.render.ffmpeg_audio_mixrate = 48000 bpy.context.scene.render.ffmpeg_audio_codec = "PCM" -bpy.context.scene.render.ffmpeg_audio_channels = 2 +bpy.context.scene.render.ffmpeg_audio_channels = "STEREO" diff --git a/release/scripts/presets/ffmpeg/DVD.py b/release/scripts/presets/ffmpeg/DVD.py index 196b5d68406..07828a755cd 100644 --- a/release/scripts/presets/ffmpeg/DVD.py +++ b/release/scripts/presets/ffmpeg/DVD.py @@ -21,4 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 10080000 bpy.context.scene.render.ffmpeg_audio_codec = "AC3" bpy.context.scene.render.ffmpeg_audio_bitrate = 448 bpy.context.scene.render.ffmpeg_audio_mixrate = 48000 -bpy.context.scene.render.ffmpeg_audio_channels = 6 +bpy.context.scene.render.ffmpeg_audio_channels = "SURROUND51" diff --git a/release/scripts/presets/ffmpeg/SVCD.py b/release/scripts/presets/ffmpeg/SVCD.py index e4459ab5c5c..584f192c3d8 100644 --- a/release/scripts/presets/ffmpeg/SVCD.py +++ b/release/scripts/presets/ffmpeg/SVCD.py @@ -21,4 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 0 bpy.context.scene.render.ffmpeg_audio_bitrate = 224 bpy.context.scene.render.ffmpeg_audio_mixrate = 44100 bpy.context.scene.render.ffmpeg_audio_codec = "MP2" -bpy.context.scene.render.ffmpeg_audio_channels = 2 +bpy.context.scene.render.ffmpeg_audio_channels = "STEREO" diff --git a/release/scripts/presets/ffmpeg/VCD.py b/release/scripts/presets/ffmpeg/VCD.py index c2b73e682a2..35dda07a064 100644 --- a/release/scripts/presets/ffmpeg/VCD.py +++ b/release/scripts/presets/ffmpeg/VCD.py @@ -21,4 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 2352 * 75 * 8 bpy.context.scene.render.ffmpeg_audio_bitrate = 224 bpy.context.scene.render.ffmpeg_audio_mixrate = 44100 bpy.context.scene.render.ffmpeg_audio_codec = "MP2" -bpy.context.scene.render.ffmpeg_audio_channels = 2 +bpy.context.scene.render.ffmpeg_audio_channels = "STEREO" diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index fd3a3fea2bb..b358209a0f4 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -45,9 +45,6 @@ struct rctf; # define DO_INLINE static inline #endif -void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); -void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int w); - struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); void curvemapping_free(struct CurveMapping *cumap); struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index a4cef2d6862..1af2f014ef4 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -75,6 +75,9 @@ extern const CustomDataMask CD_MASK_FACECORNERS; void CustomData_copy(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem); +/* BMESH_TODO, not really a public function but readfile.c needs it */ +void CustomData_update_typemap(struct CustomData *data); + /* same as the above, except that this will preserve existing layers, and only * add the layers that were not there yet */ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, @@ -128,6 +131,7 @@ int CustomData_number_of_layers(const struct CustomData *data, int type); void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem); void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, const int type, const char *name, const int totelem); +int CustomData_is_referenced_layer(struct CustomData *data, int type); /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is * zero for the layer type, so only layer types specified by the mask @@ -144,12 +148,13 @@ void CustomData_set_only_copy(const struct CustomData *data, void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count); +void CustomData_copy_elements(int type, void *source, void *dest, int count); void CustomData_em_copy_data(const struct CustomData *source, struct CustomData *dest, void *src_block, void **dest_block); void CustomData_bmesh_copy_data(const struct CustomData *source, - struct CustomData *dest,void *src_block, - void **dest_block); + struct CustomData *dest, void *src_block, + void **dest_block); void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements); /* frees data in a CustomData object @@ -191,11 +196,18 @@ void CustomData_swap(struct CustomData *data, int index, const int *corner_indic * returns NULL if there is no layer of type */ void *CustomData_get(const struct CustomData *data, int index, int type); +void *CustomData_get_n(const struct CustomData *data, int type, int index, int n); void *CustomData_em_get(const struct CustomData *data, void *block, int type); void *CustomData_em_get_n(const struct CustomData *data, void *block, int type, int n); void *CustomData_bmesh_get(const struct CustomData *data, void *block, int type); void *CustomData_bmesh_get_n(const struct CustomData *data, void *block, int type, int n); +/* gets the layer at physical index n, with no type checking. + */ +void *CustomData_bmesh_get_layer_n(const struct CustomData *data, void *block, int n); + +int CustomData_set_layer_name(const struct CustomData *data, int type, int n, const char *name); + /* gets a pointer to the active or first layer of type * returns NULL if there is no layer of type */ @@ -205,6 +217,7 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type, const char *name); int CustomData_get_layer_index(const struct CustomData *data, int type); +int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n); int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name); int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type); @@ -231,6 +244,11 @@ void CustomData_bmesh_set(const struct CustomData *data, void *block, int type, void CustomData_bmesh_set_n(struct CustomData *data, void *block, int type, int n, void *source); +/*sets the data of the block at physical layer n. no real type checking + *is performed. + */ +void CustomData_bmesh_set_layer_n(struct CustomData *data, void *block, int n, + void *source); /* set the pointer of to the first layer of type. the old data is not freed. * returns the value of ptr if the layer is found, NULL otherwise diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 5ccdd7c04af..7668d5392da 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -141,6 +141,7 @@ typedef struct Global { #define G_FILE_RECOVER (1 << 23) #define G_FILE_RELATIVE_REMAP (1 << 24) #define G_FILE_HISTORY (1 << 25) +#define G_FILE_MESH_COMPAT (1 << 26) /* BMesh option to save as older mesh format */ /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 3e2b2e47be5..d7e2c73aa9d 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -57,6 +57,11 @@ extern "C" { struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me); void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em); +/* for forwards compat only quad->tri polys to mface, skip ngons. + */ +int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, int totface, int totloop, int totpoly); + void unlink_mesh(struct Mesh *me); void free_mesh(struct Mesh *me); struct Mesh *add_mesh(const char *name); @@ -159,6 +164,11 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, int update); void BKE_mesh_ensure_navmesh(struct Mesh *me); +/*convert a triangle of loop facedata to mface facedata*/ +void mesh_loops_to_mface_corners(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, int lindex[4], int findex, + const int polyindex, const int mf_len); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 4d16df8afa3..b41f038941d 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -60,7 +60,7 @@ void BKE_movieclip_update_scopes(struct MovieClip *clip, struct MovieClipUser *u void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUser *user, int *totseg_r, int **points_r); -void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, struct MovieDistortion *distortion, +void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, int clip_flag, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, int undistorted); #define TRACK_CLEAR_UPTO 0 diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 6f088b8abf7..5af3dc15704 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1950,7 +1950,7 @@ void CDDM_calc_edges(DerivedMesh *dm) index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); for(i = 0; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { - BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); med->flag = ME_EDGEDRAW|ME_EDGERENDER; *index = ORIGINDEX_NONE; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 2f568aa01eb..67bd6a22348 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -52,45 +52,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" - -void floatbuf_to_srgb_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w)) -{ - int x, y; - float *rf= rectf; - float srgb[3]; - unsigned char *rc= rectc; - - for(y=y1; y<y2; y++) { - for(x=x1; x<x2; x++, rf+=4, rc+=4) { - srgb[0]= linearrgb_to_srgb(rf[0]); - srgb[1]= linearrgb_to_srgb(rf[1]); - srgb[2]= linearrgb_to_srgb(rf[2]); - - rc[0]= FTOCHAR(srgb[0]); - rc[1]= FTOCHAR(srgb[1]); - rc[2]= FTOCHAR(srgb[2]); - rc[3]= FTOCHAR(rf[3]); - } - } -} - -void floatbuf_to_byte(float *rectf, unsigned char *rectc, int x1, int x2, int y1, int y2, int UNUSED(w)) -{ - int x, y; - float *rf= rectf; - unsigned char *rc= rectc; - - for(y=y1; y<y2; y++) { - for(x=x1; x<x2; x++, rf+=4, rc+=4) { - rc[0]= FTOCHAR(rf[0]); - rc[1]= FTOCHAR(rf[1]); - rc[2]= FTOCHAR(rf[2]); - rc[3]= FTOCHAR(rf[3]); - } - } -} - - /* ********************************* color curve ********************* */ /* ***************** operations on full struct ************* */ diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 289faaa0095..c5bd2ee2757 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -99,6 +99,14 @@ typedef struct LayerTypeInfo { default is assumed to be all zeros */ void (*set_default)(void *data, int count); + /* functions necassary for geometry collapse*/ + int (*equal)(void *data1, void *data2); + void (*multiply)(void *data, float fac); + void (*initminmax)(void *min, void *max); + void (*add)(void *data1, void *data2); + void (*dominmax)(void *data1, void *min, void *max); + void (*copyvalue)(void *source, void *dest); + /* a function to read data from a cdf file */ int (*read)(CDataFile *cdf, void *data, int count); @@ -331,6 +339,24 @@ static void layerDefault_tface(void *data, int count) tf[i] = default_tf; } +static void layerCopy_propFloat(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MFloatProperty)*count); +} + +static void layerCopy_propInt(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MIntProperty)*count); +} + +static void layerCopy_propString(const void *source, void *dest, + int count) +{ + memcpy(dest, source, sizeof(MStringProperty)*count); +} + static void layerCopy_origspace_face(const void *source, void *dest, int count) { const OrigSpaceFace *source_tf = (const OrigSpaceFace*)source; @@ -640,10 +666,83 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), void *data, int count } /* --------- */ +static void layerCopyValue_mloopcol(void *source, void *dest) +{ + MLoopCol *m1 = source, *m2 = dest; + + m2->r = m1->r; + m2->g = m1->g; + m2->b = m1->b; + m2->a = m1->a; +} + +static int layerEqual_mloopcol(void *data1, void *data2) +{ + MLoopCol *m1 = data1, *m2 = data2; + float r, g, b, a; + + r = m1->r - m2->r; + g = m1->g - m2->g; + b = m1->b - m2->b; + a = m1->a - m2->a; + + return r*r + g*g + b*b + a*a < 0.001; +} + +static void layerMultiply_mloopcol(void *data, float fac) +{ + MLoopCol *m = data; + + m->r = (float)m->r * fac; + m->g = (float)m->g * fac; + m->b = (float)m->b * fac; + m->a = (float)m->a * fac; +} + +static void layerAdd_mloopcol(void *data1, void *data2) +{ + MLoopCol *m = data1, *m2 = data2; + + m->r += m2->r; + m->g += m2->g; + m->b += m2->b; + m->a += m2->a; +} + +static void layerDoMinMax_mloopcol(void *data, void *vmin, void *vmax) +{ + MLoopCol *m = data; + MLoopCol *min = vmin, *max = vmax; + + if (m->r < min->r) min->r = m->r; + if (m->g < min->g) min->g = m->g; + if (m->b < min->b) min->b = m->b; + if (m->a < min->a) min->a = m->a; + + if (m->r > max->r) max->r = m->r; + if (m->g > max->g) max->g = m->g; + if (m->b > max->b) max->b = m->b; + if (m->a > max->a) max->a = m->a; +} + +static void layerInitMinMax_mloopcol(void *vmin, void *vmax) +{ + MLoopCol *min = vmin, *max = vmax; + + min->r = 255; + min->g = 255; + min->b = 255; + min->a = 255; + + max->r = 0; + max->g = 0; + max->b = 0; + max->a = 0; +} static void layerDefault_mloopcol(void *data, int count) { - static MLoopCol default_mloopcol = {255,255,255,255}; + MLoopCol default_mloopcol = {255,255,255,255}; MLoopCol *mlcol = (MLoopCol*)data; int i; for(i = 0; i < count; i++) @@ -695,6 +794,56 @@ static void layerInterp_mloopcol(void **sources, float *weights, mc->g = (int)col.g; mc->b = (int)col.b; } + +static void layerCopyValue_mloopuv(void *source, void *dest) +{ + MLoopUV *luv1 = source, *luv2 = dest; + + luv2->uv[0] = luv1->uv[0]; + luv2->uv[1] = luv1->uv[1]; +} + +static int layerEqual_mloopuv(void *data1, void *data2) +{ + MLoopUV *luv1 = data1, *luv2 = data2; + float u, v; + + u = luv1->uv[0] - luv2->uv[0]; + v = luv1->uv[1] - luv2->uv[1]; + + return u*u + v*v < 0.00001; +} + +static void layerMultiply_mloopuv(void *data, float fac) +{ + MLoopUV *luv = data; + + luv->uv[0] *= fac; + luv->uv[1] *= fac; +} + +static void layerInitMinMax_mloopuv(void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax; + + INIT_MINMAX2(min->uv, max->uv); +} + +static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) +{ + MLoopUV *min = vmin, *max = vmax, *luv = data; + + DO_MINMAX2(luv->uv, min->uv, max->uv); +} + +static void layerAdd_mloopuv(void *data1, void *data2) +{ + MLoopUV *l1 = data1, *l2 = data2; + + l1->uv[0] += l2->uv[0]; + l1->uv[1] += l2->uv[1]; +} + static void layerInterp_mloopuv(void **sources, float *weights, float *sub_weights, int count, void *dest) { @@ -798,11 +947,56 @@ static void layerDefault_mcol(void *data, int count) MCol *mcol = (MCol*)data; int i; - for(i = 0; i < 4*count; i++) + for(i = 0; i < 4*count; i++) { mcol[i] = default_mcol; + } } +static void layerInterp_bweight(void **sources, float *weights, + float *UNUSED(sub_weights), int count, void *dest) +{ + float *f = dest; + float **in = (float **)sources; + int i; + + if(count <= 0) return; + + *f = 0.0f; + + if (weights) { + for(i = 0; i < count; ++i) { + *f += *in[i] * weights[i]; + } + } + else { + for(i = 0; i < count; ++i) { + *f += *in[i]; + } + } +} + +static void layerInterp_shapekey(void **sources, float *weights, + float *UNUSED(sub_weights), int count, void *dest) +{ + float *co = dest; + float **in = (float **)sources; + int i; + + if(count <= 0) return; + + zero_v3(co); + if (weights) { + for(i = 0; i < count; ++i) { + madd_v3_v3fl(co, in[i], weights[i]); + } + } + else { + for(i = 0; i < count; ++i) { + add_v3_v3(co, in[i]); + } + } +} static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ @@ -829,14 +1023,14 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 8: CD_NORMAL */ /* 3 floats per normal vector */ {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, - /* 9: CD_FLAGS */ - {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + /* 9: CD_POLYINDEX */ + {sizeof(int), "MIntProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL}, /* 10: CD_PROP_FLT */ - {sizeof(MFloatProperty), "MFloatProperty",1,"Float",NULL,NULL,NULL,NULL}, + {sizeof(MFloatProperty), "MFloatProperty",1,"Float", layerCopy_propFloat,NULL,NULL,NULL}, /* 11: CD_PROP_INT */ - {sizeof(MIntProperty), "MIntProperty",1,"Int",NULL,NULL,NULL,NULL}, + {sizeof(MIntProperty), "MIntProperty",1,"Int",layerCopy_propInt,NULL,NULL,NULL}, /* 12: CD_PROP_STR */ - {sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL}, + {sizeof(MStringProperty), "MStringProperty",1,"String",layerCopy_propString,NULL,NULL,NULL}, /* 13: CD_ORIGSPACE */ {sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVMap", layerCopy_origspace_face, NULL, layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, @@ -845,15 +1039,20 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 15: CD_MTEXPOLY */ {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, /* 16: CD_MLOOPUV */ - {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, + {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL, + layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, + layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, /* 17: CD_MLOOPCOL */ - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, /* 18: CD_TANGENT */ {sizeof(float)*4*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 19: CD_MDISPS */ {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, - layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, - layerFilesize_mdisps, layerValidate_mdisps}, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps, layerValidate_mdisps}, /* 20: CD_WEIGHT_MCOL */ {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, @@ -867,6 +1066,30 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 24: CD_RECAST */ {sizeof(MRecast), "MRecast", 1,"Recast",NULL,NULL,NULL,NULL} + +#ifdef USE_BMESH_FORWARD_COMPAT + , +/* BMESH ONLY */ + /* 25: CD_MPOLY */ + {sizeof(MPoly), "MPoly", 1, "NGon Face", NULL, NULL, NULL, NULL, NULL}, + /* 26: CD_MLOOP */ + {sizeof(MLoop), "MLoop", 1, "NGon Face-Vertex", NULL, NULL, NULL, NULL, NULL}, + /* 27: CD_SHAPE_KEYINDEX */ + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + /* 28: CD_SHAPEKEY */ + {sizeof(float)*3, "", 0, "ShapeKey", NULL, NULL, layerInterp_shapekey}, + /* 29: CD_BWEIGHT */ + {sizeof(float), "", 0, "BevelWeight", NULL, NULL, layerInterp_bweight}, + /* 30: CD_CREASE */ + {sizeof(float), "", 0, "SubSurfCrease", NULL, NULL, layerInterp_bweight}, + /* 31: CD_WEIGHT_MLOOPCOL */ + {sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL, + layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, +/* END BMESH ONLY */ + +#endif /* USE_BMESH_FORWARD_COMPAT */ + }; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -875,6 +1098,13 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", /* 20-24 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast" + +#ifdef USE_BMESH_FORWARD_COMPAT + , + /* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", "CDBevelWeight", + /* 30-31 */ "CDSubSurfCrease", "CDWeightLoopCol" + +#endif /* USE_BMESH_FORWARD_COMPAT */ }; const CustomDataMask CD_MASK_BAREMESH = @@ -896,7 +1126,6 @@ const CustomDataMask CD_MASK_FACECORNERS = CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - static const LayerTypeInfo *layerType_getInfo(int type) { if(type < 0 || type >= CD_NUMTYPES) return NULL; @@ -917,6 +1146,25 @@ static void customData_update_offsets(CustomData *data); static CustomDataLayer *customData_add_layer__internal(CustomData *data, int type, int alloctype, void *layerdata, int totelem, const char *name); +void CustomData_update_typemap(CustomData *data) +{ + int i, lasttype = -1; + + /* since we cant do in a pre-processor do here as an assert */ + BLI_assert(sizeof(data->typemap) / sizeof(int) >= CD_NUMTYPES); + + for (i=0; i<CD_NUMTYPES; i++) { + data->typemap[i] = -1; + } + + for (i=0; i<data->totlayer; i++) { + if (data->layers[i].type != lasttype) { + data->typemap[data->layers[i].type] = i; + } + lasttype = data->layers[i].type; + } +} + void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) { @@ -961,6 +1209,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, newlayer->flag |= lastflag & (CD_FLAG_EXTERNAL|CD_FLAG_IN_MEMORY); } } + + CustomData_update_typemap(dest); } void CustomData_copy(const struct CustomData *source, struct CustomData *dest, @@ -1025,6 +1275,7 @@ static void customData_update_offsets(CustomData *data) } data->totsize = offset; + CustomData_update_typemap(data); } int CustomData_get_layer_index(const CustomData *data, int type) @@ -1038,6 +1289,17 @@ int CustomData_get_layer_index(const CustomData *data, int type) return -1; } +int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n) +{ + int i = CustomData_get_layer_index(data, type); + + if (i != -1) { + i = (data->layers[i + n].type == type) ? (i + n) : (-1); + } + + return i; +} + int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name) { int i; @@ -1051,11 +1313,12 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha int CustomData_get_active_layer_index(const CustomData *data, int type) { - int i; + if (!data->totlayer) + return -1; - for(i=0; i < data->totlayer; ++i) - if(data->layers[i].type == type) - return i + data->layers[i].active; + if (data->typemap[type] != -1) { + return data->typemap[type] + data->layers[data->typemap[type]].active; + } return -1; } @@ -1284,6 +1547,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, data->layers[index].type = type; data->layers[index].flag = flag; data->layers[index].data = newlayerdata; + if(name || (name=typeInfo->defaultname)) { BLI_strncpy(data->layers[index].name, name, 32); CustomData_set_layer_unique_name(data, index); @@ -1316,6 +1580,7 @@ void *CustomData_add_layer(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, typeInfo->defaultname); + CustomData_update_typemap(data); if(layer) return layer->data; @@ -1331,6 +1596,7 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype, layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, name); + CustomData_update_typemap(data); if(layer) return layer->data; @@ -1369,6 +1635,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index) customData_resize(data, -CUSTOMDATA_GROW); customData_update_offsets(data); + CustomData_update_typemap(data); return 1; } @@ -1469,6 +1736,20 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, return layer->data; } +int CustomData_is_referenced_layer(struct CustomData *data, int type) +{ + CustomDataLayer *layer; + int layer_index; + + /* get the layer index of the first layer of type */ + layer_index = CustomData_get_active_layer_index(data, type); + if(layer_index < 0) return 0; + + layer = &data->layers[layer_index]; + + return (layer->flag & CD_FLAG_NOFREE) != 0; +} + void CustomData_free_temporary(CustomData *data, int totelem) { CustomDataLayer *layer; @@ -1495,7 +1776,7 @@ void CustomData_free_temporary(CustomData *data, int totelem) } void CustomData_set_only_copy(const struct CustomData *data, - CustomDataMask mask) + CustomDataMask mask) { int i; @@ -1504,6 +1785,16 @@ void CustomData_set_only_copy(const struct CustomData *data, data->layers[i].flag |= CD_FLAG_NOCOPY; } +void CustomData_copy_elements(int type, void *source, void *dest, int count) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + if (typeInfo->copy) + typeInfo->copy(source, dest, count); + else + memcpy(dest, source, typeInfo->size*count); +} + void CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count) { @@ -1535,7 +1826,14 @@ void CustomData_copy_data(const CustomData *source, CustomData *dest, src_offset = source_index * typeInfo->size; dest_offset = dest_index * typeInfo->size; - + + if (!src_data || !dest_data) { + printf("%s: warning null data for %s type (%p --> %p), skipping\n", + __func__, layerType_getName(source->layers[src_i].type), + (void *)src_data, (void *)dest_data); + continue; + } + if(typeInfo->copy) typeInfo->copy(src_data + src_offset, dest_data + dest_offset, @@ -1663,6 +1961,19 @@ void *CustomData_get(const CustomData *data, int index, int type) return (char *)data->layers[layer_index].data + offset; } +void *CustomData_get_n(const CustomData *data, int type, int index, int n) +{ + int layer_index; + int offset; + + /* get the layer index of the first layer of type */ + layer_index = data->typemap[type]; + if(layer_index < 0) return NULL; + + offset = layerType_getInfo(type)->size * index; + return (char *)data->layers[layer_index+n].data + offset; +} + void *CustomData_get_layer(const CustomData *data, int type) { /* get the layer index of the active layer of type */ @@ -1675,10 +1986,10 @@ void *CustomData_get_layer(const CustomData *data, int type) void *CustomData_get_layer_n(const CustomData *data, int type, int n) { /* get the layer index of the active layer of type */ - int layer_index = CustomData_get_layer_index(data, type); + int layer_index = CustomData_get_layer_index_n(data, type, n); if(layer_index < 0) return NULL; - return data->layers[layer_index+n].data; + return data->layers[layer_index].data; } void *CustomData_get_layer_named(const struct CustomData *data, int type, @@ -1690,6 +2001,20 @@ void *CustomData_get_layer_named(const struct CustomData *data, int type, return data->layers[layer_index].data; } + +int CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name) +{ + /* get the layer index of the first layer of type */ + int layer_index = CustomData_get_layer_index_n(data, type, n); + + if(layer_index < 0) return 0; + if (!name) return 0; + + strcpy(data->layers[layer_index].name, name); + + return 1; +} + void *CustomData_set_layer(const CustomData *data, int type, void *ptr) { /* get the layer index of the first layer of type */ @@ -1705,10 +2030,10 @@ void *CustomData_set_layer(const CustomData *data, int type, void *ptr) void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, void *ptr) { /* get the layer index of the first layer of type */ - int layer_index = CustomData_get_layer_index(data, type); + int layer_index = CustomData_get_layer_index_n(data, type, n); if(layer_index < 0) return NULL; - data->layers[layer_index+n].data = ptr; + data->layers[layer_index].data = ptr; return ptr; } @@ -1836,10 +2161,10 @@ void *CustomData_em_get_n(const CustomData *data, void *block, int type, int n) int layer_index; /* get the layer index of the first layer of type */ - layer_index = CustomData_get_layer_index(data, type); + layer_index = CustomData_get_layer_index_n(data, type, n); if(layer_index < 0) return NULL; - return (char *)block + data->layers[layer_index+n].offset; + return (char *)block + data->layers[layer_index].offset; } void CustomData_em_set(CustomData *data, void *block, int type, void *source) @@ -2141,6 +2466,15 @@ void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int return (char *)block + data->layers[layer_index+n].offset; } +/*gets from the layer at physical index n, note: doesn't check type.*/ +void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n) +{ + if(n < 0 || n >= data->totlayer) return NULL; + + return (char *)block + data->layers[n].offset; +} + + void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source) { void *dest = CustomData_bmesh_get(data, block, type); @@ -2167,6 +2501,19 @@ void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void memcpy(dest, source, typeInfo->size); } +void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *source) +{ + void *dest = CustomData_bmesh_get_layer_n(data, block, n); + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type); + + if(!dest) return; + + if(typeInfo->copy) + typeInfo->copy(source, dest, 1); + else + memcpy(dest, source, typeInfo->size); +} + void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights, float *sub_weights, int count, void *dest_block) { @@ -2212,6 +2559,7 @@ void CustomData_bmesh_set_default(CustomData *data, void **block) if(typeInfo->set_default) typeInfo->set_default((char*)*block + offset, 1); + else memset((char*)*block + offset, 0, typeInfo->size); } } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 4b4875213b1..61604bf1432 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -65,6 +65,10 @@ /* -- */ #include "BKE_object.h" +#ifdef USE_BMESH_FORWARD_COMPAT +#include "BLI_array.h" +#endif + EditMesh *BKE_mesh_get_editmesh(Mesh *me) { @@ -726,7 +730,7 @@ void mball_to_mesh(ListBase *lb, Mesh *me) nors= dl->nors; verts= dl->verts; while(a--) { - VECCOPY(mvert->co, verts); + copy_v3_v3(mvert->co, verts); normal_float_to_short_v3(mvert->no, nors); mvert++; nors+= 3; @@ -1445,6 +1449,175 @@ void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, c } } +#ifdef USE_BMESH_FORWARD_COMPAT + +void mesh_loops_to_mface_corners(CustomData *fdata, CustomData *ldata, + CustomData *pdata, int lindex[4], int findex, + const int polyindex, + const int mf_len /* 3 or 4 */ + ) +{ + MTFace *texface; + MTexPoly *texpoly; + MCol *mcol; + MLoopCol *mloopcol; + MLoopUV *mloopuv; + int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL); + int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY); + int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL); + + for(i=0; i < numTex; i++){ + texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); + texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i); + + texface->tpage = texpoly->tpage; + texface->flag = texpoly->flag; + texface->transp = texpoly->transp; + texface->mode = texpoly->mode; + texface->tile = texpoly->tile; + texface->unwrap = texpoly->unwrap; + + for (j=0; j < mf_len; j++) { + mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, lindex[j], i); + texface->uv[j][0] = mloopuv->uv[0]; + texface->uv[j][1] = mloopuv->uv[1]; + } + } + + for(i=0; i < numCol; i++){ + mcol = CustomData_get_n(fdata, CD_MCOL, findex, i); + + for (j=0; j < mf_len; j++) { + mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, lindex[j], i); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } + + if (hasWCol) { + mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL); + + for (j=0; j < mf_len; j++) { + mloopcol = CustomData_get(ldata, lindex[j], CD_WEIGHT_MLOOPCOL); + mcol[j].r = mloopcol->r; + mcol[j].g = mloopcol->g; + mcol[j].b = mloopcol->b; + mcol[j].a = mloopcol->a; + } + } +} + + +/* + * this function recreates a tesselation. + * returns number of tesselation faces. + */ +int mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, + struct CustomData *pdata, int totface, int UNUSED(totloop), int totpoly) +{ + MLoop *mloop; + + int lindex[4]; + int i; + int k; + + MPoly *mp, *mpoly; + MFace *mface = NULL, *mf; + BLI_array_declare(mface); + + mpoly = CustomData_get_layer(pdata, CD_MPOLY); + mloop = CustomData_get_layer(ldata, CD_MLOOP); + + mp = mpoly; + k = 0; + for (i = 0; i<totpoly; i++, mp++) { + if (ELEM(mp->totloop, 3, 4)) { + BLI_array_growone(mface); + mf = &mface[k]; + + mf->mat_nr = mp->mat_nr; + mf->flag = mp->flag; + + mf->v1 = mp->loopstart + 0; + mf->v2 = mp->loopstart + 1; + mf->v3 = mp->loopstart + 2; + mf->v4 = (mp->totloop == 4) ? (mp->loopstart + 3) : 0; + + /* abuse edcode for temp storage and clear next loop */ + mf->edcode = (char)mp->totloop; /* only ever 3 or 4 */ + + k++; + } + } + + CustomData_free(fdata, totface); + memset(fdata, 0, sizeof(CustomData)); + + totface= k; + + CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface); + + CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + + mp = mpoly; + k = 0; + for (i = 0; i<totpoly; i++, mp++) { + if (ELEM(mp->totloop, 3, 4)) { + mf = &mface[k]; + + if (mf->edcode == 3) { + /*sort loop indices to ensure winding is correct*/ + /* NO SORT - looks like we can skip this */ + + lindex[0] = mf->v1; + lindex[1] = mf->v2; + lindex[2] = mf->v3; + lindex[3] = 0; /* unused */ + + /*transform loop indices to vert indices*/ + mf->v1 = mloop[mf->v1].v; + mf->v2 = mloop[mf->v2].v; + mf->v3 = mloop[mf->v3].v; + + mesh_loops_to_mface_corners(fdata, ldata, pdata, + lindex, k, i, 3); + test_index_face(mf, fdata, totface, 3); + } + else { + /*sort loop indices to ensure winding is correct*/ + /* NO SORT - looks like we can skip this */ + + lindex[0] = mf->v1; + lindex[1] = mf->v2; + lindex[2] = mf->v3; + lindex[3] = mf->v4; + + /*transform loop indices to vert indices*/ + mf->v1 = mloop[mf->v1].v; + mf->v2 = mloop[mf->v2].v; + mf->v3 = mloop[mf->v3].v; + mf->v4 = mloop[mf->v4].v; + + mesh_loops_to_mface_corners(fdata, ldata, pdata, + lindex, k, i, 4); + test_index_face(mf, fdata, totface, 4); + } + + mf->edcode= 0; + + k++; + } + } + + return k; +} + +#endif /* USE_BMESH_FORWARD_COMPAT */ + + + /* basic vertex data functions */ int minmax_mesh(Mesh *me, float min[3], float max[3]) { diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index a1bf9cb9481..ed9b63fe98d 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -509,7 +509,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) if(update && (med_orig=BLI_edgehashIterator_getValue(ehi))) { *med= *med_orig; /* copy from the original */ } else { - BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2); + BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); med->flag = ME_EDGEDRAW|ME_EDGERENDER|SELECT; /* select for newly created meshes which are selected [#25595] */ } } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 224ce003ea3..ab963f1e78c 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -921,15 +921,17 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i IMB_freeImBuf(scaleibuf); } -void BKE_movieclip_build_proxy_frame(MovieClip *clip, struct MovieDistortion *distortion, +void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, int undistorted) { ImBuf *ibuf; MovieClipUser user; user.framenr= cfra; + user.render_flag= 0; + user.render_size= MCLIP_PROXY_RENDER_SIZE_FULL; - ibuf= BKE_movieclip_get_ibuf_flag(clip, &user, 0); + ibuf= BKE_movieclip_get_ibuf_flag(clip, &user, clip_flag); if(ibuf) { ImBuf *tmpibuf= ibuf; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 0b58d1562fa..b75a9ff0037 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -780,6 +780,7 @@ typedef struct TrackContext { typedef struct MovieTrackingContext { MovieClipUser user; MovieClip *clip; + int clip_flag; int first_time, frames; @@ -882,7 +883,20 @@ MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *u } context->clip= clip; + + /* store needed clip flags passing to get_buffer functions + * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip + * only in case Proxy/Timecode flag is set, so store this flag to use + * timecodes properly but reset render size to SIZE_FULL so correct resolution + * would be used for images + * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might + * be stored in a different location + * ignore all the rest pssible flags for now */ + context->clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS; + context->user= *user; + context->user.render_size= 0; + context->user.render_flag= MCLIP_PROXY_RENDER_SIZE_FULL; if(!sequence) BLI_begin_threaded_malloc(); @@ -1119,7 +1133,7 @@ static ImBuf *get_frame_ibuf(MovieTrackingContext *context, int framenr) user.framenr= framenr; - ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, 0); + ibuf= BKE_movieclip_get_ibuf_flag(context->clip, &user, context->clip_flag); return ibuf; } @@ -1223,7 +1237,7 @@ int BKE_tracking_next(MovieTrackingContext *context) if(context->backwards) context->user.framenr--; else context->user.framenr++; - ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, 0); + ibuf_new= BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag); if(!ibuf_new) return 0; diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h new file mode 100644 index 00000000000..bd14793e0f9 --- /dev/null +++ b/source/blender/blenlib/BLI_array.h @@ -0,0 +1,185 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joseph Eagar. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* + * this library needs to be changed to not use macros quite so heavily, + * and to be more of a complete array API. The way arrays are + * exposed to client code as normal C arrays is very useful though, imho. + * it does require some use of macros, however. + * + * anyway, it's used a bit too heavily to simply rewrite as a + * more "correct" solution without macros entirely. I originally wrote this + * to be very easy to use, without the normal pain of most array libraries. + * This was especially helpful when it came to the massive refactors necessary + * for bmesh, and really helped to speed the process up. - joeedh + * + * little array macro library. example of usage: + * + * int *arr = NULL; + * BLI_array_declare(arr); + * int i; + * + * for (i=0; i<10; i++) { + * BLI_array_growone(arr); + * arr[i] = something; + * } + * BLI_array_free(arr); + * + * arrays are buffered, using double-buffering (so on each reallocation, + * the array size is doubled). supposedly this should give good Big Oh + * behaviour, though it may not be the best in practice. + */ + +#define BLI_array_declare(arr) \ + int _##arr##_count = 0; \ + void *_##arr##_tmp; \ + void *_##arr##_static = NULL + +/* this will use stack space, up to maxstatic array elements, before + * switching to dynamic heap allocation */ +#define BLI_array_staticdeclare(arr, maxstatic) \ + int _##arr##_count = 0; \ + void *_##arr##_tmp; \ + char _##arr##_static[maxstatic*sizeof(arr)] + + +/* this returns the entire size of the array, including any buffering. */ +#define BLI_array_totalsize_dyn(arr) ( \ + ((arr)==NULL) ? \ + 0 : \ + MEM_allocN_len(arr) / sizeof(*arr) \ +) + + +#define BLI_array_totalsize(arr) ( \ + (size_t) \ + (((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \ + (sizeof(_##arr##_static) / sizeof(*arr)) : \ + BLI_array_totalsize_dyn(arr)) \ +) + + +/* this returns the logical size of the array, not including buffering. */ +#define BLI_array_count(arr) _##arr##_count + +/* Grow the array by a fixed number of items. zeroes the new elements. + * + * Allow for a large 'num' value when the new size is more then double + * to allocate the exact sized array. */ +#define _bli_array_grow_items(arr, num) ( \ + (BLI_array_totalsize(arr) >= _##arr##_count + num) ? \ + (_##arr##_count += num) : \ + ( \ + (void) (_##arr##_tmp = MEM_callocN( \ + sizeof(*arr) * (num < _##arr##_count ? \ + (_##arr##_count * 2 + 2) : \ + (_##arr##_count + num)), \ + #arr " " __FILE__ ":" STRINGIFY(__LINE__) \ + ) \ + ), \ + (void) (arr && memcpy(_##arr##_tmp, \ + arr, \ + sizeof(*arr) * _##arr##_count) \ + ), \ + (void) (arr && ((void *)(arr) != (void*)_##arr##_static ? \ + (MEM_freeN(arr), arr) : \ + arr) \ + ), \ + (void) (arr = _##arr##_tmp \ + ), \ + (_##arr##_count += num) \ + ) \ +) + +/* grow an array by a specified number of items */ +#define BLI_array_growitems(arr, num) ( \ + ((void *)(arr)==NULL && (void *)(_##arr##_static) != NULL) ? \ + ((arr= (void*)_##arr##_static), (_##arr##_count += num)) : \ + _bli_array_grow_items(arr, num) \ +) + +/* returns length of array */ +#define BLI_array_growone(arr) BLI_array_growitems(arr, 1) + + +/* appends an item to the array. */ +#define BLI_array_append(arr, item) ( \ + (void) BLI_array_growone(arr), \ + (void) (arr[_##arr##_count - 1] = item) \ +) + +/* appends an item to the array and returns a pointer to the item in the array. + * item is not a pointer, but actual data value.*/ +#define BLI_array_append_r(arr, item) ( \ + (void) BLI_array_growone(arr), \ + (void) (arr[_##arr##_count - 1] = item), \ + (&arr[_##arr##_count - 1]) \ +) + +#define BLI_array_free(arr) \ + if (arr && (char *)arr != _##arr##_static) { \ + BLI_array_fake_user(arr); \ + MEM_freeN(arr); \ + } + +#define BLI_array_pop(arr) ( \ + (arr&&_##arr##_count) ? \ + arr[--_##arr##_count] : \ + 0 \ +) + +/* resets the logical size of an array to zero, but doesn't + * free the memory. */ +#define BLI_array_empty(arr) \ + _##arr##_count=0 + +/* set the count of the array, doesn't actually increase the allocated array + * size. don't use this unless you know what you're doing. */ +#define BLI_array_set_length(arr, count) \ + _##arr##_count = (count) + +/* only to prevent unused warnings */ +#define BLI_array_fake_user(arr) \ + (void)_##arr##_count, \ + (void)_##arr##_tmp, \ + (void)_##arr##_static + + +/* not part of the 'API' but handy funcs, + * same purpose as BLI_array_staticdeclare() + * but use when the max size is known ahead of time */ +#define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \ + char _##arr##_static[maxstatic*sizeof(*arr)]; \ + const int _##arr##_is_static= ((void *)_##arr##_static) != ( \ + arr= (realsize <= maxstatic) ? \ + (void *)_##arr##_static : \ + MEM_mallocN(sizeof(*arr)*realsize, allocstr) \ + ) \ + +#define BLI_array_fixedstack_free(arr) \ + if (_##arr##_is_static) MEM_freeN(arr) \ + diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h index 283b52e06b9..9153155e359 100644 --- a/source/blender/blenlib/BLI_edgehash.h +++ b/source/blender/blenlib/BLI_edgehash.h @@ -47,22 +47,22 @@ void BLI_edgehash_free (EdgeHash *eh, EdgeHashFreeFP valfreefp); /* Insert edge (v0,v1) into hash with given value, does * not check for duplicates. */ -void BLI_edgehash_insert (EdgeHash *eh, int v0, int v1, void *val); +void BLI_edgehash_insert (EdgeHash *eh, unsigned int v0, unsigned int v1, void *val); /* Return value for given edge (v0,v1), or NULL if * if key does not exist in hash. (If need exists * to differentiate between key-value being NULL and * lack of key then see BLI_edgehash_lookup_p(). */ -void* BLI_edgehash_lookup (EdgeHash *eh, int v0, int v1); +void* BLI_edgehash_lookup (EdgeHash *eh, unsigned int v0, unsigned int v1); /* Return pointer to value for given edge (v0,v1), * or NULL if key does not exist in hash. */ -void** BLI_edgehash_lookup_p (EdgeHash *eh, int v0, int v1); +void** BLI_edgehash_lookup_p (EdgeHash *eh, unsigned int v0, unsigned int v1); /* Return boolean true/false if edge (v0,v1) in hash. */ -int BLI_edgehash_haskey (EdgeHash *eh, int v0, int v1); +int BLI_edgehash_haskey (EdgeHash *eh, unsigned int v0, unsigned int v1); /* Return number of keys in hash. */ int BLI_edgehash_size (EdgeHash *eh); @@ -83,7 +83,7 @@ EdgeHashIterator* BLI_edgehashIterator_new (EdgeHash *eh); void BLI_edgehashIterator_free (EdgeHashIterator *ehi); /* Retrieve the key from an iterator. */ -void BLI_edgehashIterator_getKey (EdgeHashIterator *ehi, int *v0_r, int *v1_r); +void BLI_edgehashIterator_getKey (EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r); /* Retrieve the value from an iterator. */ void* BLI_edgehashIterator_getValue (EdgeHashIterator *ehi); @@ -98,4 +98,3 @@ void BLI_edgehashIterator_step (EdgeHashIterator *ehi); int BLI_edgehashIterator_isDone (EdgeHashIterator *ehi); #endif - diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 0e33ee2be3f..7fbb4680b6d 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -34,6 +34,8 @@ extern "C" { #endif +#include "BLI_math_inline.h" + /* primaries */ #define BLI_XYZ_SMPTE 0 #define BLI_XYZ_REC709_SRGB 1 @@ -48,7 +50,7 @@ extern "C" { #define BLI_YCC_ITU_BT601 0 #define BLI_YCC_ITU_BT709 1 #define BLI_YCC_JFIF_0_255 2 - + /******************* Conversion to RGB ********************/ void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b); @@ -70,22 +72,23 @@ unsigned int hsv_to_cpack(float h, float s, float v); float rgb_to_grayscale(float rgb[3]); unsigned char rgb_to_grayscale_byte(unsigned char rgb[3]); -/***************** Profile Transformations ********************/ +/**************** Profile Transformations *****************/ void gamma_correct(float *c, float gamma); float rec709_to_linearrgb(float c); float linearrgb_to_rec709(float c); float srgb_to_linearrgb(float c); float linearrgb_to_srgb(float c); -void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from); -void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from); - -/* rgba buffer convenience functions */ -void srgb_to_linearrgb_rgba_buf(float *col, int tot); -void linearrgb_to_srgb_rgba_buf(float *col, int tot); -void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot); -void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot); - + +MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]); +MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]); + +MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]); +MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]); + +MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]); +MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]); + /************************** Other *************************/ int constrain_rgb(float *r, float *g, float *b); @@ -101,6 +104,10 @@ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *o void rgb_byte_to_float(const unsigned char *in, float *out); void rgb_float_to_byte(const float *in, unsigned char *out); +#ifdef BLI_MATH_INLINE_H +#include "intern/math_color_inline.c" +#endif + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index fb9b8021b8e..a03aee7cb7c 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -87,6 +87,7 @@ set(SRC intern/voxel.c intern/winstuff.c + BLI_array.h BLI_args.h BLI_blenlib.h BLI_boxpack2d.h diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index 7ae68101154..b710e5d496d 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -20,7 +20,7 @@ * * The Original Code is: none of this file. * - * Contributor(s): Daniel Dunbar + * Contributor(s): Daniel Dunbar, Joseph Eagar * * ***** END GPL LICENSE BLOCK ***** * A general (pointer -> pointer) hash table ADT @@ -35,30 +35,41 @@ #include <string.h> #include "MEM_guardedalloc.h" -#include "BLI_edgehash.h" -/***/ +#include "BLI_utildefines.h" +#include "BLI_edgehash.h" +#include "BLI_mempool.h" -static unsigned int hashsizes[]= { - 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, - 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, - 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, +/**************inlined code************/ +static unsigned int _ehash_hashsizes[]= { + 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, + 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, + 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459 }; -#define EDGEHASH(v0,v1) ((v0*39)^(v1*31)) +#define EDGE_HASH(v0, v1) ((v0 * 39)^(v1 * 31)) + +/* ensure v0 is smaller */ +#define EDGE_ORD(v0, v1) \ + if (v0 < v1) { \ + v0 ^= v1; \ + v1 ^= v0; \ + v0 ^= v1; \ + } /***/ -typedef struct Entry Entry; -struct Entry { - Entry *next; - int v0, v1; +typedef struct EdgeEntry EdgeEntry; +struct EdgeEntry { + EdgeEntry *next; + unsigned int v0, v1; void *val; }; struct EdgeHash { - Entry **buckets; + EdgeEntry **buckets; + BLI_mempool *epool; int nbuckets, nentries, cursize; }; @@ -66,87 +77,82 @@ struct EdgeHash { EdgeHash *BLI_edgehash_new(void) { - EdgeHash *eh= MEM_mallocN(sizeof(*eh), "EdgeHash"); - eh->cursize= 0; - eh->nentries= 0; - eh->nbuckets= hashsizes[eh->cursize]; - - eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets)); - memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets)); + EdgeHash *eh = MEM_callocN(sizeof(*eh), "EdgeHash"); + eh->cursize = 0; + eh->nentries = 0; + eh->nbuckets = _ehash_hashsizes[eh->cursize]; + eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets 2"); + eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, TRUE, FALSE); + return eh; } -void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) + +void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val) { unsigned int hash; - Entry *e= malloc(sizeof(*e)); + EdgeEntry *e = BLI_mempool_alloc(eh->epool); - if (v1<v0) { - v0 ^= v1; - v1 ^= v0; - v0 ^= v1; - } - hash = EDGEHASH(v0,v1)%eh->nbuckets; + EDGE_ORD(v0, v1); /* ensure v0 is smaller */ + + hash = EDGE_HASH(v0, v1) % eh->nbuckets; e->v0 = v0; e->v1 = v1; e->val = val; - e->next= eh->buckets[hash]; + e->next = eh->buckets[hash]; eh->buckets[hash]= e; - - if (++eh->nentries>eh->nbuckets*3) { - Entry **old= eh->buckets; - int i, nold= eh->nbuckets; - - eh->nbuckets= hashsizes[++eh->cursize]; - eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets)); - memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets)); - - for (i=0; i<nold; i++) { - for (e= old[i]; e;) { - Entry *n= e->next; - - hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets; - e->next= eh->buckets[hash]; + + if (++eh->nentries>eh->nbuckets * 3) { + EdgeEntry *e, **old = eh->buckets; + int i, nold = eh->nbuckets; + + eh->nbuckets = _ehash_hashsizes[++eh->cursize]; + eh->buckets = MEM_mallocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets"); + memset(eh->buckets, 0, eh->nbuckets * sizeof(*eh->buckets)); + + for (i = 0; i < nold; i++) { + for (e = old[i]; e;) { + EdgeEntry *n = e->next; + + hash = EDGE_HASH(e->v0, e->v1) % eh->nbuckets; + e->next = eh->buckets[hash]; eh->buckets[hash]= e; - - e= n; + + e = n; } } - - free(old); + + MEM_freeN(old); } } -void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) +void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) { unsigned int hash; - Entry *e; + EdgeEntry *e; - if (v1<v0) { - v0 ^= v1; - v1 ^= v0; - v0 ^= v1; - } - hash = EDGEHASH(v0,v1)%eh->nbuckets; - for (e= eh->buckets[hash]; e; e= e->next) - if (v0==e->v0 && v1==e->v1) + EDGE_ORD(v0, v1); /* ensure v0 is smaller */ + + hash = EDGE_HASH(v0, v1) % eh->nbuckets; + for (e = eh->buckets[hash]; e; e = e->next) + if (v0 == e->v0 && v1 == e->v1) return &e->val; - + return NULL; } -void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) +void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) { - void **value_p = BLI_edgehash_lookup_p(eh,v0,v1); + void **value_p = BLI_edgehash_lookup_p(eh, v0, v1); return value_p?*value_p:NULL; } -int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) +int BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1) { - return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL; + return BLI_edgehash_lookup_p(eh, v0, v1) != NULL; } int BLI_edgehash_size(EdgeHash *eh) @@ -158,28 +164,30 @@ void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) { int i; - for (i=0; i<eh->nbuckets; i++) { - Entry *e; + for (i = 0; i<eh->nbuckets; i++) { + EdgeEntry *e; - for (e= eh->buckets[i]; e; ) { - Entry *n= e->next; + for (e = eh->buckets[i]; e; ) { + EdgeEntry *n = e->next; if (valfreefp) valfreefp(e->val); - free(e); + BLI_mempool_free(eh->epool, e); - e= n; + e = n; } - eh->buckets[i]= NULL; + eh->buckets[i] = NULL; } - eh->nentries= 0; + eh->nentries = 0; } void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) { BLI_edgehash_clear(eh, valfreefp); - - free(eh->buckets); + + BLI_mempool_destroy(eh->epool); + + MEM_freeN(eh->buckets); MEM_freeN(eh); } @@ -189,29 +197,29 @@ void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) struct EdgeHashIterator { EdgeHash *eh; int curBucket; - Entry *curEntry; + EdgeEntry *curEntry; }; EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) { - EdgeHashIterator *ehi= malloc(sizeof(*ehi)); - ehi->eh= eh; - ehi->curEntry= NULL; - ehi->curBucket= -1; + EdgeHashIterator *ehi = MEM_mallocN(sizeof(*ehi), "eh iter"); + ehi->eh = eh; + ehi->curEntry = NULL; + ehi->curBucket = -1; while (!ehi->curEntry) { ehi->curBucket++; - if (ehi->curBucket==ehi->eh->nbuckets) + if (ehi->curBucket == ehi->eh->nbuckets) break; - ehi->curEntry= ehi->eh->buckets[ehi->curBucket]; + ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; } return ehi; } void BLI_edgehashIterator_free(EdgeHashIterator *ehi) { - free(ehi); + MEM_freeN(ehi); } -void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, int *v0_r, int *v1_r) +void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r) { if (ehi->curEntry) { *v0_r = ehi->curEntry->v0; @@ -225,19 +233,22 @@ void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) { - if(ehi->curEntry) - ehi->curEntry->val= val; + if (ehi->curEntry) { + ehi->curEntry->val = val; + } } void BLI_edgehashIterator_step(EdgeHashIterator *ehi) { if (ehi->curEntry) { - ehi->curEntry= ehi->curEntry->next; + ehi->curEntry = ehi->curEntry->next; while (!ehi->curEntry) { ehi->curBucket++; - if (ehi->curBucket==ehi->eh->nbuckets) + if (ehi->curBucket == ehi->eh->nbuckets) { break; - ehi->curEntry= ehi->eh->buckets[ehi->curBucket]; + } + + ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; } } } diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 2ef29c1ce94..8f5366b6317 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -393,57 +393,6 @@ float linearrgb_to_srgb(float c) return 1.055f * powf(c, 1.0f/2.4f) - 0.055f; } -void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from) -{ - col_to[0] = srgb_to_linearrgb(col_from[0]); - col_to[1] = srgb_to_linearrgb(col_from[1]); - col_to[2] = srgb_to_linearrgb(col_from[2]); -} - -void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from) -{ - col_to[0] = linearrgb_to_srgb(col_from[0]); - col_to[1] = linearrgb_to_srgb(col_from[1]); - col_to[2] = linearrgb_to_srgb(col_from[2]); -} - -/* todo, should these be moved elsewhere?, they dont belong in imbuf */ -void srgb_to_linearrgb_rgba_buf(float *col, int tot) -{ - while(tot--) { - srgb_to_linearrgb_v3_v3(col, col); - col += 4; - } -} - -void linearrgb_to_srgb_rgba_buf(float *col, int tot) -{ - while(tot--) { - linearrgb_to_srgb_v3_v3(col, col); - col += 4; - } -} - -void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot) -{ - while(tot--) { - srgb_to_linearrgb_v3_v3(col_to, col_from); - col_to[3]= col_from[3]; - col_to += 4; - col_from += 4; - } -} - -void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot) -{ - while(tot--) { - linearrgb_to_srgb_v3_v3(col_to, col_from); - col_to[3]= col_from[3]; - col_to += 4; - col_from += 4; - } -} - void minmax_rgb(short c[]) { if(c[0]>255) c[0]=255; diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c new file mode 100644 index 00000000000..aaaa065f14d --- /dev/null +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -0,0 +1,109 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: some of this file. + * + * ***** END GPL LICENSE BLOCK ***** + * */ + +/** \file blender/blenlib/intern/math_color_inline.c + * \ingroup bli + */ + + +#include "BLI_math_color.h" +#include "BLI_utildefines.h" + +#ifndef BLI_MATH_COLOR_INLINE_H +#define BLI_MATH_COLOR_INLINE_H + +/******************************** Color Space ********************************/ + +MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3]) +{ + linear[0] = srgb_to_linearrgb(srgb[0]); + linear[1] = srgb_to_linearrgb(srgb[1]); + linear[2] = srgb_to_linearrgb(srgb[2]); +} + +MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3]) +{ + srgb[0] = linearrgb_to_srgb(linear[0]); + srgb[1] = linearrgb_to_srgb(linear[1]); + srgb[2] = linearrgb_to_srgb(linear[2]); +} + +MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4]) +{ + srgb_to_linearrgb_v3_v3(linear, srgb); + linear[3] = srgb[3]; +} + +MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4]) +{ + linearrgb_to_srgb_v3_v3(srgb, linear); + srgb[3] = linear[3]; +} + +/* predivide versions to work on associated/premultipled alpha. if this should + be done or not depends on the background the image will be composited over, + ideally you would never do color space conversion on an image with alpha + because it is ill defined */ + +MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4]) +{ + float alpha, inv_alpha; + + if(srgb[3] == 1.0f || srgb[3] == 0.0f) { + alpha = 1.0f; + inv_alpha = 1.0f; + } + else { + alpha = srgb[3]; + inv_alpha = 1.0f/alpha; + } + + linear[0] = srgb_to_linearrgb(srgb[0] * inv_alpha) * alpha; + linear[1] = srgb_to_linearrgb(srgb[1] * inv_alpha) * alpha; + linear[2] = srgb_to_linearrgb(srgb[2] * inv_alpha) * alpha; + linear[3] = srgb[3]; +} + +MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4]) +{ + float alpha, inv_alpha; + + if(linear[3] == 1.0f || linear[3] == 0.0f) { + alpha = 1.0f; + inv_alpha = 1.0f; + } + else { + alpha = linear[3]; + inv_alpha = 1.0f/alpha; + } + + srgb[0] = linearrgb_to_srgb(linear[0] * inv_alpha) * alpha; + srgb[1] = linearrgb_to_srgb(linear[1] * inv_alpha) * alpha; + srgb[2] = linearrgb_to_srgb(linear[2] * inv_alpha) * alpha; + srgb[3] = linear[3]; +} + +#endif /* BLI_MATH_COLOR_INLINE_H */ + diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index eb4b10361d8..59a34a706ee 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3680,6 +3680,7 @@ static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps, int exte } } +/*this isn't really a public api function, so prototyped here*/ static void direct_link_customdata(FileData *fd, CustomData *data, int count) { int i = 0; @@ -3700,6 +3701,8 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count) i++; } } + + CustomData_update_typemap(data); } static void direct_link_mesh(FileData *fd, Mesh *mesh) @@ -3728,6 +3731,36 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) direct_link_customdata(fd, &mesh->edata, mesh->totedge); direct_link_customdata(fd, &mesh->fdata, mesh->totface); + +#ifdef USE_BMESH_FORWARD_COMPAT + /* NEVER ENABLE THIS CODE INTO BMESH! + * THIS IS FOR LOADING BMESH INTO OLDER FILES ONLY */ + mesh->mpoly= newdataadr(fd, mesh->mpoly); + mesh->mloop= newdataadr(fd, mesh->mloop); + + direct_link_customdata(fd, &mesh->pdata, mesh->totpoly); + direct_link_customdata(fd, &mesh->ldata, mesh->totloop); + + if (mesh->mpoly) { + /* be clever and load polygons as mfaces */ + + mesh->totface= mesh_mpoly_to_mface(&mesh->fdata, &mesh->ldata, &mesh->pdata, + mesh->totface, mesh->totloop, mesh->totpoly); + + CustomData_free(&mesh->pdata, mesh->totpoly); + memset(&mesh->pdata, 0, sizeof(CustomData)); + mesh->totpoly = 0; + + CustomData_free(&mesh->ldata, mesh->totloop); + memset(&mesh->ldata, 0, sizeof(CustomData)); + mesh->totloop = 0; + + mesh_update_customdata_pointers(mesh); + } + +#endif + + mesh->bb= NULL; mesh->mselect = NULL; mesh->edit_mesh= NULL; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 4828e9703fb..7cde4c8a1e2 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -174,6 +174,10 @@ typedef struct { MemFile *compare, *current; int tot, count, error, memsize; + +#ifdef USE_BMESH_SAVE_AS_COMPAT + char use_mesh_compat; /* option to save with older mesh format */ +#endif } WriteData; static WriteData *writedata_new(int file) @@ -2595,7 +2599,10 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) fg.curscene= screen->scene; fg.displaymode= G.displaymode; fg.winpos= G.winpos; - fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP)); // prevent to save this, is not good convention, and feature with concerns... + + /* prevent to save this, is not good convention, and feature with concerns... */ + fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP|G_FILE_MESH_COMPAT)); + fg.globalf= G.f; BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename)); @@ -2638,7 +2645,11 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil blo_split_main(&mainlist, mainvar); wd= bgnwrite(handle, compare, current); - + +#ifdef USE_BMESH_SAVE_AS_COMPAT + wd->use_mesh_compat = (write_flags & G_FILE_MESH_COMPAT) != 0; +#endif + sprintf(buf, "BLENDER%c%c%.3d", (sizeof(void*)==8)?'-':'_', (ENDIAN_ORDER==B_ENDIAN)?'V':'v', BLENDER_VERSION); mywrite(wd, buf, 12); diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c index 5e8105d507a..8dea636f0b6 100644 --- a/source/blender/editors/mesh/editmesh_lib.c +++ b/source/blender/editors/mesh/editmesh_lib.c @@ -2412,7 +2412,7 @@ void EM_make_hq_normals(EditMesh *em) EdgeHash *edge_hash = BLI_edgehash_new(); EdgeHashIterator *edge_iter; int edge_ref_count = 0; - int ed_v1, ed_v2; /* use when getting the key */ + unsigned int ed_v1, ed_v2; /* use when getting the key */ EdgeFaceRef *edge_ref_array = MEM_callocN(em->totedge * sizeof(EdgeFaceRef), "Edge Connectivity"); EdgeFaceRef *edge_ref; float edge_normal[3]; @@ -2426,15 +2426,20 @@ void EM_make_hq_normals(EditMesh *em) /* This function adds an edge hash if its not there, and adds the face index */ #define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \ - edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \ + { \ + const unsigned int mf_v1 = EDV1; \ + const unsigned int mf_v2 = EDV2; \ + edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, mf_v1, mf_v2); \ if (!edge_ref) { \ edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ - edge_ref->f1=i; \ - edge_ref->f2=-1; \ - BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \ - } else { \ - edge_ref->f2=i; \ - } + edge_ref->f1 = i; \ + edge_ref->f2 = -1; \ + BLI_edgehash_insert(edge_hash, mf_v1, mf_v2, edge_ref); \ + } \ + else { \ + edge_ref->f2 = i; \ + } \ + } efa= em->faces.first; @@ -2456,7 +2461,7 @@ void EM_make_hq_normals(EditMesh *em) for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { /* Get the edge vert indices, and edge value (the face indices that use it)*/ - BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2); + BLI_edgehashIterator_getKey(edge_iter, &ed_v1, &ed_v2); edge_ref = BLI_edgehashIterator_getValue(edge_iter); if (edge_ref->f2 != -1) { diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 8a580627da3..bff93fea067 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -76,10 +76,10 @@ /* called inside thread! */ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect) { - float x1, y1, *rectf= NULL; + float *rectf= NULL; int ymin, ymax, xmin, xmax; - int rymin, rxmin, do_color_management; - char *rectc; + int rymin, rxmin, predivide, profile_from; + unsigned char *rectc; /* if renrect argument, we only refresh scanlines */ if(renrect) { @@ -136,50 +136,17 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat imb_addrectImBuf(ibuf); rectf+= 4*(rr->rectx*ymin + xmin); - rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin); + rectc= (unsigned char*)(ibuf->rect + ibuf->x*rymin + rxmin); - do_color_management = (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)); - - /* XXX make nice consistent functions for this */ - for(y1= 0; y1<ymax; y1++) { - float *rf= rectf; - float srgb[3]; - char *rc= rectc; - const float dither = ibuf->dither / 255.0f; - - /* XXX temp. because crop offset */ - if(rectc >= (char *)(ibuf->rect)) { - for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) { - /* color management */ - if(do_color_management) { - srgb[0]= linearrgb_to_srgb(rf[0]); - srgb[1]= linearrgb_to_srgb(rf[1]); - srgb[2]= linearrgb_to_srgb(rf[2]); - } - else { - copy_v3_v3(srgb, rf); - } - - /* dither */ - if(dither != 0.0f) { - const float d = (BLI_frand()-0.5f)*dither; - - srgb[0] += d; - srgb[1] += d; - srgb[2] += d; - } - - /* write */ - rc[0]= FTOCHAR(srgb[0]); - rc[1]= FTOCHAR(srgb[1]); - rc[2]= FTOCHAR(srgb[2]); - rc[3]= FTOCHAR(rf[3]); - } - } + if(scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) + profile_from= IB_PROFILE_LINEAR_RGB; + else + profile_from= IB_PROFILE_SRGB; + predivide= 0; - rectf += 4*rr->rectx; - rectc += 4*ibuf->x; - } + IMB_buffer_byte_from_float(rectc, rectf, + 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + xmax, ymax, ibuf->x, rr->rectx); } /* ****************************** render invoking ***************** */ diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 35b21c626ed..be4d54ae2e8 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -206,14 +206,11 @@ static void screen_opengl_render_apply(OGLRender *oglrender) * float buffer. */ if(oglrender->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - float *rctf = rr->rectf; - int i; + int predivide= 0; /* no alpha */ - for (i = oglrender->sizex * oglrender->sizey; i > 0; i--, rctf+=4) { - rctf[0]= srgb_to_linearrgb(rctf[0]); - rctf[1]= srgb_to_linearrgb(rctf[1]); - rctf[2]= srgb_to_linearrgb(rctf[2]); - } + IMB_buffer_float_from_float(rr->rectf, rr->rectf, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, + oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } RE_ReleaseResult(oglrender->re); diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 0bba9838005..8f04940efd6 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -45,6 +45,9 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif @@ -563,17 +566,17 @@ void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void * void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int UNUSED(row_w), float *rectf, int do_gamma_correct) { unsigned char *rect32; + int profile_from= (do_gamma_correct)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; /* copy imgw-imgh to a temporal 32 bits rect */ if(img_w<1 || img_h<1) return; rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits"); - if (do_gamma_correct) { - floatbuf_to_srgb_byte(rectf, rect32, 0, img_w, 0, img_h, img_w); - } else { - floatbuf_to_byte(rectf, rect32, 0, img_w, 0, img_h, img_w); - } + IMB_buffer_byte_from_float(rect32, rectf, + 4, 0, IB_PROFILE_SRGB, profile_from, predivide, + img_w, img_h, img_w, img_w); glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 34726732a17..fe0b58ddda9 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -827,6 +827,7 @@ typedef struct ProxyBuildJob { Scene *scene; struct Main *main; MovieClip *clip; + int clip_flag; } ProxyJob; static void proxy_freejob(void *pjv) @@ -877,10 +878,10 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog for(cfra= sfra; cfra<=efra; cfra++) { if(clip->source != MCLIP_SRC_MOVIE) - BKE_movieclip_build_proxy_frame(clip, NULL, cfra, build_sizes, build_count, 0); + BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, NULL, cfra, build_sizes, build_count, 0); if(undistort) - BKE_movieclip_build_proxy_frame(clip, distortion, cfra, build_sizes, build_count, 1); + BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, distortion, cfra, build_sizes, build_count, 1); if(*stop || G.afbreek) break; @@ -911,6 +912,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) pj->scene= scene; pj->main= CTX_data_main(C); pj->clip= clip; + pj->clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS; WM_jobs_customdata(steve, pj, proxy_freejob); WM_jobs_timer(steve, 0.2, NC_MOVIECLIP|ND_DISPLAY, 0); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index dd5b78c5b8d..918fc5f347d 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -2738,7 +2738,8 @@ static int detect_features_exec(bContext *C, wmOperator *op) { SpaceClip *sc= CTX_wm_space_clip(C); MovieClip *clip= ED_space_clip(sc); - ImBuf *ibuf= BKE_movieclip_get_ibuf_flag(clip, &sc->user, 0); + int clip_flag= clip->flag&MCLIP_TIMECODE_FLAGS; + ImBuf *ibuf= BKE_movieclip_get_ibuf_flag(clip, &sc->user, clip_flag); MovieTracking *tracking= &clip->tracking; ListBase *tracksbase= BKE_tracking_get_tracks(tracking); MovieTrackingTrack *track= tracksbase->first; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 79c08c8dea9..7f54821c98d 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2811,28 +2811,34 @@ static void draw_em_indices(EditMesh *em) /* For now, reuse appropriate theme colors from stats text colors */ - UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); - for (v = em->verts.first, i = 0; v; v = v->next, i++) { - if (v->f & SELECT) { - sprintf(val, "%d", i); - view3d_cached_text_draw_add(v->co, val, 0, V3D_CACHE_TEXT_ASCII, col); + if (em->selectmode & SCE_SELECT_VERTEX) { + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); + for (v = em->verts.first, i = 0; v; v = v->next, i++) { + if (v->f & SELECT) { + sprintf(val, "%d", i); + view3d_cached_text_draw_add(v->co, val, 0, V3D_CACHE_TEXT_ASCII, col); + } } } - UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); - for (e = em->edges.first, i = 0; e; e = e->next, i++) { - if (e->f & SELECT) { - sprintf(val, "%d", i); - mid_v3_v3v3(pos, e->v1->co, e->v2->co); - view3d_cached_text_draw_add(pos, val, 0, V3D_CACHE_TEXT_ASCII, col); + if (em->selectmode & SCE_SELECT_EDGE) { + UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); + for (e = em->edges.first, i = 0; e; e = e->next, i++) { + if (e->f & SELECT) { + sprintf(val, "%d", i); + mid_v3_v3v3(pos, e->v1->co, e->v2->co); + view3d_cached_text_draw_add(pos, val, 0, V3D_CACHE_TEXT_ASCII, col); + } } } - UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); - for (f = em->faces.first, i = 0; f; f = f->next, i++) { - if (f->f & SELECT) { - sprintf(val, "%d", i); - view3d_cached_text_draw_add(f->cent, val, 0, V3D_CACHE_TEXT_ASCII, col); + if (em->selectmode & SCE_SELECT_FACE) { + UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); + for (f = em->faces.first, i = 0; f; f = f->next, i++) { + if (f->f & SELECT) { + sprintf(val, "%d", i); + view3d_cached_text_draw_add(f->cent, val, 0, V3D_CACHE_TEXT_ASCII, col); + } } } } diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index bba8786b092..919dc3f6403 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -701,8 +701,8 @@ static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int * static void GPU_buffer_copy_color3(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user) { int i, totface; - unsigned char *varray = (unsigned char *)varray_; - unsigned char *mcol = (unsigned char *)user; + char *varray = (char *)varray_; + char *mcol = (char *)user; MFace *f = dm->getFaceArray(dm); totface= dm->getNumFaces(dm); @@ -710,16 +710,16 @@ static void GPU_buffer_copy_color3(DerivedMesh *dm, float *varray_, int *index, int start = index[mat_orig_to_new[f->mat_nr]]; /* v1 v2 v3 */ - VECCOPY(&varray[start], &mcol[i*12]); - VECCOPY(&varray[start+3], &mcol[i*12+3]); - VECCOPY(&varray[start+6], &mcol[i*12+6]); + copy_v3_v3_char(&varray[start], &mcol[i*12]); + copy_v3_v3_char(&varray[start+3], &mcol[i*12+3]); + copy_v3_v3_char(&varray[start+6], &mcol[i*12+6]); index[mat_orig_to_new[f->mat_nr]] += 9; if(f->v4) { /* v3 v4 v1 */ - VECCOPY(&varray[start+9], &mcol[i*12+6]); - VECCOPY(&varray[start+12], &mcol[i*12+9]); - VECCOPY(&varray[start+15], &mcol[i*12]); + copy_v3_v3_char(&varray[start+9], &mcol[i*12+6]); + copy_v3_v3_char(&varray[start+12], &mcol[i*12+9]); + copy_v3_v3_char(&varray[start+15], &mcol[i*12]); index[mat_orig_to_new[f->mat_nr]] += 9; } } diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 39282335f46..7f99fc3ffc7 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -378,6 +378,20 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile); float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc); void IMB_color_to_bw(struct ImBuf *ibuf); +/* converting pixel buffers */ +void IMB_buffer_byte_from_float(unsigned char *rect_to, const float *rect_from, + int channels_from, int dither, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); +void IMB_buffer_float_from_byte(float *rect_to, const unsigned char *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); +void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, + int channels_from, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); +void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from); + /** * Change the ordering of the color bytes pointed to by rect from * rgba to abgr. size * 4 color bytes are reordered. diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 8c5f2dcafd6..8a3f6358c5b 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -42,10 +42,10 @@ #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" -#include "BKE_colortools.h" - #include "MEM_guardedalloc.h" +/**************************** Interlace/Deinterlace **************************/ + void IMB_de_interlace(struct ImBuf *ibuf) { struct ImBuf * tbuf1, * tbuf2; @@ -100,347 +100,498 @@ void IMB_interlace(struct ImBuf *ibuf) } } +/************************* Generic Buffer Conversion *************************/ -/* assume converting from linear float to sRGB byte */ -void IMB_rect_from_float(struct ImBuf *ibuf) +MINLINE void byte_to_float_v4(float f[4], const uchar b[4]) { - /* quick method to convert floatbuf to byte */ - float *tof = (float *)ibuf->rect_float; -// int do_dither = ibuf->dither != 0.f; - float dither= ibuf->dither / 255.0f; - float srgb[4]; - int i, channels= ibuf->channels; - short profile= ibuf->profile; - unsigned char *to = (unsigned char *) ibuf->rect; - - if(tof==NULL) return; - if(to==NULL) { - imb_addrectImBuf(ibuf); - to = (unsigned char *) ibuf->rect; - } - - if(channels==1) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof++) - to[1]= to[2]= to[3]= to[0] = FTOCHAR(tof[0]); + f[0] = b[0] * (1.0f/255.0f); + f[1] = b[1] * (1.0f/255.0f); + f[2] = b[2] * (1.0f/255.0f); + f[3] = b[3] * (1.0f/255.0f); +} + +MINLINE void float_to_byte_v4(uchar b[4], const float f[4]) +{ + F4TOCHAR4(f, b); +} + +MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], float dither) +{ + float tmp[4] = {f[0]+dither, f[1]+dither, f[2]+dither, f[3]+dither}; + float_to_byte_v4(b, tmp); +} + +/* float to byte pixels, output 4-channel RGBA */ +void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, + int channels_from, int dither, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) +{ + float tmp[4]; + float dither_fac = dither/255.0f; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + if(channels_from==1) { + /* single channel input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y; + uchar *to = rect_to + stride_to*y*4; + + for(x = 0; x < width; x++, from++, to+=4) + to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]); + } } - else if (profile == IB_PROFILE_LINEAR_RGB) { - if(channels == 3) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { - srgb[0]= linearrgb_to_srgb(tof[0]); - srgb[1]= linearrgb_to_srgb(tof[1]); - srgb[2]= linearrgb_to_srgb(tof[2]); - - to[0] = FTOCHAR(srgb[0]); - to[1] = FTOCHAR(srgb[1]); - to[2] = FTOCHAR(srgb[2]); - to[3] = 255; + else if(channels_from == 3) { + /* RGB input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*3; + uchar *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* no color space conversion */ + for(x = 0; x < width; x++, from+=3, to+=4) { + F3TOCHAR3(from, to); + to[3] = 255; + } + } + else if(profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + for(x = 0; x < width; x++, from+=3, to+=4) { + linearrgb_to_srgb_v3_v3(tmp, from); + F3TOCHAR3(tmp, to); + to[3] = 255; + } + } + else if(profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert from sRGB to linear */ + for(x = 0; x < width; x++, from+=3, to+=4) { + srgb_to_linearrgb_v3_v3(tmp, from); + F3TOCHAR3(tmp, to); + to[3] = 255; + } } } - else if (channels == 4) { - if (dither != 0.f) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { - const float d = (BLI_frand()-0.5f)*dither; - - srgb[0]= d + linearrgb_to_srgb(tof[0]); - srgb[1]= d + linearrgb_to_srgb(tof[1]); - srgb[2]= d + linearrgb_to_srgb(tof[2]); - srgb[3]= d + tof[3]; - - to[0] = FTOCHAR(srgb[0]); - to[1] = FTOCHAR(srgb[1]); - to[2] = FTOCHAR(srgb[2]); - to[3] = FTOCHAR(srgb[3]); + } + else if(channels_from == 4) { + /* RGBA input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*4; + uchar *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* no color space conversion */ + if(dither) { + for(x = 0; x < width; x++, from+=4, to+=4) + float_to_byte_dither_v4(to, from, (BLI_frand()-0.5f)*dither_fac); + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) + float_to_byte_v4(to, from); + } + } + else if(profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + if(dither && predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_predivide_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac); + } + } + else if(dither) { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac); + } + } + else if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_predivide_v4(tmp, from); + float_to_byte_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + linearrgb_to_srgb_v4(tmp, from); + float_to_byte_v4(to, tmp); + } + } + } + else if(profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert from sRGB to linear */ + if(dither && predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + srgb_to_linearrgb_predivide_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac); + } + } + else if(dither) { + for(x = 0; x < width; x++, from+=4, to+=4) { + srgb_to_linearrgb_v4(tmp, from); + float_to_byte_dither_v4(to, tmp, (BLI_frand()-0.5f)*dither_fac); + } + } + else if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + srgb_to_linearrgb_predivide_v4(tmp, from); + float_to_byte_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + srgb_to_linearrgb_v4(tmp, from); + float_to_byte_v4(to, tmp); + } } - } else { - floatbuf_to_srgb_byte(tof, to, 0, ibuf->x, 0, ibuf->y, ibuf->x); } } } - else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { - if(channels==3) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=3) { - to[0] = FTOCHAR(tof[0]); - to[1] = FTOCHAR(tof[1]); - to[2] = FTOCHAR(tof[2]); - to[3] = 255; +} + +/* byte to float pixels, input and output 4-channel RGBA */ +void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) +{ + float tmp[4]; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + /* RGBA input */ + for(y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from*y*4; + float *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* no color space conversion */ + for(x = 0; x < width; x++, from+=4, to+=4) + byte_to_float_v4(to, from); + } + else if(profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert sRGB to linear */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_predivide_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_v4(to, tmp); + } } } - else { - if (dither != 0.f) { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { - const float d = (BLI_frand()-0.5f)*dither; - float col[4]; - - col[0]= d + tof[0]; - col[1]= d + tof[1]; - col[2]= d + tof[2]; - col[3]= d + tof[3]; - - to[0] = FTOCHAR(col[0]); - to[1] = FTOCHAR(col[1]); - to[2] = FTOCHAR(col[2]); - to[3] = FTOCHAR(col[3]); + else if(profile_to == IB_PROFILE_SRGB) { + /* convert linear to sRGB */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_predivide_v4(to, tmp); } - } else { - for (i = ibuf->x * ibuf->y; i > 0; i--, to+=4, tof+=4) { - to[0] = FTOCHAR(tof[0]); - to[1] = FTOCHAR(tof[1]); - to[2] = FTOCHAR(tof[2]); - to[3] = FTOCHAR(tof[3]); + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_v4(to, tmp); } } } } - /* ensure user flag is reset */ - ibuf->userflags &= ~IB_RECT_INVALID; } - - -/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */ -void IMB_partial_rect_from_float(struct ImBuf *ibuf,float *buffer, int x, int y, int w, int h) +/* float to float pixels, output 4-channel RGBA */ +void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, + int channels_from, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) { - /* indices to source and destination image pixels */ - float *srcFloatPxl; - unsigned char *dstBytePxl; - /* buffer index will fill buffer */ - float *bufferIndex; - - /* convenience pointers to start of image buffers */ - float *init_srcFloatPxl = (float *)ibuf->rect_float; - unsigned char *init_dstBytePxl = (unsigned char *) ibuf->rect; - - /* Dithering factor */ - float dither= ibuf->dither / 255.0f; - /* respective attributes of image */ - short profile= ibuf->profile; - int channels= ibuf->channels; - - int i, j; - - /* - if called -only- from GPU_paint_update_image this test will never fail - but leaving it here for better or worse - */ - if(init_srcFloatPxl==NULL || (buffer == NULL)){ - return; - } - if(init_dstBytePxl==NULL) { - imb_addrectImBuf(ibuf); - init_dstBytePxl = (unsigned char *) ibuf->rect; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + if(channels_from==1) { + /* single channel input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y; + float *to = rect_to + stride_to*y*4; + + for(x = 0; x < width; x++, from++, to+=4) + to[0] = to[1] = to[2] = to[3] = from[0]; + } } - if(channels==1) { - for (j = 0; j < h; j++){ - bufferIndex = buffer + w*j*4; - dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; - srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x); - for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl++, bufferIndex+=4) { - dstBytePxl[1]= dstBytePxl[2]= dstBytePxl[3]= dstBytePxl[0] = FTOCHAR(srcFloatPxl[0]); - bufferIndex[0] = bufferIndex[1] = bufferIndex[2] = bufferIndex[3] = srcFloatPxl[0]; + else if(channels_from == 3) { + /* RGB input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*3; + float *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* no color space conversion */ + for(x = 0; x < width; x++, from+=3, to+=4) { + copy_v3_v3(to, from); + to[3] = 1.0f; } } - } - else if (profile == IB_PROFILE_LINEAR_RGB) { - if(channels == 3) { - for (j = 0; j < h; j++){ - bufferIndex = buffer + w*j*4; - dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; - srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3; - for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex += 4) { - linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl); - F3TOCHAR4(bufferIndex, dstBytePxl); - bufferIndex[3]= 1.0; + else if(profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert from sRGB to linear */ + for(x = 0; x < width; x++, from+=3, to+=4) { + srgb_to_linearrgb_v3_v3(to, from); + to[3] = 1.0f; + } + } + else if(profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + for(x = 0; x < width; x++, from+=3, to+=4) { + linearrgb_to_srgb_v3_v3(to, from); + to[3] = 1.0f; } } } - else if (channels == 4) { - if (dither != 0.f) { - for (j = 0; j < h; j++){ - bufferIndex = buffer + w*j*4; - dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; - srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; - for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { - const float d = (BLI_frand()-0.5f)*dither; - linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl); - bufferIndex[3] = srcFloatPxl[3]; - add_v4_fl(bufferIndex, d); - F4TOCHAR4(bufferIndex, dstBytePxl); - } + } + else if(channels_from == 4) { + /* RGBA input */ + for(y = 0; y < height; y++) { + const float *from = rect_from + stride_from*y*4; + float *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* same profile, copy */ + memcpy(to, from, sizeof(float)*4*width); + } + else if(profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert to sRGB to linear */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) + srgb_to_linearrgb_predivide_v4(to, from); } - } else { - for (j = 0; j < h; j++){ - bufferIndex = buffer + w*j*4; - dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; - srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; - for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { - linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl); - bufferIndex[3]= srcFloatPxl[3]; - F4TOCHAR4(bufferIndex, dstBytePxl); - } + else { + for(x = 0; x < width; x++, from+=4, to+=4) + srgb_to_linearrgb_v4(to, from); + } + } + else if(profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) + linearrgb_to_srgb_predivide_v4(to, from); + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) + linearrgb_to_srgb_v4(to, from); } } } } - else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { - if(channels==3) { - for (j = 0; j < h; j++){ - bufferIndex = buffer + w*j*4; - dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; - srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3; - for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex+=4) { - copy_v3_v3(bufferIndex, srcFloatPxl); - F3TOCHAR4(bufferIndex, dstBytePxl); - bufferIndex[3] = 1.0; +} + +/* byte to byte pixels, input and output 4-channel RGBA */ +void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, + int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) +{ + float tmp[4]; + int x, y; + + /* we need valid profiles */ + BLI_assert(profile_to != IB_PROFILE_NONE); + BLI_assert(profile_from != IB_PROFILE_NONE); + + /* always RGBA input */ + for(y = 0; y < height; y++) { + const uchar *from = rect_from + stride_from*y*4; + uchar *to = rect_to + stride_to*y*4; + + if(profile_to == profile_from) { + /* same profile, copy */ + memcpy(to, from, sizeof(uchar)*4*width); + } + else if(profile_to == IB_PROFILE_LINEAR_RGB) { + /* convert to sRGB to linear */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_predivide_v4(tmp, tmp); + float_to_byte_v4(to, tmp); + } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + srgb_to_linearrgb_v4(tmp, tmp); + float_to_byte_v4(to, tmp); } } } - else { - if (dither != 0.f) { - for (j = 0; j < h; j++){ - bufferIndex = buffer + w*j*4; - dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; - srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; - for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { - const float d = (BLI_frand()-0.5f)*dither; - copy_v4_v4(bufferIndex, srcFloatPxl); - add_v4_fl(bufferIndex,d); - F4TOCHAR4(bufferIndex, dstBytePxl); - } + else if(profile_to == IB_PROFILE_SRGB) { + /* convert from linear to sRGB */ + if(predivide) { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_predivide_v4(tmp, tmp); + float_to_byte_v4(to, tmp); } - } else { - for (j = 0; j < h; j++){ - bufferIndex = buffer + w*j*4; - dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; - srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; - for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { - copy_v4_v4(bufferIndex, srcFloatPxl); - F4TOCHAR4(bufferIndex, dstBytePxl); - } + } + else { + for(x = 0; x < width; x++, from+=4, to+=4) { + byte_to_float_v4(tmp, from); + linearrgb_to_srgb_v4(tmp, tmp); + float_to_byte_v4(to, tmp); } } } } +} + +/****************************** ImBuf Conversion *****************************/ + +void IMB_rect_from_float(struct ImBuf *ibuf) +{ + int predivide= 0, profile_from; + + /* verify we have a float buffer */ + if(ibuf->rect_float==NULL) + return; + + /* create byte rect if it didn't exist yet */ + if(ibuf->rect==NULL) + imb_addrectImBuf(ibuf); + + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + profile_from = IB_PROFILE_LINEAR_RGB; + else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_from = IB_PROFILE_SRGB; + else + BLI_assert(0); + + /* do conversion */ + IMB_buffer_byte_from_float((uchar*)ibuf->rect, ibuf->rect_float, + ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + /* ensure user flag is reset */ ibuf->userflags &= ~IB_RECT_INVALID; } -static void imb_float_from_rect_nonlinear(struct ImBuf *ibuf, float *fbuf) +/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */ +void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h) { - float *tof = fbuf; - int i; - unsigned char *to = (unsigned char *) ibuf->rect; - - for (i = ibuf->x * ibuf->y; i > 0; i--) - { - tof[0] = ((float)to[0])*(1.0f/255.0f); - tof[1] = ((float)to[1])*(1.0f/255.0f); - tof[2] = ((float)to[2])*(1.0f/255.0f); - tof[3] = ((float)to[3])*(1.0f/255.0f); - to += 4; - tof += 4; - } -} + float *rect_float; + uchar *rect_byte; + int predivide= 0, profile_from; + + /* verify we have a float buffer */ + if(ibuf->rect_float==NULL || buffer==NULL) + return; + /* create byte rect if it didn't exist yet */ + if(ibuf->rect==NULL) + imb_addrectImBuf(ibuf); -static void imb_float_from_rect_linear(struct ImBuf *ibuf, float *fbuf) -{ - float *tof = fbuf; - int i; - unsigned char *to = (unsigned char *) ibuf->rect; - - for (i = ibuf->x * ibuf->y; i > 0; i--) - { - tof[0] = srgb_to_linearrgb(((float)to[0])*(1.0f/255.0f)); - tof[1] = srgb_to_linearrgb(((float)to[1])*(1.0f/255.0f)); - tof[2] = srgb_to_linearrgb(((float)to[2])*(1.0f/255.0f)); - tof[3] = ((float)to[3])*(1.0f/255.0f); - to += 4; - tof += 4; - } + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + profile_from = IB_PROFILE_LINEAR_RGB; + else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_from = IB_PROFILE_SRGB; + else + BLI_assert(0); + + /* do conversion */ + rect_float= ibuf->rect_float + (x + y*ibuf->x)*ibuf->channels; + rect_byte= (uchar*)ibuf->rect + (x + y*ibuf->x)*4; + + IMB_buffer_float_from_float(buffer, rect_float, + ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, + w, h, w, ibuf->x); + + IMB_buffer_byte_from_float(rect_byte, buffer, + 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, + w, h, ibuf->x, w); + + /* ensure user flag is reset */ + ibuf->userflags &= ~IB_RECT_INVALID; } void IMB_float_from_rect(struct ImBuf *ibuf) { - /* quick method to convert byte to floatbuf */ - if(ibuf->rect==NULL) return; - if(ibuf->rect_float==NULL) { - if (imb_addrectfloatImBuf(ibuf) == 0) return; - } + int predivide= 0, profile_from; + + /* verify if we byte and float buffers */ + if(ibuf->rect==NULL) + return; + + if(ibuf->rect_float==NULL) + if(imb_addrectfloatImBuf(ibuf) == 0) + return; - /* Float bufs should be stored linear */ - - if (ibuf->profile != IB_PROFILE_NONE) { - /* if the image has been given a profile then we're working - * with color management in mind, so convert it to linear space */ - imb_float_from_rect_linear(ibuf, ibuf->rect_float); - } else { - imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float); - } + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_NONE) + profile_from = IB_PROFILE_LINEAR_RGB; + else + profile_from = IB_PROFILE_SRGB; + + /* do conversion */ + IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect, + IB_PROFILE_LINEAR_RGB, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } /* no profile conversion */ void IMB_float_from_rect_simple(struct ImBuf *ibuf) { + int predivide= 0; + if(ibuf->rect_float==NULL) imb_addrectfloatImBuf(ibuf); - imb_float_from_rect_nonlinear(ibuf, ibuf->rect_float); + + IMB_buffer_float_from_byte(ibuf->rect_float, (uchar*)ibuf->rect, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } void IMB_convert_profile(struct ImBuf *ibuf, int profile) { - int ok= FALSE; - int i; - - unsigned char *rct= (unsigned char *)ibuf->rect; - float *rctf= ibuf->rect_float; + int predivide= 0, profile_from, profile_to; if(ibuf->profile == profile) return; - if(ELEM(ibuf->profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* from */ - if(profile == IB_PROFILE_LINEAR_RGB) { /* to */ - if(ibuf->rect_float) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) { - rctf[0]= srgb_to_linearrgb(rctf[0]); - rctf[1]= srgb_to_linearrgb(rctf[1]); - rctf[2]= srgb_to_linearrgb(rctf[2]); - } - } - if(ibuf->rect) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { - rct[0]= (unsigned char)((srgb_to_linearrgb((float)rct[0]/255.0f) * 255.0f) + 0.5f); - rct[1]= (unsigned char)((srgb_to_linearrgb((float)rct[1]/255.0f) * 255.0f) + 0.5f); - rct[2]= (unsigned char)((srgb_to_linearrgb((float)rct[2]/255.0f) * 255.0f) + 0.5f); - } - } - ok= TRUE; - } - } - else if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { /* from */ - if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { /* to */ - if(ibuf->rect_float) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) { - rctf[0]= linearrgb_to_srgb(rctf[0]); - rctf[1]= linearrgb_to_srgb(rctf[1]); - rctf[2]= linearrgb_to_srgb(rctf[2]); - } - } - if(ibuf->rect) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { - rct[0]= (unsigned char)((linearrgb_to_srgb((float)rct[0]/255.0f) * 255.0f) + 0.5f); - rct[1]= (unsigned char)((linearrgb_to_srgb((float)rct[1]/255.0f) * 255.0f) + 0.5f); - rct[2]= (unsigned char)((linearrgb_to_srgb((float)rct[2]/255.0f) * 255.0f) + 0.5f); - } - } - ok= TRUE; - } + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_LINEAR_RGB) + profile_from = IB_PROFILE_LINEAR_RGB; + else if(ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_from = IB_PROFILE_SRGB; + else + BLI_assert(0); + + if(profile == IB_PROFILE_LINEAR_RGB) + profile_to = IB_PROFILE_LINEAR_RGB; + else if(ELEM(profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) + profile_to = IB_PROFILE_SRGB; + else + BLI_assert(0); + + /* do conversion */ + if(ibuf->rect_float) { + IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, + 4, profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } - if(ok==FALSE){ - printf("IMB_convert_profile: failed profile conversion %d -> %d\n", ibuf->profile, profile); - return; + if(ibuf->rect) { + IMB_buffer_byte_from_byte((uchar*)ibuf->rect, (uchar*)ibuf->rect, + profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } + /* set new profile */ ibuf->profile= profile; } @@ -448,18 +599,25 @@ void IMB_convert_profile(struct ImBuf *ibuf, int profile) * if the return */ float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc) { - /* stupid but it works like this everywhere now */ - const short is_lin_from= (ibuf->profile != IB_PROFILE_NONE); - const short is_lin_to= (profile != IB_PROFILE_NONE); - + int predivide= 0, profile_from, profile_to; + + /* determine profiles */ + if(ibuf->profile == IB_PROFILE_NONE) + profile_from = IB_PROFILE_LINEAR_RGB; + else + profile_from = IB_PROFILE_SRGB; + + if(profile == IB_PROFILE_NONE) + profile_to = IB_PROFILE_LINEAR_RGB; + else + profile_to = IB_PROFILE_SRGB; - if(is_lin_from == is_lin_to) { + if(profile_from == profile_to) { + /* simple case, just allocate the buffer and return */ *alloc= 0; - /* simple case, just allocate the buffer and return */ - if(ibuf->rect_float == NULL) { + if(ibuf->rect_float == NULL) IMB_float_from_rect(ibuf); - } return ibuf->rect_float; } @@ -469,42 +627,36 @@ float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc) *alloc= 1; if(ibuf->rect_float == NULL) { - if(is_lin_to) { - imb_float_from_rect_linear(ibuf, fbuf); - } - else { - imb_float_from_rect_nonlinear(ibuf, fbuf); - } + IMB_buffer_float_from_byte(fbuf, (uchar*)ibuf->rect, + profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } else { - if(is_lin_to) { /* lin -> nonlin */ - linearrgb_to_srgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y); - } - else { /* nonlin -> lin */ - srgb_to_linearrgb_rgba_rgba_buf(fbuf, ibuf->rect_float, ibuf->x * ibuf->y); - } + IMB_buffer_float_from_float(fbuf, ibuf->rect_float, + 4, profile_to, profile_from, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); } return fbuf; } } +/**************************** Color to Grayscale *****************************/ /* no profile conversion */ void IMB_color_to_bw(struct ImBuf *ibuf) { float *rctf= ibuf->rect_float; - unsigned char *rct= (unsigned char *)ibuf->rect; + uchar *rct= (uchar*)ibuf->rect; int i; + if(rctf) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) { + for(i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) rctf[0]= rctf[1]= rctf[2]= rgb_to_grayscale(rctf); - } } if(rct) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) { + for(i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) rct[0]= rct[1]= rct[2]= rgb_to_grayscale_byte(rct); - } } } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 97ea7592d04..8de7ae39a55 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -57,7 +57,7 @@ typedef struct IDProperty { seemed like a good idea as a pad var was needed anyway :)*/ IDPropertyData data; /* note, alignment for 64 bits */ int len; /* array length, also (this is important!) string length + 1. - the idea is to be able to reuse array realloc functions on strings.*/ + * the idea is to be able to reuse array realloc functions on strings.*/ /* totallen is total length of allocated array/string, including a buffer. * Note that the buffering is mild; the code comes from python's list implementation.*/ int totallen; /*strings and arrays are both buffered, though the buffer isn't @@ -74,7 +74,7 @@ typedef struct IDProperty { #define IDP_ARRAY 5 #define IDP_GROUP 6 /* the ID link property type hasn't been implemented yet, this will require - some cleanup of blenkernel, most likely.*/ + * some cleanup of blenkernel, most likely.*/ #define IDP_ID 7 #define IDP_DOUBLE 8 #define IDP_IDPARRAY 9 diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 20a2c36166f..a4280a6e463 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -194,7 +194,7 @@ typedef struct bVisibilityActuator { int flag; } bVisibilityActuator; -typedef struct bTwoDFilterActuator{ +typedef struct bTwoDFilterActuator { char pad[4]; /* Tells what type of 2D Filter */ short type; @@ -205,7 +205,7 @@ typedef struct bTwoDFilterActuator{ /* a float argument */ float float_arg; struct Text *text; -}bTwoDFilterActuator; +} bTwoDFilterActuator; typedef struct bParentActuator { char pad[2]; diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index e9290a92493..1dfef225828 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -132,7 +132,7 @@ typedef struct Brush { #define BRUSH_CUSTOM_ICON (1<<28) /* temporary flag which sets up autmatically for correct - brush drawing when inverted modal operator is running */ + * brush drawing when inverted modal operator is running */ #define BRUSH_INVERTED (1<<29) /* Brush.sculpt_tool */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 50c1779960d..f5abf00bd44 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -126,10 +126,10 @@ typedef struct bPythonConstraint { /* Inverse-Kinematics (IK) constraint - This constraint supports a variety of mode determine by the type field - according to B_CONSTRAINT_IK_TYPE. - Some fields are used by all types, some are specific to some types - This is indicated in the comments for each field + * This constraint supports a variety of mode determine by the type field + * according to B_CONSTRAINT_IK_TYPE. + * Some fields are used by all types, some are specific to some types + * This is indicated in the comments for each field */ typedef struct bKinematicConstraint { struct Object *tar; /* All: target object in case constraint needs a target */ diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index d98e5200d21..0b0ffb42ba8 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -29,6 +29,7 @@ * \ingroup DNA */ + #ifndef DNA_CUSTOMDATA_TYPES_H #define DNA_CUSTOMDATA_TYPES_H @@ -36,6 +37,8 @@ extern "C" { #endif +#include "DNA_defs.h" /* USE_BMESH_FORWARD_COMPAT */ + /** descriptor and storage for a custom data layer */ typedef struct CustomDataLayer { int type; /* type of data in layer */ @@ -59,6 +62,9 @@ typedef struct CustomDataExternal { * layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */ typedef struct CustomData { CustomDataLayer *layers; /* CustomDataLayers, ordered by type */ + int typemap[32]; /* runtime only! - maps types to indices of first layer of that type, + * MUST be >= CD_NUMTYPES, but we cant use a define here. + * Correct size is ensured in CustomData_update_typemap assert() */ int totlayer, maxlayer; /* number of layers, size of layers array */ int totsize, pad; /* in editmode, total size of all data layers */ void *pool; /* Bmesh: Memory pool for allocation of blocks */ @@ -75,7 +81,7 @@ typedef struct CustomData { #define CD_MCOL 6 #define CD_ORIGINDEX 7 #define CD_NORMAL 8 -#define CD_FLAGS 9 +#define CD_POLYINDEX 9 #define CD_PROP_FLT 10 #define CD_PROP_INT 11 #define CD_PROP_STR 12 @@ -91,8 +97,27 @@ typedef struct CustomData { #define CD_TEXTURE_MCOL 22 #define CD_CLOTH_ORCO 23 #define CD_RECAST 24 + +#ifdef USE_BMESH_FORWARD_COMPAT + +/* BMESH ONLY START */ +#define CD_MPOLY 25 +#define CD_MLOOP 26 +#define CD_SHAPE_KEYINDEX 27 +#define CD_SHAPEKEY 28 +#define CD_BWEIGHT 29 +#define CD_CREASE 30 +#define CD_WEIGHT_MLOOPCOL 31 +/* BMESH ONLY END */ + +#define CD_NUMTYPES 32 + +#else + #define CD_NUMTYPES 25 +#endif + /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) #define CD_MASK_MSTICKY (1 << CD_MSTICKY) @@ -103,7 +128,7 @@ typedef struct CustomData { #define CD_MASK_MCOL (1 << CD_MCOL) #define CD_MASK_ORIGINDEX (1 << CD_ORIGINDEX) #define CD_MASK_NORMAL (1 << CD_NORMAL) -#define CD_MASK_FLAGS (1 << CD_FLAGS) +#define CD_MASK_POLYINDEX (1 << CD_POLYINDEX) #define CD_MASK_PROP_FLT (1 << CD_PROP_FLT) #define CD_MASK_PROP_INT (1 << CD_PROP_INT) #define CD_MASK_PROP_STR (1 << CD_PROP_STR) @@ -118,6 +143,20 @@ typedef struct CustomData { #define CD_MASK_CLOTH_ORCO (1 << CD_CLOTH_ORCO) #define CD_MASK_RECAST (1 << CD_RECAST) +#ifdef USE_BMESH_FORWARD_COMPAT + +/* BMESH ONLY START */ +#define CD_MASK_MPOLY (1 << CD_MPOLY) +#define CD_MASK_MLOOP (1 << CD_MLOOP) +#define CD_MASK_SHAPE_KEYINDEX (1 << CD_SHAPE_KEYINDEX) +#define CD_MASK_SHAPEKEY (1 << CD_SHAPEKEY) +#define CD_MASK_BWEIGHT (1 << CD_BWEIGHT) +#define CD_MASK_CREASE (1 << CD_CREASE) +#define CD_MASK_WEIGHT_MLOOPCOL (1 << CD_WEIGHT_MLOOPCOL) +/* BMESH ONLY END */ + +#endif + /* CustomData.flag */ /* indicates layer should not be copied by CustomData_from_template or diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h index 25d95419605..54dfc18a03c 100644 --- a/source/blender/makesdna/DNA_defs.h +++ b/source/blender/makesdna/DNA_defs.h @@ -45,4 +45,6 @@ /* hrmf, we need a better include then this */ #include "../blenloader/BLO_sys_types.h" /* needed for int64_t only! */ +#define USE_BMESH_FORWARD_COMPAT + #endif /* DNA_DEFS_H */ diff --git a/source/blender/makesdna/DNA_documentation.h b/source/blender/makesdna/DNA_documentation.h index 206a45fad5d..c1d6ee4aec3 100644 --- a/source/blender/makesdna/DNA_documentation.h +++ b/source/blender/makesdna/DNA_documentation.h @@ -63,14 +63,12 @@ * \section dnanote NOTE - PLEASE READ INSTRUCTIONS ABOUT ADDING VARIABLES IN 'DNA' STRUCTS IN - - intern/dna_genfile.c - (ton) + * PLEASE READ INSTRUCTIONS ABOUT ADDING VARIABLES IN 'DNA' STRUCTS IN + * + * intern/dna_genfile.c + * (ton) */ - /* This file has intentionally no definitions or implementation. */ - diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 3e1cdd08086..189f52eead9 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -168,8 +168,8 @@ typedef struct Material { short sss_flag, sss_preset; int mapto_textured; /* render-time cache to optimise texture lookups */ - short shadowonly_flag; /* "shadowsonly" type */ - short index; /* custom index for render passes */ + short shadowonly_flag; /* "shadowsonly" type */ + short index; /* custom index for render passes */ ListBase gpumaterial; /* runtime */ } Material; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index f8062aeccc7..eae7102ef42 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -36,6 +36,8 @@ #include "DNA_ID.h" #include "DNA_customdata_types.h" +#include "DNA_defs.h" /* USE_BMESH_FORWARD_COMPAT */ + struct DerivedMesh; struct Ipo; struct Key; @@ -47,6 +49,11 @@ struct MCol; struct MSticky; struct Mesh; struct OcInfo; +struct MPoly; +struct MTexPoly; +struct MLoop; +struct MLoopUV; +struct MLoopCol; struct Multires; struct EditMesh; struct AnimData; @@ -61,6 +68,17 @@ typedef struct Mesh { struct Key *key; struct Material **mat; +/*#ifdef USE_BMESH_FORWARD_COMPAT*/ /* XXX - ifdefs dont work here! */ +/* BMESH ONLY */ + /*new face structures*/ + struct MPoly *mpoly; + struct MTexPoly *mtpoly; + struct MLoop *mloop; + struct MLoopUV *mloopuv; + struct MLoopCol *mloopcol; +/* END BMESH ONLY */ +/*#endif*/ + struct MFace *mface; /* array of mesh object mode faces */ struct MTFace *mtface; /* store face UV's and texture here */ struct TFace *tface; /* depecrated, use mtface */ @@ -76,8 +94,20 @@ typedef struct Mesh { struct CustomData vdata, edata, fdata; +/*#ifdef USE_BMESH_FORWARD_COMPAT*/ /* XXX - ifdefs dont work here! */ +/* BMESH ONLY */ + struct CustomData pdata, ldata; +/* END BMESH ONLY */ +/*#endif*/ + int totvert, totedge, totface, totselect; - + +/*#ifdef USE_BMESH_FORWARD_COMPAT*/ +/* BMESH ONLY */ + int totpoly, totloop; +/* END BMESH ONLY */ +/*#endif*/ /* XXX - ifdefs dont work here! */ + /* the last selected vertex/edge/face are used for the active face however * this means the active face must always be selected, this is to keep track * of the last selected face and is similar to the old active face flag where @@ -192,4 +222,12 @@ typedef struct TFace { #define MESH_MAX_VERTS 2000000000L +/* this is so we can save bmesh files that load in trunk, ignoring NGons + * will eventually be removed */ + +#if 0 /* enable in bmesh branch only for now */ +#define USE_BMESH_SAVE_AS_COMPAT +#endif + + #endif diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 66e1333bf66..ab4b560943f 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -72,21 +72,41 @@ typedef struct MCol { char a, r, g, b; } MCol; +#ifdef USE_BMESH_FORWARD_COMPAT + +/*new face structure, replaces MFace, which is now + only used for storing tesselations.*/ +typedef struct MPoly { + /* offset into loop array and number of loops in the face */ + int loopstart; + int totloop; /* keep signed since we need to subtract when getting the previous loop */ + short mat_nr; + char flag, pad; +} MPoly; + +/*the e here is because we want to move away from + relying on edge hashes.*/ +typedef struct MLoop { + unsigned int v; /*vertex index*/ + unsigned int e; /*edge index*/ +} MLoop; + +#endif /* USE_BMESH_FORWARD_COMPAT */ + /*bmesh custom data stuff*/ -typedef struct MTexPoly{ +typedef struct MTexPoly { struct Image *tpage; char flag, transp; short mode,tile,unwrap; -}MTexPoly; +} MTexPoly; -typedef struct MLoopUV{ +typedef struct MLoopUV { float uv[2]; -}MLoopUV; +} MLoopUV; -typedef struct MLoopCol{ +typedef struct MLoopCol { char a, r, g, b; - int pad; /*waste!*/ -}MLoopCol; +} MLoopCol; typedef struct MSticky { float co[2]; @@ -105,13 +125,13 @@ typedef struct MTFace { } MTFace; /*Custom Data Properties*/ -typedef struct MFloatProperty{ +typedef struct MFloatProperty { float f; } MFloatProperty; -typedef struct MIntProperty{ +typedef struct MIntProperty { int i; } MIntProperty; -typedef struct MStringProperty{ +typedef struct MStringProperty { char s[256]; } MStringProperty; @@ -174,7 +194,7 @@ typedef struct Multires { /** End Multires **/ -typedef struct MRecast{ +typedef struct MRecast { int i; } MRecast; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 5edc0869d9b..da77f7a85cf 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -704,7 +704,7 @@ typedef struct SimpleDeformModifierData { #define MOD_SIMPLEDEFORM_LOCK_AXIS_Y (1<<1) /* indicates whether simple deform should use the local - coordinates or global coordinates of origin */ + * coordinates or global coordinates of origin */ #define MOD_SIMPLEDEFORM_ORIGIN_LOCAL (1<<0) #define MOD_UVPROJECT_MAX 10 diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index fc21f26fa32..1a065741121 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -113,6 +113,8 @@ typedef struct MovieClipScopes { #define MCLIP_USE_PROXY (1<<0) #define MCLIP_USE_PROXY_CUSTOM_DIR (1<<1) +#define MCLIP_TIMECODE_FLAGS (MCLIP_USE_PROXY|MCLIP_USE_PROXY_CUSTOM_DIR) + /* MovieClip->render_size */ #define MCLIP_PROXY_RENDER_SIZE_FULL 0 #define MCLIP_PROXY_RENDER_SIZE_25 1 diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 845d8a87c5b..2dfc05bda04 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -354,12 +354,12 @@ typedef struct NodeChroma { float t1,t2,t3; float fsize,fstrength,falpha; float key[4]; - short algorithm, channel; + short algorithm, channel; } NodeChroma; typedef struct NodeTwoXYs { short x1, x2, y1, y2; - float fac_x1, fac_x2, fac_y1, fac_y2; + float fac_x1, fac_x2, fac_y1, fac_y2; } NodeTwoXYs; typedef struct NodeTwoFloats { @@ -428,7 +428,7 @@ typedef struct NodeColorspill { short limchan, unspill; float limscale; float uspillr, uspillg, uspillb; -}NodeColorspill; +} NodeColorspill; typedef struct NodeTexBase { TexMapping tex_mapping; diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index c56d771d3b3..504c847a9ea 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -65,7 +65,7 @@ typedef struct BoidParticle { typedef struct ParticleSpring { float rest_length; unsigned int particle_index[2], delete_flag; -}ParticleSpring; +} ParticleSpring; /* Child particles are created around or between parent particles */ typedef struct ChildParticle { @@ -295,7 +295,7 @@ typedef struct ParticleSystem float dt_frac; /* current time step, as a fraction of a frame */ float _pad; /* spare capacity */ -}ParticleSystem; +} ParticleSystem; /* part->type */ /* hair is allways baked static in object/geometry space */ diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index ca2b7e0b2a9..50f406afbf9 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -347,9 +347,9 @@ typedef struct SpeedControlVars { #define SEQ_BLEND_REPLACE 0 /* all other BLEND_MODEs are simple SEQ_EFFECT ids and therefore identical - to the table above. (Only those effects that handle _exactly_ two inputs, - otherwise, you can't really blend, right :) !) -*/ + * to the table above. (Only those effects that handle _exactly_ two inputs, + * otherwise, you can't really blend, right :) !) + */ #define SEQ_HAS_PATH(_seq) (ELEM5((_seq)->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_SOUND, SEQ_RAM_SOUND, SEQ_HD_SOUND)) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 851d4b562e6..b30a1baf7bb 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -603,20 +603,20 @@ extern UserDef U; /* from blenkernel blender.c */ #define NDOF_FLY_HELICOPTER (1 << 1) #define NDOF_LOCK_HORIZON (1 << 2) /* the following might not need to be saved between sessions, - but they do need to live somewhere accessible... */ + * but they do need to live somewhere accessible... */ #define NDOF_SHOULD_PAN (1 << 3) #define NDOF_SHOULD_ZOOM (1 << 4) #define NDOF_SHOULD_ROTATE (1 << 5) /* orbit navigation modes - only two options, so it's sort of a hyrbrid bool/enum - if ((U.ndof_flag & NDOF_ORBIT_MODE) == NDOF_OM_OBJECT)... */ + * only two options, so it's sort of a hyrbrid bool/enum + * if ((U.ndof_flag & NDOF_ORBIT_MODE) == NDOF_OM_OBJECT)... */ /* #define NDOF_ORBIT_MODE (1 << 6) #define NDOF_OM_TARGETCAMERA 0 #define NDOF_OM_OBJECT NDOF_ORBIT_MODE */ /* actually... users probably don't care about what the mode - is called, just that it feels right */ + * is called, just that it feels right */ /* zoom is up/down if this flag is set (otherwise forward/backward) */ #define NDOF_ZOOM_UPDOWN (1 << 7) #define NDOF_ZOOM_INVERT (1 << 8) diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index 29ff5975e85..773e93a22ad 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -1,16 +1,29 @@ /* -* ***** BEGIN GPL LICENSE BLOCK ***** -* -* 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. -* -* Contributor(s): Miika Hämäläinen -* -* ***** END GPL LICENSE BLOCK ***** -* -*/ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * Contributor(s): Miika Hämäläinen + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/modifiers/intern/MOD_dynamicpaint.c + * \ingroup modifiers + */ #include <stddef.h> diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 9821c0b3836..5bd38579b67 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -556,10 +556,11 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm) int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2"); int *facepa = emd->facepa; int *fs, totesplit=0,totfsplit=0,curdupface=0; - int i,j,v1,v2,v3,v4,esplit, + int i, v1, v2, v3, v4, esplit, v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */ uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */ int numlayer; + unsigned int ed_v1, ed_v2; edgehash= BLI_edgehash_new(); @@ -650,16 +651,16 @@ static DerivedMesh * cutEdges(ExplodeModifierData *emd, DerivedMesh *dm) /* create new verts */ ehi= BLI_edgehashIterator_new(edgehash); for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { - BLI_edgehashIterator_getKey(ehi, &i, &j); + BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2); esplit= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - mv=CDDM_get_vert(splitdm,j); + mv=CDDM_get_vert(splitdm, ed_v2); dupve=CDDM_get_vert(splitdm,esplit); - DM_copy_vert_data(splitdm,splitdm,j,esplit,1); + DM_copy_vert_data(splitdm,splitdm, ed_v2, esplit,1); *dupve=*mv; - mv=CDDM_get_vert(splitdm,i); + mv=CDDM_get_vert(splitdm, ed_v1); add_v3_v3(dupve->co, mv->co); mul_v3_fl(dupve->co, 0.5f); @@ -789,7 +790,8 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd, /* float timestep; */ int *facepa=emd->facepa; int totdup=0,totvert=0,totface=0,totpart=0; - int i, j, v, mindex=0; + int i, v, mindex=0; + unsigned int ed_v1, ed_v2; MTFace *mtface = NULL, *mtf; totface= dm->getNumFaces(dm); @@ -852,24 +854,24 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd, MVert *dest; /* get particle + vertex from hash */ - BLI_edgehashIterator_getKey(ehi, &j, &i); - i -= totvert; + BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2); + ed_v2 -= totvert; v= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - dm->getVert(dm, j, &source); + dm->getVert(dm, ed_v1, &source); dest = CDDM_get_vert(explode,v); - DM_copy_vert_data(dm,explode,j,v,1); + DM_copy_vert_data(dm, explode, ed_v1, v, 1); *dest = source; - if(i!=totpart) { + if(ed_v2 != totpart) { /* get particle */ - pa= pars+i; + pa= pars + ed_v2; psys_get_birth_coordinates(&sim, pa, &birth, 0, 0); state.time=cfra; - psys_get_particle_state(&sim, i, &state, 1); + psys_get_particle_state(&sim, ed_v2, &state, 1); vertco=CDDM_get_vert(explode,v)->co; mul_m4_v3(ob->obmat,vertco); diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 6541b15f66e..0452c6a4e73 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -499,16 +499,20 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, Fluidsim } // assign material + flags to new dm + // if there's no faces in original dm, keep materials and flags unchanged mface = orgdm->getFaceArray(orgdm); - mat_nr = mface[0].mat_nr; - flag = mface[0].flag; - mface = dm->getFaceArray(dm); - numfaces = dm->getNumFaces(dm); - for(i=0; i<numfaces; i++) - { - mface[i].mat_nr = mat_nr; - mface[i].flag = flag; + if(mface) { + mat_nr = mface[0].mat_nr; + flag = mface[0].flag; + + mface = dm->getFaceArray(dm); + numfaces = dm->getNumFaces(dm); + for(i=0; i<numfaces; i++) + { + mface[i].mat_nr = mat_nr; + mface[i].flag = flag; + } } // load vertex velocities, if they exist... diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 2aa69526c10..ad47e3fe569 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -93,22 +93,28 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3]) EdgeHash *edge_hash = BLI_edgehash_new(); EdgeHashIterator *edge_iter; int edge_ref_count = 0; - int ed_v1, ed_v2; /* use when getting the key */ + unsigned int ed_v1, ed_v2; /* use when getting the key */ EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity"); EdgeFaceRef *edge_ref; float edge_normal[3]; /* This function adds an edge hash if its not there, and adds the face index */ #define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \ - edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \ + { \ + const unsigned int ml_v1 = EDV1; \ + const unsigned int ml_v2 = EDV2; \ + edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, ml_v1, ml_v2); \ if (!edge_ref) { \ edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \ - edge_ref->f1=i; \ - edge_ref->f2=-1; \ - BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \ - } else { \ - edge_ref->f2=i; \ - } + edge_ref->f1 = i; \ + edge_ref->f2 =- 1; \ + BLI_edgehash_insert(edge_hash, ml_v1, ml_v2, edge_ref); \ + } \ + else { \ + edge_ref->f2 = i; \ + } \ + } + /* --- end define --- */ for(i = 0; i < numFaces; i++, mf++) { f_no = face_nors[i]; @@ -133,7 +139,7 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3]) for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) { /* Get the edge vert indices, and edge value (the face indices that use it)*/ - BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2); + BLI_edgehashIterator_getKey(edge_iter, &ed_v1, &ed_v2); edge_ref = BLI_edgehashIterator_getValue(edge_iter); if (edge_ref->f2 != -1) { @@ -250,7 +256,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if(smd->flag & MOD_SOLIDIFY_RIM) { EdgeHash *edgehash = BLI_edgehash_new(); EdgeHashIterator *ehi; - int v1, v2; + unsigned int v1, v2; int eidx; for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) { @@ -265,14 +271,19 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, #define INVALID_PAIR -2 #define ADD_EDGE_USER(_v1, _v2, edge_ord) \ - eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, _v1, _v2)); \ - if(edge_users[eidx] == INVALID_UNUSED) { \ - ed= orig_medge + eidx; \ - edge_users[eidx]= (_v1 < _v2) == (ed->v1 < ed->v2) ? i:(i+numFaces); \ - edge_order[eidx]= edge_ord; \ - } else { \ - edge_users[eidx]= INVALID_PAIR; \ - } \ + { \ + const unsigned int ml_v1 = _v1; \ + const unsigned int ml_v2 = _v2; \ + eidx= GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, ml_v1, ml_v2)); \ + if(edge_users[eidx] == INVALID_UNUSED) { \ + ed= orig_medge + eidx; \ + edge_users[eidx] = (ml_v1 < ml_v2) == (ed->v1 < ed->v2) ? i : (i + numFaces); \ + edge_order[eidx] = edge_ord; \ + } \ + else { \ + edge_users[eidx] = INVALID_PAIR; \ + } \ + } edge_users= MEM_mallocN(sizeof(int) * numEdges, "solid_mod edges"); diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 99a36691b10..8aaf1771b68 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -606,7 +606,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf) RenderData *rd= data; bNodePreview *preview= node->preview; int xsize, ysize; - int color_manage= rd->color_mgt_flag & R_COLOR_MANAGEMENT; + int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; + int dither= 0; unsigned char *rect; if(preview && stackbuf) { @@ -633,10 +635,9 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf) /* convert to byte for preview */ rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect"); - if(color_manage) - floatbuf_to_srgb_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize); - else - floatbuf_to_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize); + IMB_buffer_byte_from_float(rect, cbuf->rect, + 4, dither, IB_PROFILE_SRGB, profile_from, predivide, + xsize, ysize, xsize, xsize); free_compbuf(cbuf); if(stackbuf_use!=stackbuf) diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 9920cdab039..fd7c87adea2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -62,6 +62,7 @@ static bNodeSocketTemplate cmp_node_rlayers_out[]= { float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) { float *rect; + int predivide= 0; *alloc= FALSE; @@ -71,7 +72,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) } else { rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); - srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y); + + IMB_buffer_float_from_float(rect, ibuf->rect_float, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + *alloc= TRUE; } } @@ -81,7 +86,11 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) } else { rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); - linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y); + + IMB_buffer_float_from_float(rect, ibuf->rect_float, + 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); + *alloc= TRUE; } } diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 7075b0592b8..cd1666d0eed 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -46,5 +46,9 @@ if env['WITH_BF_INTERNATIONAL']: if env['WITH_BF_CYCLES']: defs.append('WITH_CYCLES') +if env['WITH_BF_FFMPEG']: + defs.append('WITH_FFMPEG') + incs += ' ' + env['BF_FFMPEG_INC'] + sources = env.Glob('intern/*.c') env.BlenderLib( libname = 'bf_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core'], priority = [361]) diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 63ccdea3f0d..1899936cb50 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -42,9 +42,10 @@ set(INC_SYS ) set(SRC - gpu.c + gpu.c bpy.c bpy_app.c + bpy_app_ffmpeg.c bpy_app_handlers.c bpy_driver.c bpy_interface.c @@ -62,9 +63,10 @@ set(SRC bpy_util.c stubs.c - gpu.h + gpu.h bpy.h bpy_app.h + bpy_app_ffmpeg.h bpy_app_handlers.h bpy_driver.h bpy_intern_string.h @@ -101,7 +103,15 @@ if(WITH_CYCLES) endif() if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + +if(WITH_CODEC_FFMPEG) + list(APPEND INC_SYS + ${FFMPEG_INCLUDE_DIRS} + ) + + add_definitions(-DWITH_FFMPEG) endif() blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index d5f0cd205fa..ea95c4ebd85 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -32,6 +32,9 @@ #include <Python.h> #include "bpy_app.h" + +#include "bpy_app_ffmpeg.h" + #include "bpy_app_handlers.h" #include "bpy_driver.h" @@ -79,6 +82,7 @@ static PyStructSequence_Field app_info_fields[] = { {(char *)"build_system", (char *)"Build system used"}, /* submodules */ + {(char *)"ffmpeg", (char *)"FFmpeg library information backend"}, {(char *)"handlers", (char *)"Application handler callbacks"}, {NULL} }; @@ -147,6 +151,7 @@ static PyObject *make_app_info(void) SetStrItem("Unknown"); #endif + SetObjItem(BPY_app_ffmpeg_struct()); SetObjItem(BPY_app_handlers_struct()); #undef SetIntItem diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c new file mode 100644 index 00000000000..778334c9600 --- /dev/null +++ b/source/blender/python/intern/bpy_app_ffmpeg.c @@ -0,0 +1,143 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_ffmpeg.c + * \ingroup pythonintern + */ + +#include <Python.h> +#include "BLI_utildefines.h" +#include "BLI_callbacks.h" + +#include "RNA_types.h" +#include "RNA_access.h" +#include "bpy_rna.h" + +#ifdef WITH_FFMPEG +#include <libavcodec/avcodec.h> +#include <libavdevice/avdevice.h> +#include <libavformat/avformat.h> +#include <libavutil/avutil.h> +#include <libswscale/swscale.h> +#endif + +static PyTypeObject BlenderAppFFmpegType; + +#define DEF_FFMPEG_LIB_VERSION(lib) \ + {(char *)(#lib "_version"), (char *)("The " #lib " version as a tuple of 3 numbers")}, \ + {(char *)(#lib "_version_string"), (char *)("The " #lib " version formatted as a string")}, + +static PyStructSequence_Field app_ffmpeg_info_fields[] = { + {(char *)"supported", (char *)("Boolean, True when Blender is built with FFmpeg support")}, + + DEF_FFMPEG_LIB_VERSION(avcodec) + DEF_FFMPEG_LIB_VERSION(avdevice) + DEF_FFMPEG_LIB_VERSION(avformat) + DEF_FFMPEG_LIB_VERSION(avutil) + DEF_FFMPEG_LIB_VERSION(swscale) + {NULL} +}; + +#undef DEF_FFMPEG_LIB_VERSION + +static PyStructSequence_Desc app_ffmpeg_info_desc = { + (char *)"bpy.app.ffmpeg", /* name */ + (char *)"This module contains information about FFmpeg blender is linked against", /* doc */ + app_ffmpeg_info_fields, /* fields */ + (sizeof(app_ffmpeg_info_fields) / sizeof(PyStructSequence_Field)) - 1 +}; + +static PyObject *make_ffmpeg_info(void) +{ + PyObject *ffmpeg_info; + int pos = 0; + +#ifdef WITH_FFMPEG + int curversion; +#endif + + ffmpeg_info = PyStructSequence_New(&BlenderAppFFmpegType); + if (ffmpeg_info == NULL) { + return NULL; + } + +#define SetIntItem(flag) \ + PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyLong_FromLong(flag)) +#define SetStrItem(str) \ + PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyUnicode_FromString(str)) +#define SetObjItem(obj) \ + PyStructSequence_SET_ITEM(ffmpeg_info, pos++, obj) + +#ifdef WITH_FFMPEG + #define FFMPEG_LIB_VERSION(lib) \ + curversion = lib ## _version(); \ + SetObjItem(Py_BuildValue("(iii)", \ + curversion >> 16, (curversion >> 8) % 256, curversion % 256)); \ + SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", \ + curversion >> 16, (curversion >> 8) % 256, curversion % 256)); +#else + #define FFMPEG_LIB_VERSION(lib) \ + SetStrItem("Unknown"); \ + SetStrItem("Unknown"); +#endif + +#ifdef WITH_FFMPEG + SetObjItem(PyBool_FromLong(1)); +#else + SetObjItem(PyBool_FromLong(0)); +#endif + + FFMPEG_LIB_VERSION(avcodec); + FFMPEG_LIB_VERSION(avdevice); + FFMPEG_LIB_VERSION(avformat); + FFMPEG_LIB_VERSION(avutil); + FFMPEG_LIB_VERSION(swscale); + +#undef FFMPEG_LIB_VERSION + + if (PyErr_Occurred()) { + Py_CLEAR(ffmpeg_info); + return NULL; + } + +#undef SetIntItem +#undef SetStrItem +#undef SetObjItem + + return ffmpeg_info; +} + +PyObject *BPY_app_ffmpeg_struct(void) +{ + PyObject *ret; + + PyStructSequence_InitType(&BlenderAppFFmpegType, &app_ffmpeg_info_desc); + + ret = make_ffmpeg_info(); + + /* prevent user from creating new instances */ + BlenderAppFFmpegType.tp_init = NULL; + BlenderAppFFmpegType.tp_new = NULL; + BlenderAppFFmpegType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */ + + return ret; +} diff --git a/source/blender/python/intern/bpy_app_ffmpeg.h b/source/blender/python/intern/bpy_app_ffmpeg.h new file mode 100644 index 00000000000..4ed89cd7902 --- /dev/null +++ b/source/blender/python/intern/bpy_app_ffmpeg.h @@ -0,0 +1,32 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_ffmpeg.h + * \ingroup pythonintern + */ + +#ifndef BPY_APP_FFMPEG_H +#define BPY_APP_FFMPEG_H + +PyObject *BPY_app_ffmpeg_struct(void); + +#endif // BPY_APP_FFMPEG_H diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 9984e7f2fe0..81eb81e90fa 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -395,7 +395,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) if (srna) { static const char *kwlist[] = {"attr", "name", "description", "default", "options", "subtype", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; int def = 0; PropertyRNA *prop; @@ -423,7 +423,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype); RNA_def_property_boolean_default(prop, def); - RNA_def_property_ui_text(prop, name, description); + RNA_def_property_ui_text(prop, name ? name : id, description); if (pyopts) { if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); @@ -463,7 +463,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject if (srna) { static const char *kwlist[] = {"attr", "name", "description", "default", "options", "subtype", "size", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; int def[PYRNA_STACK_ARRAY] = {0}; int size = 3; @@ -501,11 +501,11 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject return NULL; } - // prop = RNA_def_boolean_array(srna, id, size, pydef ? def:NULL, name, description); + // prop = RNA_def_boolean_array(srna, id, size, pydef ? def:NULL, name ? name : id, description); prop = RNA_def_property(srna, id, PROP_BOOLEAN, subtype); RNA_def_property_array(prop, size); if (pydef) RNA_def_property_boolean_array_default(prop, def); - RNA_def_property_ui_text(prop, name, description); + RNA_def_property_ui_text(prop, name ? name : id, description); if (pyopts) { if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); @@ -541,7 +541,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) if (srna) { static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1, def = 0; PropertyRNA *prop; @@ -570,8 +570,8 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) prop = RNA_def_property(srna, id, PROP_INT, subtype); RNA_def_property_int_default(prop, def); + RNA_def_property_ui_text(prop, name ? name : id, description); RNA_def_property_range(prop, min, max); - RNA_def_property_ui_text(prop, name, description); RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); if (pyopts) { @@ -612,7 +612,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "size", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1; int def[PYRNA_STACK_ARRAY] = {0}; @@ -657,7 +657,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject RNA_def_property_array(prop, size); if (pydef) RNA_def_property_int_array_default(prop, def); RNA_def_property_range(prop, min, max); - RNA_def_property_ui_text(prop, name, description); + RNA_def_property_ui_text(prop, name ? name : id, description); RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, 3); if (pyopts) { @@ -696,7 +696,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3, def = 0.0f; int precision = 2; @@ -735,7 +735,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) prop = RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); RNA_def_property_float_default(prop, def); RNA_def_property_range(prop, min, max); - RNA_def_property_ui_text(prop, name, description); + RNA_def_property_ui_text(prop, name ? name : id, description); RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision); if (pyopts) { @@ -777,7 +777,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec static const char *kwlist[] = {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "size", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3, def[PYRNA_STACK_ARRAY] = {0.0f}; int precision = 2, size = 3; @@ -828,7 +828,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec RNA_def_property_array(prop, size); if (pydef) RNA_def_property_float_array_default(prop, def); RNA_def_property_range(prop, min, max); - RNA_def_property_ui_text(prop, name, description); + RNA_def_property_ui_text(prop, name ? name : id, description); RNA_def_property_ui_range(prop, MAX2(soft_min, min), MIN2(soft_max, max), step, precision); if (pyopts) { @@ -864,7 +864,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw if (srna) { static const char *kwlist[] = {"attr", "name", "description", "default", "maxlen", "options", "subtype", "update", NULL}; - const char *id = NULL, *name = "", *description = "", *def = ""; + const char *id = NULL, *name = NULL, *description = "", *def = ""; int id_len; int maxlen = 0; PropertyRNA *prop; @@ -893,7 +893,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw prop = RNA_def_property(srna, id, PROP_STRING, subtype); if (maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen + 1); /* +1 since it includes null terminator */ if (def) RNA_def_property_string_default(prop, def); - RNA_def_property_ui_text(prop, name, description); + RNA_def_property_ui_text(prop, name ? name : id, description); if (pyopts) { if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); @@ -1163,7 +1163,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) if (srna) { static const char *kwlist[] = {"attr", "items", "name", "description", "default", "options", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; PyObject *def = NULL; int id_len; int defvalue = 0; @@ -1227,8 +1227,8 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) } } - if (opts & PROP_ENUM_FLAG) prop = RNA_def_enum_flag(srna, id, eitems, defvalue, name, description); - else prop = RNA_def_enum(srna, id, eitems, defvalue, name, description); + if (opts & PROP_ENUM_FLAG) prop = RNA_def_enum_flag(srna, id, eitems, defvalue, name ? name : id, description); + else prop = RNA_def_enum(srna, id, eitems, defvalue, name ? name : id, description); if (is_itemf) { RNA_def_enum_funcs(prop, bpy_props_enum_itemf); @@ -1307,7 +1307,7 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k if (srna) { static const char *kwlist[] = {"attr", "type", "name", "description", "options", "update", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; PropertyRNA *prop; StructRNA *ptype; @@ -1336,7 +1336,7 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k return NULL; } - prop = RNA_def_pointer_runtime(srna, id, ptype, name, description); + prop = RNA_def_pointer_runtime(srna, id, ptype, name ? name : id, description); if (pyopts) { if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -1368,7 +1368,7 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject if (srna) { static const char *kwlist[] = {"attr", "type", "name", "description", "options", NULL}; - const char *id = NULL, *name = "", *description = ""; + const char *id = NULL, *name = NULL, *description = ""; int id_len; PropertyRNA *prop; StructRNA *ptype; @@ -1391,7 +1391,7 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject if (!ptype) return NULL; - prop = RNA_def_collection_runtime(srna, id, ptype, name, description); + prop = RNA_def_collection_runtime(srna, id, ptype, name ? name : id, description); if (pyopts) { if (opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if ((opts & PROP_ANIMATABLE) == 0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index 8fd04026233..b1fa00d3509 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -106,21 +106,26 @@ static struct QuicktimeExport *qtexport; /* Video codec */ static QuicktimeCodecTypeDesc qtVideoCodecList[] = { {kRawCodecType, 1, "Uncompressed"}, - {kJPEGCodecType, 2, "JPEG"}, - {kMotionJPEGACodecType, 3, "M-JPEG A"}, - {kMotionJPEGBCodecType, 4, "M-JPEG B"}, - {kDVCPALCodecType, 5, "DV PAL"}, - {kDVCNTSCCodecType, 6, "DV/DVCPRO NTSC"}, - {kDVCPROHD720pCodecType, 7, "DVCPRO HD 720p"}, - {kDVCPROHD1080i50CodecType, 8, "DVCPRO HD 1080i50"}, - {kDVCPROHD1080i60CodecType, 9, "DVCPRO HD 1080i60"}, - {kMPEG4VisualCodecType, 10, "MPEG4"}, - {kH263CodecType, 11, "H.263"}, - {kH264CodecType, 12, "H.264"}, - {kAnimationCodecType, 13, "Animation"}, + {k422YpCbCr8CodecType, 2, "Uncompressed 8-bit 4:2:2"}, + {k422YpCbCr10CodecType, 3, "Uncompressed 10-bit 4:2:2"}, + {kComponentVideoCodecType, 4, "Component Video"}, + {kPixletCodecType, 5, "Pixlet"}, + {kPNGCodecType, 6, "PNG"}, + {kJPEGCodecType, 7, "JPEG"}, + {kMotionJPEGACodecType, 8, "M-JPEG A"}, + {kMotionJPEGBCodecType, 9, "M-JPEG B"}, + {kDVCPALCodecType, 10, "DV PAL"}, + {kDVCNTSCCodecType, 11, "DV/DVCPRO NTSC"}, + {kDVCPROHD720pCodecType, 12, "DVCPRO HD 720p"}, + {kDVCPROHD1080i50CodecType, 13, "DVCPRO HD 1080i50"}, + {kDVCPROHD1080i60CodecType, 14, "DVCPRO HD 1080i60"}, + {kMPEG4VisualCodecType, 15, "MPEG4"}, + {kH263CodecType, 16, "H.263"}, + {kH264CodecType, 17, "H.264"}, + {kAnimationCodecType, 18, "Animation"}, {0,0,NULL}}; -static int qtVideoCodecCount = 13; +static int qtVideoCodecCount = 18; int quicktime_get_num_videocodecs() { return qtVideoCodecCount; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index d82cff16496..0a481629ee8 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1149,32 +1149,17 @@ void RE_ResultGet32(Render *re, unsigned int *rect) RE_AcquireResultImage(re, &rres); - if(rres.rect32) + if(rres.rect32) { memcpy(rect, rres.rect32, sizeof(int)*rres.rectx*rres.recty); + } else if(rres.rectf) { - float *fp= rres.rectf; - int tot= rres.rectx*rres.recty; - char *cp= (char *)rect; - - if (re->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - /* Finally convert back to sRGB rendered image */ - for(;tot>0; tot--, cp+=4, fp+=4) { - cp[0] = FTOCHAR(linearrgb_to_srgb(fp[0])); - cp[1] = FTOCHAR(linearrgb_to_srgb(fp[1])); - cp[2] = FTOCHAR(linearrgb_to_srgb(fp[2])); - cp[3] = FTOCHAR(fp[3]); - } - } - else { - /* Color management is off : no conversion necessary */ - for(;tot>0; tot--, cp+=4, fp+=4) { - cp[0] = FTOCHAR(fp[0]); - cp[1] = FTOCHAR(fp[1]); - cp[2] = FTOCHAR(fp[2]); - cp[3] = FTOCHAR(fp[3]); - } - } + int profile_from= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; + int dither= 0; + IMB_buffer_byte_from_float((unsigned char*)rect, rres.rectf, + 4, dither, IB_PROFILE_SRGB, profile_from, predivide, + rres.rectx, rres.recty, rres.rectx, rres.rectx); } else /* else fill with black */ @@ -2567,24 +2552,18 @@ static void do_render_seq(Render * re) if(ibuf) { if(ibuf->rect_float) { + /* color management: when off ensure rectf is non-lin, since thats what the internal + * render engine delivers */ + int profile_to= (re->r.color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int profile_from= (ibuf->profile == IB_PROFILE_LINEAR_RGB)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; + int predivide= 0; + if (!rr->rectf) rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf"); - /* color management: when off ensure rectf is non-lin, since thats what the internal - * render engine delivers */ - if(re->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - if(ibuf->profile == IB_PROFILE_LINEAR_RGB) - memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); - else - srgb_to_linearrgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty); - - } - else { - if(ibuf->profile != IB_PROFILE_LINEAR_RGB) - memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); - else - linearrgb_to_srgb_rgba_rgba_buf(rr->rectf, ibuf->rect_float, rr->rectx*rr->recty); - } + IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float, + 4, profile_to, profile_from, predivide, + rr->rectx, rr->recty, rr->rectx, rr->rectx); /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 can hang around when sequence render has rendered a 32 bits one before */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index b6f59418f0a..2ab876b2165 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -46,6 +46,7 @@ #include "DNA_scene_types.h" #include "DNA_userdef_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_mesh_types.h" /* only for USE_BMESH_SAVE_AS_COMPAT */ #include "BLF_translation.h" @@ -1972,6 +1973,10 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) else fileflags &= ~G_FILE_COMPRESS; if(RNA_boolean_get(op->ptr, "relative_remap")) fileflags |= G_FILE_RELATIVE_REMAP; else fileflags &= ~G_FILE_RELATIVE_REMAP; +#ifdef USE_BMESH_SAVE_AS_COMPAT + if(RNA_boolean_get(op->ptr, "use_mesh_compat")) fileflags |= G_FILE_MESH_COMPAT; + else fileflags &= ~G_FILE_MESH_COMPAT; +#endif if ( WM_write_file(C, path, fileflags, op->reports, copy) != 0) return OPERATOR_CANCELLED; @@ -2011,6 +2016,9 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file"); RNA_def_boolean(ot->srna, "relative_remap", 1, "Remap Relative", "Remap relative paths when saving in a different directory"); RNA_def_boolean(ot->srna, "copy", 0, "Save Copy", "Save a copy of the actual working state but does not make saved file active"); +#ifdef USE_BMESH_SAVE_AS_COMPAT + RNA_def_boolean(ot->srna, "use_mesh_compat", 0, "Legacy Mesh Format", "Save using legacy mesh format (no ngons)"); +#endif } /* *************** save file directly ******** */ |