68 rctf new_clipping_uv_bounds;
80 rcti new_clipping_bounds;
81 BLI_rcti_init(&new_clipping_bounds, 0, region->winx, 0, region->winy);
113 struct TextureInfoBounds {
141 float2 region_uv_span = region_uv_max - region_uv_min;
147 assign_texture_infos_by_uv_bounds(info_bounds, unassigned_textures);
148 assign_unused_texture_infos(info_bounds, unassigned_textures);
151 rctf region_uv_bounds;
153 ®ion_uv_bounds, region_uv_min.x, region_uv_max.x, region_uv_min.y, region_uv_max.y);
154 update_region_bounds_from_uv_bounds(region_uv_bounds,
int2(region->winx, region->winy));
163 int2 texture_size(
ceil(viewport_size.x / Divisions),
ceil(viewport_size.y / Divisions));
171 info.ensure_gpu_texture(texture_size);
179 float2 region_tile_uv_span = region_uv_span /
float2(
float(Divisions));
185 uv_coords[
x][
y] = region_tile_uv_span *
float2(
float(x - 1),
float(y - 1)) +
193 TextureInfoBounds texture_info_bounds;
194 texture_info_bounds.tile_id =
int2(x, y);
197 uv_coords[x + 1][y + 1].x,
199 uv_coords[x + 1][y + 1].y);
200 info_bounds.
append(texture_info_bounds);
206 void assign_texture_infos_by_uv_bounds(Vector<TextureInfoBounds> &info_bounds,
207 Vector<TextureInfo *> &r_unassigned_textures)
210 bool assigned =
false;
211 for (TextureInfoBounds &info_bound : info_bounds) {
212 if (info_bound.info ==
nullptr &&
215 info_bound.info = &info;
216 info.tile_id = info_bound.tile_id;
222 r_unassigned_textures.append(&info);
227 void assign_unused_texture_infos(Vector<TextureInfoBounds> &info_bounds,
228 Vector<TextureInfo *> &unassigned_textures)
230 for (TextureInfoBounds &info_bound : info_bounds) {
231 if (info_bound.info ==
nullptr) {
232 info_bound.info = unassigned_textures.pop_last();
233 info_bound.info->tile_id = info_bound.tile_id;
234 info_bound.info->need_full_update =
true;
235 info_bound.info->clipping_uv_bounds = info_bound.uv_bounds;
240 void update_region_bounds_from_uv_bounds(
const rctf ®ion_uv_bounds,
const int2 region_size)
248 if (info.tile_id ==
int2(0)) {
251 float3(info.clipping_uv_bounds.xmin, info.clipping_uv_bounds.ymin, 0.0)));
258 int2 bottom_left = tile_origin + texture_size * info.tile_id;
259 int2 top_right = bottom_left + texture_size;
260 BLI_rcti_init(&info.clipping_bounds, bottom_left.
x, top_right.
x, bottom_left.
y, top_right.
y);
270 DRWPass *create_image_pass()
const
277 DRWPass *create_depth_pass()
const
297 float image_mat[4][4];
320 float image_mat[4][4];
325 tile_user = *image_user;
339 if (tile_buffer !=
nullptr) {
343 float4 min_max_uv(tile_x, tile_y, tile_x + 1, tile_y + 1);
366 switch (changes.get_result_code()) {
367 case ePartialUpdateCollectResult::FullUpdateNeeded:
371 case ePartialUpdateCollectResult::NoChangesDetected:
373 case ePartialUpdateCollectResult::PartialChangesDetected:
380 do_partial_update(changes, instance_data);
384 do_full_update_for_dirty_textures(instance_data, image_user);
390 void do_partial_update_float_buffer(
405 rcti clipped_update_region;
418 while (iterator.
get_next_change() == ePartialUpdateIterResult::ChangeAvailable) {
420 if (iterator.
tile_data.tile_buffer ==
nullptr) {
425 if (tile_buffer != iterator.
tile_data.tile_buffer) {
426 do_partial_update_float_buffer(tile_buffer, iterator);
429 const float tile_width =
float(iterator.
tile_data.tile_buffer->x);
430 const float tile_height =
float(iterator.
tile_data.tile_buffer->y);
434 if (info.need_full_update) {
437 GPUTexture *texture = info.texture;
445 rctf changed_region_in_uv_space;
447 &changed_region_in_uv_space,
448 float(changed_region_in_texel_space->
xmin) /
float(iterator.
tile_data.tile_buffer->x) +
450 float(changed_region_in_texel_space->
xmax) /
float(iterator.
tile_data.tile_buffer->x) +
452 float(changed_region_in_texel_space->
ymin) /
float(iterator.
tile_data.tile_buffer->y) +
454 float(changed_region_in_texel_space->
ymax) /
float(iterator.
tile_data.tile_buffer->y) +
456 rctf changed_overlapping_region_in_uv_space;
457 const bool region_overlap =
BLI_rctf_isect(&info.clipping_uv_bounds,
458 &changed_region_in_uv_space,
459 &changed_overlapping_region_in_uv_space);
460 if (!region_overlap) {
466 rcti gpu_texture_region_to_update;
468 &gpu_texture_region_to_update,
469 floor((changed_overlapping_region_in_uv_space.
xmin - info.clipping_uv_bounds.xmin) *
471 floor((changed_overlapping_region_in_uv_space.
xmax - info.clipping_uv_bounds.xmin) *
473 ceil((changed_overlapping_region_in_uv_space.
ymin - info.clipping_uv_bounds.ymin) *
475 ceil((changed_overlapping_region_in_uv_space.
ymax - info.clipping_uv_bounds.ymin) *
478 rcti tile_region_to_extract;
480 &tile_region_to_extract,
481 floor((changed_overlapping_region_in_uv_space.
xmin - tile_offset_x) * tile_width),
482 floor((changed_overlapping_region_in_uv_space.
xmax - tile_offset_x) * tile_width),
483 ceil((changed_overlapping_region_in_uv_space.
ymin - tile_offset_y) * tile_height),
484 ceil((changed_overlapping_region_in_uv_space.
ymax - tile_offset_y) * tile_height));
488 const int texture_region_width =
BLI_rcti_size_x(&gpu_texture_region_to_update);
489 const int texture_region_height =
BLI_rcti_size_y(&gpu_texture_region_to_update);
491 ImBuf extracted_buffer;
493 &extracted_buffer, texture_region_width, texture_region_height, 32,
IB_rectfloat);
496 for (
int y = gpu_texture_region_to_update.
ymin; y < gpu_texture_region_to_update.
ymax; y++)
498 float yf = y / (
float)texture_height;
499 float v = info.clipping_uv_bounds.ymax * yf + info.clipping_uv_bounds.ymin * (1.0 - yf) -
501 for (
int x = gpu_texture_region_to_update.
xmin; x < gpu_texture_region_to_update.
xmax;
504 float xf = x / (
float)texture_width;
505 float u = info.clipping_uv_bounds.xmax * xf +
506 info.clipping_uv_bounds.xmin * (1.0 - xf) - tile_offset_x;
519 gpu_texture_region_to_update.
xmin,
520 gpu_texture_region_to_update.
ymin,
534 if (!info.need_full_update) {
537 do_full_update_gpu_texture(info, instance_data, image_user);
545 ImBuf texture_buffer;
551 tile_user = *image_user;
562 if (tile_buffer !=
nullptr) {
563 do_full_update_texture_slot(instance_data, info, texture_buffer, *tile_buffer, image_tile);
578 ImBuf &texture_buffer,
582 const int texture_width = texture_buffer.
x;
583 const int texture_height = texture_buffer.
y;
593 BLI_rctf_init(&texture_area, 0.0, texture_width, 0.0, texture_height);
604 const rctf *crop_rect_ptr =
nullptr;
611 crop_rect_ptr = &crop_rect;
636 TextureMethod method(instance_data);
637 method.ensure_texture_infos();
646 method.update_bounds(region);
652 method.ensure_gpu_textures_allocation();
653 update_textures(*instance_data, image, iuser);
658 add_depth_shgroups(*instance_data, image, iuser);
660 add_shgroups(instance_data);
676 static float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
#define LISTBASE_FOREACH(type, var, list)
void unit_m4(float m[4][4])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
void BLI_rctf_transform_calc_m4_pivot_min(const rctf *dst, const rctf *src, float matrix[4][4])
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, float limit)
#define DRW_shgroup_call_obmat(shgroup, geom, obmat)
void GPU_framebuffer_clear_color_depth(GPUFrameBuffer *fb, const float clear_col[4], float clear_depth)
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
int GPU_texture_height(const GPUTexture *texture)
int GPU_texture_width(const GPUTexture *texture)
void GPU_texture_update_sub(GPUTexture *texture, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
void IMB_float_from_rect_ex(ImBuf *dst, const ImBuf *src, const rcti *region_to_update)
void imb_freerectImbuf_all(ImBuf *ibuf)
eIMBTransformMode
Transform modes to use for IMB_transform function.
@ IMB_TRANSFORM_MODE_WRAP_REPEAT
Wrap repeat the source buffer. Only supported in with nearest filtering.
@ IMB_TRANSFORM_MODE_CROP_SRC
Crop the source buffer.
void IMB_transform(const ImBuf *src, ImBuf *dst, eIMBTransformMode mode, eIMBInterpolationFilterMode filter, const float transform_matrix[4][4], const rctf *src_crop)
Transform source image buffer onto destination image buffer using a transform matrix.
bool IMB_initImBuf(ImBuf *ibuf, unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
void IMB_gpu_clamp_half_float(ImBuf *image_buffer)
Contains defines and structs used throughout the imbuf module.
struct GPUShader GPUShader
ATTR_WARN_UNUSED_RESULT const BMVert * v
void append(const T &value)
virtual void update_bounds(const ARegion *region)=0
Update the uv and region bounds of all texture_infos of instance_data.
virtual void ensure_gpu_textures_allocation()=0
virtual void ensure_texture_infos()=0
Ensure enough texture infos are allocated in instance_data.
BaseTextureMethod(IMAGE_InstanceData *instance_data)
IMAGE_InstanceData * instance_data
void ensure_gpu_textures_allocation() override
OneTexture(IMAGE_InstanceData *instance_data)
void ensure_texture_infos() override
Ensure enough texture infos are allocated in instance_data.
void update_bounds(const ARegion *region) override
Update the uv and region bounds of all texture_infos of instance_data.
void image_sync(IMAGE_Data *vedata, Image *image, ImageUser *iuser) const override
void draw_viewport(IMAGE_Data *vedata) const override
void draw_finish(IMAGE_Data *vedata) const override
void begin_sync(IMAGE_Data *vedata) const override
Screen space method using a multiple textures covering the region.
void ensure_gpu_textures_allocation() override
void ensure_texture_infos() override
Ensure enough texture infos are allocated in instance_data.
int2 gpu_texture_size() const
static const size_t TexturesRequired
static const size_t TexturesPerDimension
static const size_t VerticesPerDimension
void update_bounds(const ARegion *region) override
Update the uv and region bounds of all texture_infos of instance_data.
ScreenTileTextures(IMAGE_InstanceData *instance_data)
DefaultFramebufferList * DRW_viewport_framebuffer_list_get()
const float * DRW_viewport_size_get()
DefaultTextureList * DRW_viewport_texture_list_get()
const DRWContextState * DRW_context_state_get()
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_texture_ex(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex, GPUSamplerState sampler_state)
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
DRWPass * DRW_pass_create(const char *name, DRWState state)
void DRW_shgroup_uniform_ivec2_copy(DRWShadingGroup *shgroup, const char *name, const int *value)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_draw_pass(DRWPass *pass)
void DRW_view_set_active(const DRWView *view)
@ DRW_STATE_DEPTH_LESS_EQUAL
@ DRW_STATE_BLEND_ALPHA_PREMUL
draw_view in_light_buf[] float
GPUShader * IMAGE_shader_image_get()
constexpr float EPSILON_UV_BOUNDS
GPUShader * IMAGE_shader_depth_get()
float4 interpolate_nearest_border_fl(const ImBuf *in, float u, float v)
CartesianBasis invert(const CartesianBasis &basis)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
GPUFrameBuffer * color_only_fb
GPUFrameBuffer * default_fb
static constexpr GPUSamplerState default_sampler()
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
void ensure_image(const Image *new_image)
Ensure that there is a partial update user for the given image.
const c_style_mat & ptr() const
VecBase< T, 2 > xy() const
int get_tile_y_offset() const
int get_tile_x_offset() const
TileNumber get_tile_number() const
TileData tile_data
Tile specific data.
PartialUpdateRegion changed_region
ePartialUpdateIterResult get_next_change()
Load the next changed region.
CollectResult collect_changes()
Check for new changes since the last time this method was invoked for this user.
struct rcti region
region of the image that has been updated. Region can be bigger than actual changes.
ImBuf * cached_float_buffer(ImBuf *image_buffer)
void mark_used(const ImBuf *image_buffer)
void remove_unused_buffers()
IMAGE_InstanceData * instance_data
void clear_need_full_update_flag()
struct blender::draw::image_engine::IMAGE_InstanceData::@206 passes
struct blender::draw::image_engine::IMAGE_InstanceData::@205 flags
void update_image_usage(const ImageUser *image_user)
FloatBufferCache float_buffers
PartialImageUpdater partial_update
bool do_tile_drawing
should we perform tiled drawing (wrap repeat).
ShaderParameters sh_params
void mark_all_texture_slots_dirty()
float ss_to_texture[4][4]
Transform matrix to convert a normalized screen space coordinates to texture space.
Vector< TextureInfo > texture_infos
GPUTexture * texture
GPU Texture for a partial region of the image editor.
bool need_full_update
does this texture need a full update.
rcti clipping_bounds
area of the texture in screen space.
void ensure_gpu_texture(int2 texture_size)
rctf clipping_uv_bounds
uv area of the texture in screen space.