Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/intern/gpu_viewport.c
| Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
| #define MAX_ENGINE_BUFFER_SHARING 5 | #define MAX_ENGINE_BUFFER_SHARING 5 | ||||
| typedef struct ViewportTempTexture { | typedef struct ViewportTempTexture { | ||||
| struct ViewportTempTexture *next, *prev; | struct ViewportTempTexture *next, *prev; | ||||
| void *user[MAX_ENGINE_BUFFER_SHARING]; | void *user[MAX_ENGINE_BUFFER_SHARING]; | ||||
| GPUTexture *texture; | GPUTexture *texture; | ||||
| } ViewportTempTexture; | } ViewportTempTexture; | ||||
| /* Struct storing a viewport specific GPUBatch. | |||||
| * The end-goal is to have a single batch shared across viewport and use a model matrix to place | |||||
| * the batch. Due to OCIO and Image/UV editor we are not able to use an model matrix yet. */ | |||||
| struct GPUViewportBatch { | |||||
fclem: why would it be specific to CM? I would use one batch for all. | |||||
| GPUBatch *batch; | |||||
| struct { | |||||
| rctf rect_pos; | |||||
| rctf rect_uv; | |||||
| } last_used_parameters; | |||||
| } GPUViewportBatch; | |||||
Done Inline Actionsformat and attr_id could be stored globally. jbakker: `format` and `attr_id` could be stored globally. | |||||
| static struct { | |||||
| GPUVertFormat format; | |||||
| struct { | |||||
| uint pos, tex_coord; | |||||
| } attr_id; | |||||
| } g_viewport = {{0}}; | |||||
| struct GPUViewport { | struct GPUViewport { | ||||
| int size[2]; | int size[2]; | ||||
| int flag; | int flag; | ||||
| /* Set the active view (for stereoscoptic viewport rendering). */ | /* Set the active view (for stereoscoptic viewport rendering). */ | ||||
| int active_view; | int active_view; | ||||
| /* If engine_handles mismatch we free all ViewportEngineData in this viewport. */ | /* If engine_handles mismatch we free all ViewportEngineData in this viewport. */ | ||||
| Show All 16 Lines | struct GPUViewport { | ||||
| /* Color management. */ | /* Color management. */ | ||||
| ColorManagedViewSettings view_settings; | ColorManagedViewSettings view_settings; | ||||
| ColorManagedDisplaySettings display_settings; | ColorManagedDisplaySettings display_settings; | ||||
| float dither; | float dither; | ||||
| /* TODO(fclem) the uvimage display use the viewport but do not set any view transform for the | /* TODO(fclem) the uvimage display use the viewport but do not set any view transform for the | ||||
| * moment. The end goal would be to let the GPUViewport do the color management. */ | * moment. The end goal would be to let the GPUViewport do the color management. */ | ||||
| bool do_color_management; | bool do_color_management; | ||||
| struct GPUViewportBatch batch; | |||||
Done Inline Actionsdont use plural here fclem: dont use plural here | |||||
| }; | }; | ||||
| enum { | enum { | ||||
| DO_UPDATE = (1 << 0), | DO_UPDATE = (1 << 0), | ||||
| GPU_VIEWPORT_STEREO = (1 << 1), | GPU_VIEWPORT_STEREO = (1 << 1), | ||||
| }; | }; | ||||
| static void gpu_viewport_buffers_free( | static void gpu_viewport_buffers_free( | ||||
| ▲ Show 20 Lines • Show All 512 Lines • ▼ Show 20 Lines | void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo_format) | ||||
| GPU_matrix_pop(); | GPU_matrix_pop(); | ||||
| if (settings == S3D_DISPLAY_ANAGLYPH) { | if (settings == S3D_DISPLAY_ANAGLYPH) { | ||||
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||||
| } | } | ||||
| GPU_framebuffer_restore(); | GPU_framebuffer_restore(); | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | |||||
| /** \name Viewport Batches | |||||
| * \{ */ | |||||
| static GPUVertFormat *gpu_viewport_batch_format(void) | |||||
| { | |||||
| if (g_viewport.format.attr_len == 0) { | |||||
| GPUVertFormat *format = &g_viewport.format; | |||||
| g_viewport.attr_id.pos = GPU_vertformat_attr_add( | |||||
| format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | |||||
| g_viewport.attr_id.tex_coord = GPU_vertformat_attr_add( | |||||
| format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | |||||
| } | |||||
| return &g_viewport.format; | |||||
| } | |||||
| static GPUBatch *gpu_viewport_batch_create(const rctf *rect_pos, const rctf *rect_uv) | |||||
| { | |||||
| GPUVertBuf *vbo = GPU_vertbuf_create_with_format(gpu_viewport_batch_format()); | |||||
| const uint vbo_len = 4; | |||||
| GPU_vertbuf_data_alloc(vbo, vbo_len); | |||||
| GPUVertBufRaw pos_step, tex_coord_step; | |||||
| GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.pos, &pos_step); | |||||
| GPU_vertbuf_attr_get_raw_data(vbo, g_viewport.attr_id.tex_coord, &tex_coord_step); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymin); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymin); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymin); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymin); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmin, rect_pos->ymax); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmin, rect_uv->ymax); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&pos_step), rect_pos->xmax, rect_pos->ymax); | |||||
| copy_v2_fl2(GPU_vertbuf_raw_step(&tex_coord_step), rect_uv->xmax, rect_uv->ymax); | |||||
Done Inline Actionsuse copy_v2_fl2 fclem: use copy_v2_fl2 | |||||
| return GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); | |||||
| } | |||||
| static GPUBatch *gpu_viewport_batch_get(GPUViewport *viewport, | |||||
| const rctf *rect_pos, | |||||
| const rctf *rect_uv) | |||||
| { | |||||
| const float compare_limit = 0.0001f; | |||||
| const bool parameters_changed = | |||||
| (!BLI_rctf_compare( | |||||
| &viewport->batch.last_used_parameters.rect_pos, rect_pos, compare_limit) || | |||||
| !BLI_rctf_compare(&viewport->batch.last_used_parameters.rect_uv, rect_uv, compare_limit)); | |||||
| if (viewport->batch.batch && parameters_changed) { | |||||
| GPU_batch_discard(viewport->batch.batch); | |||||
| viewport->batch.batch = NULL; | |||||
| } | |||||
| if (!viewport->batch.batch) { | |||||
| viewport->batch.batch = gpu_viewport_batch_create(rect_pos, rect_uv); | |||||
| viewport->batch.last_used_parameters.rect_pos = *rect_pos; | |||||
| viewport->batch.last_used_parameters.rect_uv = *rect_uv; | |||||
| } | |||||
| return viewport->batch.batch; | |||||
| } | |||||
| static void gpu_viewport_batch_free(GPUViewport *viewport) | |||||
| { | |||||
| if (viewport->batch.batch) { | |||||
| GPU_batch_discard(viewport->batch.batch); | |||||
| viewport->batch.batch = NULL; | |||||
| } | |||||
| } | |||||
| /** \} */ | |||||
| static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, | static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, | ||||
| const rctf *rect_pos, | const rctf *rect_pos, | ||||
| const rctf *rect_uv, | const rctf *rect_uv, | ||||
| bool display_colorspace) | bool display_colorspace) | ||||
| { | { | ||||
| DefaultTextureList *dtxl = viewport->txl; | DefaultTextureList *dtxl = viewport->txl; | ||||
| GPUTexture *color = dtxl->color; | GPUTexture *color = dtxl->color; | ||||
| GPUTexture *color_overlay = dtxl->color_overlay; | GPUTexture *color_overlay = dtxl->color_overlay; | ||||
| GPUVertFormat *vert_format = immVertexFormat(); | |||||
| uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | |||||
| uint texco = GPU_vertformat_attr_add(vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); | |||||
| bool use_ocio = false; | bool use_ocio = false; | ||||
| if (viewport->do_color_management && display_colorspace) { | if (viewport->do_color_management && display_colorspace) { | ||||
| use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(&viewport->view_settings, | use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(&viewport->view_settings, | ||||
| &viewport->display_settings, | &viewport->display_settings, | ||||
| NULL, | NULL, | ||||
| viewport->dither, | viewport->dither, | ||||
| false, | false, | ||||
| true); | true); | ||||
| } | } | ||||
| if (!use_ocio) { | GPUBatch *batch = gpu_viewport_batch_get(viewport, rect_pos, rect_uv); | ||||
| immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); | if (use_ocio) { | ||||
| immUniform1i("display_transform", display_colorspace); | GPU_batch_program_set_imm_shader(batch); | ||||
| immUniform1i("image_texture", 0); | } | ||||
| immUniform1i("overlays_texture", 1); | else { | ||||
| GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); | |||||
| GPU_batch_uniform_1i(batch, "display_transform", display_colorspace); | |||||
| GPU_batch_uniform_1i(batch, "image_texture", 0); | |||||
| GPU_batch_uniform_1i(batch, "overlays_texture", 1); | |||||
| } | } | ||||
| GPU_texture_bind(color, 0); | GPU_texture_bind(color, 0); | ||||
| GPU_texture_bind(color_overlay, 1); | GPU_texture_bind(color_overlay, 1); | ||||
| GPU_batch_draw(batch); | |||||
| immBegin(GPU_PRIM_TRI_STRIP, 4); | |||||
| immAttr2f(texco, rect_uv->xmin, rect_uv->ymin); | |||||
| immVertex2f(pos, rect_pos->xmin, rect_pos->ymin); | |||||
| immAttr2f(texco, rect_uv->xmax, rect_uv->ymin); | |||||
| immVertex2f(pos, rect_pos->xmax, rect_pos->ymin); | |||||
| immAttr2f(texco, rect_uv->xmin, rect_uv->ymax); | |||||
| immVertex2f(pos, rect_pos->xmin, rect_pos->ymax); | |||||
| immAttr2f(texco, rect_uv->xmax, rect_uv->ymax); | |||||
| immVertex2f(pos, rect_pos->xmax, rect_pos->ymax); | |||||
| immEnd(); | |||||
| GPU_texture_unbind(color); | GPU_texture_unbind(color); | ||||
| GPU_texture_unbind(color_overlay); | GPU_texture_unbind(color_overlay); | ||||
| if (use_ocio) { | if (use_ocio) { | ||||
| IMB_colormanagement_finish_glsl_draw(); | IMB_colormanagement_finish_glsl_draw(); | ||||
| } | } | ||||
| else { | |||||
| immUnbindProgram(); | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| * Version of #GPU_viewport_draw_to_screen() that lets caller decide if display colorspace | * Version of #GPU_viewport_draw_to_screen() that lets caller decide if display colorspace | ||||
| * transform should be performed. | * transform should be performed. | ||||
| */ | */ | ||||
| void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, | void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, | ||||
| int view, | int view, | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, | ||||
| gpu_viewport_draw_colormanaged(viewport, &pos_rect, &uv_rect, display_colorspace); | gpu_viewport_draw_colormanaged(viewport, &pos_rect, &uv_rect, display_colorspace); | ||||
| } | } | ||||
| /** | /** | ||||
| * Merge and draw the buffers of \a viewport into the currently active framebuffer, performing | * Merge and draw the buffers of \a viewport into the currently active framebuffer, performing | ||||
| * color transform to display space. | * color transform to display space. | ||||
| * | * | ||||
| * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done with | * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done | ||||
| * inversed axis coordinates (upside down or sideways). | * with inversed axis coordinates (upside down or sideways). | ||||
| */ | */ | ||||
| void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect) | void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect) | ||||
| { | { | ||||
| GPU_viewport_draw_to_screen_ex(viewport, view, rect, true); | GPU_viewport_draw_to_screen_ex(viewport, view, rect, true); | ||||
| } | } | ||||
| /** | /** | ||||
| * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`. | * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`. | ||||
| ▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | for (int i = 0; i < viewport->vmempool.ubo_len; i++) { | ||||
| GPU_uniformbuffer_free(viewport->vmempool.obinfos_ubo[i]); | GPU_uniformbuffer_free(viewport->vmempool.obinfos_ubo[i]); | ||||
| } | } | ||||
| MEM_SAFE_FREE(viewport->vmempool.matrices_ubo); | MEM_SAFE_FREE(viewport->vmempool.matrices_ubo); | ||||
| MEM_SAFE_FREE(viewport->vmempool.obinfos_ubo); | MEM_SAFE_FREE(viewport->vmempool.obinfos_ubo); | ||||
| DRW_instance_data_list_free(viewport->idatalist); | DRW_instance_data_list_free(viewport->idatalist); | ||||
| MEM_freeN(viewport->idatalist); | MEM_freeN(viewport->idatalist); | ||||
| gpu_viewport_batch_free(viewport); | |||||
| MEM_freeN(viewport); | MEM_freeN(viewport); | ||||
| } | } | ||||
why would it be specific to CM? I would use one batch for all.