• 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, 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 
TestReleaseInternal(bool bind)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 
TestReleaseWithoutCommitInternal(bool bind)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 
TestCommitTwoTimesWithoutChangeInternal(bool bind)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 
TestGeneralInternal(bool bind)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 
CreateTexture(uint32_t * texture)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 
ReleaseTexture(uint32_t texture)409 std::string TestCompositor::ReleaseTexture(uint32_t texture) {
410   ASSERT_NE(0u, texture);
411   glDeleteTextures(1, &texture);
412 
413   return std::string();
414 }
415 
CreateImage(pp::ImageData * image)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 
SetColorLayer(pp::CompositorLayer layer,int32_t result)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