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