1 /*
2  * Copyright (c) 2010 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  * Author:
26  *    Brian Paul
27  */
28 
29 /**
30  * @file fbo-draw-buffers-blend.c
31  *
32  * Test GL_ARB_draw_buffers_blend extension (per-buffer blend state)
33  */
34 
35 #include "piglit-util-gl.h"
36 
37 PIGLIT_GL_TEST_CONFIG_BEGIN
38 
39 	config.supports_gl_compat_version = 10;
40 
41 	config.window_visual = PIGLIT_GL_VISUAL_RGB;
42 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
43 
44 PIGLIT_GL_TEST_CONFIG_END
45 
46 static const char *TestName = "fbo-draw-buffers-blend";
47 
48 static GLint maxBuffers;
49 static GLuint FBO;
50 
51 
52 #define MY_ASSERT(x) my_assert(x, #x)
53 
54 static void
my_assert(int test,const char * text)55 my_assert(int test, const char *text)
56 {
57    if (!test) {
58       printf("%s: assertion %s failed\n", TestName, text);
59       piglit_report_result(PIGLIT_FAIL);
60    }
61 }
62 
63 
64 static void
check_error(int line)65 check_error(int line)
66 {
67    GLenum err = glGetError();
68    if (err) {
69       printf("%s: Unexpected error 0x%x at line %d\n",
70               TestName, err, line);
71       piglit_report_result(PIGLIT_FAIL);
72    }
73 }
74 
75 
76 static void
create_fbo(void)77 create_fbo(void)
78 {
79    GLuint rb[32];
80    int i;
81 
82    glGenFramebuffersEXT(1, &FBO);
83    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
84 
85    glGenRenderbuffersEXT(maxBuffers, rb);
86    check_error(__LINE__);
87 
88    for (i = 0; i < maxBuffers; i++) {
89       glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rb[i]);
90       check_error(__LINE__);
91 
92       glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
93                                    GL_COLOR_ATTACHMENT0 + i,
94                                    GL_RENDERBUFFER_EXT,
95                                    rb[i]);
96       check_error(__LINE__);
97 
98       glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA,
99                                piglit_width, piglit_height);
100       check_error(__LINE__);
101    }
102 }
103 
104 
105 static enum piglit_result
test(void)106 test(void)
107 {
108    GLenum buffers[32];
109    static const GLfloat dest_color[4] = { 0.75, 0.25, 0.25, 0.5 };
110    static const GLfloat test_color[4] = { 1.0, 0.25, 0.75, 0.25 };
111    GLfloat expected[32][4];
112    int i;
113 
114    create_fbo();
115 
116    for (i = 0; i < maxBuffers; i++) {
117       buffers[i] = GL_COLOR_ATTACHMENT0_EXT + i;
118    }
119 
120    glDrawBuffersARB(maxBuffers, buffers);
121 
122    /* Setup blend modes and compute expected result color.
123     * We only test two simple blending modes.  A more elaborate
124     * test would exercise a much wider variety of modes.
125     */
126    for (i = 0; i < maxBuffers; i++) {
127       if (i % 2 == 0) {
128          float a;
129 
130          glBlendFunciARB(i, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
131 
132          a = test_color[3];
133          expected[i][0] = test_color[0] * a + dest_color[0] * (1.0 - a);
134          expected[i][1] = test_color[1] * a + dest_color[1] * (1.0 - a);
135          expected[i][2] = test_color[2] * a + dest_color[2] * (1.0 - a);
136          expected[i][3] = test_color[3] * a + dest_color[3] * (1.0 - a);
137       }
138       else {
139          glBlendFunciARB(i, GL_ONE, GL_ONE);
140          glBlendEquationiARB(i, GL_FUNC_SUBTRACT);
141 
142          expected[i][0] = test_color[0] - dest_color[0];
143          expected[i][1] = test_color[1] - dest_color[1];
144          expected[i][2] = test_color[2] - dest_color[2];
145          expected[i][3] = test_color[3] - dest_color[3];
146       }
147 
148       expected[i][0] = CLAMP(expected[i][0], 0.0, 1.0);
149       expected[i][1] = CLAMP(expected[i][1], 0.0, 1.0);
150       expected[i][2] = CLAMP(expected[i][2], 0.0, 1.0);
151       expected[i][3] = CLAMP(expected[i][3], 0.0, 1.0);
152 
153       glEnableIndexedEXT(GL_BLEND, i);
154    }
155 
156    /* query blend modes */
157    for (i = 0; i < maxBuffers; i++) {
158       GLint p0, p1, p2, p3;
159       glGetIntegerIndexedvEXT(GL_BLEND_SRC, i, &p0);
160       glGetIntegerIndexedvEXT(GL_BLEND_DST, i, &p1);
161       glGetIntegerIndexedvEXT(GL_BLEND_EQUATION, i, &p2);
162       glGetIntegerIndexedvEXT(GL_BLEND, i, &p3);
163       if (i % 2 == 0) {
164          MY_ASSERT(p0 == GL_SRC_ALPHA);
165          MY_ASSERT(p1 == GL_ONE_MINUS_SRC_ALPHA);
166          MY_ASSERT(p2 == GL_FUNC_ADD);
167       }
168       else {
169          MY_ASSERT(p0 == GL_ONE);
170          MY_ASSERT(p1 == GL_ONE);
171          MY_ASSERT(p2 == GL_FUNC_SUBTRACT);
172       }
173       MY_ASSERT(p3 == GL_TRUE);
174    }
175 
176    /* test drawing */
177    glClearColor(dest_color[0], dest_color[1], dest_color[2], dest_color[3]);
178    glClear(GL_COLOR_BUFFER_BIT);
179 
180    glColor4fv(test_color);
181    piglit_draw_rect(0, 0, piglit_width, piglit_height);
182 
183    for (i = 0; i < maxBuffers; i++) {
184       glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i);
185       check_error(__LINE__);
186 
187       if (!piglit_probe_pixel_rgba(5, 5, expected[i])) {
188          printf("For color buffer %d\n", i);
189          return PIGLIT_FAIL;
190       }
191    }
192 
193    return PIGLIT_PASS;
194 }
195 
196 
197 enum piglit_result
piglit_display(void)198 piglit_display(void)
199 {
200    return test();
201 }
202 
203 
204 void
piglit_init(int argc,char ** argv)205 piglit_init(int argc, char**argv)
206 {
207    piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
208 
209    piglit_require_extension("GL_ARB_draw_buffers_blend");
210 
211    glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &maxBuffers);
212 }
213