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, GL_TEXTURE_2D, texture,
    126                                      pp::Size(100, 100),
    127                                      texture_release_callback.GetCallback()));
    128 
    129   pp::ImageData image;
    130   VERIFY(CreateImage(&image));
    131   pp::CompositorLayer image_layer = compositor.AddLayer();
    132   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    133                                                 PP_REQUIRED);
    134   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    135             image_layer.SetImage(image, pp::Size(100, 100),
    136                                  image_release_callback.GetCallback()));
    137 
    138   // Commit layers to the chromium compositor.
    139   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    140   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    141   CHECK_CALLBACK_BEHAVIOR(callback);
    142   ASSERT_EQ(PP_OK, callback.result());
    143 
    144   // Bind the compositor and call CommitLayers() again.
    145   ASSERT_TRUE(instance_->BindGraphics(compositor));
    146   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    147   CHECK_CALLBACK_BEHAVIOR(callback);
    148   ASSERT_EQ(PP_OK, callback.result());
    149 
    150   // Unbind the compositor and call CommitLayers() again.
    151   ASSERT_TRUE(instance_->BindGraphics(pp::Compositor()));
    152   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    153   CHECK_CALLBACK_BEHAVIOR(callback);
    154   ASSERT_EQ(PP_OK, callback.result());
    155 
    156   // Reset layers and call CommitLayers() again.
    157   ASSERT_EQ(PP_OK, compositor.ResetLayers());
    158   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    159   CHECK_CALLBACK_BEHAVIOR(callback);
    160   ASSERT_EQ(PP_OK, callback.result());
    161 
    162   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    163   ASSERT_EQ(PP_OK, texture_release_callback.result());
    164   ReleaseTexture(texture);
    165 
    166   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    167   ASSERT_EQ(PP_OK, image_release_callback.result());
    168 
    169   // Reset
    170   glSetCurrentContextPPAPI(0);
    171 
    172   PASS();
    173 }
    174 
    175 std::string TestCompositor::TestReleaseInternal(bool bind) {
    176   // Setup GLES2
    177   const int32_t attribs[] = {
    178     PP_GRAPHICS3DATTRIB_WIDTH, 16,
    179     PP_GRAPHICS3DATTRIB_HEIGHT, 16,
    180     PP_GRAPHICS3DATTRIB_NONE
    181   };
    182   pp::Graphics3D graphics_3d(instance_, attribs);
    183   ASSERT_FALSE(graphics_3d.is_null());
    184   glSetCurrentContextPPAPI(graphics_3d.pp_resource());
    185 
    186   pp::Compositor compositor = pp::Compositor(instance_);
    187   ASSERT_FALSE(compositor.is_null());
    188 
    189   // Bind the compositor to the instance
    190   if (bind)
    191     ASSERT_TRUE(instance_->BindGraphics(compositor));
    192 
    193   pp::CompositorLayer color_layer = compositor.AddLayer();
    194   ASSERT_FALSE(color_layer.is_null());
    195 
    196   VERIFY(SetColorLayer(color_layer, PP_OK));
    197 
    198   uint32_t texture = 0;
    199   VERIFY(CreateTexture(&texture));
    200   pp::CompositorLayer texture_layer = compositor.AddLayer();
    201   ASSERT_FALSE(texture_layer.is_null());
    202   TestCompletionCallback texture_release_callback(instance_->pp_instance(),
    203                                                   PP_REQUIRED);
    204   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    205             texture_layer.SetTexture(graphics_3d, GL_TEXTURE_2D, texture,
    206                                      pp::Size(100, 100),
    207                                      texture_release_callback.GetCallback()));
    208 
    209   pp::ImageData image;
    210   VERIFY(CreateImage(&image));
    211   pp::CompositorLayer image_layer = compositor.AddLayer();
    212   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    213                                                 PP_REQUIRED);
    214   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    215             image_layer.SetImage(image, pp::Size(100, 100),
    216                                  image_release_callback.GetCallback()));
    217 
    218   // Commit layers to the chromium compositor.
    219   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    220   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    221   CHECK_CALLBACK_BEHAVIOR(callback);
    222   ASSERT_EQ(PP_OK, callback.result());
    223 
    224   // Release the compositor, and then release_callback will be aborted.
    225   compositor = pp::Compositor();
    226 
    227   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    228   ASSERT_EQ(PP_ERROR_ABORTED, texture_release_callback.result());
    229   ReleaseTexture(texture);
    230 
    231   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    232   ASSERT_EQ(PP_ERROR_ABORTED, image_release_callback.result());
    233 
    234   // Reset
    235   glSetCurrentContextPPAPI(0);
    236 
    237   PASS();
    238 }
    239 
    240 std::string TestCompositor::TestReleaseWithoutCommitInternal(bool bind) {
    241   // Setup GLES2
    242   const int32_t attribs[] = {
    243     PP_GRAPHICS3DATTRIB_WIDTH, 16,
    244     PP_GRAPHICS3DATTRIB_HEIGHT, 16,
    245     PP_GRAPHICS3DATTRIB_NONE
    246   };
    247   pp::Graphics3D graphics_3d(instance_, attribs);
    248   ASSERT_FALSE(graphics_3d.is_null());
    249   glSetCurrentContextPPAPI(graphics_3d.pp_resource());
    250 
    251   pp::Compositor compositor = pp::Compositor(instance_);
    252   ASSERT_FALSE(compositor.is_null());
    253 
    254   // Bind the compositor to the instance
    255   if (bind)
    256     ASSERT_TRUE(instance_->BindGraphics(compositor));
    257 
    258   pp::CompositorLayer color_layer = compositor.AddLayer();
    259   ASSERT_FALSE(color_layer.is_null());
    260 
    261   VERIFY(SetColorLayer(color_layer, PP_OK));
    262 
    263   uint32_t texture = 0;
    264   VERIFY(CreateTexture(&texture));
    265   pp::CompositorLayer texture_layer = compositor.AddLayer();
    266   ASSERT_FALSE(texture_layer.is_null());
    267   TestCompletionCallback texture_release_callback(instance_->pp_instance(),
    268                                                   PP_REQUIRED);
    269   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    270             texture_layer.SetTexture(graphics_3d, GL_TEXTURE_2D, texture,
    271                                      pp::Size(100, 100),
    272                                      texture_release_callback.GetCallback()));
    273 
    274   pp::ImageData image;
    275   VERIFY(CreateImage(&image));
    276   pp::CompositorLayer image_layer = compositor.AddLayer();
    277   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    278                                                 PP_REQUIRED);
    279   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    280             image_layer.SetImage(image, pp::Size(100, 100),
    281                                  image_release_callback.GetCallback()));
    282 
    283   // Release the compositor, and then release_callback will be aborted.
    284   compositor = pp::Compositor();
    285 
    286   // All release_callbacks should be called.
    287   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    288   ASSERT_EQ(PP_ERROR_ABORTED, texture_release_callback.result());
    289   ReleaseTexture(texture);
    290 
    291   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    292   ASSERT_EQ(PP_ERROR_ABORTED, image_release_callback.result());
    293 
    294   // The layer associated to the compositor will become invalidated.
    295   VERIFY(SetColorLayer(color_layer, PP_ERROR_BADRESOURCE));
    296 
    297   // Reset
    298   glSetCurrentContextPPAPI(0);
    299 
    300   PASS();
    301 }
    302 
    303 std::string TestCompositor::TestCommitTwoTimesWithoutChangeInternal(bool bind) {
    304   pp::Compositor compositor(instance_);
    305   ASSERT_FALSE(compositor.is_null());
    306   if (bind)
    307     ASSERT_TRUE(instance_->BindGraphics(compositor));
    308   pp::CompositorLayer layer = compositor.AddLayer();
    309   ASSERT_FALSE(layer.is_null());
    310   VERIFY(SetColorLayer(layer, PP_OK));
    311 
    312   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    313   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    314   CHECK_CALLBACK_BEHAVIOR(callback);
    315   ASSERT_EQ(PP_OK, callback.result());
    316 
    317   // CommitLayers() without any change.
    318   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    319   CHECK_CALLBACK_BEHAVIOR(callback);
    320   ASSERT_EQ(PP_OK, callback.result());
    321 
    322   PASS();
    323 }
    324 
    325 std::string TestCompositor::TestGeneralInternal(bool bind) {
    326   // Setup GLES2
    327   const int32_t attribs[] = {
    328     PP_GRAPHICS3DATTRIB_WIDTH, 16,
    329     PP_GRAPHICS3DATTRIB_HEIGHT, 16,
    330     PP_GRAPHICS3DATTRIB_NONE
    331   };
    332   pp::Graphics3D graphics_3d(instance_, attribs);
    333   ASSERT_FALSE(graphics_3d.is_null());
    334   glSetCurrentContextPPAPI(graphics_3d.pp_resource());
    335 
    336   // All functions should work with a bound compositor
    337   pp::Compositor compositor(instance_);
    338   ASSERT_FALSE(compositor.is_null());
    339   if (bind)
    340     ASSERT_TRUE(instance_->BindGraphics(compositor));
    341 
    342   pp::CompositorLayer color_layer = compositor.AddLayer();
    343   ASSERT_FALSE(color_layer.is_null());
    344   VERIFY(SetColorLayer(color_layer, PP_OK));
    345 
    346   uint32_t texture = 0;
    347   VERIFY(CreateTexture(&texture));
    348   pp::CompositorLayer texture_layer = compositor.AddLayer();
    349   ASSERT_FALSE(texture_layer.is_null());
    350   TestCompletionCallback texture_release_callback(instance_->pp_instance(),
    351                                                   PP_REQUIRED);
    352   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    353             texture_layer.SetTexture(graphics_3d, texture, GL_TEXTURE_2D,
    354                                      pp::Size(100, 100),
    355                                      texture_release_callback.GetCallback()));
    356 
    357   pp::ImageData image;
    358   VERIFY(CreateImage(&image));
    359   pp::CompositorLayer image_layer = compositor.AddLayer();
    360   TestCompletionCallback image_release_callback(instance_->pp_instance(),
    361                                                 PP_REQUIRED);
    362   ASSERT_EQ(PP_OK_COMPLETIONPENDING,
    363             image_layer.SetImage(image, pp::Size(100, 100),
    364                                  image_release_callback.GetCallback()));
    365 
    366   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
    367   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    368   CHECK_CALLBACK_BEHAVIOR(callback);
    369   ASSERT_EQ(PP_OK, callback.result());
    370 
    371   // After ResetLayers(), all layers should be invalidated.
    372   ASSERT_EQ(PP_OK, compositor.ResetLayers());
    373   VERIFY(SetColorLayer(color_layer, PP_ERROR_BADRESOURCE));
    374 
    375   // Commit empty layer stack to the chromium compositor, and then the texture
    376   // and the image will be released by the chromium compositor soon.
    377   callback.WaitForResult(compositor.CommitLayers(callback.GetCallback()));
    378   CHECK_CALLBACK_BEHAVIOR(callback);
    379   ASSERT_EQ(PP_OK, callback.result());
    380 
    381   texture_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    382   ASSERT_EQ(PP_OK, texture_release_callback.result());
    383   ReleaseTexture(texture);
    384 
    385   image_release_callback.WaitForResult(PP_OK_COMPLETIONPENDING);
    386   ASSERT_EQ(PP_OK, image_release_callback.result());
    387 
    388   // Reset
    389   glSetCurrentContextPPAPI(0);
    390 
    391   PASS();
    392 }
    393 
    394 std::string TestCompositor::CreateTexture(uint32_t* texture) {
    395   glGenTextures(1, texture);
    396   ASSERT_NE(0, *texture);
    397   glBindTexture(GL_TEXTURE_2D, *texture);
    398   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 400, 400, 0,
    399                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    400   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    401   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    402   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    403   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    404   glBindTexture(GL_TEXTURE_2D, 0);
    405 
    406   return std::string();
    407 }
    408 
    409 std::string TestCompositor::ReleaseTexture(uint32_t texture) {
    410   ASSERT_NE(0u, texture);
    411   glDeleteTextures(1, &texture);
    412 
    413   return std::string();
    414 }
    415 
    416 std::string TestCompositor::CreateImage(pp::ImageData* image) {
    417   *image = pp::ImageData(instance_, PP_IMAGEDATAFORMAT_RGBA_PREMUL,
    418                          pp::Size(400, 400), false);
    419   ASSERT_FALSE(image->is_null());
    420 
    421   return std::string();
    422 }
    423 
    424 std::string TestCompositor::SetColorLayer(
    425     pp::CompositorLayer layer, int32_t result) {
    426   ASSERT_EQ(result, layer.SetColor(255, 255, 255, 255, pp::Size(100, 100)));
    427   ASSERT_EQ(result, layer.SetClipRect(pp::Rect(0, 0, 50, 50)));
    428   ASSERT_EQ(result, layer.SetTransform(kMatrix));
    429   ASSERT_EQ(result, layer.SetOpacity(128));
    430 
    431   return std::string();
    432 }
    433 
    434 
    435