[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [57735] trunk/blender/source/blender/gpu/ intern/gpu_draw.c: Fix #34909 Texture paint mode does not correctly update when using

Antony Riakiotakis kalast at gmail.com
Tue Jun 25 15:27:44 CEST 2013


Revision: 57735
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=57735
Author:   psy-fi
Date:     2013-06-25 13:27:43 +0000 (Tue, 25 Jun 2013)
Log Message:
-----------
Fix #34909 Texture paint mode does not correctly update when using
textures larger than 2048x2048.

Check if texture is over user preference or GPU limit in texture paint
mode and if it is, scale the partial redraw rectangle before uploading
to GPU. This should be faster than rescaling the whole texture.

Modified Paths:
--------------
    trunk/blender/source/blender/gpu/intern/gpu_draw.c

Modified: trunk/blender/source/blender/gpu/intern/gpu_draw.c
===================================================================
--- trunk/blender/source/blender/gpu/intern/gpu_draw.c	2013-06-25 12:26:49 UTC (rev 57734)
+++ trunk/blender/source/blender/gpu/intern/gpu_draw.c	2013-06-25 13:27:43 UTC (rev 57735)
@@ -932,6 +932,77 @@
 	}
 }
 
+
+/* 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 @@
 			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 @@
 			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);




More information about the Bf-blender-cvs mailing list