Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsfbbuffer.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2011 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmsgui/fb/mmsfbbuffer.h"
00034 #include "mmsgui/fb/mmsfb.h"
00035 
00036 //////////////////////////////////////////////////////////////////////////////
00037 
00038 MMSFBBuffer::EXTKEY_INDEX MMSFBBuffer::extkey_index;
00039 MMSFBBuffer::BUFFER_INDEX MMSFBBuffer::buffer_index;
00040 
00041 MMSFBBuffer::MMSFBBuffer(unsigned int extkey, unsigned int subkey) {
00042     // allocate new or use existing extkey
00043     EXTKEY_INDEX::iterator extkey_it = this->extkey_index.find(extkey);
00044     if (extkey_it == this->extkey_index.end()) {
00045         // new extkey
00046         this->extkey = new EXTKEY(extkey);
00047         this->extkey_index.insert(make_pair(extkey, this->extkey));
00048     }
00049     else {
00050         // use existing extkey
00051         this->extkey = extkey_it->second;
00052         this->extkey->use_count++;
00053     }
00054 
00055     // build external id
00056     this->ext_id = (((unsigned long long)extkey) << 32) + (unsigned long long)subkey;
00057 
00058     // allocate new or use existing buffer
00059     BUFFER_INDEX::iterator buffer_it = this->buffer_index.find(this->ext_id);
00060     if (buffer_it == this->buffer_index.end()) {
00061         // new buffer
00062         this->buffer = new BUFFER();
00063         this->buffer_index.insert(make_pair(this->ext_id, this->buffer));
00064     }
00065     else {
00066         // use existing buffer
00067         this->buffer = buffer_it->second;
00068         this->buffer->use_count++;
00069     }
00070 }
00071 
00072 MMSFBBuffer::~MMSFBBuffer() {
00073     // reduce use count of buffer
00074     BUFFER_INDEX::iterator buffer_it = this->buffer_index.find(this->ext_id);
00075     if (buffer_it != this->buffer_index.end()) {
00076         // reduce use counter
00077         buffer_it->second->use_count--;
00078         if (buffer_it->second->use_count == 0) {
00079             // buffer is unused, free all resources
00080             delete buffer_it->second;
00081             this->buffer_index.erase(buffer_it);
00082         }
00083     }
00084 
00085     // reduce use count of extkey
00086     EXTKEY_INDEX::iterator extkey_it = this->extkey_index.find(this->extkey->key);
00087     if (extkey_it != this->extkey_index.end()) {
00088         // reduce use counter
00089         extkey_it->second->use_count--;
00090         if (extkey_it->second->use_count == 0) {
00091             // extkey is unused, free all resources
00092             delete extkey_it->second;
00093             this->extkey_index.erase(extkey_it);
00094         }
00095     }
00096 }
00097 
00098 bool MMSFBBuffer::isInitialized() {
00099     if (!this->buffer) return false;
00100     return this->buffer->initialized;
00101 }
00102 
00103 bool MMSFBBuffer::getExtKey(MMSFBBuffer::EXTKEY **extkey) {
00104     if (!isInitialized()) return false;
00105     if (extkey) *extkey = this->extkey;
00106     return true;
00107 }
00108 
00109 
00110 
00111 bool MMSFBBuffer::initBuffer(INDEX_BUFFER index_buffer, VERTEX_BUFFER vertex_buffer) {
00112     if (isInitialized()) return false;
00113     if (this->buffer) {
00114         this->buffer->type = BUFFER_TYPE_INDEX_VERTEX;
00115 
00116         this->buffer->initIndexBuffer(this->extkey, index_buffer);
00117 
00118         this->extkey->allocVertexArray(256*1024);
00119         this->buffer->initVertexBuffer(this->extkey, vertex_buffer);
00120 
00121         this->buffer->initialized = true;
00122         return true;
00123     }
00124     return false;
00125 }
00126 
00127 bool MMSFBBuffer::getBuffer(MMSFBBuffer::BUFFER **buffer) {
00128     if (!isInitialized()) return false;
00129     if (buffer) *buffer = this->buffer;
00130     return true;
00131 }
00132 
00133 //////////////////////////////////////////////////////////////////////////////
00134 
00135 MMSFBBuffer::EXTKEY::EXTKEY(unsigned int key) : initialized(false), use_count(1) {
00136     this->key = key;
00137 #ifdef __HAVE_OPENGL__
00138     this->ibo = 0;
00139     this->ibo_size = 0;
00140     this->ibo_used = 0;
00141     this->vbo = 0;
00142     this->vbo_size = 0;
00143     this->vbo_used = 0;
00144 #endif
00145 }
00146 
00147 MMSFBBuffer::EXTKEY::~EXTKEY() {
00148 #ifdef __HAVE_OPENGL__
00149     if (mmsfb->bei) {
00150         // delete OpenGL's index and vertex buffer
00151         if (this->ibo) mmsfb->bei->deleteBuffer(this->ibo);
00152         if (this->vbo) mmsfb->bei->deleteBuffer(this->vbo);
00153     }
00154 #endif
00155 }
00156 
00157 bool MMSFBBuffer::EXTKEY::allocVertexArray(unsigned int size) {
00158 #ifdef __HAVE_OPENGL__
00159     if (!this->vbo) {
00160         // allocate size bytes GPU buffer
00161         this->vbo_size = size;
00162         this->vbo_used = 0;
00163         if (mmsfb->bei) {
00164             mmsfb->bei->initVertexBuffer(&this->vbo, this->vbo_size);
00165             if (!this->vbo) {
00166                 this->vbo_size = 0;
00167                 return false;
00168             }
00169         }
00170     }
00171 #endif
00172 
00173     return true;
00174 }
00175 
00176 
00177 bool MMSFBBuffer::EXTKEY::reserveIndexArray(unsigned int requested_size, unsigned int *offset) {
00178 #ifdef __HAVE_OPENGL__
00179     if (!this->ibo) return false;
00180     if (this->ibo_used + requested_size > this->ibo_size) return false;
00181     *offset = this->ibo_used;
00182     this->ibo_used+= requested_size;
00183 #endif
00184     return true;
00185 }
00186 
00187 bool MMSFBBuffer::EXTKEY::reserveVertexArray(unsigned int requested_size, unsigned int *offset) {
00188 #ifdef __HAVE_OPENGL__
00189     if (!this->vbo) return false;
00190     if (this->vbo_used + requested_size > this->vbo_size) return false;
00191     *offset = this->vbo_used;
00192     this->vbo_used+= requested_size;
00193 #endif
00194     return true;
00195 }
00196 
00197 //////////////////////////////////////////////////////////////////////////////
00198 
00199 MMSFBBuffer::BUFFER::BUFFER() : initialized(false), use_count(1), type(BUFFER_TYPE_NOTSET) {
00200 #ifdef __HAVE_OPENGL__
00201     this->index_bo.bo = 0;
00202     this->index_bo.buffers = NULL;
00203     this->index_bo.num_buffers = 0;
00204     this->vertex_bo.bo = 0;
00205     this->vertex_bo.buffers = NULL;
00206     this->vertex_bo.num_buffers = 0;
00207 #endif
00208 }
00209 
00210 MMSFBBuffer::BUFFER::~BUFFER() {
00211 #ifdef __HAVE_OPENGL__
00212     switch (this->type) {
00213     case BUFFER_TYPE_INDEX_VERTEX:
00214         if (this->index_buffer.arrays) {
00215             for (unsigned int i = 0; i < this->index_buffer.num_arrays; i++)
00216                 if (this->index_buffer.arrays[i].data) free(this->index_buffer.arrays[i].data);
00217             free(this->index_buffer.arrays);
00218         }
00219         if (this->vertex_buffer.arrays) {
00220             for (unsigned int i = 0; i < this->vertex_buffer.num_arrays; i++)
00221                 if (this->vertex_buffer.arrays[i].data) free(this->vertex_buffer.arrays[i].data);
00222             free(this->vertex_buffer.arrays);
00223         }
00224         break;
00225     default:
00226         break;
00227     }
00228 
00229     if (this->index_bo.buffers)
00230         free(this->index_bo.buffers);
00231     if (this->vertex_bo.buffers)
00232         free(this->vertex_bo.buffers);
00233 #endif
00234 }
00235 
00236 void MMSFBBuffer::BUFFER::initIndexBuffer(EXTKEY *extkey, INDEX_BUFFER index_buffer) {
00237 
00238     this->index_buffer = index_buffer;
00239 
00240 #ifdef __HAVE_OPENGL__
00241 
00242     // prepare index buffer object
00243     this->index_bo.num_buffers = this->index_buffer.num_arrays;
00244     if (this->index_bo.num_buffers == 0) {
00245         // no buffers
00246         this->index_bo.bo = 0;
00247         this->index_bo.buffers = NULL;
00248         this->index_bo.num_buffers = 0;
00249         return;
00250     }
00251     this->index_bo.buffers = (MMS_INDEX_BUFFER *)malloc(sizeof(MMS_INDEX_BUFFER) * this->index_bo.num_buffers);
00252     if (!this->index_bo.buffers) {
00253         // no mem
00254         this->index_bo.bo = 0;
00255         this->index_bo.buffers = NULL;
00256         this->index_bo.num_buffers = 0;
00257         return;
00258     }
00259     this->index_bo.bo = extkey->ibo;
00260 
00261     // calculate size of whole new buffer object and setup several buffers
00262     unsigned int size = 0;
00263     for (unsigned int i = 0; i < this->index_bo.num_buffers; i++) {
00264         MMS_INDEX_ARRAY *array = &this->index_buffer.arrays[i];
00265         this->index_bo.buffers[i].bo   = 0;
00266         this->index_bo.buffers[i].offs = size;
00267         this->index_bo.buffers[i].type = array->type;
00268         this->index_bo.buffers[i].eNum = array->eNum;
00269         size+= sizeof(unsigned int) * array->eNum;
00270     }
00271 
00272     if (!this->index_bo.bo && size) {
00273         // we need a buffer object but it is not initialized
00274         free(this->index_bo.buffers);
00275         this->index_bo.bo = 0;
00276         this->index_bo.buffers = NULL;
00277         this->index_bo.num_buffers = 0;
00278         return;
00279     }
00280 
00281     if (size) {
00282         // try to reserve GPU buffer
00283         unsigned int ibo_offset = 0;
00284         if (extkey->reserveIndexArray(size, &ibo_offset)) {
00285             // fill GPU buffer
00286             for (unsigned int i = 0; i < this->index_bo.num_buffers; i++) {
00287                 MMS_INDEX_ARRAY *array = &this->index_buffer.arrays[i];
00288 
00289                 this->index_bo.buffers[i].bo = this->index_bo.bo;
00290                 this->index_bo.buffers[i].offs+= ibo_offset;
00291 
00292                 unsigned int size = sizeof(unsigned int) * array->eNum;
00293 
00294                 if (mmsfb->bei)
00295                     mmsfb->bei->initIndexSubBuffer(this->index_bo.buffers[i].bo, this->index_bo.buffers[i].offs, size, array->data);
00296             }
00297         }
00298     }
00299 #endif
00300 }
00301 
00302 void MMSFBBuffer::BUFFER::initVertexBuffer(EXTKEY *extkey, VERTEX_BUFFER vertex_buffer) {
00303 
00304     this->vertex_buffer = vertex_buffer;
00305 
00306 #ifdef __HAVE_OPENGL__
00307 
00308     // prepare vertex buffer object
00309     this->vertex_bo.num_buffers = this->vertex_buffer.num_arrays;
00310     if (this->vertex_bo.num_buffers == 0) {
00311         // no buffers
00312         this->vertex_bo.bo = 0;
00313         this->vertex_bo.buffers = NULL;
00314         this->vertex_bo.num_buffers = 0;
00315         return;
00316     }
00317     this->vertex_bo.buffers = (MMS_VERTEX_BUFFER *)malloc(sizeof(MMS_VERTEX_BUFFER) * this->vertex_bo.num_buffers);
00318     if (!this->vertex_bo.buffers) {
00319         // no mem
00320         this->vertex_bo.bo = 0;
00321         this->vertex_bo.buffers = NULL;
00322         this->vertex_bo.num_buffers = 0;
00323         return;
00324     }
00325     this->vertex_bo.bo = extkey->vbo;
00326 
00327     // calculate size of whole new buffer object and setup several buffers
00328     unsigned int size = 0;
00329     for (unsigned int i = 0; i < this->vertex_bo.num_buffers; i++) {
00330         MMS_VERTEX_ARRAY *array = &this->vertex_buffer.arrays[i];
00331         this->vertex_bo.buffers[i].dtype = array->dtype;
00332         this->vertex_bo.buffers[i].bo    = 0;
00333         this->vertex_bo.buffers[i].offs  = size;
00334         this->vertex_bo.buffers[i].eSize = array->eSize;
00335         this->vertex_bo.buffers[i].eNum  = array->eNum;
00336 
00337         switch (this->vertex_bo.buffers[i].dtype) {
00338         case MMS_VERTEX_DATA_TYPE_HALF_FLOAT:
00339             size+= sizeof(MMS_HALF_FLOAT) * array->eSize * array->eNum;
00340             break;
00341         default:
00342             size+= sizeof(float) * array->eSize * array->eNum;
00343             break;
00344         }
00345     }
00346 
00347     if (!this->vertex_bo.bo && size) {
00348         // we need a buffer object but it is not initialized
00349         free(this->vertex_bo.buffers);
00350         this->vertex_bo.bo = 0;
00351         this->vertex_bo.buffers = NULL;
00352         this->vertex_bo.num_buffers = 0;
00353         return;
00354     }
00355 
00356     if (size) {
00357         // try to reserve GPU buffer
00358         unsigned int vbo_offset = 0;
00359         if (extkey->reserveVertexArray(size, &vbo_offset)) {
00360             // fill GPU buffer
00361             for (unsigned int i = 0; i < this->vertex_bo.num_buffers; i++) {
00362                 MMS_VERTEX_ARRAY *array = &this->vertex_buffer.arrays[i];
00363 
00364                 this->vertex_bo.buffers[i].bo = this->vertex_bo.bo;
00365                 this->vertex_bo.buffers[i].offs+= vbo_offset;
00366 
00367                 unsigned int size;
00368                 switch (this->vertex_bo.buffers[i].dtype) {
00369                 case MMS_VERTEX_DATA_TYPE_HALF_FLOAT:
00370                     size = sizeof(MMS_HALF_FLOAT) * array->eSize * array->eNum;
00371                     break;
00372                 default:
00373                     size = sizeof(float) * array->eSize * array->eNum;
00374                     break;
00375                 }
00376 
00377                 if (mmsfb->bei)
00378                     mmsfb->bei->initVertexSubBuffer(this->vertex_bo.buffers[i].bo, this->vertex_bo.buffers[i].offs, size, array->data);
00379             }
00380         }
00381     }
00382 #endif
00383 }
00384 
00385 bool MMSFBBuffer::BUFFER::getBuffers(MMSFBBuffer::INDEX_BUFFER **index_buffer, MMSFBBuffer::VERTEX_BUFFER **vertex_buffer) {
00386     if (this->type != BUFFER_TYPE_INDEX_VERTEX) return false;
00387     if (index_buffer) *index_buffer = &this->index_buffer;
00388     if (vertex_buffer) *vertex_buffer = &this->vertex_buffer;
00389     return true;
00390 }
00391 
00392 #ifdef __HAVE_OPENGL__
00393 bool MMSFBBuffer::BUFFER::getBufferObjects(MMSFBBuffer::INDEX_BUFFER_OBJECT **index_bo, MMSFBBuffer::VERTEX_BUFFER_OBJECT **vertex_bo) {
00394     if (this->type != BUFFER_TYPE_INDEX_VERTEX) return false;
00395     if (index_bo) *index_bo = &this->index_bo;
00396     if (vertex_bo) *vertex_bo = &this->vertex_bo;
00397     return true;
00398 }
00399 #endif
00400 
00401 
00402 
00403 
00404 

Generated by doxygen