framebuffer.hh revision 11168:f98eb2da15a4
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 <string> 47#include <vector> 48 49#include "base/compiler.hh" 50#include "base/cprintf.hh" 51#include "base/str.hh" 52#include "base/types.hh" 53#include "sim/serialize.hh" 54 55/** 56 * Internal gem5 representation of a Pixel. 57 */ 58struct Pixel 59{ 60 Pixel() 61 : red(0), green(0), blue(0), padding(0) {} 62 63 Pixel(uint8_t _red, uint8_t _green, uint8_t _blue) 64 : red(_red), green(_green), blue(_blue), padding(0) {} 65 66 uint8_t red; 67 uint8_t green; 68 uint8_t blue; 69 uint8_t padding; 70}; 71 72inline bool 73operator==(const Pixel &lhs, const Pixel &rhs) 74{ 75 return lhs.red == rhs.red && 76 lhs.green == rhs.green && 77 lhs.blue == rhs.blue && 78 lhs.padding == rhs.padding; 79} 80 81/** 82 * Configurable RGB pixel converter. 83 * 84 * This class converts between external RGB representations and gem5's 85 * internal Pixel representation. The class assumes that pixels are 86 * stored in a word of configurable length (up to 32 bits). Individual 87 * pixels are assumed to be represented by contiguous bit ranges in 88 * the word (i.e., it is possible to shift and mask out a contiguous 89 * bit range for each pixel). 90 */ 91class PixelConverter 92{ 93 public: 94 /** 95 * Color channel conversion and scaling helper class. 96 */ 97 struct Channel { 98 /** 99 * @param offset Offset in bits. 100 * @param width Width in bits. 101 */ 102 Channel(unsigned offset, unsigned width); 103 104 /** 105 * Get the value of a single color channel represented as an 106 * 8-bit number. 107 */ 108 uint8_t toPixel(uint32_t word) const { 109 return round(((word >> offset) & mask) * factor); 110 } 111 112 /** 113 * Convert an 8-bit representation of a color into an external 114 * format. 115 */ 116 uint32_t fromPixel(uint8_t ch) const { 117 return (static_cast<uint8_t>(round(ch / factor)) & mask) << offset; 118 } 119 120 /** Offset in bits */ 121 unsigned offset; 122 /** Bit mask (after shifting) */ 123 unsigned mask; 124 /** 125 * Scaling factor when converting to the full range of an 126 * 8-bit color channel 127 */ 128 float factor; 129 }; 130 131 PixelConverter(unsigned length, 132 unsigned ro, unsigned go, unsigned bo, 133 unsigned rw, unsigned gw, unsigned bw, 134 ByteOrder byte_order = LittleEndianByteOrder); 135 136 /** Get the Pixel representation of a color word. */ 137 Pixel toPixel(uint32_t word) const { 138 return Pixel(ch_r.toPixel(word), 139 ch_g.toPixel(word), 140 ch_b.toPixel(word)); 141 } 142 143 /** Get a Pixel representation by reading a word from memory. */ 144 Pixel toPixel(const uint8_t *rfb) const { 145 return toPixel(readWord(rfb)); 146 } 147 148 /** Convert a Pixel into a color word */ 149 uint32_t fromPixel(const Pixel &pixel) const { 150 return ch_r.fromPixel(pixel.red) | 151 ch_g.fromPixel(pixel.green) | 152 ch_b.fromPixel(pixel.blue); 153 } 154 155 /** 156 * Convert a pixel into a color word and store the resulting word 157 * in memory. 158 */ 159 void fromPixel(uint8_t *rfb, const Pixel &pixel) const { 160 writeWord(rfb, fromPixel(pixel)); 161 } 162 163 /** 164 * Read a word of a given length and endianness from memory. 165 * 166 * The number of bytes read from memory is determined by the 167 * length of a color word. Note that some of the bytes may be 168 * padding. 169 * 170 * @param p Pointer to the first byte in the word. 171 * @return Word in host endianness. 172 */ 173 uint32_t readWord(const uint8_t *p) const; 174 /** 175 * Write a word of a given length and endianness to memory. 176 * 177 * @param p Pointer to the first byte in memory. 178 * @param word Word to store (host endianness). 179 */ 180 void writeWord(uint8_t *p, uint32_t word) const; 181 182 /** Bytes per pixel when stored in memory (including padding) */ 183 unsigned length; 184 /** 185 * Number of bits used to represent one pixel value (excluding 186 * padding). This could be less than length * 8 if the pixel value 187 * is padded. 188 */ 189 unsigned depth; 190 /** Byte order when stored to memory. */ 191 ByteOrder byte_order; 192 193 /** Red channel conversion helper */ 194 Channel ch_r; 195 /** Green channel conversion helper */ 196 Channel ch_g; 197 /** Blue channel conversion helper */ 198 Channel ch_b; 199 200 /** Predefined 32-bit RGB (red in least significant bits, 8 201 * bits/channel, little endian) conversion helper */ 202 static const PixelConverter rgba8888_le; 203 /** Predefined 16-bit RGB565 (red in least significant bits, 204 * little endian) conversion helper */ 205 static const PixelConverter rgb565_le; 206 207 /** Predefined 32-bit RGB (red in least significant bits, 8 208 * bits/channel, big endian) conversion helper */ 209 static const PixelConverter rgba8888_be; 210 /** Predefined 16-bit RGB565 (red in least significant bits, 211 * big endian) conversion helper */ 212 static const PixelConverter rgb565_be; 213}; 214 215inline bool 216to_number(const std::string &value, Pixel &retval) 217{ 218 uint32_t num; 219 if (!to_number(value, num)) 220 return false; 221 222 retval = PixelConverter::rgba8888_le.toPixel(num); 223 return true; 224} 225 226inline std::ostream & 227operator<<(std::ostream &os, const Pixel &pxl) 228{ 229 os << csprintf("0x%.08x", PixelConverter::rgba8888_le.fromPixel(pxl)); 230 return os; 231} 232 233/** 234 * Internal gem5 representation of a frame buffer 235 * 236 * Display controllers and other devices producing images are expected 237 * to use this class to represent the final image. 238 * 239 * Pixels are indexed relative to the upper left corner of the 240 * image. That is, the pixel at position (0, 0) is the upper left 241 * corner. The backing store is a linear vector of Pixels ordered left 242 * to right starting in the upper left corner. 243 */ 244class FrameBuffer : public Serializable 245{ 246 public: 247 /** 248 * Create a frame buffer of a given size. 249 * 250 * @param width Width in pixels 251 * @param height Height in pixels 252 */ 253 FrameBuffer(unsigned width, unsigned height); 254 /** Create an empty (0x0) frame buffer */ 255 FrameBuffer(); 256 257 virtual ~FrameBuffer(); 258 259 void serialize(CheckpointOut &cp) const override; 260 void unserialize(CheckpointIn &cp) override; 261 262 /** 263 * Resize the frame buffer. 264 * 265 * This method resizes frame buffer including the backing 266 * store. The contents of the backing store are undefined after 267 * this operation. 268 * 269 * @param with Width in pixels. 270 * @param height Height in pixels. 271 */ 272 void resize(unsigned width, unsigned height); 273 274 /** Frame buffer width in pixels */ 275 unsigned width() const { return _width; } 276 /** Frame buffer height in pixels */ 277 unsigned height() const { return _height; } 278 /** Total number of pixels in frame buffer */ 279 unsigned area() const { return _width * _height; } 280 281 /** 282 * Fill the frame buffer with a single pixel value 283 * 284 * @param pixel Pixel value to fill with. 285 */ 286 void fill(const Pixel &pixel); 287 /** 288 * Fill the frame buffer with black pixels 289 */ 290 void clear(); 291 292 /** 293 * Fill the frame buffer with pixel data from an external buffer 294 * of the same width and height as this frame buffer. 295 * 296 * @param fb External frame buffer 297 * @param conv Pixel conversion helper 298 */ 299 void copyIn(const uint8_t *fb, const PixelConverter &conv); 300 /** 301 * Fill the frame buffer with pixel data from an external buffer 302 * of the same width and height as this frame buffer. 303 * 304 * @param fb External frame buffer 305 * @param conv Pixel conversion helper 306 */ 307 void copyIn(const std::vector<uint8_t> &fb, const PixelConverter &conv) { 308 copyIn(fb.data(), conv); 309 } 310 311 /** 312 * Store the contents of this frame buffer in an external buffer 313 * of the same width and height as this frame buffer. 314 * 315 * @param fb External frame buffer 316 * @param conv Pixel conversion helper 317 */ 318 void copyOut(uint8_t *fb, const PixelConverter &conv) const; 319 /** 320 * Store the contents of this frame buffer in an external buffer 321 * of the same width and height as this frame buffer. 322 * 323 * @param fb External frame buffer 324 * @param conv Pixel conversion helper 325 */ 326 void copyOut(std::vector<uint8_t> &fb, const PixelConverter &conv) const { 327 copyOut(fb.data(), conv); 328 } 329 330 /** 331 * Get a pixel from an (x, y) coordinate 332 * 333 * @param x Distance from the left margin. 334 * @param y Distance from the top of the frame. 335 */ 336 const Pixel &pixel(unsigned x, unsigned y) const { 337 assert(x < _width); 338 assert(y < _height); 339 340 return pixels[y * _width + x]; 341 } 342 343 /** 344 * Get a pixel from an (x, y) coordinate 345 * 346 * @param x Distance from the left margin. 347 * @param y Distance from the top of the frame. 348 */ 349 Pixel &pixel(unsigned x, unsigned y) { 350 assert(x < _width); 351 assert(y < _height); 352 353 return pixels[y * _width + x]; 354 } 355 356 /** 357 * Create a hash of the image that can be used for quick 358 * comparisons. 359 */ 360 uint64_t getHash() const; 361 362 /** 363 * Static "dummy" frame buffer. 364 * 365 * This is a dummy frame buffer that can be used as a place holder 366 * for devices that always expect a frame buffer to be present. 367 */ 368 static const FrameBuffer dummy; 369 370 /** Frame buffer backing store */ 371 std::vector<Pixel> pixels; 372 373 protected: 374 /** Width in pixels */ 375 unsigned _width; 376 /** Height in pixels */ 377 unsigned _height; 378}; 379 380#endif // __BASE_FRAMEBUFFER_HH__ 381