Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/editors/image_uv_editor.c
- This file was added.
| /* | |||||
| * 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 2016, Blender Foundation. | |||||
| */ | |||||
| /** \file | |||||
| * \ingroup draw_editors | |||||
| * | |||||
| * Draw engine to draw the Image/UV editor | |||||
| */ | |||||
| #include "DRW_render.h" | |||||
| #include "GPU_batch.h" | |||||
| #include "GPU_shader.h" | |||||
| #include "ED_image.h" | |||||
| #include "IMB_imbuf.h" | |||||
| #include "IMB_imbuf_types.h" | |||||
| #include "IMB_colormanagement.h" | |||||
| #include "DNA_space_types.h" | |||||
| #include "DNA_screen_types.h" | |||||
| #include "UI_resources.h" | |||||
| #include "image_uv_editor.h" | |||||
| /* Shaders */ | |||||
| /* *********** LISTS *********** */ | |||||
| /* GPUViewport.storage | |||||
| * Is freed everytime the viewport engine changes */ | |||||
| typedef struct IMAGE_UV_EDITOR_PrivateData { | |||||
| } IMAGE_UV_EDITOR_PrivateData; | |||||
| typedef struct IMAGE_UV_EDITOR_StorageList { | |||||
| struct IMAGE_UV_EDITOR_PrivateData *g_data; | |||||
| } IMAGE_UV_EDITOR_StorageList; | |||||
| typedef struct IMAGE_UV_EDITOR_PassList { | |||||
| DRWPass *image_pass; | |||||
| } IMAGE_UV_EDITOR_PassList; | |||||
| typedef struct IMAGE_UV_EDITOR_Data { | |||||
| void *engine_type; | |||||
| DRWViewportEmptyList *fbl; | |||||
| DRWViewportEmptyList *txl; | |||||
| IMAGE_UV_EDITOR_PassList *psl; | |||||
| IMAGE_UV_EDITOR_StorageList *stl; | |||||
| } IMAGE_UV_EDITOR_Data; | |||||
| typedef struct IMAGE_UV_EDITOR_DrawCallData { | |||||
| struct IMAGE_UV_EDITOR_DrawCallData *next, *prev; | |||||
| float image_mat[4][4]; | |||||
| } IMAGE_UV_EDITOR_DrawCallData; | |||||
| typedef struct IMAGE_UV_EDITOR_Shaders { | |||||
| } IMAGE_UV_EDITOR_Shaders; | |||||
| /* *********** STATIC *********** */ | |||||
| static struct { | |||||
| int flag; | |||||
| /* TODO: when repeated we need multiple image_mats */ | |||||
| void *lock; | |||||
| ImBuf *ibuf; | |||||
| GPUTexture *texture; | |||||
| bool do_color_management; | |||||
| bool do_channel_shuffling; | |||||
| void *cache_handle; | |||||
| GPUBatch *gpu_batch_image; | |||||
| ListBase draw_call_data; | |||||
| } e_data = {0}; /* Engine data */ | |||||
| static DRWShadingGroup *image_uv_editor_shgroup_create(IMAGE_UV_EDITOR_PassList *psl) | |||||
| { | |||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | |||||
| SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; | |||||
| GPUShader *shader = NULL; | |||||
| if (e_data.do_channel_shuffling) { | |||||
| shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); | |||||
| } | |||||
| else { | |||||
| shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE); | |||||
| } | |||||
| DRWShadingGroup *shgrp = DRW_shgroup_create(shader, psl->image_pass); | |||||
| if (e_data.do_channel_shuffling) { | |||||
| float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; | |||||
| float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; | |||||
| if (sima->flag & SI_SHOW_R) { | |||||
| shuffle[0] = 1.0f; | |||||
| } | |||||
| else if (sima->flag & SI_SHOW_G) { | |||||
| shuffle[1] = 1.0f; | |||||
| } | |||||
| else if (sima->flag & SI_SHOW_B) { | |||||
| shuffle[2] = 1.0f; | |||||
| } | |||||
| else if (sima->flag & SI_SHOW_ALPHA) { | |||||
| shuffle[3] = 1.0f; | |||||
| } | |||||
| DRW_shgroup_uniform_vec4_copy(shgrp, "shuffle", shuffle); | |||||
| DRW_shgroup_uniform_vec4_copy(shgrp, "color", color); | |||||
| } | |||||
| return shgrp; | |||||
| } | |||||
| static void image_uv_editor_add_call(DRWShadingGroup *shgrp, | |||||
| int image_offset_x, | |||||
| int image_offset_y) | |||||
| { | |||||
| IMAGE_UV_EDITOR_DrawCallData *draw_call_data = MEM_callocN(sizeof(IMAGE_UV_EDITOR_DrawCallData), | |||||
| __func__); | |||||
| BLI_addtail(&e_data.draw_call_data, draw_call_data); | |||||
| unit_m4(draw_call_data->image_mat); | |||||
| translate_m4(draw_call_data->image_mat, (float)image_offset_x, (float)image_offset_y, 0.0f); | |||||
| DRW_shgroup_call_obmat(shgrp, e_data.gpu_batch_image, draw_call_data->image_mat); | |||||
| } | |||||
| static void image_uv_editor_add_image(IMAGE_UV_EDITOR_PassList *psl, | |||||
| Image *ima, | |||||
| ImageUser *iuser, | |||||
| ImBuf *ibuf) | |||||
| { | |||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | |||||
| SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; | |||||
| e_data.do_color_management = (sima->flag & | |||||
| (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0; | |||||
| e_data.do_channel_shuffling = sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA); | |||||
| unsigned char *display_buffer; | |||||
| ColorManagedViewSettings *view_settings; | |||||
| ColorManagedDisplaySettings *display_settings; | |||||
| if (ima && ibuf) { | |||||
| DRWShadingGroup *shgrp = image_uv_editor_shgroup_create(psl); | |||||
| if (e_data.do_color_management) { | |||||
| IMB_colormanagement_display_settings_from_ctx( | |||||
| draw_ctx->evil_C, &view_settings, &display_settings); | |||||
| display_buffer = IMB_display_buffer_acquire( | |||||
| ibuf, view_settings, display_settings, &e_data.cache_handle); | |||||
| if (display_buffer) { | |||||
| e_data.texture = GPU_texture_create_nD(ibuf->x, | |||||
| ibuf->y, | |||||
| 0, | |||||
| 2, | |||||
| display_buffer, | |||||
| GPU_RGBA8, | |||||
| GPU_DATA_UNSIGNED_BYTE, | |||||
| 0, | |||||
| false, | |||||
| NULL); | |||||
| } | |||||
| GPU_texture_bind(e_data.texture, 0); | |||||
| GPU_texture_filters(e_data.texture, GPU_LINEAR, GPU_NEAREST); | |||||
| GPU_texture_unbind(e_data.texture); | |||||
| } | |||||
| else { | |||||
| e_data.texture = GPU_texture_from_blender(ima, iuser, GL_TEXTURE_2D); | |||||
| } | |||||
| if (e_data.texture) { | |||||
| DRW_shgroup_uniform_texture(shgrp, "image", e_data.texture); | |||||
| if (sima->flag & SI_DRAW_TILE) { | |||||
| // TODO: When the image is a single image we could do this in the shader... | |||||
| // That will save a lot of drawing time. | |||||
| ARegion *ar = draw_ctx->ar; | |||||
| const int xmax = ceil(ar->v2d.cur.xmax); | |||||
| const int ymax = ceil(ar->v2d.cur.ymax); | |||||
| const int xmin = floor(ar->v2d.cur.xmin); | |||||
| const int ymin = floor(ar->v2d.cur.ymin); | |||||
| for (int x = xmin; x <= xmax; x++) { | |||||
| for (int y = ymin; y <= ymax; y++) { | |||||
| image_uv_editor_add_call(shgrp, x, y); | |||||
| } | |||||
| } | |||||
| } | |||||
| else { | |||||
| image_uv_editor_add_call(shgrp, 0, 0); | |||||
| } | |||||
| } | |||||
| } | |||||
| else { | |||||
| // TODO: draw checkerboard with image 256x256 in pixel space. | |||||
| } | |||||
| } | |||||
| /* Functions */ | |||||
| static void image_uv_editor_init(void *UNUSED(vedata)) | |||||
| { | |||||
| e_data.ibuf = NULL; | |||||
| e_data.lock = NULL; | |||||
| e_data.texture = NULL; | |||||
| e_data.do_color_management = false; | |||||
| e_data.do_channel_shuffling = false; | |||||
| e_data.cache_handle = NULL; | |||||
| BLI_listbase_clear(&e_data.draw_call_data); | |||||
| e_data.gpu_batch_image = DRW_cache_image_plane_get(); | |||||
| } | |||||
| static void image_uv_editor_cache_init(void *vedata) | |||||
| { | |||||
| IMAGE_UV_EDITOR_Data *ied = (IMAGE_UV_EDITOR_Data *)vedata; | |||||
| IMAGE_UV_EDITOR_PassList *psl = ied->psl; | |||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | |||||
| SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; | |||||
| { | |||||
| psl->image_pass = DRW_pass_create("Image", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS); | |||||
| } | |||||
| { | |||||
| Image *ima = ED_space_image(sima); | |||||
| ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &e_data.lock); | |||||
| image_uv_editor_add_image(psl, ima, &sima->iuser, ibuf); | |||||
| e_data.ibuf = ibuf; | |||||
| } | |||||
| } | |||||
| static void image_uv_editor_cache_populate(void *UNUSED(vedata), Object *UNUSED(ob)) | |||||
| { | |||||
| } | |||||
| static void image_uv_editor_cache_finish(void *UNUSED(vedata)) | |||||
| { | |||||
| } | |||||
| static void image_uv_editor_draw_background(void *UNUSED(vedata)) | |||||
| { | |||||
| static float color[4]; | |||||
| UI_GetThemeColor3fv(TH_BACK, color); | |||||
| DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); | |||||
| GPU_framebuffer_clear_color(dfbl->default_fb, color); | |||||
| } | |||||
| static void image_uv_editor_draw_finish(void *UNUSED(vedata)) | |||||
| { | |||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | |||||
| SpaceImage *sima = (SpaceImage *)draw_ctx->space_data; | |||||
| /* free temp memory */ | |||||
| if (e_data.do_color_management) { | |||||
| GPU_texture_free(e_data.texture); | |||||
| IMB_display_buffer_release(e_data.cache_handle); | |||||
| } | |||||
| ED_space_image_release_buffer(sima, e_data.ibuf, e_data.lock); | |||||
| BLI_freelistN(&e_data.draw_call_data); | |||||
| } | |||||
| static void image_uv_editor_draw_scene(void *vedata) | |||||
| { | |||||
| IMAGE_UV_EDITOR_Data *ied = (IMAGE_UV_EDITOR_Data *)vedata; | |||||
| IMAGE_UV_EDITOR_PassList *psl = ied->psl; | |||||
| DRW_draw_pass(psl->image_pass); | |||||
| image_uv_editor_draw_finish(vedata); | |||||
| } | |||||
| static void image_uv_editor_free(void) | |||||
| { | |||||
| } | |||||
| static const DrawEngineDataSize image_uv_editor_data_size = DRW_VIEWPORT_DATA_SIZE( | |||||
| IMAGE_UV_EDITOR_Data); | |||||
| DrawEngineType draw_engine_image_uv_editor_type = { | |||||
| NULL, | |||||
| NULL, | |||||
| N_("Image/UV Editor"), | |||||
| &image_uv_editor_data_size, | |||||
| &image_uv_editor_init, | |||||
| &image_uv_editor_free, | |||||
| &image_uv_editor_cache_init, | |||||
| &image_uv_editor_cache_populate, | |||||
| &image_uv_editor_cache_finish, | |||||
| &image_uv_editor_draw_background, | |||||
| &image_uv_editor_draw_scene, | |||||
| NULL, | |||||
| NULL, | |||||
| NULL, | |||||
| }; | |||||