diff options
Diffstat (limited to 'src/dev/pixelpump.hh')
-rw-r--r-- | src/dev/pixelpump.hh | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/dev/pixelpump.hh b/src/dev/pixelpump.hh new file mode 100644 index 000000000..582e1aa18 --- /dev/null +++ b/src/dev/pixelpump.hh @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2015 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Andreas Sandberg + */ + +#ifndef __DEV_PIXELPUMP_HH__ +#define __DEV_PIXELPUMP_HH__ + +#include "base/framebuffer.hh" +#include "sim/clocked_object.hh" + +struct BasePixelPumpParams; + +struct DisplayTimings : public Serializable +{ + /** + * Create a display timing configuration struct + * + * @param width Width of the visible area of the screen. + * @param height Height of the visible area of the screen. + * @param hfp Horizontal front porch in pixel clocks. + * @param h_sync Horizontal sync in pixel clocks. + * @param hbp Horizontal back porch in pixel clocks. + * @param vfp Vertical front porch in scan lines. + * @param v_sync Vertical sync in scan lines. + * @param vbp Vertical back porch in scan lines. + */ + DisplayTimings(unsigned width, unsigned height, + unsigned hbp, unsigned h_sync, unsigned hfp, + unsigned vbp, unsigned v_sync, unsigned vfp); + + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; + + /** How many pixel clocks are required for one line? */ + Cycles cyclesPerLine() const { + return Cycles(hSync + hBackPorch + width + hBackPorch); + } + + /** How many pixel clocks are required for one frame? */ + Cycles cyclesPerFrame() const { + return Cycles(cyclesPerLine() * linesPerFrame()); + } + + /** Calculate the first line of the vsync signal */ + unsigned lineVSyncStart() const { + return 0; + } + + /** Calculate the first line of the vertical back porch */ + unsigned lineVBackPorchStart() const { + return lineVSyncStart() + vSync; + } + + /** Calculate the first line of the visible region */ + unsigned lineFirstVisible() const { + return lineVBackPorchStart() + vBackPorch; + } + + /** Calculate the first line of the back porch */ + unsigned lineFrontPorchStart() const { + return lineFirstVisible() + height; + } + + /** Calculate the total number of lines in a frame */ + unsigned linesPerFrame() const { + return lineFrontPorchStart() + vFrontPorch; + } + + /** Display width in pixels */ + unsigned width; + /** Display height in pixels */ + unsigned height; + + /** Horizontal back porch in pixels */ + unsigned hBackPorch; + /** Horizontal front porch in pixels */ + unsigned hFrontPorch; + /** Horizontal sync signal length in pixels */ + unsigned hSync; + + /** Vertical back porch in lines */ + unsigned vBackPorch; + /** Vertical front porch in lines */ + unsigned vFrontPorch; + /** Vertical sync signal in lines */ + unsigned vSync; + + static const DisplayTimings vga; +}; + +/** + * Timing generator for a pixel-based display. + * + * Pixels are ordered relative to the top left corner of the + * display. Scan lines appear in the following order: + * <ol> + * <li>Vertical Sync (starting at line 0) + * <li>Vertical back porch + * <li>Visible lines + * <li>Vertical front porch + * </ol> + * + * Pixel order within a scan line: + * <ol> + * <li>Horizontal Sync + * <li>Horizontal Back Porch + * <li>Visible pixels + * <li>Horizontal Front Porch + * </ol> + */ +class BasePixelPump + : public EventManager, public Clocked, + public Serializable +{ + public: + BasePixelPump(EventManager &em, ClockDomain &pxl_clk, unsigned pixel_chunk); + virtual ~BasePixelPump(); + + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; + + public: // Public API + /** Starting pushing pixels using the supplied display timings. */ + void start(const DisplayTimings &timings); + + /** Immediately stop pushing pixels */ + void stop(); + + /** Get a constant reference of the current display timings */ + const DisplayTimings &timings() const { return _timings; } + + /** Is the pixel pump active and refreshing the display? */ + bool active() const { return evBeginLine.active(); } + + /** Did a buffer underrun occur within this refresh interval? */ + bool underrun() const { return _underrun; } + + /** Is the current line within the visible range? */ + bool visibleLine() const { + return line >= _timings.lineFirstVisible() && + line < _timings.lineFrontPorchStart(); + } + + /** Current pixel position within the visible area */ + unsigned posX() const { return _posX; } + + /** Current pixel position within the visible area */ + unsigned posY() const { + return visibleLine() ? line - _timings.lineFirstVisible() : 0; + } + + /** Output frame buffer */ + FrameBuffer fb; + + protected: // Callbacks + /** + * Get the next pixel from the scan line buffer. + * + * @param p Output pixel value, undefined on underrun + * @return true on success, false on buffer underrun + */ + virtual bool nextPixel(Pixel &p) = 0; + + /** First pixel clock of the first VSync line. */ + virtual void onVSyncBegin() {}; + + /** + * Callback on the first pixel of the line after the end VSync + * region (typically the first pixel of the vertical back porch). + */ + virtual void onVSyncEnd() {}; + + /** + * Start of the HSync region. + * + * @note This is called even for scan lines outside of the visible + * region. + */ + virtual void onHSyncBegin() {}; + + /** + * Start of the first pixel after the HSync region. + * + * @note This is called even for scan lines outside of the visible + * region. + */ + virtual void onHSyncEnd() {}; + + /** + * Buffer underrun occurred on a frame. + * + * This method is called once if there is buffer underrun while + * refreshing the display. The underrun state is reset on the next + * refresh. + * + * @param x Coordinate within the visible region. + * @param y Coordinate within the visible region. + */ + virtual void onUnderrun(unsigned x, unsigned y) {}; + + /** Finished displaying the visible region of a frame */ + virtual void onFrameDone() {}; + + private: // Params + /** Maximum number of pixels to handle per render callback */ + const unsigned pixelChunk; + + private: + /** + * Callback helper class with suspend support. + * + * Unlike a normal EventWrapper, this class suspends an event on + * drain() and restarts it at drainResume(). The suspend operation + * stores the tick relative to curTick() and then deschedules the + * event. The resume operation schedules the event at curTick() + * plus the relative tick stored when the event was suspended. + */ + class PixelEvent : public Event, public Drainable + { + typedef void (BasePixelPump::* CallbackType)(); + + public: + PixelEvent(const char *name, BasePixelPump *parent, CallbackType func); + + DrainState drain() M5_ATTR_OVERRIDE; + void drainResume() M5_ATTR_OVERRIDE; + + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; + + const std::string name() const M5_ATTR_OVERRIDE { return _name; } + void process() M5_ATTR_OVERRIDE { + (parent.*func)(); + } + + bool active() const { return scheduled() || suspended; } + + private: + void suspend(); + void resume(); + + const std::string _name; + BasePixelPump &parent; + const CallbackType func; + + bool suspended; + Tick relativeTick; + }; + + void beginLine(); + void renderPixels(); + + /** Convenience vector when doing operations on all events */ + std::vector<PixelEvent *> pixelEvents; + + PixelEvent evVSyncBegin; + PixelEvent evVSyncEnd; + PixelEvent evHSyncBegin; + PixelEvent evHSyncEnd; + PixelEvent evBeginLine; + PixelEvent evRenderPixels; + + DisplayTimings _timings; + + /** + * Current line (including back porch, front porch, and vsync) + * within a frame. + */ + unsigned line; + /** X-coordinate within the visible region of a frame */ + unsigned _posX; + + /** Did a buffer underrun occur within this refresh interval? */ + bool _underrun; +}; + +#endif // __DEV_PIXELPUMP_HH__ |