summaryrefslogtreecommitdiff
path: root/src/dev/pixelpump.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev/pixelpump.hh')
-rw-r--r--src/dev/pixelpump.hh312
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__