vcglib/apps/nexus/patchserver.cpp

304 lines
7.7 KiB
C++
Raw Normal View History

2004-10-09 13:09:13 +02:00
#include "patchserver.h"
#include <iostream>
2004-10-09 16:46:47 +02:00
#include <algorithm>
2004-10-09 13:09:13 +02:00
2004-10-15 18:45:27 +02:00
#include <GL/glew.h>
2004-10-09 13:09:13 +02:00
using namespace std;
using namespace nxs;
2004-11-28 02:23:26 +01:00
using namespace pt;
2004-10-09 13:09:13 +02:00
bool PatchServer::Create(const std::string &filename,
Signature sig,
unsigned int csize,
unsigned int rsize) {
signature = sig;
chunk_size = csize;
2004-10-19 03:23:02 +02:00
2004-10-21 14:19:52 +02:00
ram_size = rsize/chunk_size + 1;
2004-10-09 13:09:13 +02:00
ram_used = 0;
2004-10-15 18:45:27 +02:00
vbo_size = 0;
vbo_used = 0;
2004-10-19 03:23:02 +02:00
frame = 0;
2004-10-14 15:46:34 +02:00
ram_readed = 0;
ram_flushed = 0;
2004-10-19 03:23:02 +02:00
2004-10-09 13:09:13 +02:00
lru.clear();
2004-10-21 14:19:52 +02:00
return MFile::Create(filename);
2004-10-09 13:09:13 +02:00
}
bool PatchServer::Load(const std::string &filename, Signature sig,
unsigned int csize, bool readonly,
unsigned int rsize) {
2004-10-19 03:23:02 +02:00
2004-10-09 13:09:13 +02:00
signature = sig;
2004-10-21 16:01:24 +02:00
chunk_size = csize;
2004-10-19 03:23:02 +02:00
2004-10-21 14:19:52 +02:00
ram_size = rsize/chunk_size + 1;
2004-10-09 13:09:13 +02:00
ram_used = 0;
2004-10-19 03:23:02 +02:00
vbo_size = 0;
vbo_used = 0;
2004-10-14 15:46:34 +02:00
2004-10-19 03:23:02 +02:00
frame = 0;
2004-10-14 15:46:34 +02:00
ram_readed = 0;
ram_flushed = 0;
2004-10-19 03:23:02 +02:00
2004-10-09 13:09:13 +02:00
lru.clear();
2004-10-21 14:19:52 +02:00
return MFile::Load(filename, readonly);
2004-10-09 13:09:13 +02:00
}
2004-10-09 16:46:47 +02:00
void PatchServer::Close() {
2004-10-09 13:09:13 +02:00
FlushAll();
2004-10-21 14:19:52 +02:00
MFile::Close();
2004-10-09 13:09:13 +02:00
}
//TODO add error checking.
bool PatchServer::ReadEntries(FILE *fp) {
unsigned int n;
fread(&n, 1, sizeof(int), fp);
patches.resize(n);
for(unsigned int i = 0; i < n; i++) {
fread(&(patches[i].patch_start), 1, sizeof(unsigned int), fp);
2004-10-10 19:19:42 +02:00
fread(&(patches[i].ram_size), 1, sizeof(unsigned short), fp);
fread(&(patches[i].disk_size), 1, sizeof(unsigned short), fp);
2004-10-09 13:09:13 +02:00
patches[i].lru_pos = 0xffffffff;
}
return true;
}
bool PatchServer::WriteEntries(FILE *fp) {
unsigned int n = patches.size();
fwrite(&n, 1, sizeof(int), fp);
for(unsigned int i = 0; i < patches.size(); i++) {
fwrite(&(patches[i].patch_start), 1, sizeof(unsigned int), fp);
2004-10-10 19:19:42 +02:00
fwrite(&(patches[i].ram_size), 1, sizeof(unsigned short), fp);
fwrite(&(patches[i].disk_size), 1, sizeof(unsigned short), fp);
2004-10-09 13:09:13 +02:00
}
return true;
}
void PatchServer::AddPatch(unsigned short nvert, unsigned short nface) {
PatchEntry entry;
2004-10-10 19:19:42 +02:00
2004-10-19 03:23:02 +02:00
entry.patch_start = 0xffffffff;
entry.ram_size = Patch::ChunkSize(signature, nvert, nface, chunk_size);
entry.disk_size = 0xffff;
2004-10-09 13:09:13 +02:00
entry.lru_pos = 0xffffffff;
patches.push_back(entry);
}
Patch &PatchServer::GetPatch(unsigned int idx,
unsigned short nvert, unsigned short nface,
bool flush) {
2004-11-28 02:23:26 +01:00
// ramlock.rdlock();
2004-10-09 13:09:13 +02:00
assert(idx < patches.size());
PatchEntry &entry = patches[idx];
2004-10-19 03:23:02 +02:00
if(entry.lru_pos == 0xffffffff) { //not on buffer
2004-11-28 02:23:26 +01:00
// scopewrite dlock(disklock);
2004-10-10 19:19:42 +02:00
2004-11-28 02:23:26 +01:00
if(entry.lru_pos == 0xffffffff) { //still not read!
if(flush) Flush();
PTime nptime(idx);
char *ram = new char[entry.ram_size * chunk_size];
2004-10-22 16:31:56 +02:00
#ifdef CONTROLS
2004-11-28 02:23:26 +01:00
if(!ram) {
cerr << "COuld not allocate ram!\n";
exit(0);
}
2004-10-22 16:31:56 +02:00
#endif
2004-11-28 02:23:26 +01:00
nptime.patch = new Patch(signature, ram, nvert, nface);
if(entry.patch_start != 0xffffffff) { //was allocated.
assert(entry.disk_size != 0xffff);
SetPosition(entry.patch_start * chunk_size);
if((signature & NXS_COMPRESSED) == 0) { //not compressed
ReadBuffer(ram, entry.disk_size * chunk_size);
} else {
unsigned char *disk = new unsigned char[entry.disk_size * chunk_size];
ReadBuffer(disk, entry.disk_size * chunk_size);
nptime.patch->Decompress(entry.ram_size * chunk_size,
disk, entry.disk_size * chunk_size);
delete []disk;
}
}
// ramlock.unlock();
// ramlock.wrlock();
entry.lru_pos = lru.size();
lru.push_back(nptime);
ram_used += entry.ram_size;
ram_readed += entry.ram_size;
// ramlock.unlock();
// ramlock.rdlock();
2004-10-10 19:19:42 +02:00
}
2004-10-09 13:09:13 +02:00
}
2004-10-19 03:23:02 +02:00
PTime &ptime = lru[entry.lru_pos];
2004-11-28 02:23:26 +01:00
pexchange(&(ptime.frame), frame++);
// ramlock.unlock();
2004-10-09 13:09:13 +02:00
//avoid frame overflow!
2004-11-28 02:23:26 +01:00
if(frame > (1<<29)) {
// ramlock.wrlock();
2004-10-09 16:46:47 +02:00
cerr << "oVERFLOW! (nothing dangerous... just warning." << endl;;
2004-10-09 13:09:13 +02:00
for(unsigned int i = 0; i < lru.size(); i++) {
2004-11-28 02:23:26 +01:00
if(lru[i].frame < (1<<28)) lru[i].frame = 0;
else lru[i].frame -= (1<<28);
2004-10-09 13:09:13 +02:00
}
make_heap(lru.begin(), lru.end());
for(unsigned int i = 0; i < lru.size(); i++)
2004-10-19 03:23:02 +02:00
patches[lru[i].npatch].lru_pos = i;
2004-11-28 02:23:26 +01:00
// ramlock.unlock();
2004-10-09 13:09:13 +02:00
}
2004-11-28 02:23:26 +01:00
2004-10-19 03:23:02 +02:00
return *(ptime.patch);
2004-10-09 13:09:13 +02:00
}
2004-10-15 18:45:27 +02:00
2004-10-19 03:23:02 +02:00
void PatchServer::GetVbo(unsigned int p,
unsigned int &element, unsigned int &array) {
PatchEntry &entry = patches[p];
assert(entry.lru_pos != 0xffffffff);
PTime &ptime = lru[entry.lru_pos];
if(!ptime.vbo_element) {
//TODO cerr << "Adding vbo: " << p << endl;
assert(ptime.patch);
Patch &patch = *ptime.patch;
glGenBuffersARB(1, &ptime.vbo_element);
assert(ptime.vbo_element);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ptime.vbo_element);
unsigned int size = patch.nf * sizeof(unsigned short);
if((signature & NXS_FACES) != 0) size *= 3;
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, patch.FaceBegin(),
GL_STATIC_DRAW_ARB);
//TODO fix this when we allow data :p
size = sizeof(float) * patch.dstart;
glGenBuffersARB(1, &ptime.vbo_array);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, ptime.vbo_array);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, patch.VertBegin(),
GL_STATIC_DRAW_ARB);
vbo_used += patches[p].ram_size;
}
2004-10-15 18:45:27 +02:00
2004-10-19 03:23:02 +02:00
element = ptime.vbo_element;
array = ptime.vbo_array;
2004-10-15 18:45:27 +02:00
}
2004-10-09 13:09:13 +02:00
void PatchServer::Flush() {
2004-10-10 19:19:42 +02:00
2004-10-14 15:46:34 +02:00
if(ram_used < ram_size * 1.1) return;
2004-10-10 19:19:42 +02:00
2004-11-28 02:23:26 +01:00
// ramlock.wrlock();
2004-10-09 13:09:13 +02:00
make_heap(lru.begin(), lru.end());
2004-10-10 19:19:42 +02:00
for(unsigned int i = 0; i < lru.size(); i++)
2004-10-19 03:23:02 +02:00
patches[lru[i].npatch].lru_pos = i;
2004-10-10 19:19:42 +02:00
2004-10-09 13:09:13 +02:00
while(ram_used > ram_size) {
pop_heap(lru.begin(), lru.end());
PTime &ptime = lru.back();
2004-10-19 18:52:01 +02:00
Flush(ptime);
2004-10-09 13:09:13 +02:00
lru.pop_back();
}
for(unsigned int i = 0; i < lru.size(); i++)
2004-10-19 03:23:02 +02:00
patches[lru[i].npatch].lru_pos = i;
2004-11-28 02:23:26 +01:00
// ramlock.unlock();
2004-10-09 13:09:13 +02:00
}
void PatchServer::FlushAll() {
for(unsigned int i = 0; i < lru.size(); i++) {
PTime &ptime = lru[i];
2004-10-19 18:52:01 +02:00
Flush(ptime);
2004-10-09 13:09:13 +02:00
}
assert(ram_used == 0);
lru.clear();
}
2004-10-19 18:52:01 +02:00
void PatchServer::Flush(PTime &ptime) {
2004-11-28 02:23:26 +01:00
2004-10-19 18:52:01 +02:00
PatchEntry &entry = patches[ptime.npatch];
assert(ptime.patch);
2004-10-09 13:09:13 +02:00
if(!readonly) { //write back patch
2004-10-10 19:19:42 +02:00
if((signature & NXS_COMPRESSED)) {
unsigned int compressed_size;
2004-10-19 03:23:02 +02:00
char *compressed = ptime.patch->Compress(entry.ram_size * chunk_size,
2004-10-10 19:19:42 +02:00
compressed_size);
if(entry.disk_size == 0xffff) {//allocate space
2004-10-21 17:05:39 +02:00
assert(entry.patch_start == 0xffffffff);
entry.disk_size = (unsigned int)((compressed_size-1)/chunk_size) + 1;
entry.patch_start = (unsigned int)(Length()/chunk_size);
Redim(Length() + entry.disk_size * chunk_size);
2004-10-10 19:19:42 +02:00
} else {
2004-10-21 17:05:39 +02:00
cerr << "OOOOPSPPPS not supported!" << endl;
exit(-1);
2004-10-10 19:19:42 +02:00
}
SetPosition(entry.patch_start * chunk_size);
WriteBuffer(compressed, entry.disk_size * chunk_size);
delete []compressed;
} else {
if(entry.disk_size == 0xffff) {
2004-10-21 17:05:39 +02:00
entry.disk_size = entry.ram_size;
entry.patch_start = (unsigned int)(Length()/chunk_size);
Redim(Length() + entry.disk_size * chunk_size);
2004-10-10 19:19:42 +02:00
}
SetPosition(entry.patch_start * chunk_size);
2004-10-19 03:23:02 +02:00
WriteBuffer(ptime.patch->start, entry.disk_size * chunk_size);
2004-10-10 19:19:42 +02:00
}
/* FILE *fo = fopen("tmp", "wb+");
fwrite(entry.patch->start, 1, entry.disk_size * chunk_size, fo);
fclose(fo);
exit(0);*/
2004-10-09 13:09:13 +02:00
}
2004-10-10 19:19:42 +02:00
2004-10-19 18:52:01 +02:00
if(FlushVbo(ptime))
vbo_used -= entry.ram_size;
2004-10-19 03:23:02 +02:00
delete [](ptime.patch->start);
delete ptime.patch;
ptime.patch = NULL;
2004-10-19 18:52:01 +02:00
2004-10-19 03:23:02 +02:00
entry.lru_pos = 0xffffffff;
2004-10-10 19:19:42 +02:00
ram_used -= entry.ram_size;
2004-10-14 15:46:34 +02:00
ram_flushed += entry.ram_size;
2004-10-10 19:19:42 +02:00
}
2004-10-19 18:52:01 +02:00
bool PatchServer::FlushVbo(PTime &ptime) {
2004-10-15 18:45:27 +02:00
//TODO
//cerr << "Flushing vbo: " << patch << endl;
2004-10-19 03:23:02 +02:00
if(!ptime.vbo_element) return false;
glDeleteBuffersARB(1, &ptime.vbo_element);
glDeleteBuffersARB(1, &ptime.vbo_array);
2004-10-19 18:52:01 +02:00
ptime.vbo_element = 0;
ptime.vbo_array = 0;
2004-10-15 18:45:27 +02:00
return true;
}
2004-10-10 19:19:42 +02:00
void PatchServer::SetRamBufferSize(unsigned int r_buffer) {
2004-10-20 17:07:02 +02:00
cerr << "Chunk_size: " << chunk_size << endl;
2004-10-10 19:19:42 +02:00
ram_size = (unsigned int)(r_buffer/chunk_size) + 1;
2004-10-09 13:09:13 +02:00
}