Andreas Sandberg has uploaded this change for review. (
https://gem5-review.googlesource.com/10802
Change subject: base: Convert Pixel to a template to support wider channels
......................................................................
base: Convert Pixel to a template to support wider channels
This change converts the Pixel class to a template with the channel
data type as template parameter. This is needed to implement
high-definition color formats or when performing alpha blending.
Change-Id: Ice598aa7bb4ebf3dd96446cac57055dcd24a21e0
Signed-off-by: Rohit Kurup <[email protected]>
Reviewed-by: Andreas Sandberg <[email protected]>
Signed-off-by: Andreas Sandberg <[email protected]>
---
M src/base/bmpwriter.hh
M src/base/framebuffer.cc
M src/base/framebuffer.hh
M src/base/pixel.hh
M src/base/pixeltest.cc
M src/base/pngwriter.hh
M src/dev/arm/hdlcd.cc
M src/dev/arm/hdlcd.hh
M src/dev/pixelpump.cc
M src/dev/pixelpump.hh
M src/sim/serialize.cc
11 files changed, 135 insertions(+), 43 deletions(-)
diff --git a/src/base/bmpwriter.hh b/src/base/bmpwriter.hh
index f78b994..1e02873 100644
--- a/src/base/bmpwriter.hh
+++ b/src/base/bmpwriter.hh
@@ -108,7 +108,7 @@
} M5_ATTR_PACKED;
struct BmpPixel32 {
- BmpPixel32 &operator=(const Pixel &rhs) {
+ BmpPixel32 &operator=(const PixelU8 &rhs) {
red = rhs.red;
green = rhs.green;
blue = rhs.blue;
diff --git a/src/base/framebuffer.cc b/src/base/framebuffer.cc
index 746327a..d4eb22c 100644
--- a/src/base/framebuffer.cc
+++ b/src/base/framebuffer.cc
@@ -88,7 +88,7 @@
}
void
-FrameBuffer::fill(const Pixel &pixel)
+FrameBuffer::fill(const PixelU8 &pixel)
{
for (auto &p : pixels)
p = pixel;
@@ -97,7 +97,7 @@
void
FrameBuffer::clear()
{
- static const Pixel black(0, 0, 0);
+ static const PixelU8 black(0, 0, 0);
fill(black);
}
@@ -125,5 +125,5 @@
{
return adler32(0UL,
reinterpret_cast<const Bytef *>(pixels.data()),
- area() * sizeof(Pixel));
+ area() * sizeof(PixelU8));
}
diff --git a/src/base/framebuffer.hh b/src/base/framebuffer.hh
index ae2e15c..3a0255a 100644
--- a/src/base/framebuffer.hh
+++ b/src/base/framebuffer.hh
@@ -106,7 +106,7 @@
*
* @param pixel Pixel value to fill with.
*/
- void fill(const Pixel &pixel);
+ void fill(const PixelU8 &pixel);
/**
* Fill the frame buffer with black pixels
*/
@@ -156,7 +156,7 @@
* @param x Distance from the left margin.
* @param y Distance from the top of the frame.
*/
- const Pixel &pixel(unsigned x, unsigned y) const {
+ const PixelU8 &pixel(unsigned x, unsigned y) const {
assert(x < _width);
assert(y < _height);
@@ -169,7 +169,7 @@
* @param x Distance from the left margin.
* @param y Distance from the top of the frame.
*/
- Pixel &pixel(unsigned x, unsigned y) {
+ PixelU8 &pixel(unsigned x, unsigned y) {
assert(x < _width);
assert(y < _height);
@@ -191,7 +191,7 @@
static const FrameBuffer dummy;
/** Frame buffer backing store */
- std::vector<Pixel> pixels;
+ std::vector<PixelU8> pixels;
protected:
/** Width in pixels */
diff --git a/src/base/pixel.hh b/src/base/pixel.hh
index f6faace..75f1971 100644
--- a/src/base/pixel.hh
+++ b/src/base/pixel.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
@@ -35,6 +35,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Sandberg
+ * Rohit Kurup
*/
#ifndef __BASE_PIXEL_HH__
@@ -53,30 +54,121 @@
/**
* Internal gem5 representation of a Pixel.
*/
+template<typename DataType>
struct Pixel
{
- Pixel()
- : red(0), green(0), blue(0), padding(0) {}
+ static constexpr auto channelMax =
+ std::numeric_limits<DataType>::max();
+ DataType red;
+ DataType green;
+ DataType blue;
+ DataType alpha;
- Pixel(uint8_t _red, uint8_t _green, uint8_t _blue)
- : red(_red), green(_green), blue(_blue), padding(0) {}
+ Pixel(): red(0), green(0), blue(0), alpha(channelMax) {
+ }
- uint8_t red;
- uint8_t green;
- uint8_t blue;
- uint8_t padding;
+ Pixel(DataType _red, DataType _green, DataType _blue)
+ : red(_red), green(_green), blue(_blue), alpha(channelMax) {
+ static_assert(std::is_integral<DataType>::value,
+ "Pixel cannot have non-integer type");
+ }
+
+ template<typename FromType>
+ void convert(const Pixel<FromType> &b)
+ {
+ size_t shift = 0;
+ if (sizeof(FromType) > sizeof(DataType))
+ {
+ shift = sizeof(FromType) - sizeof(DataType);
+ red = b.red>>shift;
+ green = b.green>>shift;
+ blue = b.blue>>shift;
+ alpha = b.alpha>>shift;
+ }
+ else
+ {
+ shift = sizeof(DataType) - sizeof(FromType);
+ red = b.red<<shift;
+ green = b.green<<shift;
+ blue = b.blue<<shift;
+ alpha = b.alpha<<shift;
+ }
+ }
};
+
+
+/**
+ * Binary operator overloads
+ */
+template<typename DataType>
inline bool
-operator==(const Pixel &lhs, const Pixel &rhs)
+operator==(const Pixel<DataType> &lhs, const Pixel<DataType> &rhs)
{
return lhs.red == rhs.red &&
lhs.green == rhs.green &&
lhs.blue == rhs.blue &&
- lhs.padding == rhs.padding;
+ lhs.alpha == rhs.alpha;
}
/**
+ * Scalar Multiplication
+ */
+template<typename ScalarType, typename DataType>
+inline Pixel<DataType>
+operator * (const ScalarType& a, const Pixel<DataType>& b)
+{
+
+ Pixel<DataType> t;
+ t.red = a * b.red;
+ t.green = a * b.green;
+ t.blue = a * b.blue;
+ return t;
+}
+
+template<typename DataType, typename ScalarType>
+inline Pixel<DataType>
+operator * (const Pixel<DataType>& a, const ScalarType& b)
+{
+ return b*a;
+}
+
+/**
+ * Scalar Division
+ */
+template<typename DataType, typename ScalarType>
+inline Pixel<DataType>
+operator / (const Pixel<DataType>& a, const ScalarType& b)
+{
+ Pixel<DataType> t;
+ t.red = a.red/b;
+ t.green = a.green/b;
+ t.blue = a.blue/b;
+ return t;
+}
+
+/**
+ * non-scalar Addition
+ */
+template<typename DataType>
+inline Pixel<DataType>
+operator + (const Pixel<DataType>& a, const Pixel<DataType>& b)
+{
+ Pixel<DataType> t;
+ t.red = a.red + b.red;
+ t.green = a.green + b.green;
+ t.blue = a.blue + b.blue;
+ return t;
+}
+
+
+/**
+ * Common Pixel types
+ */
+typedef Pixel<uint8_t> PixelU8;
+typedef Pixel<uint16_t> PixelU16;
+
+/**
* Configurable RGB pixel converter.
*
* This class converts between external RGB representations and gem5's
@@ -132,19 +224,19 @@
ByteOrder byte_order = LittleEndianByteOrder);
/** Get the Pixel representation of a color word. */
- Pixel toPixel(uint32_t word) const {
- return Pixel(ch_r.toPixel(word),
+ PixelU8 toPixel(uint32_t word) const {
+ return PixelU8(ch_r.toPixel(word),
ch_g.toPixel(word),
ch_b.toPixel(word));
}
/** Get a Pixel representation by reading a word from memory. */
- Pixel toPixel(const uint8_t *rfb) const {
+ PixelU8 toPixel(const uint8_t *rfb) const {
return toPixel(readWord(rfb));
}
/** Convert a Pixel into a color word */
- uint32_t fromPixel(const Pixel &pixel) const {
+ uint32_t fromPixel(const PixelU8 &pixel) const {
return ch_r.fromPixel(pixel.red) |
ch_g.fromPixel(pixel.green) |
ch_b.fromPixel(pixel.blue);
@@ -154,7 +246,7 @@
* Convert a pixel into a color word and store the resulting word
* in memory.
*/
- void fromPixel(uint8_t *rfb, const Pixel &pixel) const {
+ void fromPixel(uint8_t *rfb, const PixelU8 &pixel) const {
writeWord(rfb, fromPixel(pixel));
}
@@ -163,7 +255,7 @@
*
* The number of bytes read from memory is determined by the
* length of a color word. Note that some of the bytes may be
- * padding.
+ * padding or alpha.
*
* @param p Pointer to the first byte in the word.
* @return Word in host endianness.
@@ -177,12 +269,12 @@
*/
void writeWord(uint8_t *p, uint32_t word) const;
- /** Bytes per pixel when stored in memory (including padding) */
+ /** Bytes per pixel when stored in memory */
unsigned length;
/**
* Number of bits used to represent one pixel value (excluding
- * padding). This could be less than length * 8 if the pixel value
- * is padded.
+ * padding/alpha). This could be less than length * 8 if the pixel
+ * value is padded or has an alpha channel.
*/
unsigned depth;
/** Byte order when stored to memory. */
@@ -211,7 +303,7 @@
};
inline bool
-to_number(const std::string &value, Pixel &retval)
+to_number(const std::string &value, PixelU8 &retval)
{
uint32_t num;
if (!to_number(value, num))
@@ -222,9 +314,9 @@
}
inline std::ostream &
-operator<<(std::ostream &os, const Pixel &pxl)
+operator<<(std::ostream &os, const PixelU8 &pxl)
{
- os << csprintf("%#.08x", PixelConverter::rgba8888_le.fromPixel(pxl));
+ os << csprintf("0x%.08x", PixelConverter::rgba8888_le.fromPixel(pxl));
return os;
}
diff --git a/src/base/pixeltest.cc b/src/base/pixeltest.cc
index 4c88fc9..0672e31 100644
--- a/src/base/pixeltest.cc
+++ b/src/base/pixeltest.cc
@@ -41,9 +41,9 @@
#include "base/pixel.hh"
-static Pixel pixel_red(0xff, 0x00, 0x00);
-static Pixel pixel_green(0x00, 0xff, 0x00);
-static Pixel pixel_blue(0x00, 0x00, 0xff);
+static PixelU8 pixel_red(0xff, 0x00, 0x00);
+static PixelU8 pixel_green(0x00, 0xff, 0x00);
+static PixelU8 pixel_blue(0x00, 0x00, 0xff);
TEST(FBTest, PixelConversionRGBA8888)
{
diff --git a/src/base/pngwriter.hh b/src/base/pngwriter.hh
index 984f2f6..fa29056 100644
--- a/src/base/pngwriter.hh
+++ b/src/base/pngwriter.hh
@@ -79,7 +79,7 @@
private:
/** Png Pixel type: not containing padding */
struct PngPixel24 {
- PngPixel24 &operator=(const Pixel &rhs) {
+ PngPixel24 &operator=(const PixelU8 &rhs) {
red = rhs.red;
green = rhs.green;
blue = rhs.blue;
diff --git a/src/dev/arm/hdlcd.cc b/src/dev/arm/hdlcd.cc
index 20dc7d4..499a263 100644
--- a/src/dev/arm/hdlcd.cc
+++ b/src/dev/arm/hdlcd.cc
@@ -521,7 +521,7 @@
}
bool
-HDLcd::pxlNext(Pixel &p)
+HDLcd::pxlNext(PixelU8 &p)
{
uint8_t pixel_data[MAX_PIXEL_SIZE];
assert(conv.length <= sizeof(pixel_data));
diff --git a/src/dev/arm/hdlcd.hh b/src/dev/arm/hdlcd.hh
index f737710..4bd963a 100644
--- a/src/dev/arm/hdlcd.hh
+++ b/src/dev/arm/hdlcd.hh
@@ -269,7 +269,7 @@
bool enabled() const { return command.enable; }
public: // Pixel pump callbacks
- bool pxlNext(Pixel &p);
+ bool pxlNext(PixelU8 &p);
void pxlVSyncBegin();
void pxlVSyncEnd();
void pxlUnderrun();
@@ -330,7 +330,7 @@
void dumpSettings();
protected:
- bool nextPixel(Pixel &p) override { return parent.pxlNext(p); }
+ bool nextPixel(PixelU8 &p) override { return parent.pxlNext(p);}
void onVSyncBegin() override { return parent.pxlVSyncBegin(); }
void onVSyncEnd() override { return parent.pxlVSyncEnd(); }
diff --git a/src/dev/pixelpump.cc b/src/dev/pixelpump.cc
index e1cf73a..79b0827 100644
--- a/src/dev/pixelpump.cc
+++ b/src/dev/pixelpump.cc
@@ -221,8 +221,8 @@
const unsigned pxl_count(x_end - _posX);
const unsigned pos_y(posY());
- Pixel pixel(0, 0, 0);
- const Pixel underrun_pixel(0, 0, 0);
+ PixelU8 pixel(0, 0, 0);
+ const PixelU8 underrun_pixel(0, 0, 0);
for (; _posX < x_end && !_underrun; ++_posX) {
if (!nextPixel(pixel)) {
warn("Input buffer underrun in BasePixelPump (%u, %u)\n",
@@ -285,7 +285,7 @@
{
const unsigned pos_y(posY());
- Pixel pixel(0, 0, 0);
+ PixelU8 pixel(0, 0, 0);
for (_posX = 0; _posX < _timings.width; ++_posX) {
if (!nextPixel(pixel)) {
panic("Unexpected underrun in BasePixelPump (%u, %u)\n",
diff --git a/src/dev/pixelpump.hh b/src/dev/pixelpump.hh
index bc21fca..5fb24b0 100644
--- a/src/dev/pixelpump.hh
+++ b/src/dev/pixelpump.hh
@@ -201,7 +201,7 @@
* @param p Output pixel value, undefined on underrun
* @return true on success, false on buffer underrun
*/
- virtual bool nextPixel(Pixel &p) = 0;
+ virtual bool nextPixel(PixelU8 &p) = 0;
/** First pixel clock of the first VSync line. */
virtual void onVSyncBegin() {};
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index a03a396..523974d 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -471,7 +471,7 @@
INSTANTIATE_PARAM_TEMPLATES(float)
INSTANTIATE_PARAM_TEMPLATES(double)
INSTANTIATE_PARAM_TEMPLATES(string)
-INSTANTIATE_PARAM_TEMPLATES(Pixel)
+INSTANTIATE_PARAM_TEMPLATES(Pixel<uint8_t>)
INSTANTIATE_PARAM_TEMPLATES(VecRegContainer<8>)
INSTANTIATE_PARAM_TEMPLATES(VecRegContainer<16>)
--
To view, visit https://gem5-review.googlesource.com/10802
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: Ice598aa7bb4ebf3dd96446cac57055dcd24a21e0
Gerrit-Change-Number: 10802
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