static void mask_rasterize_func(TaskPool *pool, void *taskdata, int UNUSED(threadid)) { ThreadedMaskRasterizeState *state = (ThreadedMaskRasterizeState *) BLI_task_pool_userdata(pool); ThreadedMaskRasterizeData *data = (ThreadedMaskRasterizeData *) taskdata; int scanline; const float x_inv = 1.0f / (float)state->width; const float y_inv = 1.0f / (float)state->height; const float x_px_ofs = x_inv * 0.5f; const float y_px_ofs = y_inv * 0.5f; for (scanline = 0; scanline < data->num_scanlines; scanline++) { float xy[2]; int x, y = data->start_scanline + scanline; xy[1] = ((float)y * y_inv) + y_px_ofs; for (x = 0; x < state->width; x++) { int index = y * state->width + x; xy[0] = ((float)x * x_inv) + x_px_ofs; state->buffer[index] = BKE_maskrasterize_handle_sample(state->handle, xy); } } }
static void proxy_task_func(TaskPool *pool, void *task_data, int UNUSED(threadid)) { ProxyThread *data = (ProxyThread *)task_data; ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool); unsigned char *mem; size_t size; int cfra; while ((mem = proxy_thread_next_frame(queue, data->clip, &size, &cfra))) { ImBuf *ibuf; ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, data->clip->colorspace_settings.name, "proxy frame"); BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra, data->build_sizes, data->build_count, false); BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra, data->build_undistort_sizes, data->build_undistort_count, true); IMB_freeImBuf(ibuf); MEM_freeN(mem); } }
static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(threadid)) { KX_GameObject *gameobj, *child; CListValue *children; bool needs_update; double curtime = *(double*)BLI_task_pool_userdata(pool); gameobj = (KX_GameObject*)taskdata; // Non-armature updates are fast enough, so just update them needs_update = gameobj->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE; if (!needs_update) { // If we got here, we're looking to update an armature, so check its // children meshes to see if we need to bother with a more expensive // pose update children = gameobj->GetChildren(); bool has_mesh = false, has_non_mesh = false; // Check for meshes that haven't been culled for (int j=0; j<children->GetCount(); ++j) { child = (KX_GameObject*)children->GetValue(j); if (!child->GetCulled()) { needs_update = true; break; } if (child->GetMeshCount() == 0) has_non_mesh = true; else has_mesh = true; } // If we didn't find a non-culled mesh, check to see // if we even have any meshes, and update if this // armature has only non-mesh children. if (!needs_update && !has_mesh && has_non_mesh) needs_update = true; children->Release(); } if (needs_update) gameobj->UpdateActionManager(curtime); }
static void mask_rasterize_func(TaskPool *pool, void *taskdata, int UNUSED(threadid)) { ThreadedMaskRasterizeState *state = (ThreadedMaskRasterizeState *) BLI_task_pool_userdata(pool); ThreadedMaskRasterizeData *data = (ThreadedMaskRasterizeData *) taskdata; int scanline; for (scanline = 0; scanline < data->num_scanlines; scanline++) { int x, y = data->start_scanline + scanline; for (x = 0; x < state->width; x++) { int index = y * state->width + x; float xy[2]; xy[0] = (float) x / state->width; xy[1] = (float) y / state->height; state->buffer[index] = BKE_maskrasterize_handle_sample(state->handle, xy); } } }
static void prefetch_task_func(TaskPool *pool, void *task_data, int UNUSED(threadid)) { PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool); MovieClip *clip = (MovieClip *)task_data; unsigned char *mem; size_t size; int current_frame; while ((mem = prefetch_thread_next_frame(queue, clip, &size, ¤t_frame))) { ImBuf *ibuf; MovieClipUser user = {0}; int flag = IB_rect | IB_alphamode_detect; int result; char *colorspace_name = NULL; const bool use_proxy = (clip->flag & MCLIP_USE_PROXY) && (queue->render_size != MCLIP_PROXY_RENDER_SIZE_FULL); user.framenr = current_frame; user.render_size = queue->render_size; user.render_flag = queue->render_flag; /* Proxies are stored in the display space. */ if (!use_proxy) { colorspace_name = clip->colorspace_settings.name; } ibuf = IMB_ibImageFromMemory(mem, size, flag, colorspace_name, "prefetch frame"); result = BKE_movieclip_put_frame_if_possible(clip, &user, ibuf); IMB_freeImBuf(ibuf); MEM_freeN(mem); if (!result) { /* no more space in the cache, stop reading frames */ *queue->stop = 1; break; } } }
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; } static void proxy_task_func(TaskPool * __restrict pool, void *task_data, int UNUSED(threadid)) { ProxyThread *data = (ProxyThread *)task_data; ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool); unsigned char *mem; size_t size; int cfra; while ((mem = proxy_thread_next_frame(queue, data->clip, &size, &cfra))) { ImBuf *ibuf; ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, data->clip->colorspace_settings.name, "proxy frame"); BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra, data->build_sizes, data->build_count, false); BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra, data->build_undistort_sizes, data->build_undistort_count, true);
float *outF = NULL; if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { return; } pixel_from_buffer(out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ nearest_interpolation_color(in, outI, outF, x, y); } /*********************** Threaded image processing *************************/ static void processor_apply_func(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid)) { void (*do_thread) (void *) = (void (*) (void *)) BLI_task_pool_userdata(pool); do_thread(taskdata); } void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_customdata, void (init_handle) (void *handle, int start_line, int tot_line, void *customdata), void *(do_thread) (void *)) { const int lines_per_task = 64; TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; void *handles; int total_tasks = (buffer_lines + lines_per_task - 1) / lines_per_task;
static void scene_update_object_func(TaskPool *pool, void *taskdata, int threadid) { /* Disable print for now in favor of summary statistics at the end of update. */ #define PRINT if (false) printf ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool); void *node = taskdata; Object *object = DAG_get_node_object(node); EvaluationContext *eval_ctx = state->eval_ctx; Scene *scene = state->scene; Scene *scene_parent = state->scene_parent; #ifdef MBALL_SINGLETHREAD_HACK if (object && object->type == OB_MBALL) { state->has_mballs = true; } else #endif if (object) { double start_time = 0.0; bool add_to_stats = false; PRINT("Thread %d: update object %s\n", threadid, object->id.name); if (G.debug & G_DEBUG) { start_time = PIL_check_seconds_timer(); if (object->recalc & OB_RECALC_ALL) { state->has_updated_objects = true; add_to_stats = true; } } /* We only update object itself here, dupli-group will be updated * separately from main thread because of we've got no idea about * dependnecies inside the group. */ BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world); /* Calculate statistics. */ if (add_to_stats) { StatisicsEntry *entry; entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics"); entry->object = object; entry->start_time = start_time; entry->duration = PIL_check_seconds_timer() - start_time; BLI_addtail(&state->statistics[threadid], entry); } } else { PRINT("Threda %d: update node %s\n", threadid, DAG_get_node_name(node)); } /* Update will decrease child's valency and schedule child with zero valency. */ DAG_threaded_update_handle_node_updated(node,scene_update_object_add_task, pool); #undef PRINT }
static void processor_apply_func(TaskPool *pool, void *taskdata, int UNUSED(threadid)) { void (*do_thread) (void *) = (void (*) (void *)) BLI_task_pool_userdata(pool); do_thread(taskdata); }