Covellite++  Version: 2.3.0 Revision: ??? Platform: x64 Build: 23:13 04.01.2025
Кроссплатформенный фреймворк для разработки приложений на С++
Загрузка...
Поиск...
Не найдено
OpenGLShader.Present_test.hpp
1
2#pragma once
3#include <gmock/gmock.hpp>
4#include <alicorn/std/vector.hpp>
5#include <alicorn/std/string/encoding.hpp>
6#include <boost/algorithm/string/replace.hpp>
7
8#ifndef OpenGLShader_test
9
10class OpenGLShader_test :
11 public ::testing::Test
12{
13
14};
15
16#endif
17
18namespace
19{
20
21// ************************************************************************** //
22TEST_F(OpenGLShader_test, /*DISABLED_*/Test_Present_Index_CreateBuffer_Fail)
23{
24 using GLProxy_t = ::mock::GLProxy;
25 GLProxy_t GLProxy;
26 GLProxy_t::GetInstance() = &GLProxy;
27
28 const Tested_t Example{ Data_t{} };
29 const ITested_t & IExample = Example;
30
31 auto itCreator = IExample.GetCreators().find(uT("Present"));
32 ASSERT_NE(IExample.GetCreators().end(), itCreator);
33
34 auto TestCallRender = [&](const Component_t::ComponentPtr_t & _pComponent)
35 {
36 using namespace ::testing;
37
38 InSequence Dummy;
39
40 EXPECT_CALL(GLProxy, GenBuffers(_))
41 .Times(1);
42
43 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _))
44 .Times(AtLeast(1));
45
46 EXPECT_CALL(GLProxy, GetError())
47 .Times(1)
48 .WillOnce(Return(1908232144));
49
50 EXPECT_THROW(itCreator->second(_pComponent), ::std::exception);
51 };
52
53 const ::std::vector<int> Source;
54
55 const auto pBuffer = Component_t::Make(
56 {
57 { uT("content"), Source },
58 });
59
60 TestCallRender(pBuffer);
61
62 const auto pData = Component_t::Make(
63 {
64 { uT("kind"), uT("Buffer") },
65 { uT("content"), Source },
66 });
67
68 TestCallRender(Component_t::Make({ { uT("service"), Object_t{ pData } } }));
69}
70
71// ************************************************************************** //
72TEST_F(OpenGLShader_test, /*DISABLED_*/Test_Present_Index)
73{
74 using GLProxy_t = ::mock::GLProxy;
75 GLProxy_t GLProxy;
76 GLProxy_t::GetInstance() = &GLProxy;
77
78 const Tested_t Example{ Data_t{} };
79 const ITested_t & IExample = Example;
80
81 const ::mock::GLuint BufferId = 1908241121;
82
83 ::std::vector<int> Indices =
84 {
85 1808261927,
86 1808261928,
87 1808261929,
88 1808261930,
89 1808261931
90 };
91
92 IntroduceBufferSize(Indices);
93
94 auto itPresentCreator = IExample.GetCreators().find(uT("Present"));
95 ASSERT_NE(IExample.GetCreators().end(), itPresentCreator);
96
97 auto TestCallRender = [&](const Component_t::ComponentPtr_t & _pPresent)
98 {
99 using namespace ::testing;
100
101 InSequence Dummy;
102
103 EXPECT_CALL(GLProxy, GenBuffers(1))
104 .Times(1)
105 .WillOnce(Return(BufferId));
106
107 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferId))
108 .Times(1);
109
110 const auto Size =
111 static_cast<::mock::GLsizeiptr>(Indices.size() * sizeof(int));
112
113 EXPECT_CALL(GLProxy, BufferData(GL_ELEMENT_ARRAY_BUFFER, Size,
114 GetExpected(Indices), GL_STATIC_DRAW))
115 .Times(1);
116
117 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0))
118 .Times(1);
119
120 EXPECT_CALL(GLProxy, GetError())
121 .Times(1)
122 .WillOnce(Return(GL_NO_ERROR));
123
124 const auto Render = itPresentCreator->second(_pPresent);
125 ASSERT_NE(nullptr, Render);
126
127 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferId))
128 .Times(1);
129
130 EXPECT_CALL(GLProxy, DrawElements(GL_TRIANGLES, (int)Indices.size(),
131 GL_UNSIGNED_INT, nullptr))
132 .Times(1);
133
134 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0))
135 .Times(1);
136
137 EXPECT_CALL(GLProxy, BindTexture(GL_TEXTURE_2D, 0))
138 .Times(0); // Нельзя!!!
139
140 Render();
141
142 EXPECT_CALL(GLProxy, DeleteBuffers(1, BufferId))
143 .Times(1);
144 };
145
146 {
147 const auto pPresent = Component_t::Make(
148 {
149 { uT("content"), Indices },
150 });
151
152 TestCallRender(pPresent);
153 }
154
155 {
156 // Индексный буфер через компонент Data
157
158 const auto pData = Component_t::Make(
159 {
160 { uT("kind"), uT("Buffer") },
161 { uT("content"), Indices },
162 });
163
164 TestCallRender(Component_t::Make({ { uT("service"), Object_t{ pData } } }));
165 }
166}
167
168// ************************************************************************** //
169TEST_F(OpenGLShader_test, /*DISABLED_*/Test_Present_Instance_SizeAndCountInvalidValue)
170{
171 ::mock::GLProxy GLProxy;
172
173 const Tested_t Example{ Data_t{} };
174 const ITested_t & IExample = Example;
175
176 auto itCreator = IExample.GetCreators().find(uT("Present"));
177 ASSERT_NE(IExample.GetCreators().end(), itCreator);
178
179 auto TestCallMapper = [&](
180 const Component_t::ComponentPtr_t & _pInstance,
181 const auto & _Mapper)
182 {
183 const ::std::vector<int> Source;
184
185 (*_pInstance)[uT("mapper")] = _Mapper;
186
187 const auto pPresent = Component_t::Make(
188 {
189 { uT("content"), Source },
190 { uT("service"), Object_t{ _pInstance } }
191 });
192
193 using namespace ::testing;
194
195 EXPECT_CALL(GLProxy, GenBuffers(_)) // Индексный буфер
196 .Times(1);
197
198 EXPECT_THROW(itCreator->second(pPresent), ::std::exception);
199 };
200
201 auto TestCall = [&](const Component_t::ComponentPtr_t & _pInstance)
202 {
203 using BufferMapperMaxCount_t = ::std::function<bool(void *)>;
204 using BufferMapperCangeCount_t = ::std::function<bool(void *, ::std::size_t &)>;
205
206 TestCallMapper(_pInstance, BufferMapperMaxCount_t{});
207 TestCallMapper(_pInstance, BufferMapperCangeCount_t{});
208 };
209
210 TestCall(Component_t::Make(
211 {
212 { uT("kind"), uT("Buffer") },
213 }));
214
215 TestCall(Component_t::Make(
216 {
217 { uT("kind"), uT("Buffer") },
218 { uT("size"), ::std::size_t(17) },
219 }));
220
221 TestCall(Component_t::Make(
222 {
223 { uT("kind"), uT("Buffer") },
224 { uT("size"), ::std::size_t(32) },
225 }));
226
227 TestCall(Component_t::Make(
228 {
229 { uT("kind"), uT("Buffer") },
230 { uT("size"), ::std::size_t(32) },
231 { uT("count"), ::std::size_t(5) },
232 }));
233}
234
235// ************************************************************************** //
236TEST_F(OpenGLShader_test, /*DISABLED_*/Test_Present_Instance_CreateBuffer_Fail)
237{
238 using BufferMapperMaxCount_t = ::std::function<bool(void *)>;
239 using BufferMapperCangeCount_t = ::std::function<bool(void *, ::std::size_t &)>;
240
241 ::mock::GLProxy GLProxy;
242
243 const Tested_t Example{ Data_t{} };
244 const ITested_t & IExample = Example;
245
246 auto itCreator = IExample.GetCreators().find(uT("Present"));
247 ASSERT_NE(IExample.GetCreators().end(), itCreator);
248
249 auto TestCallRender = [&](const auto & _Mapper)
250 {
251 const ::std::vector<int> Source;
252
253 const auto pInstanceData = Component_t::Make(
254 {
255 { uT("kind"), uT("Buffer") },
256 { uT("mapper"), _Mapper },
257 { uT("size"), ::std::size_t(16) },
258 { uT("count"), ::std::size_t(1) },
259 });
260
261 const auto pPresent = Component_t::Make(
262 {
263 { uT("content"), Source },
264 { uT("service"), Object_t{ pInstanceData } }
265 });
266
267 using namespace ::testing;
268
269 InSequence Dummy;
270
271 EXPECT_CALL(GLProxy, GenBuffers(_))
272 .Times(1);
273
274 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _))
275 .Times(AtLeast(1));
276
277 EXPECT_CALL(GLProxy, GetError())
278 .Times(1)
279 .WillOnce(Return(GL_NO_ERROR));
280
281 EXPECT_CALL(GLProxy, GenBuffers(_))
282 .Times(1);
283
284 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, _))
285 .Times(AtLeast(1));
286
287 EXPECT_CALL(GLProxy, GetError())
288 .Times(1)
289 .WillOnce(Return(1908232144));
290
291 EXPECT_THROW(itCreator->second(pPresent), ::std::exception);
292 };
293
294 TestCallRender(BufferMapperMaxCount_t{});
295 TestCallRender(BufferMapperCangeCount_t{});
296}
297
298// ************************************************************************** //
299TEST_F(OpenGLShader_test, /*DISABLED_*/Test_Present_Instance_MaxCount)
300{
301 using BufferMapper_t = ::covellite::api::cbBufferMap_t<void>;
302
303 ::mock::GLProxy GLProxy;
304
305 class MapperProxy_t
306 {
307 public:
308 MOCK_METHOD1(Map, bool(void *));
309 };
310
311 MapperProxy_t MapperProxy;
312
313 const ::mock::GLuint IndexBufferId = 1909231813;
314 const ::mock::GLuint InstanceBufferId = 1909231820;
315 const ::std::size_t InstanceCount = 120;
316 const ::std::size_t InstanceStride = 48;
317 const ::std::size_t InstanceBufferSize = InstanceCount * InstanceStride;
318 const ::mock::GLint ProgramId = 1909231917;
319
320 ::std::vector<int> Indices =
321 {
322 1808261927,
323 1808261928,
324 1808261929,
325 1808261930,
326 1808261931,
327 1909231821,
328 1909231822,
329 1909231823,
330 };
331
332 IntroduceBufferSize(Indices);
333
334 void * pLocalData = (void *)1909232013;
335
336 const BufferMapper_t Mapper = [&](void * _pData)
337 {
338 pLocalData = _pData;
339 return MapperProxy.Map(_pData);
340 };
341
342 const Tested_t Example{ Data_t{} };
343 const ITested_t & IExample = Example;
344
345 auto itCreator = IExample.GetCreators().find(uT("Present"));
346 ASSERT_NE(IExample.GetCreators().end(), itCreator);
347
348 auto TestCallRender = [&](const Component_t::ComponentPtr_t & _pPresent)
349 {
350 using namespace ::testing;
351
352 InSequence Dummy;
353
354 // *************************** Индексный буфер ************************** //
355
356 EXPECT_CALL(GLProxy, GenBuffers(1))
357 .Times(1)
358 .WillOnce(Return(IndexBufferId));
359
360 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId))
361 .Times(1);
362
363 const auto Size =
364 static_cast<::mock::GLsizeiptr>(Indices.size() * sizeof(int));
365
366 EXPECT_CALL(GLProxy, BufferData(GL_ELEMENT_ARRAY_BUFFER, Size,
367 GetExpected(Indices), GL_STATIC_DRAW))
368 .Times(1);
369
370 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0))
371 .Times(1);
372
373 EXPECT_CALL(GLProxy, GetError())
374 .Times(1)
375 .WillOnce(Return(GL_NO_ERROR));
376
377 // ****************************** Инстанс-буфер ************************* //
378
379 EXPECT_CALL(GLProxy, GenBuffers(1))
380 .Times(1)
381 .WillOnce(Return(InstanceBufferId));
382
383 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, InstanceBufferId))
384 .Times(1);
385
386 EXPECT_CALL(GLProxy, BufferData(GL_ARRAY_BUFFER, InstanceBufferSize,
387 ::std::vector<uint8_t>{}, GL_DYNAMIC_DRAW))
388 .Times(1);
389
390 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, 0))
391 .Times(1);
392
393 EXPECT_CALL(GLProxy, GetError())
394 .Times(1)
395 .WillOnce(Return(GL_NO_ERROR));
396
397 // ********************************************************************** //
398
399 const auto Render = itCreator->second(_pPresent);
400 ASSERT_NE(nullptr, Render);
401
402 // ****************** Отрисовка без обновления ************************** //
403
404 const auto TestCallDraw = [&](void)
405 {
406 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId))
407 .Times(1);
408
409 EXPECT_CALL(GLProxy, DrawElementsInstanced(GL_TRIANGLES,
410 (int)Indices.size(), GL_UNSIGNED_INT, nullptr, InstanceCount))
411 .Times(1);
412
413 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0))
414 .Times(1);
415
416 EXPECT_CALL(GLProxy, BindTexture(GL_TEXTURE_2D, 0))
417 .Times(0); // Нельзя!!!
418 };
419
420 EXPECT_CALL(MapperProxy, Map(nullptr))
421 .Times(1)
422 .WillOnce(Return(false));
423
424 EXPECT_CALL(MapperProxy, Map(_))
425 .Times(0);
426
427 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, InstanceBufferId))
428 .Times(0);
429
430 TestCallDraw();
431 Render();
432
433 // ******************* Отрисовка с обновлением ************************** //
434
435 const auto TestCallSetInstanceData = [&](
436 const ::mock::GLenum _iType,
437 const ::mock::GLenum _Type,
438 const ::mock::GLint _LocationIndex0,
439 auto pData)
440 {
441 EXPECT_CALL(MapperProxy, Map(nullptr))
442 .Times(1)
443 .WillOnce(Return(true));
444
445 EXPECT_CALL(MapperProxy, Map(pData))
446 .Times(1);
447
448 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, InstanceBufferId))
449 .Times(1);
450
451 EXPECT_CALL(GLProxy,
452 BufferSubDataRaw(GL_ARRAY_BUFFER, 0, InstanceBufferSize, pData))
453 .Times(1);
454
455 EXPECT_CALL(GLProxy, GetIntegerv(GL_CURRENT_PROGRAM))
456 .Times(1)
457 .WillOnce(Return(&ProgramId));
458
459 constexpr auto BlockSize = sizeof(float) * 4;
460
461 EXPECT_CALL(GLProxy, GetProgramiv(ProgramId, GL_ACTIVE_ATTRIBUTES))
462 .Times(1)
463 .WillOnce(Return(BlockSize));
464
465 for (int i = 0; i < BlockSize; i++)
466 {
467 EXPECT_CALL(GLProxy, GetActiveAttribType(ProgramId, i))
468 .Times(1)
469 .WillOnce(Return(_iType));
470
471 EXPECT_CALL(GLProxy, GetActiveAttribName(ProgramId, i, 255))
472 .Times(1)
473 .WillOnce(Return("iValue" + ::std::to_string(i + 1)));
474 }
475
476 for (int i = 0; i < InstanceStride / BlockSize; i++)
477 {
478 EXPECT_CALL(GLProxy,
479 GetAttribLocation(ProgramId, "iValue" + ::std::to_string(i + 1)))
480 .Times(1)
481 .WillOnce(Return(_LocationIndex0 + i));
482
483 if (_LocationIndex0 + i >= 0)
484 {
485 EXPECT_CALL(GLProxy, EnableVertexAttribArray(_LocationIndex0 + i))
486 .Times(1);
487
488 EXPECT_CALL(GLProxy, VertexAttribPointer(_LocationIndex0 + i, 4,
489 _Type, GL_FALSE, InstanceStride, (void*)(BlockSize * i)))
490 .Times(1);
491
492 EXPECT_CALL(GLProxy, VertexAttribDivisor(_LocationIndex0 + i, 1))
493 .Times(1);
494 }
495 else
496 {
497 EXPECT_CALL(GLProxy, EnableVertexAttribArray(_))
498 .Times(0);
499
500 EXPECT_CALL(GLProxy, VertexAttribPointer(_, _, _, _, _, _))
501 .Times(0);
502
503 EXPECT_CALL(GLProxy, VertexAttribDivisor(_, _))
504 .Times(0);
505 }
506 }
507
508 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, 0))
509 .Times(1);
510 };
511
512 // Первый вызов без значения, чтобы сохранился указатель на локальные
513 // данные в pLocalData
514 TestCallSetInstanceData(GL_FLOAT_VEC4, GL_FLOAT, 1909232004, _);
515 TestCallDraw();
516 Render();
517
518 TestCallSetInstanceData(GL_FLOAT_VEC4, GL_FLOAT, 1909232004, pLocalData);
519 TestCallDraw();
520 Render();
521
522 TestCallSetInstanceData(GL_INT_VEC4, GL_INT, 1909232005, pLocalData);
523 TestCallDraw();
524 Render();
525
526 TestCallSetInstanceData(2005221201, 2005221201, 2005221202, pLocalData);
527 TestCallDraw();
528 Render();
529
530 TestCallSetInstanceData(GL_FLOAT_VEC4, GL_FLOAT, -1, pLocalData);
531 TestCallDraw();
532 Render();
533
534 TestCallSetInstanceData(GL_INT_VEC4, GL_INT, -1, pLocalData);
535 TestCallDraw();
536 Render();
537
538 // ********************************************************************** //
539
540 EXPECT_CALL(GLProxy, DeleteBuffers(1, IndexBufferId))
541 .Times(1);
542
543 EXPECT_CALL(GLProxy, DeleteBuffers(1, InstanceBufferId))
544 .Times(1);
545 };
546
547 const auto pInstanceData = Component_t::Make(
548 {
549 { uT("kind"), uT("Buffer") },
550 { uT("size"), InstanceBufferSize },
551 { uT("mapper"), Mapper },
552 { uT("count"), InstanceCount },
553 });
554
555 const auto pPresent = Component_t::Make(
556 {
557 { uT("content"), Indices },
558 { uT("service"), Object_t{ pInstanceData } }
559 });
560
561 TestCallRender(pPresent);
562}
563
564// ************************************************************************** //
565TEST_F(OpenGLShader_test, /*DISABLED_*/Test_Present_Instance_ChangeCount)
566{
567 using BufferMapper_t = ::std::function<bool(void *, ::std::size_t &)>;
568
569 ::mock::GLProxy GLProxy;
570
571 class MapperProxy_t
572 {
573 public:
574 MOCK_METHOD1(GetCount, ::std::size_t(::std::size_t));
575 MOCK_METHOD1(Map, bool(void *));
576 };
577
578 MapperProxy_t MapperProxy;
579
580 const ::mock::GLuint IndexBufferId = 1909231813;
581 const ::mock::GLuint InstanceBufferId = 1909231820;
582 const ::std::size_t InstanceCount = 120;
583 const ::std::size_t InstanceStride = 48;
584 const ::std::size_t InstanceBufferSize = InstanceCount * InstanceStride;
585 const ::mock::GLint ProgramId = 1909231917;
586
587 ::std::vector<int> Indices =
588 {
589 1808261927,
590 1808261928,
591 1808261929,
592 1808261930,
593 1808261931,
594 1909231821,
595 1909231822,
596 1909231823,
597 };
598
599 IntroduceBufferSize(Indices);
600
601 void * pLocalData = (void *)1909232013;
602
603 const BufferMapper_t Mapper = [&](void * _pData, ::std::size_t & _Count)
604 {
605 pLocalData = _pData;
606 _Count = MapperProxy.GetCount(_Count);
607 return MapperProxy.Map(_pData);
608 };
609
610 const Tested_t Example{ Data_t{} };
611 const ITested_t & IExample = Example;
612
613 auto itCreator = IExample.GetCreators().find(uT("Present"));
614 ASSERT_NE(IExample.GetCreators().end(), itCreator);
615
616 auto TestCallRender = [&](const Component_t::ComponentPtr_t & _pPresent)
617 {
618 using namespace ::testing;
619
620 InSequence Dummy;
621
622 // *************************** Индексный буфер ************************** //
623
624 EXPECT_CALL(GLProxy, GenBuffers(1))
625 .Times(1)
626 .WillOnce(Return(IndexBufferId));
627
628 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId))
629 .Times(1);
630
631 const auto Size =
632 static_cast<::mock::GLsizeiptr>(Indices.size() * sizeof(int));
633
634 EXPECT_CALL(GLProxy, BufferData(GL_ELEMENT_ARRAY_BUFFER, Size,
635 GetExpected(Indices), GL_STATIC_DRAW))
636 .Times(1);
637
638 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0))
639 .Times(1);
640
641 EXPECT_CALL(GLProxy, GetError())
642 .Times(1)
643 .WillOnce(Return(GL_NO_ERROR));
644
645 // ****************************** Инстанс-буфер ************************* //
646
647 EXPECT_CALL(GLProxy, GenBuffers(1))
648 .Times(1)
649 .WillOnce(Return(InstanceBufferId));
650
651 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, InstanceBufferId))
652 .Times(1);
653
654 EXPECT_CALL(GLProxy, BufferData(GL_ARRAY_BUFFER, InstanceBufferSize,
655 ::std::vector<uint8_t>{}, GL_DYNAMIC_DRAW))
656 .Times(1);
657
658 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, 0))
659 .Times(1);
660
661 EXPECT_CALL(GLProxy, GetError())
662 .Times(1)
663 .WillOnce(Return(GL_NO_ERROR));
664
665 // ********************************************************************** //
666
667 const auto Render = itCreator->second(_pPresent);
668 ASSERT_NE(nullptr, Render);
669
670 // ****************** Отрисовка без обновления ************************** //
671
672 const auto TestCallDraw = [&](const ::std::size_t _Count)
673 {
674 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId))
675 .Times(1);
676
677 EXPECT_CALL(GLProxy, DrawElementsInstanced(GL_TRIANGLES,
678 (int)Indices.size(), GL_UNSIGNED_INT, nullptr, _Count))
679 .Times(1);
680
681 EXPECT_CALL(GLProxy, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0))
682 .Times(1);
683
684 EXPECT_CALL(GLProxy, BindTexture(GL_TEXTURE_2D, 0))
685 .Times(0); // Нельзя!!!
686 };
687
688 EXPECT_CALL(MapperProxy, GetCount(InstanceCount))
689 .Times(1)
690 .WillOnce(Return(InstanceCount / 2));
691
692 EXPECT_CALL(MapperProxy, Map(nullptr))
693 .Times(1)
694 .WillOnce(Return(false));
695
696 EXPECT_CALL(MapperProxy, Map(_))
697 .Times(0);
698
699 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, InstanceBufferId))
700 .Times(0);
701
702 TestCallDraw(InstanceCount / 2);
703 Render();
704
705 // ********** Отрисовка без обновления (слишком большое число) ********** //
706
707 EXPECT_CALL(MapperProxy, GetCount(InstanceCount))
708 .Times(1)
709 .WillOnce(Return(InstanceCount * 2));
710
711 EXPECT_CALL(MapperProxy, Map(nullptr))
712 .Times(1)
713 .WillOnce(Return(false));
714
715 EXPECT_CALL(MapperProxy, Map(_))
716 .Times(0);
717
718 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, InstanceBufferId))
719 .Times(0);
720
721 TestCallDraw(InstanceCount);
722 Render();
723
724 // ******************* Отрисовка с обновлением ************************** //
725
726 const auto TestCallSetInstanceData = [&](
727 const ::mock::GLenum _iType,
728 const ::mock::GLenum _Type,
729 const ::mock::GLint _LocationIndex0,
730 auto pData,
731 const ::std::size_t _ReturnCount)
732 {
733 EXPECT_CALL(MapperProxy, GetCount(InstanceCount))
734 .Times(1)
735 .WillOnce(Return(0));
736
737 EXPECT_CALL(MapperProxy, Map(nullptr))
738 .Times(1)
739 .WillOnce(Return(true));
740
741 EXPECT_CALL(MapperProxy, GetCount(0))
742 .Times(1)
743 .WillOnce(Return(_ReturnCount));
744
745 EXPECT_CALL(MapperProxy, Map(pData))
746 .Times(1);
747
748 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, InstanceBufferId))
749 .Times(1);
750
751 EXPECT_CALL(GLProxy,
752 BufferSubDataRaw(GL_ARRAY_BUFFER, 0, InstanceBufferSize, pData))
753 .Times(1);
754
755 EXPECT_CALL(GLProxy, GetIntegerv(GL_CURRENT_PROGRAM))
756 .Times(1)
757 .WillOnce(Return(&ProgramId));
758
759 constexpr auto BlockSize = sizeof(float) * 4;
760
761 EXPECT_CALL(GLProxy, GetProgramiv(ProgramId, GL_ACTIVE_ATTRIBUTES))
762 .Times(1)
763 .WillOnce(Return(BlockSize));
764
765 for (int i = 0; i < BlockSize; i++)
766 {
767 EXPECT_CALL(GLProxy, GetActiveAttribType(ProgramId, i))
768 .Times(1)
769 .WillOnce(Return(_iType));
770
771 EXPECT_CALL(GLProxy, GetActiveAttribName(ProgramId, i, 255))
772 .Times(1)
773 .WillOnce(Return("iValue" + ::std::to_string(i + 1)));
774 }
775
776 for (int i = 0; i < InstanceStride / BlockSize; i++)
777 {
778 EXPECT_CALL(GLProxy,
779 GetAttribLocation(ProgramId, "iValue" + ::std::to_string(i + 1)))
780 .Times(1)
781 .WillOnce(Return(_LocationIndex0 + i));
782
783 if (_LocationIndex0 + i >= 0)
784 {
785 EXPECT_CALL(GLProxy, EnableVertexAttribArray(_LocationIndex0 + i))
786 .Times(1);
787
788 EXPECT_CALL(GLProxy, VertexAttribPointer(_LocationIndex0 + i, 4,
789 _Type, GL_FALSE, InstanceStride, (void *)(BlockSize * i)))
790 .Times(1);
791
792 EXPECT_CALL(GLProxy, VertexAttribDivisor(_LocationIndex0 + i, 1))
793 .Times(1);
794 }
795 else
796 {
797 EXPECT_CALL(GLProxy, EnableVertexAttribArray(_))
798 .Times(0);
799
800 EXPECT_CALL(GLProxy, VertexAttribPointer(_, _, _, _, _, _))
801 .Times(0);
802
803 EXPECT_CALL(GLProxy, VertexAttribDivisor(_, _))
804 .Times(0);
805 }
806 }
807
808 EXPECT_CALL(GLProxy, BindBuffer(GL_ARRAY_BUFFER, 0))
809 .Times(1);
810 };
811
812 // Первый вызов без значения, просто чтобы сохранился указатель
813 // на локальные данные в pLocalData
814 TestCallSetInstanceData(GL_FLOAT_VEC4, GL_FLOAT, 1909232004, _, 0);
815 TestCallDraw(0);
816 Render();
817
818 TestCallSetInstanceData(GL_FLOAT_VEC4, GL_FLOAT, 1909232004, pLocalData, InstanceCount / 3);
819 TestCallDraw(InstanceCount / 3);
820 Render();
821
822 TestCallSetInstanceData(GL_INT_VEC4, GL_INT, 1909232005, pLocalData, InstanceCount / 4);
823 TestCallDraw(InstanceCount / 4);
824 Render();
825
826 TestCallSetInstanceData(2005221201, 2005221201, 2005221202, pLocalData, InstanceCount * 2);
827 TestCallDraw(InstanceCount);
828 Render();
829
830 TestCallSetInstanceData(GL_FLOAT_VEC4, GL_FLOAT, -1, pLocalData, InstanceCount * 3);
831 TestCallDraw(InstanceCount);
832 Render();
833
834 TestCallSetInstanceData(GL_INT_VEC4, GL_INT, -1, pLocalData, InstanceCount + 1);
835 TestCallDraw(InstanceCount);
836 Render();
837
838 // ********************************************************************** //
839
840 EXPECT_CALL(GLProxy, DeleteBuffers(1, IndexBufferId))
841 .Times(1);
842
843 EXPECT_CALL(GLProxy, DeleteBuffers(1, InstanceBufferId))
844 .Times(1);
845 };
846
847 const auto pInstanceData = Component_t::Make(
848 {
849 { uT("kind"), uT("Buffer") },
850 { uT("size"), InstanceBufferSize },
851 { uT("mapper"), Mapper },
852 { uT("count"), InstanceCount },
853 });
854
855 const auto pPresent = Component_t::Make(
856 {
857 { uT("content"), Indices },
858 { uT("service"), Object_t{ pInstanceData } }
859 });
860
861 TestCallRender(pPresent);
862}
863
864} // unnamed namespace