112366Sgabeblack@google.com/*
212366Sgabeblack@google.com * Copyright (c) 2015 ARM Limited
312366Sgabeblack@google.com * All rights reserved
412366Sgabeblack@google.com *
512366Sgabeblack@google.com * The license below extends only to copyright in the software and shall
612366Sgabeblack@google.com * not be construed as granting a license to any other intellectual
712366Sgabeblack@google.com * property including but not limited to intellectual property relating
812366Sgabeblack@google.com * to a hardware implementation of the functionality of the software
912366Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1012366Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1112366Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1212366Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1312366Sgabeblack@google.com *
1412366Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
1512366Sgabeblack@google.com * modification, are permitted provided that the following conditions are
1612366Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
1712366Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
1812366Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1912366Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2012366Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2112366Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2212366Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2312366Sgabeblack@google.com * this software without specific prior written permission.
2412366Sgabeblack@google.com *
2512366Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612366Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712366Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812366Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912366Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012366Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112366Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212366Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312366Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412366Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512366Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612366Sgabeblack@google.com *
3712366Sgabeblack@google.com * Authors: Andreas Sandberg
3812366Sgabeblack@google.com */
3912366Sgabeblack@google.com
4012366Sgabeblack@google.com#ifndef __BASE_PIXEL_HH__
4112366Sgabeblack@google.com#define __BASE_PIXEL_HH__
4212366Sgabeblack@google.com
4312366Sgabeblack@google.com#include <cmath>
4412366Sgabeblack@google.com#include <cstdint>
4512366Sgabeblack@google.com#include <string>
4612366Sgabeblack@google.com#include <vector>
4712366Sgabeblack@google.com
4812366Sgabeblack@google.com#include "base/compiler.hh"
4912366Sgabeblack@google.com#include "base/cprintf.hh"
5012366Sgabeblack@google.com#include "base/str.hh"
5112366Sgabeblack@google.com#include "base/types.hh"
5212366Sgabeblack@google.com
5312366Sgabeblack@google.com/**
5412366Sgabeblack@google.com * Internal gem5 representation of a Pixel.
5512366Sgabeblack@google.com */
5612366Sgabeblack@google.comstruct Pixel
5712366Sgabeblack@google.com{
5812366Sgabeblack@google.com    Pixel()
5912366Sgabeblack@google.com        : red(0), green(0), blue(0), padding(0) {}
6012366Sgabeblack@google.com
6112366Sgabeblack@google.com    Pixel(uint8_t _red, uint8_t _green, uint8_t _blue)
6212366Sgabeblack@google.com        : red(_red), green(_green), blue(_blue), padding(0) {}
6312366Sgabeblack@google.com
6412366Sgabeblack@google.com    uint8_t red;
6512366Sgabeblack@google.com    uint8_t green;
6612366Sgabeblack@google.com    uint8_t blue;
6712366Sgabeblack@google.com    uint8_t padding;
6812366Sgabeblack@google.com};
6912366Sgabeblack@google.com
7012366Sgabeblack@google.cominline bool
7112366Sgabeblack@google.comoperator==(const Pixel &lhs, const Pixel &rhs)
7212366Sgabeblack@google.com{
7312366Sgabeblack@google.com    return lhs.red == rhs.red &&
7412366Sgabeblack@google.com        lhs.green == rhs.green &&
7512366Sgabeblack@google.com        lhs.blue == rhs.blue &&
7612366Sgabeblack@google.com        lhs.padding == rhs.padding;
7712366Sgabeblack@google.com}
7812366Sgabeblack@google.com
7912366Sgabeblack@google.com/**
8012366Sgabeblack@google.com * Configurable RGB pixel converter.
8112366Sgabeblack@google.com *
8212366Sgabeblack@google.com * This class converts between external RGB representations and gem5's
8312366Sgabeblack@google.com * internal Pixel representation. The class assumes that pixels are
8412366Sgabeblack@google.com * stored in a word of configurable length (up to 32 bits). Individual
8512366Sgabeblack@google.com * pixels are assumed to be represented by contiguous bit ranges in
8612366Sgabeblack@google.com * the word (i.e., it is possible to shift and mask out a contiguous
8712366Sgabeblack@google.com * bit range for each pixel).
8812366Sgabeblack@google.com */
8912366Sgabeblack@google.comclass PixelConverter
9012366Sgabeblack@google.com{
9112366Sgabeblack@google.com  public:
9212366Sgabeblack@google.com    /**
9312366Sgabeblack@google.com     * Color channel conversion and scaling helper class.
9412366Sgabeblack@google.com     */
9512366Sgabeblack@google.com    struct Channel {
9612366Sgabeblack@google.com        /**
9712366Sgabeblack@google.com         * @param offset Offset in bits.
9812366Sgabeblack@google.com         * @param width Width in bits.
9912366Sgabeblack@google.com         */
10012366Sgabeblack@google.com        Channel(unsigned offset, unsigned width);
10112366Sgabeblack@google.com
10212366Sgabeblack@google.com        /**
10312366Sgabeblack@google.com         * Get the value of a single color channel represented as an
10412366Sgabeblack@google.com         * 8-bit number.
10512366Sgabeblack@google.com         */
10612366Sgabeblack@google.com        uint8_t toPixel(uint32_t word) const {
10712366Sgabeblack@google.com            return round(((word >> offset) & mask) * factor);
10812366Sgabeblack@google.com        }
10912366Sgabeblack@google.com
11012366Sgabeblack@google.com        /**
11112366Sgabeblack@google.com         * Convert an 8-bit representation of a color into an external
11212366Sgabeblack@google.com         * format.
11312366Sgabeblack@google.com         */
11412366Sgabeblack@google.com        uint32_t fromPixel(uint8_t ch) const {
11512366Sgabeblack@google.com            return (static_cast<uint8_t>(round(ch / factor)) & mask) << offset;
11612366Sgabeblack@google.com        }
11712366Sgabeblack@google.com
11812366Sgabeblack@google.com        /** Offset in bits */
11912366Sgabeblack@google.com        unsigned offset;
12012366Sgabeblack@google.com        /** Bit mask (after shifting) */
12112366Sgabeblack@google.com        unsigned mask;
12212366Sgabeblack@google.com        /**
12312366Sgabeblack@google.com         * Scaling factor when converting to the full range of an
12412366Sgabeblack@google.com         * 8-bit color channel
12512366Sgabeblack@google.com         */
12612366Sgabeblack@google.com        float factor;
12712366Sgabeblack@google.com    };
12812366Sgabeblack@google.com
12912366Sgabeblack@google.com    PixelConverter(unsigned length,
13012366Sgabeblack@google.com                   unsigned ro, unsigned go, unsigned bo,
13112366Sgabeblack@google.com                   unsigned rw, unsigned gw, unsigned bw,
13212366Sgabeblack@google.com                   ByteOrder byte_order = LittleEndianByteOrder);
13312366Sgabeblack@google.com
13412366Sgabeblack@google.com    /** Get the Pixel representation of a color word. */
13512366Sgabeblack@google.com    Pixel toPixel(uint32_t word) const {
13612366Sgabeblack@google.com        return Pixel(ch_r.toPixel(word),
13712366Sgabeblack@google.com                     ch_g.toPixel(word),
13812366Sgabeblack@google.com                     ch_b.toPixel(word));
13912366Sgabeblack@google.com    }
14012366Sgabeblack@google.com
14112366Sgabeblack@google.com    /** Get a Pixel representation by reading a word from memory. */
14212366Sgabeblack@google.com    Pixel toPixel(const uint8_t *rfb) const {
14312366Sgabeblack@google.com        return toPixel(readWord(rfb));
14412366Sgabeblack@google.com    }
14512366Sgabeblack@google.com
14612366Sgabeblack@google.com    /** Convert a Pixel into a color word */
14712366Sgabeblack@google.com    uint32_t fromPixel(const Pixel &pixel) const {
14812366Sgabeblack@google.com        return ch_r.fromPixel(pixel.red) |
14912366Sgabeblack@google.com            ch_g.fromPixel(pixel.green) |
15012366Sgabeblack@google.com            ch_b.fromPixel(pixel.blue);
15112366Sgabeblack@google.com    }
15212366Sgabeblack@google.com
15312366Sgabeblack@google.com    /**
15412366Sgabeblack@google.com     * Convert a pixel into a color word and store the resulting word
15512366Sgabeblack@google.com     * in memory.
15612366Sgabeblack@google.com     */
15712366Sgabeblack@google.com    void fromPixel(uint8_t *rfb, const Pixel &pixel) const {
15812366Sgabeblack@google.com        writeWord(rfb, fromPixel(pixel));
15912366Sgabeblack@google.com    }
16012366Sgabeblack@google.com
16112366Sgabeblack@google.com    /**
16212366Sgabeblack@google.com     * Read a word of a given length and endianness from memory.
16312366Sgabeblack@google.com     *
16412366Sgabeblack@google.com     * The number of bytes read from memory is determined by the
16512366Sgabeblack@google.com     * length of a color word. Note that some of the bytes may be
16612366Sgabeblack@google.com     * padding.
16712366Sgabeblack@google.com     *
16812366Sgabeblack@google.com     * @param p Pointer to the first byte in the word.
16912366Sgabeblack@google.com     * @return Word in host endianness.
17012366Sgabeblack@google.com     */
17112366Sgabeblack@google.com    uint32_t readWord(const uint8_t *p) const;
17212366Sgabeblack@google.com    /**
17312366Sgabeblack@google.com     * Write a word of a given length and endianness to memory.
17412366Sgabeblack@google.com     *
17512366Sgabeblack@google.com     * @param p Pointer to the first byte in memory.
17612366Sgabeblack@google.com     * @param word Word to store (host endianness).
17712366Sgabeblack@google.com     */
17812366Sgabeblack@google.com    void writeWord(uint8_t *p, uint32_t word) const;
17912366Sgabeblack@google.com
18012366Sgabeblack@google.com    /** Bytes per pixel when stored in memory (including padding) */
18112366Sgabeblack@google.com    unsigned length;
18212366Sgabeblack@google.com    /**
18312366Sgabeblack@google.com     * Number of bits used to represent one pixel value (excluding
18412366Sgabeblack@google.com     * padding). This could be less than length * 8 if the pixel value
18512366Sgabeblack@google.com     * is padded.
18612366Sgabeblack@google.com     */
18712366Sgabeblack@google.com    unsigned depth;
18812366Sgabeblack@google.com    /** Byte order when stored to memory. */
18912366Sgabeblack@google.com    ByteOrder byte_order;
19012366Sgabeblack@google.com
19112366Sgabeblack@google.com    /** Red channel conversion helper */
19212366Sgabeblack@google.com    Channel ch_r;
19312366Sgabeblack@google.com    /** Green channel conversion helper */
19412366Sgabeblack@google.com    Channel ch_g;
19512366Sgabeblack@google.com    /** Blue channel conversion helper */
19612366Sgabeblack@google.com    Channel ch_b;
19712366Sgabeblack@google.com
19812366Sgabeblack@google.com    /** Predefined 32-bit RGB (red in least significant bits, 8
19912366Sgabeblack@google.com     * bits/channel, little endian) conversion helper */
20012366Sgabeblack@google.com    static const PixelConverter rgba8888_le;
20112366Sgabeblack@google.com    /** Predefined 16-bit RGB565 (red in least significant bits,
20212366Sgabeblack@google.com     * little endian) conversion helper */
20312366Sgabeblack@google.com    static const PixelConverter rgb565_le;
20412366Sgabeblack@google.com
20512366Sgabeblack@google.com    /** Predefined 32-bit RGB (red in least significant bits, 8
20612366Sgabeblack@google.com     * bits/channel, big endian) conversion helper */
20712366Sgabeblack@google.com    static const PixelConverter rgba8888_be;
20812366Sgabeblack@google.com    /** Predefined 16-bit RGB565 (red in least significant bits,
20912366Sgabeblack@google.com     * big endian) conversion helper */
21012366Sgabeblack@google.com    static const PixelConverter rgb565_be;
21112366Sgabeblack@google.com};
21212366Sgabeblack@google.com
21312366Sgabeblack@google.cominline bool
21412366Sgabeblack@google.comto_number(const std::string &value, Pixel &retval)
21512366Sgabeblack@google.com{
21612366Sgabeblack@google.com    uint32_t num;
21712366Sgabeblack@google.com    if (!to_number(value, num))
21812366Sgabeblack@google.com        return false;
21912366Sgabeblack@google.com
22012366Sgabeblack@google.com    retval = PixelConverter::rgba8888_le.toPixel(num);
22112366Sgabeblack@google.com    return true;
22212366Sgabeblack@google.com}
22312366Sgabeblack@google.com
22412366Sgabeblack@google.cominline std::ostream &
22512366Sgabeblack@google.comoperator<<(std::ostream &os, const Pixel &pxl)
22612366Sgabeblack@google.com{
22712366Sgabeblack@google.com    os << csprintf("%#.08x", PixelConverter::rgba8888_le.fromPixel(pxl));
22812366Sgabeblack@google.com    return os;
22912366Sgabeblack@google.com}
23012366Sgabeblack@google.com
23112366Sgabeblack@google.com#endif // __BASE_PIXEL_HH__
232