📄 jmemmgr.pas
字号:
if (hdr_ptr <> NIL) then
break;
slop := slop div 2;
if (slop < MIN_SLOP) then { give up when it gets real small }
out_of_memory(cinfo, 2); { jpeg_get_small failed }
end;
Inc(mem^.total_space_allocated, min_request + slop);
{ Success, initialize the new pool header and add to end of list }
hdr_ptr^.hdr.next := NIL;
hdr_ptr^.hdr.bytes_used := 0;
hdr_ptr^.hdr.bytes_left := sizeofobject + slop;
if (prev_hdr_ptr = NIL) then { first pool in class? }
mem^.small_list[pool_id] := hdr_ptr
else
prev_hdr_ptr^.hdr.next := hdr_ptr;
end;
{ OK, allocate the object from the current pool }
data_ptr := byteptr (hdr_ptr);
Inc(small_pool_ptr(data_ptr)); { point to first data byte in pool }
Inc(data_ptr, hdr_ptr^.hdr.bytes_used); { point to place for object }
Inc(hdr_ptr^.hdr.bytes_used, sizeofobject);
Dec(hdr_ptr^.hdr.bytes_left, sizeofobject);
alloc_small := pointer(data_ptr);
end;
{ Allocation of "large" objects.
The external semantics of these are the same as "small" objects,
except that FAR pointers are used on 80x86. However the pool
management heuristics are quite different. We assume that each
request is large enough that it may as well be passed directly to
jpeg_get_large; the pool management just links everything together
so that we can free it all on demand.
Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
structures. The routines that create these structures (see below)
deliberately bunch rows together to ensure a large request size. }
{METHODDEF}
function alloc_large (cinfo : j_common_ptr;
pool_id : int;
sizeofobject : size_t) : pointer; FAR;
{ Allocate a "large" object }
var
mem : my_mem_ptr;
hdr_ptr : large_pool_ptr;
odd_bytes : size_t;
var
dest_ptr : large_pool_ptr;
begin
mem := my_mem_ptr (cinfo^.mem);
{ Check for unsatisfiable request (do now to ensure no overflow below) }
if (sizeofobject > size_t (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) then
out_of_memory(cinfo, 3); { request exceeds malloc's ability }
{ Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) }
odd_bytes := sizeofobject mod SIZEOF(ALIGN_TYPE);
if (odd_bytes > 0) then
Inc(sizeofobject, SIZEOF(ALIGN_TYPE) - odd_bytes);
{ Always make a new pool }
if (pool_id < 0) or (pool_id >= JPOOL_NUMPOOLS) then
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); { safety check }
hdr_ptr := large_pool_ptr (jpeg_get_large(cinfo, sizeofobject +
SIZEOF(large_pool_hdr)));
if (hdr_ptr = NIL) then
out_of_memory(cinfo, 4); { jpeg_get_large failed }
Inc(mem^.total_space_allocated, sizeofobject + SIZEOF(large_pool_hdr));
{ Success, initialize the new pool header and add to list }
hdr_ptr^.hdr.next := mem^.large_list[pool_id];
{ We maintain space counts in each pool header for statistical purposes,
even though they are not needed for allocation. }
hdr_ptr^.hdr.bytes_used := sizeofobject;
hdr_ptr^.hdr.bytes_left := 0;
mem^.large_list[pool_id] := hdr_ptr;
{alloc_large := pointerFAR (hdr_ptr + 1); { point to first data byte in pool }
dest_ptr := hdr_ptr;
Inc(large_pool_ptr(dest_ptr));
alloc_large := dest_ptr;
end;
{ Creation of 2-D sample arrays.
The pointers are in near heap, the samples themselves in FAR heap.
To minimize allocation overhead and to allow I/O of large contiguous
blocks, we allocate the sample rows in groups of as many rows as possible
without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
NB: the virtual array control routines, later in this file, know about
this chunking of rows. The rowsperchunk value is left in the mem manager
object so that it can be saved away if this sarray is the workspace for
a virtual array. }
{METHODDEF}
function alloc_sarray (cinfo : j_common_ptr;
pool_id : int;
samplesperrow : JDIMENSION;
numrows : JDIMENSION) : JSAMPARRAY; far;
{ Allocate a 2-D sample array }
var
mem : my_mem_ptr;
the_result : JSAMPARRAY;
workspace : JSAMPROW;
rowsperchunk, currow, i : JDIMENSION;
ltemp : long;
begin
mem := my_mem_ptr(cinfo^.mem);
{ Calculate max # of rows allowed in one allocation chunk }
ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div
(long(samplesperrow) * SIZEOF(JSAMPLE));
if (ltemp <= 0) then
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
if (ltemp < long(numrows)) then
rowsperchunk := JDIMENSION (ltemp)
else
rowsperchunk := numrows;
mem^.last_rowsperchunk := rowsperchunk;
{ Get space for row pointers (small object) }
the_result := JSAMPARRAY (alloc_small(cinfo, pool_id,
size_t (numrows * SIZEOF(JSAMPROW))));
{ Get the rows themselves (large objects) }
currow := 0;
while (currow < numrows) do
begin
{rowsperchunk := MIN(rowsperchunk, numrows - currow);}
if rowsperchunk > numrows - currow then
rowsperchunk := numrows - currow;
workspace := JSAMPROW (alloc_large(cinfo, pool_id,
size_t (size_t(rowsperchunk) * size_t(samplesperrow)
* SIZEOF(JSAMPLE))) );
for i := pred(rowsperchunk) downto 0 do
begin
the_result^[currow] := workspace;
Inc(currow);
Inc(JSAMPLE_PTR(workspace), samplesperrow);
end;
end;
alloc_sarray := the_result;
end;
{ Creation of 2-D coefficient-block arrays.
This is essentially the same as the code for sample arrays, above. }
{METHODDEF}
function alloc_barray (cinfo : j_common_ptr;
pool_id : int;
blocksperrow : JDIMENSION;
numrows : JDIMENSION) : JBLOCKARRAY; far;
{ Allocate a 2-D coefficient-block array }
var
mem : my_mem_ptr;
the_result : JBLOCKARRAY;
workspace : JBLOCKROW;
rowsperchunk, currow, i : JDIMENSION;
ltemp : long;
begin
mem := my_mem_ptr(cinfo^.mem);
{ Calculate max # of rows allowed in one allocation chunk }
ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div
(long(blocksperrow) * SIZEOF(JBLOCK));
if (ltemp <= 0) then
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
if (ltemp < long(numrows)) then
rowsperchunk := JDIMENSION (ltemp)
else
rowsperchunk := numrows;
mem^.last_rowsperchunk := rowsperchunk;
{ Get space for row pointers (small object) }
the_result := JBLOCKARRAY (alloc_small(cinfo, pool_id,
size_t (numrows * SIZEOF(JBLOCKROW))) );
{ Get the rows themselves (large objects) }
currow := 0;
while (currow < numrows) do
begin
{rowsperchunk := MIN(rowsperchunk, numrows - currow);}
if rowsperchunk > numrows - currow then
rowsperchunk := numrows - currow;
workspace := JBLOCKROW (alloc_large(cinfo, pool_id,
size_t (size_t(rowsperchunk) * size_t(blocksperrow)
* SIZEOF(JBLOCK))) );
for i := rowsperchunk downto 1 do
begin
the_result^[currow] := workspace;
Inc(currow);
Inc(JBLOCK_PTR(workspace), blocksperrow);
end;
end;
alloc_barray := the_result;
end;
{ About virtual array management:
The above "normal" array routines are only used to allocate strip buffers
(as wide as the image, but just a few rows high). Full-image-sized buffers
are handled as "virtual" arrays. The array is still accessed a strip at a
time, but the memory manager must save the whole array for repeated
accesses. The intended implementation is that there is a strip buffer in
memory (as high as is possible given the desired memory limit), plus a
backing file that holds the rest of the array.
The request_virt_array routines are told the total size of the image and
the maximum number of rows that will be accessed at once. The in-memory
buffer must be at least as large as the maxaccess value.
The request routines create control blocks but not the in-memory buffers.
That is postponed until realize_virt_arrays is called. At that time the
total amount of space needed is known (approximately, anyway), so free
memory can be divided up fairly.
The access_virt_array routines are responsible for making a specific strip
area accessible (after reading or writing the backing file, if necessary).
Note that the access routines are told whether the caller intends to modify
the accessed strip; during a read-only pass this saves having to rewrite
data to disk. The access routines are also responsible for pre-zeroing
any newly accessed rows, if pre-zeroing was requested.
In current usage, the access requests are usually for nonoverlapping
strips; that is, successive access start_row numbers differ by exactly
num_rows := maxaccess. This means we can get good performance with simple
buffer dump/reload logic, by making the in-memory buffer be a multiple
of the access height; then there will never be accesses across bufferload
boundaries. The code will still work with overlapping access requests,
but it doesn't handle bufferload overlaps very efficiently. }
{METHODDEF}
function request_virt_sarray (cinfo : j_common_ptr;
pool_id : int;
pre_zero : boolean;
samplesperrow : JDIMENSION;
numrows : JDIMENSION;
maxaccess : JDIMENSION) : jvirt_sarray_ptr; far;
{ Request a virtual 2-D sample array }
var
mem : my_mem_ptr;
the_result : jvirt_sarray_ptr;
begin
mem := my_mem_ptr (cinfo^.mem);
{ Only IMAGE-lifetime virtual arrays are currently supported }
if (pool_id <> JPOOL_IMAGE) then
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); { safety check }
{ get control block }
the_result := jvirt_sarray_ptr (alloc_small(cinfo, pool_id,
SIZEOF(jvirt_sarray_control)) );
the_result^.mem_buffer := NIL; { marks array not yet realized }
the_result^.rows_in_array := numrows;
the_result^.samplesperrow := samplesperrow;
the_result^.maxaccess := maxaccess;
the_result^.pre_zero := pre_zero;
the_result^.b_s_open := FALSE; { no associated backing-store object }
the_result^.next := mem^.virt_sarray_list; { add to list of virtual arrays }
mem^.virt_sarray_list := the_result;
request_virt_sarray := the_result;
end;
{METHODDEF}
function request_virt_barray (cinfo : j_common_ptr;
pool_id : int;
pre_zero : boolean;
blocksperrow : JDIMENSION;
numrows : JDIMENSION;
maxaccess : JDIMENSION) : jvirt_barray_ptr; far;
{ Request a virtual 2-D coefficient-block array }
var
mem : my_mem_ptr;
the_result : jvirt_barray_ptr;
begin
mem := my_mem_ptr(cinfo^.mem);
{ Only IMAGE-lifetime virtual arrays are currently supported }
if (pool_id <> JPOOL_IMAGE) then
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); { safety check }
{ get control block }
the_result := jvirt_barray_ptr(alloc_small(cinfo, pool_id,
SIZEOF(jvirt_barray_control)) );
the_result^.mem_buffer := NIL; { marks array not yet realized }
the_result^.rows_in_array := numrows;
the_result^.blocksperrow := blocksperrow;
the_result^.maxaccess := maxaccess;
the_result^.pre_zero := pre_zero;
the_result^.b_s_open := FALSE; { no associated backing-store object }
the_result^.next := mem^.virt_barray_list; { add to list of virtual arrays }
mem^.virt_barray_list := the_result;
request_virt_barray := the_result;
end;
{METHODDEF}
procedure realize_virt_arrays (cinfo : j_common_ptr); far;
{ Allocate the in-memory buffers for any unrealized virtual arrays }
var
mem : my_mem_ptr;
space_per_minheight, maximum_space, avail_mem : long;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -