- Timestamp:
- 08/17/11 10:38:53 (13 years ago)
- Location:
- ps/trunk/source/lib
- Files:
-
- 11 edited
-
allocators/dynarray.cpp (modified) (6 diffs)
-
allocators/dynarray.h (modified) (1 diff)
-
allocators/tests/test_allocators.h (modified) (1 diff)
-
tex/tex.cpp (modified) (16 diffs)
-
tex/tex_bmp.cpp (modified) (1 diff)
-
tex/tex_codec.h (modified) (2 diffs)
-
tex/tex_dds.cpp (modified) (1 diff)
-
tex/tex_internal.h (modified) (1 diff)
-
tex/tex_jpg.cpp (modified) (7 diffs)
-
tex/tex_png.cpp (modified) (5 diffs)
-
tex/tex_tga.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/source/lib/allocators/dynarray.cpp
r9462 r10024 32 32 33 33 34 // indicates that this DynArray must not be resized or freed35 // (e.g. because it merely wraps an existing memory range).36 // stored in da->prot to reduce size; doesn't conflict with any PROT_* flags.37 const int DA_NOT_OUR_MEM = 0x40000000;38 39 34 static Status validate_da(DynArray* da) 40 35 { … … 58 53 if(pos > cur_size || pos > max_size_pa) 59 54 WARN_RETURN(ERR::_5); 60 if(prot & ~(PROT_READ|PROT_WRITE|PROT_EXEC |DA_NOT_OUR_MEM))55 if(prot & ~(PROT_READ|PROT_WRITE|PROT_EXEC)) 61 56 WARN_RETURN(ERR::_6); 62 57 … … 92 87 u8* p = da->base; 93 88 size_t size_pa = da->max_size_pa; 94 bool was_wrapped = (da->prot & DA_NOT_OUR_MEM) != 0;95 89 96 90 // wipe out the DynArray for safety … … 98 92 memset(da, 0, sizeof(*da)); 99 93 100 // skip mem_Release if <da> was allocated via da_wrap_fixed 101 // (i.e. it doesn't actually own any memory). don't complain; 102 // da_free is supposed to be called even in the above case. 103 if(!was_wrapped && size_pa) 94 if(size_pa) 104 95 RETURN_STATUS_IF_ERR(mem_Release(p, size_pa)); 105 96 return INFO::OK; … … 110 101 { 111 102 CHECK_DA(da); 112 113 if(da->prot & DA_NOT_OUR_MEM)114 WARN_RETURN(ERR::LOGIC);115 103 116 104 // determine how much to add/remove … … 155 143 CHECK_DA(da); 156 144 157 // somewhat more subtle: POSIX mprotect requires the memory have been158 // mmap-ed, which it probably wasn't here.159 if(da->prot & DA_NOT_OUR_MEM)160 WARN_RETURN(ERR::LOGIC);161 162 145 da->prot = prot; 163 146 RETURN_STATUS_IF_ERR(mem_Protect(da->base, da->cur_size_pa, prot)); 164 147 165 148 CHECK_DA(da); 166 return INFO::OK;167 }168 169 170 Status da_wrap_fixed(DynArray* da, u8* p, size_t size)171 {172 da->base = p;173 da->max_size_pa = Align<pageSize>(size);174 da->cur_size = size;175 da->cur_size_pa = da->max_size_pa;176 da->prot = PROT_READ|PROT_WRITE|DA_NOT_OUR_MEM;177 da->pos = 0;178 CHECK_DA(da);179 return INFO::OK;180 }181 182 183 Status da_read(DynArray* da, void* data, size_t size)184 {185 // make sure we have enough data to read186 if(da->pos+size > da->cur_size)187 WARN_RETURN(ERR::FAIL);188 189 memcpy(data, da->base+da->pos, size);190 da->pos += size;191 149 return INFO::OK; 192 150 } -
ps/trunk/source/lib/allocators/dynarray.h
r9410 r10024 111 111 112 112 /** 113 * "wrap" (i.e. store information about) the given buffer in a DynArray.114 *115 * this is used to allow calling da_read or da_append on normal buffers.116 * da_free should be called when the DynArray is no longer needed,117 * even though it doesn't free this memory (but does zero the DynArray).118 *119 * @param da DynArray. Note: any future operations on it that would120 * change the underlying memory (e.g. da_set_size) will fail.121 * @param p target memory (no alignment/padding requirements)122 * @param size maximum size (no alignment requirements)123 * @return Status.124 **/125 LIB_API Status da_wrap_fixed(DynArray* da, u8* p, size_t size);126 127 /**128 * "read" from array, i.e. copy into the given buffer.129 *130 * starts at offset DynArray.pos and advances this.131 *132 * @param da DynArray.133 * @param data_dst destination memory134 * @param size [bytes] to copy135 * @return Status.136 **/137 LIB_API Status da_read(DynArray* da, void* data_dst, size_t size);138 139 /**140 113 * "write" to array, i.e. copy from the given buffer. 141 114 * -
ps/trunk/source/lib/allocators/tests/test_allocators.h
r9361 r10024 38 38 TS_ASSERT_OK(da_set_prot(&da, PROT_NONE)); 39 39 TS_ASSERT_OK(da_free(&da)); 40 41 // test wrapping existing mem blocks for use with da_read42 u8 data[4] = { 0x12, 0x34, 0x56, 0x78 };43 TS_ASSERT_OK(da_wrap_fixed(&da, data, sizeof(data)));44 u8 buf[4];45 TS_ASSERT_OK(da_read(&da, buf, 4));46 TS_ASSERT_EQUALS(read_le32(buf), (u32)0x78563412); // read correct value47 debug_SkipErrors(ERR::FAIL);48 TS_ASSERT(da_read(&da, buf, 1) < 0); // no more data left49 TS_ASSERT_EQUALS((uint32_t)debug_StopSkippingErrors(), (uint32_t)1);50 TS_ASSERT_OK(da_free(&da));51 40 } 52 41 }; -
ps/trunk/source/lib/tex/tex.cpp
r9447 r10024 146 146 { 147 147 // used to skip past this mip level in <data> 148 const size_t level_data _size = (size_t)(round_up(level_w, data_padding) * round_up(level_h, data_padding) * bpp/8);148 const size_t level_dataSize = (size_t)(round_up(level_w, data_padding) * round_up(level_h, data_padding) * bpp/8); 149 149 150 150 if(level >= 0) 151 cb((size_t)level, level_w, level_h, level_data, level_data _size, cbData);152 153 level_data += level_data _size;151 cb((size_t)level, level_w, level_h, level_data, level_dataSize, cbData); 152 153 level_data += level_dataSize; 154 154 155 155 // 1x1 reached - done … … 180 180 size_t prev_level_h; 181 181 const u8* prev_level_data; 182 size_t prev_level_data _size;182 size_t prev_level_dataSize; 183 183 }; 184 184 185 185 // uses 2x2 box filter 186 static void create_level(size_t level, size_t level_w, size_t level_h, const u8* RESTRICT level_data, size_t level_data _size, void* RESTRICT cbData)186 static void create_level(size_t level, size_t level_w, size_t level_h, const u8* RESTRICT level_data, size_t level_dataSize, void* RESTRICT cbData) 187 187 { 188 188 CreateLevelData* cld = (CreateLevelData*)cbData; … … 195 195 if(level == 0) 196 196 { 197 ENSURE(level_data _size == cld->prev_level_data_size);198 memcpy(dst, src, level_data _size);197 ENSURE(level_dataSize == cld->prev_level_dataSize); 198 memcpy(dst, src, level_dataSize); 199 199 } 200 200 else … … 240 240 } 241 241 242 ENSURE(dst == level_data + level_data _size);243 ENSURE(src == cld->prev_level_data + cld->prev_level_data _size);242 ENSURE(dst == level_data + level_dataSize); 243 ENSURE(src == cld->prev_level_data + cld->prev_level_dataSize); 244 244 } 245 245 246 246 cld->prev_level_data = level_data; 247 cld->prev_level_data _size = level_data_size;247 cld->prev_level_dataSize = level_dataSize; 248 248 cld->prev_level_w = level_w; 249 249 cld->prev_level_h = level_h; … … 251 251 252 252 253 static Status add_mipmaps(Tex* t, size_t w, size_t h, size_t bpp, void* newData, size_t data _size)253 static Status add_mipmaps(Tex* t, size_t w, size_t h, size_t bpp, void* newData, size_t dataSize) 254 254 { 255 255 // this code assumes the image is of POT dimension; we don't … … 262 262 shared_ptr<u8> mipmapData; 263 263 AllocateAligned(mipmapData, mipmap_size); 264 CreateLevelData cld = { bpp/8, w, h, (const u8*)newData, data _size };264 CreateLevelData cld = { bpp/8, w, h, (const u8*)newData, dataSize }; 265 265 tex_util_foreach_mipmap(w, h, bpp, mipmapData.get(), 0, 1, create_level, &cld); 266 266 t->data = mipmapData; … … 296 296 const size_t w = t->w, h = t->h, bpp = t->bpp; 297 297 const size_t flags = t->flags; 298 u8* const data= tex_get_data(t);298 u8* const srcStorage = tex_get_data(t); 299 299 300 300 // sanity checks (not errors, we just can't handle these cases) … … 308 308 return INFO::OK; 309 309 310 const size_t data_size = tex_img_size(t); // size of source311 size_t new_data_size = data_size; // size of destination310 const size_t srcSize = tex_img_size(t); 311 size_t dstSize = srcSize; 312 312 313 313 if(transforms & TEX_ALPHA) … … 316 316 if(bpp == 24) 317 317 { 318 new_data_size = (data_size / 3) * 4;318 dstSize = (srcSize / 3) * 4; 319 319 t->bpp = 32; 320 320 } … … 324 324 return INFO::TEX_CODEC_CANNOT_HANDLE; 325 325 } 326 // can't have alpha with gr eyscale326 // can't have alpha with grayscale 327 327 else 328 328 { … … 338 338 // this is necessary even when not flipping because the initial data 339 339 // is read-only. 340 shared_ptr<u8> newData;341 AllocateAligned( newData, new_data_size);340 shared_ptr<u8> dstStorage; 341 AllocateAligned(dstStorage, dstSize); 342 342 343 343 // setup row source/destination pointers (simplifies outer loop) 344 u8* dst = (u8*) newData.get();344 u8* dst = (u8*)dstStorage.get(); 345 345 const u8* src; 346 346 const size_t pitch = w * bpp/8; // source bpp (not necessarily dest bpp) … … 351 351 if(transforms & TEX_ORIENTATION) 352 352 { 353 src = (const u8*) data+data_size-pitch; // last row353 src = (const u8*)srcStorage+srcSize-pitch; // last row 354 354 row_ofs = -(ssize_t)pitch; 355 355 } … … 357 357 else if(transforms & TEX_ALPHA) 358 358 { 359 src = (const u8*) data;359 src = (const u8*)srcStorage; 360 360 } 361 361 // do other transforms in-place 362 362 else 363 363 { 364 src = (const u8*) newData.get();365 memcpy( newData.get(), data, data_size);364 src = (const u8*)dstStorage.get(); 365 memcpy(dstStorage.get(), srcStorage, srcSize); 366 366 } 367 367 … … 449 449 } 450 450 451 t->data = newData;452 t->dataSize = new_data_size;451 t->data = dstStorage; 452 t->dataSize = dstSize; 453 453 t->ofs = 0; 454 454 455 455 if(!(t->flags & TEX_MIPMAPS) && transforms & TEX_MIPMAPS) 456 RETURN_STATUS_IF_ERR(add_mipmaps(t, w, h, bpp, newData.get(), new_data_size));456 RETURN_STATUS_IF_ERR(add_mipmaps(t, w, h, bpp, dstStorage.get(), dstSize)); 457 457 458 458 CHECK_TEX(t); … … 672 672 673 673 674 static void add_level_size(size_t UNUSED(level), size_t UNUSED(level_w), size_t UNUSED(level_h), const u8* RESTRICT UNUSED(level_data), size_t level_data _size, void* RESTRICT cbData)674 static void add_level_size(size_t UNUSED(level), size_t UNUSED(level_w), size_t UNUSED(level_h), const u8* RESTRICT UNUSED(level_data), size_t level_dataSize, void* RESTRICT cbData) 675 675 { 676 676 size_t* ptotal_size = (size_t*)cbData; 677 *ptotal_size += level_data _size;677 *ptotal_size += level_dataSize; 678 678 } 679 679 … … 715 715 //----------------------------------------------------------------------------- 716 716 717 Status tex_decode(const shared_ptr<u8>& data, size_t data _size, Tex* t)717 Status tex_decode(const shared_ptr<u8>& data, size_t dataSize, Tex* t) 718 718 { 719 719 const TexCodecVTbl* c; 720 RETURN_STATUS_IF_ERR(tex_codec_for_header(data.get(), data _size, &c));720 RETURN_STATUS_IF_ERR(tex_codec_for_header(data.get(), dataSize, &c)); 721 721 722 722 // make sure the entire header is available 723 723 const size_t min_hdr_size = c->hdr_size(0); 724 if(data _size < min_hdr_size)724 if(dataSize < min_hdr_size) 725 725 WARN_RETURN(ERR::TEX_INCOMPLETE_HEADER); 726 726 const size_t hdr_size = c->hdr_size(data.get()); 727 if(data _size < hdr_size)727 if(dataSize < hdr_size) 728 728 WARN_RETURN(ERR::TEX_INCOMPLETE_HEADER); 729 729 730 730 t->data = data; 731 t->dataSize = data _size;731 t->dataSize = dataSize; 732 732 t->ofs = hdr_size; 733 733 734 // for orthogonality, encode and decode both receive the memory as a 735 // DynArray. package data into one and free it again after decoding: 736 DynArray da; 737 RETURN_STATUS_IF_ERR(da_wrap_fixed(&da, data.get(), data_size)); 738 739 RETURN_STATUS_IF_ERR(c->decode(&da, t)); 740 741 // note: not reached if decode fails. that's not a problem; 742 // this call just zeroes <da> and could be left out. 743 (void)da_free(&da); 734 RETURN_STATUS_IF_ERR(c->decode((rpU8)data.get(), dataSize, t)); 744 735 745 736 // sanity checks -
ps/trunk/source/lib/tex/tex_bmp.cpp
r9410 r10024 96 96 97 97 // requirements: uncompressed, direct colour, bottom up 98 static Status bmp_decode( DynArray* RESTRICT da, Tex* RESTRICT t)98 static Status bmp_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t) 99 99 { 100 u8* file = da->base; 101 102 const BmpHeader* hdr = (const BmpHeader*)file; 100 const BmpHeader* hdr = (const BmpHeader*)data; 103 101 const long w = (long)read_le32(&hdr->biWidth); 104 102 const long h_ = (long)read_le32(&hdr->biHeight); -
ps/trunk/source/lib/tex/tex_codec.h
r9410 r10024 42 42 * decode the file into a Tex structure. 43 43 * 44 * @param da input data array (notconst, because the texture44 * @param data input data array (non-const, because the texture 45 45 * may have to be flipped in-place - see "texture orientation"). 46 * its size is guaranteed to be >= 4.47 * (usually enough to compare the header's "magic" field;48 * anyway,no legitimate file will be smaller)46 * @param size [bytes] of data, always >= 4 47 * (this is usually enough to compare the header's "magic" field, 48 * and no legitimate file will be smaller) 49 49 * @param t output texture object 50 50 * @return Status 51 51 **/ 52 Status (*decode)(DynArray* RESTRICT da, Tex * RESTRICT t); 53 52 Status (*decode)(u8* data, size_t size, Tex* RESTRICT t); 54 53 55 54 /** … … 64 63 * @return Status 65 64 **/ 66 Status (*encode)(Tex* RESTRICT t, DynArray * RESTRICT da);65 Status (*encode)(Tex* RESTRICT t, DynArray* RESTRICT da); 67 66 68 67 /** -
ps/trunk/source/lib/tex/tex_dds.cpp
r9861 r10024 589 589 590 590 591 static Status dds_decode(DynArray* RESTRICT da, Tex* RESTRICT t) 592 { 593 u8* file = da->base; 594 const DDS_HEADER* sd = (const DDS_HEADER*)(file+4); 591 static Status dds_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t) 592 { 593 const DDS_HEADER* sd = (const DDS_HEADER*)(data+4); 595 594 RETURN_STATUS_IF_ERR(decode_sd(sd, t->w, t->h, t->bpp, t->flags)); 596 595 return INFO::OK; -
ps/trunk/source/lib/tex/tex_internal.h
r9410 r10024 28 28 #define INCLUDED_TEX_INTERNAL 29 29 30 #include "lib/pointer_typedefs.h" 30 31 #include "lib/allocators/dynarray.h" 31 32 #include "lib/file/io/io.h" // io::Allocate -
ps/trunk/source/lib/tex/tex_jpg.cpp
r9410 r10024 170 170 */ 171 171 172 GLOBAL(void) src_prepare(j_decompress_ptr cinfo, DynArray* da)172 GLOBAL(void) src_prepare(j_decompress_ptr cinfo, rpU8 data, size_t size) 173 173 { 174 174 SrcPtr src; 175 176 const u8* p = da->base;177 const size_t size = da->cur_size;178 175 179 176 /* Treat 0-length buffer as fatal error */ … … 208 205 */ 209 206 src->pub.bytes_in_buffer = size; 210 src->pub.next_input_byte = (JOCTET*) p;207 src->pub.next_input_byte = (JOCTET*)data; 211 208 } 212 209 … … 444 441 445 442 446 static Status jpg_decode_impl( DynArray* da, jpeg_decompress_struct* cinfo, Tex* t)447 { 448 src_prepare(cinfo, da );443 static Status jpg_decode_impl(rpU8 data, size_t size, jpeg_decompress_struct* cinfo, Tex* t) 444 { 445 src_prepare(cinfo, data, size); 449 446 450 447 // ignore return value since: … … 480 477 // alloc destination buffer 481 478 const size_t pitch = w * bpp / 8; 482 const size_t img _size = pitch * h; // for allow_rows483 shared_ptr<u8> data;484 AllocateAligned( data, img_size, pageSize);479 const size_t imgSize = pitch * h; // for allow_rows 480 shared_ptr<u8> img; 481 AllocateAligned(img, imgSize, pageSize); 485 482 486 483 // read rows 487 std::vector<RowPtr> rows = tex_codec_alloc_rows( data.get(), h, pitch, TEX_TOP_DOWN, 0);484 std::vector<RowPtr> rows = tex_codec_alloc_rows(img.get(), h, pitch, TEX_TOP_DOWN, 0); 488 485 // could use cinfo->output_scanline to keep track of progress, 489 486 // but we need to count lines_left anyway (paranoia). … … 508 505 509 506 // store image info 510 t->data = data;511 t->dataSize = img _size;507 t->data = img; 508 t->dataSize = imgSize; 512 509 t->ofs = 0; 513 510 t->w = w; … … 589 586 590 587 591 static Status jpg_decode( DynArray* RESTRICT da, Tex* RESTRICT t)588 static Status jpg_decode(rpU8 data, size_t size, Tex* RESTRICT t) 592 589 { 593 590 // contains the JPEG decompression parameters and pointers to … … 601 598 jpeg_create_decompress(&cinfo); 602 599 603 Status ret = jpg_decode_impl(da , &cinfo, t);600 Status ret = jpg_decode_impl(data, size, &cinfo, t); 604 601 605 602 jpeg_destroy_decompress(&cinfo); // releases a "good deal" of memory -
ps/trunk/source/lib/tex/tex_png.cpp
r9410 r10024 50 50 //----------------------------------------------------------------------------- 51 51 52 class MemoryStream 53 { 54 public: 55 MemoryStream(rpU8 data, size_t size) 56 : data(data), size(size), pos(0) 57 { 58 } 59 60 size_t RemainingSize() const 61 { 62 ASSERT(pos <= size); 63 return size-pos; 64 } 65 66 void CopyTo(rpU8 dst, size_t dstSize) 67 { 68 memcpy(dst, data+pos, dstSize); 69 pos += dstSize; 70 } 71 72 private: 73 rpU8 data; 74 size_t size; 75 size_t pos; 76 }; 77 52 78 53 79 // pass data from PNG file in memory to libpng 54 static void io_read(png_struct* png_ptr, u8* data, png_size_t length) 55 { 56 DynArray* da = (DynArray*)png_get_io_ptr(png_ptr); 57 if(da_read(da, data, length) != 0) 58 png_error(png_ptr, "io_read failed"); 80 static void io_read(png_struct* png_ptr, rpU8 data, png_size_t size) 81 { 82 MemoryStream* stream = (MemoryStream*)png_get_io_ptr(png_ptr); 83 if(stream->RemainingSize() < size) 84 { 85 png_error(png_ptr, "PNG: not enough input"); 86 return; 87 } 88 89 stream->CopyTo(data, size); 59 90 } 60 91 … … 88 119 // split out of png_decode to simplify resource cleanup and avoid 89 120 // "dtor / setjmp interaction" warning. 90 static Status png_decode_impl( DynArray* da, png_structp png_ptr, png_infop info_ptr, Tex* t)91 { 92 png_set_read_fn(png_ptr, da, io_read);121 static Status png_decode_impl(MemoryStream* stream, png_structp png_ptr, png_infop info_ptr, Tex* t) 122 { 123 png_set_read_fn(png_ptr, stream, io_read); 93 124 94 125 // read header and determine format … … 121 152 122 153 // success; make sure all data was consumed. 123 ENSURE( da->pos == da->cur_size);154 ENSURE(stream->RemainingSize() == 0); 124 155 125 156 // store image info 126 t->data = data;157 t->data = data; 127 158 t->dataSize = img_size; 128 159 t->ofs = 0; … … 201 232 202 233 // limitation: palette images aren't supported 203 static Status png_decode( DynArray* RESTRICT da, Tex* RESTRICT t)234 static Status png_decode(rpU8 data, size_t size, Tex* RESTRICT t) 204 235 { 205 236 TIMER_ACCRUE(tc_png_decode); 206 237 207 Status ret = ERR::FAIL;208 238 png_infop info_ptr = 0; 209 239 … … 214 244 info_ptr = png_create_info_struct(png_ptr); 215 245 if(!info_ptr) 216 goto fail; 246 { 247 png_destroy_read_struct(&png_ptr, &info_ptr, 0); 248 WARN_RETURN(ERR::NO_MEM); 249 } 217 250 // setup error handling 218 251 if(setjmp(png_jmpbuf(png_ptr))) 219 252 { 220 253 // libpng longjmps here after an error 221 goto fail; 222 } 223 224 ret = png_decode_impl(da, png_ptr, info_ptr, t); 225 226 fail: 254 png_destroy_read_struct(&png_ptr, &info_ptr, 0); 255 WARN_RETURN(ERR::FAIL); 256 } 257 258 MemoryStream stream(data, size); 259 Status ret = png_decode_impl(&stream, png_ptr, info_ptr, t); 260 227 261 png_destroy_read_struct(&png_ptr, &info_ptr, 0); 228 262 -
ps/trunk/source/lib/tex/tex_tga.cpp
r9410 r10024 112 112 113 113 114 // requirements: uncompressed, direct colo ur, bottom up115 static Status tga_decode( DynArray* RESTRICT da, Tex* RESTRICT t)114 // requirements: uncompressed, direct color, bottom up 115 static Status tga_decode(rpU8 data, size_t UNUSED(size), Tex* RESTRICT t) 116 116 { 117 u8* file = da->base; 118 119 TgaHeader* hdr = (TgaHeader*)file; 117 const TgaHeader* hdr = (const TgaHeader*)data; 120 118 const u8 type = hdr->img_type; 121 119 const size_t w = read_le16(&hdr->w);
Note:
See TracChangeset
for help on using the changeset viewer.
