Opengl glaDrawPixels removal: image_draw.c
Using float buffer is still laggy because of the data volume we have to transfer to the GC.
This commit is contained in:
parent
2ea5446197
commit
ab8958bbd5
|
@ -71,6 +71,8 @@
|
|||
#include "ED_render.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
#include "UI_view2d.h"
|
||||
|
@ -406,63 +408,36 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
|
|||
}
|
||||
|
||||
/* image drawing */
|
||||
|
||||
static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti)
|
||||
static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *rect,
|
||||
float zoomx, float zoomy)
|
||||
{
|
||||
|
||||
/* swap bytes, so alpha is most significant one, then just draw it as luminance int */
|
||||
if (ENDIAN_ORDER == B_ENDIAN)
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
|
||||
float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_UNSIGNED_INT, recti);
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
|
||||
/* Slowwww */
|
||||
int *recti = MEM_mallocN(rectx * recty * sizeof(int), "temp");
|
||||
for (int a = rectx * recty - 1; a >= 0; a--) {
|
||||
/* zbuffer values are signed, so we need to shift color range */
|
||||
recti[a] = rect[a] * 0.5f + 0.5f;
|
||||
}
|
||||
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
|
||||
GPU_shader_bind(shader);
|
||||
GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red);
|
||||
|
||||
immDrawPixelsTex(x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL);
|
||||
|
||||
GPU_shader_unbind();
|
||||
|
||||
MEM_freeN(recti);
|
||||
}
|
||||
|
||||
static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, float *rectf)
|
||||
{
|
||||
float *trectf = MEM_mallocN(rectx * recty * 4, "temp");
|
||||
int a, b;
|
||||
|
||||
for (a = rectx * recty - 1, b = 4 * a + 3; a >= 0; a--, b -= 4)
|
||||
trectf[a] = rectf[b];
|
||||
|
||||
glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, trectf);
|
||||
MEM_freeN(trectf);
|
||||
/* ogl trick below is slower... (on ATI 9600) */
|
||||
// glColorMask(1, 0, 0, 0);
|
||||
// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 3);
|
||||
// glColorMask(0, 1, 0, 0);
|
||||
// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 2);
|
||||
// glColorMask(0, 0, 1, 0);
|
||||
// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 1);
|
||||
// glColorMask(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti)
|
||||
{
|
||||
/* zbuffer values are signed, so we need to shift color range */
|
||||
glPixelTransferf(GL_RED_SCALE, 0.5f);
|
||||
glPixelTransferf(GL_GREEN_SCALE, 0.5f);
|
||||
glPixelTransferf(GL_BLUE_SCALE, 0.5f);
|
||||
glPixelTransferf(GL_RED_BIAS, 0.5f);
|
||||
glPixelTransferf(GL_GREEN_BIAS, 0.5f);
|
||||
glPixelTransferf(GL_BLUE_BIAS, 0.5f);
|
||||
|
||||
glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_INT, recti);
|
||||
|
||||
glPixelTransferf(GL_RED_SCALE, 1.0f);
|
||||
glPixelTransferf(GL_GREEN_SCALE, 1.0f);
|
||||
glPixelTransferf(GL_BLUE_SCALE, 1.0f);
|
||||
glPixelTransferf(GL_RED_BIAS, 0.0f);
|
||||
glPixelTransferf(GL_GREEN_BIAS, 0.0f);
|
||||
glPixelTransferf(GL_BLUE_BIAS, 0.0f);
|
||||
}
|
||||
|
||||
static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, float *rect_float)
|
||||
static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty,
|
||||
float *rect_float, float zoomx, float zoomy)
|
||||
{
|
||||
float bias, scale, *rectf, clipend;
|
||||
int a;
|
||||
|
||||
float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
if (scene->camera && scene->camera->type == OB_CAMERA) {
|
||||
bias = ((Camera *)scene->camera->data)->clipsta;
|
||||
clipend = ((Camera *)scene->camera->data)->clipend;
|
||||
|
@ -473,8 +448,8 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
|
|||
scale = 0.01f;
|
||||
clipend = 100.0f;
|
||||
}
|
||||
|
||||
rectf = MEM_mallocN(rectx * recty * 4, "temp");
|
||||
|
||||
rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp");
|
||||
for (a = rectx * recty - 1; a >= 0; a--) {
|
||||
if (rect_float[a] > clipend)
|
||||
rectf[a] = 0.0f;
|
||||
|
@ -485,22 +460,16 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
|
|||
rectf[a] *= rectf[a];
|
||||
}
|
||||
}
|
||||
glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, rectf);
|
||||
|
||||
MEM_freeN(rectf);
|
||||
}
|
||||
|
||||
static int draw_image_channel_offset(SpaceImage *sima)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
if (sima->flag & SI_SHOW_R) return 0;
|
||||
else if (sima->flag & SI_SHOW_G) return 1;
|
||||
else return 2;
|
||||
#else
|
||||
if (sima->flag & SI_SHOW_R) return 1;
|
||||
else if (sima->flag & SI_SHOW_G) return 2;
|
||||
else return 3;
|
||||
#endif
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
|
||||
GPU_shader_bind(shader);
|
||||
GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red);
|
||||
|
||||
immDrawPixelsTex(x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL);
|
||||
|
||||
GPU_shader_unbind();
|
||||
|
||||
MEM_freeN(rectf);
|
||||
}
|
||||
|
||||
static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
|
||||
|
@ -508,61 +477,70 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
|
|||
int x, y;
|
||||
|
||||
/* set zoom */
|
||||
glPixelZoom(zoomx, zoomy);
|
||||
|
||||
glaDefine2DArea(&ar->winrct);
|
||||
|
||||
/* find window pixel coordinates of origin */
|
||||
UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y);
|
||||
|
||||
/* this part is generic image display */
|
||||
if (sima->flag & SI_SHOW_ALPHA) {
|
||||
if (ibuf->rect)
|
||||
sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, ibuf->rect);
|
||||
else if (ibuf->rect_float && ibuf->channels == 4)
|
||||
sima_draw_alpha_pixelsf(x, y, ibuf->x, ibuf->y, ibuf->rect_float);
|
||||
}
|
||||
else if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
|
||||
if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
|
||||
if (ibuf->zbuf)
|
||||
sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf);
|
||||
sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy);
|
||||
else if (ibuf->zbuf_float)
|
||||
sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float);
|
||||
sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float, zoomx, zoomy);
|
||||
else if (ibuf->channels == 1)
|
||||
sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
|
||||
sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float, zoomx, zoomy);
|
||||
}
|
||||
else {
|
||||
int clip_max_x, clip_max_y;
|
||||
UI_view2d_view_to_region(&ar->v2d,
|
||||
ar->v2d.cur.xmax, ar->v2d.cur.ymax,
|
||||
&clip_max_x, &clip_max_y);
|
||||
|
||||
if (sima->flag & SI_USE_ALPHA) {
|
||||
imm_draw_checker_box(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
|
||||
}
|
||||
|
||||
if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) == 0) {
|
||||
int clip_max_x, clip_max_y;
|
||||
UI_view2d_view_to_region(&ar->v2d,
|
||||
ar->v2d.cur.xmax, ar->v2d.cur.ymax,
|
||||
&clip_max_x, &clip_max_y);
|
||||
/* If RGBA display with color management */
|
||||
if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
|
||||
|
||||
glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, GL_NEAREST,
|
||||
0, 0, clip_max_x, clip_max_y, zoomx, zoomy);
|
||||
}
|
||||
else {
|
||||
float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
unsigned char *display_buffer;
|
||||
void *cache_handle;
|
||||
ColorManagedViewSettings *view_settings;
|
||||
ColorManagedDisplaySettings *display_settings;
|
||||
|
||||
/* TODO(sergey): Ideally GLSL shading should be capable of either
|
||||
* disabling some channels or displaying buffer with custom offset.
|
||||
*/
|
||||
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
|
||||
if (sima->flag & SI_SHOW_R)
|
||||
shuffle[0] = 1.0f;
|
||||
else if (sima->flag & SI_SHOW_G)
|
||||
shuffle[1] = 1.0f;
|
||||
else if (sima->flag & SI_SHOW_B)
|
||||
shuffle[2] = 1.0f;
|
||||
else if (sima->flag & SI_SHOW_ALPHA)
|
||||
shuffle[3] = 1.0f;
|
||||
|
||||
if (display_buffer != NULL) {
|
||||
int channel_offset = draw_image_channel_offset(sima);
|
||||
glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT,
|
||||
display_buffer - (4 - channel_offset));
|
||||
}
|
||||
if (cache_handle != NULL) {
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
|
||||
GPU_shader_bind(shader);
|
||||
GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, shuffle);
|
||||
|
||||
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
|
||||
display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
|
||||
|
||||
if (display_buffer) {
|
||||
immDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer,
|
||||
0, 0, clip_max_x, clip_max_y, zoomx, zoomy, NULL);
|
||||
}
|
||||
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
|
||||
GPU_shader_unbind();
|
||||
}
|
||||
|
||||
if (sima->flag & SI_USE_ALPHA)
|
||||
|
@ -601,7 +579,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
|
|||
unsigned int *rect;
|
||||
int dx, dy, sx, sy, x, y;
|
||||
void *cache_handle;
|
||||
int channel_offset = -1;
|
||||
float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
/* verify valid values, just leave this a while */
|
||||
if (ima->xrep < 1) return;
|
||||
|
@ -615,8 +593,6 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
|
|||
if (!display_buffer)
|
||||
return;
|
||||
|
||||
glPixelZoom(zoomx, zoomy);
|
||||
|
||||
if (sima->curtile >= ima->xrep * ima->yrep)
|
||||
sima->curtile = ima->xrep * ima->yrep - 1;
|
||||
|
||||
|
@ -628,24 +604,39 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
|
|||
rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
|
||||
|
||||
/* draw repeated */
|
||||
if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) != 0) {
|
||||
channel_offset = draw_image_channel_offset(sima);
|
||||
if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) != 0) {
|
||||
if (sima->flag & SI_SHOW_R)
|
||||
shuffle[0] = 1.0f;
|
||||
else if (sima->flag & SI_SHOW_G)
|
||||
shuffle[1] = 1.0f;
|
||||
else if (sima->flag & SI_SHOW_B)
|
||||
shuffle[2] = 1.0f;
|
||||
else if (sima->flag & SI_SHOW_ALPHA)
|
||||
shuffle[3] = 1.0f;
|
||||
}
|
||||
|
||||
/* To make sure no program is bound */
|
||||
GPU_shader_unbind();
|
||||
|
||||
for (sy = 0; sy + dy <= ibuf->y; sy += dy) {
|
||||
for (sx = 0; sx + dx <= ibuf->x; sx += dx) {
|
||||
UI_view2d_view_to_region(&ar->v2d, fx + (float)sx / (float)ibuf->x, fy + (float)sy / (float)ibuf->y, &x, &y);
|
||||
if (channel_offset == -1) {
|
||||
glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect);
|
||||
|
||||
if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
|
||||
immDrawPixelsTex(x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL);
|
||||
}
|
||||
else {
|
||||
glaDrawPixelsSafe(x, y, dx, dy, dx, GL_LUMINANCE, GL_UNSIGNED_INT,
|
||||
(unsigned char *)rect - (4 - channel_offset));
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
|
||||
GPU_shader_bind(shader);
|
||||
GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, shuffle);
|
||||
|
||||
immDrawPixelsTex(x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL);
|
||||
|
||||
GPU_shader_unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glPixelZoom(1.0f, 1.0f);
|
||||
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
|
||||
MEM_freeN(rect);
|
||||
|
@ -718,84 +709,37 @@ void draw_image_sample_line(SpaceImage *sima)
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height)
|
||||
{
|
||||
Brush *brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
|
||||
ImBuf *ibuf;
|
||||
unsigned int size, alpha;
|
||||
unsigned char *display_buffer;
|
||||
unsigned char *rect, *cp;
|
||||
void *cache_handle;
|
||||
|
||||
if (!brush || !brush->clone.image)
|
||||
return NULL;
|
||||
|
||||
ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
|
||||
|
||||
if (!ibuf)
|
||||
return NULL;
|
||||
|
||||
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
|
||||
|
||||
if (!display_buffer) {
|
||||
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rect = MEM_dupallocN(display_buffer);
|
||||
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
|
||||
if (!rect) {
|
||||
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*width = ibuf->x;
|
||||
*height = ibuf->y;
|
||||
|
||||
size = (*width) * (*height);
|
||||
alpha = (unsigned char)255 * brush->clone.alpha;
|
||||
cp = rect;
|
||||
|
||||
while (size-- > 0) {
|
||||
cp[3] = alpha;
|
||||
cp += 4;
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy)
|
||||
{
|
||||
Brush *brush;
|
||||
int x, y, w, h;
|
||||
unsigned char *clonerect;
|
||||
int x, y;
|
||||
ImBuf *ibuf;
|
||||
|
||||
brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
|
||||
|
||||
if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) {
|
||||
/* this is not very efficient, but glDrawPixels doesn't allow
|
||||
* drawing with alpha */
|
||||
clonerect = get_alpha_clone_image(C, scene, &w, &h);
|
||||
if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) {
|
||||
ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
|
||||
|
||||
if (clonerect) {
|
||||
if (ibuf) {
|
||||
void *cache_handle = NULL;
|
||||
float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha};
|
||||
UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
|
||||
|
||||
glPixelZoom(zoomx, zoomy);
|
||||
unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
|
||||
|
||||
if (!display_buffer) {
|
||||
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, clonerect);
|
||||
immDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, zoomx, zoomy, col);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glPixelZoom(1.0, 1.0);
|
||||
|
||||
MEM_freeN(clonerect);
|
||||
BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
|
||||
IMB_display_buffer_release(cache_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue