This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/engines/image/image_engine.cc
Jeroen Bakker b069218a55 DrawManager: Engine Instance Data.
In the original design draw engines had to copy with a limitation that
they were not allowed to reuse complex data structures between drawing
calls. Data that could be reused were limited to:
- GPUFramebuffers
- GPUTextures
- Memory that could be removed calling MEM_freeN (storage list)
- DRWPass

This is fine when the storage list contains arrays or structs but when
more complex data types (vectors, maps) etc wasn't possible.

This patch adds instance_data that can be reused between drawing calls.
The instance_data is controlled by the draw engine and doesn't need to
be limited as described above.

When an engines stores instance_data it must implement the
`DrawEngineType.instance_free` callback to free the data.

The patch originates from eevee rewrite. But was added to master as the
image engine rewrite also has a need for it.

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D13425
2021-12-07 10:34:38 +01:00

205 lines
5.5 KiB
C++

/*
* 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.
*
* Copyright 2020, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*
* Draw engine to draw the Image/UV editor
*/
#include "DRW_render.h"
#include <memory>
#include <optional>
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "DNA_camera_types.h"
#include "DNA_screen_types.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "ED_image.h"
#include "GPU_batch.h"
#include "image_drawing_mode_image_space.hh"
#include "image_engine.h"
#include "image_private.hh"
#include "image_space_image.hh"
#include "image_space_node.hh"
namespace blender::draw::image_engine {
static std::unique_ptr<AbstractSpaceAccessor> space_accessor_from_context(
const DRWContextState *draw_ctx)
{
const char space_type = draw_ctx->space_data->spacetype;
if (space_type == SPACE_IMAGE) {
return std::make_unique<SpaceImageAccessor>((SpaceImage *)draw_ctx->space_data);
}
if (space_type == SPACE_NODE) {
return std::make_unique<SpaceNodeAccessor>((SpaceNode *)draw_ctx->space_data);
}
BLI_assert_unreachable();
return nullptr;
}
template<
/** \brief Drawing mode to use.
*
* Useful during development to switch between drawing implementations.
*/
typename DrawingMode = ImageSpaceDrawingMode>
class ImageEngine {
private:
const DRWContextState *draw_ctx;
IMAGE_Data *vedata;
std::unique_ptr<AbstractSpaceAccessor> space;
DrawingMode drawing_mode;
public:
ImageEngine(const DRWContextState *draw_ctx, IMAGE_Data *vedata)
: draw_ctx(draw_ctx), vedata(vedata), space(space_accessor_from_context(draw_ctx))
{
}
virtual ~ImageEngine() = default;
void cache_init()
{
IMAGE_StorageList *stl = vedata->stl;
IMAGE_PrivateData *pd = stl->pd;
drawing_mode.cache_init(vedata);
pd->view = nullptr;
if (space->has_view_override()) {
const ARegion *region = draw_ctx->region;
pd->view = space->create_view_override(region);
}
}
void cache_populate()
{
IMAGE_StorageList *stl = vedata->stl;
IMAGE_PrivateData *pd = stl->pd;
Main *bmain = CTX_data_main(draw_ctx->evil_C);
pd->image = space->get_image(bmain);
if (pd->image == nullptr) {
/* Early exit, nothing to draw. */
return;
}
pd->ibuf = space->acquire_image_buffer(pd->image, &pd->lock);
ImageUser *iuser = space->get_image_user();
drawing_mode.cache_image(space.get(), vedata, pd->image, iuser, pd->ibuf);
}
void draw_finish()
{
drawing_mode.draw_finish(vedata);
IMAGE_StorageList *stl = vedata->stl;
IMAGE_PrivateData *pd = stl->pd;
space->release_buffer(pd->image, pd->ibuf, pd->lock);
pd->image = nullptr;
pd->ibuf = nullptr;
}
void draw_scene()
{
drawing_mode.draw_scene(vedata);
}
};
/* -------------------------------------------------------------------- */
/** \name Engine Callbacks
* \{ */
static void IMAGE_engine_init(void *ved)
{
IMAGE_shader_library_ensure();
IMAGE_Data *vedata = (IMAGE_Data *)ved;
IMAGE_StorageList *stl = vedata->stl;
if (!stl->pd) {
stl->pd = static_cast<IMAGE_PrivateData *>(MEM_callocN(sizeof(IMAGE_PrivateData), __func__));
}
IMAGE_PrivateData *pd = stl->pd;
pd->ibuf = nullptr;
pd->lock = nullptr;
pd->texture = nullptr;
}
static void IMAGE_cache_init(void *vedata)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
ImageEngine image_engine(draw_ctx, static_cast<IMAGE_Data *>(vedata));
image_engine.cache_init();
image_engine.cache_populate();
}
static void IMAGE_cache_populate(void *UNUSED(vedata), Object *UNUSED(ob))
{
/* Function intentional left empty. `cache_populate` is required to be implemented. */
}
static void IMAGE_draw_scene(void *vedata)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
ImageEngine image_engine(draw_ctx, static_cast<IMAGE_Data *>(vedata));
image_engine.draw_scene();
image_engine.draw_finish();
}
static void IMAGE_engine_free()
{
IMAGE_shader_free();
}
/** \} */
static const DrawEngineDataSize IMAGE_data_size = DRW_VIEWPORT_DATA_SIZE(IMAGE_Data);
} // namespace blender::draw::image_engine
extern "C" {
using namespace blender::draw::image_engine;
DrawEngineType draw_engine_image_type = {
nullptr, /* next */
nullptr, /* prev */
N_("UV/Image"), /* idname */
&IMAGE_data_size, /* vedata_size */
&IMAGE_engine_init, /* engine_init */
&IMAGE_engine_free, /* engine_free */
nullptr, /* instance_free */
&IMAGE_cache_init, /* cache_init */
&IMAGE_cache_populate, /* cache_populate */
nullptr, /* cache_finish */
&IMAGE_draw_scene, /* draw_scene */
nullptr, /* view_update */
nullptr, /* id_update */
nullptr, /* render_to_image */
nullptr, /* store_metadata */
};
}