• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Init()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 
RunTests(const std::string & filter)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 
TestRelease()65 std::string TestCompositor::TestRelease() {
66   return TestReleaseInternal(true);
67 }
68 
TestReleaseWithoutCommit()69 std::string TestCompositor::TestReleaseWithoutCommit() {
70   return TestReleaseWithoutCommitInternal(true);
71 }
72 
TestCommitTwoTimesWithoutChange()73 std::string TestCompositor::TestCommitTwoTimesWithoutChange() {
74   return TestCommitTwoTimesWithoutChangeInternal(true);
75 }
76 
TestGeneral()77 std::string TestCompositor::TestGeneral() {
78   return TestGeneralInternal(true);
79 }
80 
TestReleaseUnbound()81 std::string TestCompositor::TestReleaseUnbound() {
82   return TestReleaseInternal(false);
83 }
84 
TestReleaseWithoutCommitUnbound()85 std::string TestCompositor::TestReleaseWithoutCommitUnbound() {
86   return TestReleaseWithoutCommitInternal(false);
87 }
88 
TestCommitTwoTimesWithoutChangeUnbound()89 std::string TestCompositor::TestCommitTwoTimesWithoutChangeUnbound() {
90   return TestCommitTwoTimesWithoutChangeInternal(false);
91 }
92 
TestGeneralUnbound()93 std::string TestCompositor::TestGeneralUnbound() {
94   return TestGeneralInternal(false);
95 }
96 
97 // TODO(penghuang): refactor common part in all tests to a member function.
TestBindUnbind()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 
TestReleaseInternal(bool bind)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 
TestReleaseWithoutCommitInternal(bool bind)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 
TestCommitTwoTimesWithoutChangeInternal(bool bind)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 
TestGeneralInternal(bool bind)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 
CreateTexture(uint32_t * texture)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 
ReleaseTexture(uint32_t texture)405 std::string TestCompositor::ReleaseTexture(uint32_t texture) {
406   ASSERT_NE(0u, texture);
407   glDeleteTextures(1, &texture);
408 
409   return std::string();
410 }
411 
CreateImage(pp::ImageData * image)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 
SetColorLayer(pp::CompositorLayer layer,int32_t result)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