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.
5 #include "ppapi/tests/test_compositor.h"
8 #include <GLES2/gl2ext.h>
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"
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
,
33 REGISTER_TEST_CASE(Compositor
);
35 #define VERIFY(r) do { \
36 std::string result = (r); \
41 bool TestCompositor::Init() {
42 if (!CheckTestingInterface())
45 if (!glInitializePPAPI(pp::Module::Get()->get_browser_interface()))
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
);
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
);
62 RUN_CALLBACK_TEST(TestCompositor
, BindUnbind
, filter
);
65 std::string
TestCompositor::TestRelease() {
66 return TestReleaseInternal(true);
69 std::string
TestCompositor::TestReleaseWithoutCommit() {
70 return TestReleaseWithoutCommitInternal(true);
73 std::string
TestCompositor::TestCommitTwoTimesWithoutChange() {
74 return TestCommitTwoTimesWithoutChangeInternal(true);
77 std::string
TestCompositor::TestGeneral() {
78 return TestGeneralInternal(true);
81 std::string
TestCompositor::TestReleaseUnbound() {
82 return TestReleaseInternal(false);
85 std::string
TestCompositor::TestReleaseWithoutCommitUnbound() {
86 return TestReleaseWithoutCommitInternal(false);
89 std::string
TestCompositor::TestCommitTwoTimesWithoutChangeUnbound() {
90 return TestCommitTwoTimesWithoutChangeInternal(false);
93 std::string
TestCompositor::TestGeneralUnbound() {
94 return TestGeneralInternal(false);
97 // TODO(penghuang): refactor common part in all tests to a member function.
98 std::string
TestCompositor::TestBindUnbind() {
100 const int32_t attribs
[] = {
101 PP_GRAPHICS3DATTRIB_WIDTH
, 16,
102 PP_GRAPHICS3DATTRIB_HEIGHT
, 16,
103 PP_GRAPHICS3DATTRIB_NONE
105 pp::Graphics3D
graphics_3d(instance_
, attribs
);
106 ASSERT_FALSE(graphics_3d
.is_null());
107 glSetCurrentContextPPAPI(graphics_3d
.pp_resource());
109 pp::Compositor compositor
= pp::Compositor(instance_
);
110 ASSERT_FALSE(compositor
.is_null());
112 // Add layers on an unbound compositor.
113 pp::CompositorLayer color_layer
= compositor
.AddLayer();
114 ASSERT_FALSE(color_layer
.is_null());
116 VERIFY(SetColorLayer(color_layer
, PP_OK
));
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(),
124 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
125 texture_layer
.SetTexture(graphics_3d
, GL_TEXTURE_2D
, texture
,
127 texture_release_callback
.GetCallback()));
130 VERIFY(CreateImage(&image
));
131 pp::CompositorLayer image_layer
= compositor
.AddLayer();
132 TestCompletionCallback
image_release_callback(instance_
->pp_instance(),
134 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
135 image_layer
.SetImage(image
, pp::Size(100, 100),
136 image_release_callback
.GetCallback()));
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());
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());
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());
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());
162 texture_release_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
163 ASSERT_EQ(PP_OK
, texture_release_callback
.result());
164 ReleaseTexture(texture
);
166 image_release_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
167 ASSERT_EQ(PP_OK
, image_release_callback
.result());
170 glSetCurrentContextPPAPI(0);
175 std::string
TestCompositor::TestReleaseInternal(bool bind
) {
177 const int32_t attribs
[] = {
178 PP_GRAPHICS3DATTRIB_WIDTH
, 16,
179 PP_GRAPHICS3DATTRIB_HEIGHT
, 16,
180 PP_GRAPHICS3DATTRIB_NONE
182 pp::Graphics3D
graphics_3d(instance_
, attribs
);
183 ASSERT_FALSE(graphics_3d
.is_null());
184 glSetCurrentContextPPAPI(graphics_3d
.pp_resource());
186 pp::Compositor compositor
= pp::Compositor(instance_
);
187 ASSERT_FALSE(compositor
.is_null());
189 // Bind the compositor to the instance
191 ASSERT_TRUE(instance_
->BindGraphics(compositor
));
193 pp::CompositorLayer color_layer
= compositor
.AddLayer();
194 ASSERT_FALSE(color_layer
.is_null());
196 VERIFY(SetColorLayer(color_layer
, PP_OK
));
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(),
204 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
205 texture_layer
.SetTexture(graphics_3d
, GL_TEXTURE_2D
, texture
,
207 texture_release_callback
.GetCallback()));
210 VERIFY(CreateImage(&image
));
211 pp::CompositorLayer image_layer
= compositor
.AddLayer();
212 TestCompletionCallback
image_release_callback(instance_
->pp_instance(),
214 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
215 image_layer
.SetImage(image
, pp::Size(100, 100),
216 image_release_callback
.GetCallback()));
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());
224 // Release the compositor, and then release_callback will be aborted.
225 compositor
= pp::Compositor();
227 texture_release_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
228 ASSERT_EQ(PP_ERROR_ABORTED
, texture_release_callback
.result());
229 ReleaseTexture(texture
);
231 image_release_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
232 ASSERT_EQ(PP_ERROR_ABORTED
, image_release_callback
.result());
235 glSetCurrentContextPPAPI(0);
240 std::string
TestCompositor::TestReleaseWithoutCommitInternal(bool bind
) {
242 const int32_t attribs
[] = {
243 PP_GRAPHICS3DATTRIB_WIDTH
, 16,
244 PP_GRAPHICS3DATTRIB_HEIGHT
, 16,
245 PP_GRAPHICS3DATTRIB_NONE
247 pp::Graphics3D
graphics_3d(instance_
, attribs
);
248 ASSERT_FALSE(graphics_3d
.is_null());
249 glSetCurrentContextPPAPI(graphics_3d
.pp_resource());
251 pp::Compositor compositor
= pp::Compositor(instance_
);
252 ASSERT_FALSE(compositor
.is_null());
254 // Bind the compositor to the instance
256 ASSERT_TRUE(instance_
->BindGraphics(compositor
));
258 pp::CompositorLayer color_layer
= compositor
.AddLayer();
259 ASSERT_FALSE(color_layer
.is_null());
261 VERIFY(SetColorLayer(color_layer
, PP_OK
));
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(),
269 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
270 texture_layer
.SetTexture(graphics_3d
, GL_TEXTURE_2D
, texture
,
272 texture_release_callback
.GetCallback()));
275 VERIFY(CreateImage(&image
));
276 pp::CompositorLayer image_layer
= compositor
.AddLayer();
277 TestCompletionCallback
image_release_callback(instance_
->pp_instance(),
279 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
280 image_layer
.SetImage(image
, pp::Size(100, 100),
281 image_release_callback
.GetCallback()));
283 // Release the compositor, and then release_callback will be aborted.
284 compositor
= pp::Compositor();
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
);
291 image_release_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
292 ASSERT_EQ(PP_ERROR_ABORTED
, image_release_callback
.result());
294 // The layer associated to the compositor will become invalidated.
295 VERIFY(SetColorLayer(color_layer
, PP_ERROR_BADRESOURCE
));
298 glSetCurrentContextPPAPI(0);
303 std::string
TestCompositor::TestCommitTwoTimesWithoutChangeInternal(bool bind
) {
304 pp::Compositor
compositor(instance_
);
305 ASSERT_FALSE(compositor
.is_null());
307 ASSERT_TRUE(instance_
->BindGraphics(compositor
));
308 pp::CompositorLayer layer
= compositor
.AddLayer();
309 ASSERT_FALSE(layer
.is_null());
310 VERIFY(SetColorLayer(layer
, PP_OK
));
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());
317 // CommitLayers() without any change.
318 callback
.WaitForResult(compositor
.CommitLayers(callback
.GetCallback()));
319 CHECK_CALLBACK_BEHAVIOR(callback
);
320 ASSERT_EQ(PP_OK
, callback
.result());
325 std::string
TestCompositor::TestGeneralInternal(bool bind
) {
327 const int32_t attribs
[] = {
328 PP_GRAPHICS3DATTRIB_WIDTH
, 16,
329 PP_GRAPHICS3DATTRIB_HEIGHT
, 16,
330 PP_GRAPHICS3DATTRIB_NONE
332 pp::Graphics3D
graphics_3d(instance_
, attribs
);
333 ASSERT_FALSE(graphics_3d
.is_null());
334 glSetCurrentContextPPAPI(graphics_3d
.pp_resource());
336 // All functions should work with a bound compositor
337 pp::Compositor
compositor(instance_
);
338 ASSERT_FALSE(compositor
.is_null());
340 ASSERT_TRUE(instance_
->BindGraphics(compositor
));
342 pp::CompositorLayer color_layer
= compositor
.AddLayer();
343 ASSERT_FALSE(color_layer
.is_null());
344 VERIFY(SetColorLayer(color_layer
, PP_OK
));
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(),
352 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
353 texture_layer
.SetTexture(graphics_3d
, texture
, GL_TEXTURE_2D
,
355 texture_release_callback
.GetCallback()));
358 VERIFY(CreateImage(&image
));
359 pp::CompositorLayer image_layer
= compositor
.AddLayer();
360 TestCompletionCallback
image_release_callback(instance_
->pp_instance(),
362 ASSERT_EQ(PP_OK_COMPLETIONPENDING
,
363 image_layer
.SetImage(image
, pp::Size(100, 100),
364 image_release_callback
.GetCallback()));
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());
371 // After ResetLayers(), all layers should be invalidated.
372 ASSERT_EQ(PP_OK
, compositor
.ResetLayers());
373 VERIFY(SetColorLayer(color_layer
, PP_ERROR_BADRESOURCE
));
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());
381 texture_release_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
382 ASSERT_EQ(PP_OK
, texture_release_callback
.result());
383 ReleaseTexture(texture
);
385 image_release_callback
.WaitForResult(PP_OK_COMPLETIONPENDING
);
386 ASSERT_EQ(PP_OK
, image_release_callback
.result());
389 glSetCurrentContextPPAPI(0);
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);
406 return std::string();
409 std::string
TestCompositor::ReleaseTexture(uint32_t texture
) {
410 ASSERT_NE(0u, texture
);
411 glDeleteTextures(1, &texture
);
413 return std::string();
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());
421 return std::string();
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));
431 return std::string();