Home | History | Annotate | Download | only in tests
      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, &parameter);
    233   EXPECT_EQ(GL_REPEAT, parameter);
    234   parameter = 0;
    235   glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &parameter);
    236   EXPECT_EQ(GL_LINEAR, parameter);
    237   parameter = 0;
    238   glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &parameter);
    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 TEST_F(GLTextureMailboxTest, ProduceFrontBufferMultipleContexts) {
    322   gl1_.MakeCurrent();
    323   Mailbox mailbox[2];
    324   glGenMailboxCHROMIUM(mailbox[0].name);
    325   glGenMailboxCHROMIUM(mailbox[1].name);
    326   GLuint tex[2];
    327   glGenTextures(2, tex);
    328 
    329   GLManager::Options options;
    330   options.share_mailbox_manager = &gl1_;
    331   GLManager other_gl[2];
    332   for (size_t i = 0; i < 2; ++i) {
    333     other_gl[i].Initialize(options);
    334     other_gl[i].MakeCurrent();
    335     other_gl[i].decoder()->ProduceFrontBuffer(mailbox[i]);
    336     // Make sure both "other gl" are in the same share group.
    337     if (!options.share_group_manager)
    338       options.share_group_manager = other_gl+i;
    339   }
    340 
    341 
    342   gl1_.MakeCurrent();
    343   for (size_t i = 0; i < 2; ++i) {
    344     glBindTexture(GL_TEXTURE_2D, tex[i]);
    345     glConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox[i].name);
    346     EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
    347   }
    348 
    349   for (size_t i = 0; i < 2; ++i) {
    350     other_gl[i].MakeCurrent();
    351     glResizeCHROMIUM(10, 10, 1);
    352     glClearColor(1-i%2, i%2, 0, 1);
    353     glClear(GL_COLOR_BUFFER_BIT);
    354     ::gles2::GetGLContext()->SwapBuffers();
    355   }
    356 
    357   gl1_.MakeCurrent();
    358   EXPECT_EQ(0xFF0000FFu, ReadTexel(tex[0], 0, 0));
    359   EXPECT_EQ(0xFF00FF00u, ReadTexel(tex[1], 9, 9));
    360 
    361   for (size_t i = 0; i < 2; ++i) {
    362     other_gl[i].MakeCurrent();
    363     other_gl[i].Destroy();
    364   }
    365 
    366   gl1_.MakeCurrent();
    367   glDeleteTextures(2, tex);
    368 }
    369 
    370 }  // namespace gpu
    371 
    372