OGLIndexBuffer.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../../Precompiled.h"
  4. #include "../../Core/Context.h"
  5. #include "../../Graphics/Graphics.h"
  6. #include "../../GraphicsAPI/GraphicsImpl.h"
  7. #include "../../GraphicsAPI/IndexBuffer.h"
  8. #include "../../IO/Log.h"
  9. #include "../../DebugNew.h"
  10. namespace Urho3D
  11. {
  12. void IndexBuffer::OnDeviceLost_OGL()
  13. {
  14. if (object_.name_ && !graphics_->IsDeviceLost())
  15. glDeleteBuffers(1, &object_.name_);
  16. GPUObject::OnDeviceLost();
  17. }
  18. void IndexBuffer::OnDeviceReset_OGL()
  19. {
  20. if (!object_.name_)
  21. {
  22. Create_OGL();
  23. dataLost_ = !UpdateToGPU_OGL();
  24. }
  25. else if (dataPending_)
  26. dataLost_ = !UpdateToGPU_OGL();
  27. dataPending_ = false;
  28. }
  29. void IndexBuffer::Release_OGL()
  30. {
  31. Unlock_OGL();
  32. if (object_.name_)
  33. {
  34. if (!graphics_)
  35. return;
  36. if (!graphics_->IsDeviceLost())
  37. {
  38. if (graphics_->GetIndexBuffer() == this)
  39. graphics_->SetIndexBuffer(nullptr);
  40. glDeleteBuffers(1, &object_.name_);
  41. }
  42. object_.name_ = 0;
  43. }
  44. }
  45. bool IndexBuffer::SetData_OGL(const void* data)
  46. {
  47. if (!data)
  48. {
  49. URHO3D_LOGERROR("Null pointer for index buffer data");
  50. return false;
  51. }
  52. if (!indexSize_)
  53. {
  54. URHO3D_LOGERROR("Index size not defined, can not set index buffer data");
  55. return false;
  56. }
  57. if (shadowData_ && data != shadowData_.Get())
  58. memcpy(shadowData_.Get(), data, (size_t)indexCount_ * indexSize_);
  59. if (object_.name_)
  60. {
  61. if (!graphics_->IsDeviceLost())
  62. {
  63. graphics_->SetIndexBuffer(this);
  64. glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)indexCount_ * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  65. }
  66. else
  67. {
  68. URHO3D_LOGWARNING("Index buffer data assignment while device is lost");
  69. dataPending_ = true;
  70. }
  71. }
  72. dataLost_ = false;
  73. return true;
  74. }
  75. bool IndexBuffer::SetDataRange_OGL(const void* data, i32 start, i32 count, bool discard)
  76. {
  77. assert(start >= 0 && count >= 0);
  78. if (start == 0 && count == indexCount_)
  79. return SetData_OGL(data);
  80. if (!data)
  81. {
  82. URHO3D_LOGERROR("Null pointer for index buffer data");
  83. return false;
  84. }
  85. if (!indexSize_)
  86. {
  87. URHO3D_LOGERROR("Index size not defined, can not set index buffer data");
  88. return false;
  89. }
  90. if (start + count > indexCount_)
  91. {
  92. URHO3D_LOGERROR("Illegal range for setting new index buffer data");
  93. return false;
  94. }
  95. if (!count)
  96. return true;
  97. byte* dst = shadowData_.Get() + (intptr_t)start * indexSize_;
  98. if (shadowData_ && dst != data)
  99. memcpy(dst, data, (size_t)count * indexSize_);
  100. if (object_.name_)
  101. {
  102. if (!graphics_->IsDeviceLost())
  103. {
  104. graphics_->SetIndexBuffer(this);
  105. if (!discard || start != 0)
  106. glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, (GLintptr)start * indexSize_, (GLsizeiptr)count * indexSize_, data);
  107. else
  108. glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)count * indexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  109. }
  110. else
  111. {
  112. URHO3D_LOGWARNING("Index buffer data assignment while device is lost");
  113. dataPending_ = true;
  114. }
  115. }
  116. return true;
  117. }
  118. void* IndexBuffer::Lock_OGL(i32 start, i32 count, bool discard)
  119. {
  120. assert(start >= 0 && count >= 0);
  121. if (lockState_ != LOCK_NONE)
  122. {
  123. URHO3D_LOGERROR("Index buffer already locked");
  124. return nullptr;
  125. }
  126. if (!indexSize_)
  127. {
  128. URHO3D_LOGERROR("Index size not defined, can not lock index buffer");
  129. return nullptr;
  130. }
  131. if (start + count > indexCount_)
  132. {
  133. URHO3D_LOGERROR("Illegal range for locking index buffer");
  134. return nullptr;
  135. }
  136. if (!count)
  137. return nullptr;
  138. lockStart_ = start;
  139. lockCount_ = count;
  140. discardLock_ = discard;
  141. if (shadowData_)
  142. {
  143. lockState_ = LOCK_SHADOW;
  144. return shadowData_.Get() + (intptr_t)start * indexSize_;
  145. }
  146. else if (graphics_)
  147. {
  148. lockState_ = LOCK_SCRATCH;
  149. lockScratchData_ = graphics_->ReserveScratchBuffer(count * indexSize_);
  150. return lockScratchData_;
  151. }
  152. else
  153. return nullptr;
  154. }
  155. void IndexBuffer::Unlock_OGL()
  156. {
  157. switch (lockState_)
  158. {
  159. case LOCK_SHADOW:
  160. SetDataRange_OGL(shadowData_.Get() + (intptr_t)lockStart_ * indexSize_, lockStart_, lockCount_, discardLock_);
  161. lockState_ = LOCK_NONE;
  162. break;
  163. case LOCK_SCRATCH:
  164. SetDataRange_OGL(lockScratchData_, lockStart_, lockCount_, discardLock_);
  165. if (graphics_)
  166. graphics_->FreeScratchBuffer(lockScratchData_);
  167. lockScratchData_ = nullptr;
  168. lockState_ = LOCK_NONE;
  169. break;
  170. default:
  171. break;
  172. }
  173. }
  174. bool IndexBuffer::Create_OGL()
  175. {
  176. if (!indexCount_)
  177. {
  178. Release_OGL();
  179. return true;
  180. }
  181. if (graphics_)
  182. {
  183. if (graphics_->IsDeviceLost())
  184. {
  185. URHO3D_LOGWARNING("Index buffer creation while device is lost");
  186. return true;
  187. }
  188. if (!object_.name_)
  189. glGenBuffers(1, &object_.name_);
  190. if (!object_.name_)
  191. {
  192. URHO3D_LOGERROR("Failed to create index buffer");
  193. return false;
  194. }
  195. graphics_->SetIndexBuffer(this);
  196. glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)indexCount_ * indexSize_, nullptr, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  197. }
  198. return true;
  199. }
  200. bool IndexBuffer::UpdateToGPU_OGL()
  201. {
  202. if (object_.name_ && shadowData_)
  203. return SetData_OGL(shadowData_.Get());
  204. else
  205. return false;
  206. }
  207. void* IndexBuffer::MapBuffer_OGL(i32 start, i32 count, bool discard)
  208. {
  209. // Never called on OpenGL
  210. return nullptr;
  211. }
  212. void IndexBuffer::UnmapBuffer_OGL()
  213. {
  214. // Never called on OpenGL
  215. }
  216. } // namespace Urho3D