Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/intern/gpu_draw.c
| Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| #include "BKE_colorband.h" | #include "BKE_colorband.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_image.h" | #include "BKE_image.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| #include "BKE_movieclip.h" | |||||
| #include "BKE_node.h" | #include "BKE_node.h" | ||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "GPU_draw.h" | #include "GPU_draw.h" | ||||
| #include "GPU_extensions.h" | #include "GPU_extensions.h" | ||||
| #include "GPU_glew.h" | #include "GPU_glew.h" | ||||
| #include "GPU_material.h" | #include "GPU_material.h" | ||||
| #include "GPU_matrix.h" | #include "GPU_matrix.h" | ||||
| ▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget) | ||||
| if (textarget == GL_TEXTURE_2D) | if (textarget == GL_TEXTURE_2D) | ||||
| return &ima->gputexture[TEXTARGET_TEXTURE_2D]; | return &ima->gputexture[TEXTARGET_TEXTURE_2D]; | ||||
| else if (textarget == GL_TEXTURE_CUBE_MAP) | else if (textarget == GL_TEXTURE_CUBE_MAP) | ||||
| return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; | return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| static GPUTexture **gpu_get_movieclip_gputexture(MovieClip *clip, MovieClipUser* cuser, GLenum textarget) | |||||
| { | |||||
| MovieClip_RuntimeGPUTexture *tex; | |||||
| for (tex = clip->runtime.gputextures.first; tex ; tex=tex->next) { | |||||
| if (memcmp(&tex->user, cuser, sizeof(MovieClipUser)) == 0) { | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (tex == NULL) { | |||||
| tex = MEM_mallocN(sizeof(MovieClip_RuntimeGPUTexture), __func__); | |||||
| for (int i = 0; i < TEXTARGET_COUNT; i++) { | |||||
| tex->gputexture[i] = NULL; | |||||
| } | |||||
| memcpy(&tex->user, cuser, sizeof(MovieClipUser)); | |||||
| BLI_addtail(&clip->runtime.gputextures, tex); | |||||
| } | |||||
| if (textarget == GL_TEXTURE_2D) | |||||
| return &tex->gputexture[TEXTARGET_TEXTURE_2D]; | |||||
| else if (textarget == GL_TEXTURE_CUBE_MAP) | |||||
| return &tex->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; | |||||
| return NULL; | |||||
| } | |||||
| typedef struct VerifyThreadData { | typedef struct VerifyThreadData { | ||||
| ImBuf *ibuf; | ImBuf *ibuf; | ||||
| float *srgb_frect; | float *srgb_frect; | ||||
| } VerifyThreadData; | } VerifyThreadData; | ||||
| static void gpu_verify_high_bit_srgb_buffer_slice( | static void gpu_verify_high_bit_srgb_buffer_slice( | ||||
| float *srgb_frect, | float *srgb_frect, | ||||
| ImBuf *ibuf, | ImBuf *ibuf, | ||||
| Show All 40 Lines | static void gpu_verify_high_bit_srgb_buffer( | ||||
| else { | else { | ||||
| VerifyThreadData data; | VerifyThreadData data; | ||||
| data.ibuf = ibuf; | data.ibuf = ibuf; | ||||
| data.srgb_frect = srgb_frect; | data.srgb_frect = srgb_frect; | ||||
| IMB_processor_apply_threaded_scanlines(ibuf->y, verify_thread_do, &data); | IMB_processor_apply_threaded_scanlines(ibuf->y, verify_thread_do, &data); | ||||
| } | } | ||||
| } | } | ||||
| GPUTexture *GPU_texture_from_blender( | static void gpu_texture_create_from_imbuf(uint *bindcode, | ||||
| Image *ima, | Image *ima, | ||||
| ImageUser *iuser, | ImBuf *ibuf, | ||||
| int textarget, | int textarget, | ||||
| bool is_data) | bool is_data) | ||||
| { | { | ||||
| if (ima == NULL) { | |||||
| return NULL; | |||||
| } | |||||
| /* currently, gpu refresh tagging is used by ima sequences */ | |||||
| if (ima->gpuflag & IMA_GPU_REFRESH) { | |||||
| gpu_free_image_immediate(ima); | |||||
| ima->gpuflag &= ~IMA_GPU_REFRESH; | |||||
| } | |||||
| /* Test if we already have a texture. */ | |||||
| GPUTexture **tex = gpu_get_image_gputexture(ima, textarget); | |||||
| if (*tex) { | |||||
| return *tex; | |||||
| } | |||||
| /* Check if we have a valid image. If not, we return a dummy | |||||
| * texture with zero bindcode so we don't keep trying. */ | |||||
| uint bindcode = 0; | |||||
| if (ima->ok == 0) { | |||||
| *tex = GPU_texture_from_bindcode(textarget, bindcode); | |||||
| return *tex; | |||||
| } | |||||
| /* check if we have a valid image buffer */ | |||||
| ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); | |||||
| if (ibuf == NULL) { | |||||
| *tex = GPU_texture_from_bindcode(textarget, bindcode); | |||||
| return *tex; | |||||
| } | |||||
| /* flag to determine whether deep format is used */ | /* flag to determine whether deep format is used */ | ||||
| bool use_high_bit_depth = false, do_color_management = false; | bool use_high_bit_depth = false, do_color_management = false; | ||||
| if (ibuf->rect_float) { | if (ibuf->rect_float) { | ||||
| use_high_bit_depth = true; | use_high_bit_depth = true; | ||||
| /* TODO unneeded when float images are correctly treated as linear always */ | /* TODO unneeded when float images are correctly treated as linear always */ | ||||
| if (!is_data) { | if (!is_data) { | ||||
| Show All 16 Lines | else { | ||||
| frect = ibuf->rect_float; | frect = ibuf->rect_float; | ||||
| } | } | ||||
| } | } | ||||
| const bool mipmap = GPU_get_mipmap(); | const bool mipmap = GPU_get_mipmap(); | ||||
| #ifdef WITH_DDS | #ifdef WITH_DDS | ||||
| if (ibuf->ftype == IMB_FTYPE_DDS) { | if (ibuf->ftype == IMB_FTYPE_DDS) { | ||||
| GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf); | GPU_create_gl_tex_compressed(bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf); | ||||
| } | } | ||||
| else | else | ||||
| #endif | #endif | ||||
| { | { | ||||
| GPU_create_gl_tex(&bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); | GPU_create_gl_tex(bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); | ||||
| } | |||||
| /* clean up */ | |||||
| if (srgb_frect) | |||||
| MEM_freeN(srgb_frect); | |||||
| } | |||||
| GPUTexture *GPU_texture_from_blender( | |||||
| Image *ima, | |||||
| ImageUser *iuser, | |||||
| int textarget, | |||||
| bool is_data) | |||||
| { | |||||
| if (ima == NULL) { | |||||
| return NULL; | |||||
| } | } | ||||
| /* currently, gpu refresh tagging is used by ima sequences */ | |||||
| if (ima->gpuflag & IMA_GPU_REFRESH) { | |||||
| gpu_free_image_immediate(ima); | |||||
| ima->gpuflag &= ~IMA_GPU_REFRESH; | |||||
| } | |||||
| /* Test if we already have a texture. */ | |||||
| GPUTexture **tex = gpu_get_image_gputexture(ima, textarget); | |||||
| if (*tex) { | |||||
| return *tex; | |||||
| } | |||||
| /* Check if we have a valid image. If not, we return a dummy | |||||
| * texture with zero bindcode so we don't keep trying. */ | |||||
| uint bindcode = 0; | |||||
| if (ima->ok == 0) { | |||||
| *tex = GPU_texture_from_bindcode(textarget, bindcode); | |||||
| return *tex; | |||||
| } | |||||
| /* check if we have a valid image buffer */ | |||||
| ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); | |||||
| if (ibuf == NULL) { | |||||
| *tex = GPU_texture_from_bindcode(textarget, bindcode); | |||||
| return *tex; | |||||
| } | |||||
| gpu_texture_create_from_imbuf(&bindcode, ima, ibuf, textarget, is_data); | |||||
| /* mark as non-color data texture */ | /* mark as non-color data texture */ | ||||
| if (bindcode) { | if (bindcode) { | ||||
| if (is_data) | if (is_data) | ||||
| ima->gpuflag |= IMA_GPU_IS_DATA; | ima->gpuflag |= IMA_GPU_IS_DATA; | ||||
| else | else | ||||
| ima->gpuflag &= ~IMA_GPU_IS_DATA; | ima->gpuflag &= ~IMA_GPU_IS_DATA; | ||||
| } | } | ||||
| /* clean up */ | |||||
| if (srgb_frect) | |||||
| MEM_freeN(srgb_frect); | |||||
| BKE_image_release_ibuf(ima, ibuf, NULL); | BKE_image_release_ibuf(ima, ibuf, NULL); | ||||
| *tex = GPU_texture_from_bindcode(textarget, bindcode); | *tex = GPU_texture_from_bindcode(textarget, bindcode); | ||||
| return *tex; | return *tex; | ||||
| } | } | ||||
| GPUTexture *GPU_texture_from_movieclip( | |||||
| MovieClip *clip, | |||||
| MovieClipUser *cuser, | |||||
| int textarget, | |||||
| bool is_data) | |||||
| { | |||||
| if (clip == NULL) { | |||||
| return NULL; | |||||
| } | |||||
| GPUTexture **tex = gpu_get_movieclip_gputexture(clip, cuser, textarget); | |||||
| if (*tex) { | |||||
| return *tex; | |||||
| } | |||||
| /* check if we have a valid image buffer */ | |||||
| uint bindcode = 0; | |||||
| ImBuf * ibuf = BKE_movieclip_get_ibuf(clip, cuser); | |||||
| if (ibuf == NULL) { | |||||
| *tex = GPU_texture_from_bindcode(textarget, bindcode); | |||||
| return *tex; | |||||
| } | |||||
| gpu_texture_create_from_imbuf(&bindcode, NULL, ibuf, textarget, is_data); | |||||
jbakker: Merge with `gpu_get_image_gputexture` code | |||||
| IMB_freeImBuf(ibuf); | |||||
| *tex = GPU_texture_from_bindcode(textarget, bindcode); | |||||
| return *tex; | |||||
| } | |||||
| void GPU_free_texture_movieclip(struct MovieClip *clip) | |||||
| { | |||||
| /* number of gpu textures to keep around as cache | |||||
| * We don't want to keep too many GPU textures for | |||||
| * movie clips around, as they can be large.*/ | |||||
| const int MOVIECLIP_NUM_GPUTEXTURES = 1; | |||||
| while (BLI_listbase_count(&clip->runtime.gputextures) > MOVIECLIP_NUM_GPUTEXTURES) { | |||||
| MovieClip_RuntimeGPUTexture *tex = BLI_pophead(&clip->runtime.gputextures); | |||||
| for (int i = 0; i < TEXTARGET_COUNT; i++) { | |||||
| /* free glsl image binding */ | |||||
| if (tex->gputexture[i]) { | |||||
| GPU_texture_free(tex->gputexture[i]); | |||||
| tex->gputexture[i] = NULL; | |||||
| } | |||||
| } | |||||
| MEM_freeN(tex); | |||||
| } | |||||
| } | |||||
| static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth, bool use_high_bit_depth) | static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth, bool use_high_bit_depth) | ||||
| { | { | ||||
| size_t block_size = use_high_bit_depth ? sizeof(float[4]) : sizeof(uchar[4]); | size_t block_size = use_high_bit_depth ? sizeof(float[4]) : sizeof(uchar[4]); | ||||
| void **sides = NULL; | void **sides = NULL; | ||||
| int h = recth / 2; | int h = recth / 2; | ||||
| int w = rectw / 3; | int w = rectw / 3; | ||||
| if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) | if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) | ||||
| ▲ Show 20 Lines • Show All 1,105 Lines • Show Last 20 Lines | |||||
Merge with gpu_get_image_gputexture code