/* applies to render pipeline */ static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { /* image assigned to output */ /* stack order input sockets: col, alpha, z */ if(node->flag & NODE_DO_OUTPUT) { /* only one works on out */ Scene *scene= (Scene *)node->id; RenderData *rd= data; if(scene && (rd->scemode & R_DOCOMP)) { Render *re= RE_GetRender(scene->id.name); RenderResult *rr= RE_AcquireResultWrite(re); if(rr) { CompBuf *outbuf, *zbuf=NULL; if(rr->rectf) MEM_freeN(rr->rectf); outbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 1); if(in[1]->data==NULL) composit1_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA); else composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); if(in[2]->data) { if(rr->rectz) MEM_freeN(rr->rectz); zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1); composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL); rr->rectz= zbuf->rect; zbuf->malloc= 0; free_compbuf(zbuf); } generate_preview(data, node, outbuf); /* we give outbuf to rr... */ rr->rectf= outbuf->rect; outbuf->malloc= 0; free_compbuf(outbuf); RE_ReleaseResult(re); /* signal for imageviewer to refresh (it converts to byte rects...) */ BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); return; } else RE_ReleaseResult(re); } } if(in[0]->data) generate_preview(data, node, in[0]->data); }
void RenderLayersBaseProg::initExecution() { Scene *scene = this->getScene(); Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL; RenderResult *rr = NULL; if (re) rr = RE_AcquireResultRead(re); if (rr) { SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, getLayerId()); if (srl) { RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); if (rl && rl->rectf) { this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass); if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) { this->m_inputBuffer = rl->rectf; } } } } if (re) { RE_ReleaseResult(re); re = NULL; } }
static void screen_opengl_render_apply(OGLRender *oglrender) { RenderResult *rr; RenderView *rv; int view_id; ImBuf *ibuf; void *lock; rr = RE_AcquireResultRead(oglrender->re); for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) { RE_SetActiveRenderView(oglrender->re, rv->name); oglrender->view_id = view_id; screen_opengl_render_doit(oglrender, rr); } RE_ReleaseResult(oglrender->re); ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); if (oglrender->write_still) { screen_opengl_render_write(oglrender); } }
void RenderLayersProg::initExecution() { Scene *scene = this->getScene(); Render *re = (scene) ? RE_GetSceneRender(scene) : NULL; RenderResult *rr = NULL; if (re) { rr = RE_AcquireResultRead(re); } if (rr) { ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId()); if (view_layer) { RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); if (rl) { this->m_inputBuffer = RE_RenderLayerGetPass( rl, this->m_passName.c_str(), this->m_viewName); } } } if (re) { RE_ReleaseResult(re); re = NULL; } }
void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { Scene *sce = this->getScene(); Render *re = (sce) ? RE_GetSceneRender(sce) : NULL; RenderResult *rr = NULL; resolution[0] = 0; resolution[1] = 0; if (re) { rr = RE_AcquireResultRead(re); } if (rr) { ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&sce->view_layers, getLayerId()); if (view_layer) { RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name); if (rl) { resolution[0] = rl->rectx; resolution[1] = rl->recty; } } } if (re) { RE_ReleaseResult(re); } }
void CompositorOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { int width = this->m_rd->xsch * this->m_rd->size / 100; int height = this->m_rd->ysch * this->m_rd->size / 100; // check actual render resolution with cropping it may differ with cropped border.rendering // FIX for: [31777] Border Crop gives black (easy) Render *re = RE_GetRender(this->m_sceneName); if (re) { RenderResult *rr = RE_AcquireResultRead(re); if (rr) { width = rr->rectx; height = rr->recty; } RE_ReleaseResult(re); } preferredResolution[0] = width; preferredResolution[1] = height; NodeOperation::determineResolution(resolution, preferredResolution); resolution[0] = width; resolution[1] = height; }
void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { Scene *sce = this->getScene(); Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL; RenderResult *rr = NULL; resolution[0] = 0; resolution[1] = 0; if (re) rr = RE_AcquireResultRead(re); if (rr) { SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId()); if (srl) { RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); if (rl && rl->rectf) { resolution[0] = rl->rectx; resolution[1] = rl->recty; } } } if (re) RE_ReleaseResult(re); }
static void screen_opengl_render_apply(OGLRender *oglrender) { RenderResult *rr; RenderView *rv; int view_id; ImBuf *ibuf; void *lock; if (oglrender->is_sequencer) { Scene *scene = oglrender->scene; SeqRenderData context; SpaceSeq *sseq = oglrender->sseq; int chanshown = sseq ? sseq->chanshown : 0; BKE_sequencer_new_render_data( oglrender->bmain->eval_ctx, oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f, &context); for (view_id = 0; view_id < oglrender->views_len; view_id++) { context.view_id = view_id; context.gpu_offscreen = oglrender->ofs; context.gpu_fx = oglrender->fx; context.gpu_full_samples = oglrender->ofs_full_samples; oglrender->seq_data.ibufs_arr[view_id] = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); } } rr = RE_AcquireResultRead(oglrender->re); for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) { BLI_assert(view_id < oglrender->views_len); RE_SetActiveRenderView(oglrender->re, rv->name); oglrender->view_id = view_id; /* add grease pencil passes. For sequencer, the render does not include renderpasses * TODO: The sequencer render of grease pencil should be rethought */ if (!oglrender->is_sequencer) { add_gpencil_renderpass(oglrender, rr, rv); } /* render composite */ screen_opengl_render_doit(oglrender, rr); } RE_ReleaseResult(oglrender->re); ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); if (oglrender->write_still) { screen_opengl_render_write(oglrender); } }
/* Renders texture directly to render buffer. */ static void shader_preview_texture(ShaderPreview *sp, Tex *tex, Scene *sce, Render *re) { /* Setup output buffer. */ int width = sp->sizex; int height = sp->sizey; /* This is needed otherwise no RenderResult is created. */ sce->r.scemode &= ~R_BUTS_PREVIEW; RE_InitState(re, NULL, &sce->r, &sce->view_layers, NULL, width, height, NULL); RE_SetScene(re, sce); /* Create buffer in empty RenderView created in the init step. */ RenderResult *rr = RE_AcquireResultWrite(re); RenderView *rv = (RenderView *)rr->views.first; rv->rectf = MEM_callocN(sizeof(float) * 4 * width * height, "texture render result"); RE_ReleaseResult(re); /* Get texture image pool (if any) */ struct ImagePool *img_pool = BKE_image_pool_new(); BKE_texture_fetch_images_for_pool(tex, img_pool); /* Fill in image buffer. */ float *rect_float = rv->rectf; float tex_coord[3] = {0.0f, 0.0f, 0.0f}; bool color_manage = true; for (int y = 0; y < height; y++) { /* Tex coords between -1.0f and 1.0f. */ tex_coord[1] = ((float)y / (float)height) * 2.0f - 1.0f; for (int x = 0; x < width; x++) { tex_coord[0] = ((float)x / (float)height) * 2.0f - 1.0f; /* Evaluate texture at tex_coord .*/ TexResult texres = {0}; BKE_texture_get_value_ex(sce, tex, tex_coord, &texres, img_pool, color_manage); rect_float[0] = texres.tr; rect_float[1] = texres.tg; rect_float[2] = texres.tb; rect_float[3] = 1.0f; rect_float += 4; } /* Check if we should cancel texture preview. */ if (shader_preview_break(sp)) { break; } } BKE_image_pool_free(img_pool); }
/* 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; // sa->spacedata might be empty when toggling fullscreen mode. if (sima != NULL && 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); } }
void RE_engine_set_error_message(RenderEngine *engine, const char *msg) { Render *re = engine->re; if (re != NULL) { RenderResult *rr = RE_AcquireResultRead(re); if (rr->error != NULL) { MEM_freeN(rr->error); } rr->error = BLI_strdup(msg); RE_ReleaseResult(re); } }
void CompositorOperation::deinitExecution() { if (!this->m_active) return; if (!isBreaked()) { Render *re = RE_GetRender(this->m_sceneName); RenderResult *rr = RE_AcquireResultWrite(re); if (rr) { if (rr->rectf != NULL) { MEM_freeN(rr->rectf); } rr->rectf = this->m_outputBuffer; if (rr->rectz != NULL) { MEM_freeN(rr->rectz); } rr->rectz = this->m_depthBuffer; } else { if (this->m_outputBuffer) { MEM_freeN(this->m_outputBuffer); } if (this->m_depthBuffer) { MEM_freeN(this->m_depthBuffer); } } if (re) { RE_ReleaseResult(re); re = NULL; } BLI_lock_thread(LOCK_DRAW_IMAGE); BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); BLI_unlock_thread(LOCK_DRAW_IMAGE); } else { if (this->m_outputBuffer) { MEM_freeN(this->m_outputBuffer); } if (this->m_depthBuffer) { MEM_freeN(this->m_depthBuffer); } } this->m_outputBuffer = NULL; this->m_depthBuffer = NULL; this->m_imageInput = NULL; this->m_alphaInput = NULL; this->m_depthInput = NULL; }
void RenderLayersNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const { Scene *scene = (Scene *)this->getbNode()->id; Render *re = (scene) ? RE_GetSceneRender(scene) : NULL; if (re != NULL) { testRenderLink(converter, context, re); RE_ReleaseResult(re); } else { missingRenderLink(converter); } }
void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser) { Scene *scene = CTX_data_scene(C); Render *re; RenderResult *rr; /* render layers and passes */ if (ima && iuser) { const float dpi_fac = UI_DPI_FAC; re = RE_GetRender(scene->id.name); rr = RE_AcquireResultRead(re); uiblock_layer_pass_buttons(layout, rr, iuser, 160 * dpi_fac, (ima->type == IMA_TYPE_R_RESULT) ? &ima->render_slot : NULL); RE_ReleaseResult(re); } }
static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { Scene *sce= (Scene *)node->id; Render *re= (sce)? RE_GetRender(sce->id.name): NULL; RenderData *rd= data; RenderResult *rr= NULL; if(re) rr= RE_AcquireResultRead(re); if(rr) { SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); if(srl) { RenderLayer *rl= RE_GetRenderLayer(rr, srl->name); if(rl && rl->rectf) { CompBuf *stackbuf; /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */ if(rd->scemode & R_COMP_CROP) stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA); else { stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0); stackbuf->rect= rl->rectf; } if(stackbuf==NULL) { printf("Error; Preview Panel in UV Window returns zero sized image\n"); } else { stackbuf->xof= rr->xof; stackbuf->yof= rr->yof; /* put on stack */ out[RRES_OUT_IMAGE]->data= stackbuf; if(out[RRES_OUT_ALPHA]->hasoutput) out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty); generate_preview(data, node, stackbuf); } } } } if(re) RE_ReleaseResult(re); }
static void image_renderinfo_cb(void *rjv, RenderStats *rs) { RenderJob *rj = rjv; RenderResult *rr; rr = RE_AcquireResultRead(rj->re); if (rr) { /* malloc OK here, stats_draw is not in tile threads */ if (rr->text == NULL) rr->text = MEM_callocN(IMA_MAX_RENDER_TEXT, "rendertext"); make_renderinfo_string(rs, rj->scene, rr->text); } RE_ReleaseResult(rj->re); /* make jobs timer to send notifier */ *(rj->do_update) = TRUE; }
static void screen_opengl_render_apply(OGLRender *oglrender) { Scene *scene = oglrender->scene; ARegion *ar = oglrender->ar; View3D *v3d = oglrender->v3d; RegionView3D *rv3d = oglrender->rv3d; RenderResult *rr; Object *camera = NULL; ImBuf *ibuf; void *lock; float winmat[4][4]; int sizex = oglrender->sizex; int sizey = oglrender->sizey; const short view_context = (v3d != NULL); bool draw_bgpic = true; bool draw_sky = (scene->r.alphamode == R_ADDSKY); unsigned char *rect = NULL; rr = RE_AcquireResultRead(oglrender->re); if (oglrender->is_sequencer) { SeqRenderData context; int chanshown = oglrender->sseq ? oglrender->sseq->chanshown : 0; context = BKE_sequencer_new_render_data(oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f); ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown); if (ibuf) { ImBuf *linear_ibuf; BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); linear_ibuf = IMB_dupImBuf(ibuf); IMB_freeImBuf(ibuf); if (linear_ibuf->rect_float == NULL) { /* internally sequencer working in display space and stores both bytes and float buffers in that space. * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear */ IMB_float_from_rect(linear_ibuf); } else { /* ensure float buffer is in linear space, not in display space */ BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); } } else if (view_context) { ED_view3d_draw_offscreen_init(scene, v3d); GPU_offscreen_bind(oglrender->ofs); /* bind */ /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { /*int is_ortho = scene->r.mode & R_ORTHO;*/ camera = v3d->camera; RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); } else { rctf viewplane; float clipsta, clipend; int is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL); if (is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend); else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); if ((scene->r.mode & R_OSA) == 0) { ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); } else { /* simple accumulation, less hassle then FSAA FBO's */ static float jit_ofs[32][2]; float winmat_jitter[4][4]; int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1"); int i, j; BLI_jitter_init(jit_ofs[0], scene->r.osa); /* first sample buffer, also initializes 'rv3d->persmat' */ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) accum_buffer[i] = rect[i]; /* skip the first sample */ for (j = 1; j < scene->r.osa; j++) { copy_m4_m4(winmat_jitter, winmat); window_translate_m4(winmat_jitter, rv3d->persmat, (jit_ofs[j][0] * 2.0f) / sizex, (jit_ofs[j][1] * 2.0f) / sizey); ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); for (i = 0; i < sizex * sizey * 4; i++) accum_buffer[i] += rect[i]; } for (i = 0; i < sizex * sizey * 4; i++) rect[i] = accum_buffer[i] / scene->r.osa; MEM_freeN(accum_buffer); } GPU_offscreen_unbind(oglrender->ofs); /* unbind */ } else { /* shouldnt suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rect, OB_SOLID, FALSE, TRUE, (draw_sky) ? R_ADDSKY: R_ALPHAPREMUL, err_out); camera = scene->camera; if (ibuf_view) { /* steal rect reference from ibuf */ rect = (unsigned char *)ibuf_view->rect; ibuf_view->mall &= ~IB_rect; IMB_freeImBuf(ibuf_view); } else { fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out); } } /* note on color management: * * OpenGL renders into sRGB colors, but render buffers are expected to be * linear So we convert to linear here, so the conversion back to bytes can make it * sRGB (or other display space) again, and so that e.g. openexr saving also saves the * correct linear float buffer. */ if (rect) { int profile_to; if (BKE_scene_check_color_management_enabled(scene)) profile_to = IB_PROFILE_LINEAR_RGB; else profile_to = IB_PROFILE_SRGB; /* sequencer has got trickier conversion happened above * also assume opengl's space matches byte buffer color space */ IMB_buffer_float_from_byte(rr->rectf, rect, profile_to, IB_PROFILE_SRGB, true, oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } /* rr->rectf is now filled with image data */ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) BKE_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4); RE_ReleaseResult(oglrender->re); /* update byte from float buffer */ ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { /* update display buffer */ if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); IMB_partial_display_buffer_update(ibuf, rr->rectf, rect, rr->rectx, 0, 0, &scene->view_settings, &scene->display_settings, 0, 0, rr->rectx, rr->recty, true); /* write file for animation */ if (oglrender->write_still) { char name[FILE_MAX]; int ok; if (scene->r.im_format.planes == R_IMF_CHAN_DEPTH_8) { IMB_color_to_bw(ibuf); } BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, FALSE); ok = BKE_imbuf_write_as(ibuf, name, &scene->r.im_format, TRUE); /* no need to stamp here */ if (ok) printf("OpenGL Render written to '%s'\n", name); else printf("OpenGL Render failed to write '%s'\n", name); } } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); if (rect) MEM_freeN(rect); }
static int screen_opengl_render_init(bContext *C, wmOperator *op) { /* new render clears all callbacks */ wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); ScrArea *prevsa = CTX_wm_area(C); ARegion *prevar = CTX_wm_region(C); RenderResult *rr; GPUOffScreen *ofs; OGLRender *oglrender; int sizex, sizey; short is_view_context = RNA_boolean_get(op->ptr, "view_context"); const short is_animation = RNA_boolean_get(op->ptr, "animation"); const short is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const short is_write_still = RNA_boolean_get(op->ptr, "write_still"); char err_out[256] = "unknown"; if (G.background) { BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)"); return 0; } /* ensure we have a 3d view */ if (!ED_view3d_context_activate(C)) { RNA_boolean_set(op->ptr, "view_context", FALSE); is_view_context = 0; } /* only one render job at a time */ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) return 0; if (!is_view_context && scene->camera == NULL) { BKE_report(op->reports, RPT_ERROR, "Scene has no camera"); return 0; } if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); return 0; } /* stop all running jobs, except screen one. currently previews frustrate Render */ WM_jobs_kill_all_except(wm, CTX_wm_screen(C)); /* create offscreen buffer */ sizex = (scene->r.size * scene->r.xsch) / 100; sizey = (scene->r.size * scene->r.ysch) / 100; /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ ofs = GPU_offscreen_create(sizex, sizey, err_out); if (!ofs) { BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); return 0; } /* allocate opengl render */ oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender"); op->customdata = oglrender; oglrender->ofs = ofs; oglrender->sizex = sizex; oglrender->sizey = sizey; oglrender->bmain = CTX_data_main(C); oglrender->scene = scene; oglrender->cfrao = scene->r.cfra; oglrender->write_still = is_write_still && !is_animation; oglrender->is_sequencer = is_sequencer; if (is_sequencer) { oglrender->sseq = CTX_wm_space_seq(C); } oglrender->obcenter_dia_back = U.obcenter_dia; U.obcenter_dia = 0; oglrender->prevsa = prevsa; oglrender->prevar = prevar; if (is_view_context) { ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->ar); /* so quad view renders camera */ oglrender->rv3d = oglrender->ar->regiondata; /* MUST be cleared on exit */ oglrender->scene->customdata_mask_modal = ED_view3d_datamask(oglrender->scene, oglrender->v3d); /* apply immediately in case we're rendering from a script, * running notifiers again will overwrite */ oglrender->scene->customdata_mask |= oglrender->scene->customdata_mask_modal; } /* create render */ oglrender->re = RE_NewRender(scene->id.name); /* create image and image user */ oglrender->ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); BKE_image_signal(oglrender->ima, NULL, IMA_SIGNAL_FREE); BKE_image_backup_render(oglrender->scene, oglrender->ima); oglrender->iuser.scene = scene; oglrender->iuser.ok = 1; /* create render result */ RE_InitState(oglrender->re, NULL, &scene->r, NULL, sizex, sizey, NULL); rr = RE_AcquireResultWrite(oglrender->re); if (rr->rectf == NULL) rr->rectf = MEM_callocN(sizeof(float) * 4 * sizex * sizey, "screen_opengl_render_init rect"); RE_ReleaseResult(oglrender->re); /* wm vars */ oglrender->wm = wm; oglrender->win = win; return 1; }
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; Scene *scene = oglrender->scene; char name[FILE_MAX]; bool ok = false; const bool view_context = (oglrender->v3d != NULL); bool is_movie; RenderResult *rr; /* go to next frame */ if (CFRA < oglrender->nfra) CFRA++; while (CFRA < oglrender->nfra) { unsigned int lay = screen_opengl_layers(oglrender); if (lay & 0xFF000000) lay &= 0xFF000000; BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, lay); CFRA++; } is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); if (!is_movie) { BKE_image_path_from_imformat( name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) { BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name); ok = true; goto finally; } } WM_cursor_time(oglrender->win, scene->r.cfra); BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, screen_opengl_layers(oglrender)); if (view_context) { if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) { /* since BKE_scene_update_for_newframe() is used rather * then ED_update_for_newframe() the camera needs to be set */ if (BKE_scene_camera_switch_update(scene)) { oglrender->v3d->camera = scene->camera; } } } else { BKE_scene_camera_switch_update(scene); } /* render into offscreen buffer */ screen_opengl_render_apply(oglrender); /* save to disk */ rr = RE_AcquireResultRead(oglrender->re); if (is_movie) { ok = RE_WriteRenderViewsMovie(oglrender->reports, rr, scene, &scene->r, oglrender->mh, oglrender->sizex, oglrender->sizey, oglrender->movie_ctx_arr, oglrender->totvideos, PRVRANGEON != 0); if (ok) { printf("Append frame %d", scene->r.cfra); BKE_reportf(op->reports, RPT_INFO, "Appended frame: %d", scene->r.cfra); } } else { ok = RE_WriteRenderViewsImage(op->reports, rr, scene, scene->camera, true, name); if (ok) { printf("Saved: %s", name); BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); } else { printf("Write error: cannot save %s\n", name); BKE_reportf(op->reports, RPT_ERROR, "Write error: cannot save %s", name); } } RE_ReleaseResult(oglrender->re); /* movie stats prints have no line break */ printf("\n"); finally: /* Step the frame and bail early if needed */ /* go to next frame */ oglrender->nfra += scene->r.frame_step; /* stop at the end or on error */ if (CFRA >= PEFRA || !ok) { screen_opengl_render_end(C, op->customdata); return 0; } return 1; }
void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact) { PropertyRNA *prop; PointerRNA imaptr; RNAUpdateCb *cb; Image *ima; ImageUser *iuser; ImBuf *ibuf; Scene *scene = CTX_data_scene(C); uiLayout *row, *split, *col; uiBlock *block; uiBut *but; char str[128]; void *lock; if (!ptr->data) return; prop = RNA_struct_find_property(ptr, propname); if (!prop) { printf("%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); return; } if (RNA_property_type(prop) != PROP_POINTER) { printf("%s: expected pointer property for %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); return; } block = uiLayoutGetBlock(layout); imaptr = RNA_property_pointer_get(ptr, prop); ima = imaptr.data; iuser = userptr->data; cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); cb->ptr = *ptr; cb->prop = prop; cb->iuser = iuser; uiLayoutSetContextPointer(layout, "edit_image", &imaptr); if (!compact) uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL); if (ima) { uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL); if (ima->source == IMA_SRC_VIEWER) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); BKE_image_release_ibuf(ima, lock); uiItemL(layout, ima->id.name + 2, ICON_NONE); uiItemL(layout, str, ICON_NONE); if (ima->type == IMA_TYPE_COMPOSITE) { // XXX not working yet #if 0 iuser = ntree_get_active_iuser(scene->nodetree); if (iuser) { uiBlockBeginAlign(block); uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, ""); uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play", 110, 120, 100, 20, 0, 0, 0, 0, 0, ""); but = uiDefBut(block, BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, ""); uiButSetFunc(but, image_freecache_cb, ima, NULL); if (iuser->frames) BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr); else strcpy(str, "Frames:"); uiBlockBeginAlign(block); uiDefButI(block, NUM, imagechanged, str, 10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use"); uiDefButI(block, NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie"); } #endif } else if (ima->type == IMA_TYPE_R_RESULT) { /* browse layer/passes */ Render *re = RE_GetRender(scene->id.name); RenderResult *rr = RE_AcquireResultRead(re); uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot); RE_ReleaseResult(re); } } else { uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE); if (ima->source != IMA_SRC_GENERATED) { row = uiLayoutRow(layout, 1); if (ima->packedfile) uiItemO(row, "", ICON_PACKAGE, "image.unpack"); else uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); row = uiLayoutRow(row, 0); uiLayoutSetEnabled(row, ima->packedfile == NULL); uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); } // XXX what was this for? #if 0 /* check for re-render, only buttons */ if (imagechanged == B_IMAGECHANGED) { if (iuser->flag & IMA_ANIM_REFRESHED) { iuser->flag &= ~IMA_ANIM_REFRESHED; WM_event_add_notifier(C, NC_IMAGE, ima); } } #endif /* multilayer? */ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL); } else if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); BKE_image_release_ibuf(ima, lock); uiItemL(layout, str, ICON_NONE); } } if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { /* background image view doesnt need these */ uiItemS(layout); split = uiLayoutSplit(layout, 0, 0); col = uiLayoutColumn(split, 0); uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE); row = uiLayoutRow(col, 0); uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields")); uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(layout, 0); uiItemR(row, &imaptr, "use_premultiply", 0, NULL, ICON_NONE); uiItemR(row, &imaptr, "use_color_unpremultiply", 0, NULL, ICON_NONE); } } if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { uiItemS(layout); split = uiLayoutSplit(layout, 0, 0); col = uiLayoutColumn(split, 0); BLI_snprintf(str, sizeof(str), "(%d) Frames", iuser->framenr); uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE); if (ima->anim) { block = uiLayoutGetBlock(col); but = uiDefBut(block, BUT, 0, "Match Movie Length", 0, 0, UI_UNIT_X * 2, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Set the number of frames to match the movie or sequence"); uiButSetFunc(but, set_frames_cb, ima, iuser); } uiItemR(col, userptr, "frame_start", 0, "Start", ICON_NONE); uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, 0); row = uiLayoutRow(col, 0); uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields")); uiItemR(row, userptr, "fields_per_frame", 0, "Fields", ICON_NONE); uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE); uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE); } else if (ima->source == IMA_SRC_GENERATED) { split = uiLayoutSplit(layout, 0, 0); col = uiLayoutColumn(split, 1); uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); } } uiBlockSetNFunc(block, NULL, NULL, NULL); } MEM_freeN(cb); }
static void screen_opengl_views_setup(OGLRender *oglrender) { RenderResult *rr; RenderView *rv; SceneRenderView *srv; bool is_multiview; View3D *v3d = oglrender->v3d; RenderData *rd = &oglrender->scene->r; rr = RE_AcquireResultWrite(oglrender->re); is_multiview = screen_opengl_is_multiview(oglrender); if (!is_multiview) { /* we only have one view when multiview is off */ rv = rr->views.first; if (rv == NULL) { rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); BLI_addtail(&rr->views, rv); } while (rv->next) { RenderView *rv_del = rv->next; BLI_remlink(&rr->views, rv_del); if (rv_del->rectf) MEM_freeN(rv_del->rectf); if (rv_del->rectz) MEM_freeN(rv_del->rectz); MEM_freeN(rv_del); } } else { if (!oglrender->is_sequencer) RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d)); /* remove all the views that are not needed */ rv = rr->views.last; while (rv) { srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name)); if (BKE_scene_multiview_is_render_view_active(rd, srv)) { if (rv->rectf == NULL) rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect"); rv = rv->prev; } else { RenderView *rv_del = rv; rv = rv_del->prev; BLI_remlink(&rr->views, rv_del); if (rv_del->rectf) MEM_freeN(rv_del->rectf); if (rv_del->rectz) MEM_freeN(rv_del->rectz); MEM_freeN(rv_del); } } /* create all the views that are needed */ for (srv = rd->views.first; srv; srv = srv->next) { if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) continue; rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name)); if (rv == NULL) { rv = MEM_callocN(sizeof(RenderView), "new opengl render view"); BLI_strncpy(rv->name, srv->name, sizeof(rv->name)); BLI_addtail(&rr->views, rv); } } } for (rv = rr->views.first; rv; rv = rv->next) { if (rv->rectf == NULL) { rv->rectf = MEM_callocN(sizeof(float) * 4 * oglrender->sizex * oglrender->sizey, "screen_opengl_render_init rect"); } } BLI_lock_thread(LOCK_DRAW_IMAGE); if (is_multiview && BKE_scene_multiview_is_stereo3d(rd)) { oglrender->ima->flag |= IMA_IS_STEREO; } else { oglrender->ima->flag &= ~IMA_IS_STEREO; oglrender->iuser.flag &= ~IMA_SHOW_STEREO; } BLI_unlock_thread(LOCK_DRAW_IMAGE); RE_ReleaseResult(oglrender->re); }