OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" | 8 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" |
9 #include "gpu/command_buffer/service/gpu_service_test.h" | 9 #include "gpu/command_buffer/service/gpu_service_test.h" |
10 #include "gpu/command_buffer/service/gpu_tracer.h" | 10 #include "gpu/command_buffer/service/gpu_tracer.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 } | 79 } |
80 return new MockOutputter(); | 80 return new MockOutputter(); |
81 } | 81 } |
82 | 82 |
83 unsigned char tracing_enabled_; | 83 unsigned char tracing_enabled_; |
84 scoped_refptr<Outputter> set_outputter_; | 84 scoped_refptr<Outputter> set_outputter_; |
85 }; | 85 }; |
86 | 86 |
87 class BaseGpuTest : public GpuServiceTest { | 87 class BaseGpuTest : public GpuServiceTest { |
88 public: | 88 public: |
89 explicit BaseGpuTest(gfx::GPUTiming::TimerType test_timer_type) | 89 explicit BaseGpuTest(gl::GPUTiming::TimerType test_timer_type) |
90 : test_timer_type_(test_timer_type) { | 90 : test_timer_type_(test_timer_type) {} |
91 } | |
92 | 91 |
93 protected: | 92 protected: |
94 void SetUp() override { | 93 void SetUp() override { |
95 g_fakeCPUTime = 0; | 94 g_fakeCPUTime = 0; |
96 const char* gl_version = "3.2"; | 95 const char* gl_version = "3.2"; |
97 const char* extensions = ""; | 96 const char* extensions = ""; |
98 if (GetTimerType() == gfx::GPUTiming::kTimerTypeEXT) { | 97 if (GetTimerType() == gl::GPUTiming::kTimerTypeEXT) { |
99 gl_version = "2.1"; | 98 gl_version = "2.1"; |
100 extensions = "GL_EXT_timer_query"; | 99 extensions = "GL_EXT_timer_query"; |
101 } else if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) { | 100 } else if (GetTimerType() == gl::GPUTiming::kTimerTypeDisjoint) { |
102 gl_version = "opengl es 3.0"; | 101 gl_version = "opengl es 3.0"; |
103 extensions = "GL_EXT_disjoint_timer_query"; | 102 extensions = "GL_EXT_disjoint_timer_query"; |
104 } else if (GetTimerType() == gfx::GPUTiming::kTimerTypeARB) { | 103 } else if (GetTimerType() == gl::GPUTiming::kTimerTypeARB) { |
105 // TODO(sievers): The tracer should not depend on ARB_occlusion_query. | 104 // TODO(sievers): The tracer should not depend on ARB_occlusion_query. |
106 // Try merge Query APIs (core, ARB, EXT) into a single binding each. | 105 // Try merge Query APIs (core, ARB, EXT) into a single binding each. |
107 extensions = "GL_ARB_timer_query GL_ARB_occlusion_query"; | 106 extensions = "GL_ARB_timer_query GL_ARB_occlusion_query"; |
108 } | 107 } |
109 GpuServiceTest::SetUpWithGLVersion(gl_version, extensions); | 108 GpuServiceTest::SetUpWithGLVersion(gl_version, extensions); |
110 | 109 |
111 // Disjoint check should only be called by kTracerTypeDisjointTimer type. | 110 // Disjoint check should only be called by kTracerTypeDisjointTimer type. |
112 if (GetTimerType() == gfx::GPUTiming::kTimerTypeDisjoint) | 111 if (GetTimerType() == gl::GPUTiming::kTimerTypeDisjoint) |
113 gl_fake_queries_.ExpectDisjointCalls(*gl_); | 112 gl_fake_queries_.ExpectDisjointCalls(*gl_); |
114 else | 113 else |
115 gl_fake_queries_.ExpectNoDisjointCalls(*gl_); | 114 gl_fake_queries_.ExpectNoDisjointCalls(*gl_); |
116 | 115 |
117 gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient(); | 116 gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient(); |
118 gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime)); | 117 gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime)); |
119 gl_fake_queries_.Reset(); | 118 gl_fake_queries_.Reset(); |
120 | 119 |
121 outputter_ref_ = new MockOutputter(); | 120 outputter_ref_ = new MockOutputter(); |
122 } | 121 } |
123 | 122 |
124 void TearDown() override { | 123 void TearDown() override { |
125 outputter_ref_ = NULL; | 124 outputter_ref_ = NULL; |
126 gpu_timing_client_ = NULL; | 125 gpu_timing_client_ = NULL; |
127 | 126 |
128 gl_fake_queries_.Reset(); | 127 gl_fake_queries_.Reset(); |
129 GpuServiceTest::TearDown(); | 128 GpuServiceTest::TearDown(); |
130 } | 129 } |
131 | 130 |
132 void ExpectTraceQueryMocks() { | 131 void ExpectTraceQueryMocks() { |
133 if (gpu_timing_client_->IsAvailable()) { | 132 if (gpu_timing_client_->IsAvailable()) { |
134 // Delegate query APIs used by GPUTrace to a GlFakeQueries | 133 // Delegate query APIs used by GPUTrace to a GlFakeQueries |
135 const bool elapsed = (GetTimerType() == gfx::GPUTiming::kTimerTypeEXT); | 134 const bool elapsed = (GetTimerType() == gl::GPUTiming::kTimerTypeEXT); |
136 gl_fake_queries_.ExpectGPUTimerQuery(*gl_, elapsed); | 135 gl_fake_queries_.ExpectGPUTimerQuery(*gl_, elapsed); |
137 } | 136 } |
138 } | 137 } |
139 | 138 |
140 void ExpectOutputterBeginMocks(MockOutputter* outputter, | 139 void ExpectOutputterBeginMocks(MockOutputter* outputter, |
141 GpuTracerSource source, | 140 GpuTracerSource source, |
142 const std::string& category, | 141 const std::string& category, |
143 const std::string& name) { | 142 const std::string& name) { |
144 EXPECT_CALL(*outputter, | 143 EXPECT_CALL(*outputter, |
145 TraceServiceBegin(source, category, name)); | 144 TraceServiceBegin(source, category, name)); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 if (tracing_service) | 195 if (tracing_service) |
197 ExpectOutputterBeginMocks(outputter, source, category, name); | 196 ExpectOutputterBeginMocks(outputter, source, category, name); |
198 const bool valid_timer = tracing_device && | 197 const bool valid_timer = tracing_device && |
199 gpu_timing_client_->IsAvailable(); | 198 gpu_timing_client_->IsAvailable(); |
200 ExpectOutputterEndMocks(outputter, source, category, name, | 199 ExpectOutputterEndMocks(outputter, source, category, name, |
201 expect_start_time, expect_end_time, | 200 expect_start_time, expect_end_time, |
202 tracing_service, valid_timer); | 201 tracing_service, valid_timer); |
203 } | 202 } |
204 | 203 |
205 void ExpectTracerOffsetQueryMocks() { | 204 void ExpectTracerOffsetQueryMocks() { |
206 if (GetTimerType() != gfx::GPUTiming::kTimerTypeARB) { | 205 if (GetTimerType() != gl::GPUTiming::kTimerTypeARB) { |
207 gl_fake_queries_.ExpectNoOffsetCalculationQuery(*gl_); | 206 gl_fake_queries_.ExpectNoOffsetCalculationQuery(*gl_); |
208 } else { | 207 } else { |
209 gl_fake_queries_.ExpectOffsetCalculationQuery(*gl_); | 208 gl_fake_queries_.ExpectOffsetCalculationQuery(*gl_); |
210 } | 209 } |
211 } | 210 } |
212 | 211 |
213 gfx::GPUTiming::TimerType GetTimerType() { return test_timer_type_; } | 212 gl::GPUTiming::TimerType GetTimerType() { return test_timer_type_; } |
214 | 213 |
215 gfx::GPUTiming::TimerType test_timer_type_; | 214 gl::GPUTiming::TimerType test_timer_type_; |
216 gfx::GPUTimingFake gl_fake_queries_; | 215 gl::GPUTimingFake gl_fake_queries_; |
217 | 216 |
218 scoped_refptr<gfx::GPUTimingClient> gpu_timing_client_; | 217 scoped_refptr<gl::GPUTimingClient> gpu_timing_client_; |
219 scoped_refptr<MockOutputter> outputter_ref_; | 218 scoped_refptr<MockOutputter> outputter_ref_; |
220 }; | 219 }; |
221 | 220 |
222 // Test GPUTrace calls all the correct gl calls. | 221 // Test GPUTrace calls all the correct gl calls. |
223 class BaseGpuTraceTest : public BaseGpuTest { | 222 class BaseGpuTraceTest : public BaseGpuTest { |
224 public: | 223 public: |
225 explicit BaseGpuTraceTest(gfx::GPUTiming::TimerType test_timer_type) | 224 explicit BaseGpuTraceTest(gl::GPUTiming::TimerType test_timer_type) |
226 : BaseGpuTest(test_timer_type) {} | 225 : BaseGpuTest(test_timer_type) {} |
227 | 226 |
228 void DoTraceTest(bool tracing_service, bool tracing_device) { | 227 void DoTraceTest(bool tracing_service, bool tracing_device) { |
229 // Expected results | 228 // Expected results |
230 const GpuTracerSource tracer_source = kTraceCHROMIUM; | 229 const GpuTracerSource tracer_source = kTraceCHROMIUM; |
231 const std::string category_name("trace_category"); | 230 const std::string category_name("trace_category"); |
232 const std::string trace_name("trace_test"); | 231 const std::string trace_name("trace_test"); |
233 const int64_t offset_time = 3231; | 232 const int64_t offset_time = 3231; |
234 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond; | 233 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond; |
235 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond; | 234 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 | 278 |
280 // Destroy trace after we are done. | 279 // Destroy trace after we are done. |
281 trace->Destroy(true); | 280 trace->Destroy(true); |
282 | 281 |
283 outputter_ref_ = NULL; | 282 outputter_ref_ = NULL; |
284 } | 283 } |
285 }; | 284 }; |
286 | 285 |
287 class GpuARBTimerTraceTest : public BaseGpuTraceTest { | 286 class GpuARBTimerTraceTest : public BaseGpuTraceTest { |
288 public: | 287 public: |
289 GpuARBTimerTraceTest() : BaseGpuTraceTest(gfx::GPUTiming::kTimerTypeARB) {} | 288 GpuARBTimerTraceTest() : BaseGpuTraceTest(gl::GPUTiming::kTimerTypeARB) {} |
290 }; | 289 }; |
291 | 290 |
292 class GpuDisjointTimerTraceTest : public BaseGpuTraceTest { | 291 class GpuDisjointTimerTraceTest : public BaseGpuTraceTest { |
293 public: | 292 public: |
294 GpuDisjointTimerTraceTest() | 293 GpuDisjointTimerTraceTest() |
295 : BaseGpuTraceTest(gfx::GPUTiming::kTimerTypeDisjoint) {} | 294 : BaseGpuTraceTest(gl::GPUTiming::kTimerTypeDisjoint) {} |
296 }; | 295 }; |
297 | 296 |
298 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestOff) { | 297 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestOff) { |
299 DoTraceTest(false, false); | 298 DoTraceTest(false, false); |
300 } | 299 } |
301 | 300 |
302 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestServiceOnly) { | 301 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestServiceOnly) { |
303 DoTraceTest(true, false); | 302 DoTraceTest(true, false); |
304 } | 303 } |
305 | 304 |
(...skipping 17 matching lines...) Expand all Loading... |
323 DoTraceTest(false, true); | 322 DoTraceTest(false, true); |
324 } | 323 } |
325 | 324 |
326 TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestBothOn) { | 325 TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestBothOn) { |
327 DoTraceTest(true, true); | 326 DoTraceTest(true, true); |
328 } | 327 } |
329 | 328 |
330 // Test GPUTracer calls all the correct gl calls. | 329 // Test GPUTracer calls all the correct gl calls. |
331 class BaseGpuTracerTest : public BaseGpuTest { | 330 class BaseGpuTracerTest : public BaseGpuTest { |
332 public: | 331 public: |
333 explicit BaseGpuTracerTest(gfx::GPUTiming::TimerType test_timer_type) | 332 explicit BaseGpuTracerTest(gl::GPUTiming::TimerType test_timer_type) |
334 : BaseGpuTest(test_timer_type) {} | 333 : BaseGpuTest(test_timer_type) {} |
335 | 334 |
336 void DoBasicTracerTest() { | 335 void DoBasicTracerTest() { |
337 ExpectTracerOffsetQueryMocks(); | 336 ExpectTracerOffsetQueryMocks(); |
338 | 337 |
339 MockGLES2Decoder decoder; | 338 MockGLES2Decoder decoder; |
340 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); | 339 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext())); |
341 GPUTracerTester tracer(&decoder); | 340 GPUTracerTester tracer(&decoder); |
342 tracer.SetTracingEnabled(true); | 341 tracer.SetTracingEnabled(true); |
343 | 342 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 | 548 |
550 ExpectOutputterBeginMocks(outputter_ref_.get(), source, | 549 ExpectOutputterBeginMocks(outputter_ref_.get(), source, |
551 category_name, trace_name); | 550 category_name, trace_name); |
552 ASSERT_TRUE(tracer.Begin(category_name, trace_name, source)); | 551 ASSERT_TRUE(tracer.Begin(category_name, trace_name, source)); |
553 | 552 |
554 gl_fake_queries_.SetCurrentGLTime(end_timestamp); | 553 gl_fake_queries_.SetCurrentGLTime(end_timestamp); |
555 g_fakeCPUTime = expect_end_time; | 554 g_fakeCPUTime = expect_end_time; |
556 | 555 |
557 // Create GPUTimingClient to make sure disjoint value is correct. This | 556 // Create GPUTimingClient to make sure disjoint value is correct. This |
558 // should not interfere with the tracer's disjoint value. | 557 // should not interfere with the tracer's disjoint value. |
559 scoped_refptr<gfx::GPUTimingClient> disjoint_client = | 558 scoped_refptr<gl::GPUTimingClient> disjoint_client = |
560 GetGLContext()->CreateGPUTimingClient(); | 559 GetGLContext()->CreateGPUTimingClient(); |
561 | 560 |
562 // We assert here based on the disjoint_client because if disjoints are not | 561 // We assert here based on the disjoint_client because if disjoints are not |
563 // working properly there is no point testing the tracer output. | 562 // working properly there is no point testing the tracer output. |
564 ASSERT_FALSE(disjoint_client->CheckAndResetTimerErrors()); | 563 ASSERT_FALSE(disjoint_client->CheckAndResetTimerErrors()); |
565 gl_fake_queries_.SetDisjoint(); | 564 gl_fake_queries_.SetDisjoint(); |
566 ASSERT_TRUE(disjoint_client->CheckAndResetTimerErrors()); | 565 ASSERT_TRUE(disjoint_client->CheckAndResetTimerErrors()); |
567 | 566 |
568 ExpectDisjointOutputMocks(outputter_ref_.get(), | 567 ExpectDisjointOutputMocks(outputter_ref_.get(), |
569 expect_start_time, expect_end_time); | 568 expect_start_time, expect_end_time); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 | 630 |
632 ASSERT_TRUE(tracer.End(source)); | 631 ASSERT_TRUE(tracer.End(source)); |
633 ASSERT_TRUE(tracer.EndDecoding()); | 632 ASSERT_TRUE(tracer.EndDecoding()); |
634 tracer.ProcessTraces(); | 633 tracer.ProcessTraces(); |
635 } | 634 } |
636 }; | 635 }; |
637 | 636 |
638 class InvalidTimerTracerTest : public BaseGpuTracerTest { | 637 class InvalidTimerTracerTest : public BaseGpuTracerTest { |
639 public: | 638 public: |
640 InvalidTimerTracerTest() | 639 InvalidTimerTracerTest() |
641 : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeInvalid) {} | 640 : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeInvalid) {} |
642 }; | 641 }; |
643 | 642 |
644 class GpuEXTTimerTracerTest : public BaseGpuTracerTest { | 643 class GpuEXTTimerTracerTest : public BaseGpuTracerTest { |
645 public: | 644 public: |
646 GpuEXTTimerTracerTest() : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeEXT) {} | 645 GpuEXTTimerTracerTest() : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeEXT) {} |
647 }; | 646 }; |
648 | 647 |
649 class GpuARBTimerTracerTest : public BaseGpuTracerTest { | 648 class GpuARBTimerTracerTest : public BaseGpuTracerTest { |
650 public: | 649 public: |
651 GpuARBTimerTracerTest() | 650 GpuARBTimerTracerTest() : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeARB) {} |
652 : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeARB) {} | |
653 }; | 651 }; |
654 | 652 |
655 class GpuDisjointTimerTracerTest : public BaseGpuTracerTest { | 653 class GpuDisjointTimerTracerTest : public BaseGpuTracerTest { |
656 public: | 654 public: |
657 GpuDisjointTimerTracerTest() | 655 GpuDisjointTimerTracerTest() |
658 : BaseGpuTracerTest(gfx::GPUTiming::kTimerTypeDisjoint) {} | 656 : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeDisjoint) {} |
659 }; | 657 }; |
660 | 658 |
661 TEST_F(InvalidTimerTracerTest, InvalidTimerBasicTracerTest) { | 659 TEST_F(InvalidTimerTracerTest, InvalidTimerBasicTracerTest) { |
662 DoBasicTracerTest(); | 660 DoBasicTracerTest(); |
663 } | 661 } |
664 | 662 |
665 TEST_F(GpuEXTTimerTracerTest, EXTTimerBasicTracerTest) { | 663 TEST_F(GpuEXTTimerTracerTest, EXTTimerBasicTracerTest) { |
666 DoBasicTracerTest(); | 664 DoBasicTracerTest(); |
667 } | 665 } |
668 | 666 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 EXPECT_FALSE( | 769 EXPECT_FALSE( |
772 tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM)); | 770 tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM)); |
773 | 771 |
774 ASSERT_TRUE(tracer_tester_->BeginDecoding()); | 772 ASSERT_TRUE(tracer_tester_->BeginDecoding()); |
775 EXPECT_TRUE( | 773 EXPECT_TRUE( |
776 tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM)); | 774 tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM)); |
777 ASSERT_TRUE(tracer_tester_->EndDecoding()); | 775 ASSERT_TRUE(tracer_tester_->EndDecoding()); |
778 } | 776 } |
779 | 777 |
780 TEST_F(GpuDisjointTimerTracerTest, MultipleClientsDisjointTest) { | 778 TEST_F(GpuDisjointTimerTracerTest, MultipleClientsDisjointTest) { |
781 scoped_refptr<gfx::GPUTimingClient> client1 = | 779 scoped_refptr<gl::GPUTimingClient> client1 = |
782 GetGLContext()->CreateGPUTimingClient(); | 780 GetGLContext()->CreateGPUTimingClient(); |
783 scoped_refptr<gfx::GPUTimingClient> client2 = | 781 scoped_refptr<gl::GPUTimingClient> client2 = |
784 GetGLContext()->CreateGPUTimingClient(); | 782 GetGLContext()->CreateGPUTimingClient(); |
785 | 783 |
786 // Test both clients are initialized as no errors. | 784 // Test both clients are initialized as no errors. |
787 ASSERT_FALSE(client1->CheckAndResetTimerErrors()); | 785 ASSERT_FALSE(client1->CheckAndResetTimerErrors()); |
788 ASSERT_FALSE(client2->CheckAndResetTimerErrors()); | 786 ASSERT_FALSE(client2->CheckAndResetTimerErrors()); |
789 | 787 |
790 // Issue a disjoint. | 788 // Issue a disjoint. |
791 gl_fake_queries_.SetDisjoint(); | 789 gl_fake_queries_.SetDisjoint(); |
792 | 790 |
793 ASSERT_TRUE(client1->CheckAndResetTimerErrors()); | 791 ASSERT_TRUE(client1->CheckAndResetTimerErrors()); |
794 ASSERT_TRUE(client2->CheckAndResetTimerErrors()); | 792 ASSERT_TRUE(client2->CheckAndResetTimerErrors()); |
795 | 793 |
796 // Test both are now reset. | 794 // Test both are now reset. |
797 ASSERT_FALSE(client1->CheckAndResetTimerErrors()); | 795 ASSERT_FALSE(client1->CheckAndResetTimerErrors()); |
798 ASSERT_FALSE(client2->CheckAndResetTimerErrors()); | 796 ASSERT_FALSE(client2->CheckAndResetTimerErrors()); |
799 | 797 |
800 // Issue a disjoint. | 798 // Issue a disjoint. |
801 gl_fake_queries_.SetDisjoint(); | 799 gl_fake_queries_.SetDisjoint(); |
802 | 800 |
803 // Test new client disjoint value is cleared. | 801 // Test new client disjoint value is cleared. |
804 scoped_refptr<gfx::GPUTimingClient> client3 = | 802 scoped_refptr<gl::GPUTimingClient> client3 = |
805 GetGLContext()->CreateGPUTimingClient(); | 803 GetGLContext()->CreateGPUTimingClient(); |
806 ASSERT_TRUE(client1->CheckAndResetTimerErrors()); | 804 ASSERT_TRUE(client1->CheckAndResetTimerErrors()); |
807 ASSERT_TRUE(client2->CheckAndResetTimerErrors()); | 805 ASSERT_TRUE(client2->CheckAndResetTimerErrors()); |
808 ASSERT_FALSE(client3->CheckAndResetTimerErrors()); | 806 ASSERT_FALSE(client3->CheckAndResetTimerErrors()); |
809 } | 807 } |
810 | 808 |
811 } // namespace | 809 } // namespace |
812 } // namespace gles2 | 810 } // namespace gles2 |
813 } // namespace gpu | 811 } // namespace gpu |
OLD | NEW |