Fix T81751: Use GLSL for better anim player performance

Originally colorspace of float images was converted using CPU.
GLSL will render images much faster.

Originally image was converted to `global_role_default_byte` space,
disregarding view transform and also display device, which now is
possible to specify. These parameters could be set via commandline to
settings used in Blender, however if they are to be set by users, these
needs to be sanitized.
Right now defaults are assumed for device given for
`COLOR_ROLE_DEFAULT_BYTE`. This should produce same behavior as
implemented before.

Together with D11167 animation player performance should be much better.

This code was mostly copy-pasted from sequencer.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D11178
This commit is contained in:
Richard Antalik 2021-05-07 09:43:26 +02:00
parent 7b9c865afc
commit fd3e44492e
Notes: blender-bot 2023-07-18 14:11:06 +02:00
Referenced by commit 5ec6bcd474, Fix PlayAnim X/Y flipping
Referenced by issue #88194, Animation player displays washed out colors
Referenced by issue #81751, Poor playback performance with large float images in the animation-player
Referenced by issue #110204, Animation Player draws non-uniformly scaled when resizing window
Referenced by pull request #110206, Fix #110204: Anim Player draws non-uniformly scaled when resizing window
Referenced by commit c275f4219f, Fix #110204: Anim Player draws non-uniformly scaled when resizing window
1 changed files with 148 additions and 20 deletions

View File

@ -47,9 +47,11 @@
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@ -138,6 +140,9 @@ typedef struct PlayState {
bool need_frame_update;
int frame_cursor_x;
ColorManagedViewSettings view_settings;
ColorManagedDisplaySettings display_settings;
} PlayState;
/* for debugging */
@ -288,6 +293,144 @@ static int pupdate_time(void)
return (ptottime < 0);
}
static void *ocio_transform_ibuf(PlayState *ps,
ImBuf *ibuf,
bool *r_glsl_used,
eGPUTextureFormat *r_format,
eGPUDataFormat *r_data,
void **r_buffer_cache_handle)
{
void *display_buffer;
bool force_fallback = false;
*r_glsl_used = false;
force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
force_fallback |= (ibuf->dither != 0.0f);
/* Default */
*r_format = GPU_RGBA8;
*r_data = GPU_DATA_UBYTE;
/* Fallback to CPU based color space conversion. */
if (force_fallback) {
*r_glsl_used = false;
display_buffer = NULL;
}
else if (ibuf->rect_float) {
display_buffer = ibuf->rect_float;
*r_data = GPU_DATA_FLOAT;
if (ibuf->channels == 4) {
*r_format = GPU_RGBA16F;
}
else if (ibuf->channels == 3) {
/* Alpha is implicitly 1. */
*r_format = GPU_RGB16F;
}
if (ibuf->float_colorspace) {
*r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space(&ps->view_settings,
&ps->display_settings,
ibuf->float_colorspace,
ibuf->dither,
false,
false);
}
else {
*r_glsl_used = IMB_colormanagement_setup_glsl_draw(
&ps->view_settings, &ps->display_settings, ibuf->dither, false);
}
}
else if (ibuf->rect) {
display_buffer = ibuf->rect;
*r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space(&ps->view_settings,
&ps->display_settings,
ibuf->float_colorspace,
ibuf->dither,
false,
false);
}
else {
display_buffer = NULL;
}
/* There is data to be displayed, but GLSL is not initialized
* properly, in this case we fallback to CPU-based display transform. */
if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) {
display_buffer = IMB_display_buffer_acquire(
ibuf, &ps->view_settings, &ps->display_settings, r_buffer_cache_handle);
*r_format = GPU_RGBA8;
*r_data = GPU_DATA_UBYTE;
}
return display_buffer;
}
static void draw_display_buffer(PlayState *ps, ImBuf *ibuf)
{
void *display_buffer;
/* Format needs to be created prior to any #immBindShader call.
* Do it here because OCIO binds its own shader. */
eGPUTextureFormat format;
eGPUDataFormat data;
bool glsl_used = false;
GPUVertFormat *imm_format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
uint texCoord = GPU_vertformat_attr_add(
imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
void *buffer_cache_handle = NULL;
display_buffer = ocio_transform_ibuf(ps, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
GPUTexture *texture = GPU_texture_create_2d("display_buf", ibuf->x, ibuf->y, 1, format, NULL);
GPU_texture_update(texture, data, display_buffer);
GPU_texture_filter_mode(texture, false);
GPU_texture_bind(texture, 0);
if (!glsl_used) {
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
immUniformColor3f(1.0f, 1.0f, 1.0f);
immUniform1i("image", 0);
}
immBegin(GPU_PRIM_TRI_FAN, 4);
rctf preview;
rctf canvas;
BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
BLI_rctf_init(&preview, 0.0f, 1.0f, 0.0f, 1.0f);
immAttr2f(texCoord, canvas.xmin, canvas.ymin);
immVertex2f(pos, preview.xmin, preview.ymin);
immAttr2f(texCoord, canvas.xmin, canvas.ymax);
immVertex2f(pos, preview.xmin, preview.ymax);
immAttr2f(texCoord, canvas.xmax, canvas.ymax);
immVertex2f(pos, preview.xmax, preview.ymax);
immAttr2f(texCoord, canvas.xmax, canvas.ymin);
immVertex2f(pos, preview.xmax, preview.ymin);
immEnd();
GPU_texture_unbind(texture);
GPU_texture_free(texture);
if (!glsl_used) {
immUnbindProgram();
}
else {
IMB_colormanagement_finish_glsl_draw();
}
if (buffer_cache_handle) {
IMB_display_buffer_release(buffer_cache_handle);
}
}
static void playanim_toscreen(
PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
{
@ -295,13 +438,6 @@ static void playanim_toscreen(
printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
return;
}
if (ibuf->rect == NULL && ibuf->rect_float) {
IMB_rect_from_float(ibuf);
imb_freerectfloatImBuf(ibuf);
}
if (ibuf->rect == NULL) {
return;
}
GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);
@ -331,19 +467,7 @@ static void playanim_toscreen(
8);
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
immDrawPixelsTex(&state,
offs_x + (ps->draw_flip[0] ? span_x : 0.0f),
offs_y + (ps->draw_flip[1] ? span_y : 0.0f),
ibuf->x,
ibuf->y,
GPU_RGBA8,
false,
ibuf->rect,
((ps->draw_flip[0] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_x),
((ps->draw_flip[1] ? -1.0f : 1.0f)) * (ps->zoom / (float)ps->win_y),
NULL);
draw_display_buffer(ps, ibuf);
GPU_blend(GPU_BLEND_NONE);
@ -1178,6 +1302,10 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
ps.fontid = -1;
STRNCPY(ps.display_settings.display_device,
IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE));
IMB_colormanagement_init_default_view_settings(&ps.view_settings, &ps.display_settings);
while (argc > 1) {
if (argv[1][0] == '-') {
switch (argv[1][1]) {