| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 | |
| 46 glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); | |
| 47 | |
| 48 glDeleteFramebuffers(1, &fbo); | |
| 49 | |
| 50 return texel; | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 class GLTextureMailboxTest : public testing::Test { | |
| 55 protected: | |
| 56 virtual void SetUp() { | |
| 57 gl1_.Initialize(GLManager::Options()); | |
| 58 GLManager::Options options; | |
| 59 options.share_mailbox_manager = &gl1_; | |
| 60 gl2_.Initialize(options); | |
| 61 } | |
| 62 | |
| 63 virtual void TearDown() { | |
| 64 gl1_.Destroy(); | |
| 65 gl2_.Destroy(); | |
| 66 } | |
| 67 | |
| 68 GLManager gl1_; | |
| 69 GLManager gl2_; | |
| 70 }; | |
| 71 | |
| 72 TEST_F(GLTextureMailboxTest, ProduceAndConsumeTexture) { | |
| 73 gl1_.MakeCurrent(); | |
| 74 | |
| 75 GLbyte mailbox1[GL_MAILBOX_SIZE_CHROMIUM]; | |
| 76 glGenMailboxCHROMIUM(mailbox1); | |
| 77 | |
| 78 GLbyte mailbox2[GL_MAILBOX_SIZE_CHROMIUM]; | |
| 79 glGenMailboxCHROMIUM(mailbox2); | |
| 80 | |
| 81 GLuint tex1; | |
| 82 glGenTextures(1, &tex1); | |
| 83 | |
| 84 glBindTexture(GL_TEXTURE_2D, tex1); | |
| 85 uint32 source_pixel = 0xFF0000FF; | |
| 86 glTexImage2D(GL_TEXTURE_2D, | |
| 87 0, | |
| 88 GL_RGBA, | |
| 89 1, 1, | |
| 90 0, | |
| 91 GL_RGBA, | |
| 92 GL_UNSIGNED_BYTE, | |
| 93 &source_pixel); | |
| 94 | |
| 95 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); | |
| 96 glFlush(); | |
| 97 | |
| 98 gl2_.MakeCurrent(); | |
| 99 | |
| 100 GLuint tex2; | |
| 101 glGenTextures(1, &tex2); | |
| 102 | |
| 103 glBindTexture(GL_TEXTURE_2D, tex2); | |
| 104 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox1); | |
| 105 EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); | |
| 106 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); | |
| 107 glFlush(); | |
| 108 | |
| 109 gl1_.MakeCurrent(); | |
| 110 | |
| 111 glBindTexture(GL_TEXTURE_2D, tex1); | |
| 112 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox2); | |
| 113 EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0)); | |
| 114 } | |
| 115 | |
| 116 TEST_F(GLTextureMailboxTest, ProduceTextureValidatesKey) { | |
| 117 GLuint tex; | |
| 118 glGenTextures(1, &tex); | |
| 119 | |
| 120 glBindTexture(GL_TEXTURE_2D, tex); | |
| 121 uint32 source_pixel = 0xFF0000FF; | |
| 122 glTexImage2D(GL_TEXTURE_2D, | |
| 123 0, | |
| 124 GL_RGBA, | |
| 125 1, 1, | |
| 126 0, | |
| 127 GL_RGBA, | |
| 128 GL_UNSIGNED_BYTE, | |
| 129 &source_pixel); | |
| 130 | |
| 131 GLbyte invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM]; | |
| 132 glGenMailboxCHROMIUM(invalid_mailbox); | |
| 133 ++invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM - 1]; | |
| 134 | |
| 135 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 136 glProduceTextureCHROMIUM(GL_TEXTURE_2D, invalid_mailbox); | |
| 137 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); | |
| 138 | |
| 139 // Ensure level 0 is still intact after glProduceTextureCHROMIUM fails. | |
| 140 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 141 EXPECT_EQ(source_pixel, ReadTexel(tex, 0, 0)); | |
| 142 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 143 } | |
| 144 | |
| 145 TEST_F(GLTextureMailboxTest, ConsumeTextureValidatesKey) { | |
| 146 GLuint tex; | |
| 147 glGenTextures(1, &tex); | |
| 148 | |
| 149 glBindTexture(GL_TEXTURE_2D, tex); | |
| 150 uint32 source_pixel = 0xFF0000FF; | |
| 151 glTexImage2D(GL_TEXTURE_2D, | |
| 152 0, | |
| 153 GL_RGBA, | |
| 154 1, 1, | |
| 155 0, | |
| 156 GL_RGBA, | |
| 157 GL_UNSIGNED_BYTE, | |
| 158 &source_pixel); | |
| 159 | |
| 160 GLbyte invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM]; | |
| 161 glGenMailboxCHROMIUM(invalid_mailbox); | |
| 162 ++invalid_mailbox[GL_MAILBOX_SIZE_CHROMIUM - 1]; | |
| 163 | |
| 164 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 165 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, invalid_mailbox); | |
| 166 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); | |
| 167 | |
| 168 // Ensure level 0 is still intact after glConsumeTextureCHROMIUM fails. | |
| 169 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 170 EXPECT_EQ(source_pixel, ReadTexel(tex, 0, 0)); | |
| 171 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 172 } | |
| 173 | |
| 174 TEST_F(GLTextureMailboxTest, SharedTextures) { | |
| 175 gl1_.MakeCurrent(); | |
| 176 GLuint tex1; | |
| 177 glGenTextures(1, &tex1); | |
| 178 | |
| 179 glBindTexture(GL_TEXTURE_2D, tex1); | |
| 180 uint32 source_pixel = 0xFF0000FF; | |
| 181 glTexImage2D(GL_TEXTURE_2D, | |
| 182 0, | |
| 183 GL_RGBA, | |
| 184 1, 1, | |
| 185 0, | |
| 186 GL_RGBA, | |
| 187 GL_UNSIGNED_BYTE, | |
| 188 &source_pixel); | |
| 189 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM]; | |
| 190 glGenMailboxCHROMIUM(mailbox); | |
| 191 | |
| 192 glProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox); | |
| 193 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 194 glFlush(); | |
| 195 | |
| 196 gl2_.MakeCurrent(); | |
| 197 GLuint tex2; | |
| 198 glGenTextures(1, &tex2); | |
| 199 | |
| 200 glBindTexture(GL_TEXTURE_2D, tex2); | |
| 201 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); | |
| 202 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 203 | |
| 204 // Change texture in context 2. | |
| 205 source_pixel = 0xFF00FF00; | |
| 206 glTexSubImage2D(GL_TEXTURE_2D, | |
| 207 0, | |
| 208 0, 0, | |
| 209 1, 1, | |
| 210 GL_RGBA, | |
| 211 GL_UNSIGNED_BYTE, | |
| 212 &source_pixel); | |
| 213 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 214 glFlush(); | |
| 215 | |
| 216 // Check it in context 1. | |
| 217 gl1_.MakeCurrent(); | |
| 218 EXPECT_EQ(source_pixel, ReadTexel(tex1, 0, 0)); | |
| 219 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 220 | |
| 221 // Change parameters (note: ReadTexel will reset those). | |
| 222 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | |
| 223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
| 224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | |
| 225 GL_LINEAR_MIPMAP_NEAREST); | |
| 226 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 227 glFlush(); | |
| 228 | |
| 229 // Check in context 2. | |
| 230 gl2_.MakeCurrent(); | |
| 231 GLint parameter = 0; | |
| 232 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ¶meter); | |
| 233 EXPECT_EQ(GL_REPEAT, parameter); | |
| 234 parameter = 0; | |
| 235 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, ¶meter); | |
| 236 EXPECT_EQ(GL_LINEAR, parameter); | |
| 237 parameter = 0; | |
| 238 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, ¶meter); | |
| 239 EXPECT_EQ(GL_LINEAR_MIPMAP_NEAREST, parameter); | |
| 240 | |
| 241 // Delete texture in context 1. | |
| 242 gl1_.MakeCurrent(); | |
| 243 glDeleteTextures(1, &tex1); | |
| 244 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 245 | |
| 246 // Check texture still exists in context 2. | |
| 247 gl2_.MakeCurrent(); | |
| 248 EXPECT_EQ(source_pixel, ReadTexel(tex2, 0, 0)); | |
| 249 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 250 | |
| 251 // The mailbox should still exist too. | |
| 252 GLuint tex3; | |
| 253 glGenTextures(1, &tex3); | |
| 254 glBindTexture(GL_TEXTURE_2D, tex3); | |
| 255 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); | |
| 256 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 257 | |
| 258 // Delete both textures. | |
| 259 glDeleteTextures(1, &tex2); | |
| 260 glDeleteTextures(1, &tex3); | |
| 261 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 262 | |
| 263 // Mailbox should be gone now. | |
| 264 glGenTextures(1, &tex2); | |
| 265 glBindTexture(GL_TEXTURE_2D, tex2); | |
| 266 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox); | |
| 267 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError()); | |
| 268 glDeleteTextures(1, &tex2); | |
| 269 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 270 } | |
| 271 | |
| 272 TEST_F(GLTextureMailboxTest, ProduceFrontBuffer) { | |
| 273 gl1_.MakeCurrent(); | |
| 274 Mailbox mailbox; | |
| 275 glGenMailboxCHROMIUM(mailbox.name); | |
| 276 | |
| 277 gl2_.MakeCurrent(); | |
| 278 gl2_.decoder()->ProduceFrontBuffer(mailbox); | |
| 279 | |
| 280 gl1_.MakeCurrent(); | |
| 281 GLuint tex1; | |
| 282 glGenTextures(1, &tex1); | |
| 283 glBindTexture(GL_TEXTURE_2D, tex1); | |
| 284 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
| 285 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 286 | |
| 287 gl2_.MakeCurrent(); | |
| 288 glResizeCHROMIUM(10, 10, 1); | |
| 289 glClearColor(1, 0, 0, 1); | |
| 290 glClear(GL_COLOR_BUFFER_BIT); | |
| 291 ::gles2::GetGLContext()->SwapBuffers(); | |
| 292 | |
| 293 gl1_.MakeCurrent(); | |
| 294 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex1, 0, 0)); | |
| 295 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex1, 9, 9)); | |
| 296 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 297 | |
| 298 gl2_.MakeCurrent(); | |
| 299 glClearColor(0, 1, 0, 1); | |
| 300 glClear(GL_COLOR_BUFFER_BIT); | |
| 301 glFlush(); | |
| 302 | |
| 303 gl1_.MakeCurrent(); | |
| 304 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex1, 0, 0)); | |
| 305 | |
| 306 gl2_.MakeCurrent(); | |
| 307 ::gles2::GetGLContext()->SwapBuffers(); | |
| 308 | |
| 309 gl1_.MakeCurrent(); | |
| 310 EXPECT_EQ(0xFF00FF00u, ReadTexel(tex1, 0, 0)); | |
| 311 | |
| 312 gl2_.MakeCurrent(); | |
| 313 gl2_.Destroy(); | |
| 314 | |
| 315 gl1_.MakeCurrent(); | |
| 316 EXPECT_EQ(0xFF00FF00u, ReadTexel(tex1, 0, 0)); | |
| 317 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 318 glDeleteTextures(1, &tex1); | |
| 319 } | |
| 320 | |
| 321 // http://crbug.com/281565 | |
| 322 #if !defined(OS_ANDROID) | |
| 323 TEST_F(GLTextureMailboxTest, ProduceFrontBufferMultipleContexts) { | |
| 324 gl1_.MakeCurrent(); | |
| 325 Mailbox mailbox[2]; | |
| 326 glGenMailboxCHROMIUM(mailbox[0].name); | |
| 327 glGenMailboxCHROMIUM(mailbox[1].name); | |
| 328 GLuint tex[2]; | |
| 329 glGenTextures(2, tex); | |
| 330 | |
| 331 GLManager::Options options; | |
| 332 options.share_mailbox_manager = &gl1_; | |
| 333 GLManager other_gl[2]; | |
| 334 for (size_t i = 0; i < 2; ++i) { | |
| 335 other_gl[i].Initialize(options); | |
| 336 other_gl[i].MakeCurrent(); | |
| 337 other_gl[i].decoder()->ProduceFrontBuffer(mailbox[i]); | |
| 338 // Make sure both "other gl" are in the same share group. | |
| 339 if (!options.share_group_manager) | |
| 340 options.share_group_manager = other_gl+i; | |
| 341 } | |
| 342 | |
| 343 | |
| 344 gl1_.MakeCurrent(); | |
| 345 for (size_t i = 0; i < 2; ++i) { | |
| 346 glBindTexture(GL_TEXTURE_2D, tex[i]); | |
| 347 glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox[i].name); | |
| 348 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError()); | |
| 349 } | |
| 350 | |
| 351 for (size_t i = 0; i < 2; ++i) { | |
| 352 other_gl[i].MakeCurrent(); | |
| 353 glResizeCHROMIUM(10, 10, 1); | |
| 354 glClearColor(1-i%2, i%2, 0, 1); | |
| 355 glClear(GL_COLOR_BUFFER_BIT); | |
| 356 ::gles2::GetGLContext()->SwapBuffers(); | |
| 357 } | |
| 358 | |
| 359 gl1_.MakeCurrent(); | |
| 360 EXPECT_EQ(0xFF0000FFu, ReadTexel(tex[0], 0, 0)); | |
| 361 EXPECT_EQ(0xFF00FF00u, ReadTexel(tex[1], 9, 9)); | |
| 362 | |
| 363 for (size_t i = 0; i < 2; ++i) { | |
| 364 other_gl[i].MakeCurrent(); | |
| 365 other_gl[i].Destroy(); | |
| 366 } | |
| 367 | |
| 368 gl1_.MakeCurrent(); | |
| 369 glDeleteTextures(2, tex); | |
| 370 } | |
| 371 #endif | |
| 372 | |
| 373 } // namespace gpu | |
| 374 | |
| OLD | NEW |