1#include "ANGLETest.h" 2 3class DrawBuffersTest : public ANGLETest 4{ 5 protected: 6 DrawBuffersTest(int clientVersion) 7 { 8 setWindowWidth(128); 9 setWindowHeight(128); 10 setConfigRedBits(8); 11 setConfigGreenBits(8); 12 setConfigBlueBits(8); 13 setConfigAlphaBits(8); 14 setConfigDepthBits(24); 15 setClientVersion(clientVersion); 16 } 17 18 virtual void SetUp() 19 { 20 ANGLETest::SetUp(); 21 22 glGenFramebuffers(1, &mFBO); 23 glBindFramebuffer(GL_FRAMEBUFFER, mFBO); 24 25 glGenTextures(4, mTextures); 26 27 for (size_t texIndex = 0; texIndex < ArraySize(mTextures); texIndex++) 28 { 29 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]); 30 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight()); 31 } 32 33 GLfloat data[] = 34 { 35 -1.0f, 1.0f, 36 -1.0f, -2.0f, 37 2.0f, 1.0f 38 }; 39 40 glGenBuffers(1, &mBuffer); 41 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 42 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6, data, GL_STATIC_DRAW); 43 44 GLint maxDrawBuffers; 45 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); 46 ASSERT_EQ(maxDrawBuffers, 8); 47 48 ASSERT_GL_NO_ERROR(); 49 } 50 51 virtual void TearDown() 52 { 53 glDeleteFramebuffers(1, &mFBO); 54 glDeleteTextures(4, mTextures); 55 glDeleteBuffers(1, &mBuffer); 56 57 ANGLETest::TearDown(); 58 } 59 60 void setupMRTProgramESSL3(bool bufferEnabled[8], GLuint *programOut) 61 { 62 const std::string vertexShaderSource = 63 "#version 300 es\n" 64 "in vec4 position;\n" 65 "void main() {\n" 66 " gl_Position = position;\n" 67 "}\n"; 68 69 std::stringstream strstr; 70 71 strstr << "#version 300 es\n" 72 "precision highp float;\n"; 73 74 for (unsigned int index = 0; index < 8; index++) 75 { 76 if (bufferEnabled[index]) 77 { 78 strstr << "layout(location = " << index << ") " 79 "out vec4 value" << index << ";\n"; 80 } 81 } 82 83 strstr << "void main()\n" 84 "{\n"; 85 86 for (unsigned int index = 0; index < 8; index++) 87 { 88 if (bufferEnabled[index]) 89 { 90 unsigned int r = (index + 1) & 1; 91 unsigned int g = (index + 1) & 2; 92 unsigned int b = (index + 1) & 4; 93 94 strstr << " value" << index << " = vec4(" 95 << r << ".0, " << g << ".0, " 96 << b << ".0, 1.0);\n"; 97 } 98 } 99 100 strstr << "}\n"; 101 102 *programOut = CompileProgram(vertexShaderSource, strstr.str()); 103 if (*programOut == 0) 104 { 105 FAIL() << "shader compilation failed."; 106 } 107 108 glUseProgram(*programOut); 109 110 GLint location = glGetAttribLocation(*programOut, "position"); 111 ASSERT_NE(location, -1); 112 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 113 glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 8, NULL); 114 glEnableVertexAttribArray(location); 115 } 116 117 void setupMRTProgramESSL1(bool bufferEnabled[8], GLuint *programOut) 118 { 119 const std::string vertexShaderSource = 120 "attribute vec4 position;\n" 121 "void main() {\n" 122 " gl_Position = position;\n" 123 "}\n"; 124 125 std::stringstream strstr; 126 127 strstr << "#extension GL_EXT_draw_buffers : enable\n" 128 "precision highp float;\n" 129 "void main()\n" 130 "{\n"; 131 132 for (unsigned int index = 0; index < 8; index++) 133 { 134 if (bufferEnabled[index]) 135 { 136 unsigned int r = (index + 1) & 1; 137 unsigned int g = (index + 1) & 2; 138 unsigned int b = (index + 1) & 4; 139 140 strstr << " gl_FragData[" << index << "] = vec4(" 141 << r << ".0, " << g << ".0, " 142 << b << ".0, 1.0);\n"; 143 } 144 } 145 146 strstr << "}\n"; 147 148 *programOut = CompileProgram(vertexShaderSource, strstr.str()); 149 if (*programOut == 0) 150 { 151 FAIL() << "shader compilation failed."; 152 } 153 154 glUseProgram(*programOut); 155 156 GLint location = glGetAttribLocation(*programOut, "position"); 157 ASSERT_NE(location, -1); 158 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 159 glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 8, NULL); 160 glEnableVertexAttribArray(location); 161 } 162 163 void setupMRTProgram(bool bufferEnabled[8], GLuint *programOut) 164 { 165 if (getClientVersion() == 3) 166 { 167 setupMRTProgramESSL3(bufferEnabled, programOut); 168 } 169 else 170 { 171 ASSERT_EQ(getClientVersion(), 2); 172 setupMRTProgramESSL1(bufferEnabled, programOut); 173 } 174 } 175 176 void verifyAttachment(unsigned int index, GLuint textureName) 177 { 178 for (unsigned int colorAttachment = 0; colorAttachment < 8; colorAttachment++) 179 { 180 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttachment, GL_TEXTURE_2D, 0, 0); 181 } 182 183 glBindTexture(GL_TEXTURE_2D, textureName); 184 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0); 185 186 unsigned int r = (((index + 1) & 1) > 0) ? 255 : 0; 187 unsigned int g = (((index + 1) & 2) > 0) ? 255 : 0; 188 unsigned int b = (((index + 1) & 4) > 0) ? 255 : 0; 189 190 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, r, g, b, 255); 191 } 192 193 void gapsTest() 194 { 195 glBindTexture(GL_TEXTURE_2D, mTextures[0]); 196 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[0], 0); 197 198 bool flags[8] = { false, true }; 199 200 GLuint program; 201 setupMRTProgram(flags, &program); 202 203 const GLenum bufs[] = 204 { 205 GL_NONE, 206 GL_COLOR_ATTACHMENT1 207 }; 208 glUseProgram(program); 209 glDrawBuffersEXT(2, bufs); 210 glDrawArrays(GL_TRIANGLES, 0, 3); 211 212 verifyAttachment(1, mTextures[0]); 213 214 glDeleteProgram(program); 215 } 216 217 void firstAndLastTest() 218 { 219 glBindTexture(GL_TEXTURE_2D, mTextures[0]); 220 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0); 221 222 glBindTexture(GL_TEXTURE_2D, mTextures[1]); 223 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTextures[1], 0); 224 225 bool flags[8] = { true, false, false, true }; 226 227 GLuint program; 228 setupMRTProgram(flags, &program); 229 230 const GLenum bufs[] = 231 { 232 GL_COLOR_ATTACHMENT0, 233 GL_NONE, 234 GL_NONE, 235 GL_COLOR_ATTACHMENT3 236 }; 237 238 glUseProgram(program); 239 glDrawBuffersEXT(4, bufs); 240 glDrawArrays(GL_TRIANGLES, 0, 3); 241 242 verifyAttachment(0, mTextures[0]); 243 verifyAttachment(3, mTextures[1]); 244 245 EXPECT_GL_NO_ERROR(); 246 247 glDeleteProgram(program); 248 } 249 250 void firstHalfNULLTest() 251 { 252 bool flags[8] = { false }; 253 GLenum bufs[8] = { GL_NONE }; 254 255 for (unsigned int texIndex = 0; texIndex < 4; texIndex++) 256 { 257 glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]); 258 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4 + texIndex, GL_TEXTURE_2D, mTextures[texIndex], 0); 259 flags[texIndex + 4] = true; 260 bufs[texIndex + 4] = GL_COLOR_ATTACHMENT4 + texIndex; 261 } 262 263 GLuint program; 264 setupMRTProgram(flags, &program); 265 266 glUseProgram(program); 267 glDrawBuffersEXT(8, bufs); 268 glDrawArrays(GL_TRIANGLES, 0, 3); 269 270 for (unsigned int texIndex = 0; texIndex < 4; texIndex++) 271 { 272 verifyAttachment(texIndex + 4, mTextures[texIndex]); 273 } 274 275 EXPECT_GL_NO_ERROR(); 276 277 glDeleteProgram(program); 278 } 279 280 GLuint mFBO; 281 GLuint mTextures[4]; 282 GLuint mBuffer; 283}; 284 285class DrawBuffersTestESSL3 : public DrawBuffersTest 286{ 287 protected: 288 DrawBuffersTestESSL3() 289 : DrawBuffersTest(3) 290 {} 291}; 292 293class DrawBuffersTestESSL1 : public DrawBuffersTest 294{ 295 protected: 296 DrawBuffersTestESSL1() 297 : DrawBuffersTest(2) 298 {} 299}; 300 301TEST_F(DrawBuffersTestESSL3, Gaps) 302{ 303 gapsTest(); 304} 305 306TEST_F(DrawBuffersTestESSL1, Gaps) 307{ 308 gapsTest(); 309} 310 311TEST_F(DrawBuffersTestESSL3, FirstAndLast) 312{ 313 firstAndLastTest(); 314} 315 316TEST_F(DrawBuffersTestESSL1, FirstAndLast) 317{ 318 firstAndLastTest(); 319} 320 321TEST_F(DrawBuffersTestESSL3, FirstHalfNULL) 322{ 323 firstHalfNULLTest(); 324} 325 326TEST_F(DrawBuffersTestESSL1, FirstHalfNULL) 327{ 328 firstHalfNULLTest(); 329} 330