diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-02-11 17:18:55 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-02-11 17:19:04 +0300 |
commit | 804e90b42d728ecb1073af8d0bae15a91b13a469 (patch) | |
tree | 309de25d99c92286b10c9d27e547fd43a69299c1 /source/blender/gpu | |
parent | 58cdab8b9759dd59b55895f2f76b9624addbb324 (diff) |
DRW: Color Management improvement
Reviewed By: brecht sergey jbakker
Differential Revision: http://developer.blender.org/D6729
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/gpu/GPU_batch.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/GPU_shader.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/GPU_viewport.h | 11 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_batch.c | 11 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_immediate.c | 7 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 6 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader_private.h | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 335 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl | 33 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl | 42 |
14 files changed, 283 insertions, 182 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 25f9ef886e9..ea8bcfda92c 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -168,7 +168,7 @@ data_to_c_simple(shaders/gpu_shader_2D_image_rect_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_desaturate_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_image_linear_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_image_overlays_merge_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC) diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 3616189e673..fc7dff5d99b 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -126,6 +126,7 @@ int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo); void GPU_batch_program_set_no_use(GPUBatch *, uint32_t program, const GPUShaderInterface *); void GPU_batch_program_set(GPUBatch *, uint32_t program, const GPUShaderInterface *); void GPU_batch_program_set_shader(GPUBatch *, GPUShader *shader); +void GPU_batch_program_set_imm_shader(GPUBatch *batch); void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id); void GPU_batch_program_set_builtin_with_config(GPUBatch *batch, eGPUBuiltinShader shader_id, diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index e877646310b..1339873ec67 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -183,7 +183,7 @@ typedef enum eGPUBuiltinShader { GPU_SHADER_3D_DEPTH_ONLY, GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR, /* basic image drawing */ - GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB, + GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE, GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR, GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR, /** diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 73ea9da0fe6..4e24a3172dc 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -99,6 +99,7 @@ typedef enum eGPUTextureFormat { GPU_R11F_G11F_B10F, GPU_DEPTH32F_STENCIL8, GPU_DEPTH24_STENCIL8, + GPU_SRGB8_A8, /* Texture only format */ GPU_RGB16F, @@ -124,7 +125,6 @@ typedef enum eGPUTextureFormat { /* Special formats texture only */ #if 0 - GPU_SRGB8_A8, GPU_SRGB8, GPU_RGB9_E5, GPU_COMPRESSED_RG_RGTC2, diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index e692262358b..2d125032f47 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -102,8 +102,15 @@ void GPU_viewport_unbind(GPUViewport *viewport); void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect); void GPU_viewport_free(GPUViewport *viewport); -GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs); -void GPU_viewport_clear_from_offscreen(GPUViewport *viewport); +void GPU_viewport_colorspace_set(GPUViewport *viewport, + ColorManagedViewSettings *view_settings, + ColorManagedDisplaySettings *display_settings, + float dither); + +void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen *ofs); +void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, + struct GPUOffScreen *ofs, + bool display_colorspace); ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport); struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport); diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 6b5d3053594..75989db9ecf 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -979,6 +979,17 @@ void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id) GPU_batch_program_set_builtin_with_config(batch, shader_id, GPU_SHADER_CFG_DEFAULT); } +/* Bind program bound to IMM to the batch. + * XXX Use this with much care. Drawing with the GPUBatch API is not compatible with IMM. + * DO NOT DRAW WITH THE BATCH BEFORE CALLING immUnbindProgram. */ +void GPU_batch_program_set_imm_shader(GPUBatch *batch) +{ + GLuint program; + GPUShaderInterface *interface; + immGetProgram(&program, &interface); + GPU_batch_program_set(batch, program, interface); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index a531c22365c..b0fbb0eae49 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -513,6 +513,7 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) if (GPU_framebuffer_active_get() != fb) { glBindFramebuffer(GL_FRAMEBUFFER, fb->object); + glEnable(GL_FRAMEBUFFER_SRGB); } gpu_framebuffer_current_set(fb); @@ -547,6 +548,7 @@ void GPU_framebuffer_restore(void) if (GPU_framebuffer_active_get() != NULL) { glBindFramebuffer(GL_FRAMEBUFFER, GPU_framebuffer_default()); gpu_framebuffer_current_set(NULL); + glDisable(GL_FRAMEBUFFER_SRGB); } } diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index bed7ab25bb9..bd3de96d636 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -168,6 +168,13 @@ void immUnbindProgram(void) imm.bound_program = 0; } +/* XXX do not use it. Special hack to use OCIO with batch API. */ +void immGetProgram(GLuint *program, GPUShaderInterface **shaderface) +{ + *program = imm.bound_program; + *shaderface = (GPUShaderInterface *)imm.shader_interface; +} + #if TRUST_NO_ONE static bool vertex_count_makes_sense_for_primitive(uint vertex_len, GPUPrimType prim_type) { diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index ae2c7864e36..c950a1daaa5 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -80,7 +80,7 @@ extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[]; extern char datatoc_gpu_shader_3D_image_vert_glsl[]; extern char datatoc_gpu_shader_image_frag_glsl[]; -extern char datatoc_gpu_shader_image_linear_frag_glsl[]; +extern char datatoc_gpu_shader_image_overlays_merge_frag_glsl[]; extern char datatoc_gpu_shader_image_color_frag_glsl[]; extern char datatoc_gpu_shader_image_desaturate_frag_glsl[]; extern char datatoc_gpu_shader_image_varying_color_frag_glsl[]; @@ -1008,10 +1008,10 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl, .frag = datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl, }, - [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = + [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] = { .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_linear_frag_glsl, + .frag = datatoc_gpu_shader_image_overlays_merge_frag_glsl, }, [GPU_SHADER_2D_IMAGE] = { diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h index 856a14c6868..e4443e79a8d 100644 --- a/source/blender/gpu/intern/gpu_shader_private.h +++ b/source/blender/gpu/intern/gpu_shader_private.h @@ -44,4 +44,7 @@ struct GPUShader { #endif }; +/* XXX do not use it. Special hack to use OCIO with batch API. */ +void immGetProgram(GLuint *program, GPUShaderInterface **shaderface); + #endif /* __GPU_SHADER_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 84328b8dfd4..ccafc785526 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -51,7 +51,7 @@ static struct GPUTextureGlobal { } GG = {NULL, NULL, NULL}; /* Maximum number of FBOs a texture can be attached to. */ -#define GPU_TEX_MAX_FBO_ATTACHED 10 +#define GPU_TEX_MAX_FBO_ATTACHED 12 typedef enum eGPUTextureFormatFlag { GPU_FORMAT_DEPTH = (1 << 0), @@ -183,6 +183,7 @@ static int gpu_get_component_count(eGPUTextureFormat format) case GPU_RGBA16F: case GPU_RGBA16: case GPU_RGBA32F: + case GPU_SRGB8_A8: return 4; case GPU_RGB16F: case GPU_R11F_G11F_B10F: @@ -221,7 +222,7 @@ static void gpu_validate_data_format(eGPUTextureFormat tex_format, eGPUDataForma } } /* Byte formats */ - else if (ELEM(tex_format, GPU_R8, GPU_RG8, GPU_RGBA8, GPU_RGBA8UI)) { + else if (ELEM(tex_format, GPU_R8, GPU_RG8, GPU_RGBA8, GPU_RGBA8UI, GPU_SRGB8_A8)) { BLI_assert(ELEM(data_format, GPU_DATA_UNSIGNED_BYTE, GPU_DATA_FLOAT)); } /* Special case */ @@ -349,6 +350,7 @@ static uint gpu_get_bytesize(eGPUTextureFormat data_type) case GPU_DEPTH_COMPONENT32F: case GPU_RGBA8UI: case GPU_RGBA8: + case GPU_SRGB8_A8: case GPU_R11F_G11F_B10F: case GPU_R32F: case GPU_R32UI: @@ -398,6 +400,8 @@ static GLenum gpu_get_gl_internalformat(eGPUTextureFormat format) return GL_RGBA8; case GPU_RGBA8UI: return GL_RGBA8UI; + case GPU_SRGB8_A8: + return GL_SRGB8_ALPHA8; case GPU_R32F: return GL_R32F; case GPU_R32UI: diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 972ff87ebcf..a3ee2d11e56 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -27,8 +27,13 @@ #include "BLI_listbase.h" #include "BLI_rect.h" +#include "BLI_math_vector.h" #include "BLI_memblock.h" +#include "BKE_colortools.h" + +#include "IMB_colormanagement.h" + #include "DNA_vec_types.h" #include "DNA_userdef_types.h" @@ -61,7 +66,6 @@ typedef struct ViewportTempTexture { struct GPUViewport { int size[2]; - int samples; int flag; /* If engine_handles mismatch we free all ViewportEngineData in this viewport */ @@ -80,6 +84,14 @@ struct GPUViewport { /* Profiling data */ double cache_time; + + /* Color management. */ + ColorManagedViewSettings view_settings; + ColorManagedDisplaySettings display_settings; + float dither; + /* 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. */ + bool do_color_management; }; enum { @@ -93,7 +105,6 @@ static void gpu_viewport_buffers_free(FramebufferList *fbl, static void gpu_viewport_storage_free(StorageList *stl, int stl_len); static void gpu_viewport_passes_free(PassList *psl, int psl_len); static void gpu_viewport_texture_pool_free(GPUViewport *viewport); -static void gpu_viewport_default_fb_create(GPUViewport *viewport, const bool high_bitdepth); void GPU_viewport_tag_update(GPUViewport *viewport) { @@ -113,67 +124,13 @@ GPUViewport *GPU_viewport_create(void) viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList"); viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList"); viewport->idatalist = DRW_instance_data_list_create(); + viewport->do_color_management = false; viewport->size[0] = viewport->size[1] = -1; return viewport; } -GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs) -{ - GPUViewport *viewport = GPU_viewport_create(); - GPUTexture *color, *depth; - GPUFrameBuffer *fb; - viewport->size[0] = GPU_offscreen_width(ofs); - viewport->size[1] = GPU_offscreen_height(ofs); - - GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth); - - if (GPU_texture_samples(color)) { - viewport->txl->multisample_color = color; - viewport->txl->multisample_depth = depth; - viewport->fbl->multisample_fb = fb; - gpu_viewport_default_fb_create(viewport, true); - } - else { - viewport->fbl->default_fb = fb; - viewport->txl->color = color; - viewport->txl->depth = depth; - GPU_framebuffer_ensure_config( - &viewport->fbl->color_only_fb, - {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(viewport->txl->color)}); - GPU_framebuffer_ensure_config( - &viewport->fbl->depth_only_fb, - {GPU_ATTACHMENT_TEXTURE(viewport->txl->depth), GPU_ATTACHMENT_NONE}); - /* TODO infront buffer */ - } - - return viewport; -} -/** - * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`. - */ -void GPU_viewport_clear_from_offscreen(GPUViewport *viewport) -{ - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - - if (dfbl->multisample_fb) { - /* GPUViewport expect the final result to be in default_fb but - * GPUOffscreen wants it in its multisample_fb, so we sync it back. */ - GPU_framebuffer_blit( - dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT); - dfbl->multisample_fb = NULL; - dtxl->multisample_color = NULL; - dtxl->multisample_depth = NULL; - } - else { - viewport->fbl->default_fb = NULL; - dtxl->color = NULL; - dtxl->depth = NULL; - } -} - void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) { ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); @@ -268,8 +225,7 @@ void *GPU_viewport_texture_list_get(GPUViewport *viewport) void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]) { - size[0] = viewport->size[0]; - size[1] = viewport->size[1]; + copy_v2_v2_int(size, viewport->size); } /** @@ -279,8 +235,7 @@ void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]) */ void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]) { - viewport->size[0] = size[0]; - viewport->size[1] = size[1]; + copy_v2_v2_int(viewport->size, size); } double *GPU_viewport_cache_time_get(GPUViewport *viewport) @@ -383,69 +338,61 @@ void GPU_viewport_cache_release(GPUViewport *viewport) } } -static void gpu_viewport_default_fb_create(GPUViewport *viewport, const bool high_bitdepth) +static void gpu_viewport_default_fb_create(GPUViewport *viewport) { DefaultFramebufferList *dfbl = viewport->fbl; DefaultTextureList *dtxl = viewport->txl; int *size = viewport->size; bool ok = true; - dtxl->color = GPU_texture_create_2d( - size[0], size[1], high_bitdepth ? GPU_RGBA16F : GPU_RGBA8, NULL, NULL); - dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL); + dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL); + dtxl->color_overlay = GPU_texture_create_2d(size[0], size[1], GPU_SRGB8_A8, NULL, NULL); - if (!(dtxl->depth && dtxl->color)) { + /* Can be shared with GPUOffscreen. */ + if (dtxl->depth == NULL) { + dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL); + } + + if (!dtxl->depth || !dtxl->color) { ok = false; goto cleanup; } - GPU_framebuffer_ensure_config( - &dfbl->default_fb, - {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)}); + GPU_framebuffer_ensure_config(&dfbl->default_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(dtxl->color), + }); + + GPU_framebuffer_ensure_config(&dfbl->overlay_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), + }); GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, - {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_NONE}); + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_NONE, + }); GPU_framebuffer_ensure_config(&dfbl->color_only_fb, - {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(dtxl->color)}); + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(dtxl->color), + }); + + GPU_framebuffer_ensure_config(&dfbl->overlay_only_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), + }); ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->overlay_fb, NULL); ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL); ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL); - -cleanup: - if (!ok) { - GPU_viewport_free(viewport); - DRW_opengl_context_disable(); - return; - } - - GPU_framebuffer_restore(); -} - -static void gpu_viewport_default_multisample_fb_create(GPUViewport *viewport) -{ - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - int *size = viewport->size; - int samples = viewport->samples; - bool ok = true; - - dtxl->multisample_color = GPU_texture_create_2d_multisample( - size[0], size[1], GPU_RGBA8, NULL, samples, NULL); - dtxl->multisample_depth = GPU_texture_create_2d_multisample( - size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, samples, NULL); - - if (!(dtxl->multisample_depth && dtxl->multisample_color)) { - ok = false; - goto cleanup; - } - - GPU_framebuffer_ensure_config(&dfbl->multisample_fb, - {GPU_ATTACHMENT_TEXTURE(dtxl->multisample_depth), - GPU_ATTACHMENT_TEXTURE(dtxl->multisample_color)}); - - ok = ok && GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->overlay_only_fb, NULL); cleanup: if (!ok) { @@ -462,15 +409,15 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) DefaultFramebufferList *dfbl = viewport->fbl; int fbl_len, txl_len; + int rect_size[2]; /* add one pixel because of scissor test */ - int rect_w = BLI_rcti_size_x(rect) + 1; - int rect_h = BLI_rcti_size_y(rect) + 1; + rect_size[0] = BLI_rcti_size_x(rect) + 1; + rect_size[1] = BLI_rcti_size_y(rect) + 1; DRW_opengl_context_enable(); if (dfbl->default_fb) { - if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || - U.ogl_multisamples != viewport->samples) { + if (!equals_v2v2_int(viewport->size, rect_size)) { gpu_viewport_buffers_free((FramebufferList *)viewport->fbl, default_fbl_len, (TextureList *)viewport->txl, @@ -486,36 +433,115 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) } } - viewport->size[0] = rect_w; - viewport->size[1] = rect_h; - viewport->samples = U.ogl_multisamples; + copy_v2_v2_int(viewport->size, rect_size); gpu_viewport_texture_pool_clear_users(viewport); - /* Multisample Buffer */ - if (viewport->samples > 0) { - if (!dfbl->default_fb) { - gpu_viewport_default_multisample_fb_create(viewport); - } + if (!dfbl->default_fb) { + gpu_viewport_default_fb_create(viewport); } +} + +void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen *ofs) +{ + DefaultFramebufferList *dfbl = viewport->fbl; + DefaultTextureList *dtxl = viewport->txl; + GPUTexture *color, *depth; + GPUFrameBuffer *fb; + viewport->size[0] = GPU_offscreen_width(ofs); + viewport->size[1] = GPU_offscreen_height(ofs); + + GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth); + + /* This is the only texture we can share. */ + dtxl->depth = depth; + + gpu_viewport_texture_pool_clear_users(viewport); if (!dfbl->default_fb) { - gpu_viewport_default_fb_create(viewport, false); + gpu_viewport_default_fb_create(viewport); + } +} + +void GPU_viewport_colorspace_set(GPUViewport *viewport, + ColorManagedViewSettings *view_settings, + ColorManagedDisplaySettings *display_settings, + float dither) +{ + memcpy(&viewport->view_settings, view_settings, sizeof(*view_settings)); + memcpy(&viewport->display_settings, display_settings, sizeof(*display_settings)); + viewport->dither = dither; + viewport->do_color_management = true; +} + +static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, + const rctf *rect_pos, + const rctf *rect_uv, + bool display_colorspace) +{ + DefaultTextureList *dtxl = viewport->txl; + GPUTexture *color = dtxl->color; + 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; + + if (viewport->do_color_management && display_colorspace) { + use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(&viewport->view_settings, + &viewport->display_settings, + NULL, + viewport->dither, + false, + true); + } + + if (!use_ocio) { + immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE); + immUniform1i("display_transform", display_colorspace); + immUniform1i("image_texture", 0); + immUniform1i("overlays_texture", 1); + } + + GPU_texture_bind(color, 0); + GPU_texture_bind(color_overlay, 1); + + 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_overlay); + + if (use_ocio) { + IMB_colormanagement_finish_glsl_draw(); + } + else { + immUnbindProgram(); } } void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect) { DefaultFramebufferList *dfbl = viewport->fbl; + DefaultTextureList *dtxl = viewport->txl; + GPUTexture *color = dtxl->color; if (dfbl->default_fb == NULL) { return; } - DefaultTextureList *dtxl = viewport->txl; - - GPUTexture *color = dtxl->color; - const float w = (float)GPU_texture_width(color); const float h = (float)GPU_texture_height(color); @@ -526,27 +552,58 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect) const float halfx = GLA_PIXEL_OFS / w; const float halfy = GLA_PIXEL_OFS / h; - float x1 = rect->xmin; - float x2 = rect->xmin + w; - float y1 = rect->ymin; - float y2 = rect->ymin + h; + rctf pos_rect = { + .xmin = rect->xmin, + .ymin = rect->ymin, + .xmax = rect->xmin + w, + .ymax = rect->ymin + h, + }; + + rctf uv_rect = { + .xmin = halfx, + .ymin = halfy, + .xmax = halfx + 1.0f, + .ymax = halfy + 1.0f, + }; + + gpu_viewport_draw_colormanaged(viewport, &pos_rect, &uv_rect, true); +} - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); - GPU_shader_bind(shader); +/** + * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`. + */ +void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, + struct GPUOffScreen *ofs, + bool display_colorspace) +{ + DefaultFramebufferList *dfbl = viewport->fbl; + DefaultTextureList *dtxl = viewport->txl; - GPU_texture_bind(color, 0); - glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), - halfx, - halfy, - 1.0f + halfx, - 1.0f + halfy); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x1, y1, x2, y2); - glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f); + if (dfbl->default_fb == NULL) { + return; + } - GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4); + GPU_depth_test(false); + GPU_offscreen_bind(ofs, false); - GPU_texture_unbind(color); + rctf pos_rect = { + .xmin = -1.0f, + .ymin = -1.0f, + .xmax = 1.0f, + .ymax = 1.0f, + }; + + rctf uv_rect = { + .xmin = 0.0f, + .ymin = 0.0f, + .xmax = 1.0f, + .ymax = 1.0f, + }; + + gpu_viewport_draw_colormanaged(viewport, &pos_rect, &uv_rect, display_colorspace); + + /* This one is from the offscreen. Don't free it with the viewport. */ + dtxl->depth = NULL; } void GPU_viewport_unbind(GPUViewport *UNUSED(viewport)) diff --git a/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl deleted file mode 100644 index e6acdd446d3..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl +++ /dev/null @@ -1,33 +0,0 @@ - -/* Display a linear image texture into sRGB space */ - -uniform sampler2D image; - -in vec2 texCoord_interp; - -out vec4 fragColor; - -float linearrgb_to_srgb(float c) -{ - if (c < 0.0031308) { - return (c < 0.0) ? 0.0 : c * 12.92; - } - else { - return 1.055 * pow(c, 1.0 / 2.4) - 0.055; - } -} - -void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) -{ - col_to.r = linearrgb_to_srgb(col_from.r); - col_to.g = linearrgb_to_srgb(col_from.g); - col_to.b = linearrgb_to_srgb(col_from.b); - col_to.a = col_from.a; -} - -void main() -{ - fragColor = texture(image, texCoord_interp.st); - - linearrgb_to_srgb(fragColor, fragColor); -} diff --git a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl new file mode 100644 index 00000000000..e8323520af5 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -0,0 +1,42 @@ + +/* Merge overlays texture on top of image texture and transform to display space (assume sRGB) */ + +uniform sampler2D image_texture; +uniform sampler2D overlays_texture; +uniform bool display_transform; + +in vec2 texCoord_interp; + +out vec4 fragColor; + +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } +} + +void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) +{ + col_to.r = linearrgb_to_srgb(col_from.r); + col_to.g = linearrgb_to_srgb(col_from.g); + col_to.b = linearrgb_to_srgb(col_from.b); + col_to.a = col_from.a; +} + +void main() +{ + fragColor = texture(image_texture, texCoord_interp.st); + + vec4 overlay_col = texture(overlays_texture, texCoord_interp.st); + + fragColor *= 1.0 - overlay_col.a; + fragColor += overlay_col; + + if (display_transform) { + linearrgb_to_srgb(fragColor, fragColor); + } +} |