1 /*
2  * Copyright © 2014 VMware, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 /**
25  * With AMD OpenGL drivers, when we draw a point sprite and use
26  * gl_PointCoord in the fragment (pixel) shader, the buggy host driver
27  * will wrongly put gl_PointCoord value into a fragment shader input
28  * variable, e.g., fs_color0, so that the rendering results are all wrong.
29  * We will NOT see this issue if there is no vertex attribute for the
30  * vertex position.
31  *
32  * Known to be
33  *      -- Present in : ATI HD 6770M on Mac OS X 10.8.4
34  *      -- Fixed in   : Mac OS 10.9
35  */
36 
37 
38 #include "piglit-util-gl.h"
39 
40 PIGLIT_GL_TEST_CONFIG_BEGIN
41 
42 	config.supports_gl_core_version = 32;
43 	config.supports_gl_compat_version = 32;
44 
45 	config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
46 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
47 
48 PIGLIT_GL_TEST_CONFIG_END
49 
50 #define WIDTH 32
51 #define HEIGHT 32
52 #define LEVELS 6
53 #define COLOR_GRAY       0x7F7F7FFF
54 #define CLEAR_COLOR      0x000033FF
55 #define NUM_VERTICES     4
56 #define NUM_ATTRS        2
57 #define ATTR_SIZE        4
58 
59 static GLuint prog;
60 
61 static bool
test_pointsprite_ps(void)62 test_pointsprite_ps(void)
63 {
64         static const float vertArray[ATTR_SIZE * NUM_ATTRS] = {
65                 0.0f, 0.0f, 0.0f, 1.0f,
66                 1.0f, 1.0f, 1.0f, 1.0f,
67         };
68         const unsigned int numPixels = WIDTH * HEIGHT;
69         GLuint texData[WIDTH * HEIGHT];
70         GLuint i, texFbo, fbo, vertexArray, vertexBuf;
71         GLint attrLoc;
72         const float pointSize = WIDTH;
73         const unsigned int  expectedTexelColor = 0xFFFFFFFF;
74 
75         for (i = 0; i < numPixels; ++i) {
76 	        texData[i] = COLOR_GRAY;
77         }
78 
79         /* Create 2D textures */
80         glGenTextures(1, &texFbo);
81         glActiveTexture(GL_TEXTURE0);
82         glBindTexture(GL_TEXTURE_2D, texFbo);
83         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, WIDTH, HEIGHT, 0,
84                      GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texData);
85 
86         if (!piglit_check_gl_error(GL_NO_ERROR))
87                 return false;
88 
89         /* Setup the vertex attributes */
90         glGenVertexArrays(1, &vertexArray);
91         glBindVertexArray(vertexArray);
92         glGenBuffers(1, &vertexBuf);
93         glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
94         glBufferData(GL_ARRAY_BUFFER, sizeof(vertArray), vertArray,
95                      GL_STATIC_DRAW);
96 
97         for (i = 0; i < NUM_ATTRS; i++) {
98                 const GLvoid *offset =
99                         (const GLvoid *)(i * ATTR_SIZE * sizeof(float));
100                 GLchar name[8];
101 
102                 snprintf(name, sizeof name, "Attr%d", i);
103                 attrLoc = glGetAttribLocation(prog, name);
104                 glEnableVertexAttribArray(attrLoc);
105                 glVertexAttribPointer(attrLoc, ATTR_SIZE, GL_FLOAT, GL_FALSE,
106                                       ATTR_SIZE * sizeof(float), offset);
107         }
108 
109         if (!piglit_check_gl_error(GL_NO_ERROR))
110 		return false;
111 
112         /* Setup the FBO */
113         glGenFramebuffers(1, &fbo);
114         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
115         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
116                                GL_TEXTURE_2D, texFbo, 0);
117         if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
118             GL_FRAMEBUFFER_COMPLETE) {
119                 printf("incomplete framebuffer at line %d\n", __LINE__);
120                 return false;
121         }
122 
123         glDrawBuffer(GL_COLOR_ATTACHMENT0);
124         if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
125             GL_FRAMEBUFFER_COMPLETE) {
126                 printf("incomplete framebuffer at line %d\n", __LINE__);
127                 return false;
128         }
129 
130         /* Clear and draw */
131         glViewport(0, 0, WIDTH, HEIGHT);
132         glClearColor(((CLEAR_COLOR >> 24) & 0xFF) / 255.0f,
133                      ((CLEAR_COLOR >> 16) & 0xFF) / 255.0f,
134                      ((CLEAR_COLOR >> 8)  & 0xFF) / 255.0f,
135                      ((CLEAR_COLOR) & 0xFF) / 255.0f);
136         glClear(GL_COLOR_BUFFER_BIT);
137         glPointSize(pointSize);
138         glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
139         glDrawArrays(GL_POINTS, 0, 1);
140 
141         /* Read back */
142         glReadBuffer(GL_COLOR_ATTACHMENT0);
143         if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
144             GL_FRAMEBUFFER_COMPLETE) {
145                 printf("incomplete framebuffer at line %d\n", __LINE__);
146                 return false;
147         }
148 
149 	/* read color buffer */
150         glPixelStorei(GL_PACK_ROW_LENGTH, WIDTH);
151         glPixelStorei(GL_PACK_ALIGNMENT, 1);
152         memset(texData, 0, sizeof(texData));
153         glReadPixels(0, 0, WIDTH, HEIGHT,
154                      GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texData);
155 
156         if (texData[0] != expectedTexelColor) {
157                 printf("At pixel (0,0) expected 0x%x but found 0x%x\n",
158                        expectedTexelColor, texData[0]);
159                 /* clean up */
160                 glDeleteTextures(1, &texFbo);
161                 glDeleteFramebuffers(1, &fbo);
162                 return false;
163         }
164 
165         if (!piglit_check_gl_error(GL_NO_ERROR))
166                 return false;
167 
168         glDeleteTextures(1, &texFbo);
169         glDeleteFramebuffers(1, &fbo);
170         return true;
171 }
172 
173 
174 static void
setup_shaders(void)175 setup_shaders(void)
176 {
177         static const char *vsSrc =
178                 "#version 150\n"
179                 "in vec4 Attr0;"
180                 "in vec4 Attr1;"
181                 "smooth out vec4 fs_color0;"
182                 "void main(void) {"
183                 "   gl_Position = Attr0;"
184                 "   fs_color0 = Attr1;"
185                 "}";
186         static const char *fsSrc =
187                 "#version 150\n"
188                 "smooth in vec4 fs_color0;"
189                 "out vec4 fragColor0;"
190                 "void main(void) {"
191                 "   vec2 psCoords = gl_PointCoord;"
192                 "   fragColor0 = fs_color0;"
193                 "}";
194 
195         prog = piglit_build_simple_program(vsSrc, fsSrc);
196         glBindFragDataLocation(prog, 0, "fragColor0");
197         glLinkProgram(prog);
198         glUseProgram(prog);
199 }
200 
201 
202 enum piglit_result
piglit_display(void)203 piglit_display(void)
204 {
205         bool pass = test_pointsprite_ps();
206 
207 	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
208 }
209 
210 
211 void
piglit_init(int argc,char ** argv)212 piglit_init(int argc, char **argv)
213 {
214 	setup_shaders();
215 }
216