Ptex
PtexReader.cpp
Go to the documentation of this file.
1 /*
2 PTEX SOFTWARE
3 Copyright 2014 Disney Enterprises, Inc. All rights reserved
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in
14  the documentation and/or other materials provided with the
15  distribution.
16 
17  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
18  Studios" or the names of its contributors may NOT be used to
19  endorse or promote products derived from this software without
20  specific prior written permission from Walt Disney Pictures.
21 
22 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 */
35 
36 #include "PtexPlatform.h"
37 #include <iostream>
38 #include <sstream>
39 #include <stdio.h>
40 
41 #include "Ptexture.h"
42 #include "PtexUtils.h"
43 #include "PtexReader.h"
44 
45 namespace {
46  class TempErrorHandler : public PtexErrorHandler
47  {
48  std::string _error;
49  public:
50  virtual void reportError(const char* error) {
51  _error += error;
52  }
53  const std::string& getErrorString() const { return _error; }
54  };
55 }
56 
58 
59 PtexTexture* PtexTexture::open(const char* path, Ptex::String& error, bool premultiply)
60 {
61  PtexReader* reader = new PtexReader(premultiply, (PtexInputHandler*) 0, (PtexErrorHandler*) 0);
62  bool ok = reader->open(path, error);
63  if (!ok) {
64  reader->release();
65  return 0;
66  }
67  return reader;
68 }
69 
70 
72  : _io(io ? io : &_defaultIo),
73  _err(err),
74  _premultiply(premultiply),
75  _ok(true),
76  _needToOpen(true),
77  _pendingPurge(false),
78  _fp(0),
79  _pos(0),
80  _pixelsize(0),
81  _constdata(0),
82  _metadata(0),
83  _hasEdits(false),
84  _baseMemUsed(sizeof(*this)),
85  _memUsed(_baseMemUsed),
86  _opens(0),
87  _blockReads(0)
88 {
89  memset(&_zstream, 0, sizeof(_zstream));
90 }
91 
92 
94 {
95  closeFP();
96  if (_constdata) delete [] _constdata;
97  if (_metadata) delete _metadata;
98 
99  for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
100  if (*i) delete *i;
101  }
102 }
103 
105 {
106  if (_metadata) { delete _metadata; _metadata = 0; }
107  for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
108  if (*i) { delete *i; *i = 0; }
109  }
110  _reductions.clear();
112 }
113 
114 
116 {
117  // free all dynamic data
118  prune();
119  if (_constdata) {delete [] _constdata; _constdata = 0; }
120  std::vector<FaceInfo>().swap(_faceinfo);
121  std::vector<uint32_t>().swap(_rfaceids);
122  std::vector<LevelInfo>().swap(_levelinfo);
123  std::vector<FilePos>().swap(_levelpos);
124  std::vector<Level*>().swap(_levels);
125  std::vector<MetaEdit>().swap(_metaedits);
126  std::vector<FaceEdit>().swap(_faceedits);
127  closeFP();
128 
129  // reset initial state
130  _ok = true;
131  _needToOpen = true;
132  _pendingPurge = false;
133  _memUsed = _baseMemUsed = sizeof(*this);
134 }
135 
136 
137 bool PtexReader::open(const char* pathArg, Ptex::String& error)
138 {
139  AutoMutex locker(readlock);
140  if (!needToOpen()) return false;
141 
142  if (!LittleEndian()) {
143  error = "Ptex library doesn't currently support big-endian cpu's";
144  return 0;
145  }
146  _path = pathArg;
147  _fp = _io->open(pathArg);
148  if (!_fp) {
149  std::string errstr = "Can't open ptex file: ";
150  errstr += pathArg; errstr += "\n"; errstr += _io->lastError();
151  error = errstr.c_str();
152  _ok = 0;
153  return 0;
154  }
155  memset(&_header, 0, sizeof(_header));
157  if (_header.magic != Magic) {
158  std::string errstr = "Not a ptex file: "; errstr += pathArg;
159  error = errstr.c_str();
160  _ok = 0;
161  closeFP();
162  return 0;
163  }
164  if (_header.version != 1) {
165  std::stringstream s;
166  s << "Unsupported ptex file version ("<< _header.version << "): " << pathArg;
167  error = s.str();
168  _ok = 0;
169  closeFP();
170  return 0;
171  }
173  _errorPixel.resize(_pixelsize);
174 
175  // install temp error handler to capture error (to return in error param)
176  TempErrorHandler tempErr;
177  PtexErrorHandler* prevErr = _err;
178  _err = &tempErr;
179 
180  // read extended header
181  memset(&_extheader, 0, sizeof(_extheader));
183 
184  // compute offsets of various blocks
186  _faceinfopos = pos; pos += _header.faceinfosize;
187  _constdatapos = pos; pos += _header.constdatasize;
188  _levelinfopos = pos; pos += _header.levelinfosize;
189  _leveldatapos = pos; pos += _header.leveldatasize;
190  _metadatapos = pos; pos += _header.metadatazipsize;
191  pos += sizeof(uint64_t); // compatibility barrier
193  _lmddatapos = pos; pos += _extheader.lmddatasize;
194 
195  // edit data may not start immediately if additional sections have been added
196  // use value from extheader if present (and > pos)
198 
199  // read basic file info
200  readFaceInfo();
201  readConstData();
202  readLevelInfo();
203  readEditData();
205 
206  // restore error handler
207  _err = prevErr;
208 
209  // an error occurred while reading the file
210  if (!_ok) {
211  error = tempErr.getErrorString();
212  closeFP();
213  return 0;
214  }
215  AtomicStore(&_needToOpen, false);
216  return true;
217 }
218 
220 {
221  if (_fp) {
222  if (!readlock.trylock()) return false;
223  closeFP();
224  readlock.unlock();
225  }
226  return true;
227 }
228 
229 
231 {
232  if (_fp) {
233  _io->close(_fp);
234  _fp = 0;
235  }
236  inflateEnd(&_zstream);
237 }
238 
239 
241 {
242  if (_fp) return true;
243 
244  // we assume this is called lazily in a scope where readlock is already held
245  _fp = _io->open(_path.c_str());
246  if (!_fp) {
247  setError("Can't reopen");
248  return false;
249  }
250  _pos = 0;
251  Header headerval;
252  ExtHeader extheaderval;
253  readBlock(&headerval, HeaderSize);
254  memset(&extheaderval, 0, sizeof(extheaderval));
255  readBlock(&extheaderval, PtexUtils::min(uint32_t(ExtHeaderSize), headerval.extheadersize));
256  if (0 != memcmp(&headerval, &_header, sizeof(headerval)) ||
257  0 != memcmp(&extheaderval, &_extheader, sizeof(extheaderval)))
258  {
259  setError("Header mismatch on reopen of");
260  return false;
261  }
262  logOpen();
263  return true;
264 }
265 
266 
268 {
269  if (faceid >= 0 && uint32_t(faceid) < _faceinfo.size())
270  return _faceinfo[faceid];
271 
272  static Ptex::FaceInfo dummy;
273  return dummy;
274 }
275 
276 
278 {
279  if (_faceinfo.empty()) {
280  // read compressed face info block
282  int nfaces = _header.nfaces;
283  _faceinfo.resize(nfaces);
285  (int)(sizeof(FaceInfo)*nfaces));
286 
287  // generate rfaceids
288  _rfaceids.resize(nfaces);
289  std::vector<uint32_t> faceids_r(nfaces);
290  PtexUtils::genRfaceids(&_faceinfo[0], nfaces,
291  &_rfaceids[0], &faceids_r[0]);
292  increaseMemUsed(nfaces * (sizeof(_faceinfo[0]) + sizeof(_rfaceids[0])));
293  }
294 }
295 
296 
297 
299 {
300  if (_levelinfo.empty()) {
301  // read level info block
303  _levelinfo.resize(_header.nlevels);
305 
306  // initialize related data
307  _levels.resize(_header.nlevels);
308  _levelpos.resize(_header.nlevels);
309  FilePos pos = _leveldatapos;
310  for (int i = 0; i < _header.nlevels; i++) {
311  _levelpos[i] = pos;
312  pos += _levelinfo[i].leveldatasize;
313  }
314  increaseMemUsed(_header.nlevels * sizeof(_levelinfo[0]) + sizeof(_levels[0]) + sizeof(_levelpos[0]));
315  }
316 }
317 
318 
320 {
321  if (!_constdata) {
322  // read compressed constant data block
324  int size = _pixelsize * _header.nfaces;
325  _constdata = new uint8_t[size];
327  if (_premultiply && _header.hasAlpha())
330  increaseMemUsed(size);
331  }
332 }
333 
334 
336 {
337  if (!_metadata) readMetaData();
338  return _metadata;
339 }
340 
341 
344 {
345  if (index < 0 || index >= int(_entries.size())) {
346  return 0;
347  }
348 
349  Entry* e = _entries[index];
350  if (!e->isLmd) {
351  // normal (small) meta data - just return directly
352  return e;
353  }
354 
355  // large meta data - may not be read in yet
356  if (e->lmdData) {
357  // already in memory
358  return e;
359  }
360  else {
361  // not present, must read from file
362 
363  // get read lock and make sure we still need to read
364  AutoMutex locker(_reader->readlock);
365  if (e->lmdData) {
366  return e;
367  }
368  // go ahead and read, keep local until finished
369  LargeMetaData* lmdData = new LargeMetaData(e->datasize);
370  e->data = (char*) lmdData->data();
372  _reader->seek(e->lmdPos);
374  // update entry
375  e->lmdData = lmdData;
376  return e;
377  }
378 }
379 
380 
382 {
383  // get read lock and make sure we still need to read
384  AutoMutex locker(readlock);
385  if (_metadata) {
386  return;
387  }
388 
389  // allocate new meta data (keep local until fully initialized)
390  MetaData* newmeta = new MetaData(this);
391  size_t metaDataMemUsed = sizeof(MetaData);
392 
393  // read primary meta data blocks
396  _header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
397 
398  // read large meta data headers
402 
403  // read meta data edits
404  for (size_t i = 0, size = _metaedits.size(); i < size; i++)
405  readMetaDataBlock(newmeta, _metaedits[i].pos,
406  _metaedits[i].zipsize, _metaedits[i].memsize, metaDataMemUsed);
407 
408  // store meta data
409  AtomicStore(&_metadata, newmeta);
410  increaseMemUsed(newmeta->selfDataSize() + metaDataMemUsed);
411 }
412 
413 
414 void PtexReader::readMetaDataBlock(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
415 {
416  seek(pos);
417  // read from file
418  bool useNew = memsize > AllocaMax;
419  char* buff = useNew ? new char[memsize] : (char*)alloca(memsize);
420 
421  if (readZipBlock(buff, zipsize, memsize)) {
422  // unpack data entries
423  char* ptr = buff;
424  char* end = ptr + memsize;
425  while (ptr < end) {
426  uint8_t keysize = *ptr++;
427  char* key = (char*)ptr; ptr += keysize;
428  key[keysize-1] = '\0';
429  uint8_t datatypeval = *ptr++;
430  uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
431  ptr += sizeof(datasize);
432  char* data = ptr; ptr += datasize;
433  metadata->addEntry((uint8_t)(keysize-1), key, datatypeval, datasize, data, metaDataMemUsed);
434  }
435  }
436  if (useNew) delete [] buff;
437 }
438 
439 
440 void PtexReader::readLargeMetaDataHeaders(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
441 {
442  seek(pos);
443  // read from file
444  bool useNew = memsize > AllocaMax;
445  char* buff = useNew ? new char [memsize] : (char*)alloca(memsize);
446 
447  if (readZipBlock(buff, zipsize, memsize)) {
448  pos += zipsize;
449 
450  // unpack data entries
451  char* ptr = buff;
452  char* end = ptr + memsize;
453  while (ptr < end) {
454  uint8_t keysize = *ptr++;
455  char* key = (char*)ptr; ptr += keysize;
456  uint8_t datatypeval = *ptr++;
457  uint32_t datasize; memcpy(&datasize, ptr, sizeof(datasize));
458  ptr += sizeof(datasize);
459  uint32_t zipsizeval; memcpy(&zipsizeval, ptr, sizeof(zipsizeval));
460  ptr += sizeof(zipsizeval);
461  metadata->addLmdEntry((uint8_t)(keysize-1), key, datatypeval, datasize, pos, zipsizeval, metaDataMemUsed);
462  pos += zipsizeval;
463  }
464  }
465  if (useNew) delete [] buff;
466 }
467 
469 {
470  // determine file range to scan for edits
471  FilePos pos = FilePos(_editdatapos), endpos;
472  if (_extheader.editdatapos > 0) {
473  // newer files record the edit data position and size in the extheader
474  // note: position will be non-zero even if size is zero
475  endpos = FilePos(pos + _extheader.editdatasize);
476  }
477  else {
478  // must have an older file, just read until EOF
479  endpos = FilePos((uint64_t)-1);
480  }
481 
482  while (pos < endpos) {
483  seek(pos);
484  // read the edit data header
485  uint8_t edittype = et_editmetadata;
486  uint32_t editsize;
487  if (!readBlock(&edittype, sizeof(edittype), /*reporterror*/ false)) break;
488  if (!readBlock(&editsize, sizeof(editsize), /*reporterror*/ false)) break;
489  if (!editsize) break;
490  _hasEdits = true;
491  pos = tell() + editsize;
492  switch (edittype) {
493  case et_editfacedata: readEditFaceData(); break;
494  case et_editmetadata: readEditMetaData(); break;
495  }
496  }
497  increaseMemUsed(sizeof(_faceedits[0]) * _faceedits.capacity() +
498  sizeof(_metaedits[0]) * _metaedits.capacity());
499 }
500 
501 
503 {
504  // read header
505  EditFaceDataHeader efdh;
506  if (!readBlock(&efdh, EditFaceDataHeaderSize)) return;
507 
508  // update face info
509  int faceid = efdh.faceid;
510  if (faceid < 0 || size_t(faceid) >= _header.nfaces) return;
511  FaceInfo& f = _faceinfo[faceid];
512  f = efdh.faceinfo;
513  f.flags |= FaceInfo::flag_hasedits;
514 
515  // read const value now
516  uint8_t* constdata = _constdata + _pixelsize * faceid;
517  if (!readBlock(constdata, _pixelsize)) return;
518  if (_premultiply && _header.hasAlpha())
519  PtexUtils::multalpha(constdata, 1, datatype(),
521 
522  // update header info for remaining data
523  if (!f.isConstant()) {
524  _faceedits.push_back(FaceEdit());
525  FaceEdit& e = _faceedits.back();
526  e.pos = tell();
527  e.faceid = faceid;
528  e.fdh = efdh.fdh;
529  }
530 }
531 
532 
534 {
535  // read header
536  EditMetaDataHeader emdh;
537  if (!readBlock(&emdh, EditMetaDataHeaderSize)) return;
538 
539  // record header info for later
540  _metaedits.push_back(MetaEdit());
541  MetaEdit& e = _metaedits.back();
542  e.pos = tell();
543  e.zipsize = emdh.metadatazipsize;
544  e.memsize = emdh.metadatamemsize;
545 }
546 
547 
548 bool PtexReader::readBlock(void* data, int size, bool reporterror)
549 {
550  assert(_fp && size >= 0);
551  if (!_fp || size < 0) return false;
552  int result = (int)_io->read(data, size, _fp);
553  if (result == size) {
554  _pos += size;
555  return true;
556  }
557  if (reporterror)
558  setError("PtexReader error: read failed (EOF)");
559  return false;
560 }
561 
562 
563 bool PtexReader::readZipBlock(void* data, int zipsize, int unzipsize)
564 {
565  if (zipsize < 0 || unzipsize < 0) return false;
566  if (!_zstream.state) {
567  inflateInit(&_zstream);
568  }
569 
570  void* buff = alloca(BlockSize);
571  _zstream.next_out = (Bytef*) data;
572  _zstream.avail_out = unzipsize;
573 
574  while (1) {
575  int size = (zipsize < BlockSize) ? zipsize : BlockSize;
576  zipsize -= size;
577  if (!readBlock(buff, size)) break;
578  _zstream.next_in = (Bytef*) buff;
579  _zstream.avail_in = size;
580  int zresult = inflate(&_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
581  if (zresult == Z_STREAM_END) break;
582  if (zresult != Z_OK) {
583  setError("PtexReader error: unzip failed, file corrupt");
584  inflateReset(&_zstream);
585  return 0;
586  }
587  }
588 
589  int total = (int)_zstream.total_out;
590  inflateReset(&_zstream);
591  return total == unzipsize;
592 }
593 
594 
595 void PtexReader::readLevel(int levelid, Level*& level)
596 {
597  // get read lock and make sure we still need to read
598  AutoMutex locker(readlock);
599  if (level) {
600  return;
601  }
602 
603  // go ahead and read the level
604  LevelInfo& l = _levelinfo[levelid];
605 
606  // keep new level local until finished
607  Level* newlevel = new Level(l.nfaces);
608  seek(_levelpos[levelid]);
610  computeOffsets(tell(), l.nfaces, &newlevel->fdh[0], &newlevel->offsets[0]);
611 
612  // apply edits (if any) to level 0
613  if (levelid == 0) {
614  for (size_t i = 0, size = _faceedits.size(); i < size; i++) {
615  FaceEdit& e = _faceedits[i];
616  newlevel->fdh[e.faceid] = e.fdh;
617  newlevel->offsets[e.faceid] = e.pos;
618  }
619  }
620 
621  // don't assign to result until level data is fully initialized
622  AtomicStore(&level, newlevel);
623  increaseMemUsed(level->memUsed());
624 }
625 
626 
627 void PtexReader::readFace(int levelid, Level* level, int faceid, Ptex::Res res)
628 {
629  FaceData*& face = level->faces[faceid];
630  FaceDataHeader fdh = level->fdh[faceid];
631  readFaceData(level->offsets[faceid], fdh, res, levelid, face);
632 }
633 
634 
636 {
637  _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
638 }
639 
640 
641 void PtexReader::readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid,
642  FaceData*& face)
643 {
644  AutoMutex locker(readlock);
645  if (face) {
646  return;
647  }
648 
649  // keep new face local until fully initialized
650  FaceData* newface = 0;
651  size_t newMemUsed = 0;
652 
653  seek(pos);
654  switch (fdh.encoding()) {
655  case enc_constant:
656  {
658  newface = cf;
659  newMemUsed = sizeof(ConstantFace) + _pixelsize;
660  readBlock(cf->data(), _pixelsize);
661  if (levelid==0 && _premultiply && _header.hasAlpha())
662  PtexUtils::multalpha(cf->data(), 1, datatype(),
664  }
665  break;
666  case enc_tiled:
667  {
668  Res tileres;
669  readBlock(&tileres, sizeof(tileres));
670  uint32_t tileheadersize;
671  readBlock(&tileheadersize, sizeof(tileheadersize));
672  TiledFace* tf = new TiledFace(this, res, tileres, levelid);
673  newface = tf;
674  newMemUsed = tf->memUsed();
675  readZipBlock(&tf->_fdh[0], tileheadersize, FaceDataHeaderSize * tf->_ntiles);
676  computeOffsets(tell(), tf->_ntiles, &tf->_fdh[0], &tf->_offsets[0]);
677  }
678  break;
679  case enc_zipped:
680  case enc_diffzipped:
681  {
682  int uw = res.u(), vw = res.v();
683  int npixels = uw * vw;
684  int unpackedSize = _pixelsize * npixels;
685  PackedFace* pf = new PackedFace(res, _pixelsize, unpackedSize);
686  newface = pf;
687  newMemUsed = sizeof(PackedFace) + unpackedSize;
688  bool useNew = unpackedSize > AllocaMax;
689  char* tmp = useNew ? new char [unpackedSize] : (char*) alloca(unpackedSize);
690  readZipBlock(tmp, fdh.blocksize(), unpackedSize);
691  if (fdh.encoding() == enc_diffzipped)
692  PtexUtils::decodeDifference(tmp, unpackedSize, datatype());
693  PtexUtils::interleave(tmp, uw * DataSize(datatype()), uw, vw,
694  pf->data(), uw * _pixelsize,
696  if (levelid==0 && _premultiply && _header.hasAlpha())
697  PtexUtils::multalpha(pf->data(), npixels, datatype(),
699  if (useNew) delete [] tmp;
700  }
701  break;
702  }
703 
704  if (!newface) newface = errorData();
705 
706  AtomicStore(&face, newface);
707  increaseMemUsed(newMemUsed);
708 }
709 
710 
711 void PtexReader::getData(int faceid, void* buffer, int stride)
712 {
713  const FaceInfo& f = getFaceInfo(faceid);
714  getData(faceid, buffer, stride, f.res);
715 }
716 
717 
718 void PtexReader::getData(int faceid, void* buffer, int stride, Res res)
719 {
720  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
721  PtexUtils::fill(&_errorPixel[0], buffer, stride, res.u(), res.v(), _pixelsize);
722  return;
723  }
724 
725  // note - all locking is handled in called getData methods
726  int resu = res.u(), resv = res.v();
727  int rowlen = _pixelsize * resu;
728  if (stride == 0) stride = rowlen;
729 
730  PtexPtr<PtexFaceData> d ( getData(faceid, res) );
731  if (d->isConstant()) {
732  // fill dest buffer with pixel value
733  PtexUtils::fill(d->getData(), buffer, stride,
734  resu, resv, _pixelsize);
735  }
736  else if (d->isTiled()) {
737  // loop over tiles
738  Res tileres = d->tileRes();
739  int ntilesu = res.ntilesu(tileres);
740  int ntilesv = res.ntilesv(tileres);
741  int tileures = tileres.u();
742  int tilevres = tileres.v();
743  int tilerowlen = _pixelsize * tileures;
744  int tile = 0;
745  char* dsttilerow = (char*) buffer;
746  for (int i = 0; i < ntilesv; i++) {
747  char* dsttile = dsttilerow;
748  for (int j = 0; j < ntilesu; j++) {
749  PtexPtr<PtexFaceData> t ( d->getTile(tile++) );
750  if (t->isConstant())
751  PtexUtils::fill(t->getData(), dsttile, stride,
752  tileures, tilevres, _pixelsize);
753  else
754  PtexUtils::copy(t->getData(), tilerowlen, dsttile, stride,
755  tilevres, tilerowlen);
756  dsttile += tilerowlen;
757  }
758  dsttilerow += stride * tilevres;
759  }
760  }
761  else {
762  PtexUtils::copy(d->getData(), rowlen, buffer, stride, resv, rowlen);
763  }
764 }
765 
766 
768 {
769  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
770  return errorData(/*deleteOnRelease*/ true);
771  }
772 
773  FaceInfo& fi = _faceinfo[faceid];
774  if (fi.isConstant() || fi.res == 0) {
775  return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
776  }
777 
778  // get level zero (full) res face
779  Level* level = getLevel(0);
780  FaceData* face = getFace(0, level, faceid, fi.res);
781  return face;
782 }
783 
784 
785 PtexFaceData* PtexReader::getData(int faceid, Res res)
786 {
787  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
788  return errorData(/*deleteOnRelease*/ true);
789  }
790 
791  FaceInfo& fi = _faceinfo[faceid];
792  if (fi.isConstant() || res == 0) {
793  return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
794  }
795 
796  // determine how many reduction levels are needed
797  int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
798 
799  if (redu == 0 && redv == 0) {
800  // no reduction - get level zero (full) res face
801  Level* level = getLevel(0);
802  FaceData* face = getFace(0, level, faceid, res);
803  return face;
804  }
805 
806  if (redu == redv && !fi.hasEdits()) {
807  // reduction is symmetric and non-negative
808  // and face has no edits => access data from reduction level (if present)
809  int levelid = redu;
810  if (size_t(levelid) < _levels.size()) {
811  Level* level = getLevel(levelid);
812 
813  // get reduction face id
814  int rfaceid = _rfaceids[faceid];
815 
816  // get the face data (if present)
817  FaceData* face = 0;
818  if (size_t(rfaceid) < level->faces.size()) {
819  face = getFace(levelid, level, rfaceid, res);
820  }
821  if (face) {
822  return face;
823  }
824  }
825  }
826 
827  // dynamic reduction required - look in dynamic reduction cache
828  ReductionKey key(faceid, res);
829  FaceData* face = _reductions.get(key);
830  if (face) {
831  return face;
832  }
833 
834  // not found, generate new reduction
835  FaceData *newface = 0;
836  size_t newMemUsed = 0;
837 
838  if (res.ulog2 < 0 || res.vlog2 < 0) {
839  std::cerr << "PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
840  newface = errorData();
841  }
842  else if (redu < 0 || redv < 0) {
843  std::cerr << "PtexReader::getData - enlargements not supported" << std::endl;
844  newface = errorData();
845  }
846  else if (_header.meshtype == mt_triangle)
847  {
848  if (redu != redv) {
849  std::cerr << "PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
850  newface = errorData();
851  }
852  else {
853  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)(res.vlog2+1))) );
854  FaceData* src = static_cast<FaceData*>(psrc.get());
855  newface = src->reduce(this, res, PtexUtils::reduceTri, newMemUsed);
856  }
857  }
858  else {
859  // determine which direction to blend
860  bool blendu;
861  if (redu == redv) {
862  // for symmetric face blends, alternate u and v blending
863  blendu = (res.ulog2 & 1);
864  }
865  else blendu = redu > redv;
866 
867  if (blendu) {
868  // get next-higher u-res and reduce in u
869  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2)) );
870  FaceData* src = static_cast<FaceData*>(psrc.get());
871  newface = src->reduce(this, res, PtexUtils::reduceu, newMemUsed);
872  }
873  else {
874  // get next-higher v-res and reduce in v
875  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1))) );
876  FaceData* src = static_cast<FaceData*>(psrc.get());
877  newface = src->reduce(this, res, PtexUtils::reducev, newMemUsed);
878  }
879  }
880 
881  size_t tableNewMemUsed = 0;
882  face = _reductions.tryInsert(key, newface, tableNewMemUsed);
883  if (face != newface) {
884  delete newface;
885  }
886  else {
887  increaseMemUsed(newMemUsed + tableNewMemUsed);
888  }
889  return face;
890 }
891 
892 
893 void PtexReader::getPixel(int faceid, int u, int v,
894  float* result, int firstchan, int nchannelsArg)
895 {
896  memset(result, 0, sizeof(*result)*nchannelsArg);
897 
898  // clip nchannels against actual number available
899  nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
900  if (nchannelsArg <= 0) return;
901 
902  // get raw pixel data
903  PtexPtr<PtexFaceData> data ( getData(faceid) );
904  void* pixel = alloca(_pixelsize);
905  data->getPixel(u, v, pixel);
906 
907  // adjust for firstchan offset
908  int datasize = DataSize(datatype());
909  if (firstchan)
910  pixel = (char*) pixel + datasize * firstchan;
911 
912  // convert/copy to result as needed
913  if (datatype() == dt_float)
914  memcpy(result, pixel, datasize * nchannelsArg);
915  else
916  ConvertToFloat(result, pixel, datatype(), nchannelsArg);
917 }
918 
919 
920 void PtexReader::getPixel(int faceid, int u, int v,
921  float* result, int firstchan, int nchannelsArg,
922  Ptex::Res res)
923 {
924  memset(result, 0, nchannelsArg);
925 
926  // clip nchannels against actual number available
927  nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
928  if (nchannelsArg <= 0) return;
929 
930  // get raw pixel data
931  PtexPtr<PtexFaceData> data ( getData(faceid, res) );
932  void* pixel = alloca(_pixelsize);
933  data->getPixel(u, v, pixel);
934 
935  // adjust for firstchan offset
936  int datasize = DataSize(datatype());
937  if (firstchan)
938  pixel = (char*) pixel + datasize * firstchan;
939 
940  // convert/copy to result as needed
941  if (datatype() == dt_float)
942  memcpy(result, pixel, datasize * nchannelsArg);
943  else
944  ConvertToFloat(result, pixel, datatype(), nchannelsArg);
945 }
946 
947 
950  size_t& newMemUsed)
951 {
952  // allocate a new face and reduce image
953  DataType dt = r->datatype();
954  int nchan = r->nchannels();
955  int memsize = _pixelsize * newres.size();
956  PackedFace* pf = new PackedFace(newres, _pixelsize, memsize);
957  newMemUsed = sizeof(PackedFace) + memsize;
958  // reduce and copy into new face
959  reducefn(_data, _pixelsize * _res.u(), _res.u(), _res.v(),
960  pf->_data, _pixelsize * newres.u(), dt, nchan);
961  return pf;
962 }
963 
964 
965 
967 {
968  // must make a new constant face (even though it's identical to this one)
969  // because it will be owned by a different reduction level
970  // and will therefore have a different parent
972  newMemUsed = sizeof(ConstantFace) + _pixelsize;
973  memcpy(pf->_data, _data, _pixelsize);
974  return pf;
975 }
976 
977 
980  size_t& newMemUsed)
981 {
982  /* Tiled reductions should generally only be anisotropic (just u
983  or v, not both) since isotropic reductions are precomputed and
984  stored on disk. (This function should still work for isotropic
985  reductions though.)
986 
987  In the anisotropic case, the number of tiles should be kept the
988  same along the direction not being reduced in order to preserve
989  the laziness of the file access. In contrast, if reductions
990  were not tiled, then any reduction would read all the tiles and
991  defeat the purpose of tiling.
992  */
993 
994  // keep new face local until fully initialized
995  FaceData* newface = 0;
996 
997  // don't tile triangle reductions (too complicated)
998  Res newtileres;
999  bool isTriangle = r->_header.meshtype == mt_triangle;
1000  if (isTriangle) {
1001  newtileres = newres;
1002  }
1003  else {
1004  // propagate the tile res to the reduction
1005  newtileres = _tileres;
1006  // but make sure tile isn't larger than the new face!
1007  if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1008  if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1009  }
1010 
1011 
1012  // determine how many tiles we will have on the reduction
1013  int newntiles = newres.ntiles(newtileres);
1014 
1015  if (newntiles == 1) {
1016  // no need to keep tiling, reduce tiles into a single face
1017  // first, get all tiles and check if they are constant (with the same value)
1018  PtexFaceData** tiles = (PtexFaceData**) alloca(_ntiles * sizeof(PtexFaceData*));
1019  bool allConstant = true;
1020  for (int i = 0; i < _ntiles; i++) {
1021  PtexFaceData* tile = tiles[i] = getTile(i);
1022  allConstant = (allConstant && tile->isConstant() &&
1023  (i == 0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
1024  _pixelsize))));
1025  }
1026  if (allConstant) {
1027  // allocate a new constant face
1028  newface = new ConstantFace(_pixelsize);
1029  memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1030  newMemUsed = sizeof(ConstantFace) + _pixelsize;
1031  }
1032  else if (isTriangle) {
1033  // reassemble all tiles into temporary contiguous image
1034  // (triangle reduction doesn't work on tiles)
1035  int tileures = _tileres.u();
1036  int tilevres = _tileres.v();
1037  int sstride = _pixelsize * tileures;
1038  int dstride = sstride * _ntilesu;
1039  int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1040 
1041  char* tmp = new char [_ntiles * _tileres.size() * _pixelsize];
1042  char* tmpptr = tmp;
1043  for (int i = 0; i < _ntiles;) {
1044  PtexFaceData* tile = tiles[i];
1045  if (tile->isConstant())
1046  PtexUtils::fill(tile->getData(), tmpptr, dstride,
1047  tileures, tilevres, _pixelsize);
1048  else
1049  PtexUtils::copy(tile->getData(), sstride, tmpptr, dstride, tilevres, sstride);
1050  i++;
1051  tmpptr += (i%_ntilesu) ? sstride : dstepv;
1052  }
1053 
1054  // allocate a new packed face
1055  int memsize = _pixelsize * newres.size();
1056  newface = new PackedFace(newres, _pixelsize, memsize);
1057  newMemUsed = sizeof(PackedFace) + memsize;
1058  // reduce and copy into new face
1059  reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
1060  newface->getData(), _pixelsize * newres.u(), _dt, _nchan);
1061 
1062  delete [] tmp;
1063  }
1064  else {
1065  // allocate a new packed face
1066  int memsize = _pixelsize * newres.size();
1067  newface = new PackedFace(newres, _pixelsize, memsize);
1068  newMemUsed = sizeof(PackedFace) + memsize;
1069 
1070  int tileures = _tileres.u();
1071  int tilevres = _tileres.v();
1072  int sstride = _pixelsize * tileures;
1073  int dstride = _pixelsize * newres.u();
1074  int dstepu = dstride/_ntilesu;
1075  int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1076 
1077  char* dst = (char*) newface->getData();
1078  for (int i = 0; i < _ntiles;) {
1079  PtexFaceData* tile = tiles[i];
1080  if (tile->isConstant())
1081  PtexUtils::fill(tile->getData(), dst, dstride,
1082  newres.u()/_ntilesu, newres.v()/_ntilesv,
1083  _pixelsize);
1084  else
1085  reducefn(tile->getData(), sstride, tileures, tilevres,
1086  dst, dstride, _dt, _nchan);
1087  i++;
1088  dst += (i%_ntilesu) ? dstepu : dstepv;
1089  }
1090  }
1091  // release the tiles
1092  for (int i = 0; i < _ntiles; i++) tiles[i]->release();
1093  }
1094  else {
1095  // otherwise, tile the reduced face
1096  TiledReducedFace* tf = new TiledReducedFace(_reader, newres, newtileres, this, reducefn);
1097  newface = tf;
1098  newMemUsed = tf->memUsed();
1099  }
1100  return newface;
1101 }
1102 
1103 
1104 void PtexReader::TiledFaceBase::getPixel(int ui, int vi, void* result)
1105 {
1106  int tileu = ui >> _tileres.ulog2;
1107  int tilev = vi >> _tileres.vlog2;
1108  PtexPtr<PtexFaceData> tile ( getTile(tilev * _ntilesu + tileu) );
1109  tile->getPixel(ui - (tileu<<_tileres.ulog2),
1110  vi - (tilev<<_tileres.vlog2), result);
1111 }
1112 
1113 
1114 
1116 {
1117  FaceData*& face = _tiles[tile];
1118  if (face) {
1119  return face;
1120  }
1121 
1122  // first, get all parent tiles for this tile
1123  // and check if they are constant (with the same value)
1124  int pntilesu = _parentface->ntilesu();
1125  int pntilesv = _parentface->ntilesv();
1126  int nu = pntilesu / _ntilesu; // num parent tiles for this tile in u dir
1127  int nv = pntilesv / _ntilesv; // num parent tiles for this tile in v dir
1128 
1129  int ntilesval = nu*nv; // num parent tiles for this tile
1130  PtexFaceData** tiles = (PtexFaceData**) alloca(ntilesval * sizeof(PtexFaceData*));
1131  bool allConstant = true;
1132  int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1133  for (int i = 0; i < ntilesval;) {
1134  PtexFaceData* tileval = tiles[i] = _parentface->getTile(ptile);
1135  allConstant = (allConstant && tileval->isConstant() &&
1136  (i==0 || (0 == memcmp(tiles[0]->getData(), tileval->getData(),
1137  _pixelsize))));
1138  i++;
1139  ptile += (i%nu)? 1 : pntilesu - nu + 1;
1140  }
1141 
1142  FaceData* newface = 0;
1143  size_t newMemUsed = 0;
1144  if (allConstant) {
1145  // allocate a new constant face
1146  newface = new ConstantFace(_pixelsize);
1147  newMemUsed = sizeof(ConstantFace) + _pixelsize;
1148  memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1149  }
1150  else {
1151  // allocate a new packed face for the tile
1152  int memsize = _pixelsize*_tileres.size();
1153  newface = new PackedFace(_tileres, _pixelsize, memsize);
1154  newMemUsed = sizeof(PackedFace) + memsize;
1155 
1156  // generate reduction from parent tiles
1157  int ptileures = _parentface->tileres().u();
1158  int ptilevres = _parentface->tileres().v();
1159  int sstride = ptileures * _pixelsize;
1160  int dstride = _tileres.u() * _pixelsize;
1161  int dstepu = dstride/nu;
1162  int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1163 
1164  char* dst = (char*) newface->getData();
1165  for (int i = 0; i < ntilesval;) {
1166  PtexFaceData* tileval = tiles[i];
1167  if (tileval->isConstant())
1168  PtexUtils::fill(tileval->getData(), dst, dstride,
1169  _tileres.u()/nu, _tileres.v()/nv,
1170  _pixelsize);
1171  else
1172  _reducefn(tileval->getData(), sstride, ptileures, ptilevres,
1173  dst, dstride, _dt, _nchan);
1174  i++;
1175  dst += (i%nu) ? dstepu : dstepv;
1176  }
1177  }
1178 
1179  if (!AtomicCompareAndSwap(&face, (FaceData*)0, newface)) {
1180  delete newface;
1181  }
1182  else {
1183  _reader->increaseMemUsed(newMemUsed);
1184  }
1185 
1186  return face;
1187 }
1188 
et_editmetadata
@ et_editmetadata
Definition: PtexIO.h:92
PtexReader::PackedFace::data
void * data()
Definition: PtexReader.h:382
PtexReader::getData
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition: PtexReader.cpp:711
PtexReader::_constdatapos
FilePos _constdatapos
Definition: PtexReader.h:651
PtexReader::MetaEdit::memsize
int memsize
Definition: PtexReader.h:673
PtexHashMap::tryInsert
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Definition: PtexHashMap.h:224
PtexReader::_hasEdits
bool _hasEdits
Definition: PtexReader.h:661
PtexReader::getLevel
Level * getLevel(int levelid)
Definition: PtexReader.h:572
PtexReader::MetaData
Definition: PtexReader.h:120
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
Ptex::Res
Pixel resolution of a given texture.
Definition: Ptexture.h:172
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:147
PtexReader::purge
void purge()
Definition: PtexReader.cpp:115
PtexReader::MetaData::Entry::isLmd
bool isLmd
Definition: PtexReader.h:289
PtexReader::MetaData::Entry::lmdData
LargeMetaData * lmdData
Definition: PtexReader.h:290
Header::leveldatasize
uint64_t leveldatasize
Definition: PtexIO.h:58
PtexHashMap::clear
void clear()
Definition: PtexHashMap.h:195
PtexInputHandler::open
virtual Handle open(const char *path)=0
Open a file in read mode.
PtexFaceData::isTiled
virtual bool isTiled()=0
True if this data block is tiled.
LevelInfo::nfaces
uint32_t nfaces
Definition: PtexIO.h:78
PtexReader::readLargeMetaDataHeaders
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:440
PtexReader::MetaData::addEntry
void addEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, const void *data, size_t &metaDataMemUsed)
Definition: PtexReader.h:246
PtexReader::MetaData::Entry::datasize
uint32_t datasize
Definition: PtexReader.h:287
EditFaceDataHeader::faceinfo
FaceInfo faceinfo
Definition: PtexIO.h:95
PtexReader::_metaedits
std::vector< MetaEdit > _metaedits
Definition: PtexReader.h:675
Header
Definition: PtexIO.h:44
PtexReader::readlock
Mutex readlock
Definition: PtexReader.h:637
PtexReader::MetaData::addLmdEntry
void addLmdEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, FilePos filepos, uint32_t zipsize, size_t &metaDataMemUsed)
Definition: PtexReader.h:255
PtexReader::FaceData
Definition: PtexReader.h:365
PtexReader::getConstData
uint8_t * getConstData()
Definition: PtexReader.h:579
PtexReader::prune
void prune()
Definition: PtexReader.cpp:104
PtexReader::_faceinfopos
FilePos _faceinfopos
Definition: PtexReader.h:650
Header::pixelSize
int pixelSize() const
Definition: PtexIO.h:61
FaceDataHeader::encoding
Encoding encoding() const
Definition: PtexIO.h:85
ExtHeader::editdatapos
uint64_t editdatapos
Definition: PtexIO.h:73
Header::magic
uint32_t magic
Definition: PtexIO.h:45
PtexReader::ConstantFace
Definition: PtexReader.h:401
PtexReader::_fp
PtexInputHandler::Handle _fp
Definition: PtexReader.h:645
PtexReader::getFace
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.h:580
PtexReader::datatype
DataType datatype() const
Definition: PtexReader.h:113
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexHashMap::get
Value get(Key &key)
Definition: PtexHashMap.h:203
PtexReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition: PtexReader.h:56
LevelInfo::levelheadersize
uint32_t levelheadersize
Definition: PtexIO.h:77
PtexReader::_err
PtexErrorHandler * _err
Definition: PtexReader.h:640
PtexReader::_editdatapos
FilePos _editdatapos
Definition: PtexReader.h:657
EditFaceDataHeader
Definition: PtexIO.h:93
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexReader::_levelinfopos
FilePos _levelinfopos
Definition: PtexReader.h:652
PtexReader::readZipBlock
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition: PtexReader.cpp:563
PtexReader::Level::fdh
std::vector< FaceDataHeader > fdh
Definition: PtexReader.h:522
PtexReader::_metadatapos
FilePos _metadatapos
Definition: PtexReader.h:654
PtexReader::computeOffsets
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition: PtexReader.h:605
PtexReader::_premultiply
bool _premultiply
Definition: PtexReader.h:641
PtexReader::readFaceData
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition: PtexReader.cpp:641
PtexReader::FaceEdit
Definition: PtexReader.h:678
PtexReader::_levels
std::vector< Level * > _levels
Definition: PtexReader.h:667
PtexReader::_levelinfo
std::vector< LevelInfo > _levelinfo
Definition: PtexReader.h:665
EditFaceDataHeaderSize
const int EditFaceDataHeaderSize
Definition: PtexIO.h:109
Ptex::dt_float
@ dt_float
Single-precision (32-bit) floating point.
Definition: Ptexture.h:89
PtexFaceData::tileRes
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.
PtexUtils::ReduceFn
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.h:174
PtexReader::MetaEdit::zipsize
int zipsize
Definition: PtexReader.h:672
PtexReader::MetaData::getEntry
Entry * getEntry(int index)
Definition: PtexReader.cpp:343
PtexUtils.h
PtexReader::needToOpen
bool needToOpen() const
Definition: PtexReader.h:57
PtexReader::_faceinfo
std::vector< FaceInfo > _faceinfo
Definition: PtexReader.h:663
PtexReader::getPixel
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
Definition: PtexReader.cpp:893
PtexUtils::fill
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:416
Header::nlevels
uint16_t nlevels
Definition: PtexIO.h:51
PtexReader::TiledFace::memUsed
size_t memUsed()
Definition: PtexReader.h:486
Ptex::DataSize
int DataSize(DataType dt)
Look up size of given data type (in bytes).
Definition: Ptexture.h:143
PtexReader::tryClose
bool tryClose()
Definition: PtexReader.cpp:219
AutoLock
Automatically acquire and release lock within enclosing scope.
Definition: PtexMutex.h:43
PtexReader::seek
void seek(FilePos pos)
Definition: PtexReader.h:558
PtexReader::ConstDataPtr
Definition: PtexReader.h:345
LittleEndian
bool LittleEndian()
Definition: PtexIO.h:119
PtexReader::Level::faces
std::vector< FaceData * > faces
Definition: PtexReader.h:524
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:267
PtexReader::tell
FilePos tell()
Definition: PtexReader.h:557
Header::constdatasize
uint32_t constdatasize
Definition: PtexIO.h:55
PtexReader::_pixelsize
int _pixelsize
Definition: PtexReader.h:658
PtexInputHandler::close
virtual bool close(Handle handle)=0
Close a file.
PtexMetaData
Meta data accessor.
Definition: Ptexture.h:341
Header::metadatazipsize
uint32_t metadatazipsize
Definition: PtexIO.h:59
PtexReader::MetaData::Entry
Definition: PtexReader.h:284
EditMetaDataHeader::metadatamemsize
uint32_t metadatamemsize
Definition: PtexIO.h:100
EditMetaDataHeader
Definition: PtexIO.h:98
Ptex::DataType
DataType
Type of data stored in texture file.
Definition: Ptexture.h:85
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition: Ptexture.h:671
PtexReader::PackedFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:949
PtexReader::Level
Definition: PtexReader.h:520
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:242
ExtHeader::editdatasize
uint64_t editdatasize
Definition: PtexIO.h:72
PtexUtils::copy
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition: PtexUtils.cpp:432
AllocaMax
const int AllocaMax
Definition: PtexIO.h:116
PtexReader::MetaData::LargeMetaData
Definition: PtexReader.h:273
LevelInfoSize
const int LevelInfoSize
Definition: PtexIO.h:107
PtexReader::_errorPixel
std::vector< char > _errorPixel
Definition: PtexReader.h:714
EditFaceDataHeader::fdh
FaceDataHeader fdh
Definition: PtexIO.h:96
PtexReader::_header
Header _header
Definition: PtexReader.h:648
PtexInputHandler::read
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
PtexReader::reopenFP
bool reopenFP()
Definition: PtexReader.cpp:240
PtexReader::_memUsed
volatile size_t _memUsed
Definition: PtexReader.h:718
PtexReader::nchannels
int nchannels() const
Definition: PtexReader.h:114
HeaderSize
const int HeaderSize
Definition: PtexIO.h:105
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:273
FaceDataHeaderSize
const int FaceDataHeaderSize
Definition: PtexIO.h:108
PtexUtils::reducev
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:360
Mutex::trylock
bool trylock()
Definition: PtexPlatform.h:131
PtexReader::TiledFaceBase::getPixel
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
Definition: PtexReader.cpp:1104
ExtHeaderSize
const int ExtHeaderSize
Definition: PtexIO.h:106
PtexReader::MetaData::_reader
PtexReader * _reader
Definition: PtexReader.h:338
PtexReader::readEditFaceData
void readEditFaceData()
Definition: PtexReader.cpp:502
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition: Ptexture.h:632
enc_constant
@ enc_constant
Definition: PtexIO.h:81
PtexReader::open
bool open(const char *path, Ptex::String &error)
Definition: PtexReader.cpp:137
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexReader::readEditMetaData
void readEditMetaData()
Definition: PtexReader.cpp:533
PtexUtils::interleave
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:183
PtexReader::_pos
FilePos _pos
Definition: PtexReader.h:646
PtexReader::MetaData::Entry::lmdZipSize
uint32_t lmdZipSize
Definition: PtexReader.h:292
PtexFaceData::getPixel
virtual void getPixel(int u, int v, void *result)=0
Read a single texel from the data block.
PtexReader::MetaData::_entries
std::vector< Entry * > _entries
Definition: PtexReader.h:341
ExtHeader
Definition: PtexIO.h:64
Header::nfaces
uint32_t nfaces
Definition: PtexIO.h:52
PtexReader::readEditData
void readEditData()
Definition: PtexReader.cpp:468
enc_zipped
@ enc_zipped
Definition: PtexIO.h:81
PtexReader::_io
PtexInputHandler * _io
Definition: PtexReader.h:639
et_editfacedata
@ et_editfacedata
Definition: PtexIO.h:92
FaceDataHeader
Definition: PtexIO.h:82
PtexReader::TiledFace::readTile
void readTile(int tile, FaceData *&data)
Definition: PtexReader.cpp:635
BlockSize
const int BlockSize
Definition: PtexIO.h:114
PtexReader::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition: PtexReader.cpp:267
Ptex::mt_triangle
@ mt_triangle
Mesh is triangle-based.
Definition: Ptexture.h:80
Ptex::String
Memory-managed string.
Definition: Ptexture.h:309
PtexPtr::get
T * get() const
Get pointer value.
Definition: Ptexture.h:1061
PtexReader::MetaEdit::pos
FilePos pos
Definition: PtexReader.h:671
PtexFaceData
Per-face texture data accessor.
Definition: Ptexture.h:419
Header::faceinfosize
uint32_t faceinfosize
Definition: PtexIO.h:54
PtexReader::FaceData::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
PtexReader.h
PtexReader::ConstantFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:966
PtexTexture::open
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition: PtexReader.cpp:59
PtexReader::TiledReducedFace::getTile
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
Definition: PtexReader.cpp:1115
EditMetaDataHeader::metadatazipsize
uint32_t metadatazipsize
Definition: PtexIO.h:99
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1045
PtexReader::_path
std::string _path
Definition: PtexReader.h:647
PtexReader::TiledFaceBase::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:979
PtexReader::readLevel
void readLevel(int levelid, Level *&level)
Definition: PtexReader.cpp:595
FaceDataHeader::blocksize
uint32_t blocksize() const
Definition: PtexIO.h:84
PtexReader::_pendingPurge
bool _pendingPurge
Definition: PtexReader.h:644
PtexReader::Level::memUsed
size_t memUsed()
Definition: PtexReader.h:537
PtexReader::FaceEdit::faceid
int faceid
Definition: PtexReader.h:680
PtexReader::_lmddatapos
FilePos _lmddatapos
Definition: PtexReader.h:656
PtexReader::TiledFace::_fdh
std::vector< FaceDataHeader > _fdh
Definition: PtexReader.h:493
PtexTexture
Interface for reading data from a ptex file.
Definition: Ptexture.h:470
Header::hasAlpha
bool hasAlpha() const
Definition: PtexIO.h:62
PtexReader::_extheader
ExtHeader _extheader
Definition: PtexReader.h:649
PtexReader::Level::offsets
std::vector< FilePos > offsets
Definition: PtexReader.h:523
PtexUtils::decodeDifference
void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:265
PtexReader::readBlock
bool readBlock(void *data, int size, bool reportError=true)
Definition: PtexReader.cpp:548
PtexReader::TiledReducedFace
Definition: PtexReader.h:498
PtexReader::readConstData
void readConstData()
Definition: PtexReader.cpp:319
PtexReader::_ok
bool _ok
Definition: PtexReader.h:642
PtexReader::TiledFace::_offsets
std::vector< FilePos > _offsets
Definition: PtexReader.h:494
PtexReader::_leveldatapos
FilePos _leveldatapos
Definition: PtexReader.h:653
PtexErrorHandler::reportError
virtual void reportError(const char *error)=0
PtexUtils::max
T max(T a, T b)
Definition: PtexUtils.h:150
PtexUtils::reduceu
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:327
LevelInfo
Definition: PtexIO.h:75
PtexReader::readFace
void readFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.cpp:627
ExtHeader::lmddatasize
uint64_t lmddatasize
Definition: PtexIO.h:71
Header::version
uint32_t version
Definition: PtexIO.h:46
PtexTexture::path
virtual const char * path()=0
Path that file was opened with.
PtexReader
Definition: PtexReader.h:52
PtexReader::MetaData::Entry::data
char * data
Definition: PtexReader.h:288
ExtHeader::lmdheaderzipsize
uint32_t lmdheaderzipsize
Definition: PtexIO.h:69
PtexReader::readFaceInfo
void readFaceInfo()
Definition: PtexReader.cpp:277
PtexReader::_metadata
MetaData * _metadata
Definition: PtexReader.h:660
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
ConvertToFloat
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition: PtexUtils.cpp:117
PtexReader::readLevelInfo
void readLevelInfo()
Definition: PtexReader.cpp:298
PtexReader::PtexReader
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition: PtexReader.cpp:71
PtexReader::_rfaceids
std::vector< uint32_t > _rfaceids
Definition: PtexReader.h:664
PtexReader::_needToOpen
bool _needToOpen
Definition: PtexReader.h:643
PtexReader::logOpen
void logOpen()
Definition: PtexReader.h:72
enc_diffzipped
@ enc_diffzipped
Definition: PtexIO.h:81
PtexReader::_lmdheaderpos
FilePos _lmdheaderpos
Definition: PtexReader.h:655
PtexReader::FaceEdit::fdh
FaceDataHeader fdh
Definition: PtexReader.h:681
PtexUtils::genRfaceids
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:624
PtexReader::ReductionKey
Definition: PtexReader.h:685
PtexReader::PackedFace
Definition: PtexReader.h:377
PtexReader::MetaEdit
Definition: PtexReader.h:670
Header::extheadersize
uint32_t extheadersize
Definition: PtexIO.h:53
Magic
const uint32_t Magic
Definition: PtexIO.h:104
enc_tiled
@ enc_tiled
Definition: PtexIO.h:81
PtexReader::readMetaDataBlock
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:414
EditFaceDataHeader::faceid
uint32_t faceid
Definition: PtexIO.h:94
PtexReader::getMetaData
virtual PtexMetaData * getMetaData()
Access meta data.
Definition: PtexReader.cpp:335
PtexReader::closeFP
void closeFP()
Definition: PtexReader.cpp:230
PtexReader::TiledFace
Definition: PtexReader.h:470
Header::levelinfosize
uint32_t levelinfosize
Definition: PtexIO.h:56
Header::alphachan
int32_t alphachan
Definition: PtexIO.h:49
PtexReader::~PtexReader
virtual ~PtexReader()
Definition: PtexReader.cpp:93
PtexReader::MetaData::LargeMetaData::data
void * data()
Definition: PtexReader.h:278
PtexReader::_baseMemUsed
size_t _baseMemUsed
Definition: PtexReader.h:717
PtexInputHandler::lastError
virtual const char * lastError()=0
Return the last error message encountered.
PtexReader::MetaData::selfDataSize
size_t selfDataSize()
Definition: PtexReader.h:266
Header::nchannels
uint16_t nchannels
Definition: PtexIO.h:50
Ptexture.h
Public API classes for reading, writing, caching, and filtering Ptex files.
PtexUtils::multalpha
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:573
PtexReader::_levelpos
std::vector< FilePos > _levelpos
Definition: PtexReader.h:666
PtexReader::_reductions
ReductionMap _reductions
Definition: PtexReader.h:713
PtexReader::_constdata
uint8_t * _constdata
Definition: PtexReader.h:659
PtexReader::MetaData::Entry::lmdPos
FilePos lmdPos
Definition: PtexReader.h:291
PtexReader::TiledFaceBase::_ntiles
int _ntiles
Definition: PtexReader.h:464
EditMetaDataHeaderSize
const int EditMetaDataHeaderSize
Definition: PtexIO.h:110
PtexReader::PackedFace::_data
char * _data
Definition: PtexReader.h:398
PtexReader::errorData
FaceData * errorData(bool deleteOnRelease=false)
Definition: PtexReader.h:600
Ptex::Res::ntilesu
int ntilesu(Res tileres) const
Determine the number of tiles in the u direction for the given tile res.
Definition: Ptexture.h:219
Ptex::String::c_str
const char * c_str() const
Definition: Ptexture.h:317
Header::meshtype
uint32_t meshtype
Definition: PtexIO.h:47
ExtHeader::lmdheadermemsize
uint32_t lmdheadermemsize
Definition: PtexIO.h:70
PtexReader::FaceEdit::pos
FilePos pos
Definition: PtexReader.h:679
PtexReader::setError
void setError(const char *error)
Definition: PtexReader.h:546
PtexReader::increaseMemUsed
void increaseMemUsed(size_t amount)
Definition: PtexReader.h:71
PtexReader::readMetaData
void readMetaData()
Definition: PtexReader.cpp:381
PtexReader::_faceedits
std::vector< FaceEdit > _faceedits
Definition: PtexReader.h:683
PtexUtils::reduceTri
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:400
PtexReader::_zstream
z_stream_s _zstream
Definition: PtexReader.h:716
Header::metadatamemsize
uint32_t metadatamemsize
Definition: PtexIO.h:60
PtexPlatform.h
Platform-specific classes, functions, and includes.
Mutex::unlock
void unlock()
Definition: PtexPlatform.h:132
FilePos
off_t FilePos
Definition: PtexPlatform.h:88
PtexReader::TiledReducedFace::memUsed
size_t memUsed()
Definition: PtexReader.h:512