[Bf-blender-cvs] [387dbd65ac1] temp-gpu-image-engine: Merge branch 'master' into temp-gpu-image-engine
Jeroen Bakker
noreply at git.blender.org
Fri Dec 3 16:07:31 CET 2021
Commit: 387dbd65ac12b98a23c013993a0bc37c0c8cd6a6
Author: Jeroen Bakker
Date: Fri Dec 3 14:00:34 2021 +0100
Branches: temp-gpu-image-engine
https://developer.blender.org/rB387dbd65ac12b98a23c013993a0bc37c0c8cd6a6
Merge branch 'master' into temp-gpu-image-engine
===================================================================
===================================================================
diff --cc source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
index 26f5bb895e7,00000000000..3f1daf066ca
mode 100644,000000..100644
--- a/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
+++ b/source/blender/draw/engines/image/image_drawing_mode_screen_space.hh
@@@ -1,546 -1,0 +1,546 @@@
+/*
+ * 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 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#pragma once
+
+#include "image_private.hh"
+
+#include "BKE_image_partial_update.hh"
+
+namespace blender::draw::image_engine {
+
+constexpr float EPSILON_UV_BOUNDS = 0.00001f;
+
+/**
+ * \brief Accessor to texture slots.
+ *
+ * Texture slots info is stored in IMAGE_PrivateData. The GPUTextures are stored in
+ * IMAGE_TextureList. This class simplifies accessing texture slots by providing
+ */
+struct PrivateDataAccessor {
+ IMAGE_PrivateData *pd;
+ IMAGE_TextureList *txl;
+ PrivateDataAccessor(IMAGE_PrivateData *pd, IMAGE_TextureList *txl) : pd(pd), txl(txl)
+ {
+ }
+
+ /** \brief Clear dirty flag from all texture slots. */
+ void clear_dirty_flag()
+ {
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ pd->screen_space.texture_infos[i].dirty = false;
+ }
+ }
+
+ /** \brief Update the texture slot uv and screen space bounds. */
+ void update_screen_space_bounds(const ARegion *region)
+ {
+ /* Create a single texture that covers the visible screen space. */
+ BLI_rctf_init(
+ &pd->screen_space.texture_infos[0].clipping_bounds, 0, region->winx, 0, region->winy);
+ pd->screen_space.texture_infos[0].visible = true;
+
+ /* Mark the other textures as invalid. */
+ for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ BLI_rctf_init_minmax(&pd->screen_space.texture_infos[i].clipping_bounds);
+ pd->screen_space.texture_infos[i].visible = false;
+ }
+ }
+
+ void update_uv_bounds()
+ {
+ /* Calculate the uv coordinates of the screen space visible corners. */
+ float inverse_mat[4][4];
+ DRW_view_viewmat_get(NULL, inverse_mat, true);
+
+ rctf new_uv_bounds;
+ float uv_min[3];
+ static const float screen_space_co1[3] = {0.0, 0.0, 0.0};
+ mul_v3_m4v3(uv_min, inverse_mat, screen_space_co1);
+
+ static const float screen_space_co2[3] = {1.0, 1.0, 0.0};
+ float uv_max[3];
+ mul_v3_m4v3(uv_max, inverse_mat, screen_space_co2);
+ BLI_rctf_init(&new_uv_bounds, uv_min[0], uv_max[0], uv_min[1], uv_max[1]);
+
+ if (!BLI_rctf_compare(
+ &pd->screen_space.texture_infos[0].uv_bounds, &new_uv_bounds, EPSILON_UV_BOUNDS)) {
+ pd->screen_space.texture_infos[0].uv_bounds = new_uv_bounds;
+ pd->screen_space.texture_infos[0].dirty = true;
+ update_uv_to_texture_matrix(&pd->screen_space.texture_infos[0]);
+ }
+
+ /* Mark the other textures as invalid. */
+ for (int i = 1; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ BLI_rctf_init_minmax(&pd->screen_space.texture_infos[i].clipping_bounds);
+ }
+ }
+
+ void update_uv_to_texture_matrix(IMAGE_ScreenSpaceTextureInfo *info)
+ {
+ // TODO: I remember that there was a function for this somewhere.
+ unit_m4(info->uv_to_texture);
+ float scale_x = 1.0 / BLI_rctf_size_x(&info->uv_bounds);
+ float scale_y = 1.0 / BLI_rctf_size_y(&info->uv_bounds);
+ float translate_x = scale_x * -info->uv_bounds.xmin;
+ float translate_y = scale_y * -info->uv_bounds.ymin;
+
+ info->uv_to_texture[0][0] = scale_x;
+ info->uv_to_texture[1][1] = scale_y;
+ info->uv_to_texture[3][0] = translate_x;
+ info->uv_to_texture[3][1] = translate_y;
+ }
+};
+
+struct ImageTileAccessor {
+ ImageTile *image_tile;
+ ImageTileAccessor(ImageTile *image_tile) : image_tile(image_tile)
+ {
+ }
+
+ int get_tile_number() const
+ {
+ return image_tile->tile_number;
+ }
+
+ int get_tile_x_offset() const
+ {
+ int tile_number = get_tile_number();
+ return (tile_number - 1001) % 10;
+ }
+
+ int get_tile_y_offset() const
+ {
+ int tile_number = get_tile_number();
+ return (tile_number - 1001) / 10;
+ }
+};
+
+using namespace blender::bke::image::partial_update;
+
+class ScreenSpaceDrawingMode : public AbstractDrawingMode {
+ private:
+ DRWPass *create_image_pass() const
+ {
+ /* Write depth is needed for background overlay rendering. Near depth is used for
+ * transparency checker and Far depth is used for indicating the image size. */
+ DRWState state = static_cast<DRWState>(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ALPHA_PREMUL);
+ return DRW_pass_create("Image", state);
+ }
+
+ void add_shgroups(IMAGE_PassList *psl,
+ IMAGE_TextureList *txl,
+ IMAGE_PrivateData *pd,
+ const ShaderParameters &sh_params) const
+ {
+ GPUBatch *geom = DRW_cache_quad_get();
+ GPUShader *shader = IMAGE_shader_image_get(false);
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass);
+ DRW_shgroup_uniform_vec2_copy(shgrp, "farNearDistances", sh_params.far_near);
+ DRW_shgroup_uniform_vec4_copy(shgrp, "color", ShaderParameters::color);
+ DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", sh_params.shuffle);
+ DRW_shgroup_uniform_int_copy(shgrp, "drawFlags", sh_params.flags);
+ DRW_shgroup_uniform_bool_copy(shgrp, "imgPremultiplied", sh_params.use_premul_alpha);
+ float image_mat[4][4];
+ unit_m4(image_mat);
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ if (!pd->screen_space.texture_infos[i].visible) {
+ continue;
+ }
+
+ image_mat[0][0] = pd->screen_space.texture_infos[i].clipping_bounds.xmax;
+ image_mat[1][1] = pd->screen_space.texture_infos[i].clipping_bounds.ymax;
+
+ DRWShadingGroup *shgrp_sub = DRW_shgroup_create_sub(shgrp);
+ DRW_shgroup_uniform_texture_ex(
+ shgrp_sub, "imageTexture", txl->screen_space.textures[i], GPU_SAMPLER_DEFAULT);
+ DRW_shgroup_call_obmat(shgrp_sub, geom, image_mat);
+ }
+ }
+
+ /**
+ * \brief check if the partial update user in the private data can still be used.
+ *
+ * When switching to a different image the partial update user should be recreated.
+ */
+ bool partial_update_is_valid(const IMAGE_PrivateData *pd, const Image *image) const
+ {
+ if (pd->screen_space.partial_update_image != image) {
+ return false;
+ }
+
+ return pd->screen_space.partial_update_user != nullptr;
+ }
+
+ void partial_update_allocate(IMAGE_PrivateData *pd, const Image *image) const
+ {
+ BLI_assert(pd->screen_space.partial_update_user == nullptr);
+ pd->screen_space.partial_update_user = BKE_image_partial_update_create(image);
+ pd->screen_space.partial_update_image = image;
+ }
+
+ void partial_update_free(IMAGE_PrivateData *pd) const
+ {
+ if (pd->screen_space.partial_update_user != nullptr) {
+ BKE_image_partial_update_free(pd->screen_space.partial_update_user);
+ pd->screen_space.partial_update_user = nullptr;
+ }
+ }
+
+ void update_texture_slot_allocation(IMAGE_TextureList *txl, IMAGE_PrivateData *pd) const
+ {
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ const bool is_allocated = txl->screen_space.textures[i] != nullptr;
+ const bool is_visible = pd->screen_space.texture_infos[i].visible;
+ const bool should_be_freed = !is_visible && is_allocated;
+ const bool should_be_created = is_visible && !is_allocated;
+
+ if (should_be_freed) {
+ GPU_texture_free(txl->screen_space.textures[i]);
+ txl->screen_space.textures[i] = nullptr;
+ }
+
+ if (should_be_created) {
+ DRW_texture_ensure_fullscreen_2d(
+ &txl->screen_space.textures[i], GPU_RGBA16F, static_cast<DRWTextureFlag>(0));
+ }
+ pd->screen_space.texture_infos[i].dirty |= should_be_created;
+ }
+ }
+
+ void mark_all_texture_slots_dirty(IMAGE_PrivateData *pd) const
+ {
+ for (int i = 0; i < SCREEN_SPACE_DRAWING_MODE_TEXTURE_LEN; i++) {
+ pd->screen_space.texture_infos[i].dirty = true;
+ }
+ }
+
+ /**
+ * \brief Update GPUTextures for drawing the image.
+ *
+ * GPUTextures that are marked dirty are rebuild. GPUTextures that aren't marked dirty are
+ * updated with changed region of the image.
+ */
+ void update_textures(IMAGE_TextureList *txl,
+ IMAGE_PrivateData *pd,
+ Image *image,
+ ImageUser *image_user) const
+ {
+ PartialUpdateChecker<ImageTileData> checker(
+ image, image_user, pd->screen_space.partial_update_user);
+ PartialUpdateChecker<ImageTileData>::CollectResult changes = checker.collect_changes();
+
+ switch (changes.get_result_code()) {
+ case ePartialUpdateCollectResult::FullUpdateNeeded:
+ mark_all_texture_slots_dirty(pd);
+ break;
+ case ePartialUpdateCollectResult::NoChangesDetected:
+ break;
+ case ePartialUpdateCollectResult::PartialChangesDetected:
+ do_partial_update(changes, txl, pd, image);
+ break;
+ }
+ do_full_update_for_dirty_textures(txl, pd, image_user);
+ }
+
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list