Blender  V3.3
image_gpu.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_bitmap.h"
11 #include "BLI_boxpack_2d.h"
12 #include "BLI_linklist.h"
13 #include "BLI_listbase.h"
14 #include "BLI_threads.h"
15 
16 #include "DNA_image_types.h"
17 #include "DNA_userdef_types.h"
18 
19 #include "IMB_colormanagement.h"
20 #include "IMB_imbuf.h"
21 #include "IMB_imbuf_types.h"
22 
23 #include "BKE_global.h"
24 #include "BKE_image.h"
26 #include "BKE_main.h"
27 
28 #include "GPU_capabilities.h"
29 #include "GPU_state.h"
30 #include "GPU_texture.h"
31 
32 #include "PIL_time.h"
33 
35 
36 extern "C" {
37 
38 /* Prototypes. */
39 static void gpu_free_unused_buffers();
40 static void image_free_gpu(Image *ima, const bool immediate);
41 static void image_update_gputexture_ex(
42  Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h);
43 
45 {
46  if (image) {
47  /* Render result and compositor output are always premultiplied */
49  return true;
50  }
51  /* Generated images use pre multiplied float buffer, but straight alpha for byte buffers. */
52  if (image->type == IMA_TYPE_UV_TEST && ibuf) {
53  return ibuf->rect_float != nullptr;
54  }
55  }
56  if (ibuf) {
57  if (ibuf->rect_float) {
58  return image ? (image->alpha_mode != IMA_ALPHA_STRAIGHT) : false;
59  }
60 
61  return image ? (image->alpha_mode == IMA_ALPHA_PREMUL) : true;
62  }
63  return false;
64 }
65 
66 /* -------------------------------------------------------------------- */
70 static bool is_over_resolution_limit(int w, int h)
71 {
73 }
74 
75 static int smaller_power_of_2_limit(int num)
76 {
78 }
79 
80 static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye)
81 {
82  GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye];
83 
84  if (tilearray == nullptr) {
85  return nullptr;
86  }
87 
88  float array_w = GPU_texture_width(tilearray);
89  float array_h = GPU_texture_height(tilearray);
90 
91  /* Determine maximum tile number. */
93  ImageTile *last_tile = (ImageTile *)ima->tiles.last;
94  int max_tile = last_tile->tile_number - 1001;
95 
96  /* create image */
97  int width = max_tile + 1;
98  float *data = (float *)MEM_callocN(width * 8 * sizeof(float), __func__);
99  for (int i = 0; i < width; i++) {
100  data[4 * i] = -1.0f;
101  }
102  LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
103  int i = tile->tile_number - 1001;
104  ImageTile_Runtime *tile_runtime = &tile->runtime;
105  data[4 * i] = tile_runtime->tilearray_layer;
106 
107  float *tile_info = &data[4 * width + 4 * i];
108  tile_info[0] = tile_runtime->tilearray_offset[0] / array_w;
109  tile_info[1] = tile_runtime->tilearray_offset[1] / array_h;
110  tile_info[2] = tile_runtime->tilearray_size[0] / array_w;
111  tile_info[3] = tile_runtime->tilearray_size[1] / array_h;
112  }
113 
115  GPU_texture_mipmap_mode(tex, false, false);
116 
117  MEM_freeN(data);
118 
119  return tex;
120 }
121 
122 struct PackTile {
125  float pack_score;
126 };
127 
128 static int compare_packtile(const void *a, const void *b)
129 {
130  const PackTile *tile_a = (const PackTile *)a;
131  const PackTile *tile_b = (const PackTile *)b;
132 
133  return tile_a->pack_score < tile_b->pack_score;
134 }
135 
137 {
138  int arraywidth = 0, arrayheight = 0;
139  ListBase boxes = {nullptr};
140 
141  LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
142  ImageUser iuser;
143  BKE_imageuser_default(&iuser);
144  iuser.tile = tile->tile_number;
145  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr);
146 
147  if (ibuf) {
148  PackTile *packtile = MEM_cnew<PackTile>(__func__);
149  packtile->tile = tile;
150  packtile->boxpack.w = ibuf->x;
151  packtile->boxpack.h = ibuf->y;
152 
153  if (is_over_resolution_limit(packtile->boxpack.w, packtile->boxpack.h)) {
154  packtile->boxpack.w = smaller_power_of_2_limit(packtile->boxpack.w);
155  packtile->boxpack.h = smaller_power_of_2_limit(packtile->boxpack.h);
156  }
157  arraywidth = max_ii(arraywidth, packtile->boxpack.w);
158  arrayheight = max_ii(arrayheight, packtile->boxpack.h);
159 
160  /* We sort the tiles by decreasing size, with an additional penalty term
161  * for high aspect ratios. This improves packing efficiency. */
162  float w = packtile->boxpack.w, h = packtile->boxpack.h;
163  packtile->pack_score = max_ff(w, h) / min_ff(w, h) * w * h;
164 
165  BKE_image_release_ibuf(ima, ibuf, nullptr);
166  BLI_addtail(&boxes, packtile);
167  }
168  }
169 
170  BLI_assert(arraywidth > 0 && arrayheight > 0);
171 
173  int arraylayers = 0;
174  /* Keep adding layers until all tiles are packed. */
175  while (boxes.first != nullptr) {
176  ListBase packed = {nullptr};
177  BLI_box_pack_2d_fixedarea(&boxes, arraywidth, arrayheight, &packed);
178  BLI_assert(packed.first != nullptr);
179 
180  LISTBASE_FOREACH (PackTile *, packtile, &packed) {
181  ImageTile *tile = packtile->tile;
182  ImageTile_Runtime *tile_runtime = &tile->runtime;
183  int *tileoffset = tile_runtime->tilearray_offset;
184  int *tilesize = tile_runtime->tilearray_size;
185 
186  tileoffset[0] = packtile->boxpack.x;
187  tileoffset[1] = packtile->boxpack.y;
188  tilesize[0] = packtile->boxpack.w;
189  tilesize[1] = packtile->boxpack.h;
190  tile_runtime->tilearray_layer = arraylayers;
191  }
192 
193  BLI_freelistN(&packed);
194  arraylayers++;
195  }
196 
197  const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH);
198  /* Create Texture without content. */
200  ima->id.name + 2, main_ibuf, arraywidth, arrayheight, arraylayers, use_high_bitdepth);
201 
202  /* Upload each tile one by one. */
203  LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
204  ImageTile_Runtime *tile_runtime = &tile->runtime;
205  int tilelayer = tile_runtime->tilearray_layer;
206  int *tileoffset = tile_runtime->tilearray_offset;
207  int *tilesize = tile_runtime->tilearray_size;
208 
209  if (tilesize[0] == 0 || tilesize[1] == 0) {
210  continue;
211  }
212 
213  ImageUser iuser;
214  BKE_imageuser_default(&iuser);
215  iuser.tile = tile->tile_number;
216  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, nullptr);
217 
218  if (ibuf) {
219  const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, ibuf);
221  ibuf,
222  UNPACK2(tileoffset),
223  tilelayer,
224  UNPACK2(tilesize),
225  use_high_bitdepth,
226  store_premultiplied);
227  }
228 
229  BKE_image_release_ibuf(ima, ibuf, nullptr);
230  }
231 
232  if (GPU_mipmap_enabled()) {
234  GPU_texture_mipmap_mode(tex, true, true);
235  if (ima) {
237  }
238  }
239  else {
240  GPU_texture_mipmap_mode(tex, false, true);
241  }
242 
243  return tex;
244 }
245 
248 /* -------------------------------------------------------------------- */
253  eGPUTextureTarget textarget,
254  const int multiview_eye)
255 {
256  const bool in_range = (textarget >= 0) && (textarget < TEXTARGET_COUNT);
257  BLI_assert(in_range);
258  BLI_assert(ELEM(multiview_eye, 0, 1));
259 
260  if (in_range) {
261  return &(ima->gputexture[textarget][multiview_eye]);
262  }
263  return nullptr;
264 }
265 
267 {
268  fprintf(stderr, "GPUTexture: Blender Texture Not Loaded!\n");
269  switch (textarget) {
270  case TEXTARGET_2D_ARRAY:
271  return GPU_texture_create_error(2, true);
273  return GPU_texture_create_error(1, true);
274  case TEXTARGET_2D:
275  default:
276  return GPU_texture_create_error(2, false);
277  }
278 }
279 
282 {
284  /* Calculate the clipping region with the tile buffer.
285  * TODO(jbakker): should become part of ImageTileData to deduplicate with image engine. */
286  rcti buffer_rect;
288  &buffer_rect, 0, changes.tile_data.tile_buffer->x, 0, changes.tile_data.tile_buffer->y);
289  rcti clipped_update_region;
290  const bool has_overlap = BLI_rcti_isect(
291  &buffer_rect, &changes.changed_region.region, &clipped_update_region);
292  if (!has_overlap) {
293  continue;
294  }
295 
297  changes.tile_data.tile,
298  changes.tile_data.tile_buffer,
299  clipped_update_region.xmin,
300  clipped_update_region.ymin,
301  BLI_rcti_size_x(&clipped_update_region),
302  BLI_rcti_size_y(&clipped_update_region));
303  }
304 }
305 
307 {
308  PartialUpdateChecker<ImageTileData> checker(image, iuser, image->runtime.partial_update_user);
310  switch (changes.get_result_code()) {
312  image_free_gpu(image, true);
313  break;
314  }
315 
318  break;
319  }
320 
322  /* GPUTextures are up to date. */
323  break;
324  }
325  }
326 }
327 
329  ImageUser *iuser,
330  ImBuf *ibuf,
331  eGPUTextureTarget textarget)
332 {
333  if (ima == nullptr) {
334  return nullptr;
335  }
336 
337  /* Free any unused GPU textures, since we know we are in a thread with OpenGL
338  * context and might as well ensure we have as much space free as possible. */
340 
341  /* Free GPU textures when requesting a different render pass/layer.
342  * When `iuser` isn't set (texture painting single image mode) we assume that
343  * the current `pass` and `layer` should be 0. */
344  short requested_pass = iuser ? iuser->pass : 0;
345  short requested_layer = iuser ? iuser->layer : 0;
346  short requested_view = iuser ? iuser->multi_index : 0;
347  /* There is room for 2 multiview textures. When a higher number is requested we should always
348  * target the first view slot. This is fine as multi view images aren't used together. */
349  if (requested_view < 2) {
350  requested_view = 0;
351  }
352  if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer ||
353  ima->gpu_view != requested_view) {
354  ima->gpu_pass = requested_pass;
355  ima->gpu_layer = requested_layer;
356  ima->gpu_view = requested_view;
357  }
358 #undef GPU_FLAGS_TO_CHECK
359 
360  if (ima->runtime.partial_update_user == nullptr) {
362  }
363 
365 
366  /* Tag as in active use for garbage collector. */
367  BKE_image_tag_time(ima);
368 
369  /* Test if we already have a texture. */
370  int current_view = iuser ? iuser->multi_index : 0;
371  if (current_view >= 2) {
372  current_view = 0;
373  }
374  GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, current_view);
375  if (*tex) {
376  return *tex;
377  }
378 
379  /* Check if we have a valid image. If not, we return a dummy
380  * texture with zero bind-code so we don't keep trying. */
381  ImageTile *tile = BKE_image_get_tile(ima, 0);
382  if (tile == nullptr) {
383  *tex = image_gpu_texture_error_create(textarget);
384  return *tex;
385  }
386 
387  /* check if we have a valid image buffer */
388  ImBuf *ibuf_intern = ibuf;
389  if (ibuf_intern == nullptr) {
390  ibuf_intern = BKE_image_acquire_ibuf(ima, iuser, nullptr);
391  if (ibuf_intern == nullptr) {
392  *tex = image_gpu_texture_error_create(textarget);
393  return *tex;
394  }
395  }
396 
397  if (textarget == TEXTARGET_2D_ARRAY) {
398  *tex = gpu_texture_create_tile_array(ima, ibuf_intern);
399  }
400  else if (textarget == TEXTARGET_TILE_MAPPING) {
401  *tex = gpu_texture_create_tile_mapping(ima, iuser ? iuser->multiview_eye : 0);
402  }
403  else {
404  const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH);
405  const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima,
406  ibuf_intern);
407 
409  ima->id.name + 2, ibuf_intern, use_high_bitdepth, store_premultiplied);
410 
411  if (*tex) {
412  GPU_texture_wrap_mode(*tex, true, false);
413 
414  if (GPU_mipmap_enabled()) {
416  if (ima) {
418  }
419  GPU_texture_mipmap_mode(*tex, true, true);
420  }
421  else {
422  GPU_texture_mipmap_mode(*tex, false, true);
423  }
424  }
425  }
426 
427  if (*tex) {
428  GPU_texture_orig_size_set(*tex, ibuf_intern->x, ibuf_intern->y);
429  }
430 
431  if (ibuf != ibuf_intern) {
432  BKE_image_release_ibuf(ima, ibuf_intern, nullptr);
433  }
434 
435  return *tex;
436 }
437 
439 {
440  return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_2D);
441 }
442 
444 {
445  return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_2D_ARRAY);
446 }
447 
449 {
450  return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_TILE_MAPPING);
451 }
452 
455 /* -------------------------------------------------------------------- */
464 
466 {
467  if (gpu_texture_free_queue == nullptr) {
468  return;
469  }
470 
472 
473  while (gpu_texture_free_queue != nullptr) {
476  }
477 
479 }
480 
482 {
483  if (BLI_thread_is_main()) {
485  }
486 }
487 
490 /* -------------------------------------------------------------------- */
494 static void image_free_gpu(Image *ima, const bool immediate)
495 {
496  for (int eye = 0; eye < 2; eye++) {
497  for (int i = 0; i < TEXTARGET_COUNT; i++) {
498  if (ima->gputexture[i][eye] != nullptr) {
499  if (immediate) {
500  GPU_texture_free(ima->gputexture[i][eye]);
501  }
502  else {
506  }
507 
508  ima->gputexture[i][eye] = nullptr;
509  }
510  }
511  }
512 
514 }
515 
517 {
519 }
520 
522 {
523  if (bmain) {
524  LISTBASE_FOREACH (Image *, ima, &bmain->images) {
526  }
527  }
528 }
529 
531 {
532  if (bmain) {
533  LISTBASE_FOREACH (Image *, ima, &bmain->images) {
534  if (BKE_image_is_animated(ima)) {
536  }
537  }
538  }
539 }
540 
542 {
543  static int lasttime = 0;
544  int ctime = (int)PIL_check_seconds_timer();
545 
546  /*
547  * Run garbage collector once for every collecting period of time
548  * if textimeout is 0, that's the option to NOT run the collector
549  */
550  if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) {
551  return;
552  }
553 
554  /* of course not! */
555  if (G.is_rendering) {
556  return;
557  }
558 
559  lasttime = ctime;
560 
561  LISTBASE_FOREACH (Image *, ima, &bmain->images) {
562  if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) {
563  /* If it's in GL memory, deallocate and set time tag to current time
564  * This gives textures a "second chance" to be used before dying. */
565  if (BKE_image_has_opengl_texture(ima)) {
567  ima->lastused = ctime;
568  }
569  /* Otherwise, just kill the buffers */
570  else {
572  }
573  }
574  }
575 }
576 
579 /* -------------------------------------------------------------------- */
584  float *rect_float,
585  int *x,
586  int *y,
587  int *w,
588  int *h,
589  int limit_w,
590  int limit_h,
591  int full_w,
592  int full_h)
593 {
594  /* Partial update with scaling. */
595  float xratio = limit_w / (float)full_w;
596  float yratio = limit_h / (float)full_h;
597 
598  int part_w = *w, part_h = *h;
599 
600  /* Find sub coordinates in scaled image. Take ceiling because we will be
601  * losing 1 pixel due to rounding errors in x,y. */
602  *x *= xratio;
603  *y *= yratio;
604  *w = (int)ceil(xratio * (*w));
605  *h = (int)ceil(yratio * (*h));
606 
607  /* ...but take back if we are over the limit! */
608  if (*x + *w > limit_w) {
609  (*w)--;
610  }
611  if (*y + *h > limit_h) {
612  (*h)--;
613  }
614 
615  /* Scale pixels. */
616  ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, part_w, part_h, 4);
617  IMB_scaleImBuf(ibuf, *w, *h);
618 
619  return ibuf;
620 }
621 
623  uchar *rect,
624  float *rect_float,
625  int full_w,
626  int full_h,
627  int x,
628  int y,
629  int layer,
630  const int *tile_offset,
631  const int *tile_size,
632  int w,
633  int h)
634 {
635  ImBuf *ibuf;
636  if (layer > -1) {
637  ibuf = update_do_scale(
638  rect, rect_float, &x, &y, &w, &h, tile_size[0], tile_size[1], full_w, full_h);
639 
640  /* Shift to account for tile packing. */
641  x += tile_offset[0];
642  y += tile_offset[1];
643  }
644  else {
645  /* Partial update with scaling. */
646  int limit_w = GPU_texture_width(tex);
647  int limit_h = GPU_texture_height(tex);
648 
649  ibuf = update_do_scale(rect, rect_float, &x, &y, &w, &h, limit_w, limit_h, full_w, full_h);
650  }
651 
652  void *data = (ibuf->rect_float) ? (void *)(ibuf->rect_float) : (void *)(ibuf->rect);
653  eGPUDataFormat data_format = (ibuf->rect_float) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE;
654 
655  GPU_texture_update_sub(tex, data_format, data, x, y, layer, w, h, 1);
656 
657  IMB_freeImBuf(ibuf);
658 }
659 
661  uchar *rect,
662  float *rect_float,
663  int x,
664  int y,
665  int layer,
666  const int tile_offset[2],
667  int w,
668  int h,
669  int tex_stride,
670  int tex_offset)
671 {
672  if (layer > -1) {
673  /* Shift to account for tile packing. */
674  x += tile_offset[0];
675  y += tile_offset[1];
676  }
677 
678  void *data = (rect_float) ? (void *)(rect_float + tex_offset) : (void *)(rect + tex_offset);
679  eGPUDataFormat data_format = (rect_float) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE;
680 
681  /* Partial update without scaling. Stride and offset are used to copy only a
682  * subset of a possible larger buffer than what we are updating. */
683  GPU_unpack_row_length_set(tex_stride);
684 
685  GPU_texture_update_sub(tex, data_format, data, x, y, layer, w, h, 1);
686  /* Restore default. */
688 }
689 
691  GPUTexture *tex, Image *ima, ImBuf *ibuf, ImageTile *tile, int x, int y, int w, int h)
692 {
693  bool scaled;
694  if (tile != nullptr) {
695  ImageTile_Runtime *tile_runtime = &tile->runtime;
696  int *tilesize = tile_runtime->tilearray_size;
697  scaled = (ibuf->x != tilesize[0]) || (ibuf->y != tilesize[1]);
698  }
699  else {
700  scaled = (GPU_texture_width(tex) != ibuf->x) || (GPU_texture_height(tex) != ibuf->y);
701  }
702 
703  if (scaled) {
704  /* Extra padding to account for bleed from neighboring pixels. */
705  const int padding = 4;
706  const int xmax = min_ii(x + w + padding, ibuf->x);
707  const int ymax = min_ii(y + h + padding, ibuf->y);
708  x = max_ii(x - padding, 0);
709  y = max_ii(y - padding, 0);
710  w = xmax - x;
711  h = ymax - y;
712  }
713 
714  /* Get texture data pointers. */
715  float *rect_float = ibuf->rect_float;
716  uchar *rect = (uchar *)ibuf->rect;
717  int tex_stride = ibuf->x;
718  int tex_offset = ibuf->channels * (y * ibuf->x + x);
719 
720  const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, ibuf);
721  if (rect_float) {
722  /* Float image is already in scene linear colorspace or non-color data by
723  * convention, no colorspace conversion needed. But we do require 4 channels
724  * currently. */
725  if (ibuf->channels != 4 || scaled || !store_premultiplied) {
726  rect_float = (float *)MEM_mallocN(sizeof(float[4]) * w * h, __func__);
727  if (rect_float == nullptr) {
728  return;
729  }
730 
731  tex_stride = w;
732  tex_offset = 0;
733 
735  rect_float, x, y, w, h, ibuf, store_premultiplied);
736  }
737  }
738  else {
739  /* Byte image is in original colorspace from the file, and may need conversion. */
741  /* Non-color data, just store buffer as is. */
742  }
745  /* sRGB or scene linear, store as byte texture that the GPU can decode directly. */
746  rect = (uchar *)MEM_mallocN(sizeof(uchar[4]) * w * h, __func__);
747  if (rect == nullptr) {
748  return;
749  }
750 
751  tex_stride = w;
752  tex_offset = 0;
753 
754  /* Convert to scene linear with sRGB compression, and premultiplied for
755  * correct texture interpolation. */
756  IMB_colormanagement_imbuf_to_byte_texture(rect, x, y, w, h, ibuf, store_premultiplied);
757  }
758  else {
759  /* Other colorspace, store as float texture to avoid precision loss. */
760  rect_float = (float *)MEM_mallocN(sizeof(float[4]) * w * h, __func__);
761  if (rect_float == nullptr) {
762  return;
763  }
764 
765  tex_stride = w;
766  tex_offset = 0;
767 
769  rect_float, x, y, w, h, ibuf, store_premultiplied);
770  }
771  }
772 
773  if (scaled) {
774  /* Slower update where we first have to scale the input pixels. */
775  if (tile != nullptr) {
776  ImageTile_Runtime *tile_runtime = &tile->runtime;
777  int *tileoffset = tile_runtime->tilearray_offset;
778  int *tilesize = tile_runtime->tilearray_size;
779  int tilelayer = tile_runtime->tilearray_layer;
781  tex, rect, rect_float, ibuf->x, ibuf->y, x, y, tilelayer, tileoffset, tilesize, w, h);
782  }
783  else {
785  tex, rect, rect_float, ibuf->x, ibuf->y, x, y, -1, nullptr, nullptr, w, h);
786  }
787  }
788  else {
789  /* Fast update at same resolution. */
790  if (tile != nullptr) {
791  ImageTile_Runtime *tile_runtime = &tile->runtime;
792  int *tileoffset = tile_runtime->tilearray_offset;
793  int tilelayer = tile_runtime->tilearray_layer;
795  tex, rect, rect_float, x, y, tilelayer, tileoffset, w, h, tex_stride, tex_offset);
796  }
797  else {
799  tex, rect, rect_float, x, y, -1, nullptr, w, h, tex_stride, tex_offset);
800  }
801  }
802 
803  /* Free buffers if needed. */
804  if (rect && rect != (uchar *)ibuf->rect) {
805  MEM_freeN(rect);
806  }
807  if (rect_float && rect_float != ibuf->rect_float) {
808  MEM_freeN(rect_float);
809  }
810 
811  if (GPU_mipmap_enabled()) {
813  }
814  else {
816  }
817 
819 }
820 
822  Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h)
823 {
824  const int eye = 0;
825  GPUTexture *tex = ima->gputexture[TEXTARGET_2D][eye];
826  /* Check if we need to update the main gputexture. */
827  if (tex != nullptr && tile == ima->tiles.first) {
828  gpu_texture_update_from_ibuf(tex, ima, ibuf, nullptr, x, y, w, h);
829  }
830 
831  /* Check if we need to update the array gputexture. */
832  tex = ima->gputexture[TEXTARGET_2D_ARRAY][eye];
833  if (tex != nullptr) {
834  gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h);
835  }
836 }
837 
838 void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
839 {
840  ImageTile *image_tile = BKE_image_get_tile_from_iuser(ima, iuser);
841  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, nullptr);
842  BKE_image_update_gputexture_delayed(ima, image_tile, ibuf, x, y, w, h);
843  BKE_image_release_ibuf(ima, ibuf, nullptr);
844 }
845 
847  struct ImageTile *image_tile,
848  struct ImBuf *ibuf,
849  int x,
850  int y,
851  int w,
852  int h)
853 {
854  /* Check for full refresh. */
855  if (ibuf != nullptr && ima->source != IMA_SRC_TILED && x == 0 && y == 0 && w == ibuf->x &&
856  h == ibuf->y) {
858  }
859  else {
860  rcti dirty_region;
861  BLI_rcti_init(&dirty_region, x, x + w, y, y + h);
862  BKE_image_partial_update_mark_region(ima, image_tile, ibuf, &dirty_region);
863  }
864 }
865 
866 void BKE_image_paint_set_mipmap(Main *bmain, bool mipmap)
867 {
868  LISTBASE_FOREACH (Image *, ima, &bmain->images) {
869  if (BKE_image_has_opengl_texture(ima)) {
870  if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) {
871  for (int a = 0; a < TEXTARGET_COUNT; a++) {
873  for (int eye = 0; eye < 2; eye++) {
874  GPUTexture *tex = ima->gputexture[a][eye];
875  if (tex != nullptr) {
876  GPU_texture_mipmap_mode(tex, mipmap, true);
877  }
878  }
879  }
880  }
881  }
882  else {
884  }
885  }
886  else {
887  ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
888  }
889  }
890 }
891 
893 }
typedef float(TangentPoint)[2]
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
void BKE_image_sort_tiles(struct Image *ima)
void BKE_image_partial_update_mark_region(struct Image *image, const struct ImageTile *image_tile, const struct ImBuf *image_buffer, const rcti *updated_region)
Mark a region of the image to update.
bool BKE_image_is_animated(struct Image *image)
struct PartialUpdateUser * BKE_image_partial_update_create(const struct Image *image)
Create a new PartialUpdateUser. An Object that contains data to use partial updates.
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
void BKE_image_partial_update_mark_full_update(struct Image *image)
Mark the whole image to be updated.
bool BKE_image_has_opengl_texture(struct Image *ima)
void BKE_imageuser_default(struct ImageUser *iuser)
void BKE_image_tag_time(struct Image *ima)
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_box_pack_2d_fixedarea(struct ListBase *boxes, int width, int height, struct ListBase *packed)
Definition: boxpack_2d.c:656
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
MINLINE int power_of_2_min_i(int n)
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition: rct.c:417
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)
Definition: BLI_rect.h:186
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define BLI_MUTEX_INITIALIZER
Definition: BLI_threads.h:83
int BLI_thread_is_main(void)
Definition: threads.cc:207
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:373
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:378
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:82
#define UNPACK2(a)
#define ELEM(...)
@ IMA_GPU_MIPMAP_COMPLETE
@ IMA_NOCOLLECT
@ IMA_HIGH_BITDEPTH
@ IMA_ALPHA_STRAIGHT
@ IMA_ALPHA_PREMUL
@ IMA_SRC_TILED
@ IMA_TYPE_UV_TEST
@ IMA_TYPE_R_RESULT
@ IMA_TYPE_COMPOSITE
eGPUTextureTarget
@ TEXTARGET_2D
@ TEXTARGET_2D_ARRAY
@ TEXTARGET_COUNT
@ TEXTARGET_TILE_MAPPING
int GPU_texture_size_with_limit(int res)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
bool GPU_mipmap_enabled(void)
Definition: gpu_state.cc:279
GPUTexture * GPU_texture_create_1d_array(const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:284
void GPU_texture_update_sub(GPUTexture *tex, eGPUDataFormat data_format, const void *pixels, int offset_x, int offset_y, int offset_z, int width, int height, int depth)
Definition: gpu_texture.cc:417
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp)
Definition: gpu_texture.cc:546
int GPU_texture_height(const GPUTexture *tex)
Definition: gpu_texture.cc:607
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
Definition: gpu_texture.cc:527
int GPU_texture_width(const GPUTexture *tex)
Definition: gpu_texture.cc:602
eGPUDataFormat
Definition: GPU_texture.h:170
@ GPU_DATA_UBYTE
Definition: GPU_texture.h:174
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:171
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:564
void GPU_texture_unbind(GPUTexture *tex)
Definition: gpu_texture.cc:472
@ GPU_RGBA32F
Definition: GPU_texture.h:90
void GPU_texture_orig_size_set(GPUTexture *tex, int w, int h)
Definition: gpu_texture.cc:632
void GPU_unpack_row_length_set(uint len)
Definition: gpu_texture.cc:449
GPUTexture * GPU_texture_create_error(int dimension, bool array)
Definition: gpu_texture.cc:374
void GPU_texture_generate_mipmap(GPUTexture *tex)
Definition: gpu_texture.cc:498
bool IMB_colormanagement_space_is_srgb(struct ColorSpace *colorspace)
bool IMB_colormanagement_space_is_scene_linear(struct ColorSpace *colorspace)
void IMB_colormanagement_imbuf_to_float_texture(float *out_buffer, int offset_x, int offset_y, int width, int height, const struct ImBuf *ibuf, bool store_premultiplied)
void IMB_colormanagement_imbuf_to_byte_texture(unsigned char *out_buffer, int x, int y, int width, int height, const struct ImBuf *ibuf, bool store_premultiplied)
bool IMB_colormanagement_space_is_data(struct ColorSpace *colorspace)
bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
Definition: scaling.c:1644
struct GPUTexture * IMB_create_gpu_texture(const char *name, struct ImBuf *ibuf, bool use_high_bitdepth, bool use_premult)
Definition: util_gpu.c:227
struct GPUTexture * IMB_touch_gpu_texture(const char *name, struct ImBuf *ibuf, int w, int h, int layers, bool use_high_bitdepth)
Definition: util_gpu.c:179
void IMB_update_gpu_texture_sub(struct GPUTexture *tex, struct ImBuf *ibuf, int x, int y, int z, int w, int h, bool use_high_bitdepth, bool use_premult)
Definition: util_gpu.c:198
struct ImBuf * IMB_allocFromBuffer(const unsigned int *rect, const float *rectf, unsigned int w, unsigned int h, unsigned int channels)
Definition: allocimbuf.c:447
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
Platform independent time functions.
unsigned int U
Definition: btGjkEpa3.h:78
btMatrix3x3 scaled(const btVector3 &s) const
Create a scaled copy of the matrix.
Definition: btMatrix3x3.h:622
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
short gpuflag
Image_Runtime runtime
short gpu_pass
short gpu_layer
short gpu_view
ListBase tiles
struct GPUTexture * gputexture[3][2]
short source
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
uint padding(uint offset, uint alignment)
static GPUTexture * image_get_gpu_texture(Image *ima, ImageUser *iuser, ImBuf *ibuf, eGPUTextureTarget textarget)
Definition: image_gpu.cc:328
static int compare_packtile(const void *a, const void *b)
Definition: image_gpu.cc:128
static void gpu_free_unused_buffers()
Definition: image_gpu.cc:465
GPUTexture * BKE_image_get_gpu_texture(Image *image, ImageUser *iuser, ImBuf *ibuf)
Definition: image_gpu.cc:438
static void image_gpu_texture_partial_update_changes_available(Image *image, PartialUpdateChecker< ImageTileData >::CollectResult &changes)
Definition: image_gpu.cc:280
void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
Definition: image_gpu.cc:838
static GPUTexture * image_gpu_texture_error_create(eGPUTextureTarget textarget)
Definition: image_gpu.cc:266
GPUTexture * BKE_image_get_gpu_tilemap(Image *image, ImageUser *iuser, ImBuf *ibuf)
Definition: image_gpu.cc:448
void BKE_image_free_anim_gputextures(Main *bmain)
Definition: image_gpu.cc:530
static void gpu_texture_update_from_ibuf(GPUTexture *tex, Image *ima, ImBuf *ibuf, ImageTile *tile, int x, int y, int w, int h)
Definition: image_gpu.cc:690
bool BKE_image_has_gpu_texture_premultiplied_alpha(Image *image, ImBuf *ibuf)
Definition: image_gpu.cc:44
static void image_gpu_texture_try_partial_update(Image *image, ImageUser *iuser)
Definition: image_gpu.cc:306
static ThreadMutex gpu_texture_queue_mutex
Definition: image_gpu.cc:463
static void gpu_texture_update_scaled(GPUTexture *tex, uchar *rect, float *rect_float, int full_w, int full_h, int x, int y, int layer, const int *tile_offset, const int *tile_size, int w, int h)
Definition: image_gpu.cc:622
static ImBuf * update_do_scale(uchar *rect, float *rect_float, int *x, int *y, int *w, int *h, int limit_w, int limit_h, int full_w, int full_h)
Definition: image_gpu.cc:583
static void image_free_gpu(Image *ima, const bool immediate)
Definition: image_gpu.cc:494
void BKE_image_free_gputextures(Image *ima)
Definition: image_gpu.cc:516
static bool is_over_resolution_limit(int w, int h)
Definition: image_gpu.cc:70
void BKE_image_paint_set_mipmap(Main *bmain, bool mipmap)
Definition: image_gpu.cc:866
static void gpu_texture_update_unscaled(GPUTexture *tex, uchar *rect, float *rect_float, int x, int y, int layer, const int tile_offset[2], int w, int h, int tex_stride, int tex_offset)
Definition: image_gpu.cc:660
static int smaller_power_of_2_limit(int num)
Definition: image_gpu.cc:75
static void image_update_gputexture_ex(Image *ima, ImageTile *tile, ImBuf *ibuf, int x, int y, int w, int h)
Definition: image_gpu.cc:821
void BKE_image_update_gputexture_delayed(struct Image *ima, struct ImageTile *image_tile, struct ImBuf *ibuf, int x, int y, int w, int h)
Definition: image_gpu.cc:846
static LinkNode * gpu_texture_free_queue
Definition: image_gpu.cc:462
GPUTexture * BKE_image_get_gpu_tiles(Image *image, ImageUser *iuser, ImBuf *ibuf)
Definition: image_gpu.cc:443
static GPUTexture ** get_image_gpu_texture_ptr(Image *ima, eGPUTextureTarget textarget, const int multiview_eye)
Definition: image_gpu.cc:252
void BKE_image_free_all_gputextures(Main *bmain)
Definition: image_gpu.cc:521
void BKE_image_free_unused_gpu_textures()
Definition: image_gpu.cc:481
void BKE_image_free_old_gputextures(Main *bmain)
Definition: image_gpu.cc:541
static GPUTexture * gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
Definition: image_gpu.cc:136
static GPUTexture * gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye)
Definition: image_gpu.cc:80
void * BKE_image_free_buffers
void * BKE_image_get_tile_from_iuser
ccl_global const KernelWorkTile * tile
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float3 ceil(const float3 &a)
Definition: math_float3.h:363
#define G(x, y, z)
static unsigned a[3]
Definition: RandGen.cpp:78
@ PartialChangesDetected
Changes detected since the last time requested.
@ FullUpdateNeeded
Unable to construct partial updates. Caller should perform a full update.
@ NoChangesDetected
No changes detected since the last time requested.
@ ChangeAvailable
a chunk was available and has been loaded.
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
char name[66]
Definition: DNA_ID.h:378
int channels
struct ColorSpace * rect_colorspace
unsigned int * rect
float * rect_float
char multiview_eye
short multi_index
struct PartialUpdateUser * partial_update_user
Partial update user for GPUTextures stored inside the Image.
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase images
Definition: BKE_main.h:176
ImageTile * tile
Definition: image_gpu.cc:124
float pack_score
Definition: image_gpu.cc:125
FixedSizeBoxPack boxpack
Definition: image_gpu.cc:123
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.
int ymin
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
double PIL_check_seconds_timer(void)
Definition: time.c:64