OGLVertexBuffer.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../../Precompiled.h"
  23. #include "../../Graphics/Graphics.h"
  24. #include "../../Graphics/GraphicsImpl.h"
  25. #include "../../Graphics/VertexBuffer.h"
  26. #include "../../IO/Log.h"
  27. #include "../../DebugNew.h"
  28. namespace Atomic
  29. {
  30. void VertexBuffer::OnDeviceLost()
  31. {
  32. GPUObject::OnDeviceLost();
  33. }
  34. void VertexBuffer::OnDeviceReset()
  35. {
  36. if (!object_.name_)
  37. {
  38. Create();
  39. dataLost_ = !UpdateToGPU();
  40. }
  41. else if (dataPending_)
  42. dataLost_ = !UpdateToGPU();
  43. dataPending_ = false;
  44. }
  45. void VertexBuffer::Release()
  46. {
  47. Unlock();
  48. if (object_.name_)
  49. {
  50. if (!graphics_)
  51. return;
  52. if (!graphics_->IsDeviceLost())
  53. {
  54. for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
  55. {
  56. if (graphics_->GetVertexBuffer(i) == this)
  57. graphics_->SetVertexBuffer(0);
  58. }
  59. graphics_->SetVBO(0);
  60. glDeleteBuffers(1, &object_.name_);
  61. }
  62. object_.name_ = 0;
  63. }
  64. }
  65. bool VertexBuffer::SetData(const void* data)
  66. {
  67. if (!data)
  68. {
  69. ATOMIC_LOGERROR("Null pointer for vertex buffer data");
  70. return false;
  71. }
  72. if (!vertexSize_)
  73. {
  74. ATOMIC_LOGERROR("Vertex elements not defined, can not set vertex buffer data");
  75. return false;
  76. }
  77. if (shadowData_ && data != shadowData_.Get())
  78. memcpy(shadowData_.Get(), data, vertexCount_ * vertexSize_);
  79. if (object_.name_)
  80. {
  81. if (!graphics_->IsDeviceLost())
  82. {
  83. graphics_->SetVBO(object_.name_);
  84. glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  85. }
  86. else
  87. {
  88. ATOMIC_LOGWARNING("Vertex buffer data assignment while device is lost");
  89. dataPending_ = true;
  90. }
  91. }
  92. dataLost_ = false;
  93. return true;
  94. }
  95. bool VertexBuffer::SetDataRange(const void* data, unsigned start, unsigned count, bool discard)
  96. {
  97. if (start == 0 && count == vertexCount_)
  98. return SetData(data);
  99. if (!data)
  100. {
  101. ATOMIC_LOGERROR("Null pointer for vertex buffer data");
  102. return false;
  103. }
  104. if (!vertexSize_)
  105. {
  106. ATOMIC_LOGERROR("Vertex elements not defined, can not set vertex buffer data");
  107. return false;
  108. }
  109. if (start + count > vertexCount_)
  110. {
  111. ATOMIC_LOGERROR("Illegal range for setting new vertex buffer data");
  112. return false;
  113. }
  114. if (!count)
  115. return true;
  116. if (shadowData_ && shadowData_.Get() + start * vertexSize_ != data)
  117. memcpy(shadowData_.Get() + start * vertexSize_, data, count * vertexSize_);
  118. if (object_.name_)
  119. {
  120. if (!graphics_->IsDeviceLost())
  121. {
  122. graphics_->SetVBO(object_.name_);
  123. if (!discard || start != 0)
  124. glBufferSubData(GL_ARRAY_BUFFER, start * vertexSize_, count * vertexSize_, data);
  125. else
  126. glBufferData(GL_ARRAY_BUFFER, count * vertexSize_, data, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  127. }
  128. else
  129. {
  130. ATOMIC_LOGWARNING("Vertex buffer data assignment while device is lost");
  131. dataPending_ = true;
  132. }
  133. }
  134. return true;
  135. }
  136. void* VertexBuffer::Lock(unsigned start, unsigned count, bool discard)
  137. {
  138. if (lockState_ != LOCK_NONE)
  139. {
  140. ATOMIC_LOGERROR("Vertex buffer already locked");
  141. return 0;
  142. }
  143. if (!vertexSize_)
  144. {
  145. ATOMIC_LOGERROR("Vertex elements not defined, can not lock vertex buffer");
  146. return 0;
  147. }
  148. if (start + count > vertexCount_)
  149. {
  150. ATOMIC_LOGERROR("Illegal range for locking vertex buffer");
  151. return 0;
  152. }
  153. if (!count)
  154. return 0;
  155. lockStart_ = start;
  156. lockCount_ = count;
  157. discardLock_ = discard;
  158. if (shadowData_)
  159. {
  160. lockState_ = LOCK_SHADOW;
  161. return shadowData_.Get() + start * vertexSize_;
  162. }
  163. else if (graphics_)
  164. {
  165. lockState_ = LOCK_SCRATCH;
  166. lockScratchData_ = graphics_->ReserveScratchBuffer(count * vertexSize_);
  167. return lockScratchData_;
  168. }
  169. else
  170. return 0;
  171. }
  172. void VertexBuffer::Unlock()
  173. {
  174. switch (lockState_)
  175. {
  176. case LOCK_SHADOW:
  177. SetDataRange(shadowData_.Get() + lockStart_ * vertexSize_, lockStart_, lockCount_, discardLock_);
  178. lockState_ = LOCK_NONE;
  179. break;
  180. case LOCK_SCRATCH:
  181. SetDataRange(lockScratchData_, lockStart_, lockCount_, discardLock_);
  182. if (graphics_)
  183. graphics_->FreeScratchBuffer(lockScratchData_);
  184. lockScratchData_ = 0;
  185. lockState_ = LOCK_NONE;
  186. break;
  187. default:
  188. break;
  189. }
  190. }
  191. bool VertexBuffer::Create()
  192. {
  193. if (!vertexCount_ || !elementMask_)
  194. {
  195. Release();
  196. return true;
  197. }
  198. if (graphics_)
  199. {
  200. if (graphics_->IsDeviceLost())
  201. {
  202. ATOMIC_LOGWARNING("Vertex buffer creation while device is lost");
  203. return true;
  204. }
  205. if (!object_.name_)
  206. glGenBuffers(1, &object_.name_);
  207. if (!object_.name_)
  208. {
  209. ATOMIC_LOGERROR("Failed to create vertex buffer");
  210. return false;
  211. }
  212. graphics_->SetVBO(object_.name_);
  213. glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  214. }
  215. return true;
  216. }
  217. bool VertexBuffer::UpdateToGPU()
  218. {
  219. if (object_.name_ && shadowData_)
  220. return SetData(shadowData_.Get());
  221. else
  222. return false;
  223. }
  224. void* VertexBuffer::MapBuffer(unsigned start, unsigned count, bool discard)
  225. {
  226. // Never called on OpenGL
  227. return 0;
  228. }
  229. void VertexBuffer::UnmapBuffer()
  230. {
  231. // Never called on OpenGL
  232. }
  233. }