static void wm_draw_region_buffer_create(ARegion *ar, bool stereo, bool use_viewport) { if (ar->draw_buffer) { if (ar->draw_buffer->stereo != stereo) { /* Free draw buffer on stereo changes. */ wm_draw_region_buffer_free(ar); } else { /* Free offscreen buffer on size changes. Viewport auto resizes. */ GPUOffScreen *offscreen = ar->draw_buffer->offscreen[0]; if (offscreen && (GPU_offscreen_width(offscreen) != ar->winx || GPU_offscreen_height(offscreen) != ar->winy)) { wm_draw_region_buffer_free(ar); } } } if (!ar->draw_buffer) { if (use_viewport) { /* Allocate viewport which includes an offscreen buffer with depth * multisample, etc. */ ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); ar->draw_buffer->viewport[0] = GPU_viewport_create(); ar->draw_buffer->viewport[1] = (stereo) ? GPU_viewport_create() : NULL; } else { /* Allocate offscreen buffer if it does not exist. This one has no * depth or multisample buffers. 3D view creates own buffers with * the data it needs. */ GPUOffScreen *offscreen = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); if (!offscreen) { return; } wm_draw_offscreen_texture_parameters(offscreen); GPUOffScreen *offscreen_right = NULL; if (stereo) { offscreen_right = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL); if (!offscreen_right) { GPU_offscreen_free(offscreen); return; } wm_draw_offscreen_texture_parameters(offscreen_right); } ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer"); ar->draw_buffer->offscreen[0] = offscreen; ar->draw_buffer->offscreen[1] = offscreen_right; } ar->draw_buffer->bound_view = -1; ar->draw_buffer->stereo = stereo; } }
static PyObject *bpygpu_offscreen_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds) { BPYGPU_IS_INIT_OR_ERROR_OBJ; GPUOffScreen *ofs; int width, height, samples = 0; char err_out[256]; static const char *_keywords[] = {"width", "height", "samples", NULL}; static _PyArg_Parser _parser = {"ii|i:GPUOffScreen.__new__", _keywords, 0}; if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &width, &height, &samples)) { return NULL; } ofs = GPU_offscreen_create(width, height, samples, true, false, err_out); if (ofs == NULL) { PyErr_Format(PyExc_RuntimeError, "gpu.offscreen.new(...) failed with '%s'", err_out[0] ? err_out : "unknown error"); return NULL; } return BPyGPUOffScreen_CreatePyObject(ofs); }
static PyObject *pygpu_offscreen_new(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"width", "height", "samples", NULL}; GPUOffScreen *ofs; int width, height, samples = 0; char err_out[256]; if (!PyArg_ParseTupleAndKeywords( args, kwds, "ii|i:new", (char **)(kwlist), &width, &height, &samples)) { return NULL; } ofs = GPU_offscreen_create(width, height, samples, err_out); if (ofs == NULL) { PyErr_Format(PyExc_RuntimeError, "gpu.offscreen.new(...) failed with '%s'", err_out[0] ? err_out : "unknown error"); return NULL; } return BPy_GPU_OffScreen_CreatePyObject(ofs); }
/* Transform buffer from role to scene linear space using GLSL OCIO conversion * * See IMB_colormanagement_setup_transform_from_role_glsl description for * some more details * * NOTE: this only works for RGBA buffers! */ int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role) { GPUOffScreen *ofs; char err_out[256]; rcti display_rect; ofs = GPU_offscreen_create(width, height, err_out); if (!ofs) return FALSE; GPU_offscreen_bind(ofs); if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) { GPU_offscreen_unbind(ofs); GPU_offscreen_free(ofs); return FALSE; } BLI_rcti_init(&display_rect, 0, width, 0, height); glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glaDefine2DArea(&display_rect); glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT, GL_NEAREST, buffer); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); GPU_offscreen_read_pixels(ofs, GL_FLOAT, buffer); IMB_colormanagement_finish_glsl_transform(); /* unbind */ GPU_offscreen_unbind(ofs); GPU_offscreen_free(ofs); return TRUE; }
static bool 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); GPUOffScreen *ofs; OGLRender *oglrender; int sizex, sizey; bool is_view_context = RNA_boolean_get(op->ptr, "view_context"); const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const bool 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 false; } /* only one render job at a time */ if (WM_jobs_test(wm, scene, WM_JOB_TYPE_RENDER)) return false; if (is_sequencer) { is_view_context = false; } else { /* ensure we have a 3d view */ if (!ED_view3d_context_activate(C)) { RNA_boolean_set(op->ptr, "view_context", false); is_view_context = false; } if (!is_view_context && scene->camera == NULL) { BKE_report(op->reports, RPT_ERROR, "Scene has no camera"); return false; } } 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 false; } /* 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 false; } /* 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->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; if (oglrender->v3d->fx_settings.fx_flag & (GPU_FX_FLAG_DOF | GPU_FX_FLAG_SSAO)) { oglrender->fx = GPU_fx_compositor_create(); } } /* 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); /* create render views */ screen_opengl_views_setup(oglrender); /* wm vars */ oglrender->wm = wm; oglrender->win = win; oglrender->totvideos = 0; oglrender->mh = NULL; oglrender->movie_ctx_arr = NULL; return true; }