1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <GLES2/gl2.h> 6 #include <GLES2/gl2ext.h> 7 #include <GLES2/gl2extchromium.h> 8 9 #include "gpu/command_buffer/client/gles2_lib.h" 10 #include "gpu/command_buffer/common/mailbox.h" 11 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 12 #include "gpu/command_buffer/service/mailbox_manager.h" 13 #include "gpu/command_buffer/tests/gl_manager.h" 14 #include "testing/gmock/include/gmock/gmock.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "ui/gl/gl_share_group.h" 17 18 namespace gpu { 19 20 namespace { 21 uint32 ReadTexel(GLuint id, GLint x, GLint y) { 22 GLint old_fbo = 0; 23 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo); 24 25 GLuint fbo; 26 glGenFramebuffers(1, &fbo); 27 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 28 glFramebufferTexture2D(GL_FRAMEBUFFER, 29 GL_COLOR_ATTACHMENT0, 30 GL_TEXTURE_2D, 31 id, 32 0); 33 // Some drivers (NVidia/SGX) require texture settings to be a certain way or 34 // they won't report FRAMEBUFFER_COMPLETE. 35 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 36 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 37 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 38 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 39 40 EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), 41 glCheckFramebufferStatus(GL_FRAMEBUFFER)); 42 43 uint32 texel = 0; 44 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &texel); 45 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 46 47 glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); 48 49 glDeleteFramebuffers(1, &fbo); 50 51 return texel; 52 } 53 } 54 55 class GLTextureMailboxTest : public testing::Test { 56 protected: 57 virtual void SetUp() { 58 gl1_.Initialize(GLManager::Options()); 59 GLManager::Options options; 60 options.share_mailbox_manager = &gl1_; 61 gl2_.Initialize(options); 62 } 63 64 virtual void TearDown() { 65 gl1_.Destroy(); 66 gl2_.Destroy(); 67 } 68 69 GLManager gl1_; 70 GLManager gl2_; 71 }; 72 73 TEST_F(GLTextureMailboxTest, ProduceAndConsumeTexture) { 74 gl1_.MakeCurrent(); 75 76 GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM]; 77 glGenMailboxCHROMIUM(mailbox1); 78 79 GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM]; 80 glGenMailboxCHROMIUM(mailbox2); 81 82 GLuint tex1; 83 glGenTextures(1, &tex1); 84 85 glBindTexture(GL_TEXTURE_2D, tex1); 86 uint32 source_pixel = 0xFF0000FF; 87 glTexImage2D(GL_TEXTURE_2D, 88 0, 89 GL_RGBA, 90 1, 1, 91 0, 92 GL_RGBA, 93 GL_UNSIGNED_BYTE, 94 &source_pixel); 95 96 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); 97 glFlush(); 98 99 gl2_.MakeCurrent(); 100 101 GLuint tex2; 102 glGenTextures(1, &tex2); 103 104 glBindTexture(GL_TEXTURE_2D, tex2); 105 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); 106 EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); 107 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); 108 glFlush(); 109 110 gl1_.MakeCurrent(); 111 112 glBindTexture(GL_TEXTURE_2D, tex1); 113 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); 114 EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0)); 115 } 116 117 TEST_F(GLTextureMailboxTest, ProduceAndConsumeTextureRGB) { 118 gl1_.MakeCurrent(); 119 120 GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM]; 121 glGenMailboxCHROMIUM(mailbox1); 122 123 GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM]; 124 glGenMailboxCHROMIUM(mailbox2); 125 126 GLuint tex1; 127 glGenTextures(1, &tex1); 128 129 glBindTexture(GL_TEXTURE_2D, tex1); 130 uint32 source_pixel = 0xFF000000; 131 glTexImage2D(GL_TEXTURE_2D, 132 0, 133 GL_RGB, 134 1, 1, 135 0, 136 GL_RGB, 137 GL_UNSIGNED_BYTE, 138 &source_pixel); 139 140 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); 141 glFlush(); 142 143 gl2_.MakeCurrent(); 144 145 GLuint tex2; 146 glGenTextures(1, &tex2); 147 148 glBindTexture(GL_TEXTURE_2D, tex2); 149 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); 150 EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); 151 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); 152 glFlush(); 153 154 gl1_.MakeCurrent(); 155 156 glBindTexture(GL_TEXTURE_2D, tex1); 157 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); 158 EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0)); 159 } 160 161 TEST_F(GLTextureMailboxTest, ProduceAndConsumeTextureDirect) { 162 gl1_.MakeCurrent(); 163 164 GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM]; 165 glGenMailboxCHROMIUM(mailbox1); 166 167 GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM]; 168 glGenMailboxCHROMIUM(mailbox2); 169 170 GLuint tex1; 171 glGenTextures(1, &tex1); 172 173 glBindTexture(GL_TEXTURE_2D, tex1); 174 uint32 source_pixel = 0xFF0000FF; 175 glTexImage2D(GL_TEXTURE_2D, 176 0, 177 GL_RGBA, 178 1, 1, 179 0, 180 GL_RGBA, 181 GL_UNSIGNED_BYTE, 182 &source_pixel); 183 184 glProduceTextureDirectCHROMIUM(tex1, GL_TEXTURE_2D, mailbox1); 185 glFlush(); 186 187 gl2_.MakeCurrent(); 188 189 GLuint tex2 = glCreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); 190 glBindTexture(GL_TEXTURE_2D, tex2); 191 EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); 192 glProduceTextureDirectCHROMIUM(tex2, GL_TEXTURE_2D, mailbox2); 193 glFlush(); 194 195 gl1_.MakeCurrent(); 196 197 GLuint tex3 = glCreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); 198 glBindTexture(GL_TEXTURE_2D, tex3); 199 EXPECT_EQ(source_pixel, ReadTexel(tex3, 0, 0)); 200 } 201 202 TEST_F(GLTextureMailboxTest, ConsumeTextureValidatesKey) { 203 GLuint tex; 204 glGenTextures(1, &tex); 205 206 glBindTexture(GL_TEXTURE_2D, tex); 207 uint32 source_pixel = 0xFF0000FF; 208 glTexImage2D(GL_TEXTURE_2D, 209 0, 210 GL_RGBA, 211 1, 1, 212 0, 213 GL_RGBA, 214 GL_UNSIGNED_BYTE, 215 &source_pixel); 216 217 GLbyte invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM]; 218 glGenMailboxCHROMIUM(invalid_mailbox); 219 220 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 221 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, invalid_mailbox); 222 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); 223 224 // Ensure level 0 is still intact after glConsumeTextureCHROMIUM fails. 225 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 226 EXPECT_EQ(source_pixel, ReadTexel(tex, 0, 0)); 227 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 228 } 229 230 TEST_F(GLTextureMailboxTest, SharedTextures) { 231 gl1_.MakeCurrent(); 232 GLuint tex1; 233 glGenTextures(1, &tex1); 234 235 glBindTexture(GL_TEXTURE_2D, tex1); 236 uint32 source_pixel = 0xFF0000FF; 237 glTexImage2D(GL_TEXTURE_2D, 238 0, 239 GL_RGBA, 240 1, 1, 241 0, 242 GL_RGBA, 243 GL_UNSIGNED_BYTE, 244 &source_pixel); 245 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; 246 glGenMailboxCHROMIUM(mailbox); 247 248 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox); 249 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 250 glFlush(); 251 252 gl2_.MakeCurrent(); 253 GLuint tex2; 254 glGenTextures(1, &tex2); 255 256 glBindTexture(GL_TEXTURE_2D, tex2); 257 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); 258 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 259 260 // Change texture in context 2. 261 source_pixel = 0xFF00FF00; 262 glTexSubImage2D(GL_TEXTURE_2D, 263 0, 264 0, 0, 265 1, 1, 266 GL_RGBA, 267 GL_UNSIGNED_BYTE, 268 &source_pixel); 269 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 270 glFlush(); 271 272 // Check it in context 1. 273 gl1_.MakeCurrent(); 274 EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0)); 275 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 276 277 // Change parameters (note: ReadTexel will reset those). 278 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 281 GL_LINEAR_MIPMAP_NEAREST); 282 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 283 glFlush(); 284 285 // Check in context 2. 286 gl2_.MakeCurrent(); 287 GLint parameter = 0; 288 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ¶meter); 289 EXPECT_EQ(GL_REPEAT, parameter); 290 parameter = 0; 291 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ¶meter); 292 EXPECT_EQ(GL_LINEAR, parameter); 293 parameter = 0; 294 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ¶meter); 295 EXPECT_EQ(GL_LINEAR_MIPMAP_NEAREST, parameter); 296 297 // Delete texture in context 1. 298 gl1_.MakeCurrent(); 299 glDeleteTextures(1, &tex1); 300 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 301 302 // Check texture still exists in context 2. 303 gl2_.MakeCurrent(); 304 EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); 305 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 306 307 // The mailbox should still exist too. 308 GLuint tex3; 309 glGenTextures(1, &tex3); 310 glBindTexture(GL_TEXTURE_2D, tex3); 311 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); 312 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 313 314 // Delete both textures. 315 glDeleteTextures(1, &tex2); 316 glDeleteTextures(1, &tex3); 317 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 318 319 // Mailbox should be gone now. 320 glGenTextures(1, &tex2); 321 glBindTexture(GL_TEXTURE_2D, tex2); 322 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); 323 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); 324 glDeleteTextures(1, &tex2); 325 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 326 } 327 328 TEST_F(GLTextureMailboxTest, ProduceFrontBuffer) { 329 gl1_.MakeCurrent(); 330 Mailbox mailbox; 331 glGenMailboxCHROMIUM(mailbox.name); 332 333 gl2_.MakeCurrent(); 334 gl2_.decoder()->ProduceFrontBuffer(mailbox); 335 336 gl1_.MakeCurrent(); 337 GLuint tex1; 338 glGenTextures(1, &tex1); 339 glBindTexture(GL_TEXTURE_2D, tex1); 340 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); 341 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 342 343 gl2_.MakeCurrent(); 344 glResizeCHROMIUM(10, 10, 1); 345 glClearColor(1, 0, 0, 1); 346 glClear(GL_COLOR_BUFFER_BIT); 347 ::gles2::GetGLContext()->SwapBuffers(); 348 349 gl1_.MakeCurrent(); 350 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex1, 0, 0)); 351 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex1, 9, 9)); 352 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 353 354 gl2_.MakeCurrent(); 355 glClearColor(0, 1, 0, 1); 356 glClear(GL_COLOR_BUFFER_BIT); 357 glFlush(); 358 359 gl1_.MakeCurrent(); 360 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex1, 0, 0)); 361 362 gl2_.MakeCurrent(); 363 ::gles2::GetGLContext()->SwapBuffers(); 364 365 gl1_.MakeCurrent(); 366 EXPECT_EQ(0xFF00FF00u, ReadTexel(tex1, 0, 0)); 367 368 gl2_.MakeCurrent(); 369 gl2_.Destroy(); 370 371 gl1_.MakeCurrent(); 372 EXPECT_EQ(0xFF00FF00u, ReadTexel(tex1, 0, 0)); 373 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 374 glDeleteTextures(1, &tex1); 375 } 376 377 TEST_F(GLTextureMailboxTest, ProduceTextureDirectInvalidTarget) { 378 gl1_.MakeCurrent(); 379 380 GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM]; 381 glGenMailboxCHROMIUM(mailbox1); 382 383 GLuint tex1; 384 glGenTextures(1, &tex1); 385 386 glBindTexture(GL_TEXTURE_CUBE_MAP, tex1); 387 uint32 source_pixel = 0xFF0000FF; 388 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 389 0, 390 GL_RGBA, 391 1, 1, 392 0, 393 GL_RGBA, 394 GL_UNSIGNED_BYTE, 395 &source_pixel); 396 397 glProduceTextureDirectCHROMIUM(tex1, GL_TEXTURE_2D, mailbox1); 398 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); 399 } 400 401 // http://crbug.com/281565 402 #if !defined(OS_ANDROID) 403 TEST_F(GLTextureMailboxTest, ProduceFrontBufferMultipleContexts) { 404 gl1_.MakeCurrent(); 405 Mailbox mailbox[2]; 406 glGenMailboxCHROMIUM(mailbox[0].name); 407 glGenMailboxCHROMIUM(mailbox[1].name); 408 GLuint tex[2]; 409 glGenTextures(2, tex); 410 411 GLManager::Options options; 412 options.share_mailbox_manager = &gl1_; 413 GLManager other_gl[2]; 414 for (size_t i = 0; i < 2; ++i) { 415 other_gl[i].Initialize(options); 416 other_gl[i].MakeCurrent(); 417 other_gl[i].decoder()->ProduceFrontBuffer(mailbox[i]); 418 // Make sure both "other gl" are in the same share group. 419 if (!options.share_group_manager) 420 options.share_group_manager = other_gl+i; 421 } 422 423 424 gl1_.MakeCurrent(); 425 for (size_t i = 0; i < 2; ++i) { 426 glBindTexture(GL_TEXTURE_2D, tex[i]); 427 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox[i].name); 428 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); 429 } 430 431 for (size_t i = 0; i < 2; ++i) { 432 other_gl[i].MakeCurrent(); 433 glResizeCHROMIUM(10, 10, 1); 434 glClearColor(1-i%2, i%2, 0, 1); 435 glClear(GL_COLOR_BUFFER_BIT); 436 ::gles2::GetGLContext()->SwapBuffers(); 437 } 438 439 gl1_.MakeCurrent(); 440 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex[0], 0, 0)); 441 EXPECT_EQ(0xFF00FF00u, ReadTexel(tex[1], 9, 9)); 442 443 for (size_t i = 0; i < 2; ++i) { 444 other_gl[i].MakeCurrent(); 445 other_gl[i].Destroy(); 446 } 447 448 gl1_.MakeCurrent(); 449 glDeleteTextures(2, tex); 450 } 451 #endif 452 453 } // namespace gpu 454 455