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

Reply via email to