2011-10-22 16:24:28 +00:00
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* ***** 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) 2006 Blender Foundation.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): none yet.
|
|
|
|
|
*
|
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** \file blender/render/intern/pipeline/engine.c
|
|
|
|
|
* \ingroup render
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
#include "BLI_string.h"
|
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
|
|
|
|
#include "BKE_report.h"
|
|
|
|
|
#include "BKE_scene.h"
|
|
|
|
|
|
|
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
|
2011-10-22 17:01:54 +00:00
|
|
|
#ifdef WITH_PYTHON
|
|
|
|
|
#include "BPY_extern.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-10-22 16:24:28 +00:00
|
|
|
#include "RE_engine.h"
|
|
|
|
|
#include "RE_pipeline.h"
|
|
|
|
|
|
|
|
|
|
#include "render_types.h"
|
|
|
|
|
#include "renderpipeline.h"
|
|
|
|
|
|
2011-10-22 17:01:54 +00:00
|
|
|
/* Render Engine Types */
|
|
|
|
|
|
|
|
|
|
static RenderEngineType internal_render_type = {
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
"BLENDER_RENDER", "Blender Render", RE_INTERNAL,
|
|
|
|
|
NULL,
|
|
|
|
|
{NULL, NULL, NULL}};
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_GAMEENGINE
|
|
|
|
|
|
|
|
|
|
static RenderEngineType internal_game_type = {
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
"BLENDER_GAME", "Blender Game", RE_INTERNAL|RE_GAME,
|
|
|
|
|
NULL,
|
|
|
|
|
{NULL, NULL, NULL}};
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ListBase R_engines = {NULL, NULL};
|
|
|
|
|
|
|
|
|
|
void RE_engines_init(void)
|
|
|
|
|
{
|
|
|
|
|
BLI_addtail(&R_engines, &internal_render_type);
|
|
|
|
|
#ifdef WITH_GAMEENGINE
|
|
|
|
|
BLI_addtail(&R_engines, &internal_game_type);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RE_engines_exit(void)
|
|
|
|
|
{
|
|
|
|
|
RenderEngineType *type, *next;
|
|
|
|
|
|
|
|
|
|
for(type=R_engines.first; type; type=next) {
|
|
|
|
|
next= type->next;
|
|
|
|
|
|
|
|
|
|
BLI_remlink(&R_engines, type);
|
|
|
|
|
|
|
|
|
|
if(!(type->flag & RE_INTERNAL)) {
|
|
|
|
|
if(type->ext.free)
|
|
|
|
|
type->ext.free(type->ext.data);
|
|
|
|
|
|
|
|
|
|
MEM_freeN(type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RenderEngineType *RE_engines_find(const char *idname)
|
|
|
|
|
{
|
|
|
|
|
RenderEngineType *type;
|
|
|
|
|
|
|
|
|
|
type= BLI_findstring(&R_engines, idname, offsetof(RenderEngineType, idname));
|
|
|
|
|
if(!type)
|
|
|
|
|
type= &internal_render_type;
|
|
|
|
|
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create, Free */
|
|
|
|
|
|
|
|
|
|
RenderEngine *RE_engine_create(RenderEngineType *type)
|
|
|
|
|
{
|
|
|
|
|
RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine");
|
|
|
|
|
engine->type= type;
|
|
|
|
|
|
|
|
|
|
return engine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RE_engine_free(RenderEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
MEM_freeN(engine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Render Results */
|
2011-10-22 16:24:28 +00:00
|
|
|
|
|
|
|
|
RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h)
|
|
|
|
|
{
|
|
|
|
|
Render *re= engine->re;
|
|
|
|
|
RenderResult *result;
|
|
|
|
|
rcti disprect;
|
|
|
|
|
|
|
|
|
|
/* ensure the coordinates are within the right limits */
|
|
|
|
|
CLAMP(x, 0, re->result->rectx);
|
|
|
|
|
CLAMP(y, 0, re->result->recty);
|
|
|
|
|
CLAMP(w, 0, re->result->rectx);
|
|
|
|
|
CLAMP(h, 0, re->result->recty);
|
|
|
|
|
|
|
|
|
|
if(x + w > re->result->rectx)
|
|
|
|
|
w= re->result->rectx - x;
|
|
|
|
|
if(y + h > re->result->recty)
|
|
|
|
|
h= re->result->recty - y;
|
|
|
|
|
|
|
|
|
|
/* allocate a render result */
|
|
|
|
|
disprect.xmin= x;
|
|
|
|
|
disprect.xmax= x+w;
|
|
|
|
|
disprect.ymin= y;
|
|
|
|
|
disprect.ymax= y+h;
|
|
|
|
|
|
|
|
|
|
result= new_render_result(re, &disprect, 0, RR_USEMEM);
|
|
|
|
|
BLI_addtail(&engine->fullresult, result);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
|
|
|
|
|
{
|
|
|
|
|
Render *re= engine->re;
|
|
|
|
|
|
|
|
|
|
if(result) {
|
|
|
|
|
result->renlay= result->layers.first; // weak, draws first layer always
|
|
|
|
|
re->display_draw(re->ddh, result, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RE_engine_end_result(RenderEngine *engine, RenderResult *result)
|
|
|
|
|
{
|
|
|
|
|
Render *re= engine->re;
|
|
|
|
|
|
|
|
|
|
if(!result)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* merge. on break, don't merge in result for preview renders, looks nicer */
|
|
|
|
|
if(!(re->test_break(re->tbh) && (re->r.scemode & R_PREVIEWBUTS)))
|
|
|
|
|
merge_render_result(re->result, result);
|
|
|
|
|
|
|
|
|
|
/* draw */
|
|
|
|
|
if(!re->test_break(re->tbh)) {
|
|
|
|
|
result->renlay= result->layers.first; // weak, draws first layer always
|
|
|
|
|
re->display_draw(re->ddh, result, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* free */
|
|
|
|
|
free_render_result(&engine->fullresult, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Cancel */
|
|
|
|
|
|
|
|
|
|
int RE_engine_test_break(RenderEngine *engine)
|
|
|
|
|
{
|
|
|
|
|
Render *re= engine->re;
|
|
|
|
|
|
|
|
|
|
if(re)
|
|
|
|
|
return re->test_break(re->tbh);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Statistics */
|
|
|
|
|
|
|
|
|
|
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
|
|
|
|
|
{
|
|
|
|
|
Render *re= engine->re;
|
|
|
|
|
|
2011-10-22 17:01:54 +00:00
|
|
|
/* stats draw callback */
|
|
|
|
|
if(re) {
|
|
|
|
|
re->i.statstr= stats;
|
|
|
|
|
re->i.infostr= info;
|
|
|
|
|
re->stats_draw(re->sdh, &re->i);
|
|
|
|
|
re->i.infostr= NULL;
|
|
|
|
|
re->i.statstr= NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RE_engine_update_progress(RenderEngine *engine, float progress)
|
|
|
|
|
{
|
|
|
|
|
Render *re= engine->re;
|
|
|
|
|
|
|
|
|
|
if(re) {
|
|
|
|
|
CLAMP(progress, 0.0f, 1.0f);
|
|
|
|
|
re->progress(re->prh, progress);
|
|
|
|
|
}
|
2011-10-22 16:24:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RE_engine_report(RenderEngine *engine, int type, const char *msg)
|
|
|
|
|
{
|
|
|
|
|
BKE_report(engine->re->reports, type, msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Render */
|
|
|
|
|
|
|
|
|
|
int RE_engine_render(Render *re, int do_all)
|
|
|
|
|
{
|
2011-10-22 17:01:54 +00:00
|
|
|
RenderEngineType *type= RE_engines_find(re->r.engine);
|
|
|
|
|
RenderEngine *engine;
|
2011-10-22 16:24:28 +00:00
|
|
|
|
2011-10-22 17:01:54 +00:00
|
|
|
/* verify if we can render */
|
|
|
|
|
if(!type->render)
|
2011-10-22 16:24:28 +00:00
|
|
|
return 0;
|
2011-10-22 17:01:54 +00:00
|
|
|
if((re->r.scemode & R_PREVIEWBUTS) && !(type->flag & RE_USE_PREVIEW))
|
2011-10-22 16:24:28 +00:00
|
|
|
return 0;
|
2011-10-22 17:01:54 +00:00
|
|
|
if(do_all && !(type->flag & RE_USE_POSTPROCESS))
|
2011-10-22 16:24:28 +00:00
|
|
|
return 0;
|
2011-10-22 17:01:54 +00:00
|
|
|
if(!do_all && (type->flag & RE_USE_POSTPROCESS))
|
2011-10-22 16:24:28 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* create render result */
|
|
|
|
|
BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE);
|
|
|
|
|
if(re->result==NULL || !(re->r.scemode & R_PREVIEWBUTS)) {
|
|
|
|
|
RE_FreeRenderResult(re->result);
|
|
|
|
|
re->result= new_render_result(re, &re->disprect, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
BLI_rw_mutex_unlock(&re->resultmutex);
|
|
|
|
|
|
|
|
|
|
if(re->result==NULL)
|
|
|
|
|
return 1;
|
|
|
|
|
|
2011-10-22 17:01:54 +00:00
|
|
|
/* render */
|
|
|
|
|
engine = RE_engine_create(type);
|
|
|
|
|
engine->re= re;
|
|
|
|
|
|
|
|
|
|
if((re->r.scemode & (R_NO_FRAME_UPDATE|R_PREVIEWBUTS))==0)
|
|
|
|
|
scene_update_for_newframe(re->main, re->scene, re->lay);
|
|
|
|
|
|
|
|
|
|
type->render(engine, re->scene);
|
|
|
|
|
|
2011-10-22 16:24:28 +00:00
|
|
|
|
2011-10-22 17:01:54 +00:00
|
|
|
free_render_result(&engine->fullresult, engine->fullresult.first);
|
2011-10-22 16:24:28 +00:00
|
|
|
|
2011-10-22 17:01:54 +00:00
|
|
|
RE_engine_free(engine);
|
2011-10-22 16:24:28 +00:00
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|