Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/render/render_internal.c')
-rw-r--r--source/blender/editors/render/render_internal.c190
1 files changed, 160 insertions, 30 deletions
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 1b090cb16ec..7ecada993e2 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -94,11 +94,17 @@
static int render_break(void *rjv);
/* called inside thread! */
-void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect)
+static void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, ImageUser *iuser, volatile rcti *renrect)
{
float *rectf = NULL;
int ymin, ymax, xmin, xmax;
int rymin, rxmin;
+ int linear_stride, linear_offset_x, linear_offset_y;
+
+ if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) {
+ /* The whole image buffer it so be color managed again anyway. */
+ return;
+ }
/* if renrect argument, we only refresh scanlines */
if (renrect) {
@@ -138,33 +144,55 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
if (xmax < 1 || ymax < 1) return;
- /* find current float rect for display, first case is after composite... still weak */
- if (rr->rectf)
- rectf = rr->rectf;
- else {
- if (rr->rect32) {
- /* special case, currently only happens with sequencer rendering,
- * which updates the whole frame, so we can only mark display buffer
- * as invalid here (sergey)
- */
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
- return;
- }
+ /* The thing here is, the logic below (which was default behavior
+ * of how rectf is acquiring since forever) gives float buffer for
+ * composite output only. This buffer can not be used for other
+ * passes obviously.
+ *
+ * We might try finding corresponding for pass buffer in render result
+ * (which is actually missing when rendering with Cycles, who only
+ * writes all the passes when the tile is finished) or use float
+ * buffer from image buffer as reference, which is easier to use and
+ * contains all the data we need anyway.
+ * - sergey -
+ */
+ /* TODO(sergey): Need to check has_combined here? */
+ if (iuser->pass == 0) {
+ /* find current float rect for display, first case is after composite... still weak */
+ if (rr->rectf)
+ rectf = rr->rectf;
else {
- if (rr->renlay == NULL || rr->renlay->rectf == NULL) return;
- rectf = rr->renlay->rectf;
+ if (rr->rect32) {
+ /* special case, currently only happens with sequencer rendering,
+ * which updates the whole frame, so we can only mark display buffer
+ * as invalid here (sergey)
+ */
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ return;
+ }
+ else {
+ if (rr->renlay == NULL || rr->renlay->rectf == NULL) return;
+ rectf = rr->renlay->rectf;
+ }
}
- }
- if (rectf == NULL) return;
+ if (rectf == NULL) return;
- if (ibuf->rect == NULL)
- imb_addrectImBuf(ibuf);
-
- rectf += 4 * (rr->rectx * ymin + xmin);
+ rectf += 4 * (rr->rectx * ymin + xmin);
+ linear_stride = rr->rectx;
+ linear_offset_x = rxmin;
+ linear_offset_y = rymin;
+ }
+ else {
+ rectf = ibuf->rect_float;
+ linear_stride = ibuf->x;
+ linear_offset_x = 0;
+ linear_offset_y = 0;
+ }
- IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
+ IMB_partial_display_buffer_update(ibuf, rectf, NULL,
+ linear_stride, linear_offset_x, linear_offset_y,
&scene->view_settings, &scene->display_settings,
- rxmin, rymin, rxmin + xmax, rymin + ymax, true);
+ rxmin, rymin, rxmin + xmax, rymin + ymax, false);
}
/* ****************************** render invoking ***************** */
@@ -262,7 +290,6 @@ typedef struct RenderJob {
Main *main;
Scene *scene;
Render *re;
- wmWindow *win;
SceneRenderLayer *srl;
struct Object *camera_override;
int lay_override;
@@ -275,6 +302,9 @@ typedef struct RenderJob {
short *do_update;
float *progress;
ReportList *reports;
+ int orig_layer;
+ int last_layer;
+ ScrArea *sa;
} RenderJob;
static void render_freejob(void *rjv)
@@ -402,6 +432,64 @@ static void render_progress_update(void *rjv, float progress)
}
}
+/* Not totally reliable, but works fine in most of cases and
+ * in worst case would just make it so extra color management
+ * for the whole render result is applied (which was already
+ * happening already).
+ */
+static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr, ImageUser *iuser)
+{
+ wmWindowManager *wm;
+ ScrArea *first_sa = NULL, *matched_sa = NULL;
+
+ /* image window, compo node users */
+ for (wm = rj->main->wm.first; wm && matched_sa == NULL; wm = wm->id.next) { /* only 1 wm */
+ wmWindow *win;
+ for (win = wm->windows.first; win && matched_sa == NULL; win = win->next) {
+ ScrArea *sa;
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ if (sima->image == rj->image) {
+ if (first_sa == NULL) {
+ first_sa = sa;
+ }
+ if (sa == rj->sa) {
+ matched_sa = sa;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (matched_sa == NULL) {
+ matched_sa = first_sa;
+ }
+
+ if (matched_sa) {
+ SpaceImage *sima = matched_sa->spacedata.first;
+ RenderResult *main_rr = RE_AcquireResultRead(rj->re);
+
+ /* TODO(sergey): is there faster way to get the layer index? */
+ if (rr->renlay) {
+ int layer = BLI_findstringindex(&main_rr->layers,
+ (char *)rr->renlay->name,
+ offsetof(RenderLayer, name));
+ if (layer != rj->last_layer) {
+ sima->iuser.layer = layer;
+ rj->last_layer = layer;
+ }
+ }
+
+ iuser->pass = sima->iuser.pass;
+ iuser->layer = sima->iuser.layer;
+
+ RE_ReleaseResult(rj->re);
+ }
+}
+
static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
{
RenderJob *rj = rjv;
@@ -423,9 +511,17 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
}
/* update part of render */
+ render_image_update_pass_and_layer(rj, rr, &rj->iuser);
ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);
if (ibuf) {
- image_buffer_rect_update(rj->scene, rr, ibuf, renrect);
+ /* Don't waste time on CPU side color management if
+ * image will be displayed using GLSL.
+ */
+ if (ibuf->channels == 1 ||
+ U.image_draw_method != IMAGE_DRAW_METHOD_GLSL)
+ {
+ image_buffer_rect_update(rj->scene, rr, ibuf, &rj->iuser, renrect);
+ }
/* make jobs timer to send notifier */
*(rj->do_update) = TRUE;
@@ -451,6 +547,28 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro
RE_SetReports(rj->re, NULL);
}
+static void render_image_restore_layer(RenderJob *rj)
+{
+ wmWindowManager *wm;
+
+ /* image window, compo node users */
+ for (wm = rj->main->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
+ wmWindow *win;
+ for (win = wm->windows.first; win; win = win->next) {
+ ScrArea *sa;
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ if (sa == rj->sa) {
+ if (sa->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = sa->spacedata.first;
+ sima->iuser.layer = rj->orig_layer;
+ }
+ return;
+ }
+ }
+ }
+ }
+}
+
static void render_endjob(void *rjv)
{
RenderJob *rj = rjv;
@@ -481,6 +599,10 @@ static void render_endjob(void *rjv)
WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
}
+ if (rj->sa) {
+ render_image_restore_layer(rj);
+ }
+
/* XXX render stability hack */
G.is_rendering = FALSE;
WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);
@@ -592,6 +714,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
struct Object *camera_override = v3d ? V3D_CAMERA_LOCAL(v3d) : NULL;
const char *name;
Object *active_object = CTX_data_active_object(C);
+ ScrArea *sa;
/* only one render job at a time */
if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_RENDER))
@@ -644,7 +767,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
// store spare
/* ensure at least 1 area shows result */
- render_view_open(C, event->x, event->y);
+ sa = render_view_open(C, event->x, event->y);
jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
@@ -658,7 +781,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj = MEM_callocN(sizeof(RenderJob), "render job");
rj->main = mainp;
rj->scene = scene;
- rj->win = CTX_wm_window(C);
rj->srl = srl;
rj->camera_override = camera_override;
rj->lay_override = 0;
@@ -667,6 +789,14 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->iuser.scene = scene;
rj->iuser.ok = 1;
rj->reports = op->reports;
+ rj->orig_layer = 0;
+ rj->last_layer = 0;
+ rj->sa = sa;
+
+ if (sa) {
+ SpaceImage *sima = sa->spacedata.first;
+ rj->orig_layer = sima->iuser.layer;
+ }
if (v3d) {
if (scene->lay != v3d->lay) {
@@ -699,7 +829,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
re = RE_NewRender(scene->id.name);
RE_test_break_cb(re, rj, render_breakjob);
RE_draw_lock_cb(re, rj, render_drawlock);
- RE_display_draw_cb(re, rj, image_rect_update);
+ RE_display_update_cb(re, rj, image_rect_update);
RE_stats_draw_cb(re, rj, image_renderinfo_cb);
RE_progress_cb(re, rj, render_progress_update);
@@ -850,7 +980,7 @@ static int render_view3d_break(void *rpv)
return *(rp->stop);
}
-static void render_view3d_draw_update(void *rpv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
+static void render_view3d_display_update(void *rpv, RenderResult *UNUSED(rr), volatile struct rcti *UNUSED(rect))
{
RenderPreview *rp = rpv;
@@ -908,7 +1038,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda
/* set this always, rp is different for each job */
RE_test_break_cb(re, rp, render_view3d_break);
- RE_display_draw_cb(re, rp, render_view3d_draw_update);
+ RE_display_update_cb(re, rp, render_view3d_display_update);
RE_stats_draw_cb(re, rp, render_view3d_renderinfo_cb);
rstats = RE_GetStats(re);