2017-02-07 11:20:15 +01:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
2019-01-23 11:29:18 +11:00
|
|
|
* Copyright 2016, Blender Foundation.
|
2017-02-07 11:20:15 +01:00
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup draw
|
2017-02-07 11:20:15 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2019-05-07 18:42:28 +02:00
|
|
|
#include "BLI_alloca.h"
|
2017-02-07 11:20:15 +01:00
|
|
|
#include "BLI_listbase.h"
|
2019-05-07 18:01:14 +02:00
|
|
|
#include "BLI_memblock.h"
|
2017-02-07 11:20:15 +01:00
|
|
|
#include "BLI_rect.h"
|
|
|
|
#include "BLI_string.h"
|
2018-02-26 19:41:17 +01:00
|
|
|
#include "BLI_threads.h"
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2018-03-30 21:10:24 +02:00
|
|
|
#include "BLF_api.h"
|
|
|
|
|
2019-05-07 18:42:28 +02:00
|
|
|
#include "BKE_anim.h"
|
2018-12-06 12:30:35 +01:00
|
|
|
#include "BKE_colortools.h"
|
2019-02-23 12:58:39 +11:00
|
|
|
#include "BKE_curve.h"
|
2019-05-16 09:26:33 +10:00
|
|
|
#include "BKE_editmesh.h"
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "BKE_global.h"
|
2019-02-23 12:58:39 +11:00
|
|
|
#include "BKE_gpencil.h"
|
|
|
|
#include "BKE_lattice.h"
|
2019-04-19 02:22:22 +02:00
|
|
|
#include "BKE_main.h"
|
2019-02-23 12:58:39 +11:00
|
|
|
#include "BKE_mball.h"
|
|
|
|
#include "BKE_mesh.h"
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "BKE_object.h"
|
2018-05-15 11:35:39 +02:00
|
|
|
#include "BKE_particle.h"
|
2019-05-02 16:51:17 +02:00
|
|
|
#include "BKE_paint.h"
|
2019-05-31 10:20:48 +02:00
|
|
|
#include "BKE_pbvh.h"
|
2018-05-15 11:35:39 +02:00
|
|
|
#include "BKE_pointcache.h"
|
2017-09-15 20:08:31 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "draw_manager.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
2018-07-10 14:14:55 +02:00
|
|
|
#include "DNA_world_types.h"
|
2017-09-11 23:15:29 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "ED_space_api.h"
|
|
|
|
#include "ED_screen.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "ED_gpencil.h"
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "ED_view3d.h"
|
2017-09-15 20:08:31 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "GPU_draw.h"
|
|
|
|
#include "GPU_extensions.h"
|
|
|
|
#include "GPU_framebuffer.h"
|
|
|
|
#include "GPU_immediate.h"
|
|
|
|
#include "GPU_uniformbuffer.h"
|
|
|
|
#include "GPU_viewport.h"
|
|
|
|
#include "GPU_matrix.h"
|
2019-03-28 14:17:00 -03:00
|
|
|
#include "GPU_select.h"
|
2017-09-15 20:08:31 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "IMB_colormanagement.h"
|
2017-09-15 20:08:31 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "RE_engine.h"
|
|
|
|
#include "RE_pipeline.h"
|
2017-09-11 23:15:29 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "UI_resources.h"
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "WM_api.h"
|
|
|
|
#include "wm_window.h"
|
2017-09-15 20:08:31 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "draw_manager_text.h"
|
|
|
|
#include "draw_manager_profiling.h"
|
2017-09-15 20:08:31 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
/* only for callbacks */
|
|
|
|
#include "draw_cache_impl.h"
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "draw_mode_engines.h"
|
|
|
|
#include "engines/eevee/eevee_engine.h"
|
|
|
|
#include "engines/basic/basic_engine.h"
|
2018-04-13 15:49:50 +02:00
|
|
|
#include "engines/workbench/workbench_engine.h"
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "engines/external/external_engine.h"
|
2019-07-05 23:11:53 +02:00
|
|
|
#include "engines/gpencil/gpencil_engine.h"
|
2019-07-30 06:46:59 -03:00
|
|
|
#include "engines/select/select_engine.h"
|
2018-01-09 14:21:55 +01:00
|
|
|
|
2018-07-17 21:11:23 +02:00
|
|
|
#include "GPU_context.h"
|
2017-07-30 02:17:11 +10:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
#include "DEG_depsgraph_query.h"
|
2018-01-09 14:21:55 +01:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
#ifdef USE_GPU_SELECT
|
|
|
|
# include "GPU_select.h"
|
2017-04-26 04:39:25 +10:00
|
|
|
#endif
|
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
/** Render State: No persistent data between draw calls. */
|
|
|
|
DRWManager DST = {NULL};
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2018-07-31 20:44:49 +10:00
|
|
|
static ListBase DRW_engines = {NULL, NULL};
|
2017-06-26 20:42:58 +02:00
|
|
|
|
2018-03-29 11:43:42 +02:00
|
|
|
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
memset(dst, 0x0, offsetof(DRWManager, gl_context));
|
2019-01-17 18:33:08 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Maybe not the best place for this. */
|
|
|
|
if (!DST.uniform_names.buffer) {
|
|
|
|
DST.uniform_names.buffer = MEM_callocN(DRW_UNIFORM_BUFFER_NAME, "Name Buffer");
|
|
|
|
DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
|
|
|
|
}
|
|
|
|
else if (DST.uniform_names.buffer_len > DRW_UNIFORM_BUFFER_NAME) {
|
|
|
|
DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DRW_UNIFORM_BUFFER_NAME);
|
|
|
|
DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
|
|
|
|
}
|
|
|
|
DST.uniform_names.buffer_ofs = 0;
|
2018-03-29 11:43:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This function is used to reset draw manager to a state
|
|
|
|
* where we don't re-use data by accident across different
|
|
|
|
* draw calls.
|
|
|
|
*/
|
2018-03-29 12:40:23 +02:00
|
|
|
#ifdef DEBUG
|
2018-03-29 11:43:42 +02:00
|
|
|
static void drw_state_ensure_not_reused(DRWManager *dst)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
memset(dst, 0xff, offsetof(DRWManager, gl_context));
|
2018-03-29 11:43:42 +02:00
|
|
|
}
|
2018-03-29 12:40:23 +02:00
|
|
|
#endif
|
2018-03-29 11:43:42 +02:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
2017-06-26 20:42:58 +02:00
|
|
|
|
2017-03-05 18:09:43 +01:00
|
|
|
void DRW_draw_callbacks_pre_scene(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
RegionView3D *rv3d = DST.draw_ctx.rv3d;
|
2017-03-05 18:09:43 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_matrix_projection_set(rv3d->winmat);
|
|
|
|
GPU_matrix_set(rv3d->viewmat);
|
2017-03-05 18:09:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_draw_callbacks_post_scene(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
RegionView3D *rv3d = DST.draw_ctx.rv3d;
|
2017-03-05 18:09:43 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_matrix_projection_set(rv3d->winmat);
|
|
|
|
GPU_matrix_set(rv3d->viewmat);
|
2017-03-05 18:09:43 +01:00
|
|
|
}
|
|
|
|
|
2017-04-28 04:33:58 +10:00
|
|
|
struct DRWTextStore *DRW_text_cache_ensure(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(DST.text_store_p);
|
|
|
|
if (*DST.text_store_p == NULL) {
|
|
|
|
*DST.text_store_p = DRW_text_cache_create();
|
|
|
|
}
|
|
|
|
return *DST.text_store_p;
|
2017-04-28 04:33:58 +10:00
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Settings
|
|
|
|
* \{ */
|
2017-03-03 02:48:34 +01:00
|
|
|
|
2018-10-08 10:43:34 +11:00
|
|
|
bool DRW_object_is_renderable(const Object *ob)
|
2017-03-03 02:48:34 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert((ob->base_flag & BASE_VISIBLE) != 0);
|
2017-09-21 12:55:14 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (ob->type == OB_MESH) {
|
|
|
|
if ((ob == DST.draw_ctx.object_edit) || BKE_object_is_in_editmode(ob)) {
|
|
|
|
View3D *v3d = DST.draw_ctx.v3d;
|
|
|
|
const int mask = (V3D_OVERLAY_EDIT_OCCLUDE_WIRE | V3D_OVERLAY_EDIT_WEIGHT);
|
2018-05-03 15:09:09 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (v3d && v3d->overlay.edit_flag & mask) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-02-17 17:29:43 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
return true;
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-12-21 13:29:14 -02:00
|
|
|
/**
|
|
|
|
* Return whether this object is visible depending if
|
|
|
|
* we are rendering or drawing in the viewport.
|
|
|
|
*/
|
2018-12-18 18:18:00 +01:00
|
|
|
int DRW_object_visibility_in_active_context(const Object *ob)
|
2017-12-21 13:29:14 -02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
const eEvaluationMode mode = DRW_state_is_scene_render() ? DAG_EVAL_RENDER : DAG_EVAL_VIEWPORT;
|
|
|
|
return BKE_object_visibility(ob, mode);
|
2017-12-21 13:29:14 -02:00
|
|
|
}
|
|
|
|
|
2017-07-13 00:27:06 +10:00
|
|
|
bool DRW_object_is_flat_normal(const Object *ob)
|
2017-05-18 20:43:53 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (ob->type == OB_MESH) {
|
|
|
|
const Mesh *me = ob->data;
|
|
|
|
if (me->mpoly && me->mpoly[0].flag & ME_SMOOTH) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2017-05-18 20:43:53 +10:00
|
|
|
}
|
|
|
|
|
2018-11-25 18:34:28 +03:00
|
|
|
bool DRW_object_use_hide_faces(const struct Object *ob)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (ob->type == OB_MESH) {
|
|
|
|
const Mesh *me = ob->data;
|
|
|
|
|
|
|
|
switch (ob->mode) {
|
2019-07-10 13:23:47 +02:00
|
|
|
case OB_MODE_SCULPT:
|
|
|
|
return true;
|
2019-04-17 06:17:24 +02:00
|
|
|
case OB_MODE_TEXTURE_PAINT:
|
|
|
|
return (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
|
|
|
|
case OB_MODE_VERTEX_PAINT:
|
|
|
|
case OB_MODE_WEIGHT_PAINT:
|
|
|
|
return (me->editflag & (ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DRW_object_is_visible_psys_in_active_context(const Object *object, const ParticleSystem *psys)
|
|
|
|
{
|
|
|
|
const bool for_render = DRW_state_is_image_render();
|
|
|
|
/* NOTE: psys_check_enabled is using object and particle system for only
|
|
|
|
* reading, but is using some other functions which are more generic and
|
|
|
|
* which are hard to make const-pointer. */
|
|
|
|
if (!psys_check_enabled((Object *)object, (ParticleSystem *)psys, for_render)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
|
|
const Scene *scene = draw_ctx->scene;
|
|
|
|
if (object == draw_ctx->object_edit) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const ParticleSettings *part = psys->part;
|
|
|
|
const ParticleEditSettings *pset = &scene->toolsettings->particle;
|
|
|
|
if (object->mode == OB_MODE_PARTICLE_EDIT) {
|
|
|
|
if (psys_in_edit_mode(draw_ctx->depsgraph, psys)) {
|
|
|
|
if ((pset->flag & PE_DRAW_PART) == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ((part->childtype == 0) &&
|
|
|
|
(psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2018-05-09 16:55:09 +02:00
|
|
|
}
|
|
|
|
|
2018-11-26 15:23:16 +01:00
|
|
|
struct Object *DRW_object_get_dupli_parent(const Object *UNUSED(ob))
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.dupli_parent;
|
2018-11-26 15:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob))
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.dupli_source;
|
2018-11-26 15:23:16 +01:00
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2018-02-28 01:16:23 +01:00
|
|
|
/** \name Color Management
|
2017-04-27 02:04:56 +10:00
|
|
|
* \{ */
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2017-05-11 16:20:10 +02:00
|
|
|
/* Use color management profile to draw texture to framebuffer */
|
2019-02-01 20:30:10 +01:00
|
|
|
void DRW_transform_to_display(GPUTexture *tex, bool use_view_transform, bool use_render_settings)
|
2017-05-11 16:20:10 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_state_set(DRW_STATE_WRITE_COLOR);
|
|
|
|
|
|
|
|
GPUVertFormat *vert_format = immVertexFormat();
|
|
|
|
uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
uint texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
|
|
|
const float dither = 1.0f;
|
|
|
|
|
|
|
|
bool use_ocio = false;
|
|
|
|
|
2019-05-21 12:00:48 +02:00
|
|
|
/* Should we apply the view transform */
|
|
|
|
if (DRW_state_do_color_management()) {
|
2019-04-17 06:17:24 +02:00
|
|
|
Scene *scene = DST.draw_ctx.scene;
|
|
|
|
ColorManagedDisplaySettings *display_settings = &scene->display_settings;
|
|
|
|
ColorManagedViewSettings view_settings;
|
|
|
|
if (use_render_settings) {
|
|
|
|
/* Use full render settings, for renders with scene lighting. */
|
|
|
|
view_settings = scene->view_settings;
|
|
|
|
}
|
|
|
|
else if (use_view_transform) {
|
|
|
|
/* Use only view transform + look and nothing else for lookdev without
|
|
|
|
* scene lighting, as exposure depends on scene light intensity. */
|
|
|
|
BKE_color_managed_view_settings_init_render(&view_settings, display_settings, NULL);
|
|
|
|
STRNCPY(view_settings.view_transform, scene->view_settings.view_transform);
|
|
|
|
STRNCPY(view_settings.look, scene->view_settings.look);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* For workbench use only default view transform in configuration,
|
|
|
|
* using no scene settings. */
|
|
|
|
BKE_color_managed_view_settings_init_render(&view_settings, display_settings, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(
|
|
|
|
&view_settings, display_settings, NULL, dither, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!use_ocio) {
|
|
|
|
/* View transform is already applied for offscreen, don't apply again, see: T52046 */
|
|
|
|
if (DST.options.is_image_render && !DST.options.is_scene_render) {
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
|
|
|
|
immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB);
|
|
|
|
}
|
|
|
|
immUniform1i("image", 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
GPU_texture_bind(tex, 0); /* OCIO texture bind point is 0 */
|
|
|
|
|
|
|
|
float mat[4][4];
|
|
|
|
unit_m4(mat);
|
|
|
|
immUniformMatrix4fv("ModelViewProjectionMatrix", mat);
|
|
|
|
|
|
|
|
/* Full screen triangle */
|
|
|
|
immBegin(GPU_PRIM_TRIS, 3);
|
|
|
|
immAttr2f(texco, 0.0f, 0.0f);
|
|
|
|
immVertex2f(pos, -1.0f, -1.0f);
|
|
|
|
|
|
|
|
immAttr2f(texco, 2.0f, 0.0f);
|
|
|
|
immVertex2f(pos, 3.0f, -1.0f);
|
|
|
|
|
|
|
|
immAttr2f(texco, 0.0f, 2.0f);
|
|
|
|
immVertex2f(pos, -1.0f, 3.0f);
|
|
|
|
immEnd();
|
|
|
|
|
|
|
|
GPU_texture_unbind(tex);
|
|
|
|
|
|
|
|
if (use_ocio) {
|
|
|
|
IMB_colormanagement_finish_glsl_draw();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
immUnbindProgram();
|
|
|
|
}
|
2017-05-11 16:20:10 +02:00
|
|
|
}
|
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
/* Draw texture to framebuffer without any color transforms */
|
|
|
|
void DRW_transform_none(GPUTexture *tex)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_state_set(DRW_STATE_WRITE_COLOR);
|
2019-03-11 23:52:12 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Draw as texture for final render (without immediate mode). */
|
|
|
|
GPUBatch *geom = DRW_cache_fullscreen_quad_get();
|
|
|
|
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_IMAGE_COLOR);
|
2018-07-11 11:43:56 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_texture_bind(tex, 0);
|
2018-07-11 11:43:56 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
|
|
|
GPU_batch_uniform_4fv(geom, "color", white);
|
2018-07-11 11:43:56 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
float mat[4][4];
|
|
|
|
unit_m4(mat);
|
|
|
|
GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
|
2018-07-11 11:43:56 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_batch_program_use_begin(geom);
|
2019-05-22 11:31:49 +02:00
|
|
|
GPU_batch_bind(geom);
|
|
|
|
GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_batch_program_use_end(geom);
|
2018-07-11 11:43:56 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_texture_unbind(tex);
|
2018-07-11 11:43:56 +02:00
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/** \} */
|
|
|
|
|
2018-04-23 23:10:59 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Multisample Resolve
|
|
|
|
* \{ */
|
|
|
|
|
2019-03-19 15:17:46 +11:00
|
|
|
/**
|
|
|
|
* Use manual multisample resolve pass.
|
2018-04-23 23:10:59 +02:00
|
|
|
* Much quicker than blitting back and forth.
|
2019-03-19 15:17:46 +11:00
|
|
|
* Assume destination fb is bound.
|
|
|
|
*/
|
2018-07-30 13:56:22 +02:00
|
|
|
void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool use_depth)
|
2018-04-23 23:10:59 +02:00
|
|
|
{
|
2019-05-27 23:21:39 +02:00
|
|
|
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
if (use_depth) {
|
|
|
|
state |= DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
|
|
|
|
}
|
|
|
|
drw_state_set(state);
|
|
|
|
|
|
|
|
int samples = GPU_texture_samples(src_depth);
|
|
|
|
|
|
|
|
BLI_assert(samples > 0);
|
|
|
|
BLI_assert(GPU_texture_samples(src_color) == samples);
|
|
|
|
|
|
|
|
GPUBatch *geom = DRW_cache_fullscreen_quad_get();
|
|
|
|
|
|
|
|
int builtin;
|
|
|
|
if (use_depth) {
|
|
|
|
switch (samples) {
|
|
|
|
case 2:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST;
|
|
|
|
break;
|
|
|
|
default:
|
2019-04-19 02:22:22 +02:00
|
|
|
BLI_assert(!"Mulisample count unsupported by blit shader.");
|
2019-04-17 06:17:24 +02:00
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch (samples) {
|
|
|
|
case 2:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_4;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_8;
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16;
|
|
|
|
break;
|
|
|
|
default:
|
2019-04-19 02:22:22 +02:00
|
|
|
BLI_assert(!"Mulisample count unsupported by blit shader.");
|
2019-04-17 06:17:24 +02:00
|
|
|
builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GPU_batch_program_set_builtin(geom, builtin);
|
|
|
|
|
|
|
|
if (use_depth) {
|
|
|
|
GPU_texture_bind(src_depth, 0);
|
|
|
|
GPU_batch_uniform_1i(geom, "depthMulti", 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
GPU_texture_bind(src_color, 1);
|
|
|
|
GPU_batch_uniform_1i(geom, "colorMulti", 1);
|
|
|
|
|
|
|
|
float mat[4][4];
|
|
|
|
unit_m4(mat);
|
|
|
|
GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
|
|
|
|
|
|
|
|
/* avoid gpuMatrix calls */
|
|
|
|
GPU_batch_program_use_begin(geom);
|
2019-05-22 11:31:49 +02:00
|
|
|
GPU_batch_bind(geom);
|
|
|
|
GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_batch_program_use_end(geom);
|
2018-04-23 23:10:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Viewport (DRW_viewport)
|
|
|
|
* \{ */
|
2017-04-12 19:49:19 +10:00
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
void *drw_viewport_engine_data_ensure(void *engine_type)
|
2017-03-08 20:00:09 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type);
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (data == NULL) {
|
|
|
|
data = GPU_viewport_engine_data_create(DST.viewport, engine_type);
|
|
|
|
}
|
|
|
|
return data;
|
2017-03-08 20:00:09 +01:00
|
|
|
}
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2017-04-12 19:49:19 +10:00
|
|
|
void DRW_engine_viewport_data_size_get(
|
2019-04-17 06:17:24 +02:00
|
|
|
const void *engine_type_v, int *r_fbl_len, int *r_txl_len, int *r_psl_len, int *r_stl_len)
|
2017-04-12 19:49:19 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
const DrawEngineType *engine_type = engine_type_v;
|
2017-04-12 19:49:19 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (r_fbl_len) {
|
|
|
|
*r_fbl_len = engine_type->vedata_size->fbl_len;
|
|
|
|
}
|
|
|
|
if (r_txl_len) {
|
|
|
|
*r_txl_len = engine_type->vedata_size->txl_len;
|
|
|
|
}
|
|
|
|
if (r_psl_len) {
|
|
|
|
*r_psl_len = engine_type->vedata_size->psl_len;
|
|
|
|
}
|
|
|
|
if (r_stl_len) {
|
|
|
|
*r_stl_len = engine_type->vedata_size->stl_len;
|
|
|
|
}
|
2017-04-12 19:49:19 +10:00
|
|
|
}
|
|
|
|
|
2018-09-17 11:53:43 +02:00
|
|
|
/* WARNING: only use for custom pipeline. 99% of the time, you don't want to use this. */
|
|
|
|
void DRW_render_viewport_size_set(int size[2])
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DST.size[0] = size[0];
|
|
|
|
DST.size[1] = size[1];
|
2018-09-17 11:53:43 +02:00
|
|
|
}
|
|
|
|
|
2017-04-12 12:10:01 +10:00
|
|
|
const float *DRW_viewport_size_get(void)
|
2017-02-07 11:20:15 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.size;
|
2018-03-13 22:38:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const float *DRW_viewport_invert_size_get(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.inv_size;
|
2017-02-07 11:20:15 +01:00
|
|
|
}
|
|
|
|
|
2017-04-12 12:10:01 +10:00
|
|
|
const float *DRW_viewport_screenvecs_get(void)
|
2017-02-07 11:20:15 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return &DST.screenvecs[0][0];
|
2017-02-07 11:20:15 +01:00
|
|
|
}
|
|
|
|
|
2017-04-12 12:10:01 +10:00
|
|
|
const float *DRW_viewport_pixelsize_get(void)
|
2017-02-07 11:20:15 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return &DST.pixsize;
|
2017-02-07 11:20:15 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_viewport_cache_resize(void)
|
2017-11-06 16:47:23 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Release the memiter before clearing the mempools that references them */
|
|
|
|
GPU_viewport_cache_release(DST.viewport);
|
2017-11-06 16:47:23 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.vmempool != NULL) {
|
2019-04-23 20:34:26 +02:00
|
|
|
/* Release Image textures. */
|
2019-05-07 18:01:14 +02:00
|
|
|
BLI_memblock_iter iter;
|
2019-04-23 20:34:26 +02:00
|
|
|
GPUTexture **tex;
|
2019-05-07 18:01:14 +02:00
|
|
|
BLI_memblock_iternew(DST.vmempool->images, &iter);
|
|
|
|
while ((tex = BLI_memblock_iterstep(&iter))) {
|
2019-04-23 20:34:26 +02:00
|
|
|
GPU_texture_free(*tex);
|
|
|
|
}
|
|
|
|
|
2019-05-13 15:57:03 +02:00
|
|
|
BLI_memblock_clear(DST.vmempool->calls, NULL);
|
|
|
|
BLI_memblock_clear(DST.vmempool->states, NULL);
|
2019-05-20 18:01:42 +02:00
|
|
|
BLI_memblock_clear(DST.vmempool->cullstates, NULL);
|
2019-05-13 15:57:03 +02:00
|
|
|
BLI_memblock_clear(DST.vmempool->shgroups, NULL);
|
|
|
|
BLI_memblock_clear(DST.vmempool->uniforms, NULL);
|
|
|
|
BLI_memblock_clear(DST.vmempool->passes, NULL);
|
2019-05-20 18:01:42 +02:00
|
|
|
BLI_memblock_clear(DST.vmempool->views, NULL);
|
2019-05-13 15:57:03 +02:00
|
|
|
BLI_memblock_clear(DST.vmempool->images, NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-01-09 14:21:55 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_instance_data_list_free_unused(DST.idatalist);
|
|
|
|
DRW_instance_data_list_resize(DST.idatalist);
|
2017-11-06 16:47:23 +01:00
|
|
|
}
|
|
|
|
|
2018-02-13 18:15:47 +11:00
|
|
|
/* Not a viewport variable, we could split this out. */
|
|
|
|
static void drw_context_state_init(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.draw_ctx.obact) {
|
|
|
|
DST.draw_ctx.object_mode = DST.draw_ctx.obact->mode;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DST.draw_ctx.object_mode = OB_MODE_OBJECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Edit object. */
|
|
|
|
if (DST.draw_ctx.object_mode & OB_MODE_EDIT) {
|
|
|
|
DST.draw_ctx.object_edit = DST.draw_ctx.obact;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DST.draw_ctx.object_edit = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pose object. */
|
|
|
|
if (DST.draw_ctx.object_mode & OB_MODE_POSE) {
|
|
|
|
DST.draw_ctx.object_pose = DST.draw_ctx.obact;
|
|
|
|
}
|
|
|
|
else if (DST.draw_ctx.object_mode & OB_MODE_WEIGHT_PAINT) {
|
|
|
|
DST.draw_ctx.object_pose = BKE_object_pose_armature_get(DST.draw_ctx.obact);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DST.draw_ctx.object_pose = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DST.draw_ctx.sh_cfg = GPU_SHADER_CFG_DEFAULT;
|
|
|
|
if (DST.draw_ctx.rv3d && DST.draw_ctx.rv3d->rflag & RV3D_CLIPPING) {
|
|
|
|
DST.draw_ctx.sh_cfg = GPU_SHADER_CFG_CLIPPED;
|
|
|
|
}
|
2018-02-13 18:15:47 +11:00
|
|
|
}
|
|
|
|
|
2019-05-30 00:36:54 +02:00
|
|
|
static DRWCallState *draw_unit_state_create(void)
|
|
|
|
{
|
|
|
|
DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states);
|
|
|
|
state->flag = 0;
|
|
|
|
state->matflag = 0;
|
|
|
|
|
|
|
|
unit_m4(state->model);
|
|
|
|
unit_m4(state->modelinverse);
|
|
|
|
|
|
|
|
copy_v3_fl(state->orcotexfac[0], 0.0f);
|
|
|
|
copy_v3_fl(state->orcotexfac[1], 1.0f);
|
|
|
|
|
|
|
|
state->ob_index = 0;
|
|
|
|
state->ob_random = 0.0f;
|
|
|
|
|
|
|
|
/* TODO(fclem) get rid of this. */
|
|
|
|
state->culling = BLI_memblock_alloc(DST.vmempool->cullstates);
|
|
|
|
state->culling->bsphere.radius = -1.0f;
|
|
|
|
state->culling->user_data = NULL;
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2017-03-08 20:00:09 +01:00
|
|
|
/* It also stores viewport variable to an immutable place: DST
|
|
|
|
* This is because a cache uniform only store reference
|
|
|
|
* to its value. And we don't want to invalidate the cache
|
|
|
|
* if this value change per viewport */
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_viewport_var_init(void)
|
2017-02-07 11:20:15 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
RegionView3D *rv3d = DST.draw_ctx.rv3d;
|
|
|
|
/* Refresh DST.size */
|
|
|
|
if (DST.viewport) {
|
|
|
|
int size[2];
|
|
|
|
GPU_viewport_size_get(DST.viewport, size);
|
|
|
|
DST.size[0] = size[0];
|
|
|
|
DST.size[1] = size[1];
|
|
|
|
DST.inv_size[0] = 1.0f / size[0];
|
|
|
|
DST.inv_size[1] = 1.0f / size[1];
|
|
|
|
|
|
|
|
DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(
|
|
|
|
DST.viewport);
|
|
|
|
DST.default_framebuffer = fbl->default_fb;
|
|
|
|
|
|
|
|
DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
|
|
|
|
|
|
|
|
if (DST.vmempool->calls == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (DST.vmempool->states == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-05-20 18:01:42 +02:00
|
|
|
if (DST.vmempool->cullstates == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState));
|
2019-05-20 18:01:42 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.vmempool->shgroups == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
if (DST.vmempool->uniforms == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-05-20 18:01:42 +02:00
|
|
|
if (DST.vmempool->views == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->views = BLI_memblock_create(sizeof(DRWView));
|
2019-05-20 18:01:42 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.vmempool->passes == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass));
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-04-23 20:34:26 +02:00
|
|
|
if (DST.vmempool->images == NULL) {
|
2019-05-21 00:54:03 +02:00
|
|
|
DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
|
2019-04-23 20:34:26 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-30 00:36:54 +02:00
|
|
|
/* Alloc default unit state */
|
|
|
|
DST.unit_state = draw_unit_state_create();
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
|
|
|
|
DRW_instance_data_list_reset(DST.idatalist);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DST.size[0] = 0;
|
|
|
|
DST.size[1] = 0;
|
|
|
|
|
|
|
|
DST.inv_size[0] = 0;
|
|
|
|
DST.inv_size[1] = 0;
|
|
|
|
|
|
|
|
DST.default_framebuffer = NULL;
|
|
|
|
DST.vmempool = NULL;
|
2019-05-30 00:36:54 +02:00
|
|
|
|
|
|
|
DST.unit_state = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-05-20 18:01:42 +02:00
|
|
|
DST.primary_view_ct = 0;
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (rv3d != NULL) {
|
2019-05-20 18:01:42 +02:00
|
|
|
normalize_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
|
|
|
|
normalize_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
DST.pixsize = rv3d->pixsize;
|
2019-05-20 18:01:42 +02:00
|
|
|
DST.view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, NULL, NULL, NULL);
|
2019-05-22 16:09:03 +02:00
|
|
|
DRW_view_camtexco_set(DST.view_default, rv3d->viewcamtexcofac);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-20 18:01:42 +02:00
|
|
|
if (DST.draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) {
|
|
|
|
int plane_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
|
|
|
|
DRW_view_clip_planes_set(DST.view_default, rv3d->clip, plane_len);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-21 21:29:25 +02:00
|
|
|
DST.view_active = DST.view_default;
|
2019-05-21 22:11:53 +02:00
|
|
|
DST.view_previous = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
else {
|
2019-05-20 18:01:42 +02:00
|
|
|
zero_v3(DST.screenvecs[0]);
|
|
|
|
zero_v3(DST.screenvecs[1]);
|
|
|
|
|
|
|
|
DST.pixsize = 1.0f;
|
|
|
|
DST.view_default = NULL;
|
2019-05-21 21:29:25 +02:00
|
|
|
DST.view_active = NULL;
|
2019-05-21 22:11:53 +02:00
|
|
|
DST.view_previous = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-05-20 18:01:42 +02:00
|
|
|
/* fclem: Is this still needed ? */
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.draw_ctx.object_edit) {
|
|
|
|
ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Alloc array of texture reference. */
|
|
|
|
memset(&DST.RST, 0x0, sizeof(DST.RST));
|
|
|
|
|
|
|
|
if (G_draw.view_ubo == NULL) {
|
2019-05-21 23:56:55 +02:00
|
|
|
G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data));
|
2017-02-07 11:20:15 +01:00
|
|
|
}
|
|
|
|
|
2017-03-08 20:00:09 +01:00
|
|
|
DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
|
2017-02-07 11:20:15 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return GPU_viewport_framebuffer_list_get(DST.viewport);
|
2017-02-07 11:20:15 +01:00
|
|
|
}
|
|
|
|
|
2017-03-08 20:00:09 +01:00
|
|
|
DefaultTextureList *DRW_viewport_texture_list_get(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return GPU_viewport_texture_list_get(DST.viewport);
|
2017-03-08 20:00:09 +01:00
|
|
|
}
|
2017-02-14 17:48:16 +01:00
|
|
|
|
2017-06-08 20:25:20 +02:00
|
|
|
void DRW_viewport_request_redraw(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_viewport_tag_update(DST.viewport);
|
2017-06-08 20:25:20 +02:00
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/** \} */
|
|
|
|
|
2019-05-07 20:56:20 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Duplis
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
static void drw_duplidata_load(DupliObject *dupli)
|
|
|
|
{
|
|
|
|
if (dupli == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DST.dupli_origin != dupli->ob) {
|
|
|
|
DST.dupli_origin = dupli->ob;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Same data as previous iter. No need to poll ghash for this. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DST.dupli_ghash == NULL) {
|
|
|
|
DST.dupli_ghash = BLI_ghash_ptr_new(__func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
void **value;
|
|
|
|
if (!BLI_ghash_ensure_p(DST.dupli_ghash, DST.dupli_origin, &value)) {
|
|
|
|
*value = MEM_callocN(sizeof(void *) * DST.enabled_engine_count, __func__);
|
2019-05-08 12:02:49 +02:00
|
|
|
|
|
|
|
/* TODO: Meh a bit out of place but this is nice as it is
|
|
|
|
* only done once per "original" object. */
|
|
|
|
drw_batch_cache_validate(DST.dupli_origin);
|
2019-05-07 20:56:20 +02:00
|
|
|
}
|
|
|
|
DST.dupli_datas = *(void ***)value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void duplidata_value_free(void *val)
|
|
|
|
{
|
|
|
|
void **dupli_datas = val;
|
|
|
|
for (int i = 0; i < DST.enabled_engine_count; i++) {
|
|
|
|
MEM_SAFE_FREE(dupli_datas[i]);
|
|
|
|
}
|
|
|
|
MEM_freeN(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void drw_duplidata_free(void)
|
|
|
|
{
|
|
|
|
if (DST.dupli_ghash != NULL) {
|
2019-05-08 12:02:49 +02:00
|
|
|
BLI_ghash_free(DST.dupli_ghash,
|
|
|
|
(void (*)(void *key))drw_batch_cache_generate_requested,
|
|
|
|
duplidata_value_free);
|
2019-05-07 20:56:20 +02:00
|
|
|
DST.dupli_ghash = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return NULL if not a dupli or a pointer of pointer to the engine data */
|
|
|
|
void **DRW_duplidata_get(void *vedata)
|
|
|
|
{
|
|
|
|
if (DST.dupli_source == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* XXX Search engine index by using vedata array */
|
|
|
|
for (int i = 0; i < DST.enabled_engine_count; i++) {
|
|
|
|
if (DST.vedata_array[i] == vedata) {
|
|
|
|
return &DST.dupli_datas[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
2017-05-30 22:28:47 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
2017-11-22 10:52:39 -02:00
|
|
|
/** \name ViewLayers (DRW_scenelayer)
|
2017-05-30 22:28:47 +02:00
|
|
|
* \{ */
|
|
|
|
|
2017-11-29 11:00:50 +01:00
|
|
|
void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
for (ViewLayerEngineData *sled = DST.draw_ctx.view_layer->drawdata.first; sled;
|
|
|
|
sled = sled->next) {
|
|
|
|
if (sled->engine_type == engine_type) {
|
|
|
|
return sled->storage;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
2017-11-29 11:00:50 +01:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
void **DRW_view_layer_engine_data_ensure_ex(ViewLayer *view_layer,
|
|
|
|
DrawEngineType *engine_type,
|
|
|
|
void (*callback)(void *storage))
|
2017-05-30 22:28:47 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
ViewLayerEngineData *sled;
|
2017-05-30 22:28:47 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
for (sled = view_layer->drawdata.first; sled; sled = sled->next) {
|
|
|
|
if (sled->engine_type == engine_type) {
|
|
|
|
return &sled->storage;
|
|
|
|
}
|
|
|
|
}
|
2017-05-30 22:28:47 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
sled = MEM_callocN(sizeof(ViewLayerEngineData), "ViewLayerEngineData");
|
|
|
|
sled->engine_type = engine_type;
|
|
|
|
sled->free = callback;
|
|
|
|
BLI_addtail(&view_layer->drawdata, sled);
|
2017-05-30 22:28:47 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
return &sled->storage;
|
2017-05-30 22:28:47 +02:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type,
|
|
|
|
void (*callback)(void *storage))
|
2018-05-11 10:56:52 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DRW_view_layer_engine_data_ensure_ex(DST.draw_ctx.view_layer, engine_type, callback);
|
2018-05-11 10:56:52 +02:00
|
|
|
}
|
|
|
|
|
2017-05-30 22:28:47 +02:00
|
|
|
/** \} */
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
2018-07-10 14:14:55 +02:00
|
|
|
/** \name Draw Data (DRW_drawdata)
|
2017-04-27 02:04:56 +10:00
|
|
|
* \{ */
|
2017-04-03 19:01:10 +02:00
|
|
|
|
2018-07-10 14:14:55 +02:00
|
|
|
/* Used for DRW_drawdata_from_id()
|
2019-06-12 09:04:10 +10:00
|
|
|
* All ID-data-blocks which have their own 'local' DrawData
|
2018-07-10 14:14:55 +02:00
|
|
|
* should have the same arrangement in their structs.
|
|
|
|
*/
|
|
|
|
typedef struct IdDdtTemplate {
|
2019-04-17 06:17:24 +02:00
|
|
|
ID id;
|
|
|
|
struct AnimData *adt;
|
|
|
|
DrawDataList drawdata;
|
2018-07-10 14:14:55 +02:00
|
|
|
} IdDdtTemplate;
|
|
|
|
|
|
|
|
/* Check if ID can have AnimData */
|
|
|
|
static bool id_type_can_have_drawdata(const short id_type)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Only some ID-blocks have this info for now */
|
|
|
|
/* TODO: finish adding this for the other blocktypes */
|
|
|
|
switch (id_type) {
|
|
|
|
/* has DrawData */
|
|
|
|
case ID_OB:
|
|
|
|
case ID_WO:
|
|
|
|
return true;
|
2018-07-10 14:14:55 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* no DrawData */
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2018-07-10 14:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool id_can_have_drawdata(const ID *id)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* sanity check */
|
|
|
|
if (id == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-07-10 14:14:55 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
return id_type_can_have_drawdata(GS(id->name));
|
2018-07-10 14:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get DrawData from the given ID-block. In order for this to work, we assume that
|
|
|
|
* the DrawData pointer is stored in the struct in the same fashion as in IdDdtTemplate.
|
|
|
|
*/
|
|
|
|
DrawDataList *DRW_drawdatalist_from_id(ID *id)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* only some ID-blocks have this info for now, so we cast the
|
|
|
|
* types that do to be of type IdDdtTemplate, and extract the
|
|
|
|
* DrawData that way
|
|
|
|
*/
|
|
|
|
if (id_can_have_drawdata(id)) {
|
|
|
|
IdDdtTemplate *idt = (IdDdtTemplate *)id;
|
|
|
|
return &idt->drawdata;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-07-10 14:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DrawData *DRW_drawdata_get(ID *id, DrawEngineType *engine_type)
|
2017-11-29 11:00:50 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
|
|
|
|
|
|
|
|
if (drawdata == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (DrawData *, dd, drawdata) {
|
|
|
|
if (dd->engine_type == engine_type) {
|
|
|
|
return dd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
DrawData *DRW_drawdata_ensure(ID *id,
|
|
|
|
DrawEngineType *engine_type,
|
|
|
|
size_t size,
|
|
|
|
DrawDataInitCb init_cb,
|
|
|
|
DrawDataFreeCb free_cb)
|
|
|
|
{
|
|
|
|
BLI_assert(size >= sizeof(DrawData));
|
|
|
|
BLI_assert(id_can_have_drawdata(id));
|
|
|
|
/* Try to re-use existing data. */
|
|
|
|
DrawData *dd = DRW_drawdata_get(id, engine_type);
|
|
|
|
if (dd != NULL) {
|
|
|
|
return dd;
|
|
|
|
}
|
|
|
|
|
|
|
|
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
|
|
|
|
|
|
|
|
/* Allocate new data. */
|
|
|
|
if ((GS(id->name) == ID_OB) && (((Object *)id)->base_flag & BASE_FROM_DUPLI) != 0) {
|
|
|
|
/* NOTE: data is not persistent in this case. It is reset each redraw. */
|
|
|
|
BLI_assert(free_cb == NULL); /* No callback allowed. */
|
|
|
|
/* Round to sizeof(float) for DRW_instance_data_request(). */
|
|
|
|
const size_t t = sizeof(float) - 1;
|
|
|
|
size = (size + t) & ~t;
|
|
|
|
size_t fsize = size / sizeof(float);
|
|
|
|
BLI_assert(fsize < MAX_INSTANCE_DATA_SIZE);
|
|
|
|
if (DST.object_instance_data[fsize] == NULL) {
|
|
|
|
DST.object_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize);
|
|
|
|
}
|
|
|
|
dd = (DrawData *)DRW_instance_data_next(DST.object_instance_data[fsize]);
|
|
|
|
memset(dd, 0, size);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dd = MEM_callocN(size, "DrawData");
|
|
|
|
}
|
|
|
|
dd->engine_type = engine_type;
|
|
|
|
dd->free = free_cb;
|
|
|
|
/* Perform user-side initialization, if needed. */
|
|
|
|
if (init_cb != NULL) {
|
|
|
|
init_cb(dd);
|
|
|
|
}
|
|
|
|
/* Register in the list. */
|
|
|
|
BLI_addtail((ListBase *)drawdata, dd);
|
|
|
|
return dd;
|
2018-07-10 14:14:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_drawdata_free(ID *id)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
|
2018-07-10 14:14:55 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (drawdata == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2018-07-10 14:14:55 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
LISTBASE_FOREACH (DrawData *, dd, drawdata) {
|
|
|
|
if (dd->free != NULL) {
|
|
|
|
dd->free(dd);
|
|
|
|
}
|
|
|
|
}
|
2018-07-10 14:14:55 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_freelistN((ListBase *)drawdata);
|
2017-04-03 19:01:10 +02:00
|
|
|
}
|
|
|
|
|
2018-08-22 13:41:18 +02:00
|
|
|
/* Unlink (but don't free) the drawdata from the DrawDataList if the ID is an OB from dupli. */
|
|
|
|
static void drw_drawdata_unlink_dupli(ID *id)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if ((GS(id->name) == ID_OB) && (((Object *)id)->base_flag & BASE_FROM_DUPLI) != 0) {
|
|
|
|
DrawDataList *drawdata = DRW_drawdatalist_from_id(id);
|
2018-08-22 13:41:18 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (drawdata == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2018-08-22 13:41:18 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_listbase_clear((ListBase *)drawdata);
|
|
|
|
}
|
2018-08-22 13:41:18 +02:00
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/** \} */
|
|
|
|
|
2019-04-19 02:22:22 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
2019-04-19 18:52:38 +02:00
|
|
|
/** \name Garbage Collection
|
2019-04-19 02:22:22 +02:00
|
|
|
* \{ */
|
|
|
|
|
|
|
|
void DRW_cache_free_old_batches(Main *bmain)
|
|
|
|
{
|
|
|
|
Scene *scene;
|
|
|
|
ViewLayer *view_layer;
|
|
|
|
static int lasttime = 0;
|
|
|
|
int ctime = (int)PIL_check_seconds_timer();
|
|
|
|
|
2019-04-22 12:20:14 +10:00
|
|
|
if (U.vbotimeout == 0 || (ctime - lasttime) < U.vbocollectrate || ctime == lasttime) {
|
2019-04-19 02:22:22 +02:00
|
|
|
return;
|
2019-04-22 12:20:14 +10:00
|
|
|
}
|
2019-04-19 02:22:22 +02:00
|
|
|
|
|
|
|
lasttime = ctime;
|
|
|
|
|
|
|
|
for (scene = bmain->scenes.first; scene; scene = scene->id.next) {
|
|
|
|
for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
|
|
|
|
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
|
2019-04-23 14:31:21 +02:00
|
|
|
if (depsgraph == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-19 02:22:22 +02:00
|
|
|
|
|
|
|
/* TODO(fclem): This is not optimal since it iter over all dupli instances.
|
|
|
|
* In this case only the source object should be tagged. */
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
2019-04-19 02:22:22 +02:00
|
|
|
DRW_batch_cache_free_old(ob, ctime);
|
|
|
|
}
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
2019-04-19 02:22:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Rendering (DRW_engines)
|
|
|
|
* \{ */
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_init(void)
|
2017-02-14 17:48:16 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
|
|
|
|
PROFILE_START(stime);
|
2017-03-26 19:25:45 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->engine_init) {
|
|
|
|
engine->engine_init(data);
|
|
|
|
}
|
2017-03-26 19:25:45 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
PROFILE_END_UPDATE(data->init_time, stime);
|
|
|
|
}
|
2017-02-14 17:48:16 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_cache_init(void)
|
2017-02-17 17:29:43 +01:00
|
|
|
{
|
2019-05-07 20:56:20 +02:00
|
|
|
DST.enabled_engine_count = BLI_listbase_count(&DST.enabled_engines);
|
|
|
|
DST.vedata_array = MEM_mallocN(sizeof(void *) * DST.enabled_engine_count, __func__);
|
2019-05-07 18:40:02 +02:00
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
DrawEngineType *engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
|
2019-05-07 18:40:02 +02:00
|
|
|
DST.vedata_array[i] = data;
|
2017-04-28 04:33:58 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (data->text_draw_cache) {
|
|
|
|
DRW_text_cache_destroy(data->text_draw_cache);
|
|
|
|
data->text_draw_cache = NULL;
|
|
|
|
}
|
|
|
|
if (DST.text_store_p == NULL) {
|
|
|
|
DST.text_store_p = &data->text_draw_cache;
|
|
|
|
}
|
2017-04-28 04:33:58 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->cache_init) {
|
|
|
|
engine->cache_init(data);
|
|
|
|
}
|
|
|
|
}
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2018-07-10 14:14:55 +02:00
|
|
|
static void drw_engines_world_update(Scene *scene)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (scene->world == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2018-07-10 14:14:55 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
|
2018-07-10 14:14:55 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->id_update) {
|
|
|
|
engine->id_update(data, &scene->world->id);
|
|
|
|
}
|
|
|
|
}
|
2018-07-10 14:14:55 +02:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_cache_populate(Object *ob)
|
2017-02-17 17:29:43 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DST.ob_state = NULL;
|
2018-02-28 16:23:33 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* HACK: DrawData is copied by COW from the duplicated object.
|
|
|
|
* This is valid for IDs that cannot be instantiated but this
|
|
|
|
* is not what we want in this case so we clear the pointer
|
|
|
|
* ourselves here. */
|
|
|
|
drw_drawdata_unlink_dupli((ID *)ob);
|
2018-08-22 13:41:18 +02:00
|
|
|
|
2019-05-08 12:02:49 +02:00
|
|
|
/* Validation for dupli objects happen elsewhere. */
|
|
|
|
if (!DST.dupli_source) {
|
|
|
|
drw_batch_cache_validate(ob);
|
|
|
|
}
|
2019-05-07 23:21:16 +02:00
|
|
|
|
2019-05-07 18:40:02 +02:00
|
|
|
int i = 0;
|
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
DrawEngineType *engine = link->data;
|
2019-05-07 18:40:02 +02:00
|
|
|
ViewportEngineData *data = DST.vedata_array[i];
|
2017-03-26 19:25:45 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->id_update) {
|
|
|
|
engine->id_update(data, &ob->id);
|
|
|
|
}
|
2018-01-29 16:42:04 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->cache_populate) {
|
|
|
|
engine->cache_populate(data, ob);
|
|
|
|
}
|
|
|
|
}
|
2018-08-22 13:41:18 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* TODO: in the future it would be nice to generate once for all viewports.
|
|
|
|
* But we need threaded DRW manager first. */
|
2019-05-08 12:02:49 +02:00
|
|
|
if (!DST.dupli_source) {
|
|
|
|
drw_batch_cache_generate_requested(ob);
|
|
|
|
}
|
2018-12-08 20:10:20 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* ... and clearing it here too because theses draw data are
|
|
|
|
* from a mempool and must not be free individually by depsgraph. */
|
|
|
|
drw_drawdata_unlink_dupli((ID *)ob);
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_cache_finish(void)
|
2017-02-17 17:29:43 +01:00
|
|
|
{
|
2019-05-07 18:40:02 +02:00
|
|
|
int i = 0;
|
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
|
2019-04-17 06:17:24 +02:00
|
|
|
DrawEngineType *engine = link->data;
|
2019-05-07 18:40:02 +02:00
|
|
|
ViewportEngineData *data = DST.vedata_array[i];
|
2017-03-26 19:25:45 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->cache_finish) {
|
|
|
|
engine->cache_finish(data);
|
|
|
|
}
|
|
|
|
}
|
2019-05-07 18:40:02 +02:00
|
|
|
MEM_freeN(DST.vedata_array);
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_draw_background(void)
|
2017-02-17 17:29:43 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
|
2017-03-26 19:25:45 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->draw_background) {
|
|
|
|
PROFILE_START(stime);
|
2017-07-26 19:57:46 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_stats_group_start(engine->idname);
|
|
|
|
engine->draw_background(data);
|
|
|
|
DRW_stats_group_end();
|
2017-07-26 19:57:46 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
PROFILE_END_UPDATE(data->background_time, stime);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* No draw_background found, doing default background */
|
2019-05-01 10:51:27 +02:00
|
|
|
const bool do_alpha_checker = !DRW_state_draw_background();
|
|
|
|
DRW_draw_background(do_alpha_checker);
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_draw_scene(void)
|
2017-02-17 17:29:43 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
|
|
|
|
PROFILE_START(stime);
|
2017-03-26 19:25:45 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (engine->draw_scene) {
|
|
|
|
DRW_stats_group_start(engine->idname);
|
|
|
|
engine->draw_scene(data);
|
|
|
|
/* Restore for next engine */
|
|
|
|
if (DRW_state_is_fbo()) {
|
|
|
|
GPU_framebuffer_bind(DST.default_framebuffer);
|
|
|
|
}
|
|
|
|
DRW_stats_group_end();
|
|
|
|
}
|
2017-03-26 19:25:45 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
PROFILE_END_UPDATE(data->render_time, stime);
|
|
|
|
}
|
|
|
|
/* Reset state after drawing */
|
|
|
|
DRW_state_reset();
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_draw_text(void)
|
2017-04-28 04:33:58 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
|
|
|
|
PROFILE_START(stime);
|
2017-04-28 04:33:58 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (data->text_draw_cache) {
|
|
|
|
DRW_text_cache_draw(data->text_draw_cache, DST.draw_ctx.ar);
|
|
|
|
}
|
2017-04-28 04:33:58 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
PROFILE_END_UPDATE(data->render_time, stime);
|
|
|
|
}
|
2017-04-28 04:33:58 +10:00
|
|
|
}
|
|
|
|
|
2018-10-25 11:47:37 +02:00
|
|
|
/* Draw render engine info. */
|
|
|
|
void DRW_draw_region_engine_info(int xoffset, int yoffset)
|
2017-05-04 15:46:09 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
|
2017-05-04 15:46:09 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (data->info[0] != '\0') {
|
|
|
|
char *chr_current = data->info;
|
|
|
|
char *chr_start = chr_current;
|
|
|
|
int line_len = 0;
|
2017-05-04 21:56:34 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
const int font_id = BLF_default();
|
|
|
|
UI_FontThemeColor(font_id, TH_TEXT_HI);
|
2018-10-25 11:47:37 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BLF_enable(font_id, BLF_SHADOW);
|
|
|
|
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
|
|
|
|
BLF_shadow_offset(font_id, 1, -1);
|
2018-10-25 11:47:37 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
while (*chr_current++ != '\0') {
|
|
|
|
line_len++;
|
|
|
|
if (*chr_current == '\n') {
|
|
|
|
char info[GPU_INFO_SIZE];
|
|
|
|
BLI_strncpy(info, chr_start, line_len + 1);
|
|
|
|
yoffset -= U.widget_unit;
|
|
|
|
BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info));
|
2018-10-25 11:47:37 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Re-start counting. */
|
|
|
|
chr_start = chr_current + 1;
|
|
|
|
line_len = -1;
|
|
|
|
}
|
|
|
|
}
|
2017-05-04 21:56:34 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
char info[GPU_INFO_SIZE];
|
|
|
|
BLI_strncpy(info, chr_start, line_len + 1);
|
|
|
|
yoffset -= U.widget_unit;
|
|
|
|
BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info));
|
2017-05-04 21:56:34 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BLF_disable(font_id, BLF_SHADOW);
|
|
|
|
}
|
|
|
|
}
|
2017-05-04 15:46:09 +02:00
|
|
|
}
|
|
|
|
|
2017-03-08 20:00:09 +01:00
|
|
|
static void use_drw_engine(DrawEngineType *engine)
|
2017-02-17 17:29:43 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data");
|
|
|
|
ld->data = engine;
|
|
|
|
BLI_addtail(&DST.enabled_engines, ld);
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2018-02-28 01:16:23 +01:00
|
|
|
/**
|
|
|
|
* Use for external render engines.
|
|
|
|
*/
|
|
|
|
static void drw_engines_enable_external(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
|
2018-02-28 01:16:23 +01:00
|
|
|
}
|
|
|
|
|
2017-03-08 20:00:09 +01:00
|
|
|
/* TODO revisit this when proper layering is implemented */
|
|
|
|
/* Gather all draw engines needed and store them in DST.enabled_engines
|
|
|
|
* That also define the rendering order of engines */
|
2019-04-17 06:17:24 +02:00
|
|
|
static void drw_engines_enable_from_engine(RenderEngineType *engine_type,
|
|
|
|
int drawtype,
|
|
|
|
bool use_xray)
|
|
|
|
{
|
|
|
|
switch (drawtype) {
|
|
|
|
case OB_WIRE:
|
|
|
|
use_drw_engine(&draw_engine_workbench_transparent);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OB_SOLID:
|
|
|
|
if (use_xray) {
|
|
|
|
use_drw_engine(&draw_engine_workbench_transparent);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
use_drw_engine(&draw_engine_workbench_solid);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OB_MATERIAL:
|
|
|
|
case OB_RENDER:
|
|
|
|
default:
|
|
|
|
/* TODO layers */
|
|
|
|
if (engine_type->draw_engine != NULL) {
|
|
|
|
use_drw_engine(engine_type->draw_engine);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((engine_type->flag & RE_INTERNAL) == 0) {
|
|
|
|
drw_engines_enable_external();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2017-04-26 16:52:02 +10:00
|
|
|
}
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_enable_from_object_mode(void)
|
2017-04-26 16:52:02 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
use_drw_engine(&draw_engine_object_type);
|
|
|
|
/* TODO(fclem) remove this, it does not belong to it's own engine. */
|
|
|
|
use_drw_engine(&draw_engine_motion_path_type);
|
2017-04-26 04:39:25 +10:00
|
|
|
}
|
|
|
|
|
2018-06-28 16:12:24 +02:00
|
|
|
static void drw_engines_enable_from_paint_mode(int mode)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
switch (mode) {
|
|
|
|
case CTX_MODE_SCULPT:
|
|
|
|
use_drw_engine(&draw_engine_sculpt_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_PAINT_WEIGHT:
|
|
|
|
case CTX_MODE_PAINT_VERTEX:
|
|
|
|
use_drw_engine(&draw_engine_paint_vertex_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_PAINT_TEXTURE:
|
|
|
|
use_drw_engine(&draw_engine_paint_texture_type);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2018-06-28 16:12:24 +02:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_enable_from_mode(int mode)
|
2017-04-26 04:39:25 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
switch (mode) {
|
|
|
|
case CTX_MODE_EDIT_MESH:
|
|
|
|
use_drw_engine(&draw_engine_edit_mesh_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_EDIT_SURFACE:
|
|
|
|
case CTX_MODE_EDIT_CURVE:
|
|
|
|
use_drw_engine(&draw_engine_edit_curve_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_EDIT_TEXT:
|
|
|
|
use_drw_engine(&draw_engine_edit_text_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_EDIT_ARMATURE:
|
|
|
|
use_drw_engine(&draw_engine_edit_armature_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_EDIT_METABALL:
|
|
|
|
use_drw_engine(&draw_engine_edit_metaball_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_EDIT_LATTICE:
|
|
|
|
use_drw_engine(&draw_engine_edit_lattice_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_PARTICLE:
|
|
|
|
use_drw_engine(&draw_engine_particle_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_POSE:
|
|
|
|
case CTX_MODE_PAINT_WEIGHT:
|
|
|
|
/* The pose engine clears the depth of the default framebuffer
|
|
|
|
* to draw an object with `OB_DRAWXRAY`.
|
|
|
|
* (different of workbench that has its own framebuffer).
|
|
|
|
* So make sure you call its `draw_scene` after all the other engines. */
|
|
|
|
use_drw_engine(&draw_engine_pose_type);
|
|
|
|
break;
|
|
|
|
case CTX_MODE_SCULPT:
|
|
|
|
case CTX_MODE_PAINT_VERTEX:
|
|
|
|
case CTX_MODE_PAINT_TEXTURE:
|
|
|
|
case CTX_MODE_OBJECT:
|
|
|
|
case CTX_MODE_PAINT_GPENCIL:
|
|
|
|
case CTX_MODE_EDIT_GPENCIL:
|
|
|
|
case CTX_MODE_SCULPT_GPENCIL:
|
|
|
|
case CTX_MODE_WEIGHT_GPENCIL:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BLI_assert(!"Draw mode invalid");
|
|
|
|
break;
|
|
|
|
}
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2018-08-20 10:45:02 +02:00
|
|
|
static void drw_engines_enable_from_overlays(int UNUSED(overlay_flag))
|
2018-04-21 20:42:27 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
use_drw_engine(&draw_engine_overlay_type);
|
2018-04-20 10:45:46 +02:00
|
|
|
}
|
2017-04-27 02:49:13 +10:00
|
|
|
/**
|
|
|
|
* Use for select and depth-drawing.
|
|
|
|
*/
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_enable_basic(void)
|
2017-04-26 16:52:02 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
use_drw_engine(DRW_engine_viewport_basic_type.draw_engine);
|
2017-04-26 16:52:02 +10:00
|
|
|
}
|
|
|
|
|
2019-05-28 09:11:55 +02:00
|
|
|
static void drw_engines_enable(ViewLayer *view_layer,
|
|
|
|
RenderEngineType *engine_type,
|
|
|
|
bool gpencil_engine_needed)
|
2017-04-26 16:11:37 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
Object *obact = OBACT(view_layer);
|
|
|
|
const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
|
|
|
|
DST.draw_ctx.object_edit, obact, DST.draw_ctx.object_mode);
|
|
|
|
View3D *v3d = DST.draw_ctx.v3d;
|
|
|
|
const int drawtype = v3d->shading.type;
|
|
|
|
const bool use_xray = XRAY_ENABLED(v3d);
|
|
|
|
|
|
|
|
drw_engines_enable_from_engine(engine_type, drawtype, use_xray);
|
|
|
|
/* grease pencil */
|
2019-05-28 09:11:55 +02:00
|
|
|
if (gpencil_engine_needed) {
|
|
|
|
use_drw_engine(&draw_engine_gpencil_type);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
if (DRW_state_draw_support()) {
|
|
|
|
/* Draw paint modes first so that they are drawn below the wireframes. */
|
|
|
|
drw_engines_enable_from_paint_mode(mode);
|
|
|
|
drw_engines_enable_from_overlays(v3d->overlay.flag);
|
|
|
|
drw_engines_enable_from_object_mode();
|
|
|
|
drw_engines_enable_from_mode(mode);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Force enable overlays engine for wireframe mode */
|
|
|
|
if (v3d->shading.type == OB_WIRE) {
|
|
|
|
drw_engines_enable_from_overlays(v3d->overlay.flag);
|
|
|
|
}
|
|
|
|
}
|
2017-04-26 16:11:37 +10:00
|
|
|
}
|
|
|
|
|
2017-11-29 12:49:15 +01:00
|
|
|
static void drw_engines_disable(void)
|
2017-02-17 17:29:43 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_freelistN(&DST.enabled_engines);
|
2017-03-08 20:00:09 +01:00
|
|
|
}
|
|
|
|
|
2019-05-07 18:42:28 +02:00
|
|
|
static void drw_engines_data_validate(void)
|
2017-03-08 20:00:09 +01:00
|
|
|
{
|
2019-05-07 18:42:28 +02:00
|
|
|
int enabled_engines = BLI_listbase_count(&DST.enabled_engines);
|
|
|
|
void **engine_handle_array = BLI_array_alloca(engine_handle_array, enabled_engines + 1);
|
|
|
|
int i = 0;
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *engine = link->data;
|
2019-05-07 18:42:28 +02:00
|
|
|
engine_handle_array[i++] = engine;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-05-07 18:42:28 +02:00
|
|
|
engine_handle_array[i] = NULL;
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2019-05-07 18:42:28 +02:00
|
|
|
GPU_viewport_engines_data_validate(DST.viewport, engine_handle_array);
|
2017-03-08 20:00:09 +01:00
|
|
|
}
|
|
|
|
|
2019-05-28 09:11:55 +02:00
|
|
|
/* Fast check to see if gpencil drawing engine is needed.
|
|
|
|
* For slow exact check use `DRW_render_check_grease_pencil` */
|
|
|
|
static bool drw_gpencil_engine_needed(Depsgraph *depsgraph, View3D *v3d)
|
|
|
|
{
|
|
|
|
const bool exclude_gpencil_rendering = v3d ? (v3d->object_type_exclude_viewport &
|
|
|
|
(1 << OB_GPENCIL)) != 0 :
|
|
|
|
false;
|
|
|
|
return (!exclude_gpencil_rendering) || DEG_id_type_any_exists(depsgraph, ID_GD);
|
|
|
|
}
|
|
|
|
|
2017-09-25 20:07:02 +02:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name View Update
|
|
|
|
* \{ */
|
|
|
|
|
2017-11-28 16:42:58 +01:00
|
|
|
void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
|
2017-09-25 20:07:02 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
RenderEngineType *engine_type = update_ctx->engine_type;
|
|
|
|
ARegion *ar = update_ctx->ar;
|
|
|
|
View3D *v3d = update_ctx->v3d;
|
|
|
|
RegionView3D *rv3d = ar->regiondata;
|
|
|
|
Depsgraph *depsgraph = update_ctx->depsgraph;
|
|
|
|
Scene *scene = update_ctx->scene;
|
|
|
|
ViewLayer *view_layer = update_ctx->view_layer;
|
|
|
|
|
2019-05-28 09:11:55 +02:00
|
|
|
const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d);
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Separate update for each stereo view. */
|
|
|
|
for (int view = 0; view < 2; view++) {
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_viewport(ar, view);
|
|
|
|
if (!viewport) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX Really nasty locking. But else this could
|
|
|
|
* be executed by the material previews thread
|
|
|
|
* while rendering a viewport. */
|
|
|
|
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
|
|
|
|
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
|
|
|
|
DST.viewport = viewport;
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.ar = ar,
|
|
|
|
.rv3d = rv3d,
|
|
|
|
.v3d = v3d,
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.obact = OBACT(view_layer),
|
|
|
|
.engine_type = engine_type,
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
.object_mode = OB_MODE_OBJECT,
|
|
|
|
};
|
|
|
|
|
2019-05-28 09:11:55 +02:00
|
|
|
drw_engines_enable(view_layer, engine_type, gpencil_engine_needed);
|
2019-06-17 23:07:41 +02:00
|
|
|
drw_engines_data_validate();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
|
|
|
|
DrawEngineType *draw_engine = link->data;
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine);
|
|
|
|
|
|
|
|
if (draw_engine->view_update) {
|
|
|
|
draw_engine->view_update(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DST.viewport = NULL;
|
|
|
|
|
|
|
|
drw_engines_disable();
|
|
|
|
|
|
|
|
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
|
|
|
}
|
2017-09-25 20:07:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
2017-04-27 02:04:56 +10:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Main Draw Loops (DRW_draw)
|
|
|
|
* \{ */
|
|
|
|
|
2017-03-08 20:00:09 +01:00
|
|
|
/* Everything starts here.
|
|
|
|
* This function takes care of calling all cache and rendering functions
|
|
|
|
* for each relevant engine / mode engine. */
|
|
|
|
void DRW_draw_view(const bContext *C)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
|
|
|
ARegion *ar = CTX_wm_region(C);
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_bound_viewport(ar);
|
2017-05-03 00:45:10 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 &&
|
|
|
|
(v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0);
|
2019-05-24 13:37:52 +02:00
|
|
|
DST.options.draw_background = (scene->r.alphamode == R_ADDSKY) ||
|
|
|
|
(v3d->shading.type != OB_RENDER);
|
2019-05-21 12:00:48 +02:00
|
|
|
DST.options.do_color_management = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C);
|
2017-05-03 00:45:10 +10:00
|
|
|
}
|
|
|
|
|
2017-05-03 02:50:29 +10:00
|
|
|
/**
|
2017-05-03 04:59:15 +10:00
|
|
|
* Used for both regular and off-screen drawing.
|
2017-06-20 18:33:58 +02:00
|
|
|
* Need to reset DST before calling this function
|
2017-05-03 02:50:29 +10:00
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
|
|
|
|
RenderEngineType *engine_type,
|
|
|
|
ARegion *ar,
|
|
|
|
View3D *v3d,
|
|
|
|
GPUViewport *viewport,
|
|
|
|
const bContext *evil_C)
|
|
|
|
{
|
|
|
|
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
RegionView3D *rv3d = ar->regiondata;
|
|
|
|
const bool do_annotations = (((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
|
|
|
|
((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
|
|
|
|
|
|
|
|
DST.draw_ctx.evil_C = evil_C;
|
|
|
|
DST.viewport = viewport;
|
|
|
|
|
|
|
|
/* Setup viewport */
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.ar = ar,
|
|
|
|
.rv3d = rv3d,
|
|
|
|
.v3d = v3d,
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.obact = OBACT(view_layer),
|
|
|
|
.engine_type = engine_type,
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
|
|
|
|
/* reuse if caller sets */
|
|
|
|
.evil_C = DST.draw_ctx.evil_C,
|
|
|
|
};
|
|
|
|
drw_context_state_init();
|
|
|
|
drw_viewport_var_init();
|
|
|
|
|
2019-05-28 09:11:55 +02:00
|
|
|
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
|
|
|
|
/* Check if scene needs to perform the populate loop */
|
|
|
|
const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0;
|
|
|
|
const bool draw_type_render = v3d->shading.type == OB_RENDER;
|
|
|
|
const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
|
|
|
|
const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d);
|
|
|
|
const bool do_populate_loop = internal_engine || overlays_on || !draw_type_render ||
|
|
|
|
gpencil_engine_needed;
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Get list of enabled engines */
|
2019-05-28 09:11:55 +02:00
|
|
|
drw_engines_enable(view_layer, engine_type, gpencil_engine_needed);
|
2019-05-07 18:42:28 +02:00
|
|
|
drw_engines_data_validate();
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Update ubos */
|
|
|
|
DRW_globals_update();
|
|
|
|
|
|
|
|
drw_debug_init();
|
|
|
|
DRW_hair_init();
|
|
|
|
|
|
|
|
/* No framebuffer allowed before drawing. */
|
|
|
|
BLI_assert(GPU_framebuffer_active_get() == NULL);
|
|
|
|
|
|
|
|
/* Init engines */
|
|
|
|
drw_engines_init();
|
|
|
|
|
|
|
|
/* Cache filling */
|
|
|
|
{
|
|
|
|
PROFILE_START(stime);
|
|
|
|
drw_engines_cache_init();
|
|
|
|
drw_engines_world_update(scene);
|
|
|
|
|
2019-05-03 15:48:21 +02:00
|
|
|
/* Only iterate over objects for internal engines or when overlays are enabled */
|
2019-05-28 09:11:55 +02:00
|
|
|
if (do_populate_loop) {
|
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
2019-05-03 15:48:21 +02:00
|
|
|
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
DST.dupli_parent = data_.dupli_parent;
|
|
|
|
DST.dupli_source = data_.dupli_object_current;
|
2019-05-07 20:56:20 +02:00
|
|
|
drw_duplidata_load(DST.dupli_source);
|
2019-05-03 15:48:21 +02:00
|
|
|
drw_engines_cache_populate(ob);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-05-07 20:56:20 +02:00
|
|
|
drw_duplidata_free();
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_cache_finish();
|
|
|
|
|
|
|
|
DRW_render_instance_buffer_finish();
|
2018-03-17 04:47:26 +01:00
|
|
|
|
|
|
|
#ifdef USE_PROFILE
|
2019-04-17 06:17:24 +02:00
|
|
|
double *cache_time = GPU_viewport_cache_time_get(DST.viewport);
|
|
|
|
PROFILE_END_UPDATE(*cache_time, stime);
|
2018-03-17 04:47:26 +01:00
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_stats_begin();
|
2017-07-26 19:57:46 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_framebuffer_bind(DST.default_framebuffer);
|
2018-03-25 17:46:48 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Start Drawing */
|
|
|
|
DRW_state_reset();
|
2017-12-20 15:28:12 -02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_hair_update();
|
2018-06-13 22:20:48 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_draw_background();
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_framebuffer_bind(DST.default_framebuffer);
|
2018-08-22 15:22:54 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_draw_callbacks_pre_scene();
|
|
|
|
if (DST.draw_ctx.evil_C) {
|
|
|
|
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_PRE_VIEW);
|
|
|
|
}
|
2017-04-26 00:35:08 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_draw_scene();
|
2017-04-26 00:35:08 +10:00
|
|
|
|
2019-05-06 12:41:55 +02:00
|
|
|
/* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_flush();
|
2018-12-02 22:33:31 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* annotations - temporary drawing buffer (3d space) */
|
|
|
|
/* XXX: Or should we use a proper draw/overlay engine for this case? */
|
|
|
|
if (do_annotations) {
|
|
|
|
GPU_depth_test(false);
|
|
|
|
/* XXX: as scene->gpd is not copied for COW yet */
|
|
|
|
ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, true);
|
|
|
|
GPU_depth_test(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
DRW_draw_callbacks_post_scene();
|
2019-05-17 14:04:30 +02:00
|
|
|
DRW_state_reset();
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.draw_ctx.evil_C) {
|
2019-06-18 16:14:17 +02:00
|
|
|
GPU_depth_test(false);
|
2019-04-17 06:17:24 +02:00
|
|
|
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
|
2019-06-18 16:14:17 +02:00
|
|
|
GPU_depth_test(true);
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Callback can be nasty and do whatever they want with the state.
|
|
|
|
* Don't trust them! */
|
|
|
|
DRW_state_reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
drw_debug_draw();
|
|
|
|
|
|
|
|
GPU_depth_test(false);
|
|
|
|
drw_engines_draw_text();
|
|
|
|
GPU_depth_test(true);
|
|
|
|
|
|
|
|
if (DST.draw_ctx.evil_C) {
|
|
|
|
/* needed so gizmo isn't obscured */
|
|
|
|
if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
DRW_draw_gizmo_3d();
|
|
|
|
}
|
|
|
|
|
|
|
|
DRW_draw_region_info();
|
|
|
|
|
|
|
|
/* annotations - temporary drawing buffer (screenspace) */
|
|
|
|
/* XXX: Or should we use a proper draw/overlay engine for this case? */
|
|
|
|
if (((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && (do_annotations)) {
|
|
|
|
GPU_depth_test(false);
|
|
|
|
/* XXX: as scene->gpd is not copied for COW yet */
|
|
|
|
ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, ar, false);
|
|
|
|
GPU_depth_test(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((v3d->gizmo_flag & V3D_GIZMO_HIDE) == 0) {
|
|
|
|
/* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
|
|
|
|
* 'DRW_draw_region_info' sets the projection in pixel-space. */
|
|
|
|
GPU_depth_test(false);
|
|
|
|
DRW_draw_gizmo_2d();
|
|
|
|
GPU_depth_test(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DRW_stats_reset();
|
|
|
|
|
|
|
|
if (G.debug_value > 20 && G.debug_value < 30) {
|
|
|
|
GPU_depth_test(false);
|
|
|
|
rcti rect; /* local coordinate visible rect inside region, to accommodate overlapping ui */
|
|
|
|
ED_region_visible_rect(DST.draw_ctx.ar, &rect);
|
|
|
|
DRW_stats_draw(&rect);
|
|
|
|
GPU_depth_test(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WM_draw_region_get_bound_viewport(ar)) {
|
|
|
|
/* Don't unbind the framebuffer yet in this case and let
|
|
|
|
* GPU_viewport_unbind do it, so that we can still do further
|
|
|
|
* drawing of action zones on top. */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
GPU_framebuffer_restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
DRW_state_reset();
|
|
|
|
drw_engines_disable();
|
|
|
|
|
|
|
|
drw_viewport_cache_resize();
|
2017-11-06 16:47:23 +01:00
|
|
|
|
2017-06-06 16:19:07 +02:00
|
|
|
#ifdef DEBUG
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Avoid accidental reuse. */
|
|
|
|
drw_state_ensure_not_reused(&DST);
|
2017-06-06 16:19:07 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
void DRW_draw_render_loop(struct Depsgraph *depsgraph,
|
|
|
|
ARegion *ar,
|
|
|
|
View3D *v3d,
|
|
|
|
GPUViewport *viewport)
|
2017-06-06 16:19:07 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
2017-10-16 17:15:03 -02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
|
2017-10-16 17:15:03 -02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, NULL);
|
2017-03-08 20:00:09 +01:00
|
|
|
}
|
|
|
|
|
2018-01-05 10:18:44 +01:00
|
|
|
/* @viewport CAN be NULL, in this case we create one. */
|
2019-04-17 06:17:24 +02:00
|
|
|
void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
|
|
|
|
RenderEngineType *engine_type,
|
|
|
|
ARegion *ar,
|
|
|
|
View3D *v3d,
|
|
|
|
const bool draw_background,
|
|
|
|
const bool do_color_management,
|
|
|
|
GPUOffScreen *ofs,
|
|
|
|
GPUViewport *viewport)
|
|
|
|
{
|
|
|
|
/* Create temporary viewport if needed. */
|
|
|
|
GPUViewport *render_viewport = viewport;
|
|
|
|
if (viewport == NULL) {
|
|
|
|
render_viewport = GPU_viewport_create_from_offscreen(ofs);
|
|
|
|
}
|
|
|
|
|
|
|
|
GPU_framebuffer_restore();
|
|
|
|
|
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
2019-05-21 12:00:48 +02:00
|
|
|
DST.options.is_image_render = true;
|
|
|
|
DST.options.do_color_management = do_color_management;
|
2019-04-17 06:17:24 +02:00
|
|
|
DST.options.draw_background = draw_background;
|
|
|
|
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, render_viewport, NULL);
|
|
|
|
|
|
|
|
/* Free temporary viewport. */
|
|
|
|
if (viewport == NULL) {
|
|
|
|
/* don't free data owned by 'ofs' */
|
|
|
|
GPU_viewport_clear_from_offscreen(render_viewport);
|
|
|
|
GPU_viewport_free(render_viewport);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we need to re-bind (annoying!) */
|
|
|
|
GPU_offscreen_bind(ofs, false);
|
2017-05-03 02:50:29 +10:00
|
|
|
}
|
|
|
|
|
2018-11-09 16:30:44 +01:00
|
|
|
/* Helper to check if exit object type to render. */
|
|
|
|
bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
|
2018-07-31 10:22:19 +02:00
|
|
|
{
|
2019-05-28 09:11:55 +02:00
|
|
|
if (!drw_gpencil_engine_needed(depsgraph, NULL)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
|
|
|
if (ob->type == OB_GPENCIL) {
|
|
|
|
if (DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
return false;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
static void DRW_render_gpencil_to_image(RenderEngine *engine,
|
|
|
|
struct RenderLayer *render_layer,
|
|
|
|
const rcti *rect)
|
2018-07-31 10:22:19 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (draw_engine_gpencil_type.render_to_image) {
|
|
|
|
ViewportEngineData *gpdata = drw_viewport_engine_data_ensure(&draw_engine_gpencil_type);
|
|
|
|
draw_engine_gpencil_type.render_to_image(gpdata, engine, render_layer, rect);
|
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph)
|
|
|
|
{
|
2019-05-07 15:01:12 +02:00
|
|
|
/* This function is only valid for Cycles & Workbench
|
|
|
|
* Eevee does all work in the Eevee render directly.
|
|
|
|
* Maybe it can be done equal for all engines?
|
2019-04-17 06:17:24 +02:00
|
|
|
*/
|
|
|
|
if (STREQ(engine->type->name, "Eevee")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Early out if there are no grease pencil objects, especially important
|
|
|
|
* to avoid failing in in background renders without OpenGL context. */
|
|
|
|
if (!DRW_render_check_grease_pencil(depsgraph)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
RenderEngineType *engine_type = engine->type;
|
|
|
|
RenderData *r = &scene->r;
|
|
|
|
Render *render = engine->re;
|
|
|
|
/* Changing Context */
|
|
|
|
if (G.background && DST.gl_context == NULL) {
|
|
|
|
WM_init_opengl(G_MAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *re_gl_context = RE_gl_context_get(render);
|
|
|
|
void *re_gpu_context = NULL;
|
|
|
|
|
|
|
|
/* Changing Context */
|
|
|
|
if (re_gl_context != NULL) {
|
|
|
|
DRW_opengl_render_context_enable(re_gl_context);
|
|
|
|
/* We need to query gpu context after a gl context has been bound. */
|
|
|
|
re_gpu_context = RE_gpu_context_get(render);
|
|
|
|
DRW_gawain_render_context_enable(re_gpu_context);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DRW_opengl_context_enable();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
DST.options.is_image_render = true;
|
|
|
|
DST.options.is_scene_render = true;
|
|
|
|
DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
|
|
|
|
DST.buffer_finish_called = true;
|
|
|
|
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.engine_type = engine_type,
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
.object_mode = OB_MODE_OBJECT,
|
|
|
|
};
|
|
|
|
drw_context_state_init();
|
|
|
|
|
|
|
|
DST.viewport = GPU_viewport_create();
|
|
|
|
const int size[2] = {(r->size * r->xsch) / 100, (r->size * r->ysch) / 100};
|
|
|
|
GPU_viewport_size_set(DST.viewport, size);
|
|
|
|
|
|
|
|
drw_viewport_var_init();
|
|
|
|
|
|
|
|
/* Main rendering. */
|
|
|
|
rctf view_rect;
|
|
|
|
rcti render_rect;
|
|
|
|
RE_GetViewPlane(render, &view_rect, &render_rect);
|
|
|
|
if (BLI_rcti_is_empty(&render_rect)) {
|
|
|
|
BLI_rcti_init(&render_rect, 0, size[0], 0, size[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderResult *render_result = RE_engine_get_result(engine);
|
2019-05-07 15:01:12 +02:00
|
|
|
RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
|
|
|
|
|
|
|
|
/* Force cache to reset. */
|
|
|
|
drw_viewport_cache_resize();
|
|
|
|
GPU_viewport_free(DST.viewport);
|
|
|
|
DRW_state_reset();
|
|
|
|
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
|
|
|
|
/* Restore Drawing area. */
|
|
|
|
GPU_framebuffer_restore();
|
|
|
|
|
|
|
|
/* Changing Context */
|
|
|
|
/* GPXX Review this context */
|
|
|
|
DRW_opengl_context_disable();
|
|
|
|
|
|
|
|
DST.buffer_finish_called = false;
|
2018-07-31 10:22:19 +02:00
|
|
|
}
|
|
|
|
|
2019-07-04 15:44:49 +02:00
|
|
|
static void drw_view_reset(void)
|
2019-07-03 09:01:17 +02:00
|
|
|
{
|
|
|
|
DST.view_default = NULL;
|
|
|
|
DST.view_active = NULL;
|
|
|
|
DST.view_previous = NULL;
|
|
|
|
}
|
|
|
|
|
2018-02-20 10:14:23 -03:00
|
|
|
void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
|
2018-01-29 14:56:16 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
RenderEngineType *engine_type = engine->type;
|
|
|
|
DrawEngineType *draw_engine_type = engine_type->draw_engine;
|
|
|
|
Render *render = engine->re;
|
|
|
|
|
|
|
|
if (G.background && DST.gl_context == NULL) {
|
|
|
|
WM_init_opengl(G_MAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *re_gl_context = RE_gl_context_get(render);
|
|
|
|
void *re_gpu_context = NULL;
|
|
|
|
|
|
|
|
/* Changing Context */
|
|
|
|
if (re_gl_context != NULL) {
|
|
|
|
DRW_opengl_render_context_enable(re_gl_context);
|
|
|
|
/* We need to query gpu context after a gl context has been bound. */
|
|
|
|
re_gpu_context = RE_gpu_context_get(render);
|
|
|
|
DRW_gawain_render_context_enable(re_gpu_context);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DRW_opengl_context_enable();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* IMPORTANT: We dont support immediate mode in render mode!
|
|
|
|
* This shall remain in effect until immediate mode supports
|
|
|
|
* multiple threads. */
|
|
|
|
|
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
DST.options.is_image_render = true;
|
|
|
|
DST.options.is_scene_render = true;
|
|
|
|
DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
|
|
|
|
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.engine_type = engine_type,
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
.object_mode = OB_MODE_OBJECT,
|
|
|
|
};
|
|
|
|
drw_context_state_init();
|
|
|
|
|
|
|
|
DST.viewport = GPU_viewport_create();
|
|
|
|
const int size[2] = {engine->resolution_x, engine->resolution_y};
|
|
|
|
GPU_viewport_size_set(DST.viewport, size);
|
|
|
|
|
|
|
|
drw_viewport_var_init();
|
|
|
|
|
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type);
|
|
|
|
|
|
|
|
/* set default viewport */
|
|
|
|
glViewport(0, 0, size[0], size[1]);
|
|
|
|
|
|
|
|
/* Main rendering. */
|
|
|
|
rctf view_rect;
|
|
|
|
rcti render_rect;
|
|
|
|
RE_GetViewPlane(render, &view_rect, &render_rect);
|
|
|
|
if (BLI_rcti_is_empty(&render_rect)) {
|
|
|
|
BLI_rcti_init(&render_rect, 0, size[0], 0, size[1]);
|
|
|
|
}
|
|
|
|
|
2019-06-07 10:23:16 +02:00
|
|
|
/* Set the default Blender draw state */
|
|
|
|
GPU_state_init();
|
2019-06-19 16:20:02 +02:00
|
|
|
/* Reset state before drawing */
|
|
|
|
DRW_state_reset();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/* Init render result. */
|
|
|
|
RenderResult *render_result = RE_engine_begin_result(engine,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(int)size[0],
|
|
|
|
(int)size[1],
|
|
|
|
view_layer->name,
|
|
|
|
/* RR_ALL_VIEWS */ NULL);
|
|
|
|
|
|
|
|
RenderLayer *render_layer = render_result->layers.first;
|
|
|
|
for (RenderView *render_view = render_result->views.first; render_view != NULL;
|
|
|
|
render_view = render_view->next) {
|
|
|
|
RE_SetActiveRenderView(render, render_view->name);
|
2019-07-03 09:01:17 +02:00
|
|
|
drw_view_reset();
|
2019-04-17 06:17:24 +02:00
|
|
|
engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect);
|
|
|
|
/* grease pencil: render result is merged in the previous render result. */
|
|
|
|
if (DRW_render_check_grease_pencil(depsgraph)) {
|
|
|
|
DRW_state_reset();
|
2019-07-03 09:01:17 +02:00
|
|
|
drw_view_reset();
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
|
|
|
|
}
|
|
|
|
DST.buffer_finish_called = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
RE_engine_end_result(engine, render_result, false, false, false);
|
|
|
|
|
|
|
|
/* Force cache to reset. */
|
|
|
|
drw_viewport_cache_resize();
|
|
|
|
|
|
|
|
GPU_viewport_free(DST.viewport);
|
|
|
|
GPU_framebuffer_restore();
|
2018-01-29 14:56:16 +01:00
|
|
|
|
2018-06-14 12:01:18 +02:00
|
|
|
#ifdef DEBUG
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Avoid accidental reuse. */
|
|
|
|
drw_state_ensure_not_reused(&DST);
|
2018-06-14 12:01:18 +02:00
|
|
|
#endif
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Reset state after drawing */
|
|
|
|
DRW_state_reset();
|
2019-03-12 15:53:10 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Changing Context */
|
|
|
|
if (re_gl_context != NULL) {
|
|
|
|
DRW_gawain_render_context_disable(re_gpu_context);
|
|
|
|
DRW_opengl_render_context_disable(re_gl_context);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DRW_opengl_context_disable();
|
|
|
|
}
|
2018-01-29 14:56:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_render_object_iter(
|
2019-04-17 06:17:24 +02:00
|
|
|
void *vedata,
|
|
|
|
RenderEngine *engine,
|
|
|
|
struct Depsgraph *depsgraph,
|
|
|
|
void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
|
|
|
|
{
|
|
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
|
|
|
|
|
|
DRW_hair_init();
|
|
|
|
|
|
|
|
const int object_type_exclude_viewport = draw_ctx->v3d ?
|
|
|
|
draw_ctx->v3d->object_type_exclude_viewport :
|
|
|
|
0;
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
2019-04-17 06:17:24 +02:00
|
|
|
if ((object_type_exclude_viewport & (1 << ob->type)) == 0) {
|
|
|
|
DST.dupli_parent = data_.dupli_parent;
|
|
|
|
DST.dupli_source = data_.dupli_object_current;
|
|
|
|
DST.ob_state = NULL;
|
2019-05-08 12:02:49 +02:00
|
|
|
drw_duplidata_load(DST.dupli_source);
|
2019-05-07 23:21:16 +02:00
|
|
|
|
2019-05-08 12:02:49 +02:00
|
|
|
if (!DST.dupli_source) {
|
|
|
|
drw_batch_cache_validate(ob);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
callback(vedata, ob, engine, depsgraph);
|
2019-05-08 12:02:49 +02:00
|
|
|
if (!DST.dupli_source) {
|
|
|
|
drw_batch_cache_generate_requested(ob);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
}
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
2019-05-08 12:02:49 +02:00
|
|
|
|
|
|
|
drw_duplidata_free();
|
2018-01-29 14:56:16 +01:00
|
|
|
}
|
|
|
|
|
2018-09-19 18:19:49 +02:00
|
|
|
/* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired).
|
2018-07-10 14:40:28 +02:00
|
|
|
* This function only setup DST and execute the given function.
|
|
|
|
* Warning: similar to DRW_render_to_image you cannot use default lists (dfbl & dtxl). */
|
2019-04-17 06:17:24 +02:00
|
|
|
void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
|
|
|
|
struct Depsgraph *depsgraph,
|
|
|
|
void (*callback)(void *vedata, void *user_data),
|
|
|
|
void *user_data)
|
2018-07-10 14:40:28 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
DST.options.is_image_render = true;
|
|
|
|
DST.options.is_scene_render = true;
|
|
|
|
DST.options.draw_background = false;
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.engine_type = NULL,
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
.object_mode = OB_MODE_OBJECT,
|
|
|
|
};
|
|
|
|
drw_context_state_init();
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DST.viewport = GPU_viewport_create();
|
|
|
|
const int size[2] = {1, 1};
|
|
|
|
GPU_viewport_size_set(DST.viewport, size);
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_viewport_var_init();
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_hair_init();
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type);
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Execute the callback */
|
|
|
|
callback(data, user_data);
|
|
|
|
DST.buffer_finish_called = false;
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_viewport_free(DST.viewport);
|
|
|
|
GPU_framebuffer_restore();
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* The use of custom pipeline in other thread using the same
|
|
|
|
* resources as the main thread (viewport) may lead to data
|
|
|
|
* races and undefined behavior on certain drivers. Using
|
|
|
|
* GPU_finish to sync seems to fix the issue. (see T62997) */
|
|
|
|
GPU_finish();
|
2019-03-27 19:15:23 +01:00
|
|
|
|
2018-07-10 14:40:28 +02:00
|
|
|
#ifdef DEBUG
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Avoid accidental reuse. */
|
|
|
|
drw_state_ensure_not_reused(&DST);
|
2018-07-10 14:40:28 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-02-26 19:41:17 +01:00
|
|
|
static struct DRWSelectBuffer {
|
2019-04-17 06:17:24 +02:00
|
|
|
struct GPUFrameBuffer *framebuffer_depth_only;
|
|
|
|
struct GPUTexture *texture_depth;
|
2018-02-26 19:41:17 +01:00
|
|
|
} g_select_buffer = {NULL};
|
|
|
|
|
2019-03-21 17:02:41 -03:00
|
|
|
static void draw_select_framebuffer_depth_only_setup(const int size[2])
|
2018-02-26 19:41:17 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (g_select_buffer.framebuffer_depth_only == NULL) {
|
|
|
|
g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create();
|
|
|
|
}
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if ((g_select_buffer.texture_depth != NULL) &&
|
|
|
|
((GPU_texture_width(g_select_buffer.texture_depth) != size[0]) ||
|
|
|
|
(GPU_texture_height(g_select_buffer.texture_depth) != size[1]))) {
|
|
|
|
GPU_texture_free(g_select_buffer.texture_depth);
|
|
|
|
g_select_buffer.texture_depth = NULL;
|
|
|
|
}
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (g_select_buffer.texture_depth == NULL) {
|
|
|
|
g_select_buffer.texture_depth = GPU_texture_create_2d(
|
|
|
|
size[0], size[1], GPU_DEPTH_COMPONENT24, NULL, NULL);
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_framebuffer_texture_attach(
|
|
|
|
g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0);
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_framebuffer_check_valid(g_select_buffer.framebuffer_depth_only, NULL);
|
|
|
|
}
|
2018-02-26 19:41:17 +01:00
|
|
|
}
|
|
|
|
|
2018-02-14 18:59:15 +01:00
|
|
|
/* Must run after all instance datas have been added. */
|
|
|
|
void DRW_render_instance_buffer_finish(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!");
|
|
|
|
DST.buffer_finish_called = true;
|
|
|
|
DRW_instance_buffer_finish(DST.idatalist);
|
2018-02-14 18:59:15 +01:00
|
|
|
}
|
|
|
|
|
2017-04-26 04:39:25 +10:00
|
|
|
/**
|
|
|
|
* object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
|
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
void DRW_draw_select_loop(struct Depsgraph *depsgraph,
|
|
|
|
ARegion *ar,
|
|
|
|
View3D *v3d,
|
|
|
|
bool UNUSED(use_obedit_skip),
|
|
|
|
bool draw_surface,
|
|
|
|
bool UNUSED(use_nearest),
|
|
|
|
const rcti *rect,
|
|
|
|
DRW_SelectPassFn select_pass_fn,
|
|
|
|
void *select_pass_user_data,
|
|
|
|
DRW_ObjectFilterFn object_filter_fn,
|
|
|
|
void *object_filter_user_data)
|
|
|
|
{
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
Object *obact = OBACT(view_layer);
|
|
|
|
Object *obedit = OBEDIT_FROM_OBACT(obact);
|
2017-04-26 04:39:25 +10:00
|
|
|
#ifndef USE_GPU_SELECT
|
2019-04-17 06:17:24 +02:00
|
|
|
UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect);
|
2018-04-16 16:27:55 +02:00
|
|
|
#else
|
2019-04-17 06:17:24 +02:00
|
|
|
RegionView3D *rv3d = ar->regiondata;
|
|
|
|
|
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
|
|
|
|
bool use_obedit = false;
|
|
|
|
int obedit_mode = 0;
|
|
|
|
if (obedit != NULL) {
|
|
|
|
if (obedit->type == OB_MBALL) {
|
|
|
|
use_obedit = true;
|
|
|
|
obedit_mode = CTX_MODE_EDIT_METABALL;
|
|
|
|
}
|
|
|
|
else if (obedit->type == OB_ARMATURE) {
|
|
|
|
use_obedit = true;
|
|
|
|
obedit_mode = CTX_MODE_EDIT_ARMATURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) {
|
|
|
|
if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) {
|
|
|
|
/* Note: don't use "BKE_object_pose_armature_get" here, it breaks selection. */
|
|
|
|
Object *obpose = OBPOSE_FROM_OBACT(obact);
|
|
|
|
if (obpose) {
|
|
|
|
use_obedit = true;
|
|
|
|
obedit_mode = CTX_MODE_POSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int viewport_size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)};
|
|
|
|
struct GPUViewport *viewport = GPU_viewport_create();
|
|
|
|
GPU_viewport_size_set(viewport, viewport_size);
|
|
|
|
|
|
|
|
DST.viewport = viewport;
|
|
|
|
DST.options.is_select = true;
|
|
|
|
|
|
|
|
/* Get list of enabled engines */
|
|
|
|
if (use_obedit) {
|
|
|
|
drw_engines_enable_from_paint_mode(obedit_mode);
|
|
|
|
drw_engines_enable_from_mode(obedit_mode);
|
|
|
|
}
|
|
|
|
else if (!draw_surface) {
|
|
|
|
/* grease pencil selection */
|
|
|
|
use_drw_engine(&draw_engine_gpencil_type);
|
|
|
|
|
|
|
|
drw_engines_enable_from_overlays(v3d->overlay.flag);
|
|
|
|
drw_engines_enable_from_object_mode();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
drw_engines_enable_basic();
|
|
|
|
/* grease pencil selection */
|
|
|
|
use_drw_engine(&draw_engine_gpencil_type);
|
|
|
|
|
|
|
|
drw_engines_enable_from_overlays(v3d->overlay.flag);
|
|
|
|
drw_engines_enable_from_object_mode();
|
|
|
|
}
|
2019-06-17 23:07:41 +02:00
|
|
|
drw_engines_data_validate();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
|
|
|
/* Setup viewport */
|
|
|
|
|
|
|
|
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.ar = ar,
|
|
|
|
.rv3d = rv3d,
|
|
|
|
.v3d = v3d,
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.obact = obact,
|
|
|
|
.engine_type = engine_type,
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
};
|
|
|
|
drw_context_state_init();
|
|
|
|
drw_viewport_var_init();
|
|
|
|
|
|
|
|
/* Update ubos */
|
|
|
|
DRW_globals_update();
|
|
|
|
|
|
|
|
/* Init engines */
|
|
|
|
drw_engines_init();
|
|
|
|
DRW_hair_init();
|
|
|
|
|
|
|
|
{
|
|
|
|
drw_engines_cache_init();
|
|
|
|
drw_engines_world_update(scene);
|
|
|
|
|
|
|
|
if (use_obedit) {
|
|
|
|
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
|
|
|
|
drw_engines_cache_populate(ob_iter);
|
|
|
|
}
|
|
|
|
FOREACH_OBJECT_IN_MODE_END;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const int object_type_exclude_select = (v3d->object_type_exclude_viewport |
|
|
|
|
v3d->object_type_exclude_select);
|
|
|
|
bool filter_exclude = false;
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) {
|
2019-04-17 06:17:24 +02:00
|
|
|
if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ob->base_flag & BASE_SELECTABLE) &&
|
|
|
|
(object_type_exclude_select & (1 << ob->type)) == 0) {
|
|
|
|
if (object_filter_fn != NULL) {
|
|
|
|
if (ob->base_flag & BASE_FROM_DUPLI) {
|
|
|
|
/* pass (use previous filter_exclude value) */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
filter_exclude = (object_filter_fn(ob, object_filter_user_data) == false);
|
|
|
|
}
|
|
|
|
if (filter_exclude) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This relies on dupli instances being after their instancing object. */
|
|
|
|
if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
|
|
|
|
Object *ob_orig = DEG_get_original_object(ob);
|
2019-05-08 09:45:20 +02:00
|
|
|
DRW_select_load_id(ob_orig->runtime.select_id);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
DST.dupli_parent = data_.dupli_parent;
|
|
|
|
DST.dupli_source = data_.dupli_object_current;
|
2019-05-07 20:56:20 +02:00
|
|
|
drw_duplidata_load(DST.dupli_source);
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_cache_populate(ob);
|
|
|
|
}
|
|
|
|
}
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-05-07 20:56:20 +02:00
|
|
|
drw_duplidata_free();
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_cache_finish();
|
|
|
|
|
|
|
|
DRW_render_instance_buffer_finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup framebuffer */
|
|
|
|
draw_select_framebuffer_depth_only_setup(viewport_size);
|
|
|
|
GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only);
|
|
|
|
GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f);
|
|
|
|
|
|
|
|
/* Start Drawing */
|
|
|
|
DRW_state_reset();
|
|
|
|
DRW_draw_callbacks_pre_scene();
|
|
|
|
|
|
|
|
DRW_hair_update();
|
|
|
|
|
|
|
|
DRW_state_lock(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_DEPTH_LESS_EQUAL |
|
|
|
|
DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_ALWAYS);
|
|
|
|
|
|
|
|
/* Only 1-2 passes. */
|
|
|
|
while (true) {
|
|
|
|
if (!select_pass_fn(DRW_SELECT_PASS_PRE, select_pass_user_data)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
drw_engines_draw_scene();
|
|
|
|
|
|
|
|
if (!select_pass_fn(DRW_SELECT_PASS_POST, select_pass_user_data)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-05 23:11:53 +02:00
|
|
|
/* TODO: GPXX Workaround for grease pencil selection while draw manager support a callback from
|
|
|
|
* scene finish */
|
|
|
|
void *data = GPU_viewport_engine_data_get(DST.viewport, &draw_engine_gpencil_type);
|
|
|
|
if (data != NULL) {
|
|
|
|
DRW_gpencil_free_runtime_data(data);
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_state_lock(0);
|
|
|
|
|
|
|
|
DRW_draw_callbacks_post_scene();
|
|
|
|
|
|
|
|
DRW_state_reset();
|
|
|
|
drw_engines_disable();
|
|
|
|
|
|
|
|
# ifdef DEBUG
|
|
|
|
/* Avoid accidental reuse. */
|
|
|
|
drw_state_ensure_not_reused(&DST);
|
|
|
|
# endif
|
|
|
|
GPU_framebuffer_restore();
|
|
|
|
|
|
|
|
/* Cleanup for selection state */
|
|
|
|
GPU_viewport_free(viewport);
|
|
|
|
#endif /* USE_GPU_SELECT */
|
2017-04-26 04:39:25 +10:00
|
|
|
}
|
|
|
|
|
2017-04-27 01:43:05 +10:00
|
|
|
/**
|
|
|
|
* object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
|
|
|
|
*/
|
2019-03-27 10:52:13 -03:00
|
|
|
static void drw_draw_depth_loop_imp(void)
|
2017-04-27 01:43:05 +10:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Setup framebuffer */
|
|
|
|
DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(
|
|
|
|
DST.viewport);
|
|
|
|
GPU_framebuffer_bind(fbl->depth_only_fb);
|
|
|
|
GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f);
|
2019-03-26 12:19:00 -03:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Setup viewport */
|
|
|
|
drw_context_state_init();
|
|
|
|
drw_viewport_var_init();
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Update ubos */
|
|
|
|
DRW_globals_update();
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Init engines */
|
|
|
|
drw_engines_init();
|
|
|
|
DRW_hair_init();
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
{
|
|
|
|
drw_engines_cache_init();
|
|
|
|
drw_engines_world_update(DST.draw_ctx.scene);
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
View3D *v3d = DST.draw_ctx.v3d;
|
|
|
|
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (DST.draw_ctx.depsgraph, ob) {
|
2019-04-17 06:17:24 +02:00
|
|
|
if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2018-11-25 09:50:34 -02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
|
|
|
|
continue;
|
|
|
|
}
|
2018-11-25 09:50:34 -02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DST.dupli_parent = data_.dupli_parent;
|
|
|
|
DST.dupli_source = data_.dupli_object_current;
|
2019-05-07 20:56:20 +02:00
|
|
|
drw_duplidata_load(DST.dupli_source);
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_cache_populate(ob);
|
|
|
|
}
|
2019-05-28 09:11:55 +02:00
|
|
|
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-05-07 20:56:20 +02:00
|
|
|
drw_duplidata_free();
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_cache_finish();
|
2018-02-14 18:59:15 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_render_instance_buffer_finish();
|
|
|
|
}
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Start Drawing */
|
|
|
|
DRW_state_reset();
|
2018-06-13 22:20:48 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_hair_update();
|
2018-06-13 22:20:48 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_draw_callbacks_pre_scene();
|
|
|
|
drw_engines_draw_scene();
|
|
|
|
DRW_draw_callbacks_post_scene();
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_state_reset();
|
2017-04-27 01:43:05 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* TODO: Reading depth for operators should be done here. */
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_framebuffer_restore();
|
2019-03-27 10:52:13 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
|
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
|
|
|
|
ARegion *ar,
|
|
|
|
View3D *v3d,
|
|
|
|
GPUViewport *viewport)
|
|
|
|
{
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
RegionView3D *rv3d = ar->regiondata;
|
|
|
|
|
2019-05-11 19:13:54 +02:00
|
|
|
DRW_opengl_context_enable();
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
|
|
|
|
DST.viewport = viewport;
|
|
|
|
DST.options.is_depth = true;
|
|
|
|
|
|
|
|
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.ar = ar,
|
|
|
|
.rv3d = rv3d,
|
|
|
|
.v3d = v3d,
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.obact = OBACT(view_layer),
|
|
|
|
.engine_type = engine_type,
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Get list of enabled engines */
|
|
|
|
{
|
|
|
|
drw_engines_enable_basic();
|
|
|
|
if (DRW_state_draw_support()) {
|
|
|
|
drw_engines_enable_from_object_mode();
|
|
|
|
}
|
2019-06-17 23:07:41 +02:00
|
|
|
drw_engines_data_validate();
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
drw_draw_depth_loop_imp();
|
|
|
|
|
|
|
|
drw_engines_disable();
|
|
|
|
|
2019-03-27 11:05:48 -03:00
|
|
|
#ifdef DEBUG
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Avoid accidental reuse. */
|
|
|
|
drw_state_ensure_not_reused(&DST);
|
2019-03-27 11:05:48 -03:00
|
|
|
#endif
|
2019-05-11 19:13:54 +02:00
|
|
|
|
|
|
|
/* Changin context */
|
|
|
|
DRW_opengl_context_disable();
|
2017-04-27 01:43:05 +10:00
|
|
|
}
|
|
|
|
|
2019-03-27 10:52:13 -03:00
|
|
|
/**
|
|
|
|
* Converted from ED_view3d_draw_depth_gpencil (legacy drawing).
|
|
|
|
*/
|
2019-04-17 06:17:24 +02:00
|
|
|
void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
|
|
|
|
ARegion *ar,
|
|
|
|
View3D *v3d,
|
|
|
|
GPUViewport *viewport)
|
|
|
|
{
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
RegionView3D *rv3d = ar->regiondata;
|
|
|
|
|
2019-05-11 19:13:54 +02:00
|
|
|
DRW_opengl_context_enable();
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
|
|
|
|
DST.viewport = viewport;
|
|
|
|
DST.options.is_depth = true;
|
|
|
|
|
|
|
|
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.ar = ar,
|
|
|
|
.rv3d = rv3d,
|
|
|
|
.v3d = v3d,
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.obact = OBACT(view_layer),
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
};
|
|
|
|
|
|
|
|
use_drw_engine(&draw_engine_gpencil_type);
|
2019-06-17 23:07:41 +02:00
|
|
|
drw_engines_data_validate();
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_draw_depth_loop_imp();
|
2019-06-17 23:07:41 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
drw_engines_disable();
|
2019-03-27 10:52:13 -03:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Avoid accidental reuse. */
|
|
|
|
drw_state_ensure_not_reused(&DST);
|
2019-03-27 10:52:13 -03:00
|
|
|
#endif
|
2019-05-11 19:13:54 +02:00
|
|
|
|
|
|
|
/* Changin context */
|
|
|
|
DRW_opengl_context_disable();
|
2019-03-27 10:52:13 -03:00
|
|
|
}
|
|
|
|
|
2019-07-30 06:46:59 -03:00
|
|
|
void DRW_draw_select_id(Depsgraph *depsgraph,
|
|
|
|
ARegion *ar,
|
|
|
|
View3D *v3d,
|
|
|
|
Base **bases,
|
|
|
|
const uint bases_len,
|
|
|
|
short select_mode)
|
|
|
|
{
|
|
|
|
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
|
|
|
|
|
|
|
DRW_select_context_create(depsgraph, bases, bases_len, select_mode);
|
|
|
|
|
|
|
|
DRW_opengl_context_enable();
|
|
|
|
|
|
|
|
/* Reset before using it. */
|
|
|
|
drw_state_prepare_clean_for_draw(&DST);
|
|
|
|
DST.buffer_finish_called = true;
|
|
|
|
|
|
|
|
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
|
|
|
|
DST.draw_ctx = (DRWContextState){
|
|
|
|
.ar = ar,
|
|
|
|
.rv3d = ar->regiondata,
|
|
|
|
.v3d = v3d,
|
|
|
|
.scene = scene,
|
|
|
|
.view_layer = view_layer,
|
|
|
|
.obact = OBACT(view_layer),
|
|
|
|
.depsgraph = depsgraph,
|
|
|
|
};
|
|
|
|
|
|
|
|
use_drw_engine(&draw_engine_select_type);
|
|
|
|
drw_context_state_init();
|
|
|
|
|
|
|
|
/* Setup viewport */
|
|
|
|
DST.viewport = WM_draw_region_get_viewport(ar, 0);
|
|
|
|
drw_viewport_var_init();
|
|
|
|
|
|
|
|
/* Update ubos */
|
|
|
|
DRW_globals_update();
|
|
|
|
|
|
|
|
/* Init engines */
|
|
|
|
drw_engines_init();
|
|
|
|
|
|
|
|
{
|
|
|
|
drw_engines_cache_init();
|
|
|
|
|
|
|
|
/* Keep `base_index` in sync with `e_data.context.last_base_drawn`.
|
|
|
|
* So don't skip objects. */
|
|
|
|
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
|
|
|
Object *obj_eval = DEG_get_evaluated_object(depsgraph, bases[base_index]->object);
|
|
|
|
drw_engines_cache_populate(obj_eval);
|
|
|
|
}
|
|
|
|
|
|
|
|
drw_engines_cache_finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start Drawing */
|
|
|
|
DRW_state_reset();
|
|
|
|
drw_engines_draw_scene();
|
|
|
|
DRW_state_reset();
|
|
|
|
|
|
|
|
drw_engines_disable();
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
/* Avoid accidental reuse. */
|
|
|
|
drw_state_ensure_not_reused(&DST);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Changin context */
|
|
|
|
GPU_framebuffer_restore();
|
|
|
|
DRW_opengl_context_disable();
|
|
|
|
}
|
|
|
|
|
2019-05-16 09:26:33 +10:00
|
|
|
/** See #DRW_shgroup_world_clip_planes_from_rv3d. */
|
|
|
|
static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
|
|
|
|
{
|
2019-05-31 00:28:03 +02:00
|
|
|
GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
|
2019-05-16 09:26:33 +10:00
|
|
|
}
|
|
|
|
|
2019-04-19 11:49:17 -03:00
|
|
|
/**
|
|
|
|
* Clears the Depth Buffer and draws only the specified object.
|
|
|
|
*/
|
2019-04-20 09:15:06 +02:00
|
|
|
void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
|
2019-04-19 11:49:17 -03:00
|
|
|
{
|
|
|
|
RegionView3D *rv3d = ar->regiondata;
|
|
|
|
|
|
|
|
DRW_opengl_context_enable();
|
|
|
|
|
|
|
|
/* Setup framebuffer */
|
|
|
|
DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport);
|
|
|
|
|
|
|
|
GPU_framebuffer_bind(fbl->depth_only_fb);
|
|
|
|
GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f);
|
|
|
|
GPU_depth_test(true);
|
|
|
|
GPU_matrix_mul(object->obmat);
|
|
|
|
|
|
|
|
const float(*world_clip_planes)[4] = NULL;
|
|
|
|
if (rv3d->rflag & RV3D_CLIPPING) {
|
|
|
|
ED_view3d_clipping_set(rv3d);
|
|
|
|
ED_view3d_clipping_local(rv3d, object->obmat);
|
|
|
|
world_clip_planes = rv3d->clip_local;
|
|
|
|
}
|
|
|
|
|
2019-07-01 15:45:16 +02:00
|
|
|
drw_batch_cache_validate(object);
|
|
|
|
|
2019-04-19 11:49:17 -03:00
|
|
|
switch (object->type) {
|
|
|
|
case OB_MESH: {
|
|
|
|
GPUBatch *batch;
|
|
|
|
|
|
|
|
Mesh *me = object->data;
|
|
|
|
|
|
|
|
if (object->mode & OB_MODE_EDIT) {
|
|
|
|
batch = DRW_mesh_batch_cache_get_edit_triangles(me);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
batch = DRW_mesh_batch_cache_get_surface(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
DRW_mesh_batch_cache_create_requested(object, me, NULL, false, true);
|
|
|
|
|
|
|
|
const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
|
|
|
|
GPU_SHADER_CFG_DEFAULT;
|
|
|
|
GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
|
|
|
|
if (world_clip_planes != NULL) {
|
2019-05-16 09:26:33 +10:00
|
|
|
draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
|
2019-04-19 11:49:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
GPU_batch_draw(batch);
|
|
|
|
} break;
|
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rv3d->rflag & RV3D_CLIPPING) {
|
|
|
|
ED_view3d_clipping_disable();
|
|
|
|
}
|
|
|
|
|
|
|
|
GPU_matrix_set(rv3d->viewmat);
|
|
|
|
GPU_depth_test(false);
|
|
|
|
GPU_framebuffer_restore();
|
|
|
|
DRW_opengl_context_disable();
|
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Draw Manager State (DRW_state)
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
void DRW_state_dfdy_factors_get(float dfdyfac[2])
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_get_dfdy_factors(dfdyfac);
|
2017-04-27 02:04:56 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When false, drawing doesn't output to a pixel buffer
|
|
|
|
* eg: Occlusion queries, or when we have setup a context to draw in already.
|
|
|
|
*/
|
|
|
|
bool DRW_state_is_fbo(void)
|
|
|
|
{
|
2019-05-11 00:21:27 +02:00
|
|
|
return ((DST.default_framebuffer != NULL) || DST.options.is_image_render) &&
|
|
|
|
!DRW_state_is_depth() && !DRW_state_is_select();
|
2017-04-27 02:04:56 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* For when engines need to know if this is drawing for selection or not.
|
|
|
|
*/
|
|
|
|
bool DRW_state_is_select(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.options.is_select;
|
2017-04-28 04:33:58 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DRW_state_is_depth(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.options.is_depth;
|
2017-04-28 04:33:58 +10:00
|
|
|
}
|
|
|
|
|
2017-06-20 18:33:58 +02:00
|
|
|
/**
|
|
|
|
* Whether we are rendering for an image
|
|
|
|
*/
|
|
|
|
bool DRW_state_is_image_render(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.options.is_image_render;
|
2017-06-20 18:33:58 +02:00
|
|
|
}
|
|
|
|
|
2019-05-21 12:00:48 +02:00
|
|
|
/**
|
|
|
|
* Whether the view transform should be applied.
|
|
|
|
*/
|
|
|
|
bool DRW_state_do_color_management(void)
|
|
|
|
{
|
|
|
|
return DST.options.do_color_management;
|
|
|
|
}
|
|
|
|
|
2017-06-20 18:33:58 +02:00
|
|
|
/**
|
|
|
|
* Whether we are rendering only the render engine,
|
|
|
|
* or if we should also render the mode engines.
|
|
|
|
*/
|
|
|
|
bool DRW_state_is_scene_render(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(DST.options.is_scene_render ? DST.options.is_image_render : true);
|
|
|
|
return DST.options.is_scene_render;
|
2017-06-20 18:33:58 +02:00
|
|
|
}
|
|
|
|
|
2018-02-16 16:52:08 +01:00
|
|
|
/**
|
2018-09-02 18:28:27 +10:00
|
|
|
* Whether we are rendering simple opengl render
|
|
|
|
*/
|
2018-02-16 16:52:08 +01:00
|
|
|
bool DRW_state_is_opengl_render(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.options.is_image_render && !DST.options.is_scene_render;
|
2018-02-16 16:52:08 +01:00
|
|
|
}
|
|
|
|
|
2018-12-04 15:39:30 +01:00
|
|
|
bool DRW_state_is_playback(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.draw_ctx.evil_C != NULL) {
|
|
|
|
struct wmWindowManager *wm = CTX_wm_manager(DST.draw_ctx.evil_C);
|
|
|
|
return ED_screen_animation_playing(wm) != NULL;
|
|
|
|
}
|
|
|
|
return false;
|
2018-12-04 15:39:30 +01:00
|
|
|
}
|
|
|
|
|
2017-04-28 04:33:58 +10:00
|
|
|
/**
|
|
|
|
* Should text draw in this mode?
|
|
|
|
*/
|
|
|
|
bool DRW_state_show_text(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return (DST.options.is_select) == 0 && (DST.options.is_depth) == 0 &&
|
|
|
|
(DST.options.is_scene_render) == 0 && (DST.options.draw_text) == 0;
|
2017-04-27 02:04:56 +10:00
|
|
|
}
|
|
|
|
|
2017-07-03 16:16:24 +02:00
|
|
|
/**
|
|
|
|
* Should draw support elements
|
|
|
|
* Objects center, selection outline, probe data, ...
|
|
|
|
*/
|
|
|
|
bool DRW_state_draw_support(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
View3D *v3d = DST.draw_ctx.v3d;
|
|
|
|
return (DRW_state_is_scene_render() == false) && (v3d != NULL) &&
|
|
|
|
((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0);
|
2017-07-03 16:16:24 +02:00
|
|
|
}
|
|
|
|
|
2017-12-20 15:28:12 -02:00
|
|
|
/**
|
|
|
|
* Whether we should render the background
|
|
|
|
*/
|
|
|
|
bool DRW_state_draw_background(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return DST.options.draw_background;
|
2017-12-20 15:28:12 -02:00
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Context State (DRW_context_state)
|
|
|
|
* \{ */
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2017-04-26 00:35:08 +10:00
|
|
|
const DRWContextState *DRW_context_state_get(void)
|
2017-03-08 20:00:09 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return &DST.draw_ctx;
|
2017-02-17 17:29:43 +01:00
|
|
|
}
|
|
|
|
|
2017-04-27 02:04:56 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Init/Exit (DRW_engines)
|
|
|
|
* \{ */
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2018-01-29 14:56:16 +01:00
|
|
|
bool DRW_engine_render_support(DrawEngineType *draw_engine_type)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
return draw_engine_type->render_to_image;
|
2018-01-29 14:56:16 +01:00
|
|
|
}
|
|
|
|
|
2017-03-08 20:00:09 +01:00
|
|
|
void DRW_engine_register(DrawEngineType *draw_engine_type)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_addtail(&DRW_engines, draw_engine_type);
|
2017-03-08 20:00:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_engines_register(void)
|
2017-02-07 11:20:15 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
RE_engines_register(&DRW_engine_viewport_eevee_type);
|
|
|
|
RE_engines_register(&DRW_engine_viewport_workbench_type);
|
2017-03-08 20:00:09 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_engine_register(&draw_engine_workbench_solid);
|
|
|
|
DRW_engine_register(&draw_engine_workbench_transparent);
|
2018-04-17 14:58:48 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_engine_register(&draw_engine_object_type);
|
|
|
|
DRW_engine_register(&draw_engine_edit_armature_type);
|
|
|
|
DRW_engine_register(&draw_engine_edit_curve_type);
|
|
|
|
DRW_engine_register(&draw_engine_edit_lattice_type);
|
|
|
|
DRW_engine_register(&draw_engine_edit_mesh_type);
|
|
|
|
DRW_engine_register(&draw_engine_edit_metaball_type);
|
|
|
|
DRW_engine_register(&draw_engine_edit_text_type);
|
|
|
|
DRW_engine_register(&draw_engine_motion_path_type);
|
|
|
|
DRW_engine_register(&draw_engine_overlay_type);
|
|
|
|
DRW_engine_register(&draw_engine_paint_texture_type);
|
|
|
|
DRW_engine_register(&draw_engine_paint_vertex_type);
|
|
|
|
DRW_engine_register(&draw_engine_particle_type);
|
|
|
|
DRW_engine_register(&draw_engine_pose_type);
|
|
|
|
DRW_engine_register(&draw_engine_sculpt_type);
|
|
|
|
DRW_engine_register(&draw_engine_gpencil_type);
|
2019-07-30 06:46:59 -03:00
|
|
|
DRW_engine_register(&draw_engine_select_type);
|
2017-04-21 21:14:11 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* setup callbacks */
|
|
|
|
{
|
|
|
|
BKE_mball_batch_cache_dirty_tag_cb = DRW_mball_batch_cache_dirty_tag;
|
|
|
|
BKE_mball_batch_cache_free_cb = DRW_mball_batch_cache_free;
|
2017-11-16 15:12:32 -02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BKE_curve_batch_cache_dirty_tag_cb = DRW_curve_batch_cache_dirty_tag;
|
|
|
|
BKE_curve_batch_cache_free_cb = DRW_curve_batch_cache_free;
|
2017-04-21 21:14:11 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BKE_mesh_batch_cache_dirty_tag_cb = DRW_mesh_batch_cache_dirty_tag;
|
|
|
|
BKE_mesh_batch_cache_free_cb = DRW_mesh_batch_cache_free;
|
2017-04-21 21:14:11 +10:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BKE_lattice_batch_cache_dirty_tag_cb = DRW_lattice_batch_cache_dirty_tag;
|
|
|
|
BKE_lattice_batch_cache_free_cb = DRW_lattice_batch_cache_free;
|
2017-05-09 16:23:47 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BKE_particle_batch_cache_dirty_tag_cb = DRW_particle_batch_cache_dirty_tag;
|
|
|
|
BKE_particle_batch_cache_free_cb = DRW_particle_batch_cache_free;
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BKE_gpencil_batch_cache_dirty_tag_cb = DRW_gpencil_batch_cache_dirty_tag;
|
|
|
|
BKE_gpencil_batch_cache_free_cb = DRW_gpencil_batch_cache_free;
|
|
|
|
}
|
2017-02-07 11:20:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_engines_free(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.gl_context == NULL) {
|
|
|
|
/* Nothing has been setup. Nothing to clear.
|
|
|
|
* Otherwise, DRW_opengl_context_enable can
|
|
|
|
* create a context in background mode. (see T62355) */
|
|
|
|
return;
|
|
|
|
}
|
2019-03-08 14:31:58 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_opengl_context_enable();
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
|
|
|
|
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_hair_free();
|
|
|
|
DRW_shape_cache_free();
|
|
|
|
DRW_stats_free();
|
|
|
|
DRW_globals_free();
|
2017-03-02 01:07:03 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DrawEngineType *next;
|
|
|
|
for (DrawEngineType *type = DRW_engines.first; type; type = next) {
|
|
|
|
next = type->next;
|
|
|
|
BLI_remlink(&R_engines, type);
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (type->engine_free) {
|
|
|
|
type->engine_free();
|
|
|
|
}
|
|
|
|
}
|
2017-02-07 11:20:15 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_UBO_FREE_SAFE(G_draw.block_ubo);
|
|
|
|
DRW_UBO_FREE_SAFE(G_draw.view_ubo);
|
|
|
|
DRW_TEXTURE_FREE_SAFE(G_draw.ramp);
|
|
|
|
DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp);
|
2018-02-14 18:59:15 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
MEM_SAFE_FREE(DST.uniform_names.buffer);
|
2019-01-17 18:33:08 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_opengl_context_disable();
|
2017-02-17 20:06:31 +01:00
|
|
|
}
|
2017-04-27 02:04:56 +10:00
|
|
|
|
|
|
|
/** \} */
|
2018-02-26 19:41:17 +01:00
|
|
|
|
|
|
|
/** \name Init/Exit (DRW_opengl_ctx)
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
void DRW_opengl_context_create(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(DST.gl_context == NULL); /* Ensure it's called once */
|
|
|
|
|
|
|
|
DST.gl_context_mutex = BLI_ticket_mutex_alloc();
|
|
|
|
if (!G.background) {
|
|
|
|
immDeactivate();
|
|
|
|
}
|
|
|
|
/* This changes the active context. */
|
|
|
|
DST.gl_context = WM_opengl_context_create();
|
|
|
|
WM_opengl_context_activate(DST.gl_context);
|
|
|
|
/* Be sure to create gawain.context too. */
|
2019-06-01 17:54:07 +02:00
|
|
|
DST.gpu_context = GPU_context_create(0);
|
2019-04-17 06:17:24 +02:00
|
|
|
if (!G.background) {
|
|
|
|
immActivate();
|
|
|
|
}
|
|
|
|
/* Set default Blender OpenGL state */
|
|
|
|
GPU_state_init();
|
|
|
|
/* So we activate the window's one afterwards. */
|
|
|
|
wm_window_reset_drawable();
|
2018-02-26 19:41:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_opengl_context_destroy(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_assert(BLI_thread_is_main());
|
|
|
|
if (DST.gl_context != NULL) {
|
|
|
|
WM_opengl_context_activate(DST.gl_context);
|
|
|
|
GPU_context_active_set(DST.gpu_context);
|
|
|
|
GPU_context_discard(DST.gpu_context);
|
|
|
|
WM_opengl_context_dispose(DST.gl_context);
|
|
|
|
BLI_ticket_mutex_free(DST.gl_context_mutex);
|
|
|
|
}
|
2018-02-26 19:41:17 +01:00
|
|
|
}
|
|
|
|
|
2018-07-19 15:48:13 +02:00
|
|
|
void DRW_opengl_context_enable_ex(bool restore)
|
2018-02-26 19:41:17 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.gl_context != NULL) {
|
|
|
|
/* IMPORTANT: We dont support immediate mode in render mode!
|
|
|
|
* This shall remain in effect until immediate mode supports
|
|
|
|
* multiple threads. */
|
|
|
|
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
|
|
|
if (BLI_thread_is_main() && restore) {
|
|
|
|
if (!G.background) {
|
|
|
|
immDeactivate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
WM_opengl_context_activate(DST.gl_context);
|
|
|
|
GPU_context_active_set(DST.gpu_context);
|
|
|
|
if (BLI_thread_is_main() && restore) {
|
|
|
|
if (!G.background) {
|
|
|
|
immActivate();
|
|
|
|
}
|
|
|
|
BLF_batch_reset();
|
|
|
|
}
|
|
|
|
}
|
2018-02-26 19:41:17 +01:00
|
|
|
}
|
|
|
|
|
2018-07-19 15:48:13 +02:00
|
|
|
void DRW_opengl_context_disable_ex(bool restore)
|
2018-02-26 19:41:17 +01:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (DST.gl_context != NULL) {
|
2018-02-26 19:41:17 +01:00
|
|
|
#ifdef __APPLE__
|
2019-04-17 06:17:24 +02:00
|
|
|
/* Need to flush before disabling draw context, otherwise it does not
|
|
|
|
* always finish drawing and viewport can be empty or partially drawn */
|
|
|
|
GPU_flush();
|
2018-02-26 19:41:17 +01:00
|
|
|
#endif
|
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
if (BLI_thread_is_main() && restore) {
|
|
|
|
wm_window_reset_drawable();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
WM_opengl_context_release(DST.gl_context);
|
|
|
|
GPU_context_active_set(NULL);
|
|
|
|
}
|
2018-02-26 19:41:17 +01:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
|
|
|
}
|
2018-02-26 19:41:17 +01:00
|
|
|
}
|
|
|
|
|
2018-07-19 15:48:13 +02:00
|
|
|
void DRW_opengl_context_enable(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
if (G.background && DST.gl_context == NULL) {
|
|
|
|
WM_init_opengl(G_MAIN);
|
|
|
|
}
|
|
|
|
DRW_opengl_context_enable_ex(true);
|
2018-07-19 15:48:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_opengl_context_disable(void)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_opengl_context_disable_ex(true);
|
2018-07-19 15:48:13 +02:00
|
|
|
}
|
|
|
|
|
2018-07-10 14:40:28 +02:00
|
|
|
void DRW_opengl_render_context_enable(void *re_gl_context)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* If thread is main you should use DRW_opengl_context_enable(). */
|
|
|
|
BLI_assert(!BLI_thread_is_main());
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
/* TODO get rid of the blocking. Only here because of the static global DST. */
|
|
|
|
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
|
|
|
WM_opengl_context_activate(re_gl_context);
|
2018-07-10 14:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DRW_opengl_render_context_disable(void *re_gl_context)
|
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_flush();
|
|
|
|
WM_opengl_context_release(re_gl_context);
|
|
|
|
/* TODO get rid of the blocking. */
|
|
|
|
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
2018-07-10 14:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Needs to be called AFTER DRW_opengl_render_context_enable() */
|
2018-07-18 00:12:21 +02:00
|
|
|
void DRW_gawain_render_context_enable(void *re_gpu_context)
|
2018-07-10 14:40:28 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
/* If thread is main you should use DRW_opengl_context_enable(). */
|
|
|
|
BLI_assert(!BLI_thread_is_main());
|
2018-07-10 14:40:28 +02:00
|
|
|
|
2019-04-17 06:17:24 +02:00
|
|
|
GPU_context_active_set(re_gpu_context);
|
|
|
|
DRW_shape_cache_reset(); /* XXX fix that too. */
|
2018-07-10 14:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Needs to be called BEFORE DRW_opengl_render_context_disable() */
|
2018-07-18 00:12:21 +02:00
|
|
|
void DRW_gawain_render_context_disable(void *UNUSED(re_gpu_context))
|
2018-07-10 14:40:28 +02:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
DRW_shape_cache_reset(); /* XXX fix that too. */
|
|
|
|
GPU_context_active_set(NULL);
|
2018-07-10 14:40:28 +02:00
|
|
|
}
|
|
|
|
|
2018-02-26 19:41:17 +01:00
|
|
|
/** \} */
|