diff options
author | Pierre Ossman <ossman@cendio.se> | 2014-01-30 10:47:07 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2014-07-09 14:55:30 +0200 |
commit | c02c05d403f000d15f736458b8c26ad60b4811f0 (patch) | |
tree | 5716d8ffa9f75209cc1a5051b5d235e0407a5f7b /common/rfb/PixelFormatBPP.cxx | |
parent | 761fe24089bfe95028b0da02a12650351b244165 (diff) | |
download | tigervnc-c02c05d403f000d15f736458b8c26ad60b4811f0.tar.gz tigervnc-c02c05d403f000d15f736458b8c26ad60b4811f0.zip |
Add optimised buffer conversion
Handles the common cases when the target or source are in
the preferred 888 format.
If one of the buffers is not 888, then it must also be properly
aligned (which is commonly the case). Performance is now in many
cases on par with PixelTransformer.
Diffstat (limited to 'common/rfb/PixelFormatBPP.cxx')
-rw-r--r-- | common/rfb/PixelFormatBPP.cxx | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/common/rfb/PixelFormatBPP.cxx b/common/rfb/PixelFormatBPP.cxx new file mode 100644 index 00000000..6b5ad6bb --- /dev/null +++ b/common/rfb/PixelFormatBPP.cxx @@ -0,0 +1,155 @@ +/* Copyright 2014 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) + +#define UIN CONCAT2E(U,INBPP) +#define UOUT CONCAT2E(U,OUTBPP) + +#define SWAP16(n) ((((n) & 0xff) << 8) | (((n) >> 8) & 0xff)) +#define SWAP32(n) (((n) >> 24) | (((n) & 0x00ff0000) >> 8) | \ + (((n) & 0x0000ff00) << 8) | ((n) << 24)) + +#define SWAPIN CONCAT2E(SWAP,INBPP) +#define SWAPOUT CONCAT2E(SWAP,OUTBPP) + +#if INBPP == 32 + +void PixelFormat::directBufferFromBufferFrom888(rdr::UOUT* dst, + const PixelFormat &srcPF, + const rdr::U8* src, + int w, int h, + int dstStride, + int srcStride) const +{ + const rdr::U8 *r, *g, *b; + int dstPad, srcPad; + + int redTruncShift, greenTruncShift, blueTruncShift; + + redTruncShift = 8 - redBits; + greenTruncShift = 8 - greenBits; + blueTruncShift = 8 - blueBits; + + if (srcPF.bigEndian) { + r = src + (24 - srcPF.redShift)/8; + g = src + (24 - srcPF.greenShift)/8; + b = src + (24 - srcPF.blueShift)/8; + } else { + r = src + srcPF.redShift/8; + g = src + srcPF.greenShift/8; + b = src + srcPF.blueShift/8; + } + + dstPad = (dstStride - w); + srcPad = (srcStride - w) * 4; + while (h--) { + int w_ = w; + while (w_--) { + rdr::UOUT d; + + d = (*r >> redTruncShift) << redShift; + d |= (*g >> greenTruncShift) << greenShift; + d |= (*b >> blueTruncShift) << blueShift; + +#if OUTBPP != 8 + if (endianMismatch) + d = SWAPOUT(d); +#endif + + *dst = d; + + dst++; + r += 4; + g += 4; + b += 4; + } + dst += dstPad; + r += srcPad; + g += srcPad; + b += srcPad; + } +} + +#endif /* INBPP == 32 */ + +#if OUTBPP == 32 + +void PixelFormat::directBufferFromBufferTo888(rdr::U8* dst, + const PixelFormat &srcPF, + const rdr::UIN* src, + int w, int h, + int dstStride, + int srcStride) const +{ + rdr::U8 *r, *g, *b, *x; + int dstPad, srcPad; + + const rdr::U8 *redUpTable, *greenUpTable, *blueUpTable; + + redUpTable = &upconvTable[(srcPF.redBits-1)*256]; + greenUpTable = &upconvTable[(srcPF.greenBits-1)*256]; + blueUpTable = &upconvTable[(srcPF.blueBits-1)*256]; + + if (bigEndian) { + r = dst + (24 - redShift)/8; + g = dst + (24 - greenShift)/8; + b = dst + (24 - blueShift)/8; + x = dst + (24 - (48 - redShift - greenShift - blueShift))/8; + } else { + r = dst + redShift/8; + g = dst + greenShift/8; + b = dst + blueShift/8; + x = dst + (48 - redShift - greenShift - blueShift)/8; + } + + dstPad = (dstStride - w) * 4; + srcPad = (srcStride - w); + while (h--) { + int w_ = w; + while (w_--) { + rdr::UIN s; + + s = *src; + +#if INBPP != 8 + if (srcPF.endianMismatch) + s = SWAPIN(s); +#endif + + *r = redUpTable[(s >> srcPF.redShift) & 0xff]; + *g = greenUpTable[(s >> srcPF.greenShift) & 0xff]; + *b = blueUpTable[(s >> srcPF.blueShift) & 0xff]; + *x = 0; + + r += 4; + g += 4; + b += 4; + x += 4; + src++; + } + r += dstPad; + g += dstPad; + b += dstPad; + x += dstPad; + src += srcPad; + } +} + +#endif /* OUTBPP == 32 */ |