[Glamor] [PATCH V3 1/3] Prepare for modification of gradient using shader.

junyan.he at linux.intel.com junyan.he at linux.intel.com
Thu Mar 22 13:05:48 PDT 2012


From: Junyan He <junyan.he at linux.intel.com>

 Prepare for modification of gradient using shader. The
 gradient pixmaps now is generated by pixman and we will
 replace them with shader. Add structure fields and
 dispatch functions which will be needed. Some auxiliary
 macro for vertex convert and some assistant functions
 to compare the difference of two pixmaps are also added.

---
 src/glamor.c             |    2 +
 src/glamor_gl_dispatch.c |    4 +-
 src/glamor_gl_dispatch.h |   15 ++-
 src/glamor_priv.h        |   13 ++
 src/glamor_render.c      |   22 ++++
 src/glamor_utils.h       |  301 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 350 insertions(+), 7 deletions(-)

diff --git a/src/glamor.c b/src/glamor.c
index 0d9ba28..532b9ef 100644
--- a/src/glamor.c
+++ b/src/glamor.c
@@ -389,6 +389,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
 	glamor_init_tile_shader(screen);
 	glamor_init_putimage_shaders(screen);
 	glamor_init_finish_access_shaders(screen);
+	glamor_init_gradient_shader(screen);
 	glamor_pixmap_init(screen);
 
 	glamor_priv->flags = flags;
@@ -416,6 +417,7 @@ glamor_release_screen_priv(ScreenPtr screen)
 	glamor_fini_tile_shader(screen);
 	glamor_fini_putimage_shaders(screen);
 	glamor_fini_finish_access_shaders(screen);
+	glamor_fini_gradient_shader(screen);
 	glamor_pixmap_fini(screen);
 	free(glamor_priv);
 
diff --git a/src/glamor_gl_dispatch.c b/src/glamor_gl_dispatch.c
index ef0ac43..fc3c5c0 100644
--- a/src/glamor_gl_dispatch.c
+++ b/src/glamor_gl_dispatch.c
@@ -65,10 +65,12 @@ glamor_gl_dispatch_init_impl(struct glamor_gl_dispatch *dispatch,
 
 	INIT_FUNC(dispatch, glUseProgram, get_proc_address);
 	INIT_FUNC(dispatch, glUniform1i, get_proc_address);
+	INIT_FUNC(dispatch, glUniform1f, get_proc_address);
 	INIT_FUNC(dispatch, glUniform4f, get_proc_address);
+	INIT_FUNC(dispatch, glUniform4fv, get_proc_address);
 	INIT_FUNC(dispatch, glUniform1fv, get_proc_address);
 	INIT_FUNC(dispatch, glUniform2fv, get_proc_address);
-	INIT_FUNC(dispatch, glUniform4fv, get_proc_address);
+	INIT_FUNC(dispatch, glUniformMatrix3fv, get_proc_address);
 	INIT_FUNC(dispatch, glCreateProgram, get_proc_address);
 	INIT_FUNC(dispatch, glDeleteProgram, get_proc_address);
 	INIT_FUNC(dispatch, glCreateShader, get_proc_address);
diff --git a/src/glamor_gl_dispatch.h b/src/glamor_gl_dispatch.h
index bd33bcc..6adbde9 100644
--- a/src/glamor_gl_dispatch.h
+++ b/src/glamor_gl_dispatch.h
@@ -60,7 +60,7 @@ typedef struct glamor_gl_dispatch {
 			      const GLvoid * data, GLenum usage);
 	GLvoid *(*glMapBuffer) (GLenum target, GLenum access);
 	GLvoid *(*glMapBufferRange) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-	GLboolean(*glUnmapBuffer) (GLenum target);
+	GLboolean (*glUnmapBuffer) (GLenum target);
 	void (*glBindBuffer) (GLenum target, GLuint buffer);
 	void (*glDeleteBuffers) (GLsizei n, const GLuint * buffers);
 
@@ -71,7 +71,7 @@ typedef struct glamor_gl_dispatch {
 	void (*glDeleteFramebuffers) (GLsizei n,
 				      const GLuint * framebuffers);
 	void (*glGenFramebuffers) (GLsizei n, GLuint * framebuffers);
-	 GLenum(*glCheckFramebufferStatus) (GLenum target);
+	GLenum (*glCheckFramebufferStatus) (GLenum target);
 	void (*glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1,
 				   GLint srcY1, GLint dstX0, GLint dstY0,
 				   GLint dstX1, GLint dstY1,
@@ -92,6 +92,7 @@ typedef struct glamor_gl_dispatch {
 				const GLint * length);
 	void (*glUseProgram) (GLuint program);
 	void (*glUniform1i) (GLint location, GLint v0);
+	void (*glUniform1f) (GLint location, GLfloat v0);
 	void (*glUniform4f) (GLint location, GLfloat v0, GLfloat v1,
 			     GLfloat v2, GLfloat v3);
 	void (*glUniform1fv) (GLint location, GLsizei count,
@@ -100,9 +101,11 @@ typedef struct glamor_gl_dispatch {
 			      const GLfloat * value);
 	void (*glUniform4fv) (GLint location, GLsizei count,
 			      const GLfloat * value);
-	 GLuint(*glCreateProgram) (void);
-	 GLuint(*glDeleteProgram) (GLuint);
-	 GLuint(*glCreateShader) (GLenum type);
+	void (*glUniformMatrix3fv) (GLint location, GLsizei count,
+		           GLboolean transpose, const GLfloat* value);
+	GLuint (*glCreateProgram) (void);
+	GLuint (*glDeleteProgram) (GLuint);
+	GLuint (*glCreateShader) (GLenum type);
 	void (*glCompileShader) (GLuint shader);
 	void (*glAttachShader) (GLuint program, GLuint shader);
 	void (*glGetShaderiv) (GLuint shader, GLenum pname,
@@ -113,7 +116,7 @@ typedef struct glamor_gl_dispatch {
 				GLint * params);
 	void (*glGetProgramInfoLog) (GLuint program, GLsizei bufSize,
 				     GLsizei * length, GLchar * infoLog);
-	 GLint(*glGetUniformLocation) (GLuint program,
+	GLint (*glGetUniformLocation) (GLuint program,
 				       const GLchar * name);
 
 } glamor_gl_dispatch;
diff --git a/src/glamor_priv.h b/src/glamor_priv.h
index 1404703..ad68737 100755
--- a/src/glamor_priv.h
+++ b/src/glamor_priv.h
@@ -123,6 +123,13 @@ enum shader_in {
 	SHADER_IN_COUNT,
 };
 
+enum gradient_shader_type {
+	GRADIENT_SHADER_LINEAR,
+	GRADIENT_SHADER_RADIAL,
+	GRADIENT_SHADER_CONICAL,
+	GRADIENT_SHADER_COUNT,
+};
+
 struct glamor_screen_private;
 struct glamor_pixmap_private;
 typedef void (*glamor_pixmap_validate_function_t) (struct
@@ -221,6 +228,9 @@ typedef struct glamor_screen_private {
 	GLint tile_prog;
 	GLint tile_wh;
 
+	/* glamor gradient */
+	GLint gradient_prog[GRADIENT_SHADER_COUNT];
+
 	/* glamor_putimage */
 	GLint put_image_xybitmap_prog;
 	GLint put_image_xybitmap_fg_uniform_location;
@@ -562,6 +572,9 @@ Bool glamor_tile(PixmapPtr pixmap, PixmapPtr tile,
 void glamor_init_tile_shader(ScreenPtr screen);
 void glamor_fini_tile_shader(ScreenPtr screen);
 
+void glamor_init_gradient_shader(ScreenPtr screen);
+void glamor_fini_gradient_shader(ScreenPtr screen);
+
 /* glamor_triangles.c */
 void
 
diff --git a/src/glamor_render.c b/src/glamor_render.c
index 9f0b034..093e01d 100644
--- a/src/glamor_render.c
+++ b/src/glamor_render.c
@@ -1275,6 +1275,28 @@ done:
 	return ret;
 }
 
+
+void
+glamor_init_gradient_shader(ScreenPtr screen)
+{
+	glamor_screen_private *glamor_priv;
+
+	glamor_priv = glamor_get_screen_private(screen);
+
+}
+
+void
+glamor_fini_gradient_shader(ScreenPtr screen)
+{
+	glamor_screen_private *glamor_priv;
+	glamor_gl_dispatch *dispatch;
+
+	glamor_priv = glamor_get_screen_private(screen);
+	dispatch = glamor_get_dispatch(glamor_priv);
+
+	glamor_put_dispatch(glamor_priv);
+}
+
 static PicturePtr
 glamor_convert_gradient_picture(ScreenPtr screen,
 				PicturePtr source,
diff --git a/src/glamor_utils.h b/src/glamor_utils.h
index 4a51ba5..9724745 100644
--- a/src/glamor_utils.h
+++ b/src/glamor_utils.h
@@ -99,6 +99,24 @@
     (vertices)[7] = (vertices)[5];					\
   } while(0)
 
+#define glamor_set_tcoords(x1, y1, x2, y2, yInverted, vertices)	    \
+    do {                                                            \
+      (vertices)[0] = (x1);                                         \
+      (vertices)[2] = (x2);                                         \
+      (vertices)[4] = (vertices)[2];                                \
+      (vertices)[6] = (vertices)[0];                                \
+      if (yInverted) {                                              \
+          (vertices)[1] = (y1);                                     \
+          (vertices)[5] = (y2);                                     \
+      }                                                             \
+      else {                                                        \
+          (vertices)[1] = (y2);                                     \
+          (vertices)[5] = (y1);                                     \
+      }                                                             \
+      (vertices)[3] = (vertices)[1];                \
+      (vertices)[7] = (vertices)[5];                \
+    } while(0)
+
 
 #define glamor_set_normalize_vcoords(xscale, yscale, x1, y1, x2, y2,	\
                                      yInverted, vertices)		\
@@ -119,6 +137,17 @@
     (vertices)[7] = (vertices)[5];					\
   } while(0)
 
+#define glamor_set_normalize_pt(xscale, yscale, x, x_start, y, y_start,     \
+                                yInverted, pt)                              \
+    do {                                                                    \
+        (pt)[0] = t_from_x_coord_x(xscale, x - x_start);                    \
+        if (yInverted) {                                                    \
+            (pt)[1] = t_from_x_coord_y_inverted(yscale, y - y_start);       \
+        } else {                                                            \
+            (pt)[1] = t_from_x_coord_y(yscale, y - y_start);                \
+        }                                                                   \
+        (pt)[3] = (pt)[4] = 0.0;                                            \
+    } while(0)
 
 inline static void
 glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox)
@@ -664,6 +693,278 @@ static inline void glamor_dump_pixmap(PixmapPtr pixmap, int x, int y, int w, int
 	glamor_finish_access(&pixmap->drawable, GLAMOR_ACCESS_RO);
 }
 
+static inline void _glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
+                                           int x, int y, int w, int h,
+                                           PictFormatShort short_format,
+                                           int all, int diffs)
+{
+	int i, j;
+	unsigned char * p1 = pixmap1->devPrivate.ptr;
+	unsigned char * p2 = pixmap2->devPrivate.ptr;
+	int line_need_printed = 0;
+	int test_code = 0xAABBCCDD;
+	int little_endian = 0;
+	unsigned char *p_test;
+	int bpp = pixmap1->drawable.depth == 8 ? 1 : 4;
+
+	assert(pixmap1->devKind == pixmap2->devKind);
+	int stride = pixmap1->devKind;
+
+	ErrorF("stride:%d, width:%d, height:%d\n", stride, w, h);
+
+	p1 = p1 + y * stride + x;
+	p2 = p2 + y * stride + x;
+
+	if (all) {
+		for (i = 0; i < h; i++) {
+			ErrorF("line %3d: ", i);
+
+			for (j = 0; j < stride; j++) {
+				if (j % bpp == 0)
+					ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
+				else
+					ErrorF("%2x:%2x ", p1[j], p2[j]);
+			}
+
+			p1 += stride;
+			p2 += stride;
+			ErrorF("\n");
+		}
+	} else {
+		if (short_format == PICT_a8r8g8b8) {
+			p_test = (unsigned char *) & test_code;
+			little_endian = (*p_test == 0xDD);
+			bpp = 4;
+
+			for (i = 0; i < h; i++) {
+				line_need_printed = 0;
+
+				for (j = 0; j < stride; j++) {
+					if (p1[j] != p2[j] && (p1[j] - p2[j] > diffs || p2[j] - p1[j] > diffs)) {
+						if (line_need_printed) {
+							if (little_endian) {
+								switch (j % 4) {
+									case 2:
+										ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+									case 1:
+										ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+									case 0:
+										ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+									case 3:
+										ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+								}
+							} else {
+								switch (j % 4) {
+									case 1:
+										ErrorF("[%d]RED:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+									case 2:
+										ErrorF("[%d]GREEN:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+									case 3:
+										ErrorF("[%d]BLUE:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+									case 0:
+										ErrorF("[%d]Alpha:%2x:%2x ", j / bpp, p1[j], p2[j]);
+										break;
+								}
+							}
+						} else {
+							line_need_printed = 1;
+							j = -1;
+							ErrorF("line %3d: ", i);
+							continue;
+						}
+					}
+				}
+
+				p1 += stride;
+				p2 += stride;
+				ErrorF("\n");
+			}
+		} //more format can be added here.
+		else { // the default format, just print.
+			for (i = 0; i < h; i++) {
+				line_need_printed = 0;
+
+				for (j = 0; j < stride; j++) {
+					if (p1[j] != p2[j]) {
+						if (line_need_printed) {
+							ErrorF("[%d]%2x:%2x ", j / bpp, p1[j], p2[j]);
+						} else {
+							line_need_printed = 1;
+							j = -1;
+							ErrorF("line %3d: ", i);
+							continue;
+						}
+					}
+				}
+
+				p1 += stride;
+				p2 += stride;
+				ErrorF("\n");
+			}
+		}
+	}
+}
+
+static inline void glamor_compare_pixmaps(PixmapPtr pixmap1, PixmapPtr pixmap2,
+                                          int x, int y, int w, int h, int all, int diffs)
+{
+	assert(pixmap1->drawable.depth == pixmap2->drawable.depth);
+
+	glamor_prepare_access(&pixmap1->drawable, GLAMOR_ACCESS_RO);
+	glamor_prepare_access(&pixmap2->drawable, GLAMOR_ACCESS_RO);
+
+	_glamor_compare_pixmaps(pixmap1, pixmap2, x, y, w, h, -1, all, diffs);
+
+	glamor_finish_access(&pixmap1->drawable, GLAMOR_ACCESS_RO);
+	glamor_finish_access(&pixmap2->drawable, GLAMOR_ACCESS_RO);
+}
+
+/* This function is used to compare two pictures.
+   If the picture has no drawable, we use fb functions to generate it. */
+static inline void glamor_compare_pictures( ScreenPtr screen,
+                                            PicturePtr fst_picture,
+                                            PicturePtr snd_picture,
+                                            int x_source, int y_source,
+                                            int width, int height,
+                                            int all, int diffs)
+{
+	PixmapPtr fst_pixmap;
+	PixmapPtr snd_pixmap;
+	int fst_generated, snd_generated;
+	glamor_pixmap_private *fst_pixmap_priv;
+	glamor_pixmap_private *snd_pixmap_priv;
+	int error;
+	int fst_type = -1;
+	int snd_type = -1; // -1 represent has drawable.
+
+	if (fst_picture->format != snd_picture->format) {
+		ErrorF("Different picture format can not compare!\n");
+		return;
+	}
+
+	if (!fst_picture->pDrawable) {
+		fst_type = fst_picture->pSourcePict->type;
+	}
+
+	if (!snd_picture->pDrawable) {
+		snd_type = snd_picture->pSourcePict->type;
+	}
+
+	if ((fst_type != -1) && (snd_type != -1) && (fst_type != snd_type)) {
+		ErrorF("Different picture type will never be same!\n");
+		return;
+	}
+
+	fst_generated = snd_generated = 0;
+
+	if (!fst_picture->pDrawable) {
+		PicturePtr pixman_pic;
+		PixmapPtr pixmap = NULL;
+		PictFormatShort format;
+
+		format = fst_picture->format;
+
+		pixmap = glamor_create_pixmap(screen,
+		                              width, height,
+		                              PIXMAN_FORMAT_DEPTH(format),
+		                              GLAMOR_CREATE_PIXMAP_CPU);
+
+		pixman_pic = CreatePicture(0,
+		                           &pixmap->drawable,
+		                           PictureMatchFormat(screen,
+		                               PIXMAN_FORMAT_DEPTH(format), format),
+		                           0, 0, serverClient, &error);
+
+		fbComposite(PictOpSrc, fst_picture, NULL, pixman_pic,
+		            x_source, y_source,
+		            0, 0,
+		            0, 0,
+		            width, height);
+
+		glamor_destroy_pixmap(pixmap);
+
+		fst_picture = pixman_pic;
+		fst_generated = 1;
+	}
+
+	if (!snd_picture->pDrawable) {
+		PicturePtr pixman_pic;
+		PixmapPtr pixmap = NULL;
+		PictFormatShort format;
+
+		format = snd_picture->format;
+
+		pixmap = glamor_create_pixmap(screen,
+		                              width, height,
+		                              PIXMAN_FORMAT_DEPTH(format),
+		                              GLAMOR_CREATE_PIXMAP_CPU);
+
+		pixman_pic = CreatePicture(0,
+		                           &pixmap->drawable,
+		                           PictureMatchFormat(screen,
+		                               PIXMAN_FORMAT_DEPTH(format), format),
+		                           0, 0, serverClient, &error);
+
+		fbComposite(PictOpSrc, snd_picture, NULL, pixman_pic,
+		            x_source, y_source,
+		            0, 0,
+		            0, 0,
+		            width, height);
+
+		glamor_destroy_pixmap(pixmap);
+
+		snd_picture = pixman_pic;
+		snd_generated = 1;
+	}
+
+	fst_pixmap = glamor_get_drawable_pixmap(fst_picture->pDrawable);
+	snd_pixmap = glamor_get_drawable_pixmap(snd_picture->pDrawable);
+
+	if (fst_pixmap->drawable.depth != snd_pixmap->drawable.depth) {
+		if (fst_generated)
+			glamor_destroy_picture(fst_picture);
+		if (snd_generated)
+			glamor_destroy_picture(snd_picture);
+
+		ErrorF("Different pixmap depth can not compare!\n");
+		return;
+	}
+
+	glamor_prepare_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO);
+	glamor_prepare_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO);
+
+	if ((fst_type == SourcePictTypeLinear) ||
+	     (fst_type == SourcePictTypeRadial) ||
+	     (fst_type == SourcePictTypeConical) ||
+	     (snd_type == SourcePictTypeLinear) ||
+	     (snd_type == SourcePictTypeRadial) ||
+	     (snd_type == SourcePictTypeConical)) {
+		x_source = y_source = 0;
+	}
+
+	_glamor_compare_pixmaps(fst_pixmap, snd_pixmap,
+	                        x_source, y_source,
+	                        width, height,
+	                        fst_picture->format, all, diffs);
+
+	glamor_finish_access(&fst_pixmap->drawable, GLAMOR_ACCESS_RO);
+	glamor_finish_access(&snd_pixmap->drawable, GLAMOR_ACCESS_RO);
+
+	if (fst_generated)
+		glamor_destroy_picture(fst_picture);
+	if (snd_generated)
+		glamor_destroy_picture(snd_picture);
+
+	return;
+}
+
 static inline void glamor_make_current(ScreenPtr screen)
 {
 	glamor_egl_make_current(screen);
-- 
1.7.7.6



More information about the Glamor mailing list