2011-04-27 11:58:34 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2011, Blender Foundation.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "background.h"
|
|
|
|
#include "buffers.h"
|
|
|
|
#include "camera.h"
|
|
|
|
#include "device.h"
|
|
|
|
#include "integrator.h"
|
2011-08-28 13:55:59 +00:00
|
|
|
#include "film.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
#include "light.h"
|
|
|
|
#include "scene.h"
|
|
|
|
#include "session.h"
|
|
|
|
#include "shader.h"
|
|
|
|
|
|
|
|
#include "util_color.h"
|
|
|
|
#include "util_foreach.h"
|
|
|
|
#include "util_function.h"
|
|
|
|
#include "util_progress.h"
|
|
|
|
#include "util_time.h"
|
|
|
|
|
|
|
|
#include "blender_sync.h"
|
|
|
|
#include "blender_session.h"
|
|
|
|
#include "blender_util.h"
|
|
|
|
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_)
|
|
|
|
: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL)
|
|
|
|
{
|
|
|
|
/* offline render */
|
|
|
|
BL::RenderSettings r = b_scene.render();
|
|
|
|
|
|
|
|
width = (int)(r.resolution_x()*r.resolution_percentage()*0.01f);
|
|
|
|
height = (int)(r.resolution_y()*r.resolution_percentage()*0.01f);
|
|
|
|
background = true;
|
|
|
|
last_redraw_time = 0.0f;
|
|
|
|
|
|
|
|
create_session();
|
|
|
|
}
|
|
|
|
|
|
|
|
BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_,
|
|
|
|
BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_)
|
|
|
|
: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(b_v3d_), b_rv3d(b_rv3d_)
|
|
|
|
{
|
|
|
|
/* 3d view render */
|
|
|
|
width = width_;
|
|
|
|
height = height_;
|
|
|
|
background = false;
|
|
|
|
last_redraw_time = 0.0f;
|
|
|
|
|
|
|
|
create_session();
|
|
|
|
}
|
|
|
|
|
|
|
|
BlenderSession::~BlenderSession()
|
|
|
|
{
|
|
|
|
free_session();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::create_session()
|
|
|
|
{
|
2011-11-04 15:46:15 +00:00
|
|
|
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
|
2011-04-27 11:58:34 +00:00
|
|
|
SessionParams session_params = BlenderSync::get_session_params(b_scene, background);
|
|
|
|
|
2011-10-30 10:12:34 +00:00
|
|
|
/* reset status/progress */
|
|
|
|
last_status= "";
|
|
|
|
last_progress= -1.0f;
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* create scene */
|
|
|
|
scene = new Scene(scene_params);
|
|
|
|
|
|
|
|
/* create sync */
|
|
|
|
sync = new BlenderSync(b_data, b_scene, scene, !background);
|
|
|
|
sync->sync_data(b_v3d);
|
|
|
|
|
|
|
|
if(b_rv3d)
|
|
|
|
sync->sync_view(b_v3d, b_rv3d, width, height);
|
|
|
|
else
|
|
|
|
sync->sync_camera(width, height);
|
|
|
|
|
|
|
|
/* create session */
|
|
|
|
session = new Session(session_params);
|
|
|
|
session->scene = scene;
|
|
|
|
session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
|
|
|
|
session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
|
2011-08-29 16:54:13 +00:00
|
|
|
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
/* start rendering */
|
2011-12-20 12:25:37 +00:00
|
|
|
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
|
|
|
|
|
|
|
|
session->reset(buffer_params, session_params.samples);
|
2011-04-27 11:58:34 +00:00
|
|
|
session->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::free_session()
|
|
|
|
{
|
|
|
|
delete sync;
|
|
|
|
delete session;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::render()
|
|
|
|
{
|
|
|
|
session->wait();
|
|
|
|
|
|
|
|
if(session->progress.get_cancel())
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* write result */
|
|
|
|
write_render_result();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::write_render_result()
|
|
|
|
{
|
|
|
|
/* get result */
|
2011-08-28 13:55:59 +00:00
|
|
|
RenderBuffers *buffers = session->buffers;
|
|
|
|
float exposure = scene->film->exposure;
|
2011-09-16 13:14:02 +00:00
|
|
|
double total_time, sample_time;
|
|
|
|
int sample;
|
|
|
|
session->progress.get_sample(sample, total_time, sample_time);
|
2011-05-09 09:03:08 +00:00
|
|
|
|
2011-09-16 13:14:02 +00:00
|
|
|
float4 *pixels = buffers->copy_from_device(exposure, sample);
|
2011-05-09 09:03:08 +00:00
|
|
|
|
2011-08-28 13:55:59 +00:00
|
|
|
if(!pixels)
|
|
|
|
return;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-12-20 12:25:37 +00:00
|
|
|
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
|
|
|
|
int w = buffer_params.width, h = buffer_params.height;
|
|
|
|
|
|
|
|
struct RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, w, h);
|
2011-04-27 11:58:34 +00:00
|
|
|
PointerRNA rrptr;
|
|
|
|
RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr);
|
|
|
|
BL::RenderResult rr(rrptr);
|
|
|
|
|
2011-08-21 10:32:15 +00:00
|
|
|
BL::RenderResult::layers_iterator layer;
|
|
|
|
rr.layers.begin(layer);
|
2011-08-28 13:55:59 +00:00
|
|
|
rna_RenderLayer_rect_set(&layer->ptr, (float*)pixels);
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
RE_engine_end_result((RenderEngine*)b_engine.ptr.data, rrp);
|
2011-08-28 13:55:59 +00:00
|
|
|
|
|
|
|
delete [] pixels;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::synchronize()
|
|
|
|
{
|
|
|
|
/* on session/scene parameter changes, we recreate session entirely */
|
2011-11-04 15:46:15 +00:00
|
|
|
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
|
2011-04-27 11:58:34 +00:00
|
|
|
SessionParams session_params = BlenderSync::get_session_params(b_scene, background);
|
|
|
|
|
|
|
|
if(session->params.modified(session_params) ||
|
|
|
|
scene->params.modified(scene_params)) {
|
|
|
|
free_session();
|
|
|
|
create_session();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-16 13:14:02 +00:00
|
|
|
/* increase samples, but never decrease */
|
|
|
|
session->set_samples(session_params.samples);
|
2011-08-29 16:54:13 +00:00
|
|
|
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
|
2011-08-28 13:55:59 +00:00
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* copy recalc flags, outside of mutex so we can decide to do the real
|
|
|
|
synchronization at a later time to not block on running updates */
|
|
|
|
sync->sync_recalc();
|
|
|
|
|
|
|
|
/* try to acquire mutex. if we don't want to or can't, come back later */
|
|
|
|
if(!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
|
|
|
|
tag_update();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* data and camera synchronize */
|
|
|
|
sync->sync_data(b_v3d);
|
|
|
|
|
|
|
|
if(b_rv3d)
|
|
|
|
sync->sync_view(b_v3d, b_rv3d, width, height);
|
|
|
|
else
|
|
|
|
sync->sync_camera(width, height);
|
|
|
|
|
2011-08-29 16:54:13 +00:00
|
|
|
/* unlock */
|
|
|
|
session->scene->mutex.unlock();
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* reset if needed */
|
2011-12-20 12:25:37 +00:00
|
|
|
if(scene->need_reset()) {
|
|
|
|
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
|
|
|
|
session->reset(buffer_params, session_params.samples);
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool BlenderSession::draw(int w, int h)
|
|
|
|
{
|
|
|
|
/* before drawing, we verify camera and viewport size changes, because
|
|
|
|
we do not get update callbacks for those, we must detect them here */
|
|
|
|
if(session->ready_to_reset()) {
|
|
|
|
bool reset = false;
|
|
|
|
|
|
|
|
/* try to acquire mutex. if we can't, come back later */
|
|
|
|
if(!session->scene->mutex.try_lock()) {
|
|
|
|
tag_update();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* update camera from 3d view */
|
|
|
|
bool need_update = scene->camera->need_update;
|
|
|
|
|
|
|
|
sync->sync_view(b_v3d, b_rv3d, w, h);
|
|
|
|
|
|
|
|
if(scene->camera->need_update && !need_update)
|
|
|
|
reset = true;
|
|
|
|
|
|
|
|
session->scene->mutex.unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if dimensions changed, reset */
|
|
|
|
if(width != w || height != h) {
|
|
|
|
width = w;
|
|
|
|
height = h;
|
|
|
|
reset = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset if requested */
|
2011-08-28 13:55:59 +00:00
|
|
|
if(reset) {
|
|
|
|
SessionParams session_params = BlenderSync::get_session_params(b_scene, background);
|
2011-12-20 12:25:37 +00:00
|
|
|
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
|
|
|
|
|
|
|
|
session->reset(buffer_params, session_params.samples);
|
2011-08-28 13:55:59 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
2011-08-23 12:20:11 +00:00
|
|
|
/* update status and progress for 3d view draw */
|
|
|
|
update_status_progress();
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-08-23 12:20:11 +00:00
|
|
|
/* draw */
|
2011-12-20 12:25:37 +00:00
|
|
|
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
|
|
|
|
|
|
|
|
return !session->draw(buffer_params);
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::get_status(string& status, string& substatus)
|
|
|
|
{
|
|
|
|
session->progress.get_status(status, substatus);
|
|
|
|
}
|
|
|
|
|
2011-08-22 13:17:43 +00:00
|
|
|
void BlenderSession::get_progress(float& progress, double& total_time)
|
|
|
|
{
|
2011-09-16 13:14:02 +00:00
|
|
|
double sample_time;
|
|
|
|
int sample;
|
2011-08-22 13:17:43 +00:00
|
|
|
|
2011-09-16 13:14:02 +00:00
|
|
|
session->progress.get_sample(sample, total_time, sample_time);
|
|
|
|
progress = ((float)sample/(float)session->params.samples);
|
2011-08-22 13:17:43 +00:00
|
|
|
}
|
|
|
|
|
2011-08-23 12:20:11 +00:00
|
|
|
void BlenderSession::update_status_progress()
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
2011-08-22 13:17:43 +00:00
|
|
|
string status, substatus;
|
|
|
|
float progress;
|
|
|
|
double total_time;
|
|
|
|
char time_str[128];
|
|
|
|
|
|
|
|
get_status(status, substatus);
|
|
|
|
get_progress(progress, total_time);
|
|
|
|
|
|
|
|
if(!background) {
|
|
|
|
BLI_timestr(total_time, time_str);
|
|
|
|
status = "Time: " + string(time_str) + " | " + status;
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-08-22 13:17:43 +00:00
|
|
|
if(substatus.size() > 0)
|
|
|
|
status += " | " + substatus;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-10-30 10:12:34 +00:00
|
|
|
if(status != last_status) {
|
|
|
|
RE_engine_update_stats((RenderEngine*)b_engine.ptr.data, "", status.c_str());
|
|
|
|
last_status = status;
|
|
|
|
}
|
|
|
|
if(progress != last_progress) {
|
|
|
|
RE_engine_update_progress((RenderEngine*)b_engine.ptr.data, progress);
|
|
|
|
last_progress = progress;
|
|
|
|
}
|
2011-08-23 12:20:11 +00:00
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
|
2011-08-23 12:20:11 +00:00
|
|
|
void BlenderSession::tag_update()
|
|
|
|
{
|
|
|
|
/* tell blender that we want to get another update callback */
|
|
|
|
engine_tag_update((RenderEngine*)b_engine.ptr.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::tag_redraw()
|
|
|
|
{
|
2011-08-22 13:17:43 +00:00
|
|
|
if(background) {
|
2011-08-23 12:20:11 +00:00
|
|
|
/* update stats and progress, only for background here because
|
|
|
|
in 3d view we do it in draw for thread safety reasons */
|
|
|
|
update_status_progress();
|
|
|
|
|
2011-08-22 13:17:43 +00:00
|
|
|
/* offline render, redraw if timeout passed */
|
2011-04-27 11:58:34 +00:00
|
|
|
if(time_dt() - last_redraw_time > 1.0f) {
|
|
|
|
write_render_result();
|
|
|
|
engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
|
|
|
|
last_redraw_time = time_dt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* tell blender that we want to redraw */
|
|
|
|
engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlenderSession::test_cancel()
|
|
|
|
{
|
|
|
|
/* test if we need to cancel rendering */
|
|
|
|
if(background)
|
|
|
|
if(RE_engine_test_break((RenderEngine*)b_engine.ptr.data))
|
|
|
|
session->progress.set_cancel("Cancelled");
|
|
|
|
}
|
|
|
|
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
|