diff options
-rw-r--r-- | source/blender/editors/include/BIF_glutil.h | 30 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_icons.c | 21 | ||||
-rw-r--r-- | source/blender/editors/screen/glutil.c | 69 |
3 files changed, 106 insertions, 14 deletions
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 8f2a189e35e..8546c3eae89 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -55,6 +55,36 @@ typedef struct IMMDrawPixelsTexState { IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin); /** + * Unlike the other `immDrawPixelsTex` functions, this doesn't do tiled drawing, but draws into a + * full texture. + * + * Use the currently bound shader. + * + * Use #immDrawPixelsTexSetup to bind the shader you want before calling #immDrawPixelsTex. + * + * If using a special shader double check it uses the same attributes "pos" "texCoord" and uniform + * "image". + * + * If color is NULL then use white by default + * + * Unless <em>state->do_shader_unbind<em> is explicitly set to `false`, the shader is unbound when + * finished. + */ +void immDrawPixelsTexScaledFullSize(const IMMDrawPixelsTexState *state, + const float x, + const float y, + const int img_w, + const int img_h, + const eGPUTextureFormat gpu_format, + const bool use_filter, + const void *rect, + const float scaleX, + const float scaleY, + const float xzoom, + const float yzoom, + const float color[4]); + +/** * #immDrawPixelsTex - Functions like a limited #glDrawPixels, but actually draws the * image using textures, which can be tremendously faster on low-end * cards, and also avoids problems with the raster position being diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index ca5d08ba40e..085b7d04be9 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1546,7 +1546,7 @@ static void icon_draw_rect_fast(float x, immUniform1f("factor", desaturate); } - immDrawPixelsTexScaled( + immDrawPixelsTexScaledFullSize( &state, draw_x, draw_y, rw, rh, GPU_RGBA8, true, rect, scale_x, scale_y, 1.0f, 1.0f, col); } @@ -1561,7 +1561,6 @@ static void icon_draw_rect(float x, float alpha, const float desaturate) { - ImBuf *ima = NULL; int draw_w = w; int draw_h = h; int draw_x = x; @@ -1577,6 +1576,8 @@ static void icon_draw_rect(float x, /* modulate color */ const float col[4] = {alpha, alpha, alpha, alpha}; + float scale_x = 1.0f; + float scale_y = 1.0f; /* rect contains image in 'rendersize', we only scale if needed */ if (rw != w || rh != h) { /* preserve aspect ratio and center */ @@ -1590,13 +1591,9 @@ static void icon_draw_rect(float x, draw_h = h; draw_x += (w - draw_w) / 2; } + scale_x = draw_w / (float)rw; + scale_y = draw_h / (float)rh; /* If the image is squared, the `draw_*` initialization values are good. */ - - /* first allocate imbuf for scaling and copy preview into it */ - ima = IMB_allocImBuf(rw, rh, 32, IB_rect); - memcpy(ima->rect, rect, rw * rh * sizeof(uint)); - IMB_scaleImBuf(ima, draw_w, draw_h); /* scale it */ - rect = ima->rect; } /* draw */ @@ -1613,12 +1610,8 @@ static void icon_draw_rect(float x, immUniform1f("factor", desaturate); } - immDrawPixelsTex( - &state, draw_x, draw_y, draw_w, draw_h, GPU_RGBA8, false, rect, 1.0f, 1.0f, col); - - if (ima) { - IMB_freeImBuf(ima); - } + immDrawPixelsTexScaledFullSize( + &state, draw_x, draw_y, rw, rh, GPU_RGBA8, true, rect, scale_x, scale_y, 1.0f, 1.0f, col); } /* High enough to make a difference, low enough so that diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 5f523df18d1..cb5c5df20ec 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -72,6 +72,75 @@ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) return state; } +void immDrawPixelsTexScaledFullSize(const IMMDrawPixelsTexState *state, + const float x, + const float y, + const int img_w, + const int img_h, + const eGPUTextureFormat gpu_format, + const bool use_filter, + const void *rect, + const float scaleX, + const float scaleY, + const float xzoom, + const float yzoom, + const float color[4]) +{ + const static float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float draw_width = img_w * scaleX * xzoom; + const float draw_height = img_h * scaleY * yzoom; + /* Downscaling with regular bilinear interpolation (i.e. #GL_LINEAR) doesn't give good filtering + * results. Mipmaps can be used to get better results (i.e. #GL_LINEAR_MIPMAP_LINEAR), so always + * use mipmaps when filtering. */ + const bool use_mipmap = use_filter && ((draw_width < img_w) || (draw_height < img_h)); + + GPUTexture *tex = GPU_texture_create_2d("immDrawPixels", img_w, img_h, 1, gpu_format, NULL); + + const bool use_float_data = ELEM(gpu_format, GPU_RGBA16F, GPU_RGB16F, GPU_R16F); + eGPUDataFormat gpu_data_format = (use_float_data) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE; + GPU_texture_update(tex, gpu_data_format, rect); + + GPU_texture_filter_mode(tex, use_filter); + if (use_mipmap) { + GPU_texture_generate_mipmap(tex); + GPU_texture_mipmap_mode(tex, true, true); + } + GPU_texture_wrap_mode(tex, false, true); + + GPU_texture_bind(tex, 0); + + /* optional */ + /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since + * it does not need color. + */ + if (state->shader != NULL && GPU_shader_get_uniform(state->shader, "color") != -1) { + immUniformColor4fv((color) ? color : white); + } + + uint pos = state->pos, texco = state->texco; + + immBegin(GPU_PRIM_TRI_FAN, 4); + immAttr2f(texco, 0.0f, 0.0f); + immVertex2f(pos, x, y); + + immAttr2f(texco, 1.0f, 0.0f); + immVertex2f(pos, x + draw_width, y); + + immAttr2f(texco, 1.0f, 1.0f); + immVertex2f(pos, x + draw_width, y + draw_height); + + immAttr2f(texco, 0.0f, 1.0f); + immVertex2f(pos, x, y + draw_height); + immEnd(); + + if (state->do_shader_unbind) { + immUnbindProgram(); + } + + GPU_texture_unbind(tex); + GPU_texture_free(tex); +} + void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, float x, float y, |