List.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
  3. * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
  4. * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/TemporaryChange.h>
  9. #include <LibGL/GLContext.h>
  10. namespace GL {
  11. void GLContext::gl_call_list(GLuint list)
  12. {
  13. if (m_gl_call_depth > max_allowed_gl_call_depth)
  14. return;
  15. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_call_list, list);
  16. if (m_listings.size() < list)
  17. return;
  18. TemporaryChange change { m_gl_call_depth, m_gl_call_depth + 1 };
  19. invoke_list(list);
  20. }
  21. void GLContext::gl_call_lists(GLsizei n, GLenum type, void const* lists)
  22. {
  23. if (m_gl_call_depth > max_allowed_gl_call_depth)
  24. return;
  25. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_call_lists, n, type, lists);
  26. RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
  27. RETURN_WITH_ERROR_IF(!(type == GL_BYTE
  28. || type == GL_UNSIGNED_BYTE
  29. || type == GL_SHORT
  30. || type == GL_UNSIGNED_SHORT
  31. || type == GL_INT
  32. || type == GL_UNSIGNED_INT
  33. || type == GL_FLOAT
  34. || type == GL_2_BYTES
  35. || type == GL_3_BYTES
  36. || type == GL_4_BYTES),
  37. GL_INVALID_ENUM);
  38. TemporaryChange change { m_gl_call_depth, m_gl_call_depth + 1 };
  39. auto invoke_all_lists = [&]<typename T>(T const* lists) {
  40. for (int i = 0; i < n; ++i) {
  41. auto list = static_cast<size_t>(lists[i]);
  42. invoke_list(m_list_base + list);
  43. }
  44. };
  45. switch (type) {
  46. case GL_BYTE:
  47. invoke_all_lists(static_cast<GLbyte const*>(lists));
  48. break;
  49. case GL_UNSIGNED_BYTE:
  50. invoke_all_lists(static_cast<GLubyte const*>(lists));
  51. break;
  52. case GL_SHORT:
  53. invoke_all_lists(static_cast<GLshort const*>(lists));
  54. break;
  55. case GL_UNSIGNED_SHORT:
  56. invoke_all_lists(static_cast<GLushort const*>(lists));
  57. break;
  58. case GL_INT:
  59. invoke_all_lists(static_cast<GLint const*>(lists));
  60. break;
  61. case GL_UNSIGNED_INT:
  62. invoke_all_lists(static_cast<GLuint const*>(lists));
  63. break;
  64. case GL_FLOAT:
  65. invoke_all_lists(static_cast<GLfloat const*>(lists));
  66. break;
  67. case GL_2_BYTES:
  68. case GL_3_BYTES:
  69. case GL_4_BYTES:
  70. dbgln("GLContext FIXME: unimplemented glCallLists() with type {}", type);
  71. break;
  72. default:
  73. VERIFY_NOT_REACHED();
  74. }
  75. }
  76. void GLContext::gl_delete_lists(GLuint list, GLsizei range)
  77. {
  78. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  79. RETURN_WITH_ERROR_IF(range < 0, GL_INVALID_VALUE);
  80. if (m_listings.size() < list || m_listings.size() <= list + range)
  81. return;
  82. for (auto& entry : m_listings.span().slice(list - 1, range))
  83. entry.entries.clear_with_capacity();
  84. }
  85. void GLContext::gl_end_list()
  86. {
  87. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  88. RETURN_WITH_ERROR_IF(!m_current_listing_index.has_value(), GL_INVALID_OPERATION);
  89. m_listings[m_current_listing_index->index] = move(m_current_listing_index->listing);
  90. m_current_listing_index.clear();
  91. }
  92. GLuint GLContext::gl_gen_lists(GLsizei range)
  93. {
  94. RETURN_VALUE_WITH_ERROR_IF(range <= 0, GL_INVALID_VALUE, 0);
  95. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
  96. auto initial_entry = m_listings.size();
  97. m_listings.resize(range + initial_entry);
  98. return initial_entry + 1;
  99. }
  100. GLboolean GLContext::gl_is_list(GLuint list)
  101. {
  102. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, GL_FALSE);
  103. return list < m_listings.size() ? GL_TRUE : GL_FALSE;
  104. }
  105. void GLContext::gl_list_base(GLuint base)
  106. {
  107. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_list_base, base);
  108. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  109. m_list_base = base;
  110. }
  111. void GLContext::gl_new_list(GLuint list, GLenum mode)
  112. {
  113. RETURN_WITH_ERROR_IF(list == 0, GL_INVALID_VALUE);
  114. RETURN_WITH_ERROR_IF(mode != GL_COMPILE && mode != GL_COMPILE_AND_EXECUTE, GL_INVALID_ENUM);
  115. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  116. RETURN_WITH_ERROR_IF(m_current_listing_index.has_value(), GL_INVALID_OPERATION);
  117. if (m_listings.size() < list)
  118. return;
  119. m_current_listing_index = CurrentListing { {}, static_cast<size_t>(list - 1), mode };
  120. }
  121. void GLContext::invoke_list(size_t list_index)
  122. {
  123. auto& listing = m_listings[list_index - 1];
  124. for (auto& entry : listing.entries) {
  125. entry.function.visit([&](auto& function) {
  126. entry.arguments.visit([&](auto& arguments) {
  127. auto apply = [&]<typename... Args>(Args&&... args) {
  128. if constexpr (requires { (this->*function)(forward<Args>(args)...); })
  129. (this->*function)(forward<Args>(args)...);
  130. };
  131. arguments.apply_as_args(apply);
  132. });
  133. });
  134. }
  135. }
  136. }