framebuffer.hh revision 10839:10cac0f0f419
1/*
2 * Copyright (c) 2015 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Sandberg
38 */
39
40#ifndef __BASE_FRAMEBUFFER_HH__
41#define __BASE_FRAMEBUFFER_HH__
42
43#include <cmath>
44#include <cstdint>
45
46#include <vector>
47
48#include "base/types.hh"
49
50/**
51 * Internal gem5 representation of a Pixel.
52 */
53struct Pixel
54{
55    Pixel()
56        : red(0), green(0), blue(0), padding(0) {}
57
58    Pixel(uint8_t _red, uint8_t _green, uint8_t _blue)
59        : red(_red), green(_green), blue(_blue), padding(0) {}
60
61    uint8_t red;
62    uint8_t green;
63    uint8_t blue;
64    uint8_t padding;
65};
66
67inline bool
68operator==(const Pixel &lhs, const Pixel &rhs)
69{
70    return lhs.red == rhs.red &&
71        lhs.green == rhs.green &&
72        lhs.blue == rhs.blue &&
73        lhs.padding == rhs.padding;
74}
75
76
77/**
78 * Configurable RGB pixel converter.
79 *
80 * This class converts between external RGB representations and gem5's
81 * internal Pixel representation. The class assumes that pixels are
82 * stored in a word of configurable length (up to 32 bits). Individual
83 * pixels are assumed to be represented by contiguous bit ranges in
84 * the word (i.e., it is possible to shift and mask out a contiguous
85 * bit range for each pixel).
86 */
87class PixelConverter
88{
89  public:
90    /**
91     * Color channel conversion and scaling helper class.
92     */
93    struct Channel {
94        /**
95         * @param offset Offset in bits.
96         * @param width Width in bits.
97         */
98        Channel(unsigned offset, unsigned width);
99
100        /**
101         * Get the value of a single color channel represented as an
102         * 8-bit number.
103         */
104        uint8_t toPixel(uint32_t word) const {
105            return round(((word >> offset) & mask) * factor);
106        }
107
108        /**
109         * Convert an 8-bit representation of a color into an external
110         * format.
111         */
112        uint32_t fromPixel(uint8_t ch) const {
113            return (static_cast<uint8_t>(round(ch / factor)) & mask) << offset;
114        }
115
116        /** Offset in bits */
117        unsigned offset;
118        /** Bit mask (after shifting) */
119        unsigned mask;
120        /**
121         * Scaling factor when converting to the full range of an
122         * 8-bit color channel
123         */
124        float factor;
125    };
126
127    PixelConverter(unsigned length,
128                   unsigned ro, unsigned go, unsigned bo,
129                   unsigned rw, unsigned gw, unsigned bw,
130                   ByteOrder byte_order = LittleEndianByteOrder);
131
132    /** Get the Pixel representation of a color word. */
133    Pixel toPixel(uint32_t word) const {
134        return Pixel(ch_r.toPixel(word),
135                     ch_g.toPixel(word),
136                     ch_b.toPixel(word));
137    }
138
139    /** Get a Pixel representation by reading a word from memory. */
140    Pixel toPixel(const uint8_t *rfb) const {
141        return toPixel(readWord(rfb));
142    }
143
144    /** Convert a Pixel into a color word */
145    uint32_t fromPixel(const Pixel &pixel) const {
146        return ch_r.fromPixel(pixel.red) |
147            ch_g.fromPixel(pixel.green) |
148            ch_b.fromPixel(pixel.blue);
149    }
150
151    /**
152     * Convert a pixel into a color word and store the resulting word
153     * in memory.
154     */
155    void fromPixel(uint8_t *rfb, const Pixel &pixel) const {
156        writeWord(rfb, fromPixel(pixel));
157    }
158
159    /**
160     * Read a word of a given length and endianness from memory.
161     *
162     * The number of bytes read from memory is determined by the
163     * length of a color word. Note that some of the bytes may be
164     * padding.
165     *
166     * @param p Pointer to the first byte in the word.
167     * @return Word in host endianness.
168     */
169    uint32_t readWord(const uint8_t *p) const;
170    /**
171     * Write a word of a given length and endianness to memory.
172     *
173     * @param p Pointer to the first byte in memory.
174     * @param word Word to store (host endianness).
175     */
176    void writeWord(uint8_t *p, uint32_t word) const;
177
178    /** Bytes per pixel when stored in memory (including padding) */
179    unsigned length;
180    /**
181     * Number of bits used to represent one pixel value (excluding
182     * padding). This could be less than length * 8 if the pixel value
183     * is padded.
184     */
185    unsigned depth;
186    /** Byte order when stored to memory. */
187    ByteOrder byte_order;
188
189    /** Red channel conversion helper */
190    Channel ch_r;
191    /** Green channel conversion helper */
192    Channel ch_g;
193    /** Blue channel conversion helper */
194    Channel ch_b;
195
196    /** Predefined 32-bit RGB (red in least significant bits, 8
197     * bits/channel, little endian) conversion helper */
198    static const PixelConverter rgba8888_le;
199    /** Predefined 16-bit RGB565 (red in least significant bits,
200     * little endian) conversion helper */
201    static const PixelConverter rgb565_le;
202
203    /** Predefined 32-bit RGB (red in least significant bits, 8
204     * bits/channel, big endian) conversion helper */
205    static const PixelConverter rgba8888_be;
206    /** Predefined 16-bit RGB565 (red in least significant bits,
207     * big endian) conversion helper */
208    static const PixelConverter rgb565_be;
209};
210
211/**
212 * Internal gem5 representation of a frame buffer
213 *
214 * Display controllers and other devices producing images are expected
215 * to use this class to represent the final image.
216 *
217 * Pixels are indexed relative to the upper left corner of the
218 * image. That is, the pixel at position (0, 0) is the upper left
219 * corner. The backing store is a linear vector of Pixels ordered left
220 * to right starting in the upper left corner.
221 */
222class FrameBuffer
223{
224  public:
225    /**
226     * Create a frame buffer of a given size.
227     *
228     * @param width Width in pixels
229     * @param height Height in pixels
230     */
231    FrameBuffer(unsigned width, unsigned height);
232    /** Create an empty (0x0) frame buffer */
233    FrameBuffer();
234
235    virtual ~FrameBuffer();
236
237    /**
238     * Resize the frame buffer.
239     *
240     * This method resizes frame buffer including the backing
241     * store. The contents of the backing store are undefined after
242     * this operation.
243     *
244     * @param with Width in pixels.
245     * @param height Height in pixels.
246     */
247    void resize(unsigned width, unsigned height);
248
249    /** Frame buffer width in pixels */
250    unsigned width() const { return _width; }
251    /** Frame buffer height in pixels */
252    unsigned height() const { return _height; }
253    /** Total number of pixels in frame buffer */
254    unsigned area() const { return _width * _height; }
255
256    /**
257     * Fill the frame buffer with a single pixel value
258     *
259     * @param pixel Pixel value to fill with.
260     */
261    void fill(const Pixel &pixel);
262    /**
263     * Fill the frame buffer with black pixels
264     */
265    void clear();
266
267    /**
268     * Fill the frame buffer with pixel data from an external buffer
269     * of the same width and height as this frame buffer.
270     *
271     * @param fb External frame buffer
272     * @param conv Pixel conversion helper
273     */
274    void copyIn(const uint8_t *fb, const PixelConverter &conv);
275    /**
276     * Fill the frame buffer with pixel data from an external buffer
277     * of the same width and height as this frame buffer.
278     *
279     * @param fb External frame buffer
280     * @param conv Pixel conversion helper
281     */
282    void copyIn(const std::vector<uint8_t> &fb, const PixelConverter &conv) {
283        copyIn(fb.data(), conv);
284    }
285
286    /**
287     * Store the contents of this frame buffer in an external buffer
288     * of the same width and height as this frame buffer.
289     *
290     * @param fb External frame buffer
291     * @param conv Pixel conversion helper
292     */
293    void copyOut(uint8_t *fb, const PixelConverter &conv) const;
294    /**
295     * Store the contents of this frame buffer in an external buffer
296     * of the same width and height as this frame buffer.
297     *
298     * @param fb External frame buffer
299     * @param conv Pixel conversion helper
300     */
301    void copyOut(std::vector<uint8_t> &fb, const PixelConverter &conv) const {
302        copyOut(fb.data(), conv);
303    }
304
305    /**
306     * Get a pixel from an (x, y) coordinate
307     *
308     * @param x Distance from the left margin.
309     * @param y Distance from the top of the frame.
310     */
311    const Pixel &pixel(unsigned x, unsigned y) const {
312        assert(x < _width);
313        assert(y < _height);
314
315        return pixels[y * _width + x];
316    }
317
318    /**
319     * Get a pixel from an (x, y) coordinate
320     *
321     * @param x Distance from the left margin.
322     * @param y Distance from the top of the frame.
323     */
324    Pixel &pixel(unsigned x, unsigned y) {
325        assert(x < _width);
326        assert(y < _height);
327
328        return pixels[y * _width + x];
329    }
330
331    /**
332     * Create a hash of the image that can be used for quick
333     * comparisons.
334     */
335    uint64_t getHash() const;
336
337    /**
338     * Static "dummy" frame buffer.
339     *
340     * This is a dummy frame buffer that can be used as a place holder
341     * for devices that always expect a frame buffer to be present.
342     */
343    static const FrameBuffer dummy;
344
345    /** Frame buffer backing store */
346    std::vector<Pixel> pixels;
347
348  protected:
349    /** Width in pixels */
350    unsigned _width;
351    /** Height in pixels */
352    unsigned _height;
353};
354
355#endif // __BASE_FRAMEBUFFER_HH__
356