void IMB_freeImBuf(ImBuf *ibuf) { if (ibuf) { bool needs_free = false; BLI_spin_lock(&refcounter_spin); if (ibuf->refcounter > 0) { ibuf->refcounter--; } else { needs_free = true; } BLI_spin_unlock(&refcounter_spin); if (needs_free) { imb_freerectImBuf(ibuf); imb_freerectfloatImBuf(ibuf); imb_freetilesImBuf(ibuf); IMB_freezbufImBuf(ibuf); IMB_freezbuffloatImBuf(ibuf); freeencodedbufferImBuf(ibuf); IMB_metadata_free(ibuf); colormanage_cache_free(ibuf); if (ibuf->dds_data.data != NULL) { free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */ } MEM_freeN(ibuf); } } }
ImBuf *IMB_makeSingleUser(ImBuf *ibuf) { ImBuf *rval; if (ibuf) { bool is_single; BLI_spin_lock(&refcounter_spin); is_single = (ibuf->refcounter == 0); BLI_spin_unlock(&refcounter_spin); if (is_single) { return ibuf; } } else { return NULL; } rval = IMB_dupImBuf(ibuf); IMB_metadata_copy(rval, ibuf); IMB_freeImBuf(ibuf); return rval; }
static void *do_multires_bake_thread(void *data_v) { MultiresBakeThread *handle = (MultiresBakeThread *) data_v; MResolvePixelData *data = &handle->data; MBakeRast *bake_rast = &handle->bake_rast; MultiresBakeRender *bkr = handle->bkr; int f; while ((f = multires_bake_queue_next_face(handle->queue)) >= 0) { MTFace *mtfate = &data->mtface[f]; int verts[3][2], nr_tris, t; if (multiresbake_test_break(bkr)) break; if (mtfate->tpage != handle->image) continue; data->face_index = f; /* might support other forms of diagonal splits later on such as * split by shortest diagonal.*/ verts[0][0] = 0; verts[1][0] = 1; verts[2][0] = 2; verts[0][1] = 0; verts[1][1] = 2; verts[2][1] = 3; nr_tris = data->mface[f].v4 != 0 ? 2 : 1; for (t = 0; t < nr_tris; t++) { data->i0 = verts[0][t]; data->i1 = verts[1][t]; data->i2 = verts[2][t]; bake_rasterize(bake_rast, mtfate->uv[data->i0], mtfate->uv[data->i1], mtfate->uv[data->i2]); /* tag image buffer for refresh */ if (data->ibuf->rect_float) data->ibuf->userflags |= IB_RECT_INVALID; data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } /* update progress */ BLI_spin_lock(&handle->queue->spin); bkr->baked_faces++; if (bkr->do_update) *bkr->do_update = TRUE; if (bkr->progress) *bkr->progress = ((float)bkr->baked_objects + (float)bkr->baked_faces / handle->queue->tot_face) / bkr->tot_obj; BLI_spin_unlock(&handle->queue->spin); } return NULL; }
/* get memory buffer for first uncached frame within prefetch frame range */ static unsigned char *prefetch_thread_next_frame( PrefetchQueue *queue, MovieClip *clip, size_t *r_size, int *r_current_frame) { unsigned char *mem = NULL; BLI_spin_lock(&queue->spin); if (!*queue->stop && !check_prefetch_break() && IN_RANGE_INCL(queue->current_frame, queue->start_frame, queue->end_frame)) { int current_frame; if (queue->forward) { current_frame = prefetch_find_uncached_frame(clip, queue->current_frame + 1, queue->end_frame, queue->render_size, queue->render_flag, 1); /* switch direction if read frames from current up to scene end frames */ if (current_frame > queue->end_frame) { queue->current_frame = queue->initial_frame; queue->forward = false; } } if (!queue->forward) { current_frame = prefetch_find_uncached_frame(clip, queue->current_frame - 1, queue->start_frame, queue->render_size, queue->render_flag, -1); } if (IN_RANGE_INCL(current_frame, queue->start_frame, queue->end_frame)) { int frames_processed; mem = prefetch_read_file_to_memory(clip, current_frame, queue->render_size, queue->render_flag, r_size); *r_current_frame = current_frame; queue->current_frame = current_frame; if (queue->forward) { frames_processed = queue->current_frame - queue->initial_frame; } else { frames_processed = (queue->end_frame - queue->initial_frame) + (queue->initial_frame - queue->current_frame); } *queue->do_update = 1; *queue->progress = (float)frames_processed / (queue->end_frame - queue->start_frame); } } BLI_spin_unlock(&queue->spin); return mem; }
/* only this runs inside thread */ static void preview_startjob(void *data, short *stop, short *do_update, float *progress) { PreviewJob *pj = data; PreviewJobAudio *previewjb; BLI_mutex_lock(pj->mutex); previewjb = pj->previews.first; BLI_mutex_unlock(pj->mutex); while (previewjb) { PreviewJobAudio *preview_next; bSound *sound = previewjb->sound; BKE_sound_read_waveform(sound, stop); if (*stop || G.is_break) { BLI_mutex_lock(pj->mutex); previewjb = previewjb->next; BLI_mutex_unlock(pj->mutex); while (previewjb) { sound = previewjb->sound; /* make sure we cleanup the loading flag! */ BLI_spin_lock(sound->spinlock); sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING; BLI_spin_unlock(sound->spinlock); BLI_mutex_lock(pj->mutex); previewjb = previewjb->next; BLI_mutex_unlock(pj->mutex); } BLI_mutex_lock(pj->mutex); BLI_freelistN(&pj->previews); pj->total = 0; pj->processed = 0; BLI_mutex_unlock(pj->mutex); break; } BLI_mutex_lock(pj->mutex); preview_next = previewjb->next; BLI_freelinkN(&pj->previews, previewjb); previewjb = preview_next; pj->processed++; *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0f; *do_update = true; BLI_mutex_unlock(pj->mutex); } }
static unsigned char *proxy_thread_next_frame(ProxyQueue *queue, MovieClip *clip, size_t *size_r, int *cfra_r) { unsigned char *mem = NULL; BLI_spin_lock(&queue->spin); if (!*queue->stop && queue->cfra <= queue->efra) { MovieClipUser user = {0}; char name[FILE_MAX]; size_t size; int file; user.framenr = queue->cfra; BKE_movieclip_filename_for_frame(clip, &user, name); file = open(name, O_BINARY | O_RDONLY, 0); if (file < 0) { BLI_spin_unlock(&queue->spin); return NULL; } size = BLI_file_descriptor_size(file); if (size < 1) { close(file); BLI_spin_unlock(&queue->spin); return NULL; } mem = MEM_mallocN(size, "movieclip proxy memory file"); if (read(file, mem, size) != size) { close(file); BLI_spin_unlock(&queue->spin); MEM_freeN(mem); return NULL; } *size_r = size; *cfra_r = queue->cfra; queue->cfra++; close(file); *queue->do_update = 1; *queue->progress = (float)(queue->cfra - queue->sfra) / (queue->efra - queue->sfra); } BLI_spin_unlock(&queue->spin); return mem; }
void BKE_cachefile_ensure_handle(const Main *bmain, CacheFile *cache_file) { BLI_spin_lock(&spin); if (cache_file->handle_mutex == NULL) { cache_file->handle_mutex = BLI_mutex_alloc(); } BLI_spin_unlock(&spin); BLI_mutex_lock(cache_file->handle_mutex); if (cache_file->handle == NULL) { BKE_cachefile_reload(bmain, cache_file); } BLI_mutex_unlock(cache_file->handle_mutex); }
static int multires_bake_queue_next_face(MultiresBakeQueue *queue) { int face = -1; /* TODO: it could worth making it so thread will handle neighbor faces * for better memory cache utilization */ BLI_spin_lock(&queue->spin); if (queue->cur_face < queue->tot_face) { face = queue->cur_face; queue->cur_face++; } BLI_spin_unlock(&queue->spin); return face; }
void IMB_refImBuf(ImBuf *ibuf) { BLI_spin_lock(&refcounter_spin); ibuf->refcounter++; BLI_spin_unlock(&refcounter_spin); }
GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) { FT_GlyphSlot slot; GlyphBLF *g; FT_Error err; FT_Bitmap bitmap, tempbitmap; const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0; int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; FT_BBox bbox; unsigned int key; g = blf_glyph_search(font->glyph_cache, c); if (g) return g; /* glyphs are dynamically created as needed by font rendering. this means that * to make font rendering thread safe we have to do locking here. note that this * must be a lock for the whole library and not just per font, because the font * renderer uses a shared buffer internally */ BLI_spin_lock(font->ft_lib_mutex); /* search again after locking */ g = blf_glyph_search(font->glyph_cache, c); if (g) { BLI_spin_unlock(font->ft_lib_mutex); return g; } if (font->flags & BLF_HINTING) flags &= ~FT_LOAD_NO_HINTING; if (is_sharp) err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO); else err = FT_Load_Glyph(font->face, (FT_UInt)index, flags); if (err) { BLI_spin_unlock(font->ft_lib_mutex); return NULL; } /* get the glyph. */ slot = font->face->glyph; if (is_sharp) { err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO); /* Convert result from 1 bit per pixel to 8 bit per pixel */ /* Accum errors for later, fine if not interested beyond "ok vs any error" */ FT_Bitmap_New(&tempbitmap); err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1); /* Does Blender use Pitch 1 always? It works so far */ err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap); err += FT_Bitmap_Done(font->ft_lib, &tempbitmap); } else { err = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL); } if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) { BLI_spin_unlock(font->ft_lib_mutex); return NULL; } g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add"); g->c = c; g->idx = (FT_UInt)index; g->xoff = -1; g->yoff = -1; bitmap = slot->bitmap; g->width = (int)bitmap.width; g->height = (int)bitmap.rows; if (g->width && g->height) { if (is_sharp) { /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */ int i; for (i = 0; i < (g->width * g->height); i++) { bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0; } } g->bitmap = (unsigned char *)MEM_mallocN((size_t)(g->width * g->height), "glyph bitmap"); memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)(g->width * g->height)); } g->advance = ((float)slot->advance.x) / 64.0f; g->advance_i = (int)g->advance; g->pos_x = (float)slot->bitmap_left; g->pos_y = (float)slot->bitmap_top; g->pitch = slot->bitmap.pitch; FT_Outline_Get_CBox(&(slot->outline), &bbox); g->box.xmin = ((float)bbox.xMin) / 64.0f; g->box.xmax = ((float)bbox.xMax) / 64.0f; g->box.ymin = ((float)bbox.yMin) / 64.0f; g->box.ymax = ((float)bbox.yMax) / 64.0f; key = blf_hash(g->c); BLI_addhead(&(font->glyph_cache->bucket[key]), g); BLI_spin_unlock(font->ft_lib_mutex); return g; }
void tracks_map_merge(TracksMap *map, MovieTracking *tracking) { MovieTrackingTrack *track; ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL}; ListBase *old_tracks; int a; if (map->is_camera) { old_tracks = &tracking->tracks; } else { MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name); if (!object) { /* object was deleted by user, create new one */ object = BKE_tracking_object_add(tracking, map->object_name); } old_tracks = &object->tracks; } /* duplicate currently operating tracks to temporary list. * this is needed to keep names in unique state and it's faster to change names * of currently operating tracks (if needed) */ for (a = 0; a < map->num_tracks; a++) { MovieTrackingTrack *old_track; bool mapped_to_old = false; track = &map->tracks[a]; /* find original of operating track in list of previously displayed tracks */ old_track = BLI_ghash_lookup(map->hash, track); if (old_track) { if (BLI_findindex(old_tracks, old_track) != -1) { BLI_remlink(old_tracks, old_track); BLI_spin_lock(&map->spin_lock); /* Copy flags like selection back to the track map. */ track->flag = old_track->flag; track->pat_flag = old_track->pat_flag; track->search_flag = old_track->search_flag; /* Copy all the rest settings back from the map to the actual tracks. */ MEM_freeN(old_track->markers); *old_track = *track; old_track->markers = MEM_dupallocN(old_track->markers); BLI_spin_unlock(&map->spin_lock); BLI_addtail(&tracks, old_track); mapped_to_old = true; } } if (mapped_to_old == false) { MovieTrackingTrack *new_track = BKE_tracking_track_duplicate(track); /* Update old-new track mapping */ BLI_ghash_reinsert(map->hash, track, new_track, NULL, NULL); BLI_addtail(&tracks, new_track); } } /* move all tracks, which aren't operating */ track = old_tracks->first; while (track) { MovieTrackingTrack *next = track->next; BLI_addtail(&new_tracks, track); track = next; } /* now move all tracks which are currently operating and keep their names unique */ track = tracks.first; while (track) { MovieTrackingTrack *next = track->next; BLI_remlink(&tracks, track); track->next = track->prev = NULL; BLI_addtail(&new_tracks, track); BLI_uniquename(&new_tracks, track, CTX_DATA_(BLF_I18NCONTEXT_ID_MOVIECLIP, "Track"), '.', offsetof(MovieTrackingTrack, name), sizeof(track->name)); track = next; } *old_tracks = new_tracks; }
void imb_mmap_lock(void) { BLI_spin_lock(&mmap_spin); }
static void BLI_lock_malloc_thread(void) { BLI_spin_lock(&_malloc_lock); }
static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize) { /* * x1 is the starting x value to draw the wave, * x2 the end x value, same for y1 and y2 * stepsize is width of a pixel. */ if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) { int i, j, pos; int length = floor((x2 - x1) / stepsize) + 1; float ymid = (y1 + y2) / 2; float yscale = (y2 - y1) / 2; float samplestep; float startsample, endsample; float value1, value2; bSound *sound = seq->sound; SoundWaveform *waveform; if (!sound->spinlock) { sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); BLI_spin_init(sound->spinlock); } BLI_spin_lock(sound->spinlock); if (!seq->sound->waveform) { if (!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) { /* prevent sounds from reloading */ seq->sound->flags |= SOUND_FLAGS_WAVEFORM_LOADING; BLI_spin_unlock(sound->spinlock); sequencer_preview_add_sound(C, seq); } else { BLI_spin_unlock(sound->spinlock); } return; /* nothing to draw */ } BLI_spin_unlock(sound->spinlock); waveform = seq->sound->waveform; if (waveform->length == 0) { /* BKE_sound_read_waveform() set an empty SoundWaveform data in case it cannot generate a valid one... * See T45726. */ return; } startsample = floor((seq->startofs + seq->anim_startofs) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND); endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND); samplestep = (endsample - startsample) * stepsize / (x2 - x1); if (length > floor((waveform->length - startsample) / samplestep)) length = floor((waveform->length - startsample) / samplestep); glColor4f(1.0f, 1.0f, 1.0f, 0.5); glEnable(GL_BLEND); glBegin(GL_TRIANGLE_STRIP); for (i = 0; i < length; i++) { float sampleoffset = startsample + i * samplestep; pos = sampleoffset; value1 = waveform->data[pos * 3]; value2 = waveform->data[pos * 3 + 1]; if (samplestep > 1.0f) { for (j = pos + 1; (j < waveform->length) && (j < pos + samplestep); j++) { if (value1 > waveform->data[j * 3]) value1 = waveform->data[j * 3]; if (value2 < waveform->data[j * 3 + 1]) value2 = waveform->data[j * 3 + 1]; } } else { /* use simple linear interpolation */ float f = sampleoffset - pos; value1 = (1.0f - f) * value1 + f * waveform->data[pos * 3 + 3]; value2 = (1.0f - f) * value2 + f * waveform->data[pos * 3 + 4]; } glVertex2f(x1 + i * stepsize, ymid + value1 * yscale); glVertex2f(x1 + i * stepsize, ymid + value2 * yscale); } glEnd(); glDisable(GL_BLEND); } }
void BKE_main_lock(struct Main *bmain) { BLI_spin_lock((SpinLock *) bmain->lock); }