Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-02-11 17:18:55 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-02-11 17:19:04 +0300
commit804e90b42d728ecb1073af8d0bae15a91b13a469 (patch)
tree309de25d99c92286b10c9d27e547fd43a69299c1 /source/blender/gpu/intern/gpu_viewport.c
parent58cdab8b9759dd59b55895f2f76b9624addbb324 (diff)
DRW: Color Management improvement
Reviewed By: brecht sergey jbakker Differential Revision: http://developer.blender.org/D6729
Diffstat (limited to 'source/blender/gpu/intern/gpu_viewport.c')
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c335
1 files changed, 196 insertions, 139 deletions
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))