diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2015-12-15 03:38:59 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2015-12-15 03:47:48 +0300 |
commit | 31d1895abfbcc3857109bd81343894e94d4cabc9 (patch) | |
tree | 201364f3158996e35c427d54335596ee9970dfb0 /source/blender/imbuf/intern/filter.c | |
parent | 7fa72b8970b921190ae4fbd56748c0c808f870d1 (diff) |
Fix T46951: invalid OpenGL mipmaps when using high bit depth textures.
Diffstat (limited to 'source/blender/imbuf/intern/filter.c')
-rw-r--r-- | source/blender/imbuf/intern/filter.c | 137 |
1 files changed, 90 insertions, 47 deletions
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index ef445239491..90b3fe092a8 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -203,54 +203,97 @@ void imb_filterx(struct ImBuf *ibuf) } } -void IMB_filterN(ImBuf *out, ImBuf *in) +static void imb_filterN(ImBuf *out, ImBuf *in) { - register char *row1, *row2, *row3; - register char *cp, *r11, *r13, *r21, *r23, *r31, *r33; - int rowlen, x, y; - - rowlen = in->x; - - /* generate 32-bit version for float images if it is not already generated by other space */ - if (in->rect == NULL) - IMB_rect_from_float(in); + BLI_assert(out->channels == in->channels); + BLI_assert(out->x == in->x && out->y == out->y); + + const int channels = in->channels; + const int rowlen = in->x; - for (y = 0; y < in->y; y++) { - /* setup rows */ - row2 = (char *)(in->rect + y * rowlen); - row1 = (y == 0) ? row2 : row2 - 4 * rowlen; - row3 = (y == in->y - 1) ? row2 : row2 + 4 * rowlen; - - cp = (char *)(out->rect + y * rowlen); - - for (x = 0; x < rowlen; x++) { - if (x == 0) { - r11 = row1; - r21 = row2; - r31 = row3; - } - else { - r11 = row1 - 4; - r21 = row2 - 4; - r31 = row3 - 4; - } + if (in->rect && out->rect) { + for (int y = 0; y < in->y; y++) { + /* setup rows */ + const char *row2 = (const char *)in->rect + y * channels * rowlen; + const char *row1 = (y == 0) ? row2 : row2 - channels * rowlen; + const char *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen; + + char *cp = (char *)out->rect + y * channels * rowlen; + + for (int x = 0; x < rowlen; x++) { + const char *r11, *r13, *r21, *r23, *r31, *r33; + + if (x == 0) { + r11 = row1; + r21 = row2; + r31 = row3; + } + else { + r11 = row1 - channels; + r21 = row2 - channels; + r31 = row3 - channels; + } - if (x == rowlen - 1) { - r13 = row1; - r23 = row2; - r33 = row3; - } - else { - r13 = row1 + 4; - r23 = row2 + 4; - r33 = row3 + 4; + if (x == rowlen - 1) { + r13 = row1; + r23 = row2; + r33 = row3; + } + else { + r13 = row1 + channels; + r23 = row2 + channels; + r33 = row3 + channels; + } + + cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + 2 * row3[0] + r33[0]) >> 4; + cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + 2 * row3[1] + r33[1]) >> 4; + cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + 2 * row3[2] + r33[2]) >> 4; + cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + 2 * row3[3] + r33[3]) >> 4; + cp += channels; row1 += channels; row2 += channels; row3 += channels; } + } + } + + if (in->rect_float && out->rect_float) { + for (int y = 0; y < in->y; y++) { + /* setup rows */ + const float *row2 = (const float *)in->rect_float + y * channels * rowlen; + const float *row1 = (y == 0) ? row2 : row2 - channels * rowlen; + const float *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen; + + float *cp = (float *)out->rect_float + y * channels * rowlen; + + for (int x = 0; x < rowlen; x++) { + const float *r11, *r13, *r21, *r23, *r31, *r33; - cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + 2 * row3[0] + r33[0]) >> 4; - cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + 2 * row3[1] + r33[1]) >> 4; - cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + 2 * row3[2] + r33[2]) >> 4; - cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + 2 * row3[3] + r33[3]) >> 4; - cp += 4; row1 += 4; row2 += 4; row3 += 4; + if (x == 0) { + r11 = row1; + r21 = row2; + r31 = row3; + } + else { + r11 = row1 - channels; + r21 = row2 - channels; + r31 = row3 - channels; + } + + if (x == rowlen - 1) { + r13 = row1; + r23 = row2; + r33 = row3; + } + else { + r13 = row1 + channels; + r23 = row2 + channels; + r33 = row3 + channels; + } + + cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] + 2 * row3[0] + r33[0]) * (1.0f/16.0f); + cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] + 2 * row3[1] + r33[1]) * (1.0f/16.0f); + cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] + 2 * row3[2] + r33[2]) * (1.0f/16.0f); + cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] + 2 * row3[3] + r33[3]) * (1.0f/16.0f); + cp += channels; row1 += channels; row2 += channels; row3 += channels; + } } } } @@ -477,8 +520,8 @@ void IMB_remakemipmap(ImBuf *ibuf, int use_filter) if (ibuf->mipmap[curmap]) { if (use_filter) { - ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, 32, IB_rect); - IMB_filterN(nbuf, hbuf); + ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags); + imb_filterN(nbuf, hbuf); imb_onehalf_no_alloc(ibuf->mipmap[curmap], nbuf); IMB_freeImBuf(nbuf); } @@ -514,8 +557,8 @@ void IMB_makemipmap(ImBuf *ibuf, int use_filter) while (curmap < IMB_MIPMAP_LEVELS) { if (use_filter) { - ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, 32, IB_rect); - IMB_filterN(nbuf, hbuf); + ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags); + imb_filterN(nbuf, hbuf); ibuf->mipmap[curmap] = IMB_onehalf(nbuf); IMB_freeImBuf(nbuf); } |