00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define JPEG_INTERNALS
00028 #define AM_MEMORY_MANAGER
00029 #include "jinclude.h"
00030 #include "jpeglib.h"
00031 #include "jmemsys.h"
00032
00033 #ifndef NO_GETENV
00034 #error "tgghh"
00035 #ifndef HAVE_STDLIB_H
00036 extern char * getenv JPP((const char * name));
00037 #endif
00038 #endif
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #ifndef ALIGN_TYPE
00074 #define ALIGN_TYPE double
00075 #endif
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 typedef union small_pool_struct * small_pool_ptr;
00091
00092 typedef union small_pool_struct {
00093 struct {
00094 small_pool_ptr next;
00095 size_t bytes_used;
00096 size_t bytes_left;
00097 } hdr;
00098 ALIGN_TYPE dummy;
00099 } small_pool_hdr;
00100
00101 typedef union large_pool_struct FAR * large_pool_ptr;
00102
00103 typedef union large_pool_struct {
00104 struct {
00105 large_pool_ptr next;
00106 size_t bytes_used;
00107 size_t bytes_left;
00108 } hdr;
00109 ALIGN_TYPE dummy;
00110 } large_pool_hdr;
00111
00112
00113
00114
00115
00116
00117 typedef struct {
00118 struct jpeg_memory_mgr pub;
00119
00120
00121 small_pool_ptr small_list[JPOOL_NUMPOOLS];
00122 large_pool_ptr large_list[JPOOL_NUMPOOLS];
00123
00124
00125
00126
00127
00128
00129 jvirt_sarray_ptr virt_sarray_list;
00130 jvirt_barray_ptr virt_barray_list;
00131
00132
00133 long total_space_allocated;
00134
00135
00136
00137
00138 JDIMENSION last_rowsperchunk;
00139 } my_memory_mgr;
00140
00141 typedef my_memory_mgr * my_mem_ptr;
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 struct jvirt_sarray_control {
00152 JSAMPARRAY mem_buffer;
00153 JDIMENSION rows_in_array;
00154 JDIMENSION samplesperrow;
00155 JDIMENSION maxaccess;
00156 JDIMENSION rows_in_mem;
00157 JDIMENSION rowsperchunk;
00158 JDIMENSION cur_start_row;
00159 JDIMENSION first_undef_row;
00160 boolean pre_zero;
00161 boolean dirty;
00162 boolean b_s_open;
00163 jvirt_sarray_ptr next;
00164 backing_store_info b_s_info;
00165 };
00166
00167 struct jvirt_barray_control {
00168 JBLOCKARRAY mem_buffer;
00169 JDIMENSION rows_in_array;
00170 JDIMENSION blocksperrow;
00171 JDIMENSION maxaccess;
00172 JDIMENSION rows_in_mem;
00173 JDIMENSION rowsperchunk;
00174 JDIMENSION cur_start_row;
00175 JDIMENSION first_undef_row;
00176 boolean pre_zero;
00177 boolean dirty;
00178 boolean b_s_open;
00179 jvirt_barray_ptr next;
00180 backing_store_info b_s_info;
00181 };
00182
00183
00184 #ifdef MEM_STATS
00185
00186 LOCAL(void)
00187 print_mem_stats (j_common_ptr cinfo, int pool_id)
00188 {
00189 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00190 small_pool_ptr shdr_ptr;
00191 large_pool_ptr lhdr_ptr;
00192
00193
00194
00195
00196
00197 fprintf(stderr, "Freeing pool %d, total space = %ld\n",
00198 pool_id, mem->total_space_allocated);
00199
00200 for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
00201 lhdr_ptr = lhdr_ptr->hdr.next) {
00202 fprintf(stderr, " Large chunk used %ld\n",
00203 (long) lhdr_ptr->hdr.bytes_used);
00204 }
00205
00206 for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
00207 shdr_ptr = shdr_ptr->hdr.next) {
00208 fprintf(stderr, " Small chunk used %ld free %ld\n",
00209 (long) shdr_ptr->hdr.bytes_used,
00210 (long) shdr_ptr->hdr.bytes_left);
00211 }
00212 }
00213
00214 #endif
00215
00216
00217 LOCAL(void)
00218 out_of_memory (j_common_ptr cinfo, int which)
00219
00220
00221 {
00222 #ifdef MEM_STATS
00223 cinfo->err->trace_level = 2;
00224 #endif
00225 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
00243 {
00244 1600,
00245 16000
00246 };
00247
00248 static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
00249 {
00250 0,
00251 5000
00252 };
00253
00254 #define MIN_SLOP 50
00255
00256
00257 METHODDEF(void *)
00258 alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
00259
00260 {
00261 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00262 small_pool_ptr hdr_ptr, prev_hdr_ptr;
00263 char * data_ptr;
00264 size_t odd_bytes, min_request, slop;
00265
00266
00267 if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
00268 out_of_memory(cinfo, 1);
00269
00270
00271 odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
00272 if (odd_bytes > 0)
00273 sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
00274
00275
00276 if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00277 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00278 prev_hdr_ptr = NULL;
00279 hdr_ptr = mem->small_list[pool_id];
00280 while (hdr_ptr != NULL) {
00281 if (hdr_ptr->hdr.bytes_left >= sizeofobject)
00282 break;
00283 prev_hdr_ptr = hdr_ptr;
00284 hdr_ptr = hdr_ptr->hdr.next;
00285 }
00286
00287
00288 if (hdr_ptr == NULL) {
00289
00290 min_request = sizeofobject + SIZEOF(small_pool_hdr);
00291 if (prev_hdr_ptr == NULL)
00292 slop = first_pool_slop[pool_id];
00293 else
00294 slop = extra_pool_slop[pool_id];
00295
00296 if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
00297 slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
00298
00299 for (;;) {
00300 hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
00301 if (hdr_ptr != NULL)
00302 break;
00303 slop /= 2;
00304 if (slop < MIN_SLOP)
00305 out_of_memory(cinfo, 2);
00306 }
00307 mem->total_space_allocated += min_request + slop;
00308
00309 hdr_ptr->hdr.next = NULL;
00310 hdr_ptr->hdr.bytes_used = 0;
00311 hdr_ptr->hdr.bytes_left = sizeofobject + slop;
00312 if (prev_hdr_ptr == NULL)
00313 mem->small_list[pool_id] = hdr_ptr;
00314 else
00315 prev_hdr_ptr->hdr.next = hdr_ptr;
00316 }
00317
00318
00319 data_ptr = (char *) (hdr_ptr + 1);
00320 data_ptr += hdr_ptr->hdr.bytes_used;
00321 hdr_ptr->hdr.bytes_used += sizeofobject;
00322 hdr_ptr->hdr.bytes_left -= sizeofobject;
00323
00324 return (void *) data_ptr;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 METHODDEF(void FAR *)
00343 alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
00344
00345 {
00346 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00347 large_pool_ptr hdr_ptr;
00348 size_t odd_bytes;
00349
00350
00351 if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
00352 out_of_memory(cinfo, 3);
00353
00354
00355 odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
00356 if (odd_bytes > 0)
00357 sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
00358
00359
00360 if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00361 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00362
00363 hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
00364 SIZEOF(large_pool_hdr));
00365 if (hdr_ptr == NULL)
00366 out_of_memory(cinfo, 4);
00367 mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
00368
00369
00370 hdr_ptr->hdr.next = mem->large_list[pool_id];
00371
00372
00373
00374 hdr_ptr->hdr.bytes_used = sizeofobject;
00375 hdr_ptr->hdr.bytes_left = 0;
00376 mem->large_list[pool_id] = hdr_ptr;
00377
00378 return (void FAR *) (hdr_ptr + 1);
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 METHODDEF(JSAMPARRAY)
00396 alloc_sarray (j_common_ptr cinfo, int pool_id,
00397 JDIMENSION samplesperrow, JDIMENSION numrows)
00398
00399 {
00400 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00401 JSAMPARRAY result;
00402 JSAMPROW workspace;
00403 JDIMENSION rowsperchunk, currow, i;
00404 long ltemp;
00405
00406
00407 ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
00408 ((long) samplesperrow * SIZEOF(JSAMPLE));
00409 if (ltemp <= 0)
00410 ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
00411 if (ltemp < (long) numrows)
00412 rowsperchunk = (JDIMENSION) ltemp;
00413 else
00414 rowsperchunk = numrows;
00415 mem->last_rowsperchunk = rowsperchunk;
00416
00417
00418 result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
00419 (size_t) (numrows * SIZEOF(JSAMPROW)));
00420
00421
00422 currow = 0;
00423 while (currow < numrows) {
00424 rowsperchunk = MIN(rowsperchunk, numrows - currow);
00425 workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
00426 (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
00427 * SIZEOF(JSAMPLE)));
00428 for (i = rowsperchunk; i > 0; i--) {
00429 result[currow++] = workspace;
00430 workspace += samplesperrow;
00431 }
00432 }
00433
00434 return result;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443 METHODDEF(JBLOCKARRAY)
00444 alloc_barray (j_common_ptr cinfo, int pool_id,
00445 JDIMENSION blocksperrow, JDIMENSION numrows)
00446
00447 {
00448 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00449 JBLOCKARRAY result;
00450 JBLOCKROW workspace;
00451 JDIMENSION rowsperchunk, currow, i;
00452 long ltemp;
00453
00454
00455 ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
00456 ((long) blocksperrow * SIZEOF(JBLOCK));
00457 if (ltemp <= 0)
00458 ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
00459 if (ltemp < (long) numrows)
00460 rowsperchunk = (JDIMENSION) ltemp;
00461 else
00462 rowsperchunk = numrows;
00463 mem->last_rowsperchunk = rowsperchunk;
00464
00465
00466 result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
00467 (size_t) (numrows * SIZEOF(JBLOCKROW)));
00468
00469
00470 currow = 0;
00471 while (currow < numrows) {
00472 rowsperchunk = MIN(rowsperchunk, numrows - currow);
00473 workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
00474 (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
00475 * SIZEOF(JBLOCK)));
00476 for (i = rowsperchunk; i > 0; i--) {
00477 result[currow++] = workspace;
00478 workspace += blocksperrow;
00479 }
00480 }
00481
00482 return result;
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 METHODDEF(jvirt_sarray_ptr)
00524 request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
00525 JDIMENSION samplesperrow, JDIMENSION numrows,
00526 JDIMENSION maxaccess)
00527
00528 {
00529 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00530 jvirt_sarray_ptr result;
00531
00532
00533 if (pool_id != JPOOL_IMAGE)
00534 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00535
00536
00537 result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
00538 SIZEOF(struct jvirt_sarray_control));
00539
00540 result->mem_buffer = NULL;
00541 result->rows_in_array = numrows;
00542 result->samplesperrow = samplesperrow;
00543 result->maxaccess = maxaccess;
00544 result->pre_zero = pre_zero;
00545 result->b_s_open = FALSE;
00546 result->next = mem->virt_sarray_list;
00547 mem->virt_sarray_list = result;
00548
00549 return result;
00550 }
00551
00552
00553 METHODDEF(jvirt_barray_ptr)
00554 request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
00555 JDIMENSION blocksperrow, JDIMENSION numrows,
00556 JDIMENSION maxaccess)
00557
00558 {
00559 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00560 jvirt_barray_ptr result;
00561
00562
00563 if (pool_id != JPOOL_IMAGE)
00564 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00565
00566
00567 result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
00568 SIZEOF(struct jvirt_barray_control));
00569
00570 result->mem_buffer = NULL;
00571 result->rows_in_array = numrows;
00572 result->blocksperrow = blocksperrow;
00573 result->maxaccess = maxaccess;
00574 result->pre_zero = pre_zero;
00575 result->b_s_open = FALSE;
00576 result->next = mem->virt_barray_list;
00577 mem->virt_barray_list = result;
00578
00579 return result;
00580 }
00581
00582
00583 METHODDEF(void)
00584 realize_virt_arrays (j_common_ptr cinfo)
00585
00586 {
00587 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00588 long space_per_minheight, maximum_space, avail_mem;
00589 long minheights, max_minheights;
00590 jvirt_sarray_ptr sptr;
00591 jvirt_barray_ptr bptr;
00592
00593
00594
00595
00596
00597 space_per_minheight = 0;
00598 maximum_space = 0;
00599 for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00600 if (sptr->mem_buffer == NULL) {
00601 space_per_minheight += (long) sptr->maxaccess *
00602 (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
00603 maximum_space += (long) sptr->rows_in_array *
00604 (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
00605 }
00606 }
00607 for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00608 if (bptr->mem_buffer == NULL) {
00609 space_per_minheight += (long) bptr->maxaccess *
00610 (long) bptr->blocksperrow * SIZEOF(JBLOCK);
00611 maximum_space += (long) bptr->rows_in_array *
00612 (long) bptr->blocksperrow * SIZEOF(JBLOCK);
00613 }
00614 }
00615
00616 if (space_per_minheight <= 0)
00617 return;
00618
00619
00620 avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
00621 mem->total_space_allocated);
00622
00623
00624
00625
00626
00627 if (avail_mem >= maximum_space)
00628 max_minheights = 1000000000L;
00629 else {
00630 max_minheights = avail_mem / space_per_minheight;
00631
00632
00633
00634 if (max_minheights <= 0)
00635 max_minheights = 1;
00636 }
00637
00638
00639
00640 for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00641 if (sptr->mem_buffer == NULL) {
00642 minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
00643 if (minheights <= max_minheights) {
00644
00645 sptr->rows_in_mem = sptr->rows_in_array;
00646 } else {
00647
00648 sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
00649 jpeg_open_backing_store(cinfo, & sptr->b_s_info,
00650 (long) sptr->rows_in_array *
00651 (long) sptr->samplesperrow *
00652 (long) SIZEOF(JSAMPLE));
00653 sptr->b_s_open = TRUE;
00654 }
00655 sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
00656 sptr->samplesperrow, sptr->rows_in_mem);
00657 sptr->rowsperchunk = mem->last_rowsperchunk;
00658 sptr->cur_start_row = 0;
00659 sptr->first_undef_row = 0;
00660 sptr->dirty = FALSE;
00661 }
00662 }
00663
00664 for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00665 if (bptr->mem_buffer == NULL) {
00666 minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
00667 if (minheights <= max_minheights) {
00668
00669 bptr->rows_in_mem = bptr->rows_in_array;
00670 } else {
00671
00672 bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
00673 jpeg_open_backing_store(cinfo, & bptr->b_s_info,
00674 (long) bptr->rows_in_array *
00675 (long) bptr->blocksperrow *
00676 (long) SIZEOF(JBLOCK));
00677 bptr->b_s_open = TRUE;
00678 }
00679 bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
00680 bptr->blocksperrow, bptr->rows_in_mem);
00681 bptr->rowsperchunk = mem->last_rowsperchunk;
00682 bptr->cur_start_row = 0;
00683 bptr->first_undef_row = 0;
00684 bptr->dirty = FALSE;
00685 }
00686 }
00687 }
00688
00689
00690 LOCAL(void)
00691 do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
00692
00693 {
00694 long bytesperrow, file_offset, byte_count, rows, thisrow, i;
00695
00696 bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
00697 file_offset = ptr->cur_start_row * bytesperrow;
00698
00699 for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
00700
00701 rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
00702
00703 thisrow = (long) ptr->cur_start_row + i;
00704 rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
00705
00706 rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
00707 if (rows <= 0)
00708 break;
00709 byte_count = rows * bytesperrow;
00710 if (writing)
00711 (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
00712 (void FAR *) ptr->mem_buffer[i],
00713 file_offset, byte_count);
00714 else
00715 (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
00716 (void FAR *) ptr->mem_buffer[i],
00717 file_offset, byte_count);
00718 file_offset += byte_count;
00719 }
00720 }
00721
00722
00723 LOCAL(void)
00724 do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
00725
00726 {
00727 long bytesperrow, file_offset, byte_count, rows, thisrow, i;
00728
00729 bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
00730 file_offset = ptr->cur_start_row * bytesperrow;
00731
00732 for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
00733
00734 rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
00735
00736 thisrow = (long) ptr->cur_start_row + i;
00737 rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
00738
00739 rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
00740 if (rows <= 0)
00741 break;
00742 byte_count = rows * bytesperrow;
00743 if (writing)
00744 (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
00745 (void FAR *) ptr->mem_buffer[i],
00746 file_offset, byte_count);
00747 else
00748 (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
00749 (void FAR *) ptr->mem_buffer[i],
00750 file_offset, byte_count);
00751 file_offset += byte_count;
00752 }
00753 }
00754
00755
00756 METHODDEF(JSAMPARRAY)
00757 access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
00758 JDIMENSION start_row, JDIMENSION num_rows,
00759 boolean writable)
00760
00761
00762
00763 {
00764 JDIMENSION end_row = start_row + num_rows;
00765 JDIMENSION undef_row;
00766
00767
00768 if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
00769 ptr->mem_buffer == NULL)
00770 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00771
00772
00773 if (start_row < ptr->cur_start_row ||
00774 end_row > ptr->cur_start_row+ptr->rows_in_mem) {
00775 if (! ptr->b_s_open)
00776 ERREXIT(cinfo, JERR_VIRTUAL_BUG);
00777
00778 if (ptr->dirty) {
00779 do_sarray_io(cinfo, ptr, TRUE);
00780 ptr->dirty = FALSE;
00781 }
00782
00783
00784
00785
00786
00787
00788
00789 if (start_row > ptr->cur_start_row) {
00790 ptr->cur_start_row = start_row;
00791 } else {
00792
00793 long ltemp;
00794
00795 ltemp = (long) end_row - (long) ptr->rows_in_mem;
00796 if (ltemp < 0)
00797 ltemp = 0;
00798 ptr->cur_start_row = (JDIMENSION) ltemp;
00799 }
00800
00801
00802
00803
00804 do_sarray_io(cinfo, ptr, FALSE);
00805 }
00806
00807
00808
00809
00810 if (ptr->first_undef_row < end_row) {
00811 if (ptr->first_undef_row < start_row) {
00812 if (writable)
00813 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00814 undef_row = start_row;
00815 } else {
00816 undef_row = ptr->first_undef_row;
00817 }
00818 if (writable)
00819 ptr->first_undef_row = end_row;
00820 if (ptr->pre_zero) {
00821 size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
00822 undef_row -= ptr->cur_start_row;
00823 end_row -= ptr->cur_start_row;
00824 while (undef_row < end_row) {
00825 jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
00826 undef_row++;
00827 }
00828 } else {
00829 if (! writable)
00830 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00831 }
00832 }
00833
00834 if (writable)
00835 ptr->dirty = TRUE;
00836
00837 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
00838 }
00839
00840
00841 METHODDEF(JBLOCKARRAY)
00842 access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
00843 JDIMENSION start_row, JDIMENSION num_rows,
00844 boolean writable)
00845
00846
00847
00848 {
00849 JDIMENSION end_row = start_row + num_rows;
00850 JDIMENSION undef_row;
00851
00852
00853 if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
00854 ptr->mem_buffer == NULL)
00855 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00856
00857
00858 if (start_row < ptr->cur_start_row ||
00859 end_row > ptr->cur_start_row+ptr->rows_in_mem) {
00860 if (! ptr->b_s_open)
00861 ERREXIT(cinfo, JERR_VIRTUAL_BUG);
00862
00863 if (ptr->dirty) {
00864 do_barray_io(cinfo, ptr, TRUE);
00865 ptr->dirty = FALSE;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874 if (start_row > ptr->cur_start_row) {
00875 ptr->cur_start_row = start_row;
00876 } else {
00877
00878 long ltemp;
00879
00880 ltemp = (long) end_row - (long) ptr->rows_in_mem;
00881 if (ltemp < 0)
00882 ltemp = 0;
00883 ptr->cur_start_row = (JDIMENSION) ltemp;
00884 }
00885
00886
00887
00888
00889 do_barray_io(cinfo, ptr, FALSE);
00890 }
00891
00892
00893
00894
00895 if (ptr->first_undef_row < end_row) {
00896 if (ptr->first_undef_row < start_row) {
00897 if (writable)
00898 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00899 undef_row = start_row;
00900 } else {
00901 undef_row = ptr->first_undef_row;
00902 }
00903 if (writable)
00904 ptr->first_undef_row = end_row;
00905 if (ptr->pre_zero) {
00906 size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
00907 undef_row -= ptr->cur_start_row;
00908 end_row -= ptr->cur_start_row;
00909 while (undef_row < end_row) {
00910 jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
00911 undef_row++;
00912 }
00913 } else {
00914 if (! writable)
00915 ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
00916 }
00917 }
00918
00919 if (writable)
00920 ptr->dirty = TRUE;
00921
00922 return ptr->mem_buffer + (start_row - ptr->cur_start_row);
00923 }
00924
00925
00926
00927
00928
00929
00930 METHODDEF(void)
00931 free_pool (j_common_ptr cinfo, int pool_id)
00932 {
00933 my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
00934 small_pool_ptr shdr_ptr;
00935 large_pool_ptr lhdr_ptr;
00936 size_t space_freed;
00937
00938 if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
00939 ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);
00940
00941 #ifdef MEM_STATS
00942 if (cinfo->err->trace_level > 1)
00943 print_mem_stats(cinfo, pool_id);
00944 #endif
00945
00946
00947 if (pool_id == JPOOL_IMAGE) {
00948 jvirt_sarray_ptr sptr;
00949 jvirt_barray_ptr bptr;
00950
00951 for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
00952 if (sptr->b_s_open) {
00953 sptr->b_s_open = FALSE;
00954 (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
00955 }
00956 }
00957 mem->virt_sarray_list = NULL;
00958 for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
00959 if (bptr->b_s_open) {
00960 bptr->b_s_open = FALSE;
00961 (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
00962 }
00963 }
00964 mem->virt_barray_list = NULL;
00965 }
00966
00967
00968 lhdr_ptr = mem->large_list[pool_id];
00969 mem->large_list[pool_id] = NULL;
00970
00971 while (lhdr_ptr != NULL) {
00972 large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
00973 space_freed = lhdr_ptr->hdr.bytes_used +
00974 lhdr_ptr->hdr.bytes_left +
00975 SIZEOF(large_pool_hdr);
00976 jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
00977 mem->total_space_allocated -= space_freed;
00978 lhdr_ptr = next_lhdr_ptr;
00979 }
00980
00981
00982 shdr_ptr = mem->small_list[pool_id];
00983 mem->small_list[pool_id] = NULL;
00984
00985 while (shdr_ptr != NULL) {
00986 small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
00987 space_freed = shdr_ptr->hdr.bytes_used +
00988 shdr_ptr->hdr.bytes_left +
00989 SIZEOF(small_pool_hdr);
00990 jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
00991 mem->total_space_allocated -= space_freed;
00992 shdr_ptr = next_shdr_ptr;
00993 }
00994 }
00995
00996
00997
00998
00999
01000
01001
01002 METHODDEF(void)
01003 self_destruct (j_common_ptr cinfo)
01004 {
01005 int pool;
01006
01007
01008
01009
01010
01011 for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
01012 free_pool(cinfo, pool);
01013 }
01014
01015
01016 jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
01017 cinfo->mem = NULL;
01018
01019 jpeg_mem_term(cinfo);
01020 }
01021
01022
01023
01024
01025
01026
01027
01028 GLOBAL(void)
01029 jinit_memory_mgr (j_common_ptr cinfo)
01030 {
01031 my_mem_ptr mem;
01032 long max_to_use;
01033 int pool;
01034 size_t test_mac;
01035
01036 cinfo->mem = NULL;
01037
01038
01039
01040
01041
01042
01043
01044
01045 if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
01046 ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
01047
01048
01049
01050
01051
01052 test_mac = (size_t) MAX_ALLOC_CHUNK;
01053 if ((long) test_mac != MAX_ALLOC_CHUNK ||
01054 (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
01055 ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
01056
01057 max_to_use = jpeg_mem_init(cinfo);
01058
01059
01060 mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
01061
01062 if (mem == NULL) {
01063 jpeg_mem_term(cinfo);
01064 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
01065 }
01066
01067
01068 mem->pub.alloc_small = alloc_small;
01069 mem->pub.alloc_large = alloc_large;
01070 mem->pub.alloc_sarray = alloc_sarray;
01071 mem->pub.alloc_barray = alloc_barray;
01072 mem->pub.request_virt_sarray = request_virt_sarray;
01073 mem->pub.request_virt_barray = request_virt_barray;
01074 mem->pub.realize_virt_arrays = realize_virt_arrays;
01075 mem->pub.access_virt_sarray = access_virt_sarray;
01076 mem->pub.access_virt_barray = access_virt_barray;
01077 mem->pub.free_pool = free_pool;
01078 mem->pub.self_destruct = self_destruct;
01079
01080
01081 mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
01082
01083
01084 mem->pub.max_memory_to_use = max_to_use;
01085
01086 for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
01087 mem->small_list[pool] = NULL;
01088 mem->large_list[pool] = NULL;
01089 }
01090 mem->virt_sarray_list = NULL;
01091 mem->virt_barray_list = NULL;
01092
01093 mem->total_space_allocated = SIZEOF(my_memory_mgr);
01094
01095
01096 cinfo->mem = & mem->pub;
01097
01098
01099
01100
01101
01102
01103
01104 #ifndef NO_GETENV
01105 { char * memenv;
01106
01107 if ((memenv = getenv("JPEGMEM")) != NULL) {
01108 char ch = 'x';
01109
01110 if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
01111 if (ch == 'm' || ch == 'M')
01112 max_to_use *= 1000L;
01113 mem->pub.max_memory_to_use = max_to_use * 1000L;
01114 }
01115 }
01116 }
01117 #endif
01118
01119 }