void Gui_Init() { Gui_InitBars(); Gui_InitNotifier(); qglGenBuffersARB(1, &crosshairBuffer); qglGenBuffersARB(1, &backgroundBuffer); qglGenBuffersARB(1, &rectBuffer); qglGenTextures(1, &load_screen_tex); Gui_FillCrosshairBuffer(); Gui_FillBackgroundBuffer(); main_inventory_manager = new gui_InventoryManager(); }
/* ======================== idJointBuffer::AllocBufferObject ======================== */ bool idJointBuffer::AllocBufferObject( const float * joints, int numAllocJoints ) { assert( apiObject == NULL ); assert_16_byte_aligned( joints ); if ( numAllocJoints <= 0 ) { idLib::Error( "idJointBuffer::AllocBufferObject: joints = %i", numAllocJoints ); } numJoints = numAllocJoints; bool allocationFailed = false; const int numBytes = GetAllocedSize(); GLuint buffer = 0; qglGenBuffersARB( 1, &buffer ); qglBindBufferARB( GL_UNIFORM_BUFFER, buffer ); qglBufferDataARB( GL_UNIFORM_BUFFER, numBytes, NULL, GL_STREAM_DRAW_ARB ); qglBindBufferARB( GL_UNIFORM_BUFFER, 0); apiObject = reinterpret_cast< void * >( buffer ); if ( r_showBuffers.GetBool() ) { idLib::Printf( "joint buffer alloc %p, api %p (%i joints)\n", this, GetAPIObject(), GetNumJoints() ); } // copy the data if ( joints != NULL ) { Update( joints, numAllocJoints ); } return !allocationFailed; }
void CDynamicBSP::Reset(struct anim_seq_s *seq) { if(m_vbo == 0) { qglGenBuffersARB(1, &m_vbo); } switch(m_realloc_state) { case NEED_REALLOC_TREE_BUFF: { uint32_t new_buffer_size = m_tree_buffer_size * 1.5; uint8_t *new_buffer = (uint8_t*)malloc(new_buffer_size * sizeof(uint8_t)); if(new_buffer != NULL) { free(m_tree_buffer); m_tree_buffer = new_buffer; m_tree_buffer_size = new_buffer_size; } } break; case NEED_REALLOC_TEMP_BUFF: { uint32_t new_buffer_size = m_temp_buffer_size * 1.5; uint8_t *new_buffer = (uint8_t*)malloc(new_buffer_size * sizeof(uint8_t)); if(new_buffer != NULL) { free(m_temp_buffer); m_temp_buffer = new_buffer; m_temp_buffer_size = new_buffer_size; } } break; case NEED_REALLOC_VERTEX_BUFF: { uint32_t new_buffer_size = m_vertex_buffer_size * 1.5; vertex_p new_buffer = (vertex_p)malloc(new_buffer_size * sizeof(vertex_t)); if(new_buffer != NULL) { free(m_vertex_buffer); m_vertex_buffer = new_buffer; m_vertex_buffer_size = new_buffer_size; } } break; }; m_anim_seq = seq; m_temp_allocated = 0; m_tree_allocated = 0; m_vertex_allocated = 0; m_realloc_state = 0; m_input_polygons = 0; m_added_polygons = 0; m_root = this->CreateBSPNode(); }
/* ============ R_CreateVBO ============ */ VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage) { VBO_t *vbo; int glUsage; switch (usage) { case VBO_USAGE_STATIC: glUsage = GL_STATIC_DRAW_ARB; break; case VBO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW_ARB; break; default: Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); return NULL; } if(strlen(name) >= MAX_QPATH) { ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long\n", name); } if ( tr.numVBOs == MAX_VBOS ) { ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit\n"); } // make sure the render thread is stopped R_SyncRenderThread(); vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); tr.numVBOs++; memset(vbo, 0, sizeof(*vbo)); Q_strncpyz(vbo->name, name, sizeof(vbo->name)); vbo->vertexesSize = vertexesSize; qglGenBuffersARB(1, &vbo->vertexesVBO); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glState.currentVBO = NULL; GL_CheckErrors(); return vbo; }
/* ============ R_CreateIBO ============ */ IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage) { IBO_t *ibo; int glUsage; switch (usage) { case VBO_USAGE_STATIC: glUsage = GL_STATIC_DRAW_ARB; break; case VBO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW_ARB; break; default: Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); return NULL; } if(strlen(name) >= MAX_QPATH) { ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long", name); } if ( tr.numIBOs == MAX_IBOS ) { ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit"); } R_IssuePendingRenderCommands(); ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); tr.numIBOs++; Q_strncpyz(ibo->name, name, sizeof(ibo->name)); ibo->indexesSize = indexesSize; qglGenBuffersARB(1, &ibo->indexesVBO); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glState.currentIBO = NULL; GL_CheckErrors(); return ibo; }
/* ======================== idIndexBuffer::AllocBufferObject ======================== */ bool idIndexBuffer::AllocBufferObject( const void * data, int allocSize ) { assert( apiObject == NULL ); assert_16_byte_aligned( data ); if ( allocSize <= 0 ) { idLib::Error( "idIndexBuffer::AllocBufferObject: allocSize = %i", allocSize ); } size = allocSize; bool allocationFailed = false; int numBytes = GetAllocedSize(); // clear out any previous error qglGetError(); GLuint bufferObject = 0xFFFF; qglGenBuffersARB( 1, & bufferObject ); if ( bufferObject == 0xFFFF ) { GLenum error = qglGetError(); idLib::FatalError( "idIndexBuffer::AllocBufferObject: failed - GL_Error %d", error ); } qglBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, bufferObject ); // these are rewritten every frame qglBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, numBytes, NULL, bufferUsage ); apiObject = reinterpret_cast< void * >( bufferObject ); GLenum err = qglGetError(); if ( err == GL_OUT_OF_MEMORY ) { idLib::Warning( "idIndexBuffer:AllocBufferObject: allocation failed" ); allocationFailed = true; } if ( r_showBuffers.GetBool() ) { idLib::Printf( "index buffer alloc %p, api %p (%i bytes)\n", this, GetAPIObject(), GetSize() ); } // copy the data if ( data != NULL ) { Update( data, allocSize ); } return !allocationFailed; }
/* ============ R_CreateVBO2 ============ */ VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts, unsigned int stateBits, vboUsage_t usage) { VBO_t *vbo; int i; byte *data; int dataSize; int dataOfs; int glUsage; switch (usage) { case VBO_USAGE_STATIC: glUsage = GL_STATIC_DRAW_ARB; break; case VBO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW_ARB; break; default: Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); return NULL; } if(!numVertexes) return NULL; if(strlen(name) >= MAX_QPATH) { ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long", name); } if ( tr.numVBOs == MAX_VBOS ) { ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit"); } R_IssuePendingRenderCommands(); vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); tr.numVBOs++; memset(vbo, 0, sizeof(*vbo)); Q_strncpyz(vbo->name, name, sizeof(vbo->name)); if (usage == VBO_USAGE_STATIC) { // since these vertex attributes are never altered, interleave them vbo->ofs_xyz = 0; dataSize = sizeof(verts[0].xyz); if(stateBits & ATTR_NORMAL) { vbo->ofs_normal = dataSize; dataSize += sizeof(uint8_t) * 4; } #ifdef USE_VERT_TANGENT_SPACE if(stateBits & ATTR_TANGENT) { vbo->ofs_tangent = dataSize; dataSize += sizeof(uint8_t) * 4; } #endif if(stateBits & ATTR_TEXCOORD) { vbo->ofs_st = dataSize; dataSize += sizeof(verts[0].st); } if(stateBits & ATTR_LIGHTCOORD) { vbo->ofs_lightmap = dataSize; dataSize += sizeof(verts[0].lightmap); } if(stateBits & ATTR_COLOR) { vbo->ofs_vertexcolor = dataSize; dataSize += sizeof(verts[0].vertexColors); } if(stateBits & ATTR_LIGHTDIRECTION) { vbo->ofs_lightdir = dataSize; dataSize += sizeof(verts[0].lightdir); } vbo->stride_xyz = dataSize; vbo->stride_normal = dataSize; #ifdef USE_VERT_TANGENT_SPACE vbo->stride_tangent = dataSize; #endif vbo->stride_st = dataSize; vbo->stride_lightmap = dataSize; vbo->stride_vertexcolor = dataSize; vbo->stride_lightdir = dataSize; // create VBO dataSize *= numVertexes; data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; //ri.Printf(PRINT_ALL, "CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); for (i = 0; i < numVertexes; i++) { // xyz memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); dataOfs += sizeof(verts[i].xyz); // normal if(stateBits & ATTR_NORMAL) { uint8_t *p = data + dataOfs; p[0] = (uint8_t)(verts[i].normal[0] * 127.5f + 128.0f); p[1] = (uint8_t)(verts[i].normal[1] * 127.5f + 128.0f); p[2] = (uint8_t)(verts[i].normal[2] * 127.5f + 128.0f); p[3] = 0; dataOfs += sizeof(uint8_t) * 4; } #ifdef USE_VERT_TANGENT_SPACE // tangent if(stateBits & ATTR_TANGENT) { vec3_t nxt; uint8_t *p = data + dataOfs; CrossProduct(verts[i].normal, verts[i].tangent, nxt); p[0] = (uint8_t)(verts[i].tangent[0] * 127.5f + 128.0f); p[1] = (uint8_t)(verts[i].tangent[1] * 127.5f + 128.0f); p[2] = (uint8_t)(verts[i].tangent[2] * 127.5f + 128.0f); p[3] = (uint8_t)(verts[i].tangent[3] * 127.5f + 128.0f); dataOfs += sizeof(uint8_t) * 4; } #endif // vertex texcoords if(stateBits & ATTR_TEXCOORD) { memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); dataOfs += sizeof(verts[i].st); } // feed vertex lightmap texcoords if(stateBits & ATTR_LIGHTCOORD) { memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); dataOfs += sizeof(verts[i].lightmap); } // feed vertex colors if(stateBits & ATTR_COLOR) { memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); dataOfs += sizeof(verts[i].vertexColors); } // feed vertex light directions if(stateBits & ATTR_LIGHTDIRECTION) { memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir)); dataOfs += sizeof(verts[i].lightdir); } } } else { // since these vertex attributes may be changed, put them in flat arrays dataSize = sizeof(verts[0].xyz); if(stateBits & ATTR_NORMAL) { dataSize += sizeof(uint8_t) * 4; } #ifdef USE_VERT_TANGENT_SPACE if(stateBits & ATTR_TANGENT) { dataSize += sizeof(uint8_t) * 4; } #endif if(stateBits & ATTR_TEXCOORD) { dataSize += sizeof(verts[0].st); } if(stateBits & ATTR_LIGHTCOORD) { dataSize += sizeof(verts[0].lightmap); } if(stateBits & ATTR_COLOR) { dataSize += sizeof(verts[0].vertexColors); } if(stateBits & ATTR_LIGHTDIRECTION) { dataSize += sizeof(verts[0].lightdir); } // create VBO dataSize *= numVertexes; data = ri.Hunk_AllocateTempMemory(dataSize); dataOfs = 0; vbo->ofs_xyz = 0; vbo->ofs_normal = 0; #ifdef USE_VERT_TANGENT_SPACE vbo->ofs_tangent = 0; #endif vbo->ofs_st = 0; vbo->ofs_lightmap = 0; vbo->ofs_vertexcolor = 0; vbo->ofs_lightdir = 0; vbo->stride_xyz = sizeof(verts[0].xyz); vbo->stride_normal = sizeof(uint8_t) * 4; #ifdef USE_VERT_TANGENT_SPACE vbo->stride_tangent = sizeof(uint8_t) * 4; #endif vbo->stride_vertexcolor = sizeof(verts[0].vertexColors); vbo->stride_st = sizeof(verts[0].st); vbo->stride_lightmap = sizeof(verts[0].lightmap); vbo->stride_lightdir = sizeof(verts[0].lightdir); //ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); // xyz for (i = 0; i < numVertexes; i++) { memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); dataOfs += sizeof(verts[i].xyz); } // normal if(stateBits & ATTR_NORMAL) { vbo->ofs_normal = dataOfs; for (i = 0; i < numVertexes; i++) { uint8_t *p = data + dataOfs; p[0] = (uint8_t)(verts[i].normal[0] * 127.5f + 128.0f); p[1] = (uint8_t)(verts[i].normal[1] * 127.5f + 128.0f); p[2] = (uint8_t)(verts[i].normal[2] * 127.5f + 128.0f); p[3] = 0; dataOfs += sizeof(uint8_t) * 4; } } #ifdef USE_VERT_TANGENT_SPACE // tangent if(stateBits & ATTR_TANGENT) { vbo->ofs_tangent = dataOfs; for (i = 0; i < numVertexes; i++) { vec3_t nxt; uint8_t *p = data + dataOfs; CrossProduct(verts[i].normal, verts[i].tangent, nxt); p[0] = (uint8_t)(verts[i].tangent[0] * 127.5f + 128.0f); p[1] = (uint8_t)(verts[i].tangent[1] * 127.5f + 128.0f); p[2] = (uint8_t)(verts[i].tangent[2] * 127.5f + 128.0f); p[3] = (uint8_t)(verts[i].tangent[3] * 127.5f + 128.0f); dataOfs += sizeof(uint8_t) * 4; } } #endif // vertex texcoords if(stateBits & ATTR_TEXCOORD) { vbo->ofs_st = dataOfs; for (i = 0; i < numVertexes; i++) { memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); dataOfs += sizeof(verts[i].st); } } // feed vertex lightmap texcoords if(stateBits & ATTR_LIGHTCOORD) { vbo->ofs_lightmap = dataOfs; for (i = 0; i < numVertexes; i++) { memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); dataOfs += sizeof(verts[i].lightmap); } } // feed vertex colors if(stateBits & ATTR_COLOR) { vbo->ofs_vertexcolor = dataOfs; for (i = 0; i < numVertexes; i++) { memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); dataOfs += sizeof(verts[i].vertexColors); } } // feed vertex lightdirs if(stateBits & ATTR_LIGHTDIRECTION) { vbo->ofs_lightdir = dataOfs; for (i = 0; i < numVertexes; i++) { memcpy(data + dataOfs, &verts[i].lightdir, sizeof(verts[i].lightdir)); dataOfs += sizeof(verts[i].lightdir); } } } vbo->vertexesSize = dataSize; qglGenBuffersARB(1, &vbo->vertexesVBO); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glState.currentVBO = NULL; GL_CheckErrors(); ri.Hunk_FreeTempMemory(data); return vbo; }
/* * R_CreateMeshVBO * * Create two static buffer objects: vertex buffer and elements buffer, the real * data is uploaded by calling R_UploadVBOVertexData and R_UploadVBOElemData. * * Tag allows vertex buffer objects to be grouped and released simultaneously. */ mesh_vbo_t *R_CreateMeshVBO( void *owner, int numVerts, int numElems, int numInstances, vattribmask_t vattribs, vbo_tag_t tag, vattribmask_t halfFloatVattribs ) { int i; size_t size; GLuint vbo_id; vbohandle_t *vboh = NULL; mesh_vbo_t *vbo = NULL; GLenum array_usage = VBO_ARRAY_USAGE_FOR_TAG(tag); GLenum elem_usage = VBO_ELEM_USAGE_FOR_TAG(tag); size_t vertexSize; vattribbit_t lmattrbit; if( !glConfig.ext.vertex_buffer_object ) return NULL; if( !r_free_vbohandles ) return NULL; if( !glConfig.ext.half_float_vertex ) { halfFloatVattribs = 0; } else { if( !(halfFloatVattribs & VATTRIB_POSITION_BIT) ) { halfFloatVattribs &= ~(VATTRIB_AUTOSPRITE_BIT); } halfFloatVattribs &= ~VATTRIB_COLORS_BITS; halfFloatVattribs &= ~VATTRIB_BONES_BITS; // TODO: convert quaternion component of instance_t to half-float // when uploading instances data halfFloatVattribs &= ~VATTRIB_INSTANCES_BITS; } vboh = r_free_vbohandles; vbo = &r_mesh_vbo[vboh->index]; memset( vbo, 0, sizeof( *vbo ) ); // vertex data vertexSize = 0; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_POSITION_BIT, halfFloatVattribs) * 4; // normals data if( vattribs & VATTRIB_NORMAL_BIT ) { assert( !(vertexSize & 3) ); vbo->normalsOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_NORMAL_BIT, halfFloatVattribs) * 4; } // s-vectors (tangent vectors) if( vattribs & VATTRIB_SVECTOR_BIT ) { assert( !(vertexSize & 3) ); vbo->sVectorsOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_SVECTOR_BIT, halfFloatVattribs) * 4; } // texture coordinates if( vattribs & VATTRIB_TEXCOORDS_BIT ) { assert( !(vertexSize & 3) ); vbo->stOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_TEXCOORDS_BIT, halfFloatVattribs) * 2; } // lightmap texture coordinates lmattrbit = VATTRIB_LMCOORDS0_BIT; for( i = 0; i < MAX_LIGHTMAPS/2; i++ ) { if( !(vattribs & lmattrbit) ) { break; } assert( !(vertexSize & 3) ); vbo->lmstOffset[i] = vertexSize; vbo->lmstSize[i] = vattribs & VATTRIB_LMCOORDS0_BIT<<1 ? 4 : 2; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_LMCOORDS0_BIT, halfFloatVattribs) * vbo->lmstSize[i]; lmattrbit = ( vattribbit_t )( ( vattribmask_t )lmattrbit << 2 ); } // vertex colors if( vattribs & VATTRIB_COLOR0_BIT ) { assert( !(vertexSize & 3) ); vbo->colorsOffset[0] = vertexSize; vertexSize += sizeof( int ); } // bones data for skeletal animation if( (vattribs & VATTRIB_BONES_BITS) == VATTRIB_BONES_BITS ) { assert( SKM_MAX_WEIGHTS == 4 ); assert( !(vertexSize & 3) ); vbo->bonesIndicesOffset = vertexSize; vertexSize += sizeof( int ); assert( !(vertexSize & 3) ); vbo->bonesWeightsOffset = vertexSize; vertexSize += sizeof( int ); } // autosprites // FIXME: autosprite2 requires waaaay too much data for such a trivial // transformation.. if( (vattribs & VATTRIB_AUTOSPRITE_BIT) == VATTRIB_AUTOSPRITE_BIT ) { assert( !(vertexSize & 3) ); vbo->spritePointsOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_AUTOSPRITE_BIT, halfFloatVattribs) * 4; } size = vertexSize * numVerts; // instances data if( ( (vattribs & VATTRIB_INSTANCES_BITS) == VATTRIB_INSTANCES_BITS ) && numInstances && glConfig.ext.instanced_arrays ) { assert( !(vertexSize & 3) ); vbo->instancesOffset = size; size += numInstances * sizeof( GLfloat ) * 8; } // pre-allocate vertex buffer vbo_id = 0; qglGenBuffersARB( 1, &vbo_id ); if( !vbo_id ) goto error; vbo->vertexId = vbo_id; RB_BindArrayBuffer( vbo->vertexId ); qglBufferDataARB( GL_ARRAY_BUFFER_ARB, size, NULL, array_usage ); if( qglGetError () == GL_OUT_OF_MEMORY ) goto error; vbo->arrayBufferSize = size; // pre-allocate elements buffer vbo_id = 0; qglGenBuffersARB( 1, &vbo_id ); if( !vbo_id ) goto error; vbo->elemId = vbo_id; size = numElems * sizeof( elem_t ); RB_BindElementArrayBuffer( vbo->elemId ); qglBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, size, NULL, elem_usage ); if( qglGetError () == GL_OUT_OF_MEMORY ) goto error; vbo->elemBufferSize = size; r_free_vbohandles = vboh->next; // link to the list of active vbo handles vboh->prev = &r_vbohandles_headnode; vboh->next = r_vbohandles_headnode.next; vboh->next->prev = vboh; vboh->prev->next = vboh; r_num_active_vbos++; vbo->registrationSequence = rsh.registrationSequence; vbo->vertexSize = vertexSize; vbo->numVerts = numVerts; vbo->numElems = numElems; vbo->owner = owner; vbo->index = vboh->index + 1; vbo->tag = tag; vbo->halfFloatAttribs = halfFloatVattribs; return vbo; error: if( vbo ) R_ReleaseMeshVBO( vbo ); RB_BindArrayBuffer( 0 ); RB_BindElementArrayBuffer( 0 ); return NULL; }
/* =========== idVertexCache::Alloc =========== */ void idVertexCache::Alloc(void *data, int size, vertCache_t **buffer, bool indexBuffer) { vertCache_t *block; if (size <= 0) { common->Error("idVertexCache::Alloc: size = %i\n", size); } // if we can't find anything, it will be NULL *buffer = NULL; // if we don't have any remaining unused headers, allocate some more if (freeStaticHeaders.next == &freeStaticHeaders) { for (int i = 0; i < EXPAND_HEADERS; i++) { block = headerAllocator.Alloc(); block->next = freeStaticHeaders.next; block->prev = &freeStaticHeaders; block->next->prev = block; block->prev->next = block; if (!virtualMemory) { qglGenBuffersARB(1, & block->vbo); } } } // move it from the freeStaticHeaders list to the staticHeaders list block = freeStaticHeaders.next; block->next->prev = block->prev; block->prev->next = block->next; block->next = staticHeaders.next; block->prev = &staticHeaders; block->next->prev = block; block->prev->next = block; block->size = size; block->offset = 0; block->tag = TAG_USED; // save data for debugging staticAllocThisFrame += block->size; staticCountThisFrame++; staticCountTotal++; staticAllocTotal += block->size; // this will be set to zero when it is purged block->user = buffer; *buffer = block; // allocation doesn't imply used-for-drawing, because at level // load time lots of things may be created, but they aren't // referenced by the GPU yet, and can be purged if needed. block->frameUsed = currentFrame - NUM_VERTEX_FRAMES; block->indexBuffer = indexBuffer; // copy the data if (block->vbo) { if (indexBuffer) { qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, block->vbo); qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, (GLsizeiptrARB)size, data, GL_STATIC_DRAW_ARB); } else { qglBindBufferARB(GL_ARRAY_BUFFER_ARB, block->vbo); if (allocatingTempBuffer) { qglBufferDataARB(GL_ARRAY_BUFFER_ARB, (GLsizeiptrARB)size, data, GL_STREAM_DRAW_ARB); } else { qglBufferDataARB(GL_ARRAY_BUFFER_ARB, (GLsizeiptrARB)size, data, GL_STATIC_DRAW_ARB); } } } else { block->virtMem = Mem_Alloc(size); SIMDProcessor->Memcpy(block->virtMem, data, size); } }
/* ============ R_CreateIBO2 ============ */ IBO_t *R_CreateIBO2(const char *name, int numTriangles, srfTriangle_t * triangles, vboUsage_t usage) { IBO_t *ibo; int i, j; byte *indexes; int indexesSize; int indexesOfs; srfTriangle_t *tri; glIndex_t index; int glUsage; switch (usage) { case VBO_USAGE_STATIC: glUsage = GL_STATIC_DRAW_ARB; break; case VBO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW_ARB; break; default: Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); return NULL; } if(!numTriangles) return NULL; if(strlen(name) >= MAX_QPATH) { ri.Error(ERR_DROP, "R_CreateIBO2: \"%s\" is too long\n", name); } if ( tr.numIBOs == MAX_IBOS ) { ri.Error( ERR_DROP, "R_CreateIBO2: MAX_IBOS hit\n"); } // make sure the render thread is stopped R_SyncRenderThread(); ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); tr.numIBOs++; Q_strncpyz(ibo->name, name, sizeof(ibo->name)); indexesSize = numTriangles * 3 * sizeof(int); indexes = ri.Hunk_AllocateTempMemory(indexesSize); indexesOfs = 0; for(i = 0, tri = triangles; i < numTriangles; i++, tri++) { for(j = 0; j < 3; j++) { index = tri->indexes[j]; memcpy(indexes + indexesOfs, &index, sizeof(glIndex_t)); indexesOfs += sizeof(glIndex_t); } } ibo->indexesSize = indexesSize; qglGenBuffersARB(1, &ibo->indexesVBO); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glState.currentIBO = NULL; GL_CheckErrors(); ri.Hunk_FreeTempMemory(indexes); return ibo; }