void* GLES2HardwareVertexBuffer::lockImpl(size_t offset, size_t length, LockOptions options) { if (mIsLocked) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Invalid attempt to lock an index buffer that has already been locked", "GLES2HardwareVertexBuffer::lock"); } GLenum access = 0; // Use glMapBuffer static_cast<GLES2HardwareBufferManagerBase*>(mMgr)->getStateCacheManager()->bindGLBuffer(GL_ARRAY_BUFFER, mBufferId); void* pBuffer; #if OGRE_NO_GLES3_SUPPORT == 0 || defined(GL_EXT_map_buffer_range) if (mUsage & HBU_WRITE_ONLY) { access = GL_MAP_WRITE_BIT_EXT; access |= GL_MAP_FLUSH_EXPLICIT_BIT_EXT; if(options == HBL_DISCARD || options == HBL_NO_OVERWRITE) { // Discard the buffer access |= GL_MAP_INVALIDATE_RANGE_BIT_EXT; } access |= GL_MAP_UNSYNCHRONIZED_BIT_EXT; } else if (options == HBL_READ_ONLY) access = GL_MAP_READ_BIT_EXT; else access = GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT; OGRE_CHECK_GL_ERROR(pBuffer = glMapBufferRangeEXT(GL_ARRAY_BUFFER, offset, length, access)); #else if(options == HBL_DISCARD || options == HBL_NO_OVERWRITE) { // Discard the buffer OGRE_CHECK_GL_ERROR(glBufferData(GL_ARRAY_BUFFER, mSizeInBytes, NULL, GLES2HardwareBufferManager::getGLUsage(mUsage))); } if (mUsage & HBU_WRITE_ONLY) access = GL_WRITE_ONLY_OES; OGRE_CHECK_GL_ERROR(pBuffer = glMapBufferOES(GL_ARRAY_BUFFER, access)); #endif if(pBuffer == 0) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Vertex Buffer: Out of memory", "GLES2HardwareVertexBuffer::lock"); } // return offsetted void* retPtr = static_cast<void*>( static_cast<unsigned char*>(pBuffer) + offset); mIsLocked = true; return retPtr; }
void* GLESHardwareVertexBuffer::lockImpl(size_t offset, size_t length, LockOptions options) { GLenum access = 0; if (mIsLocked) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Invalid attempt to lock an index buffer that has already been locked", "GLESHardwareVertexBuffer::lock"); } void* retPtr = 0; GLESHardwareBufferManager* glBufManager = static_cast<GLESHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr()); // Try to use scratch buffers for smaller buffers if (length < glBufManager->getGLMapBufferThreshold()) { // if this fails, we fall back on mapping retPtr = glBufManager->allocateScratch((uint32)length); if (retPtr) { mLockedToScratch = true; mScratchOffset = offset; mScratchSize = length; mScratchPtr = retPtr; mScratchUploadOnUnlock = (options != HBL_READ_ONLY); if (options != HBL_DISCARD) { // have to read back the data before returning the pointer readData(offset, length, retPtr); } } } else { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Invalid Buffer lockSize", "GLESHardwareVertexBuffer::lock"); } #if GL_OES_mapbuffer if (!retPtr) { // Use glMapBuffer glBindBuffer( GL_ARRAY_BUFFER, mBufferId ); // Use glMapBuffer if(options == HBL_DISCARD) { // Discard the buffer glBufferData(GL_ARRAY_BUFFER, mSizeInBytes, NULL, GLESHardwareBufferManager::getGLUsage(mUsage)); } if (mUsage & HBU_WRITE_ONLY) access = GL_WRITE_ONLY_OES; void* pBuffer = glMapBufferOES( GL_ARRAY_BUFFER, access); if(pBuffer == 0) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Vertex Buffer: Out of memory", "GLESHardwareVertexBuffer::lock"); } // return offsetted retPtr = static_cast<void*>( static_cast<unsigned char*>(pBuffer) + offset); mLockedToScratch = false; } #endif mIsLocked = true; return retPtr; }
bool AppCore::render() { #if !DISCARD_SKYBOX // Try to load textures if not already completed if (_staticTextureCompleteCount <= 6) loadStaticTextureIfAvailable(); #endif APIFactory::GetInstance().lock(OPENGL_LOCK); double timestamp = APIFactory::GetInstance().getTimeInMS(); #if !(RENDER_OCTREE_DEBUG_VOXELS || USE_STATIC_POINT_CLOUD) if ( !(_currentCameraParameterRequest & 1) && (timestamp - _lastCameraParameterChangeTimestamp > WVS_RELOAD_DELAY[0])) { // Request 1/4 of screen resolution from WVS requestPointCloudForCurrentView(4); _currentCameraParameterRequest |= 1; } else if ( !(_currentCameraParameterRequest & 2) && (timestamp - _lastCameraParameterChangeTimestamp > WVS_RELOAD_DELAY[1])) { // Request full screen resolution from WVS requestPointCloudForCurrentView(1); _currentCameraParameterRequest |= 3; } #endif if (_isUserInputMode) _renderingRequired = true; if (_renderQuality < 1.0f) _renderingRequired = true; #if !(RENDER_OCTREE_DEBUG_VOXELS || USE_STATIC_POINT_CLOUD) if (_isNewDataAvialable) { _renderingRequired = true; _isNewDataAvialable = false; } #endif if (!_renderingRequired) { APIFactory::GetInstance().unlock(OPENGL_LOCK); APIFactory::GetInstance().processUserInterfaceEvents(); return false; } _renderingRequired = false; // Updates the view frustum that is used for culling etc. based on the current // camera parameters _viewFrustum->updateCameraViewParameterCache(); // Clear context glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #if !DISCARD_SKYBOX // Render Skybox and ground plane if (_staticTextureCompleteCount > 0) { glUseProgram(_textureShaderProgram.handle); glUniformMatrix4fv( _textureShaderProgram.uniforms[SHADER_UNIFORM_VIEW_PROJECTION_MATRIX], 1, GL_FALSE, _viewFrustum->getViewProjectionMatrixCachePtr()->f); MATRIX model; MatrixTranslation(model, _viewFrustum->getCameraPostionCachePtr()->x, _viewFrustum->getCameraPostionCachePtr()->y, _viewFrustum->getCameraPostionCachePtr()->z); glUniformMatrix4fv( _textureShaderProgram.uniforms[SHADER_UNIFORM_MODEL_MATRIX], 1, GL_FALSE, model.f); _skybox->render(); } #endif // Render points glUseProgram(_pointShaderProgram.handle); glUniform3fv( _pointShaderProgram.uniforms[POINT_SHADER_UNIFORM_REGION_ORIGIN], OCTREE_LEAF_LEVEL + 1, _octree->getRegionOrginArray()); glUniform1fv( _pointShaderProgram.uniforms[POINT_SHADER_UNIFORM_VOXEL_INCIRCLE_DIAMETER], OCTREE_LEAF_LEVEL + 1, _octree->getVoxelIncircleDiameterArray()); glUniform1fv( _pointShaderProgram.uniforms[POINT_SHADER_UNIFORM_NODE_INCIRCLE_DIAMETER], OCTREE_LEAF_LEVEL + 1, _octree->getNodeIncircleDiameterArray()); glUniform1fv( _pointShaderProgram.uniforms[POINT_SHADER_UNIFORM_VOXEL_SCREENSIZE_CIRCUMCIRCLE_RADIUS], OCTREE_LEAF_LEVEL + 1, _voxelScreensizeCircumcircleRadius); // Set camera position (necessary for backface culling) glUniform3fv( _pointShaderProgram.uniforms[POINT_SHADER_UNIFORM_CAMERA_POSITION], 1, (GLfloat*)(_viewFrustum->getCameraPostionCachePtr())); glUniformMatrix4fv( _pointShaderProgram.uniforms[POINT_SHADER_UNIFORM_PROJECTION_MATRIX], 1, GL_FALSE, _viewFrustum->getProjectionMatrixCachePtr()->f); glUniformMatrix4fv( _pointShaderProgram.uniforms[POINT_SHADER_UNIFORM_VIEW_MATRIX], 1, GL_FALSE, _viewFrustum->getViewMatrixCachePtr()->f); #if COMPACT_NODE_REGION_ENCODING const uint32_t regionVoxelFactor = 1; const uint8_t regionLevelStride = 4; const uint32_t regionLevelDataType = GL_UNSIGNED_BYTE; #else const uint32_t regionVoxelFactor = 2; const uint8_t regionLevelStride = 8; const uint32_t regionLevelDataType = GL_UNSIGNED_SHORT; #endif #if DIRECT_VBO #if DIRECT_VBO_DOUBLE_BUFFERED if (bufferID == 0) bufferID = 1; else bufferID = 0; #endif glBindBuffer(GL_ARRAY_BUFFER, _dataVBO[bufferID]); uint32_t* const gpuBuffer = (uint32_t*)glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); uint32_t* const regionLevelBuffer = gpuBuffer; uint32_t* const voxelBuffer = gpuBuffer + GPU_MAX_POINTS * regionVoxelFactor; glVertexAttribPointer( POINT_SHADER_ATTRIBUTE_DATA1, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, (void *)(GPU_MAX_POINTS * regionLevelStride)); glVertexAttribPointer( POINT_SHADER_ATTRIBUTE_DATA2, 4, regionLevelDataType, GL_FALSE, 0, 0); glEnableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA1); glEnableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA2); // Traverse octree, copy points into buffer and call rendering callback _octree->copyPointsToBuffer( _renderQuality, !_isInteractiveMode, regionLevelBuffer, voxelBuffer, &_pointsToRenderCount, &_renderingRequired); glDisableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA1); glDisableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA2); glUnmapBufferOES(GL_ARRAY_BUFFER); #elif NO_VBO uint32_t* const regionLevelBuffer = _gpuBuffer; uint32_t* const voxelBuffer = _gpuBuffer + GPU_MAX_POINTS * regionVoxelFactor; glVertexAttribPointer( POINT_SHADER_ATTRIBUTE_DATA1, 4, GL_UNSIGNED_BYTE, GL_FALSE, 4, voxelBuffer); glVertexAttribPointer( POINT_SHADER_ATTRIBUTE_DATA2, 4, regionLevelDataType, GL_FALSE, regionLevelStride, regionLevelBuffer); glEnableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA1); glEnableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA2); // Traverse octree, copy points into buffer and call rendering callback _octree->copyPointsToBuffer( _renderQuality, !_isInteractiveMode, regionLevelBuffer, voxelBuffer, &_pointsToRenderCount, &_renderingRequired); glDisableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA1); glDisableVertexAttribArray(POINT_SHADER_ATTRIBUTE_DATA2); #endif #ifdef OPENGL_ES const GLenum discard_attachments[] = { GL_DEPTH_ATTACHMENT }; glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discard_attachments); #endif if (_renderingRequired & Octree::OCTREE_RENDERING_CANCELED) { APIFactory::GetInstance().unlock(OPENGL_LOCK); //TODO: In case we overestimate the render quality by far this becomes a stupid loop _octree->estimateInteractiveRenderQuality(&_renderQuality, OCTREE_INTERACTIVE_RENDERING_POINT_THRESHOLD); return false; } #if BENCHMARK_1_MILLION if (_pointsToRenderCount >= 1000000) { _renderingRequired = true; double time = APIFactory::GetInstance().getTimeInMS(); printf("%f\n", time - _lastFrame); _lastFrame = time; } #endif if (_isUserInputMode || ((timestamp - _lastCameraParameterChangeTimestamp) < 500)) { // Within 500ms we consider any input as movement double_t renderingTimeInMS = APIFactory::GetInstance().getTimeInMS() - timestamp; if (renderingTimeInMS > (1000.0 / MINIMUM_FRAMERATE)) { // Time to render last frame took longer than target framerate. // Lower render quality to speed up framerate. _renderQuality -= RENDER_QUALITY_FINE_ADJUSTMENT; _nodeRestoreQuota = 0; } else if (renderingTimeInMS < (1000.0 / MAXIMUM_FRAMERATE)) { _renderQuality += RENDER_QUALITY_FINE_ADJUSTMENT; _nodeRestoreQuota = 32; } _renderingRequired = true; } else { // No movement with in the last 500ms. Increase render quality _renderQuality += RENDER_QUALITY_COARSE_ADJUSTMENT; _isInteractiveMode = false; } // Check range of render quality if (_renderQuality > 1.0f) _renderQuality = 1.0f; else if (_renderQuality < RENDER_QUALITY_FINE_ADJUSTMENT) _renderQuality = RENDER_QUALITY_FINE_ADJUSTMENT; APIFactory::GetInstance().unlock(OPENGL_LOCK); return true; }
void* GLESHardwareIndexBuffer::lockImpl(size_t offset, size_t length, LockOptions options) { if(mIsLocked) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Invalid attempt to lock an index buffer that has already been locked", "GLESHardwareIndexBuffer::lock"); } void* retPtr = 0; GLenum access = 0; GLESHardwareBufferManager* glBufManager = static_cast<GLESHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr()); if(length < glBufManager->getGLMapBufferThreshold()) { retPtr = glBufManager->allocateScratch((uint32)length); if (retPtr) { mLockedToScratch = true; mScratchOffset = offset; mScratchSize = length; mScratchPtr = retPtr; mScratchUploadOnUnlock = (options != HBL_READ_ONLY); if (options != HBL_DISCARD) { readData(offset, length, retPtr); } } } else { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Invalid Buffer lockSize", "GLESHardwareIndexBuffer::lock"); } #if defined(GL_GLEXT_PROTOTYPES) if (!retPtr) { glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mBufferId ); // Use glMapBuffer if(options == HBL_DISCARD) { // Discard the buffer glBufferData(GL_ELEMENT_ARRAY_BUFFER, mSizeInBytes, NULL, GLESHardwareBufferManager::getGLUsage(mUsage)); } if (mUsage & HBU_WRITE_ONLY) access = GL_WRITE_ONLY_OES; void* pBuffer = glMapBufferOES( GL_ELEMENT_ARRAY_BUFFER, access ); if(pBuffer == 0) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Index Buffer: Out of memory", "GLESHardwareIndexBuffer::lock"); } // return offsetted retPtr = static_cast<void*>(static_cast<unsigned char*>(pBuffer) + offset); mLockedToScratch = false; } mIsLocked = true; #endif return retPtr; }
void* AEVAMap(AEVA* va, unsigned int elementCount, int writereadmode){ unsigned int writereadmodeOGL = 0; switch (writereadmode) { case AEVAMapFlagWritable: #ifdef AEiOS writereadmodeOGL=GL_WRITE_ONLY_OES; #else writereadmodeOGL=GL_WRITE_ONLY; #endif break; case AEVAMapFlagReadable: #ifdef AEiOS return NULL; #else writereadmodeOGL=GL_READ_ONLY; #endif break; default: #ifdef AEiOS return NULL; #else writereadmodeOGL=GL_READ_WRITE; #endif break; } #ifdef AEiOS if(va->format.indexType==AEVAFormatIndexType32Bit) va->format.indexType=AEVAFormatIndexType16Bit; #endif unsigned int arrayType=va->format.indexType?GL_ELEMENT_ARRAY_BUFFER:GL_ARRAY_BUFFER; //if(sizeof(GLfloat) not_eq sizeof(char[4]) and sizeof(GLuint)!=sizeof(char[4])) AEError("A GLfloat or GLuint is not equal to 4 bytes on your system! This is very, very, bad."); if(va->elementCount and va->elementCount not_eq elementCount) return NULL; //if(sizeof(AEVec3) not_eq 3*sizeof(float)) AEError("AEVec3 is padded, this is bad!"); if(va->elementCount==0){ va->elementCount=elementCount; #ifdef AEiOS if(va->format.storageType==AEVAFormatStorageTypeStream) va->format.storageType=0; #endif if(va->format.storageType){ glGenBuffers(1, &va->data.vbo); //glBindBuffer(GL_ARRAY_BUFFER, va->data.vbo); unsigned int vbotype=0; switch(va->format.storageType){ #ifndef AEiOS case AEVAFormatStorageTypeStream: vbotype=GL_STREAM_DRAW; break; #endif case AEVAFormatStorageTypeDynamic: vbotype=GL_DYNAMIC_DRAW; break; case AEVAFormatStorageTypeStatic: vbotype=GL_STATIC_DRAW; break; } glBindBuffer(arrayType, va->data.vbo); glBufferData(arrayType, elementCount * AEVAFormatByteSize(& va->format), NULL,vbotype); #ifdef AEiOS void* data = glMapBufferOES(arrayType, writereadmodeOGL); #else void* data = glMapBuffer(arrayType, writereadmodeOGL); #endif return data; } else va->data.pointer=malloc(elementCount * AEVAFormatByteSize(& va->format)); } if(va->format.storageType){ glBindBuffer(arrayType, va->data.vbo); #ifdef AEiOS return glMapBufferOES(arrayType, writereadmodeOGL); #else return glMapBuffer(arrayType, writereadmodeOGL); #endif } return va->data.pointer; }