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

Reply via email to