Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 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 "ppapi/tests/test_compositor.h"
      6 
      7 #include <GLES2/gl2.h>
      8 #include <GLES2/gl2ext.h>
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 
     13 #include "ppapi/c/ppb_opengles2.h"
     14 #include "ppapi/cpp/compositor.h"
     15 #include "ppapi/cpp/compositor_layer.h"
     16 #include "ppapi/cpp/image_data.h"
     17 #include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
     18 #include "ppapi/lib/gl/include/GLES2/gl2.h"
     19 #include "ppapi/lib/gl/include/GLES2/gl2ext.h"
     20 #include "ppapi/tests/test_utils.h"
     21 
     22 namespace {
     23 
     24 const float kMatrix[16] = {
     25   1.0f, 0.0f, 0.0f, 0.0f,
     26   0.0f, 1.0f, 0.0f, 0.0f,
     27   0.0f, 0.0f, 1.0f, 0.0f,
     28   0.0f, 0.0f, 0.0f, 1.0f,
     29 };
     30 
     31 }  // namespace
     32 
     33 REGISTER_TEST_CASE(Compositor);
     34 
     35 #define VERIFY(r) do { \
     36     std::string result = (r); \
     37     if (result != "") \
     38       return result; \
     39   } while (false)
     40 
     41 bool TestCompositor::Init() {
     42   if (!CheckTestingInterface())
     43     return false;
     44 
     45   if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface()))
     46     return false;
     47 
     48   return true;
     49 }
     50 
     51 void TestCompositor::RunTests(const std::string& filter) {
     52   RUN_CALLBACK_TEST(TestCompositor, Release, filter);
     53   RUN_CALLBACK_TEST(TestCompositor, ReleaseWithoutCommit, filter);
     54   RUN_CALLBACK_TEST(TestCompositor, CommitTwoTimesWithoutChange, filter);
     55   RUN_CALLBACK_TEST(TestCompositor, General, filter);
     56 
     57   RUN_CALLBACK_TEST(TestCompositor, ReleaseUnbound, filter);
     58   RUN_CALLBACK_TEST(TestCompositor, ReleaseWithoutCommitUnbound, filter);
     59   RUN_CALLBACK_TEST(TestCompositor, CommitTwoTimesWithoutChangeUnbound, filter);
     60   RUN_CALLBACK_TEST(TestCompositor, GeneralUnbound, filter);
     61 
     62   RUN_CALLBACK_TEST(TestCompositor, BindUnbind, filter);
     63 }
     64 
     65 std::string TestCompositor::TestRelease() {
     66   return TestReleaseInternal(true);
     67 }
     68 
     69 std::string TestCompositor::TestReleaseWithoutCommit() {
     70   return TestReleaseWithoutCommitInternal(true);
     71 }
     72 
     73 std::string TestCompositor::TestCommitTwoTimesWithoutChange() {
     74   return TestCommitTwoTimesWithoutChangeInternal(true);
     75 }
     76 
     77 std::string TestCompositor::TestGeneral() {
     78   return TestGeneralInternal(true);
     79 }
     80 
     81 std::string TestCompositor::TestReleaseUnbound() {
     82   return TestReleaseInternal(false);
     83 }
     84 
     85 std::string TestCompositor::TestReleaseWithoutCommitUnbound() {
     86   return TestReleaseWithoutCommitInternal(false);
     87 }
     88 
     89 std::string TestCompositor::TestCommitTwoTimesWithoutChangeUnbound() {
     90   return TestCommitTwoTimesWithoutChangeInternal(false);
     91 }
     92 
     93 std::string TestCompositor::TestGeneralUnbound() {
     94   return TestGeneralInternal(false);
     95 }
     96 
     97 // TODO(penghuang): refactor common part in all tests to a member function.
     98 std::string TestCompositor::TestBindUnbind() {
     99   // Setup GLES2
    100   const int32_t attribs[] = {
    101     PP_GRAPHICS3DATTRIB_WIDTH, 16,
    102     PP_GRAPHICS3DATTRIB_HEIGHT, 16,
    103     PP_GRAPHICS3DATTRIB_NONE
    104   };
    105   pp::Graphics3D graphics_3d(instance_, attribs);
    106   ASSERT_FALSE(graphics_3d.is_null());
    107   glSetCurrentContextPPAPI(graphics_3d.pp_resource());
    108 
    109   pp::Compositor compositor = pp::Compositor(instance_);
    110   ASSERT_FALSE(compositor.is_null());
    111 
    112   // Add layers on an unbound compositor.
    113   pp::CompositorLayer color_layer = compositor.AddLayer();
    114   ASSERT_FALSE(color_layer.is_null());
    115 
    116   VERIFY(SetColorLayer(color_layer, PP_OK));
    117 
    118   uint32_t texture = 0;
    119   VERIFY(CreateTexture(&texture));
    120   pp::CompositorLayer texture_layer = compositor.AddLayer();
    121   ASSERT_FALSE(texture_layer.is_null());
    122   TestCompletionCallback texture_release_callback(instance_->pp_instance(),
    123                                                   PP_REQUIRED);
    124   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    125             texture_layer.SetTexture(graphics_3d, texture, pp::Size(100, 100),
    126                                      texture_release_callback.GetCallback()));
    127 
    128   pp::ImageData image;
    129   VERIFY(CreateImage(&image));
    130   pp::CompositorLayer image_layer = compositor.AddLayer();
    131   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    132                                                 PP_REQUIRED);
    133   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    134             image_layer.SetImage(image, pp::Size(100, 100),
    135                                  image_release_callback.GetCallback()));
    136 
    137   // Commit layers to the chromium compositor.
    138   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    139   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    140   CHECK_CALLBACK_BEHAVIOR(callback);
    141   ASSERT_EQ(PP_OK, callback.result());
    142 
    143   // Bind the compositor and call CommitLayers() again.
    144   ASSERT_TRUE(instance_->BindGraphics(compositor));
    145   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    146   CHECK_CALLBACK_BEHAVIOR(callback);
    147   ASSERT_EQ(PP_OK, callback.result());
    148 
    149   // Unbind the compositor and call CommitLayers() again.
    150   ASSERT_TRUE(instance_->BindGraphics(pp::Compositor()));
    151   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    152   CHECK_CALLBACK_BEHAVIOR(callback);
    153   ASSERT_EQ(PP_OK, callback.result());
    154 
    155   // Reset layers and call CommitLayers() again.
    156   ASSERT_EQ(PP_OK, compositor.ResetLayers());
    157   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    158   CHECK_CALLBACK_BEHAVIOR(callback);
    159   ASSERT_EQ(PP_OK, callback.result());
    160 
    161   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    162   ASSERT_EQ(PP_OK, texture_release_callback.result());
    163   ReleaseTexture(texture);
    164 
    165   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    166   ASSERT_EQ(PP_OK, image_release_callback.result());
    167 
    168   // Reset
    169   glSetCurrentContextPPAPI(0);
    170 
    171   PASS();
    172 }
    173 
    174 std::string TestCompositor::TestReleaseInternal(bool bind) {
    175   // Setup GLES2
    176   const int32_t attribs[] = {
    177     PP_GRAPHICS3DATTRIB_WIDTH, 16,
    178     PP_GRAPHICS3DATTRIB_HEIGHT, 16,
    179     PP_GRAPHICS3DATTRIB_NONE
    180   };
    181   pp::Graphics3D graphics_3d(instance_, attribs);
    182   ASSERT_FALSE(graphics_3d.is_null());
    183   glSetCurrentContextPPAPI(graphics_3d.pp_resource());
    184 
    185   pp::Compositor compositor = pp::Compositor(instance_);
    186   ASSERT_FALSE(compositor.is_null());
    187 
    188   // Bind the compositor to the instance
    189   if (bind)
    190     ASSERT_TRUE(instance_->BindGraphics(compositor));
    191 
    192   pp::CompositorLayer color_layer = compositor.AddLayer();
    193   ASSERT_FALSE(color_layer.is_null());
    194 
    195   VERIFY(SetColorLayer(color_layer, PP_OK));
    196 
    197   uint32_t texture = 0;
    198   VERIFY(CreateTexture(&texture));
    199   pp::CompositorLayer texture_layer = compositor.AddLayer();
    200   ASSERT_FALSE(texture_layer.is_null());
    201   TestCompletionCallback texture_release_callback(instance_->pp_instance(),
    202                                                   PP_REQUIRED);
    203   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    204             texture_layer.SetTexture(graphics_3d, texture, pp::Size(100, 100),
    205                                      texture_release_callback.GetCallback()));
    206 
    207   pp::ImageData image;
    208   VERIFY(CreateImage(&image));
    209   pp::CompositorLayer image_layer = compositor.AddLayer();
    210   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    211                                                 PP_REQUIRED);
    212   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    213             image_layer.SetImage(image, pp::Size(100, 100),
    214                                  image_release_callback.GetCallback()));
    215 
    216   // Commit layers to the chromium compositor.
    217   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    218   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    219   CHECK_CALLBACK_BEHAVIOR(callback);
    220   ASSERT_EQ(PP_OK, callback.result());
    221 
    222   // Release the compositor, and then release_callback will be aborted.
    223   compositor = pp::Compositor();
    224 
    225   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    226   ASSERT_EQ(PP_ERROR_ABORTED, texture_release_callback.result());
    227   ReleaseTexture(texture);
    228 
    229   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    230   ASSERT_EQ(PP_ERROR_ABORTED, image_release_callback.result());
    231 
    232   // Reset
    233   glSetCurrentContextPPAPI(0);
    234 
    235   PASS();
    236 }
    237 
    238 std::string TestCompositor::TestReleaseWithoutCommitInternal(bool bind) {
    239   // Setup GLES2
    240   const int32_t attribs[] = {
    241     PP_GRAPHICS3DATTRIB_WIDTH, 16,
    242     PP_GRAPHICS3DATTRIB_HEIGHT, 16,
    243     PP_GRAPHICS3DATTRIB_NONE
    244   };
    245   pp::Graphics3D graphics_3d(instance_, attribs);
    246   ASSERT_FALSE(graphics_3d.is_null());
    247   glSetCurrentContextPPAPI(graphics_3d.pp_resource());
    248 
    249   pp::Compositor compositor = pp::Compositor(instance_);
    250   ASSERT_FALSE(compositor.is_null());
    251 
    252   // Bind the compositor to the instance
    253   if (bind)
    254     ASSERT_TRUE(instance_->BindGraphics(compositor));
    255 
    256   pp::CompositorLayer color_layer = compositor.AddLayer();
    257   ASSERT_FALSE(color_layer.is_null());
    258 
    259   VERIFY(SetColorLayer(color_layer, PP_OK));
    260 
    261   uint32_t texture = 0;
    262   VERIFY(CreateTexture(&texture));
    263   pp::CompositorLayer texture_layer = compositor.AddLayer();
    264   ASSERT_FALSE(texture_layer.is_null());
    265   TestCompletionCallback texture_release_callback(instance_->pp_instance(),
    266                                                   PP_REQUIRED);
    267   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    268             texture_layer.SetTexture(graphics_3d, texture, pp::Size(100, 100),
    269                                      texture_release_callback.GetCallback()));
    270 
    271   pp::ImageData image;
    272   VERIFY(CreateImage(&image));
    273   pp::CompositorLayer image_layer = compositor.AddLayer();
    274   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    275                                                 PP_REQUIRED);
    276   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    277             image_layer.SetImage(image, pp::Size(100, 100),
    278                                  image_release_callback.GetCallback()));
    279 
    280   // Release the compositor, and then release_callback will be aborted.
    281   compositor = pp::Compositor();
    282 
    283   // All release_callbacks should be called.
    284   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    285   ASSERT_EQ(PP_ERROR_ABORTED, texture_release_callback.result());
    286   ReleaseTexture(texture);
    287 
    288   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    289   ASSERT_EQ(PP_ERROR_ABORTED, image_release_callback.result());
    290 
    291   // The layer associated to the compositor will become invalidated.
    292   VERIFY(SetColorLayer(color_layer, PP_ERROR_BADRESOURCE));
    293 
    294   // Reset
    295   glSetCurrentContextPPAPI(0);
    296 
    297   PASS();
    298 }
    299 
    300 std::string TestCompositor::TestCommitTwoTimesWithoutChangeInternal(bool bind) {
    301   pp::Compositor compositor(instance_);
    302   ASSERT_FALSE(compositor.is_null());
    303   if (bind)
    304     ASSERT_TRUE(instance_->BindGraphics(compositor));
    305   pp::CompositorLayer layer = compositor.AddLayer();
    306   ASSERT_FALSE(layer.is_null());
    307   VERIFY(SetColorLayer(layer, PP_OK));
    308 
    309   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    310   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    311   CHECK_CALLBACK_BEHAVIOR(callback);
    312   ASSERT_EQ(PP_OK, callback.result());
    313 
    314   // CommitLayers() without any change.
    315   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    316   CHECK_CALLBACK_BEHAVIOR(callback);
    317   ASSERT_EQ(PP_OK, callback.result());
    318 
    319   PASS();
    320 }
    321 
    322 std::string TestCompositor::TestGeneralInternal(bool bind) {
    323   // Setup GLES2
    324   const int32_t attribs[] = {
    325     PP_GRAPHICS3DATTRIB_WIDTH, 16,
    326     PP_GRAPHICS3DATTRIB_HEIGHT, 16,
    327     PP_GRAPHICS3DATTRIB_NONE
    328   };
    329   pp::Graphics3D graphics_3d(instance_, attribs);
    330   ASSERT_FALSE(graphics_3d.is_null());
    331   glSetCurrentContextPPAPI(graphics_3d.pp_resource());
    332 
    333   // All functions should work with a bound compositor
    334   pp::Compositor compositor(instance_);
    335   ASSERT_FALSE(compositor.is_null());
    336   if (bind)
    337     ASSERT_TRUE(instance_->BindGraphics(compositor));
    338 
    339   pp::CompositorLayer color_layer = compositor.AddLayer();
    340   ASSERT_FALSE(color_layer.is_null());
    341   VERIFY(SetColorLayer(color_layer, PP_OK));
    342 
    343   uint32_t texture = 0;
    344   VERIFY(CreateTexture(&texture));
    345   pp::CompositorLayer texture_layer = compositor.AddLayer();
    346   ASSERT_FALSE(texture_layer.is_null());
    347   TestCompletionCallback texture_release_callback(instance_->pp_instance(),
    348                                                   PP_REQUIRED);
    349   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    350             texture_layer.SetTexture(graphics_3d, texture, pp::Size(100, 100),
    351                                      texture_release_callback.GetCallback()));
    352 
    353   pp::ImageData image;
    354   VERIFY(CreateImage(&image));
    355   pp::CompositorLayer image_layer = compositor.AddLayer();
    356   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    357                                                 PP_REQUIRED);
    358   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    359             image_layer.SetImage(image, pp::Size(100, 100),
    360                                  image_release_callback.GetCallback()));
    361 
    362   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    363   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    364   CHECK_CALLBACK_BEHAVIOR(callback);
    365   ASSERT_EQ(PP_OK, callback.result());
    366 
    367   // After ResetLayers(), all layers should be invalidated.
    368   ASSERT_EQ(PP_OK, compositor.ResetLayers());
    369   VERIFY(SetColorLayer(color_layer, PP_ERROR_BADRESOURCE));
    370 
    371   // Commit empty layer stack to the chromium compositor, and then the texture
    372   // and the image will be released by the chromium compositor soon.
    373   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    374   CHECK_CALLBACK_BEHAVIOR(callback);
    375   ASSERT_EQ(PP_OK, callback.result());
    376 
    377   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    378   ASSERT_EQ(PP_OK, texture_release_callback.result());
    379   ReleaseTexture(texture);
    380 
    381   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    382   ASSERT_EQ(PP_OK, image_release_callback.result());
    383 
    384   // Reset
    385   glSetCurrentContextPPAPI(0);
    386 
    387   PASS();
    388 }
    389 
    390 std::string TestCompositor::CreateTexture(uint32_t* texture) {
    391   glGenTextures(1, texture);
    392   ASSERT_NE(0, *texture);
    393   glBindTexture(GL_TEXTURE_2D, *texture);
    394   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 400, 400, 0,
    395                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    396   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    397   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    398   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    399   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    400   glBindTexture(GL_TEXTURE_2D, 0);
    401 
    402   return std::string();
    403 }
    404 
    405 std::string TestCompositor::ReleaseTexture(uint32_t texture) {
    406   ASSERT_NE(0u, texture);
    407   glDeleteTextures(1, &texture);
    408 
    409   return std::string();
    410 }
    411 
    412 std::string TestCompositor::CreateImage(pp::ImageData* image) {
    413   *image = pp::ImageData(instance_, PP_IMAGEDATAFORMAT_RGBA_PREMUL,
    414                          pp::Size(400, 400), false);
    415   ASSERT_FALSE(image->is_null());
    416 
    417   return std::string();
    418 }
    419 
    420 std::string TestCompositor::SetColorLayer(
    421     pp::CompositorLayer layer, int32_t result) {
    422   ASSERT_EQ(result, layer.SetColor(255, 255, 255, 255, pp::Size(100, 100)));
    423   ASSERT_EQ(result, layer.SetClipRect(pp::Rect(0, 0, 50, 50)));
    424   ASSERT_EQ(result, layer.SetTransform(kMatrix));
    425   ASSERT_EQ(result, layer.SetOpacity(128));
    426 
    427   return std::string();
    428 }
    429 
    430 
    431