Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/image_gpu.c
| Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | if (ibuf) { | ||||
| return image ? (image->alpha_mode == IMA_ALPHA_PREMUL) : true; | return image ? (image->alpha_mode == IMA_ALPHA_PREMUL) : true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name UDIM gpu texture | /** \name UDIM gpu texture | ||||
| * \{ */ | * \{ */ | ||||
| static bool is_over_resolution_limit(int w, int h, bool limit_gl_texture_size) | |||||
| static bool is_over_resolution_limit(int w, int h) | |||||
| { | { | ||||
| return (w > GPU_texture_size_with_limit(w) || h > GPU_texture_size_with_limit(h)); | return (w > GPU_texture_size_with_limit(w, limit_gl_texture_size) || | ||||
| h > GPU_texture_size_with_limit(h, limit_gl_texture_size)); | |||||
| } | } | ||||
| static int smaller_power_of_2_limit(int num) | static int smaller_power_of_2_limit(int num, bool limit_gl_texture_size) | ||||
| { | { | ||||
| return power_of_2_min_i(GPU_texture_size_with_limit(num)); | return power_of_2_min_i(GPU_texture_size_with_limit(num, limit_gl_texture_size)); | ||||
| } | } | ||||
| static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye) | static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye) | ||||
| { | { | ||||
| GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye]; | GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye]; | ||||
| if (tilearray == NULL) { | if (tilearray == NULL) { | ||||
| return 0; | return 0; | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | static int compare_packtile(const void *a, const void *b) | ||||
| const PackTile *tile_a = (const PackTile *)a; | const PackTile *tile_a = (const PackTile *)a; | ||||
| const PackTile *tile_b = (const PackTile *)b; | const PackTile *tile_b = (const PackTile *)b; | ||||
| return tile_a->pack_score < tile_b->pack_score; | return tile_a->pack_score < tile_b->pack_score; | ||||
| } | } | ||||
| static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf) | static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf) | ||||
| { | { | ||||
| const bool limit_gl_texture_size = (ima->gpuflag & IMA_GPU_MAX_RESOLUTION) == 0; | |||||
| int arraywidth = 0, arrayheight = 0; | int arraywidth = 0, arrayheight = 0; | ||||
| ListBase boxes = {NULL}; | ListBase boxes = {NULL}; | ||||
| LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { | LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { | ||||
| ImageUser iuser; | ImageUser iuser; | ||||
| BKE_imageuser_default(&iuser); | BKE_imageuser_default(&iuser); | ||||
| iuser.tile = tile->tile_number; | iuser.tile = tile->tile_number; | ||||
| ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); | ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); | ||||
| if (ibuf) { | if (ibuf) { | ||||
| PackTile *packtile = (PackTile *)MEM_callocN(sizeof(PackTile), __func__); | PackTile *packtile = (PackTile *)MEM_callocN(sizeof(PackTile), __func__); | ||||
| packtile->tile = tile; | packtile->tile = tile; | ||||
| packtile->boxpack.w = ibuf->x; | packtile->boxpack.w = ibuf->x; | ||||
| packtile->boxpack.h = ibuf->y; | packtile->boxpack.h = ibuf->y; | ||||
| if (is_over_resolution_limit(packtile->boxpack.w, packtile->boxpack.h)) { | if (is_over_resolution_limit( | ||||
| packtile->boxpack.w = smaller_power_of_2_limit(packtile->boxpack.w); | packtile->boxpack.w, packtile->boxpack.h, limit_gl_texture_size)) { | ||||
| packtile->boxpack.h = smaller_power_of_2_limit(packtile->boxpack.h); | packtile->boxpack.w = smaller_power_of_2_limit(packtile->boxpack.w, limit_gl_texture_size); | ||||
| packtile->boxpack.h = smaller_power_of_2_limit(packtile->boxpack.h, limit_gl_texture_size); | |||||
| } | } | ||||
| arraywidth = max_ii(arraywidth, packtile->boxpack.w); | arraywidth = max_ii(arraywidth, packtile->boxpack.w); | ||||
| arrayheight = max_ii(arrayheight, packtile->boxpack.h); | arrayheight = max_ii(arrayheight, packtile->boxpack.h); | ||||
| /* We sort the tiles by decreasing size, with an additional penalty term | /* We sort the tiles by decreasing size, with an additional penalty term | ||||
| * for high aspect ratios. This improves packing efficiency. */ | * for high aspect ratios. This improves packing efficiency. */ | ||||
| float w = packtile->boxpack.w, h = packtile->boxpack.h; | float w = packtile->boxpack.w, h = packtile->boxpack.h; | ||||
| packtile->pack_score = max_ff(w, h) / min_ff(w, h) * w * h; | packtile->pack_score = max_ff(w, h) / min_ff(w, h) * w * h; | ||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | static GPUTexture *image_get_gpu_texture(Image *ima, | ||||
| gpu_free_unused_buffers(); | gpu_free_unused_buffers(); | ||||
| /* Free GPU textures when requesting a different render pass/layer. | /* Free GPU textures when requesting a different render pass/layer. | ||||
| * When `iuser` isn't set (texture painting single image mode) we assume that | * When `iuser` isn't set (texture painting single image mode) we assume that | ||||
| * the current `pass` and `layer` should be 0. */ | * the current `pass` and `layer` should be 0. */ | ||||
| short requested_pass = iuser ? iuser->pass : 0; | short requested_pass = iuser ? iuser->pass : 0; | ||||
| short requested_layer = iuser ? iuser->layer : 0; | short requested_layer = iuser ? iuser->layer : 0; | ||||
| short requested_view = iuser ? iuser->multi_index : 0; | short requested_view = iuser ? iuser->multi_index : 0; | ||||
| const bool limit_resolution = U.glreslimit != 0 && | |||||
| ((iuser && (iuser->flag & IMA_SHOW_MAX_RESOLUTION) == 0) || | |||||
| (iuser == NULL)); | |||||
| short requested_gpu_flags = limit_resolution ? 0 : IMA_GPU_MAX_RESOLUTION; | |||||
| #define GPU_FLAGS_TO_CHECK (IMA_GPU_MAX_RESOLUTION) | |||||
| /* There is room for 2 multiview textures. When a higher number is requested we should always | /* There is room for 2 multiview textures. When a higher number is requested we should always | ||||
| * target the first view slot. This is fine as multi view images aren't used together. */ | * target the first view slot. This is fine as multi view images aren't used together. */ | ||||
| if (requested_view < 2) { | if (requested_view < 2) { | ||||
| requested_view = 0; | requested_view = 0; | ||||
| } | } | ||||
| if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer || | if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer || | ||||
| ima->gpu_view != requested_view) { | ima->gpu_view != requested_view || | ||||
| ((ima->gpuflag & GPU_FLAGS_TO_CHECK) != requested_gpu_flags)) { | |||||
| ima->gpu_pass = requested_pass; | ima->gpu_pass = requested_pass; | ||||
| ima->gpu_layer = requested_layer; | ima->gpu_layer = requested_layer; | ||||
| ima->gpu_view = requested_view; | ima->gpu_view = requested_view; | ||||
| ima->gpuflag |= IMA_GPU_REFRESH; | ima->gpuflag &= ~GPU_FLAGS_TO_CHECK; | ||||
| ima->gpuflag |= requested_gpu_flags | IMA_GPU_REFRESH; | |||||
| } | } | ||||
| #undef GPU_FLAGS_TO_CHECK | |||||
| /* Check if image has been updated and tagged to be updated (full or partial). */ | /* Check if image has been updated and tagged to be updated (full or partial). */ | ||||
| ImageTile *tile = BKE_image_get_tile(ima, 0); | ImageTile *tile = BKE_image_get_tile(ima, 0); | ||||
| if (((ima->gpuflag & IMA_GPU_REFRESH) != 0) || | if (((ima->gpuflag & IMA_GPU_REFRESH) != 0) || | ||||
| ((ibuf == NULL || tile == NULL || !tile->ok) && | ((ibuf == NULL || tile == NULL || !tile->ok) && | ||||
| ((ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) != 0))) { | ((ima->gpuflag & IMA_GPU_PARTIAL_REFRESH) != 0))) { | ||||
| image_free_gpu(ima, true); | image_free_gpu(ima, true); | ||||
| BLI_freelistN(&ima->gpu_refresh_areas); | BLI_freelistN(&ima->gpu_refresh_areas); | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | #undef GPU_FLAGS_TO_CHECK | ||||
| } | } | ||||
| else if (textarget == TEXTARGET_TILE_MAPPING) { | else if (textarget == TEXTARGET_TILE_MAPPING) { | ||||
| *tex = gpu_texture_create_tile_mapping(ima, iuser ? iuser->multiview_eye : 0); | *tex = gpu_texture_create_tile_mapping(ima, iuser ? iuser->multiview_eye : 0); | ||||
| } | } | ||||
| else { | else { | ||||
| const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH); | const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH); | ||||
| const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, | const bool store_premultiplied = BKE_image_has_gpu_texture_premultiplied_alpha(ima, | ||||
| ibuf_intern); | ibuf_intern); | ||||
| const bool limit_gl_texture_size = (ima->gpuflag & IMA_GPU_MAX_RESOLUTION) == 0; | |||||
| *tex = IMB_create_gpu_texture( | *tex = IMB_create_gpu_texture(ima->id.name + 2, | ||||
| ima->id.name + 2, ibuf_intern, use_high_bitdepth, store_premultiplied); | ibuf_intern, | ||||
| use_high_bitdepth, | |||||
| store_premultiplied, | |||||
| limit_gl_texture_size); | |||||
| GPU_texture_wrap_mode(*tex, true, false); | GPU_texture_wrap_mode(*tex, true, false); | ||||
| if (GPU_mipmap_enabled()) { | if (GPU_mipmap_enabled()) { | ||||
| GPU_texture_generate_mipmap(*tex); | GPU_texture_generate_mipmap(*tex); | ||||
| if (ima) { | if (ima) { | ||||
| ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; | ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 519 Lines • Show Last 20 Lines | |||||