renderer_test.cxx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //
  2. // direct_renderer_test.cxx
  3. // graphics-test
  4. //
  5. // Created by Sam Jaffe on 6/1/19.
  6. // Copyright © 2019 Sam Jaffe. All rights reserved.
  7. //
  8. #include <gmock/gmock.h>
  9. #include "../src/renderer_impl.hpp"
  10. #include "game/graphics/object.hpp"
  11. #include "game/graphics/renderer.hpp"
  12. #include "game/graphics/vertex.h"
  13. #include "game/math/shape.hpp"
  14. #include "matrix/matrix.hpp"
  15. using testing::_;
  16. using testing::AnyNumber;
  17. using testing::IsEmpty;
  18. using testing::SizeIs;
  19. struct mock_renderer_impl : graphics::renderer_impl {
  20. MOCK_CONST_METHOD0(manager, std::shared_ptr<graphics::manager const>());
  21. MOCK_METHOD3(draw, void(identity<graphics::material>, math::matr4 const &,
  22. std::vector<graphics::vertex> const &));
  23. MOCK_METHOD0(clear, void());
  24. MOCK_METHOD0(flush, void());
  25. };
  26. identity<graphics::material> cast(unsigned int id) {
  27. return *reinterpret_cast<identity<graphics::material> *>(&id);
  28. }
  29. struct DirectRendererTest : testing::Test {
  30. void SetUp() override;
  31. void TearDown() override;
  32. std::unique_ptr<graphics::direct_renderer> renderer;
  33. mock_renderer_impl * mock;
  34. };
  35. void DirectRendererTest::SetUp() {
  36. mock = new mock_renderer_impl;
  37. renderer.reset(new graphics::direct_renderer(mock));
  38. }
  39. void DirectRendererTest::TearDown() {
  40. renderer.reset();
  41. delete mock;
  42. }
  43. graphics::object DemoObject(unsigned int id = 1) {
  44. math::dim2::rectangle const size{{{-1.f, -1.f}}, {{2.f, 2.f}}};
  45. math::dim2::rectangle const tex{{{0.f, 0.f}}, {{1.f, 1.f}}};
  46. return {size, size, cast(id), tex};
  47. }
  48. TEST_F(DirectRendererTest, DrawPassesToDraw) {
  49. EXPECT_CALL(*mock, draw(cast(1), math::matr4(), IsEmpty())).Times(1);
  50. renderer->draw(cast(1), math::matr4(), {});
  51. }
  52. TEST_F(DirectRendererTest, DrawObjectHasEmptyTranslation) {
  53. EXPECT_CALL(*mock, draw(cast(1), math::matr4(), _)).Times(1);
  54. renderer->draw(DemoObject());
  55. }
  56. TEST_F(DirectRendererTest, DrawObjectHasSixVertices) {
  57. EXPECT_CALL(*mock, draw(_, _, SizeIs(6))).Times(1);
  58. renderer->draw(DemoObject());
  59. }
  60. TEST_F(DirectRendererTest, MultipleDrawCallsDispatchMultipleDraws) {
  61. EXPECT_CALL(*mock, draw(_, _, SizeIs(6))).Times(2);
  62. renderer->draw(DemoObject());
  63. renderer->draw(DemoObject());
  64. }
  65. TEST_F(DirectRendererTest, ClearPassesToClear) {
  66. EXPECT_CALL(*mock, clear()).Times(1);
  67. renderer->clear();
  68. }
  69. TEST_F(DirectRendererTest, FlushPassesToFlush) {
  70. EXPECT_CALL(*mock, flush()).Times(1);
  71. renderer->flush();
  72. }
  73. struct BatchRendererTest : testing::Test {
  74. void SetUp() override;
  75. void TearDown() override;
  76. std::unique_ptr<graphics::batch_renderer> renderer;
  77. std::unique_ptr<graphics::direct_renderer> drenderer;
  78. mock_renderer_impl * mock;
  79. };
  80. void BatchRendererTest::SetUp() {
  81. mock = new mock_renderer_impl;
  82. drenderer.reset(new graphics::direct_renderer(mock));
  83. renderer.reset(new graphics::batch_renderer(drenderer.get()));
  84. }
  85. void BatchRendererTest::TearDown() {
  86. renderer.reset();
  87. drenderer.reset();
  88. delete mock;
  89. }
  90. TEST_F(BatchRendererTest, CallsFlushOnDestructor) {
  91. EXPECT_CALL(*mock, flush()).Times(1);
  92. renderer.reset();
  93. testing::Mock::VerifyAndClearExpectations(mock);
  94. }
  95. TEST_F(BatchRendererTest, ClearPassesToClear) {
  96. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  97. EXPECT_CALL(*mock, clear()).Times(1);
  98. renderer->clear();
  99. }
  100. TEST_F(BatchRendererTest, FlushPassesToFlush) {
  101. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  102. // This will end up changing
  103. EXPECT_CALL(*mock, flush()).Times(1).RetiresOnSaturation();
  104. renderer->flush();
  105. }
  106. TEST_F(BatchRendererTest, DoesNotWriteImmediately) {
  107. EXPECT_CALL(*mock, draw(_, _, _)).Times(0);
  108. renderer->draw(cast(1), math::matr4(), {});
  109. testing::Mock::VerifyAndClearExpectations(mock);
  110. // We need to re-enact this expectation
  111. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  112. EXPECT_CALL(*mock, draw(_, _, _)).Times(1);
  113. }
  114. TEST_F(BatchRendererTest, GroupsDataTogetherByMaterial) {
  115. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  116. EXPECT_CALL(*mock, draw(cast(1), _, SizeIs(12))).Times(1);
  117. EXPECT_CALL(*mock, draw(cast(2), _, SizeIs(6))).Times(1);
  118. renderer->draw(DemoObject());
  119. renderer->draw(DemoObject());
  120. renderer->draw(DemoObject(2));
  121. }
  122. TEST_F(BatchRendererTest, BatchLimitingCanSplitTheWrites) {
  123. EXPECT_CALL(*mock, flush()).Times(AnyNumber());
  124. renderer.reset(new graphics::batch_renderer(drenderer.get(), 15));
  125. EXPECT_CALL(*mock, draw(cast(1), _, SizeIs(12))).Times(1);
  126. EXPECT_CALL(*mock, draw(cast(2), _, SizeIs(6))).Times(2);
  127. renderer->draw(DemoObject());
  128. renderer->draw(DemoObject());
  129. renderer->draw(DemoObject(2));
  130. renderer->draw(DemoObject(2));
  131. }