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