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:
-rw-r--r--source/blender/gpu/intern/gpu_draw.c90
1 files changed, 89 insertions, 1 deletions
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index e98f8988aa6..fc28ec2d6f7 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -932,6 +932,77 @@ void GPU_paint_set_mipmap(int mipmap)
}
}
+
+/* check if image has been downscaled and do scaled partial update */
+static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
+{
+ if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
+ is_over_resolution_limit(ibuf->x, ibuf->y))
+ {
+ int x_limit = smaller_power_of_2_limit(ibuf->x);
+ int y_limit = smaller_power_of_2_limit(ibuf->y);
+
+ float xratio = x_limit/(float)ibuf->x;
+ float yratio = y_limit/(float)ibuf->y;
+
+ /* find new width, height and x,y gpu texture coordinates */
+
+ /* take ceiling because we will be losing 1 pixel due to rounding errors in x,y... */
+ int rectw = (int)ceil(xratio * w);
+ int recth = (int)ceil(yratio * h);
+
+ x *= xratio;
+ y *= yratio;
+
+ /* ...but take back if we are over the limit! */
+ if (rectw + x > x_limit) rectw--;
+ if (recth + y > y_limit) recth--;
+
+ /* float rectangles are already continuous in memory so we can use gluScaleImage */
+ if (frect) {
+ float *fscalerect = MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
+ gluScaleImage(GL_RGBA, w, h, GL_FLOAT, frect, rectw, recth, GL_FLOAT, fscalerect);
+
+ glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
+ GL_FLOAT, fscalerect);
+
+ MEM_freeN(fscalerect);
+ }
+ /* byte images are not continuous in memory so do manual interpolation */
+ else {
+ unsigned char *scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect)*4, "scalerect");
+ unsigned int *p = (unsigned int *)scalerect;
+ int i, j;
+ float inv_xratio = 1.0/xratio;
+ float inv_yratio = 1.0/yratio;
+ for (i = 0; i < rectw; i++) {
+ float u = (x + i)*inv_xratio;
+ for (j = 0; j < recth; j++) {
+ float v = (y + j)*inv_yratio;
+ bilinear_interpolation_color_wrap(ibuf, (unsigned char *)(p + i + j * (rectw)), NULL, u, v);
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D, ima->bindcode);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
+ GL_UNSIGNED_BYTE, scalerect);
+
+ MEM_freeN(scalerect);
+ }
+
+ if (GPU_get_mipmap()) {
+ gpu_generate_mipmap(GL_TEXTURE_2D);
+ }
+ else {
+ ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
{
ImBuf *ibuf;
@@ -959,6 +1030,15 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
int is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA);
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
+ if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
+ MEM_freeN(buffer);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
GL_FLOAT, buffer);
@@ -977,7 +1057,15 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
BKE_image_release_ibuf(ima, ibuf, NULL);
return;
}
-
+
+ if (GPU_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ return;
+ }
+
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);