Andreas Sandberg has uploaded this change for review. (
https://gem5-review.googlesource.com/10803
Change subject: base: Templatize PixelConverter class
......................................................................
base: Templatize PixelConverter class
PixelConverter is currently supporting 8-bit color channels. This
change makes it a template to support wider color channels like
10-bit, 12-bit upto max resolution of 16-bit. Since there are no color
channels greater than 16-bit, a static assertion triggers a
compilation failure if for wider channels.
Change-Id: I6e3e131f17e58fd2bc170c075d2340812e324b90
Reviewed-by: Andreas Sandberg <[email protected]>
Signed-off-by: Andreas Sandberg <[email protected]>
---
M src/base/framebuffer.cc
M src/base/framebuffer.hh
M src/base/pixel.cc
M src/base/pixel.hh
M src/base/pixeltest.cc
M src/base/vnc/vncserver.cc
M src/base/vnc/vncserver.hh
M src/dev/arm/hdlcd.cc
M src/dev/arm/hdlcd.hh
M src/dev/arm/pl111.cc
M src/dev/arm/pl111.hh
11 files changed, 105 insertions(+), 86 deletions(-)
diff --git a/src/base/framebuffer.cc b/src/base/framebuffer.cc
index d4eb22c..e76b8db 100644
--- a/src/base/framebuffer.cc
+++ b/src/base/framebuffer.cc
@@ -102,24 +102,6 @@
fill(black);
}
-void
-FrameBuffer::copyIn(const uint8_t *fb, const PixelConverter &conv)
-{
- for (auto &p : pixels) {
- p = conv.toPixel(fb);
- fb += conv.length;
- }
-}
-
-void
-FrameBuffer::copyOut(uint8_t *fb, const PixelConverter &conv) const
-{
- for (auto &p : pixels) {
- conv.fromPixel(fb, p);
- fb += conv.length;
- }
-}
-
uint64_t
FrameBuffer::getHash() const
{
diff --git a/src/base/framebuffer.hh b/src/base/framebuffer.hh
index 3a0255a..c0ebd47 100644
--- a/src/base/framebuffer.hh
+++ b/src/base/framebuffer.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2015, 2017-2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -119,7 +119,13 @@
* @param fb External frame buffer
* @param conv Pixel conversion helper
*/
- void copyIn(const uint8_t *fb, const PixelConverter &conv);
+ template<typename PixelConvType>
+ void copyIn(const uint8_t *fb, const PixelConvType &conv) {
+ for (auto &p : pixels) {
+ p = conv.toPixel(fb);
+ fb += conv.length;
+ }
+ }
/**
* Fill the frame buffer with pixel data from an external buffer
* of the same width and height as this frame buffer.
@@ -127,7 +133,8 @@
* @param fb External frame buffer
* @param conv Pixel conversion helper
*/
- void copyIn(const std::vector<uint8_t> &fb, const PixelConverter
&conv) {
+ template<typename PixelConvType>
+ void copyIn(const std::vector<uint8_t> &fb, const PixelConvType &conv)
{
copyIn(fb.data(), conv);
}
@@ -138,7 +145,13 @@
* @param fb External frame buffer
* @param conv Pixel conversion helper
*/
- void copyOut(uint8_t *fb, const PixelConverter &conv) const;
+ template<typename PixelConvType>
+ void copyOut(uint8_t *fb, const PixelConvType &conv) const{
+ for (auto &p : pixels) {
+ conv.fromPixel(fb, p);
+ fb += conv.length;
+ }
+ }
/**
* Store the contents of this frame buffer in an external buffer
* of the same width and height as this frame buffer.
@@ -146,7 +159,8 @@
* @param fb External frame buffer
* @param conv Pixel conversion helper
*/
- void copyOut(std::vector<uint8_t> &fb, const PixelConverter &conv)
const {
+ template<typename PixelConvType>
+ void copyOut(std::vector<uint8_t> &fb, const PixelConvType &conv)
const {
copyOut(fb.data(), conv);
}
diff --git a/src/base/pixel.cc b/src/base/pixel.cc
index 29dcaf6..31dfa2c 100644
--- a/src/base/pixel.cc
+++ b/src/base/pixel.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2015, 2017-2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -43,14 +43,18 @@
#include "base/bitfield.hh"
-const PixelConverter PixelConverter::rgba8888_le(4, 0, 8, 16, 8, 8, 8);
-const PixelConverter PixelConverter::rgba8888_be(4, 0, 8, 16, 8, 8, 8,
+template<typename Type>
+const PixelConverter8b PixelConverter<Type>::rgba8888_le(4, 0, 8, 16, 8,
8, 8);
+template<typename Type>
+const PixelConverter8b PixelConverter<Type>::rgba8888_be(4, 0, 8, 16, 8,
8, 8,
BigEndianByteOrder);
-const PixelConverter PixelConverter::rgb565_le(2, 0, 5, 11, 5, 6, 5);
-const PixelConverter PixelConverter::rgb565_be(2, 0, 5, 11, 5, 6, 5,
+template<typename Type>
+const PixelConverter8b PixelConverter<Type>::rgb565_le(2, 0, 5, 11, 5, 6,
5);
+template<typename Type>
+const PixelConverter8b PixelConverter<Type>::rgb565_be(2, 0, 5, 11, 5, 6,
5,
BigEndianByteOrder);
-
-PixelConverter::PixelConverter(unsigned _length,
+template<typename Type>
+PixelConverter<Type>::PixelConverter(unsigned _length,
unsigned ro, unsigned go, unsigned bo,
unsigned rw, unsigned gw, unsigned bw,
ByteOrder _byte_order)
@@ -64,15 +68,17 @@
assert(length > 1);
}
-PixelConverter::Channel::Channel(unsigned _offset, unsigned width)
+template<typename Type>
+PixelConverter<Type>::Channel::Channel(unsigned _offset, unsigned width)
: offset(_offset),
mask(::mask(width)),
factor(255.0 / mask)
{
}
+template<typename Type>
uint32_t
-PixelConverter::readWord(const uint8_t *p) const
+PixelConverter<Type>::readWord(const uint8_t *p) const
{
uint32_t word(0);
@@ -87,8 +93,9 @@
return word;
}
+template<typename Type>
void
-PixelConverter::writeWord(uint8_t *p, uint32_t word) const
+PixelConverter<Type>::writeWord(uint8_t *p, uint32_t word) const
{
if (byte_order == LittleEndianByteOrder) {
for (int i = 0; i < length; ++i)
@@ -98,3 +105,6 @@
p[i] = (word >> (8 * (length - i - 1))) & 0xFF;
}
}
+
+template class PixelConverter<uint8_t>;
+template class PixelConverter<uint16_t>;
diff --git a/src/base/pixel.hh b/src/base/pixel.hh
index 75f1971..3d75a2b 100644
--- a/src/base/pixel.hh
+++ b/src/base/pixel.hh
@@ -178,8 +178,16 @@
* the word (i.e., it is possible to shift and mask out a contiguous
* bit range for each pixel).
*/
+
+template<typename Type>
class PixelConverter
{
+ static_assert(std::is_same<Type,uint8_t>::value |
+ std::is_same<Type,uint16_t>::value, "Pixel precision more than
16\
+ bit is not supported");
+ typedef typename
+ std::conditional<std::is_same<Type,uint8_t>::value,
+ PixelU8,PixelU16>::type PixelType;
public:
/**
* Color channel conversion and scaling helper class.
@@ -195,7 +203,7 @@
* Get the value of a single color channel represented as an
* 8-bit number.
*/
- uint8_t toPixel(uint32_t word) const {
+ Type toPixel(uint32_t word) const {
return round(((word >> offset) & mask) * factor);
}
@@ -203,8 +211,9 @@
* Convert an 8-bit representation of a color into an external
* format.
*/
- uint32_t fromPixel(uint8_t ch) const {
- return (static_cast<uint8_t>(round(ch / factor)) & mask) <<
offset;
+ uint32_t fromPixel(Type ch) const {
+ return (static_cast<Type>(round(ch / factor)) & mask)
+ << offset;
}
/** Offset in bits */
@@ -224,19 +233,19 @@
ByteOrder byte_order = LittleEndianByteOrder);
/** Get the Pixel representation of a color word. */
- PixelU8 toPixel(uint32_t word) const {
- return PixelU8(ch_r.toPixel(word),
+ PixelType toPixel(uint32_t word) const {
+ return PixelType(ch_r.toPixel(word),
ch_g.toPixel(word),
ch_b.toPixel(word));
}
/** Get a Pixel representation by reading a word from memory. */
- PixelU8 toPixel(const uint8_t *rfb) const {
+ PixelType toPixel(const uint8_t *rfb) const {
return toPixel(readWord(rfb));
}
/** Convert a Pixel into a color word */
- uint32_t fromPixel(const PixelU8 &pixel) const {
+ uint32_t fromPixel(const PixelType &pixel) const {
return ch_r.fromPixel(pixel.red) |
ch_g.fromPixel(pixel.green) |
ch_b.fromPixel(pixel.blue);
@@ -246,7 +255,7 @@
* Convert a pixel into a color word and store the resulting word
* in memory.
*/
- void fromPixel(uint8_t *rfb, const PixelU8 &pixel) const {
+ void fromPixel(uint8_t *rfb, const PixelType &pixel) const {
writeWord(rfb, fromPixel(pixel));
}
@@ -289,19 +298,22 @@
/** Predefined 32-bit RGB (red in least significant bits, 8
* bits/channel, little endian) conversion helper */
- static const PixelConverter rgba8888_le;
+ static const PixelConverter<uint8_t> rgba8888_le;
/** Predefined 16-bit RGB565 (red in least significant bits,
* little endian) conversion helper */
- static const PixelConverter rgb565_le;
+ static const PixelConverter<uint8_t> rgb565_le;
/** Predefined 32-bit RGB (red in least significant bits, 8
* bits/channel, big endian) conversion helper */
- static const PixelConverter rgba8888_be;
+ static const PixelConverter<uint8_t> rgba8888_be;
/** Predefined 16-bit RGB565 (red in least significant bits,
* big endian) conversion helper */
- static const PixelConverter rgb565_be;
+ static const PixelConverter<uint8_t> rgb565_be;
};
+typedef PixelConverter<uint8_t> PixelConverter8b;
+typedef PixelConverter<uint16_t> PixelConverter16b;
+
inline bool
to_number(const std::string &value, PixelU8 &retval)
{
@@ -309,14 +321,14 @@
if (!to_number(value, num))
return false;
- retval = PixelConverter::rgba8888_le.toPixel(num);
+ retval = PixelConverter8b::rgba8888_le.toPixel(num);
return true;
}
inline std::ostream &
operator<<(std::ostream &os, const PixelU8 &pxl)
{
- os << csprintf("0x%.08x", PixelConverter::rgba8888_le.fromPixel(pxl));
+ os << csprintf("0x%.08x",
PixelConverter8b::rgba8888_le.fromPixel(pxl));
return os;
}
diff --git a/src/base/pixeltest.cc b/src/base/pixeltest.cc
index 0672e31..46ce161 100644
--- a/src/base/pixeltest.cc
+++ b/src/base/pixeltest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2015, 2017-2018 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -47,55 +47,55 @@
TEST(FBTest, PixelConversionRGBA8888)
{
- EXPECT_EQ(PixelConverter::rgba8888_le.fromPixel(pixel_red),
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.fromPixel(pixel_red),
0x000000ffU);
- EXPECT_EQ(PixelConverter::rgba8888_le.fromPixel(pixel_green),
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.fromPixel(pixel_green),
0x0000ff00U);
- EXPECT_EQ(PixelConverter::rgba8888_le.fromPixel(pixel_blue),
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.fromPixel(pixel_blue),
0x00ff0000U);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(0x000000ffU),
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(0x000000ffU),
pixel_red);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(0x0000ff00U),
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(0x0000ff00U),
pixel_green);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(0x00ff0000U),
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(0x00ff0000U),
pixel_blue);
}
TEST(FBTest, PixelConversionRGB565)
{
- EXPECT_EQ(PixelConverter::rgb565_le.fromPixel(pixel_red), 0x001fU);
- EXPECT_EQ(PixelConverter::rgb565_le.fromPixel(pixel_green), 0x07e0U);
- EXPECT_EQ(PixelConverter::rgb565_le.fromPixel(pixel_blue), 0xf800U);
+ EXPECT_EQ(PixelConverter8b::rgb565_le.fromPixel(pixel_red), 0x001fU);
+ EXPECT_EQ(PixelConverter8b::rgb565_le.fromPixel(pixel_green), 0x07e0U);
+ EXPECT_EQ(PixelConverter8b::rgb565_le.fromPixel(pixel_blue), 0xf800U);
- EXPECT_EQ(PixelConverter::rgb565_le.toPixel(0x001fU), pixel_red);
- EXPECT_EQ(PixelConverter::rgb565_le.toPixel(0x07e0U), pixel_green);
- EXPECT_EQ(PixelConverter::rgb565_le.toPixel(0xf800U), pixel_blue);
+ EXPECT_EQ(PixelConverter8b::rgb565_le.toPixel(0x001fU), pixel_red);
+ EXPECT_EQ(PixelConverter8b::rgb565_le.toPixel(0x07e0U), pixel_green);
+ EXPECT_EQ(PixelConverter8b::rgb565_le.toPixel(0xf800U), pixel_blue);
}
TEST(FBTest, PixelToMemRGBA8888LE)
{
uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef };
- PixelConverter::rgba8888_le.fromPixel(data, pixel_red);
+ PixelConverter8b::rgba8888_le.fromPixel(data, pixel_red);
EXPECT_EQ(data[0], 0xff);
EXPECT_EQ(data[1], 0x00);
EXPECT_EQ(data[3], 0x00);
EXPECT_EQ(data[3], 0x00);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(data), pixel_red);
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(data), pixel_red);
- PixelConverter::rgba8888_le.fromPixel(data, pixel_green);
+ PixelConverter8b::rgba8888_le.fromPixel(data, pixel_green);
EXPECT_EQ(data[0], 0x00);
EXPECT_EQ(data[1], 0xff);
EXPECT_EQ(data[3], 0x00);
EXPECT_EQ(data[3], 0x00);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(data), pixel_green);
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(data), pixel_green);
- PixelConverter::rgba8888_le.fromPixel(data, pixel_blue);
+ PixelConverter8b::rgba8888_le.fromPixel(data, pixel_blue);
EXPECT_EQ(data[0], 0x00);
EXPECT_EQ(data[1], 0x00);
EXPECT_EQ(data[2], 0xff);
EXPECT_EQ(data[3], 0x00);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(data), pixel_blue);
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(data), pixel_blue);
}
TEST(FBTest, MemToPixelRGBA8888LE)
@@ -104,9 +104,9 @@
uint8_t green[] = { 0x00, 0xff, 0x00, 0x00 };
uint8_t blue[] = { 0x00, 0x00, 0xff, 0x00 };
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(red), pixel_red);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(green), pixel_green);
- EXPECT_EQ(PixelConverter::rgba8888_le.toPixel(blue), pixel_blue);
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(red), pixel_red);
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(green), pixel_green);
+ EXPECT_EQ(PixelConverter8b::rgba8888_le.toPixel(blue), pixel_blue);
}
TEST(FBTest, MemToPixelRGBA8888BE)
@@ -115,7 +115,7 @@
uint8_t green[] = { 0x00, 0x00, 0xff, 0x00 };
uint8_t blue[] = { 0x00, 0xff, 0x00, 0x00 };
- EXPECT_EQ(PixelConverter::rgba8888_be.toPixel(red), pixel_red);
- EXPECT_EQ(PixelConverter::rgba8888_be.toPixel(green), pixel_green);
- EXPECT_EQ(PixelConverter::rgba8888_be.toPixel(blue), pixel_blue);
+ EXPECT_EQ(PixelConverter8b::rgba8888_be.toPixel(red), pixel_red);
+ EXPECT_EQ(PixelConverter8b::rgba8888_be.toPixel(green), pixel_green);
+ EXPECT_EQ(PixelConverter8b::rgba8888_be.toPixel(blue), pixel_blue);
}
diff --git a/src/base/vnc/vncserver.cc b/src/base/vnc/vncserver.cc
index a37f1dd..ea202cc 100644
--- a/src/base/vnc/vncserver.cc
+++ b/src/base/vnc/vncserver.cc
@@ -74,7 +74,7 @@
using namespace std;
-const PixelConverter VncServer::pixelConverter(
+const PixelConverter8b VncServer::pixelConverter(
4, // 4 bytes / pixel
16, 8, 0, // R in [23, 16], G in [15, 8], B in [7, 0]
8, 8, 8, // 8 bits / channel
diff --git a/src/base/vnc/vncserver.hh b/src/base/vnc/vncserver.hh
index f64ccd7..8f36e37 100644
--- a/src/base/vnc/vncserver.hh
+++ b/src/base/vnc/vncserver.hh
@@ -303,7 +303,7 @@
*/
void sendFrameBufferResized();
- static const PixelConverter pixelConverter;
+ static const PixelConverter8b pixelConverter;
public:
void setDirty() override;
diff --git a/src/dev/arm/hdlcd.cc b/src/dev/arm/hdlcd.cc
index 499a263..d75e6b8 100644
--- a/src/dev/arm/hdlcd.cc
+++ b/src/dev/arm/hdlcd.cc
@@ -86,7 +86,8 @@
virtRefreshEvent([this]{ virtRefresh(); }, name()),
// Other
- imgFormat(p->frame_format), pic(NULL),
conv(PixelConverter::rgba8888_le),
+ imgFormat(p->frame_format), pic(NULL),
+ conv(PixelConverter8b::rgba8888_le),
pixelPump(*this, *p->pxl_clk, p->pixel_chunk)
{
if (vnc)
@@ -433,7 +434,7 @@
}
}
-PixelConverter
+PixelConverter8b
HDLcd::pixelConverter() const
{
ByteOrder byte_order(
@@ -442,13 +443,13 @@
/* Some Linux kernels have a broken driver that swaps the red and
* blue color select registers. */
if (!workaroundSwapRB) {
- return PixelConverter(
+ return PixelConverter8b(
pixel_format.bytes_per_pixel + 1,
red_select.offset, green_select.offset, blue_select.offset,
red_select.size, green_select.size, blue_select.size,
byte_order);
} else {
- return PixelConverter(
+ return PixelConverter8b(
pixel_format.bytes_per_pixel + 1,
blue_select.offset, green_select.offset, red_select.offset,
blue_select.size, green_select.size, red_select.size,
diff --git a/src/dev/arm/hdlcd.hh b/src/dev/arm/hdlcd.hh
index 4bd963a..d647de8 100644
--- a/src/dev/arm/hdlcd.hh
+++ b/src/dev/arm/hdlcd.hh
@@ -258,7 +258,7 @@
uint32_t readReg(Addr offset);
void writeReg(Addr offset, uint32_t value);
- PixelConverter pixelConverter() const;
+ PixelConverter8b pixelConverter() const;
DisplayTimings displayTimings() const;
void createDmaEngine();
@@ -359,7 +359,7 @@
OutputStream *pic;
/** Cached pixel converter, set when the converter is enabled. */
- PixelConverter conv;
+ PixelConverter8b conv;
PixelPump pixelPump;
diff --git a/src/dev/arm/pl111.cc b/src/dev/arm/pl111.cc
index 344eb08..729a25f 100644
--- a/src/dev/arm/pl111.cc
+++ b/src/dev/arm/pl111.cc
@@ -64,7 +64,7 @@
clcdCrsrPalette1(0), clcdCrsrXY(0), clcdCrsrClip(0), clcdCrsrImsc(0),
clcdCrsrIcr(0), clcdCrsrRis(0), clcdCrsrMis(0),
pixelClock(p->pixel_clock),
- converter(PixelConverter::rgba8888_le), fb(LcdMaxWidth,
LcdMaxHeight),
+ converter(PixelConverter8b::rgba8888_le), fb(LcdMaxWidth,
LcdMaxHeight),
vnc(p->vnc), bmp(&fb), pic(NULL),
width(LcdMaxWidth), height(LcdMaxHeight),
bytesPerPixel(4), startTime(0), startAddr(0), maxAddr(0), curAddr(0),
@@ -383,7 +383,7 @@
return pioDelay;
}
-PixelConverter
+PixelConverter8b
Pl111::pixelConverter() const
{
unsigned rw, gw, bw;
@@ -411,13 +411,13 @@
}
if (lcdControl.bgr) {
- return PixelConverter(
+ return PixelConverter8b(
bytesPerPixel,
offsets[2], offsets[1], offsets[0],
rw, gw, bw,
LittleEndianByteOrder);
} else {
- return PixelConverter(
+ return PixelConverter8b(
bytesPerPixel,
offsets[0], offsets[1], offsets[2],
rw, gw, bw,
diff --git a/src/dev/arm/pl111.hh b/src/dev/arm/pl111.hh
index 3040ea7..8abb9dc 100644
--- a/src/dev/arm/pl111.hh
+++ b/src/dev/arm/pl111.hh
@@ -259,7 +259,7 @@
/** Pixel clock */
Tick pixelClock;
- PixelConverter converter;
+ PixelConverter8b converter;
FrameBuffer fb;
/** VNC server */
@@ -301,7 +301,7 @@
/** Number of pending dma reads */
uint32_t dmaPendingNum;
- PixelConverter pixelConverter() const;
+ PixelConverter8b pixelConverter() const;
/** Send updated parameters to the vnc server */
void updateVideoParams();
--
To view, visit https://gem5-review.googlesource.com/10803
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I6e3e131f17e58fd2bc170c075d2340812e324b90
Gerrit-Change-Number: 10803
Gerrit-PatchSet: 1
Gerrit-Owner: Andreas Sandberg <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev