1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 29 #include "OgreGLES2HardwareBufferManager.h" 30 31 #if OGRE_NO_GLES3_SUPPORT == 0 32 #include "OgreGLES2HardwareUniformBuffer.h" 33 #include "OgreRoot.h" 34 #include "OgreGLES2RenderSystem.h" 35 36 namespace Ogre { GLES2HardwareUniformBuffer(HardwareBufferManagerBase * mgr,size_t bufferSize,HardwareBuffer::Usage usage,bool useShadowBuffer,const String & name)37 GLES2HardwareUniformBuffer::GLES2HardwareUniformBuffer(HardwareBufferManagerBase* mgr, 38 size_t bufferSize, 39 HardwareBuffer::Usage usage, 40 bool useShadowBuffer, const String& name) 41 : HardwareUniformBuffer(mgr, bufferSize, usage, useShadowBuffer, name) 42 { 43 OGRE_CHECK_GL_ERROR(glGenBuffers(1, &mBufferId)); 44 45 if (!mBufferId) 46 { 47 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 48 "Cannot create GL uniform buffer", 49 "GLES2HardwareUniformBuffer::GLES2HardwareUniformBuffer"); 50 } 51 52 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, mBufferId)); 53 OGRE_CHECK_GL_ERROR(glBufferData(GL_UNIFORM_BUFFER, mSizeInBytes, NULL, 54 GLES2HardwareBufferManager::getGLUsage(usage))); 55 56 // std::cerr << "creating uniform buffer = " << mBufferId << std::endl; 57 } 58 ~GLES2HardwareUniformBuffer()59 GLES2HardwareUniformBuffer::~GLES2HardwareUniformBuffer() 60 { 61 OGRE_CHECK_GL_ERROR(glDeleteBuffers(1, &mBufferId)); 62 } 63 setGLBufferBinding(GLint binding)64 void GLES2HardwareUniformBuffer::setGLBufferBinding(GLint binding) 65 { 66 mBinding = binding; 67 68 // Attach the buffer to the UBO binding 69 OGRE_CHECK_GL_ERROR(glBindBufferBase(GL_UNIFORM_BUFFER, mBinding, mBufferId)); 70 } 71 lockImpl(size_t offset,size_t length,LockOptions options)72 void* GLES2HardwareUniformBuffer::lockImpl(size_t offset, 73 size_t length, 74 LockOptions options) 75 { 76 if (mIsLocked) 77 { 78 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 79 "Invalid attempt to lock a uniform buffer that has already been locked", 80 "GLES2HardwareUniformBuffer::lock"); 81 } 82 83 GLenum access = 0; 84 void* retPtr = 0; 85 86 // Use glMapBuffer 87 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, mBufferId)); 88 89 if (mUsage & HBU_WRITE_ONLY) 90 { 91 access |= GL_MAP_WRITE_BIT; 92 access |= GL_MAP_FLUSH_EXPLICIT_BIT; 93 if(options == HBL_DISCARD) 94 { 95 // Discard the buffer 96 access |= GL_MAP_INVALIDATE_RANGE_BIT; 97 } 98 } 99 else if (options == HBL_READ_ONLY) 100 access |= GL_MAP_READ_BIT; 101 else 102 access |= GL_MAP_READ_BIT | GL_MAP_WRITE_BIT; 103 104 access |= GL_MAP_UNSYNCHRONIZED_BIT; 105 106 void* pBuffer; 107 OGRE_CHECK_GL_ERROR(pBuffer = glMapBufferRange(GL_UNIFORM_BUFFER, offset, length, access)); 108 109 if(pBuffer == 0) 110 { 111 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 112 "Uniform Buffer: Out of memory", 113 "GLES2HardwareUniformBuffer::lock"); 114 } 115 116 // return offsetted 117 retPtr = static_cast<void*>(static_cast<unsigned char*>(pBuffer) + offset); 118 119 mIsLocked = true; 120 return retPtr; 121 } 122 unlockImpl(void)123 void GLES2HardwareUniformBuffer::unlockImpl(void) 124 { 125 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, mBufferId)); 126 127 if (mUsage & HBU_WRITE_ONLY) 128 { 129 OGRE_CHECK_GL_ERROR(glFlushMappedBufferRange(GL_UNIFORM_BUFFER, mLockStart, mLockSize)); 130 } 131 132 GLboolean mapped; 133 OGRE_CHECK_GL_ERROR(mapped = glUnmapBuffer(GL_UNIFORM_BUFFER)); 134 if(!mapped) 135 { 136 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 137 "Buffer data corrupted, please reload", 138 "GLES2HardwareUniformBuffer::unlock"); 139 } 140 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, 0)); 141 142 mIsLocked = false; 143 } 144 readData(size_t offset,size_t length,void * pDest)145 void GLES2HardwareUniformBuffer::readData(size_t offset, size_t length, void* pDest) 146 { 147 // Get data from the real buffer 148 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, mBufferId)); 149 150 OGRE_CHECK_GL_ERROR(glGetBufferPointerv(GL_UNIFORM_BUFFER, GL_BUFFER_MAP_POINTER, &pDest)); 151 } 152 writeData(size_t offset,size_t length,const void * pSource,bool discardWholeBuffer)153 void GLES2HardwareUniformBuffer::writeData(size_t offset, 154 size_t length, 155 const void* pSource, 156 bool discardWholeBuffer) 157 { 158 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, mBufferId)); 159 160 if (offset == 0 && length == mSizeInBytes) 161 { 162 OGRE_CHECK_GL_ERROR(glBufferData(GL_UNIFORM_BUFFER, mSizeInBytes, pSource, 163 GLES2HardwareBufferManager::getGLUsage(mUsage))); 164 } 165 else 166 { 167 if(discardWholeBuffer) 168 { 169 OGRE_CHECK_GL_ERROR(glBufferData(GL_UNIFORM_BUFFER, mSizeInBytes, NULL, 170 GLES2HardwareBufferManager::getGLUsage(mUsage))); 171 } 172 173 OGRE_CHECK_GL_ERROR(glBufferSubData(GL_UNIFORM_BUFFER, offset, length, pSource)); 174 } 175 } 176 copyData(HardwareBuffer & srcBuffer,size_t srcOffset,size_t dstOffset,size_t length,bool discardWholeBuffer)177 void GLES2HardwareUniformBuffer::copyData(HardwareBuffer& srcBuffer, size_t srcOffset, 178 size_t dstOffset, size_t length, bool discardWholeBuffer) 179 { 180 // If the buffer is not in system memory we can use ARB_copy_buffers to do an optimised copy. 181 if (srcBuffer.isSystemMemory()) 182 { 183 HardwareBuffer::copyData(srcBuffer, srcOffset, dstOffset, length, discardWholeBuffer); 184 } 185 else 186 { 187 // Unbind the current buffer 188 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, 0)); 189 190 // Zero out this(destination) buffer 191 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, mBufferId)); 192 OGRE_CHECK_GL_ERROR(glBufferData(GL_UNIFORM_BUFFER, length, 0, GLES2HardwareBufferManager::getGLUsage(mUsage))); 193 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_UNIFORM_BUFFER, 0)); 194 195 // Do it the fast way. 196 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_COPY_READ_BUFFER, static_cast<GLES2HardwareUniformBuffer &>(srcBuffer).getGLBufferId())); 197 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_COPY_WRITE_BUFFER, mBufferId)); 198 199 OGRE_CHECK_GL_ERROR(glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, srcOffset, dstOffset, length)); 200 201 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_COPY_READ_BUFFER, 0)); 202 OGRE_CHECK_GL_ERROR(glBindBuffer(GL_COPY_WRITE_BUFFER, 0)); 203 } 204 } 205 } 206 #endif 207