blob: 7ad49014e1975ed5dff70f441a3e582e7a64c450 [file] [log] [blame]
#! /bin/sh
# $Id: fb-xlat-auto.sh,v 1.12 2009/08/30 21:51:53 fredette Exp $
# generic/fb-xlat-auto.sh - automatically generates C code
# for many framebuffer translation functions:
#
# Copyright (c) 2003, 2005 Matt Fredette
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Matt Fredette.
# 4. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# this script generates one or more C functions. each function
# translates an image from a source image format into a destination
# image format, optionally halving or doubling the image size in the
# process.
#
# the source and destination image formats are represented by "keys",
# strings that describe the different attributes of a format.
#
# a source image format key has the form: WxHdDbBsSpPoO[cC][mMS][_rR_gG_bB][_X]
#
# a destination image format key has the form: dDbBsSpPoO[mM][_rR_gG_bB]
#
# all of the lowercase letters and underscores are literals, and all
# of the uppercase letters represent attribute values. the different
# attributes are:
#
# W is the width of the source image. if zero, the generated function
# will be able to translate source images of any width, but it will be
# suboptimal. if nonzero, the generated function will only be able to
# translate source images of that width, but it will have some
# optimization. this attribute is only used in source keys, since the
# destination width is always the scaled source width.
#
# H is the height of the source image. if zero, the generated
# function will be able to translate source images of any height, but
# it will be suboptimal. if nonzero, the generated function will only
# be able to translate source images of that height, but it will have
# some optimization. this attribute is only used in source keys,
# since the destination height is always the scaled source height.
#
# D is the color (d)epth, in bits, of the source/destination image.
# if zero, the generated function will be able to handle
# source/destination images of any depth, but it will be suboptimal.
# if nonzero, the generated function will only be able to handle
# source/destination images of that depth, but it will have some
# optimization.
#
# B is the (b)its-per-pixel of the source/destination image. this
# must be at least as large as the depth, and it may be larger. if
# zero, the generated function will be able to handle
# source/destination images of any bits-per-pixel, but it will be
# suboptimal. if nonzero, the generated function will only be able to
# handle source/destination images of that bits-per-pixel, but it will
# have some optimization.
#
# S is the (s)kip-x-bits of the source/destination image. this is the
# number of bits at the beginning of each image scanline that are not
# displayed. if an underscore, the generated function will be able to
# handle source/destination images with any skip-x-bits, but it will
# be suboptimal. if not an underscore, the generated function will
# only be able to handle source/destination images with that many
# skip-x-bits, but it will have some optimization.
#
# P is the (p)adding of the source/destination image. this is how
# many bits each image scanline is padded to. if zero, the generated
# function will be able to handle source/destination images with any
# padding, but it will be suboptimal. if nonzero, the generated
# function will only be able to handle source/destination images with
# that padding, but it will have some optimization.
#
# O is the byte and bit (o)rder of the source/destination image. this
# is always m or l for most- or least-significant, respectively.
# there is no "any" wildcard value. this script cannot handle image
# formats where a word-unit of pixels has one order for its bytes in
# memory, but the opposite order for its pixels within the word-unit.
#
# C is the optional class. it is 'm' for a monochrome (grayscale) image,
# and 'c' for a color image. if not given, an image with a depth of
# one is considered monochrome, and any other image is considered color.
#
# M is the optional mapping type. it is 'l' for a monochrome image
# that linearly maps pixels into intensities and for a color image
# that linearly maps pixel subfields into intensities. it is 'i' for
# images that index pixels or pixel subfields into intensities. if
# not given, monochrome images and color images with subfields are
# assumed to be linear, and color images without subfields are assumed
# to be indexed.
#
# S is the optional mapping size. if the mapping type is given, this
# must be given, and it is the size of the mapping range - i.e., the
# number of bits per intensity. if the mapping type is not given, and
# the image is linearly mapped monochrome, the mapping size is assumed
# to be the same as the image depth.
#
# R, G, and B are the optional subfield masks. if an image's pixels
# can be decomposed into subfields for red, green, and blue, these are
# the masks for the subfields.
#
# X is the optional scaling. it is `h' to halve the source image,
# or `d' to double it. this attribute is only used in source keys.
# this script generates a set of functions for the product of all
# source image formats and all destination image formats.
#
# "all source image formats" includes all source image formats given
# on the command line, plus:
#
# the "any" source image format, unscaled
# the "any" source image format, halved
# the "any" source image format, doubled
#
# "all destination image formats" includes all destination
# image formats given on the command line, plus:
#
# the "any" destination image format
#
src_all=
dst_all=
for order in m l; do
src_key="0x0d0b0s_p0o${order}_r0x0_g0x0_b0x0"
src_all="${src_all} ${src_key} ${src_key}_h ${src_key}_d"
dst_all="${dst_all} d0b0s_p0o${order}_r0x0_g0x0_b0x0"
done
which=
for arg
do
case $arg in
src|dst) which=$arg ;;
*)
if test "x${which}" != x; then
eval "${which}_all=\"$arg \$${which}_all\""
fi
;;
esac
done
PROG=`basename $0`
cat <<EOF
/* automatically generated by $PROG, do not edit! */
/*
* Copyright (c) 2003, 2005 Matt Fredette
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Matt Fredette.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
_TME_RCSID("\$Id: fb-xlat-auto.sh,v 1.12 2009/08/30 21:51:53 fredette Exp $");
/* the central feature of these translation functions is the "bit
FIFO", a first-in, first-out stream of bits. source bit FIFOs are
used to read pixel bits out of source images, and destination bit
FIFOs are used to write pixel bits into destination images.
a bit FIFO has a visible part and an invisible part.
the visible part of a bit FIFO is 32 bits wide, meaning the
translation code can read (for a source bit FIFO) or write (for a
destination bit FIFO) up to 32 bits of pixel data before a bit
FIFO shift.
the invisible part of a source bit FIFO contains pixel bits that
have already been read from the source image memory, but that have
yet to be shifted in to the visible part.
the invisible part of a destination bit FIFO contains the pixel
bits that have been shifted out of the visible part, but that have
yet to be written to the destination image memory.
depending on various attributes of an image format, it may be
possible for the translation code to always read or write the
entire 32 visible bits of a bit FIFO at a time, and as a result
always shift the bit FIFO 32 bits at a time. this is desirable
because it minimizes bit FIFO shifts.
when this does happen, it may also be the case that the visible
part of the bit FIFO always perfectly corresponds to an aligned
32-bit word in the image buffer.
this is the optimal situation, as it makes it unnecessary to track
the invisible part in C local variables at all - each 32-bit FIFO
shift of a source bit FIFO just reads the next 32-bit word directly
into the visible part, and each 32-bit FIFO shift of a destination
bit FIFO just writes the next 32-bit word directly out of the
visible part.
within the visible part of a bit FIFO, which bits belong to which
pixels depends on the "order" of the image format. most-significant
(big-endian) images have earlier (more to the left on the screen)
pixels in more-significant bit positions. least-significant
(little-endian) images have earlier pixels in less-significant bit
bit positions.
bit significance *within* a pixel never depends on image order.
once the bits belonging to a pixel have been identified according
to image order, the least significant bit in that pixel's value is
always the bit with the least absolute value.
some pictures may help explain this better. each picture shows the
32 bit visible part of a bit FIFO, with the bits marked from 0
(least significant) to 31 (most significant). all of these
examples are for a two-bit-deep/two-bits-per-pixel image, and in
the visible part sixteen pixels are numbered. lesser numbered
pixels are earlier (more to the left on the screen). some of the
invisible part is also shown, along with the direction that the bit
FIFO shifts in:
a source bit FIFO for a little-endian source image with two bits
per pixel looks like:
|
| 31 30 29 28 7 6 5 4 3 2 1 0
--+--+--+--+--+--+|+--+--+--+--+- --+--+--+--+--+--+--+--+
.. p18 | p17 | p16 ||| p15 | p14 | .. p3 | p2 | p1 | p0 |
--+--+--+--+--+--+|+--+--+--+--+- --+--+--+--+--+--+--+--+
|
invisible part | visible part
shift -> shift -> shift -> shift -> shift ->
a source bit FIFO for a big-endian source image with two bits per
pixel looks like:
|
31 30 29 28 27 26 25 26 4 3 2 1 0 |
+--+--+--+--+--+--+--+-- -+--+--+--+--+|+--+--+--+--+--+--
| p0 | p1 | p2 | p3 .. | p14 | p15 ||| p16 | p17 | p18 ..
+--+--+--+--+--+--+--+-- -+--+--+--+--+|+--+--+--+--+--+--
|
visible part | invisible part
<- shift <- shift <- shift <- shift <- shift
a destination bit FIFO for a little-endian destination image with
two bits per pixel looks like:
|
31 30 29 28 27 26 25 26 4 3 2 1 0 |
+--+--+--+--+--+--+--+-- -+--+--+--+--+|+--+--+--+--+--+--
| p23 | p22 | p21 | p20 .. | p9 | p8 ||| p7 | p6 | p5 ..
+--+--+--+--+--+--+--+-- -+--+--+--+--+|+--+--+--+--+--+--
|
visible part | invisible part
shift -> shift -> shift -> shift -> shift ->
a destination bit FIFO for a big-endian destination image with
two bits per pixel looks like:
|
| 31 30 29 28 7 6 5 4 3 2 1 0
--+--+--+--+--+--+|+--+--+--+--+- --+--+--+--+--+--+--+--+
.. p5 | p6 | p7 ||| p8 | p9 | .. p20 | p21 | p22 | p23 |
--+--+--+--+--+--+|+--+--+--+--+- --+--+--+--+--+--+--+--+
|
invisible part | visible part
<- shift <- shift <- shift <- shift <- shift
each translation function has at least one source bit FIFO and at
least one destination bit FIFO. the general idea is to read source
pixel value(s) from the source image, map those source pixel
value(s) somehow into destination pixel value(s), and write those
destination pixel value(s) to the destination image.
translation functions that do not scale the image have exactly one
source bit FIFO and exactly one destination bit FIFO. one pixel
read from the source bit FIFO becomes one pixel written to the
destination bit FIFO.
translation functions that halve the image size have two source bit
FIFOs and one destination bit FIFO. one source bit FIFO sources
bits from an even-numbered scanline, and the other sources bits from
an odd-numbered scanline. four pixels read from the source bit
FIFOs - two from each source bit FIFO, making a 2x2 square - become
one pixel written to the destination bit FIFO.
translation functions that double the image size have one source
bit FIFO and two destination bit FIFOs. one destination bit FIFO
sinks bits for an even-numbered scanline, and the other sinks bits
for an odd-numbered scanline. one pixel read from the source bit
FIFO becomes four pixels written to the destination bit FIFOs -
two to each destination bit FIFO, making a 2x2 square.
translation functions don't necessarily always translate the entire
source image into the entire destination image. instead, the buffer
holding the current source image is expected to be twice as large as
necessary (plus some overhead), with the second half of the buffer
holding a copy of the last translated ("old") source image.
before setting up and translating pixels using bit FIFOs, a
translation function treats the the current and old source images as
an array of aligned 32-bit words and compares them. if it finds no
32-bit word that has changed, no translation is done and the
function returns.
otherwise, initial source pixel x and y coordinates are derived from
the offset of the 32-bit word that failed comparison, and the source
primary bit FIFO is primed. if this translation function halves the
image size, the source secondary bit FIFO is primed from the same x
coordinate on the "other" (think y ^ 1) scanline.
then, initial destination pixel x and y coordinates are derived from
the initial source x and y coordinates, and the destination primary
bit FIFO is primed. if this translation function doubles the image
size, the destination secondary bit FIFO is primed from the same x
coordinate on the "other" (think y ^ 1) scanline.
as mentioned previously, the buffer holding the current source image
is expected to be twice as large as necessary (plus some overhead),
with the second half of the buffer holding a copy of the last
translated ("old") source image.
this "overhead" is approximately two extra scanlines worth of data,
that is initialized to all-bits-zero and must always remain zero.
this extra data is present at the end of both the current ("new")
and last translated ("old") source images.
these extra, always-blank scanlines guarantee that the pixel
translation loop terminates. the pixel translation loop *never*
checks for the end of the image buffer. instead, it terminates only
after it has read in TME_FB_XLAT_RUN consecutive aligned 32-bit
words that have *not* changed between the new and old source images.
this small amount of extra memory overhead simplifies the pixel
translation loop, because it doesn't have to worry about going past
the end of the actual image.
*/
/* macros: */
/* given a 32-bit aligned pointer into the current source image, this
returns the corresponding 32-bit aligned pointer in the last
translated ("old") source image. since the old source image
follows the current source image, this is simple pointer arithmetic
using src_bypb: */
#define TME_FB_XLAT_SRC_OLD(raw) \\
((tme_uint32_t *) (((tme_uint8_t *) (raw)) + src_bypb))
/* when the fast, aligned 32-bit word comparison loop finds a word
that has changed in the source image, pixels are translated until
TME_FB_XLAT_RUN consecutive aligned 32-bit words are processed that
have *not* changed in the source image, at which point the fast
comparison loop resumes.
the idea is that after you've started translating pixels, once the
FIFO shift operation has read TME_FB_XLAT_RUN consecutive raw,
unchanged 32-bit words, all of the pixels from previous, changed
32-bit words have been translated and shifted out of the source bit
FIFO(s), and all bits remaining in the source bit FIFO(s) are for
pixels in those unchanged 32-bit words. since the pixels are
unchanged, pixel translation can stop, and the entire state of the
source bit FIFO(s) can be discarded.
so, each time a raw, changed 32-bit word is read, xlat_run is
reloaded with TME_FB_XLAT_RUN, and each time 32 bits worth of
source image pixels are processed, it is decremented. when it
reaches zero, the source bit FIFO(s) are discarded, the destination
bit FIFO(s) are flushed, the pixel translation loop breaks and the
fast comparison loop continues: */
#define TME_FB_XLAT_RUN (2)
/* this shifts a source FIFO: */
#define TME_FB_XLAT_SHIFT_SRC(unaligned, fifo, next, bits, shift, raw, order)\\
do { \\
\\
/* if the source FIFO may not be 32-bit aligned: */ \\
if (unaligned) { \\
\\
/* we must be shifting between 1 and 32 bits: */ \\
assert ((shift) >= 1 && (shift) <= 32); \\
\\
/* the FIFO must have more than 32 bits in it already: */ \\
assert (bits > 32); \\
\\
/* shift the FIFO: */ \\
if ((shift) == 32) { \\
fifo = next; \\
} \\
else if (order == TME_ENDIAN_BIG) { \\
fifo = (fifo << ((shift) & 31)) | (next >> (32 - (shift)));\\
next <<= ((shift) & 31); \\
} \\
else { \\
fifo = (fifo >> ((shift) & 31)) | (next << (32 - (shift)));\\
next >>= ((shift) & 31); \\
} \\
bits -= (shift); \\
\\
/* if we have a new 32-bit word to read: */ \\
if (bits <= 32) { \\
next = *raw; \\
if (*TME_FB_XLAT_SRC_OLD(raw) != next) { \\
*TME_FB_XLAT_SRC_OLD(raw) = next; \\
xlat_run = TME_FB_XLAT_RUN; \\
} \\
raw++; \\
next = (order == TME_ENDIAN_BIG \\
? tme_betoh_u32(next) \\
: tme_letoh_u32(next)); \\
\\
/* before the load, if there were fewer than 32 bits \\
remaining in the FIFO, shift bits from the word \\
we just loaded into their proper positions: */ \\
if (bits < 32) { \\
if (order == TME_ENDIAN_BIG) { \\
fifo |= (next >> bits); \\
next <<= (32 - bits); \\
} \\
else { \\
fifo |= (next << bits); \\
next >>= (32 - bits); \\
} \\
} \\
\\
/* there are now 32 more bits in the FIFO: */ \\
bits += 32; \\
} \\
} \\
\\
/* otherwise, if the source FIFO is always 32-bit aligned: */ \\
else { \\
\\
/* we must be shifting exactly 32 bits: */ \\
assert((shift) == 32); \\
\\
/* load the next 32-bit word: */ \\
fifo = *raw; \\
if (*TME_FB_XLAT_SRC_OLD(raw) != fifo) { \\
*TME_FB_XLAT_SRC_OLD(raw) = fifo; \\
xlat_run = TME_FB_XLAT_RUN; \\
} \\
raw++; \\
fifo = (order == TME_ENDIAN_BIG \\
? tme_betoh_u32(fifo) \\
: tme_letoh_u32(fifo)); \\
} \\
} while (/* CONSTCOND */ 0)
/* this shifts a destination FIFO: */
#define TME_FB_XLAT_SHIFT_DST(unaligned, fifo, next, bits, shift, raw, order)\\
do { \\
\\
/* if the destination FIFO may not be 32-bit aligned: */ \\
if (unaligned) { \\
\\
/* we must be shifting between 1 and 32 bits: */ \\
assert ((shift) >= 1 && (shift) <= 32); \\
\\
/* the FIFO must have fewer than 32 bits in it: */ \\
assert (bits < 32); \\
\\
/* shift the FIFO: */ \\
if (order == TME_ENDIAN_BIG) { \\
next |= (fifo >> bits); \\
fifo <<= (32 - bits); \\
} \\
else { \\
next |= (fifo << bits); \\
fifo >>= (32 - bits); \\
} \\
if (SHIFTMAX_INT32_T < 32 && bits == 0) { \\
fifo = 0; \\
} \\
bits += (shift); \\
\\
/* if we have a completed 32-bit word to write: */ \\
if (bits >= 32) { \\
*(raw++) = (order == TME_ENDIAN_BIG \\
? tme_htobe_u32(next) \\
: tme_htole_u32(next)); \\
bits -= 32; \\
assert(bits != 0 || fifo == 0); \\
next = fifo; \\
} \\
} \\
\\
/* the destination FIFO is always 32-bit aligned: */ \\
else { \\
\\
/* we must be shifting exactly 32 bits: */ \\
assert((shift) == 32); \\
\\
/* store the next 32-bit word: */ \\
*(raw++) = (order == TME_ENDIAN_BIG \\
? tme_htobe_u32(fifo) \\
: tme_htole_u32(fifo)); \\
\\
} \\
\\
/* clear the writable part of the FIFO: */ \\
fifo = 0; \\
} while (/* CONSTCOND */ 0)
/* _TME_FB_XLAT_MAP_LINEAR_SCALE gives the factor needed to scale a
masked value up or down to a given size in bits. for example, if a
value's mask is 0xf800 (a five bit mask), and the value needs to be
scaled up to seven bits, this gives an factor of four. if a
value's mask is 0x7e0 (a six bit mask), and the value needs to be
scaled down to three bits, this gives a factor of eight: */
#define _TME_FB_XLAT_MAP_LINEAR_SCALE(mask_in, mask_out) \\
(TME_FB_XLAT_MAP_BASE_MASK(mask_in) \\
^ TME_FB_XLAT_MAP_BASE_MASK(mask_out))
#define TME_FB_XLAT_MAP_LINEAR_SCALE(mask_in, mask_out) \\
(_TME_FB_XLAT_MAP_LINEAR_SCALE(mask_in, mask_out) \\
? (TME_FB_XLAT_MAP_BASE_MASK(_TME_FB_XLAT_MAP_LINEAR_SCALE(mask_in, mask_out))\\
+ 1) \\
: 1)
/* this linearly maps a value from one mask to another: */
#define _TME_FB_XLAT_MAP_LINEAR(value, mask_in, mask_out) \\
\\
/* if the value does not need to be scaled up: */ \\
(((TME_FB_XLAT_MAP_BASE_MASK(mask_out) \\
<= TME_FB_XLAT_MAP_BASE_MASK(mask_in)) \\
? \\
\\
/* extract the value and scale it down: */ \\
(TME_FIELD_MASK_EXTRACTU(value, mask_in) \\
/ TME_FB_XLAT_MAP_LINEAR_SCALE(mask_in, mask_out)) \\
\\
/* otherwise, the value needs to be scaled up: */ \\
: \\
\\
/* extract the value: */ \\
((TME_FIELD_MASK_EXTRACTU(value, mask_in) \\
\\
/* scale it up: */ \\
* TME_FB_XLAT_MAP_LINEAR_SCALE(mask_in, mask_out)) \\
\\
/* if the least significant bit of the value is set, add \\
in the scale minus one. this makes the linear mapping \\
at least cover the entire range: */ \\
+ (((value / \\
_TME_FIELD_MASK_FACTOR(mask_in)) \\
& 1) \\
* (TME_FB_XLAT_MAP_LINEAR_SCALE(mask_in, mask_out) \\
- 1)))) \\
\\
/* finally, shift the value into position: */ \\
* _TME_FIELD_MASK_FACTOR(mask_out))
/* this indexes a value: */
#define _TME_FB_XLAT_MAP_INDEX(value, mask_out, index) \\
\\
/* intensities are either stored as 8 or 16 bits: */ \\
(((TME_FB_XLAT_MAP_BASE_MASK(mask_out) <= 0xff) \\
? ((const tme_uint8_t *) (index))[(value)] \\
: ((const tme_uint16_t *) (index))[(value)]) \\
\\
/* shift the value into position: */ \\
* _TME_FIELD_MASK_FACTOR(mask_out))
/* this maps one subfield or intensity value into another subfield or
intensity value: */
#define TME_FB_XLAT_MAP(value, mask_in, mask_out, indexed, index)\\
\\
/* do the linear mapping or the index mapping: */ \\
((!(indexed)) \\
? _TME_FB_XLAT_MAP_LINEAR(value, mask_in, mask_out) \\
: _TME_FB_XLAT_MAP_INDEX(TME_FIELD_MASK_EXTRACTU(value, mask_in), mask_out, index))
EOF
# the next function number:
xlat_next=0
xlat_array=
# permute over the source possibilities:
for src_key in ${src_all}; do
# take apart the source possibility:
src_parts=${src_key}
# get the width:
width=`echo ${src_parts} | sed -e 's/^\([0-9][0-9]*\)\(.*\)$/\1/'`
src_parts=`echo ${src_parts} | sed -e 's/^\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the height:
height=`echo ${src_parts} | sed -e 's/^x\([0-9][0-9]*\)\(.*\)$/\1/'`
src_parts=`echo ${src_parts} | sed -e 's/^x\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the source depth:
src_depth=`echo ${src_parts} | sed -e 's/^d\([0-9][0-9]*\)\(.*\)$/\1/'`
src_parts=`echo ${src_parts} | sed -e 's/^d\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the source bits per pixel:
src_bipp=`echo ${src_parts} | sed -e 's/^b\([0-9][0-9]*\)\(.*\)$/\1/'`
src_parts=`echo ${src_parts} | sed -e 's/^b\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the source skip pixel count:
src_skipx=`echo ${src_parts} | sed -e 's/^s\([_0-9][0-9]*\)\(.*\)$/\1/'`
src_parts=`echo ${src_parts} | sed -e 's/^s\([_0-9][0-9]*\)\(.*\)$/\2/'`
# get the source scanline pad:
src_pad=`echo ${src_parts} | sed -e 's/^p\([0-9][0-9]*\)\(.*\)$/\1/'`
src_parts=`echo ${src_parts} | sed -e 's/^p\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the source "order" - i.e., byte order and leftmost (first)
# pixel significance:
src_order=`echo ${src_parts} | sed -e 's/^o\([ml]\)\(.*\)$/\1/'`
src_parts=`echo ${src_parts} | sed -e 's/^o\([ml]\)\(.*\)$/\2/'`
# get the optional source "class" - monochrome or color:
src_class=`echo ${src_parts} | sed -e 's/^c\([mc]\)\(.*\)$/\1/'`
if test "x${src_class}" = "x${src_parts}"; then src_class= ; fi
src_parts=`echo ${src_parts} | sed -e 's/^c\([mc]\)\(.*\)$/\2/'`
# get the optional source pixel mapping - linear or indexed, and
# the optional number of bits in the map range:
src_map=`echo ${src_parts} | sed -e 's/^m\([li]\)\([0-9]*\)\(.*\)$/\1/'`
src_map_bits=`echo ${src_parts} | sed -e 's/^m\([li]\)\([0-9]*\)\(.*\)$/\2/'`
if test "x${src_map}" = "x${src_parts}"; then src_map= ; src_map_bits= ; fi
src_parts=`echo ${src_parts} | sed -e 's/^m\([li]\)\([0-9]*\)\(.*\)$/\3/'`
# get the optional source pixel subfield masks:
src_mask_g= ; src_mask_r= ; src_mask_b=
while true; do
src_mask=`echo ${src_parts} | sed -e 's/^\(_[rgb]\)\(0x[0-9A-Fa-f][0-9A-Fa-f]*\)\(.*\)$/src_mask\1=\2/'`
if test "x${src_mask}" = "x${src_parts}"; then break; fi
eval ${src_mask}
src_parts=`echo ${src_parts} | sed -e 's/^\(_[rgb]\)\(0x[0-9A-Fa-f][0-9A-Fa-f]*\)\(.*\)$/\3/'`
done
# get the source scaling:
scale="${src_parts}_"
# if the source class is not given, but the source depth is
# known, assume monochrome if the source depth is one, else
# assume color:
#
if test "x${src_class}" = x; then
case "${src_depth}" in
0) src_class= ;;
1) src_class=m ;;
*) src_class=c ;;
esac
fi
# if the source mapping type is not given:
#
if test "x${src_map}" = x; then
# if the source class is known as color:
#
if test "x${src_class}" = "xc"; then
# if it is known that there are not any subfield masks, assume an indexed
# mapping, else if it is known that there are subfield masks, assume a
# linear mapping:
#
case "x${src_mask_r}" in
x0x0) ;;
x) src_map=i ;;
*) src_map=l ;;
esac
# if the source class is known as monochrome:
#
elif test "x${src_class}" = "xm"; then
# assume a linear mapping:
#
src_map=l
fi
fi
# if the size of the source mapping range in bits is not given:
#
if test "x${src_map_bits}" = x; then
# if the source class is known as mono and the source mapping
# type is known as linear, assume that the source depth is the
# size of the mapping range in bits:
#
if test "x${src_class}" = xm && test "x${src_map}" = xl; then
src_map_bits=${src_depth}
# otherwise, set the size of the mapping range to zero to indicate
# unknown:
#
else
src_map_bits=0
fi
fi
# permute over the destination possibilities:
for dst_key in ${dst_all}; do
# take apart the destination possibility:
dst_parts=${dst_key}
# get the destination depth:
dst_depth=`echo ${dst_parts} | sed -e 's/^d\([0-9][0-9]*\)\(.*\)$/\1/'`
dst_parts=`echo ${dst_parts} | sed -e 's/^d\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the destination bits per pixel:
dst_bipp=`echo ${dst_parts} | sed -e 's/^b\([0-9][0-9]*\)\(.*\)$/\1/'`
dst_parts=`echo ${dst_parts} | sed -e 's/^b\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the destination skip pixel count:
dst_skipx=`echo ${dst_parts} | sed -e 's/^s\([_0-9][0-9]*\)\(.*\)$/\1/'`
dst_parts=`echo ${dst_parts} | sed -e 's/^s\([_0-9][0-9]*\)\(.*\)$/\2/'`
# get the destination scanline pad:
dst_pad=`echo ${dst_parts} | sed -e 's/^p\([0-9][0-9]*\)\(.*\)$/\1/'`
dst_parts=`echo ${dst_parts} | sed -e 's/^p\([0-9][0-9]*\)\(.*\)$/\2/'`
# get the destination "order" - i.e., byte order and leftmost
# (first) pixel significance:
dst_order=`echo ${dst_parts} | sed -e 's/^o\([ml]\)\(.*\)$/\1/'`
dst_parts=`echo ${dst_parts} | sed -e 's/^o\([ml]\)\(.*\)$/\2/'`
# get the optional destination pixel mapping - linear or indexed:
dst_map=`echo ${dst_parts} | sed -e 's/^m\([li]\)\(.*\)$/\1/'`
if test "x${dst_map}" = "x${dst_parts}"; then dst_map= ; fi
dst_parts=`echo ${dst_parts} | sed -e 's/^m\([li]\)\(.*\)$/\2/'`
# get the optional destination pixel subfield masks:
dst_mask_g= ; dst_mask_r= ; dst_mask_b=
while true; do
dst_mask=`echo ${dst_parts} | sed -e 's/^\(_[rgb]\)\(0x[0-9A-Fa-f][0-9A-Fa-f]*\)\(.*\)$/dst_mask\1=\2/'`
if test "x${dst_mask}" = "x${dst_parts}"; then break; fi
eval ${dst_mask}
dst_parts=`echo ${dst_parts} | sed -e 's/^\(_[rgb]\)\(0x[0-9A-Fa-f][0-9A-Fa-f]*\)\(.*\)$/\3/'`
done
# allocate the xlat number:
xlat=${xlat_next}
xlat_next=`expr ${xlat_next} + 1`
xlat_info="tme_fb_xlat${xlat}"
# start the function:
echo ""
echo "/* this translates frame buffer contents from this source format:"
case "${width}x${height}" in
0x0) echo -n " any dimensions" ;;
*x0) echo -n " width $width, any height" ;;
0x*) echo -n " any width, height ${height}" ;;
*) echo -n " ${width}x${height}" ;;
esac
xlat_info="${xlat_info}, ${width}, ${height}"
case ${scale} in
_h_) echo " (image will be halved)" ; value="HALF" ;;
_d_) echo " (image will be doubled)" ; value="DOUBLE" ;;
*) echo "" ; value="NONE" ;;
esac
xlat_info="${xlat_info}, TME_FB_XLAT_SCALE_${value}"
echo -n " "
case ${src_depth} in
0) echo -n "any depth" ;;
1) echo -n "1 bit deep" ;;
*) echo -n "${src_depth} bits deep" ;;
esac
xlat_info="${xlat_info}, ${src_depth}"
case ${src_bipp} in
0) echo -n ", any bits per pixel" ;;
1) echo -n ", 1 bit per pixel" ;;
*) echo -n ", ${src_bipp} bits per pixel" ;;
esac
xlat_info="${xlat_info}, ${src_bipp}"
case ${src_skipx} in
_) echo -n ", any number of pixels skipped" ; value="-1";;
*) echo -n ", ${src_skipx} pixels skipped" ; value=${src_skipx} ;;
esac
xlat_info="${xlat_info}, ${value}"
case ${src_pad} in
0) echo -n ", any scanline padding" ;;
*) echo -n ", ${src_pad}-bit scanline padding" ;;
esac
xlat_info="${xlat_info}, ${src_pad}"
case ${src_order} in
m) echo -n ", MSB-first" ; value="BIG" ;;
l) echo -n ", LSB-first" ; value="LITTLE" ;;
esac
xlat_info="${xlat_info}, TME_ENDIAN_${value}"
case "x${src_class}" in
xm) echo -n ", monochrome" ; value="MONOCHROME" ;;
xc) echo -n ", color" ; value="COLOR" ;;
*) echo -n ", either color or monochrome" ; value="ANY" ;;
esac
xlat_info="${xlat_info}, TME_FB_XLAT_CLASS_${value}"
case "x${src_map}" in
xl) echo -n ", linearly mapped pixels" ; value="LINEAR" ;;
xi) echo -n ", index mapped pixels" ; value="INDEX" ;;
*) echo -n ", any pixel mapping" ; value="ANY" ;;
esac
xlat_info="${xlat_info}, TME_FB_XLAT_MAP_${value}"
value=${src_map_bits}
case "${src_map_bits}" in
0) echo -n ", any bits per mapped intensity" ;;
1) echo -n ", 1 bit per mapped intensity" ;;
*) echo -n ", ${src_map_bits} bits per mapped intensity" ;;
esac
xlat_info="${xlat_info}, ${value}"
for primary in g r b; do
eval "src_mask=\$src_mask_${primary}"
case "x${src_mask}" in
x) echo -n ", no ${primary} mask" ; value=0 ;;
x0x0) echo -n ", any ${primary} mask" ; value=TME_FB_XLAT_MASK_ANY ;;
*) echo -n ", a ${primary} mask of ${src_mask}" ; value=${src_mask} ;;
esac
xlat_info="${xlat_info}, ${value}"
done
echo ""
echo " to this destination format:"
echo -n " "
case ${dst_depth} in
0) echo -n "any depth" ;;
1) echo -n "1 bit deep" ;;
*) echo -n "${dst_depth} bits deep" ;;
esac
xlat_info="${xlat_info}, ${dst_depth}"
case ${dst_bipp} in
0) echo -n ", any bits per pixel" ;;
1) echo -n ", 1 bit per pixel" ;;
*) echo -n ", ${dst_bipp} bits per pixel" ;;
esac
xlat_info="${xlat_info}, ${dst_bipp}"
case ${dst_skipx} in
_) echo -n ", any number of pixels skipped" ; value="-1";;
*) echo -n ", ${dst_skipx} pixels skipped" ; value=${dst_skipx} ;;
esac
xlat_info="${xlat_info}, ${value}"
case ${dst_pad} in
0) echo -n ", any scanline padding" ;;
*) echo -n ", ${dst_pad}-bit scanline padding" ;;
esac
xlat_info="${xlat_info}, ${dst_pad}"
case ${dst_order} in
m) echo -n ", MSB-first" ; value="BIG" ;;
l) echo -n ", LSB-first" ; value="LITTLE" ;;
esac
xlat_info="${xlat_info}, TME_ENDIAN_${value}"
case "x${dst_map}" in
xl) echo -n ", linearly mapped pixels" ; value="LINEAR" ;;
xi) echo -n ", index mapped pixels" ; value="INDEX" ;;
*) echo -n ", any pixel mapping" ; value="ANY" ;;
esac
xlat_info="${xlat_info}, TME_FB_XLAT_MAP_${value}"
for primary in g r b; do
eval "dst_mask=\$dst_mask_${primary}"
case "x${dst_mask}" in
x) echo -n ", no ${primary} mask" ; value=0 ;;
x0x0) echo -n ", any ${primary} mask" ; value=TME_FB_XLAT_MASK_ANY ;;
*) echo -n ", a ${primary} mask of ${dst_mask}" ; value=${dst_mask} ;;
esac
xlat_info="${xlat_info}, ${value}"
done
save_IFS=$IFS
IFS=
xlat_array="${xlat_array}
{ $xlat_info }, "
IFS=$save_IFS
echo ""
echo "*/"
echo "static int"
echo "tme_fb_xlat${xlat}(struct tme_fb_connection *src,"
echo " struct tme_fb_connection *dst)"
echo "{"
undef_macros=
echo ""
echo " /* whenever possible we define macros instead of declaring"
echo " variables, for optimization: */"
echo ""
echo " /* declare src_x and src_y. these are the current translation"
echo " coordinates in the source image: */"
echo " unsigned int src_x, src_y;"
echo ""
echo " /* declare dst_x and dst_y. these are the current translation"
echo " coordinates in the destination image. since this function"
if test $scale = _; then
echo " does not scale the image, these coordinates are always"
echo " the same as the coordinates in the source image: */"
echo "#define dst_x (src_x)"
echo "#define dst_y (src_y)"
undef_macros="${undef_macros} dst_x dst_y"
scale_op=
scale_math=
else
if test $scale = _h_; then
scale_op='/'
scale_name='halves'
else
scale_op='*'
scale_name='doubles'
fi
scale_math=" ${scale_op} 2"
echo " ${scale_name} the image, the coordinates in the destination image"
echo " are always the coordinates in the source image${scale_math}: */"
echo " unsigned int dst_x, dst_y;"
fi
echo ""
echo " /* declare pixel. this holds a single pixel value being translated"
echo " for the destination image: */"
echo " tme_uint32_t pixel;"
echo ""
echo " /* declare src_width and dst_width. these are in terms of pixels: */"
value="(src_width${scale_math})"
if test ${width} = 0; then
echo " const unsigned int src_width = src->tme_fb_connection_width;"
if test $scale != _; then
echo " const unsigned int dst_width = ${value};"
else
echo "#define dst_width ${value}"
undef_macros="${undef_macros} dst_width"
fi
else
echo "#define src_width (${width})"
echo "#define dst_width ${value}"
undef_macros="${undef_macros} src_width dst_width"
fi
echo ""
echo " /* declare src_depth, the source pixel depth, which is in"
echo " terms of bits. declare src_mask, which is the corresponding"
echo " mask of one bits: */"
value="(0xffffffff >> (32 - src_depth))"
if test ${src_depth} = 0; then
echo " const unsigned int src_depth = src->tme_fb_connection_depth;"
echo " const tme_uint32_t src_mask = ${value};"
else
echo "#define src_depth (${src_depth})"
echo "#define src_mask ${value}"
undef_macros="${undef_macros} src_depth src_mask"
fi
# if we are halving, or if source pixels may have subfields,
# we may need to deal with intensities:
#
if test ${scale} = _h_ || test "x${src_mask_g}" != x; then
echo ""
echo " /* declare src_indexed. this is nonzero if source pixel subfields"
echo " are index-mapped into intensities: */"
if test "x${src_map}" = x; then
echo " const unsigned int src_indexed = (src->tme_fb_connection_map_g != NULL);"
else
if test "x${src_map}" = xi; then value=TRUE; else value=FALSE; fi
echo "#define src_indexed (${value})"
undef_macros="${undef_macros} src_indexed"
fi
echo ""
echo " /* declare src_mask_i, which is the mask for a source intensity: */"
if test "${src_map_bits}" = 0; then
echo " const tme_uint32_t src_mask_i = (0xffffffff >> (32 - src->tme_fb_connection_map_bits));"
else
echo "#define src_mask_i (0xffffffff >> (32 - ${src_map_bits}))"
undef_macros="${undef_macros} src_mask_i"
fi
if test "x${src_class}" != xm; then
echo ""
echo " /* declare dst_indexed. this is nonzero if intensities are index-mapped"
echo " into destination pixel subfields: */"
if test "x${dst_map}" = x; then
echo " const unsigned int dst_indexed = (dst->tme_fb_connection_map_g != NULL);"
else
if test "x${dst_map}" = xi; then value=TRUE; else value=FALSE; fi
echo "#define dst_indexed (${value})"
undef_macros="${undef_macros} dst_indexed"
fi
echo ""
echo " /* declare dst_masks_default. this is nonzero if the destination"
echo " subfield masks are the default: */"
if test "x${dst_mask_g}" = "x0x0"; then
echo " const unsigned int dst_masks_default = (dst->tme_fb_connection_mask_g == 0);"
else
if test "x${dst_mask_g}" = x; then value=TRUE; else value=FALSE; fi
echo "#define dst_masks_default (${value})"
undef_macros="${undef_macros} dst_masks_default"
fi
fi
for primary in g r b; do
primary_cap=`echo ${primary} | tr a-z A-Z`
echo ""
echo " /* declare src_mask_${primary}, the mask for the ${primary} subfield in a source pixel: */"
eval "src_mask=\$src_mask_${primary}"
if test "x${src_mask}" = x0x0; then
echo " const tme_uint32_t src_mask_${primary}"
echo " = (src->tme_fb_connection_mask_${primary} != 0"
echo " ? src->tme_fb_connection_mask_${primary}"
echo " : src_mask);"
else
if test "x${src_mask}" = x; then src_mask="src_mask"; fi
echo "#define src_mask_${primary} (${src_mask})"
undef_macros="${undef_macros} src_mask_${primary}"
fi
echo ""
echo " /* declare value_${primary}, the intensity value for the ${primary} subfield in a pixel: */"
echo " tme_uint32_t value_${primary};"
if test "x${src_class}" = xm; then break; fi
echo ""
echo " /* declare dst_mask_${primary}, the mask for the ${primary} subfield in a destination pixel: */"
eval "dst_mask=\$dst_mask_${primary}"
if test "x${dst_mask}" = x0x0; then
echo " const tme_uint32_t dst_mask_${primary}"
echo " = (dst->tme_fb_connection_mask_${primary} != 0"
echo " ? dst->tme_fb_connection_mask_${primary}"
echo " : TME_FB_XLAT_MASK_DEFAULT_${primary_cap});"
else
if test "x${dst_mask}" = x; then dst_mask="TME_FB_XLAT_MASK_DEFAULT_${primary_cap}"; fi
echo "#define dst_mask_${primary} (${dst_mask})"
undef_macros="${undef_macros} dst_mask_${primary}"
fi
done
fi
echo ""
echo " /* declare src_bipp and dst_bipp. these are the bits-per-pixel"
echo " values for the source and destination images: */"
if test ${src_bipp} = 0; then
echo " const unsigned int src_bipp = src->tme_fb_connection_bits_per_pixel;"
else
echo "#define src_bipp (${src_bipp})"
undef_macros="${undef_macros} src_bipp"
fi
if test ${dst_bipp} = 0; then
echo " const unsigned int dst_bipp = dst->tme_fb_connection_bits_per_pixel;"
else
echo "#define dst_bipp (${dst_bipp})"
undef_macros="${undef_macros} dst_bipp"
fi
echo ""
echo " /* declare src_skipx and dst_skipx. these are the counts of"
echo " undisplayed pixels at the beginning of each scanline in the"
echo " source and destination images: */"
if test ${src_skipx} = _; then
echo " const unsigned int src_skipx = src->tme_fb_connection_skipx;"
else
echo "#define src_skipx (${src_skipx})"
undef_macros="${undef_macros} src_skipx"
fi
if test ${dst_skipx} = _; then
echo " const unsigned int dst_skipx = dst->tme_fb_connection_skipx;"
else
echo "#define dst_skipx (${dst_skipx})"
undef_macros="${undef_macros} dst_skipx"
fi
echo ""
echo " /* declare src_pad and dst_pad. these are the paddings, in bits,"
echo " of each scanline in the source and destination images: */"
if test ${src_pad} = 0; then
echo " const unsigned int src_pad = src->tme_fb_connection_scanline_pad;"
else
echo "#define src_pad (${src_pad})"
undef_macros="${undef_macros} src_pad"
fi
if test ${dst_pad} = 0; then
echo " const unsigned int dst_pad = dst->tme_fb_connection_scanline_pad;"
else
echo "#define dst_pad (${dst_pad})"
undef_macros="${undef_macros} dst_pad"
fi
echo ""
echo " /* declare src_order and dst_order. these are the bit and byte"
echo " orders (either TME_ENDIAN_BIG or TME_ENDIAN_LITTLE) of the"
echo " source and destination images. since these values profoundly"
echo " affect optimization, they are always constant: */"
if test ${src_order} = m; then value=BIG; else value=LITTLE; fi
echo "#define src_order (TME_ENDIAN_${value})"
undef_macros="${undef_macros} src_order"
if test ${dst_order} = m; then value=BIG; else value=LITTLE; fi
echo "#define dst_order (TME_ENDIAN_${value})"
undef_macros="${undef_macros} dst_order"
echo ""
echo " /* declare src_bypl and dst_bypl. these are the bytes per scanline"
echo " in the source and destination images. these values are calculated"
echo " from the count of undisplayed and displayed pixels per scanline,"
echo " the number of bits per pixel, and the scanline padding: */"
value="(((((src_skipx + src_width) * src_bipp) + (src_pad - 1)) & -src_pad) / 8)"
if test ${src_skipx} = _ || test ${width} = 0 || test ${src_bipp} = 0 || test ${src_pad} = 0; then
echo " const unsigned int src_bypl = ${value};"
src_bypl_var=true
else
echo "#define src_bypl ${value}"
undef_macros="${undef_macros} src_bypl"
src_bypl_var=false
fi
value="(((((dst_skipx + dst_width) * dst_bipp) + (dst_pad - 1)) & -dst_pad) / 8)"
if test ${dst_skipx} = _ || test ${width} = 0 || test ${dst_bipp} = 0 || test ${dst_pad} = 0; then
echo " const unsigned int dst_bypl = ${value};"
dst_bypl_var=true
else
echo "#define dst_bypl ${value}"
undef_macros="${undef_macros} dst_bypl"
dst_bypl_var=false
fi
echo ""
echo " /* declare src_packed and dst_packed. these are nonzero iff"
echo " every last bit in a scanline belongs to a displayed pixel."
echo " put another way, this is zero iff a scanline has undisplayed"
echo " pixels at its beginning or padding bits at its end. when"
echo " a source image or destination image is packed, translation"
echo " doesn't have to worry about skipping FIFO bits to get to"
echo " bits belonging to displayed pixels: */"
value="((src_width * src_bipp) == (src_bypl * 8))"
if $src_bypl_var; then
echo " const unsigned int src_packed = ${value};"
else
echo "#define src_packed ${value}"
undef_macros="${undef_macros} src_packed"
fi
value="((dst_width * dst_bipp) == (dst_bypl * 8))"
if $dst_bypl_var; then
echo " const unsigned int dst_packed = ${value};"
else
echo "#define dst_packed ${value}"
undef_macros="${undef_macros} dst_packed"
fi
echo ""
echo " /* declare src_bypb and src_bypb_real. src_bypb is the bytes"
echo " per source image buffer with the \"translation termination"
echo " overhead\" of approximately two extra scanlines. src_bypb_real"
echo " is the real bytes per source image buffer with no overhead."
echo " both values are padded to a multiple of 4 bytes (32 bits): */"
if test ${height} = 0; then
value="src->tme_fb_connection_height"
else
value="${height}"
fi
value_real="(((${value} * src_bypl) + 3) & -4)"
value="((src_bypb_real + (src_bypl * 2)) & -4)"
if test ${height} = 0 || $src_bypl_var; then
echo " const unsigned int src_bypb_real = ${value_real};"
echo " const unsigned int src_bypb = ${value};"
else
echo "#define src_bypb_real ${value_real}"
echo "#define src_bypb ${value}"
undef_macros="${undef_macros} src_bypb_real src_bypb"
fi
echo ""
echo " /* declare the source primary bit FIFO:"
echo ""
echo " src_raw0 points to the next aligned 32-bit word to be"
echo " read from the image buffer."
echo ""
echo " src_fifo0 is the visible part of the bit FIFO."
echo ""
echo " src_fifo0_next and src_fifo0_bits are only used when the"
echo " visible part of the bit FIFO is not guaranteed to always"
echo " correspond to an aligned 32-bit word in the image buffer."
echo " src_fifo0_next is the invisible part of the bit FIFO,"
echo " and src_fifo0_bits tracks the total number of bits in the"
echo " visible and invisible parts of the FIFO. */"
echo " const tme_uint32_t *src_raw0;"
echo " tme_uint32_t src_fifo0, src_fifo0_next;"
echo " unsigned int src_fifo0_bits;"
if test ${scale} = _h_; then
echo ""
echo " /* since this function ${scale_name} the image, declare the"
echo " source secondary bit FIFO. these variables work in "
echo " exactly the same way that their primary counterparts do: */"
echo " const tme_uint32_t *src_raw1;"
echo " tme_uint32_t src_fifo1, src_fifo1_next;"
echo " unsigned int src_fifo1_bits;"
fi
echo ""
echo " /* declare the destination primary bit FIFO:"
echo ""
echo " dst_raw0 points to the next aligned 32-bit word to be"
echo " written into the image buffer."
echo ""
echo " dst_fifo0 is the visible part of the bit FIFO."
echo ""
echo " dst_fifo0_next and dst_fifo0_bits are only used when the"
echo " visible part of the bit FIFO is not guaranteed to always"
echo " correspond to an aligned 32-bit word in the image buffer."
echo " dst_fifo0_next is the invisible part of the bit FIFO,"
echo " and dst_fifo0_bits tracks the total number of bits in the"
echo " invisible part of the FIFO. */"
echo " tme_uint32_t *dst_raw0;"
echo " tme_uint32_t dst_fifo0, dst_fifo0_next;"
echo " unsigned int dst_fifo0_bits;"
if test ${scale} = _d_; then
echo ""
echo " /* since this function ${scale_name} the image, declare"
echo " the destination secondary bit FIFO. these variables work"
echo " in exactly the same way that their primary counterparts"
echo " do: */"
echo " tme_uint32_t *dst_raw1;"
echo " tme_uint32_t dst_fifo1, dst_fifo1_next;"
echo " unsigned int dst_fifo1_bits;"
fi
echo ""
echo " /* declare src_off and dst_off. these are used when priming a"
echo " source or destination bit FIFO, to identify an initial aligned"
echo " 32-bit word in the source or destination image buffer, and an"
echo " initial bit offset within that word: */"
echo " unsigned int src_off, dst_off;"
echo ""
echo " /* declare src_fifo0_may_be_unaligned. this is zero iff all"
echo " aligned 32-bit words in the source buffer contain a whole"
echo " number of displayed pixels, and at *all times during the"
echo " translation* the visible part of the bit FIFO is guaranteed"
echo " to correspond to an aligned 32-bit word in the image buffer."
echo ""
echo " this is *not* so if any of the following are true:"
echo ""
echo " - the source bits-per-pixel value is not known at compile"
echo " time. in this case, we can't unroll the translation loop"
echo " for source pixels, and are forced to shift the FIFO after"
echo " each one."
echo ""
echo " - if the source image is not packed. in this case, there may"
echo " be undisplayed pixels in the FIFO, which we will need to"
echo " shift out."
echo ""
echo " - if there are 24 bits per source pixel. in this case, a"
echo " source pixel may cross a 32-bit boundary: */"
src_fifo0_may_be_unaligned_var=false
if test ${src_bipp} = 0; then
value=TRUE
else
value="(!src_packed || (src_bipp == 24))"
src_fifo0_may_be_unaligned_var=${src_bypl_var}
fi
if $src_fifo0_may_be_unaligned_var; then
echo " const unsigned int src_fifo0_may_be_unaligned = ${value};"
else
echo "#define src_fifo0_may_be_unaligned ${value}"
undef_macros="${undef_macros} src_fifo0_may_be_unaligned"
fi
if test $scale = _h_; then
echo ""
echo " /* declare src_fifo1_may_be_unaligned. this is zero iff all"
echo " aligned 32-bit words in the source buffer contain a"
echo " whole number of displayed pixels, *and* for every aligned"
echo " 32-bit word on one scanline all other scanlines have an"
echo " aligned 32-bit word corresponding to the same x coordinate: */"
value="(src_fifo0_may_be_unaligned || (src_bypl & 3))"
if $src_bypl_var; then
echo " const unsigned int src_fifo1_may_be_unaligned = ${value};"
else
echo "#define src_fifo1_may_be_unaligned ${value}"
undef_macros="${undef_macros} src_fifo1_may_be_unaligned"
fi
fi
echo ""
echo " /* declare dst_fifo0_may_be_unaligned. this is zero iff all"
echo " aligned 32-bit words in the destination buffer contain a whole"
echo " number of displayed pixels, and at *all times during the"
echo " translation* the visible part of the bit FIFO is guaranteed"
echo " to correspond to an aligned 32-bit word in the image buffer."
echo ""
echo " this is *not* so if any of the following are true:"
echo ""
echo " - the destination bits-per-pixel value is not known at compile"
echo " time. in this case, we can't unroll the translation loop"
echo " for destination pixels, and are forced to shift the FIFO"
echo " after each one."
echo ""
echo " - if src_fifo0_may_be_unaligned is true. in this case, we"
echo " definitely can't guarantee that any initial dst_x will"
echo " correspond to an aligned 32-bit word in the destination buffer."
echo ""
echo " - if the destination image is not packed. in this case, there may"
echo " be undisplayed pixels in the FIFO, which we will need to"
echo " shift out."
echo ""
echo " - if there are 24 bits per destination pixel. in this case,"
echo " a destination pixel may cross a 32-bit boundary."
echo ""
echo " - if a possible initial dst_x doesn't correspond to an aligned"
echo " 32-bit word in the destination buffer. for this last one:"
echo ""
echo " since we require that src_fifo0_may_be_unaligned is zero, we"
echo " know that the initial src_x = (Z * 32) / src_bipp for "
echo " some Z. we also have the initial dst_x = src_x${scale_math}."
echo " the initial destination bit offset will then be:"
echo ""
echo " (dst_skipx + dst_x) * dst_bipp"
echo " = (dst_skipx * dst_bipp) + (dst_x * dst_bipp)"
echo ""
echo " if we additionally require that (dst_skipx * dst_bipp)"
echo " be 32-bit aligned, this reduces things to:"
echo ""
echo " dst_x * dst_bipp"
echo " = (src_x${scale_math}) * dst_bipp"
echo " = (((Z * 32) / src_bipp)${scale_math}) * dst_bipp"
echo ""
echo " which will be a multiple of 32 iff:"
echo ""
echo " ((1 / src_bipp)${scale_math}) * dst_bipp >= 1 and integral"
echo ""
echo " or, equivalently:"
echo ""
denom="src_bipp"
numer="dst_bipp"
case $scale in
_) ;;
_h_) denom="(${denom} * 2)" ;;
_d_) numer="(${numer} * 2)" ;;
esac
echo " (${numer} % ${denom}) == 0"
echo " */"
dst_fifo0_may_be_unaligned_var=false
if test ${dst_bipp} = 0; then
value=TRUE
else
value="(src_fifo0_may_be_unaligned || !dst_packed || (dst_bipp == 24) || (dst_bypl % 4) || ((dst_skipx * dst_bipp) % 32) || (${numer} % ${denom}))"
if $src_bypl_var || $dst_bypl_var; then
dst_fifo0_may_be_unaligned_var=true
fi
fi
if $dst_fifo0_may_be_unaligned_var; then
echo " const unsigned int dst_fifo0_may_be_unaligned = ${value};"
else
echo "#define dst_fifo0_may_be_unaligned ${value}"
undef_macros="${undef_macros} dst_fifo0_may_be_unaligned"
fi
if test $scale = _d_; then
echo ""
echo " /* declare dst_fifo1_may_be_unaligned. this is zero iff all"
echo " 32-bit aligned values in the destination buffer contain a"
echo " whole number of displayed pixels, and for every 32-bit"
echo " aligned value on one scanline all other scanlines have a"
echo " 32-bit aligned value corresponding to the same x coordinate: */"
value="(dst_fifo0_may_be_unaligned || (dst_bypl & 3))"
if $src_bypl_var || $dst_bypl_var; then
echo " const unsigned int dst_fifo1_may_be_unaligned = ${value};"
else
echo "#define dst_fifo1_may_be_unaligned ${value}"
undef_macros="${undef_macros} dst_fifo1_may_be_unaligned"
fi
fi
echo ""
echo " /* declare src_offset_updated_first and src_offset_updated_last,"
echo " which hold the offsets of the first and last updated bytes in"
echo " the source image: */"
echo " tme_uint32_t src_offset_updated_first;"
echo " tme_uint32_t src_offset_updated_last;"
echo ""
echo " /* declare src_raw0_end. when treating the source image as"
echo " an array of aligned 32-bit words, this variable holds the"
echo " address of the first word after the real source image."
echo " if the fast, aligned 32-bit word comparison loop passes"
echo " this point, the entire source image has been processed and"
echo " the function terminates: */"
echo " const tme_uint32_t *src_raw0_end;"
echo ""
echo " /* declare xlat_run. see the comment for the TME_FB_XLAT_RUN"
echo " macro for an explanation of what this variable does: */"
echo " int xlat_run;"
echo ""
echo " /* this silences gcc -Wuninitialized: */"
echo " src_fifo0_next = 0;"
echo " src_fifo0_bits = 0;"
if test ${scale} = _h_; then
echo " src_fifo1_next = 0;"
echo " src_fifo1_bits = 0;"
fi
echo " dst_fifo0_next = 0;"
echo " dst_fifo0_bits = 0;"
if test ${scale} = _d_; then
echo " dst_fifo1_next = 0;"
echo " dst_fifo1_bits = 0;"
fi
echo ""
echo " /* initialize src_raw0 and src_raw0_end for the fast aligned 32-bit"
echo " word comparison loop. on entry to (and when continuing) that loop,"
echo " src_raw0 always points to the aligned 32-bit word *before* the"
echo " next word to check. src_raw0_end always points after the last"
echo " word to check."
echo ""
echo " src_raw0 is actually part of the source primary bit FIFO, which"
echo " is good, because when the fast comparison fails on a word, src_raw0"
echo " is already primed and ready to work for that bit FIFO: */"
echo " src_offset_updated_first = src->tme_fb_connection_offset_updated_first;"
echo " src_offset_updated_last = TME_MIN(src->tme_fb_connection_offset_updated_last, src_bypb_real - 1);"
echo " src->tme_fb_connection_offset_updated_first = 0;"
echo " src->tme_fb_connection_offset_updated_last = src_bypb_real - 1;"
echo " if (src_offset_updated_first > src_offset_updated_last) {"
echo " return (FALSE);"
echo " }"
echo " src_raw0"
echo " = (((const tme_uint32_t *)"
echo " (src->tme_fb_connection_buffer"
echo " + (src_offset_updated_first"
echo " & (0 - (tme_uint32_t) sizeof(tme_uint32_t)))))"
echo " -1);"
echo " src_raw0_end"
echo " = ((const tme_uint32_t *)"
echo " (src->tme_fb_connection_buffer"
echo " + src_offset_updated_last"
echo " + 1));"
echo ""
echo " /* initialize xlat_run to -1. it can never go negative inside the"
echo " pixel translation loop, so if xlat_run stays negative for the"
echo " entire translation, it means that the source image hasn't changed"
echo " since the last translation. this information is returned to the"
echo " caller to hopefully save more work in updating the display: */"
echo " xlat_run = -1;"
echo ""
echo " /* this is the main translation loop, which contains the fast aligned"
echo " 32-bit word comparison loop, and the pixel translation loop: */"
echo " for (;;) {"
echo ""
echo " /* this is the fast aligned 32-bit word comparison loop. it"
echo " terminates either when a word fails comparison, or when the"
echo " entire source image has been compared. the if test that"
echo " follows checks for the latter case and breaks the main"
echo " translation loop: */"
echo " for (; (++src_raw0 < src_raw0_end"
echo " && *src_raw0 == *TME_FB_XLAT_SRC_OLD(src_raw0)); );"
echo " if (src_raw0 >= src_raw0_end) {"
echo " break;"
echo " }"
echo ""
echo " /* calculate the byte offset into the source buffer of the"
echo " 32-bit word that failed comparison: */"
echo " src_off = ((tme_uint8_t *) src_raw0) - src->tme_fb_connection_buffer;"
echo ""
echo " /* calculate the source y pixel coordinate, and reduce"
echo " src_off from the byte offset into the buffer to the"
echo " byte offset into that scanline: */"
echo " src_y = src_off / src_bypl;"
echo " src_off = src_off % src_bypl;"
echo ""
echo " /* while translating pixels, we use one or more \"bit FIFOs\","
echo " each composed of one or more 32-bit integers. we load these"
echo " FIFOs 32 bits at a time. */"
echo ""
echo " /* prime the visible part of the source primary bit FIFO: */"
echo " src_fifo0 = *src_raw0;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw0) = src_fifo0;"
echo " src_raw0++;"
echo " src_fifo0 = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(src_fifo0)"
echo " : tme_letoh_u32(src_fifo0));"
echo ""
echo " /* if the source primary bit FIFO may be unaligned: */"
echo " if (src_fifo0_may_be_unaligned) {"
echo ""
echo " /* prime the invisible part of the source primary bit FIFO and"
echo " assume that we will not have to shift it to finish: */"
echo " src_fifo0_next = *src_raw0;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw0) = src_fifo0_next;"
echo " src_raw0++;"
echo " src_fifo0_next = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(src_fifo0_next)"
echo " : tme_letoh_u32(src_fifo0_next));"
echo " src_fifo0_bits = 0;"
echo ""
echo " /* if there are pixels that need to be skipped, the first 32 bits"
echo " we loaded into the FIFO may have first bits that belong to"
echo " those undisplayed (skipped) pixels. it is *not* possible for"
echo " it to have first bits that belong to the scanline pad; there"
echo " might be pad bits in the *middle* of the first 32 bits, but any"
echo " first bits *must* belong to pixels, displayed or not: */"
echo " if (src_skipx > 0"
echo " && (src_off * 8) < (src_skipx * src_bipp)) {"
echo ""
echo " /* see how many bits we will need to skip: */"
echo " src_fifo0_bits = (src_skipx * src_bipp) - (src_off * 8);"
echo ""
echo " /* if it is more than 31 bits, this is an entire 32 bits of"
echo " undisplayed pixels. just advance: */"
echo " if (src_fifo0_bits > 31) {"
echo " src_raw0--;"
echo " continue;"
echo " }"
echo ""
echo " /* set the source x coordinate to zero: */"
echo " src_x = 0;"
echo " }"
echo ""
echo " /* otherwise, the first 32 bits we load will have first bits for"
echo " a displayable pixel: */"
echo " else {"
echo ""
echo " /* if the source bits per pixel is 24, calculate the number of"
echo " bytes *before* the original src_raw0 of any split pixel, and"
echo " subtract this from src_off, to leave src_off as the byte offset"
echo " into the scanline of the beginning of a pixel: */"
echo " if (src_bipp == 24) {"
echo " src_fifo0_bits = (src_off % 3);"
echo " src_off -= src_fifo0_bits;"
echo ""
echo " /* if this is a split pixel, we need to prime the source primary"
echo " bit FIFO starting with the part *before* the original src_raw0."
echo " we do not have to copy to the old; it passed comparison: */"
echo " if (src_fifo0_bits) {"
echo " src_raw0--;"
echo " src_fifo0_next = src_fifo0;"
echo " src_fifo0 = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(*(src_raw0 - 2))"
echo " : tme_letoh_u32(*(src_raw0 - 2)));"
echo " }"
echo " }"
echo ""
echo " /* calculate the source x coordinate: */"
echo " src_x = ((src_off * 8) / src_bipp) - src_skipx;"
echo " }"
echo ""
echo " /* do any shifting to finish priming the source primary FIFO: */"
echo " if (src_fifo0_bits) {"
echo " if (src_order == TME_ENDIAN_BIG) {"
echo " src_fifo0 = (src_fifo0 << src_fifo0_bits) | (src_fifo0_next >> (32 - src_fifo0_bits));"
echo " src_fifo0_next <<= src_fifo0_bits;"
echo " }"
echo " else {"
echo " src_fifo0 = (src_fifo0 >> src_fifo0_bits) | (src_fifo0_next << (32 - src_fifo0_bits));"
echo " src_fifo0_next >>= src_fifo0_bits;"
echo " }"
echo " }"
echo " src_fifo0_bits = 64 - src_fifo0_bits;"
echo " }"
echo ""
echo " /* otherwise, the source primary FIFO is aligned: */"
echo " else {"
echo " src_x = ((src_off * 8) / src_bipp) - src_skipx;"
echo " }"
if test $scale = _h_; then
echo ""
echo " /* when halving the image, we have a source secondary bit "
echo " FIFO, providing pixel values at the same source x coordinate"
echo " but on the \"other\" line. prime the source secondary"
echo " bit FIFO: */"
echo " if (src_fifo1_may_be_unaligned) {"
echo ""
echo " /* calculate the bit offset into the source buffer of"
echo " this exact same pixel on the other line: */"
echo " src_off = ((src_y ^ 1) * src_bypl * 8) + ((src_skipx + src_x) * src_bipp);"
echo ""
echo " /* calculate how many bits offset from a 32-bit boundary the pixel is: */"
echo " src_fifo1_bits = src_off % 32;"
echo ""
echo " /* set src_raw1: */"
echo " src_raw1 = (const tme_uint32_t *)"
echo " (src->tme_fb_connection_buffer"
echo " + ((src_off - src_fifo1_bits) / 8));"
echo ""
echo " /* actually prime the FIFO by loading the first two words and"
echo " shifting off any offset bits: */"
echo " src_fifo1 = *src_raw1;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw1) = src_fifo1;"
echo " src_raw1++;"
echo " src_fifo1_next = *src_raw1;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw1) = src_fifo1_next;"
echo " src_raw1++;"
echo " if (src_order == TME_ENDIAN_BIG) {"
echo " src_fifo1 = tme_betoh_u32(src_fifo1);"
echo " src_fifo1_next = tme_betoh_u32(src_fifo1_next);"
echo " if (src_fifo1_bits) {"
echo " src_fifo1 = (src_fifo1 << src_fifo1_bits) | (src_fifo1_next >> (32 - src_fifo1_bits));"
echo " src_fifo1_next <<= src_fifo1_bits;"
echo " }"
echo " }"
echo " else {"
echo " src_fifo1 = tme_letoh_u32(src_fifo1);"
echo " src_fifo1_next = tme_letoh_u32(src_fifo1_next);"
echo " if (src_fifo1_bits) {"
echo " src_fifo1 = (src_fifo1 >> src_fifo1_bits) | (src_fifo1_next << (32 - src_fifo1_bits));"
echo " src_fifo1_next >>= src_fifo1_bits;"
echo " }"
echo " }"
echo " src_fifo1_bits = 64 - src_fifo1_bits;"
echo " }"
echo ""
echo " /* otherwise the source secondary FIFO is aligned: */"
echo " else {"
echo " src_raw1 = (const tme_uint32_t *)"
echo " (((tme_uint8_t *) src_raw0)"
echo " + (("
echo " /* if src_y is even, this addend is now src_bypl * 4,"
echo " else if src_y is odd, this addend is now src_bypl * 2: */"
echo " ((src_bypl * 4) >> (src_y & 1))"
echo " /* if src_y is even, this addend is now src_bypl,"
echo " else if src_y is odd, this addend is now -src_bypl: */"
echo " - (src_bypl * 3))"
echo " /* this -4 compensates for src_raw0 already having"
echo " been advanced by one: */"
echo " - 4));"
echo " src_fifo1 = *src_raw1;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw1) = src_fifo1;"
echo " src_raw1++;"
echo " src_fifo1 = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(src_fifo1)"
echo " : tme_letoh_u32(src_fifo1));"
echo " }"
fi
if test $scale != _; then
echo ""
echo " /* calculate the destination coordinates: */"
echo " dst_y = src_y${scale_math};"
echo " dst_x = src_x${scale_math};"
fi
echo ""
echo " /* prime the destination primary bit FIFO: */"
echo " dst_fifo0 = 0;"
echo " if (dst_fifo0_may_be_unaligned) {"
echo ""
echo " /* calculate the bit offset into the destination buffer of"
echo " the destination pixel: */"
echo " dst_off = (dst_y * dst_bypl * 8) + ((dst_skipx + dst_x) * dst_bipp);"
echo ""
echo " /* calculate the number of bits that will be in the primed FIFO: */"
echo " dst_fifo0_bits = dst_off % 32;"
echo ""
echo " /* set dst_raw0: */"
echo " dst_raw0 = (tme_uint32_t *)"
echo " (dst->tme_fb_connection_buffer"
echo " + ((dst_off - dst_fifo0_bits) / 8));"
echo ""
echo " /* prime the primary destination FIFO: */"
echo " dst_fifo0_next = 0;"
echo " if (dst_fifo0_bits) {"
echo " dst_fifo0_next = (src_order == TME_ENDIAN_BIG"
echo " ? (tme_betoh_u32(*dst_raw0) & (0xffffffffUL << (32 - dst_fifo0_bits)))"
echo " : (tme_letoh_u32(*dst_raw0) & (0xffffffffUL >> (32 - dst_fifo0_bits))));"
echo " }"
echo " }"
echo ""
echo " /* otherwise the destination primary FIFO is aligned: */"
echo " else {"
echo " dst_off = (dst_y * dst_bypl) + (((dst_skipx + dst_x) * dst_bipp) / 8);"
echo " dst_raw0 = (tme_uint32_t *) (dst->tme_fb_connection_buffer + dst_off);"
echo " }"
if test $scale = _d_; then
echo ""
echo " /* when doubling the image, we have a destination secondary bit "
echo " FIFO, for pixel values at the same source x coordinate"
echo " but on the \"other\" line. prime the destination secondary"
echo " bit FIFO: */"
echo " dst_fifo1 = 0;"
echo " if (dst_fifo1_may_be_unaligned) {"
echo ""
echo " /* calculate the bit offset into the destination buffer of"
echo " the destination pixel: */"
echo " dst_off = ((dst_y + 1) * dst_bypl * 8) + ((dst_skipx + dst_x) * dst_bipp);"
echo ""
echo " /* calculate the number of bits that will be in the primed FIFO: */"
echo " dst_fifo1_bits = dst_off % 32;"
echo ""
echo " /* set dst_raw1: */"
echo " dst_raw1 = (tme_uint32_t *)"
echo " (dst->tme_fb_connection_buffer"
echo " + ((dst_off - dst_fifo1_bits) / 8));"
echo ""
echo " /* prime the primary destination FIFO: */"
echo " dst_fifo1_next = 0;"
echo " if (dst_fifo1_bits) {"
echo " dst_fifo1_next = (src_order == TME_ENDIAN_BIG"
echo " ? (tme_betoh_u32(*dst_raw1) & (0xffffffffUL << (32 - dst_fifo1_bits)))"
echo " : (tme_letoh_u32(*dst_raw1) & (0xffffffffUL >> (32 - dst_fifo1_bits))));"
echo " }"
echo " }"
echo ""
echo " /* otherwise, the destination secondary FIFO is aligned: */"
echo " else {"
echo " dst_raw1 = (tme_uint32_t *)"
echo " (((tme_uint8_t *) dst_raw0)"
echo " + dst_bypl);"
echo " }"
fi
# we want to unroll the pixel translation loop to read as many
# source pixels as possible out of the source bit FIFOs and
# write as many destination pixels as possible into the
# destination bit FIFOs before shifting them.
#
# it is very common to want to unroll the translation loop a
# different number of times on source and destination pixels,
# so we always unroll the maximum possible, tracking within
# each unrolled iteration the relative unrolled iteration for
# the source and destination bit FIFOs.
#
# src_unroll and dst_unroll are the number of times we will
# unroll the translation loop on source and destination
# pixels, respectively. assume no unrolling:
#
src_unroll=1
dst_unroll=1
# src_iter_scale is the number of source pixels read out of a
# source bit FIFO in one unrolled iteration of the translation
# loop. if this function halves the source image, this is
# two, otherwise this is one.
#
# dst_iter_scale is the number of destination pixels written
# to a destination bit FIFO in one unrolled iteration of the
# translation loop. if this function doubles the source
# image, this is two, otherwise this is one.
#
# src_fifo_shift is the number of bits that the source bit
# FIFO(s) must be shifted after all unrolled iterations on
# source pixels. assume no unrolling, so if this function
# halves the source image and src_bipp is less than 24, two
# pixels' bits must be shifted, otherwise one pixel's bits
# must be shifted.
#
# dst_fifo_shift is the number of bits that the destination bit
# FIFO(s) must be shifted after all unrolled iterations on
# destination pixels. we are assuming no unrolling, so if this
# function doubles the source image and dst_bipp is less than
# 24, two pixels' bits must be shifted, otherwise one pixel's
# bits must be shifted:
#
if test $scale = _h_; then
src_iter_scale=2
src_fifo_shift="(src_bipp < 24 ? (src_bipp * 2) : src_bipp)"
else
src_iter_scale=1
src_fifo_shift="src_bipp"
fi
if test $scale = _d_; then
dst_iter_scale=2
dst_fifo_shift="(dst_bipp < 24 ? (dst_bipp * 2) : dst_bipp)"
else
dst_iter_scale=1
dst_fifo_shift="dst_bipp"
fi
# if src_bipp is known now, see how many times we can unroll the
# translation loop on source pixels:
#
if test ${src_bipp} != 0; then
# in general, we can unroll once for each pixel in the
# visible part of a source bit FIFO:
#
src_unroll=`expr 32 / ${src_bipp}`
# if this function halves the source image, we can unroll
# half as many times:
#
src_unroll=`expr ${src_unroll} / ${src_iter_scale}`
# if we think we can unroll zero times, this means that
# src_bipp is greater than 16 and this function halves the
# source image - the zero is telling us that two whole
# pixels cannot fit in the visible part of a source bit
# FIFO. so we unroll once on source pixels, and shift
# only one pixel's bits after the unrolling (the halving
# code will be shifting one pixel's worth of bits to get
# to the next pixel it has to read):
#
if test ${src_unroll} = 0; then
src_unroll=1
src_fifo_shift=${src_bipp}
# otherwise, we will be shifting the entire visible part
# of the source bit FIFO(s) after all unrolled iterations:
#
else
src_fifo_shift=32
fi
echo ""
echo " /* since src_bipp is known at code-generation time, the"
echo " pixel translation loop is unrolled to translate all"
echo " source pixels in the 32-bit visible part of the source"
echo " bit FIFO(s) before shifting."
echo ""
echo " in this case, src_bipp is known to be ${src_bipp}, so "`expr ${src_unroll} \* ${src_iter_scale}`" pixels will"
echo " be read out of the source bit FIFO(s) before shifting, and"
echo " when the source bit FIFO(s) are shifted, they are shifted"
echo " ${src_fifo_shift} bits at a time: */"
fi
# if dst_bipp is known now, see how many times we can unroll the
# translation loop on destination pixels:
#
if test ${dst_bipp} != 0; then
# in general, we can unroll once for each pixel in the
# visible part of a destination bit FIFO:
#
dst_unroll=`expr 32 / ${dst_bipp}`
# if this function doubles the source image, we can unroll
# half as many times:
#
dst_unroll=`expr ${dst_unroll} / ${dst_iter_scale}`
# if we think we can unroll zero times, this means that
# dst_bipp is greater than 16 and this function doubles the
# source image - the zero is telling us that two whole
# pixels cannot fit in the visible part of a destination bit
# FIFO. so we unroll once on destination pixels, and shift
# only one pixel's bits after the unrolling (the doubling
# code will be shifting one pixel's worth of bits to get
# out the first pixel it has to write):
#
if test ${dst_unroll} = 0; then
dst_unroll=1
dst_fifo_shift=${dst_bipp}
# otherwise, we will be shifting the entire visible part
# of the source bit FIFO(s) after all unrolled iterations:
#
else
dst_fifo_shift=32
fi
echo ""
echo " /* since dst_bipp is known at code-generation time, the pixel"
echo " translation loop is unrolled to translate all destination"
echo " pixels in the 32-bit visible part of the destination bit"
echo " FIFO(s) before shifting."
echo ""
echo " in this case, dst_bipp is known to be ${dst_bipp}, so "`expr ${dst_unroll} \* ${dst_iter_scale}`" pixels will"
echo " be written into the destination bit FIFO(s) before shifting,"
echo " and when the destination bit FIFO(s) are shifted, they are"
echo " shifted ${dst_fifo_shift} bits at a time: */"
fi
# unroll the translation loop the maximum number amount of times:
#
if test `expr ${src_unroll} \> ${dst_unroll}` = 1; then
unroll=${src_unroll}
else
unroll=${dst_unroll}
fi
echo ""
echo " /* src_unroll = ${src_unroll}, src_iter_scale = ${src_iter_scale}"
echo " dst_unroll = ${dst_unroll}, dst_iter_scale = ${dst_iter_scale} */"
echo " for (xlat_run = TME_FB_XLAT_RUN;"
echo " xlat_run > 0; ) {"
iter=0
while test `expr ${iter} \< ${unroll}` = 1; do
echo ""
echo " /* iter #${iter} */"
echo ""
iter_next=`expr ${iter} + 1`
# the number of bits to skip in a source FIFO to get to
# this iteration's pixel:
src_shift=`expr ${iter} % ${src_unroll}`
src_shift='('`expr ${src_shift} \* ${src_iter_scale}`' * src_bipp)'
echo " /* get a pixel from the source primary FIFO: */"
echo " pixel ="
echo " ((src_fifo0"
echo " >> (src_order == TME_ENDIAN_BIG"
echo " ? (32 - (src_bipp + ${src_shift}))"
echo " : ${src_shift})));"
indent0=X
if test $scale != _h_; then
if test "x${src_mask_g}" = x; then
echo ""
echo " /* since source pixels are known at compile time to"
echo " not have subfields, map the source pixel into the"
echo " destination pixel: */"
echo " pixel = dst->tme_fb_connection_map_pixel[pixel & src_mask];"
else
echo ""
echo " /* if the source depth is within the threshold for pixel"
echo " mapping, or if source pixels don't have subfields,"
echo " map the source pixel into the destination pixel: */"
echo " if (src_mask <= TME_FB_XLAT_MAP_INDEX_MASK_MAX"
echo " || src_mask_g == src_mask) {"
echo " pixel = dst->tme_fb_connection_map_pixel[pixel & src_mask];"
echo " }"
echo ""
echo " /* otherwise, we will decompose this source pixel"
echo " and then compose the destination pixel: */"
echo " else {"
echo ""
echo " /* map the pixel subfields into intensities: */"
echo " value_g = TME_FB_XLAT_MAP(pixel, src_mask_g, src_mask_i, src_indexed, src->tme_fb_connection_map_g);"
if test "x${src_class}" != xm; then
echo " value_r = TME_FB_XLAT_MAP(pixel, src_mask_r, src_mask_i, src_indexed, src->tme_fb_connection_map_r);"
echo " value_b = TME_FB_XLAT_MAP(pixel, src_mask_b, src_mask_i, src_indexed, src->tme_fb_connection_map_b);"
fi
indent0=" "
src_mask_i=src_mask_i
src_mask_i_max=TME_FB_XLAT_MAP_INDEX_MASK_MAX
fi
else
echo ""
echo " /* map the pixel subfields into intensities: */"
echo " value_g = TME_FB_XLAT_MAP(pixel, src_mask_g, src_mask_i, src_indexed, src->tme_fb_connection_map_g);"
if test "x${src_class}" != xm; then
echo " value_r = TME_FB_XLAT_MAP(pixel, src_mask_r, src_mask_i, src_indexed, src->tme_fb_connection_map_r);"
echo " value_b = TME_FB_XLAT_MAP(pixel, src_mask_b, src_mask_i, src_indexed, src->tme_fb_connection_map_b);"
fi
echo ""
echo " /* get a second pixel, from the source secondary FIFO: */"
echo " pixel ="
echo " ((src_fifo1"
echo " >> (src_order == TME_ENDIAN_BIG"
echo " ? (32 - (src_bipp + ${src_shift}))"
echo " : ${src_shift})));"
echo ""
echo " /* map the pixel subfields into intensities and accumulate them: */"
echo " value_g += TME_FB_XLAT_MAP(pixel, src_mask_g, src_mask_i, src_indexed, src->tme_fb_connection_map_g);"
if test "x${src_class}" != xm; then
echo " value_r += TME_FB_XLAT_MAP(pixel, src_mask_r, src_mask_i, src_indexed, src->tme_fb_connection_map_r);"
echo " value_b += TME_FB_XLAT_MAP(pixel, src_mask_b, src_mask_i, src_indexed, src->tme_fb_connection_map_b);"
fi
echo ""
echo " /* get third and fourth pixels, from the source primary"
echo " FIFO and source secondary FIFO, respectively. if"
echo " src_bipp is 24 or greater, these pixels are not yet"
echo " entirely in the first parts of the FIFOs, so we need"
echo " to shift: */"
echo " if (src_bipp >= 24) {"
echo " TME_FB_XLAT_SHIFT_SRC(src_fifo0_may_be_unaligned,"
echo " src_fifo0,"
echo " src_fifo0_next,"
echo " src_fifo0_bits,"
echo " src_bipp,"
echo " src_raw0,"
echo " src_order);"
echo " TME_FB_XLAT_SHIFT_SRC(src_fifo1_may_be_unaligned,"
echo " src_fifo1,"
echo " src_fifo1_next,"
echo " src_fifo1_bits,"
echo " src_bipp,"
echo " src_raw1,"
echo " src_order);"
echo " pixel ="
echo " ((src_fifo0"
echo " >> (src_order == TME_ENDIAN_BIG"
echo " ? (32 - (src_bipp + ${src_shift}))"
echo " : ${src_shift})));"
echo ""
echo " /* map the pixel subfields into intensities and accumulate them: */"
echo " value_g += TME_FB_XLAT_MAP(pixel, src_mask_g, src_mask_i, src_indexed, src->tme_fb_connection_map_g);"
if test "x${src_class}" != xm; then
echo " value_r += TME_FB_XLAT_MAP(pixel, src_mask_r, src_mask_i, src_indexed, src->tme_fb_connection_map_r);"
echo " value_b += TME_FB_XLAT_MAP(pixel, src_mask_b, src_mask_i, src_indexed, src->tme_fb_connection_map_b);"
fi
echo ""
echo " pixel ="
echo " ((src_fifo1"
echo " >> (src_order == TME_ENDIAN_BIG"
echo " ? (32 - (src_bipp + ${src_shift}))"
echo " : ${src_shift})));"
echo ""
echo " /* map the pixel subfields into intensities and accumulate them: */"
echo " value_g += TME_FB_XLAT_MAP(pixel, src_mask_g, src_mask_i, src_indexed, src->tme_fb_connection_map_g);"
if test "x${src_class}" != xm; then
echo " value_r += TME_FB_XLAT_MAP(pixel, src_mask_r, src_mask_i, src_indexed, src->tme_fb_connection_map_r);"
echo " value_b += TME_FB_XLAT_MAP(pixel, src_mask_b, src_mask_i, src_indexed, src->tme_fb_connection_map_b);"
fi
echo " }"
echo ""
echo " /* otherwise, the third and fourth pixels are already in the"
echo " visible parts of the source bit FIFOs; we just have to"
echo " reach over the pixels we already read to get at them: */"
echo " else {"
echo " pixel ="
echo " ((src_fifo0"
echo " >> (src_order == TME_ENDIAN_BIG"
echo " ? (32 - (src_bipp + (${src_shift} + src_bipp)))"
echo " : (${src_shift} + src_bipp))));"
echo ""
echo " /* map the pixel subfields into intensities and accumulate them: */"
echo " value_g += TME_FB_XLAT_MAP(pixel, src_mask_g, src_mask_i, src_indexed, src->tme_fb_connection_map_g);"
if test "x${src_class}" != xm; then
echo " value_r += TME_FB_XLAT_MAP(pixel, src_mask_r, src_mask_i, src_indexed, src->tme_fb_connection_map_r);"
echo " value_b += TME_FB_XLAT_MAP(pixel, src_mask_b, src_mask_i, src_indexed, src->tme_fb_connection_map_b);"
fi
echo ""
echo " pixel ="
echo " ((src_fifo1"
echo " >> (src_order == TME_ENDIAN_BIG"
echo " ? (32 - (src_bipp + (${src_shift} + src_bipp)))"
echo " : (${src_shift} + src_bipp))));"
echo ""
echo " /* map the pixel subfields into intensities and accumulate them: */"
echo " value_g += TME_FB_XLAT_MAP(pixel, src_mask_g, src_mask_i, src_indexed, src->tme_fb_connection_map_g);"
if test "x${src_class}" != xm; then
echo " value_r += TME_FB_XLAT_MAP(pixel, src_mask_r, src_mask_i, src_indexed, src->tme_fb_connection_map_r);"
echo " value_b += TME_FB_XLAT_MAP(pixel, src_mask_b, src_mask_i, src_indexed, src->tme_fb_connection_map_b);"
fi
echo " }"
indent0=
src_mask_i='((src_mask_i * 4) + 3)'
src_mask_i_max='(TME_FB_XLAT_MAP_INDEX_MASK_MAX / 4)'
fi
# if we may have intensities:
#
if test "X${indent0}" != XX; then
echo ""
indent1=X
case "x${src_class}" in
xm)
echo "${indent0} /* since the source_class is known as monochrome at code-generation"
echo "${indent0} time, we map the green intensity directly into a pixel. we may have"
echo "${indent0} to scale the intensity to be in the lookup range: */"
echo "${indent0} if (src_mask_i > ${src_mask_i_max}) {"
echo "${indent0} value_g /= TME_FB_XLAT_MAP_LINEAR_SCALE(${src_mask_i}, TME_FB_XLAT_MAP_INDEX_MASK_MAX);"
echo "${indent0} }"
echo "${indent0} pixel = dst->tme_fb_connection_map_pixel[value_g];"
;;
x)
echo "${indent0} /* if the source class is monochrome, we map the green intensity"
echo "${indent0} directly into a pixel. we may have to scale the intensity"
echo "${indent0} to be in the lookup range: */"
echo "${indent0} if (src->tme_fb_connection_class == TME_FB_XLAT_CLASS_MONOCHROME) {"
echo "${indent0} if (src_mask_i > ${src_mask_i_max}) {"
echo "${indent0} value_g /= TME_FB_XLAT_MAP_LINEAR_SCALE(${src_mask_i}, TME_FB_XLAT_MAP_INDEX_MASK_MAX);"
echo "${indent0} }"
echo "${indent0} pixel = dst->tme_fb_connection_map_pixel[value_g];"
echo "${indent0} }"
echo ""
echo "${indent0} /* otherwise, we have to consider all three intensities: */"
echo "${indent0} else {"
indent1="${indent0} "
;;
*)
echo "${indent0} /* we have to consider all three intensities: */"
indent1="${indent0}"
esac
if test "X${indent1}" != "XX"; then
echo ""
echo "${indent1} /* if destination intensities are indexed: */"
echo "${indent1} if (dst_indexed) {"
echo ""
echo "${indent1} /* we may have to scale the intensities to be in the lookup range: */"
echo "${indent1} if (src_mask_i > ${src_mask_i_max}) {"
echo "${indent1} value_g /= TME_FB_XLAT_MAP_LINEAR_SCALE(${src_mask_i}, TME_FB_XLAT_MAP_INDEX_MASK_MAX);"
echo "${indent1} value_r /= TME_FB_XLAT_MAP_LINEAR_SCALE(${src_mask_i}, TME_FB_XLAT_MAP_INDEX_MASK_MAX);"
echo "${indent1} value_b /= TME_FB_XLAT_MAP_LINEAR_SCALE(${src_mask_i}, TME_FB_XLAT_MAP_INDEX_MASK_MAX);"
echo "${indent1} }"
echo ""
echo "${indent1} /* form the pixel: */"
echo "${indent1} pixel = _TME_FB_XLAT_MAP_INDEX(value_g, dst_mask_g, dst->tme_fb_connection_map_g);"
echo "${indent1} pixel |= _TME_FB_XLAT_MAP_INDEX(value_r, dst_mask_r, dst->tme_fb_connection_map_r);"
echo "${indent1} pixel |= _TME_FB_XLAT_MAP_INDEX(value_b, dst_mask_b, dst->tme_fb_connection_map_b);"
echo "${indent1} }"
echo ""
echo "${indent1} /* otherwise, destination intensities are linear: */"
echo "${indent1} else {"
echo ""
echo "${indent1} /* form the pixel: */"
echo "${indent1} pixel = _TME_FB_XLAT_MAP_LINEAR(value_g, ${src_mask_i}, dst_mask_g);"
echo "${indent1} pixel |= _TME_FB_XLAT_MAP_LINEAR(value_r, ${src_mask_i}, dst_mask_r);"
echo "${indent1} pixel |= _TME_FB_XLAT_MAP_LINEAR(value_b, ${src_mask_i}, dst_mask_b);"
echo ""
echo "${indent1} /* if destination pixels are indexed: */"
echo "${indent1} if (dst_masks_default) {"
echo "${indent1} pixel = dst->tme_fb_connection_map_pixel[pixel];"
echo "${indent1} }"
echo "${indent1} }"
if test "X${indent1}" != "X${indent0}"; then
echo "${indent0} }"
fi
if test "X${indent0}" != X; then
echo "${indent0} }"
fi
fi
fi
echo ""
if test $scale = _h_; then
echo " /* if we just read the last pixels on these"
echo " source scanlines: */"
if test `expr ${iter_next} % ${src_unroll}` = 0; then
echo " if ((src_x +="
echo " (src_packed"
echo " ? `expr ${src_unroll} \* 2`"
echo " : 2))"
echo " == src_width) {"
else
echo " if (!src_packed"
echo " && (src_x += 2) == src_width) {"
fi
echo ""
echo " /* we need to rapidly shift the source FIFOs"
echo " to skip not only pad bits and undisplayed"
echo " pixels on the next line, but actually the"
echo " *entire* next line."
echo ""
echo " note that this sounds like when we're done,"
echo " the bits at the fronts of the FIFOs will be"
echo " the *first* pixels on the next scanlines."
echo ""
echo " but the bits at the fronts of the FIFOs now"
echo " are the *last* pixels on the current scanlines -"
echo " they haven't been shifted off yet. so when"
echo " we're done, we want one pixel's worth of bits"
echo " in the FIFOs before the first pixel on the"
echo " next scanlines: */"
echo ""
echo " /* calculate the number of bits that we need"
echo " to shift the source primary FIFO, after"
echo " discarding any bits in it now: */"
echo " src_off = ((src_bypl * 8) - (src_width * src_bipp)) + (src_bypl * 8);"
echo " src_off -= (src_fifo0_may_be_unaligned"
echo " ? src_fifo0_bits"
echo " : 32);"
echo ""
echo " /* rapidly advance src_raw0 by the number of"
echo " whole 32-bit words. this will leave it pointing"
echo " to the 32-bit word that has the first bit that"
echo " we want to end up as the first bit in the source"
echo " primary FIFO: */"
echo " src_raw0 += (src_off / 32);"
echo ""
echo " /* reprime the source primary FIFO: */"
echo " src_fifo0 = *src_raw0;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw0) = src_fifo0;"
echo " src_raw0++;"
echo " src_fifo0 = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(src_fifo0)"
echo " : tme_letoh_u32(src_fifo0));"
echo ""
echo " /* if the source primary FIFO may be unaligned: */"
echo " if (src_fifo0_may_be_unaligned) {"
echo ""
echo " /* reprime the top half of the FIFO, leaving a"
echo " total of 64 bits in it: */"
echo " src_fifo0_next = *src_raw0;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw0) = src_fifo0_next;"
echo " src_raw0++;"
echo " src_fifo0_next = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(src_fifo0_next)"
echo " : tme_letoh_u32(src_fifo0_next));"
echo " src_fifo0_bits = 64;"
echo ""
echo " /* if we have to shift off bits left over"
echo " from rapidly advancing whole 32-bit words: */"
echo " src_off %= 32;"
echo " if (src_off > 0) {"
echo " TME_FB_XLAT_SHIFT_SRC(TRUE,"
echo " src_fifo0,"
echo " src_fifo0_next,"
echo " src_fifo0_bits,"
echo " src_off,"
echo " src_raw0,"
echo " src_order);"
echo " }"
echo " }"
echo ""
echo " /* otherwise, the source primary FIFO is always aligned: */"
echo " else {"
echo " assert ((src_off % 32) == 0);"
echo " }"
echo ""
echo " /* calculate the number of bits that we need"
echo " to shift the source secondary FIFO, after"
echo " discarding any bits in it now: */"
echo " src_off = ((src_bypl * 8) - (src_width * src_bipp)) + (src_bypl * 8);"
echo " src_off -= (src_fifo1_may_be_unaligned"
echo " ? src_fifo1_bits"
echo " : 32);"
echo ""
echo " /* rapidly advance src_raw1 by the number of"
echo " whole 32-bit words. this will leave it pointing"
echo " to the 32-bit word that has the first bit that"
echo " we want to end up as the first bit in the source"
echo " secondary FIFO: */"
echo " src_raw1 += (src_off / 32);"
echo ""
echo " /* reprime the source secondary FIFO: */"
echo " src_fifo1 = *src_raw1;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw1) = src_fifo1;"
echo " src_raw1++;"
echo " src_fifo1 = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(src_fifo1)"
echo " : tme_letoh_u32(src_fifo1));"
echo ""
echo " /* if the source secondary FIFO may be unaligned: */"
echo " if (src_fifo1_may_be_unaligned) {"
echo ""
echo " /* reprime the top half of the FIFO, leaving a"
echo " total of 64 bits in it: */"
echo " src_fifo1_next = *src_raw1;"
echo " *TME_FB_XLAT_SRC_OLD(src_raw1) = src_fifo1_next;"
echo " src_raw1++;"
echo " src_fifo1_next = ((src_order == TME_ENDIAN_BIG)"
echo " ? tme_betoh_u32(src_fifo1_next)"
echo " : tme_letoh_u32(src_fifo1_next));"
echo " src_fifo1_bits = 64;"
echo ""
echo " /* if we have to shift off bits left over"
echo " from rapidly advancing whole 32-bit words: */"
echo " src_off %= 32;"
echo " if (src_off > 0) {"
echo " TME_FB_XLAT_SHIFT_SRC(TRUE,"
echo " src_fifo1,"
echo " src_fifo1_next,"
echo " src_fifo1_bits,"
echo " src_off,"
echo " src_raw1,"
echo " src_order);"
echo " }"
echo " }"
echo ""
echo " /* otherwise, the source secondary FIFO is always aligned: */"
echo " else {"
echo " assert ((src_off % 32) == 0);"
echo " }"
echo ""
echo " /* we are now on the first pixel of the next scanline: */"
echo " src_x = 0;"
echo " }"
else
echo " /* if the source buffer is not packed, and we just"
echo " read the last pixel on this source scanline: */"
echo " if (!src_packed"
echo " && ++src_x == src_width) {"
echo ""
echo " /* calculate the number of bits between the"
echo " last bit of the last pixel and the first bit"
echo " of the first displayed pixel on the next"
echo " scanline. this is equal to the number of"
echo " pad bits plus bits for undisplayed pixels: */"
echo " src_off = ((src_bypl * 8) - (src_width * src_bipp));"
echo ""
echo " /* while there are bits to shift: */"
echo " for (; src_off > 0; src_off -= TME_MIN(src_off, 32)) {"
echo ""
echo " /* shift the source primary FIFO: */"
echo " TME_FB_XLAT_SHIFT_SRC(src_fifo0_may_be_unaligned,"
echo " src_fifo0,"
echo " src_fifo0_next,"
echo " src_fifo0_bits,"
echo " TME_MIN(src_off, 32),"
echo " src_raw0,"
echo " src_order);"
echo " }"
echo ""
echo " /* we are now on the first pixel of the next scanline: */"
echo " src_x = 0;"
echo " }"
fi
if test `expr ${iter_next} % ${src_unroll}` = 0; then
echo ""
if test "${src_fifo_shift}" = 32; then
echo " /* we've just translated another 32-bit word of the"
echo " source image, so decrement xlat_run: */"
echo " xlat_run--;"
else
echo " /* if we've just finished translating another 32-bit"
echo " word of the source image, decrement xlat_run: */"
echo " if (src_fifo0_bits <= 32 + ${src_fifo_shift}) {"
echo " xlat_run--;"
echo " }"
fi
echo ""
echo " /* shift the source primary FIFO: */"
echo " TME_FB_XLAT_SHIFT_SRC(src_fifo0_may_be_unaligned,"
echo " src_fifo0,"
echo " src_fifo0_next,"
echo " src_fifo0_bits,"
echo " ${src_fifo_shift},"
echo " src_raw0,"
echo " src_order);"
if test $scale = _h_; then
echo ""
echo " /* shift the source secondary FIFO: */"
echo " TME_FB_XLAT_SHIFT_SRC(src_fifo1_may_be_unaligned,"
echo " src_fifo1,"
echo " src_fifo1_next,"
echo " src_fifo1_bits,"
echo " ${src_fifo_shift},"
echo " src_raw1,"
echo " src_order);"
fi
fi
# the number of bits to skip in a destination FIFO to get to
# this iteration's pixel:
dst_shift=`expr ${iter} % ${dst_unroll}`
dst_shift='('`expr ${dst_shift} \* ${dst_iter_scale}`' * dst_bipp)'
echo ""
echo " /* put the pixel into the destination primary FIFO: */"
echo " dst_fifo0 |="
echo " (pixel"
echo " << (dst_order == TME_ENDIAN_BIG"
echo " ? ((32 - dst_bipp) - ${dst_shift})"
echo " : ${dst_shift}));"
if test $scale = _d_; then
echo ""
echo " /* put the pixel into the destination secondary FIFO: */"
echo " dst_fifo1 |="
echo " (pixel"
echo " << (dst_order == TME_ENDIAN_BIG"
echo " ? ((32 - dst_bipp) - ${dst_shift})"
echo " : ${dst_shift}));"
echo ""
if test `expr ${dst_bipp} \>= 24` = 1; then
echo " /* put the pixel into both FIFOs again. in"
echo " this case, dst_bipp is known to be ${dst_bipp},"
echo " meaning the FIFOs cannot entirely take these"
echo " further pixels, so we need to shift the FIFOs: */"
indent0=""
indent1=X
elif test ${dst_bipp} = 0; then
echo " /* put the pixel into both FIFOs again. if"
echo " dst_bipp is 24 or greater, the FIFOs can"
echo " not entirely take these further pixels,"
echo " so we need to shift the FIFOs: */"
echo " if (dst_bipp >= 24) {"
indent0=" "
indent1=" "
else
echo " /* put the pixel into both FIFOs again. in"
echo " this case, dst_bipp is known to be ${dst_bipp},"
echo " meaning the FIFOs can take these further pixels"
echo " without shifting the FIFOs, as long as we shift"
echo " the pixels one pixel further: */"
indent0=X
indent1=""
fi
if test "X${indent0}" != "XX"; then
echo "${indent0} TME_FB_XLAT_SHIFT_DST(dst_fifo0_may_be_unaligned,"
echo "${indent0} dst_fifo0,"
echo "${indent0} dst_fifo0_next,"
echo "${indent0} dst_fifo0_bits,"
echo "${indent0} dst_bipp,"
echo "${indent0} dst_raw0,"
echo "${indent0} dst_order);"
echo "${indent0} TME_FB_XLAT_SHIFT_DST(dst_fifo1_may_be_unaligned,"
echo "${indent0} dst_fifo1,"
echo "${indent0} dst_fifo1_next,"
echo "${indent0} dst_fifo1_bits,"
echo "${indent0} dst_bipp,"
echo "${indent0} dst_raw1,"
echo "${indent0} dst_order);"
echo ""
echo "${indent0} /* now that we've shifted by dst_bipp, we can"
echo "${indent0} put the further pixels exactly where the"
echo "${indent0} first pixels went in the FIFOs: */"
echo "${indent0} dst_fifo0 |="
echo "${indent0} (pixel"
echo "${indent0} << (dst_order == TME_ENDIAN_BIG"
echo "${indent0} ? ((32 - dst_bipp) - ${dst_shift})"
echo "${indent0} : ${dst_shift}));"
echo "${indent0} dst_fifo1 |="
echo "${indent0} (pixel"
echo "${indent0} << (dst_order == TME_ENDIAN_BIG"
echo "${indent0} ? ((32 - dst_bipp) - ${dst_shift})"
echo "${indent0} : ${dst_shift}));"
fi
if test ${dst_bipp} = 0; then
echo " }"
echo ""
echo " /* otherwise, the FIFOs can take these further pixels,"
echo " as long as we shift the pixels one pixel further: */"
echo " else {"
fi
if test "X${indent1}" != "XX"; then
echo "${indent1} dst_fifo0 |="
echo "${indent1} (pixel"
echo "${indent1} << (dst_order == TME_ENDIAN_BIG"
echo "${indent1} ? ((32 - dst_bipp) - (${dst_shift} + dst_bipp))"
echo "${indent1} : (${dst_shift} + dst_bipp)));"
echo "${indent1} dst_fifo1 |="
echo "${indent1} (pixel"
echo "${indent1} << (dst_order == TME_ENDIAN_BIG"
echo "${indent1} ? ((32 - dst_bipp) - (${dst_shift} + dst_bipp))"
echo "${indent1} : (${dst_shift} + dst_bipp)));"
fi
if test ${dst_bipp} = 0; then
echo " }"
fi
fi
echo ""
echo " /* if the destination buffer is not packed, and we just"
echo " wrote the last pixel on this destination scanline: */"
if test $scale = _d_; then value=2; else value=1; fi
echo " if (!dst_packed"
echo " && (dst_x += ${value}) == dst_width) {"
echo ""
echo " /* calculate the number of bits between the"
echo " last bit of the last pixel and the first bit"
echo " of the first displayed pixel on the next"
echo " scanline. this is equal to the number of"
echo " pad bits plus bits for undisplayed pixels: */"
echo " dst_off = ((dst_bypl * 8) - (dst_width * dst_bipp));"
echo ""
echo " /* while there are bits to shift: */"
echo " for (; dst_off > 0; dst_off -= TME_MIN(dst_off, 32)) {"
echo ""
echo " /* shift the destination primary FIFO: */"
echo " TME_FB_XLAT_SHIFT_DST(dst_fifo0_may_be_unaligned,"
echo " dst_fifo0,"
echo " dst_fifo0_next,"
echo " dst_fifo0_bits,"
echo " TME_MIN(dst_off, 32),"
echo " dst_raw0,"
echo " dst_order);"
if test $scale = _d_; then
echo ""
echo " /* shift the destination secondary FIFO: */"
echo " TME_FB_XLAT_SHIFT_DST(dst_fifo1_may_be_unaligned,"
echo " dst_fifo1,"
echo " dst_fifo1_next,"
echo " dst_fifo1_bits,"
echo " TME_MIN(dst_off, 32),"
echo " dst_raw1,"
echo " dst_order);"
fi
echo " }"
echo ""
echo " /* we are now on the first pixel of the next scanline: */"
echo " dst_x = 0;"
echo " }"
if test `expr ${iter_next} % ${dst_unroll}` = 0; then
echo ""
echo " /* shift the destination primary FIFO: */"
echo " TME_FB_XLAT_SHIFT_DST(dst_fifo0_may_be_unaligned,"
echo " dst_fifo0,"
echo " dst_fifo0_next,"
echo " dst_fifo0_bits,"
echo " ${dst_fifo_shift},"
echo " dst_raw0,"
echo " dst_order);"
if test $scale = _d_; then
echo ""
echo " /* shift the destination secondary FIFO: */"
echo " TME_FB_XLAT_SHIFT_DST(dst_fifo1_may_be_unaligned,"
echo " dst_fifo1,"
echo " dst_fifo1_next,"
echo " dst_fifo1_bits,"
echo " ${dst_fifo_shift},"
echo " dst_raw1,"
echo " dst_order);"
fi
fi
iter=${iter_next}
done
echo ""
echo " }"
if test `expr ${iter} % ${dst_unroll}` != 0; then
echo "$PROG internal error - the last iter did not shift the destination FIFOs ($iter and $dst_unroll)" 1>&2
exit 1
fi
echo ""
echo " /* if the destination FIFOs may be unaligned, there"
echo " may be bits left in the FIFO that we need to flush: */"
echo " if (dst_fifo0_may_be_unaligned"
echo " && dst_fifo0_bits > 0) {"
echo " dst_fifo0 = *dst_raw0;"
echo " if (dst_order == TME_ENDIAN_BIG) {"
echo " dst_fifo0_next |= (tme_betoh_u32(dst_fifo0) & (0xffffffff >> dst_fifo0_bits));"
echo " dst_fifo0_next = tme_htobe_u32(dst_fifo0_next);"
echo " }"
echo " else {"
echo " dst_fifo0_next |= (tme_letoh_u32(dst_fifo0) & (0xffffffff << dst_fifo0_bits));"
echo " dst_fifo0_next = tme_htole_u32(dst_fifo0_next);"
echo " }"
echo " *dst_raw0 = dst_fifo0;"
echo " }"
if test $scale = _d_; then
echo " if (dst_fifo1_may_be_unaligned"
echo " && dst_fifo1_bits > 0) {"
echo " dst_fifo1 = *dst_raw1;"
echo " if (dst_order == TME_ENDIAN_BIG) {"
echo " dst_fifo1_next |= (tme_betoh_u32(dst_fifo1) & (0xffffffff >> dst_fifo1_bits));"
echo " dst_fifo1_next = tme_htobe_u32(dst_fifo1_next);"
echo " }"
echo " else {"
echo " dst_fifo1_next |= (tme_letoh_u32(dst_fifo1) & (0xffffffff << dst_fifo1_bits));"
echo " dst_fifo1_next = tme_htole_u32(dst_fifo1_next);"
echo " }"
echo " *dst_raw1 = dst_fifo1;"
echo " }"
fi
echo ""
echo " /* loop back to compare more 32-bit words: */"
echo " src_raw0--;"
echo " }"
echo ""
echo " /* return nonzero iff we did some translating: */"
echo " return (xlat_run >= 0);"
echo ""
for macro in ${undef_macros}; do
echo "#undef ${macro}"
done
echo "}"
done
done
echo ""
echo "/* the xlat function array: */"
echo "static const struct tme_fb_xlat tme_fb_xlats[] = {$xlat_array
};"
# done:
exit 0