misc: Merge branch v20.1.0.3 hotfix into develop
[gem5.git] / src / dev / pixelpump.hh
1 /*
2 * Copyright (c) 2015, 2017 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
38 #ifndef __DEV_PIXELPUMP_HH__
39 #define __DEV_PIXELPUMP_HH__
40
41 #include <vector>
42
43 #include "base/framebuffer.hh"
44 #include "sim/clocked_object.hh"
45
46 struct BasePixelPumpParams;
47
48 struct DisplayTimings : public Serializable
49 {
50 /**
51 * Create a display timing configuration struct
52 *
53 * @param width Width of the visible area of the screen.
54 * @param height Height of the visible area of the screen.
55 * @param hfp Horizontal front porch in pixel clocks.
56 * @param h_sync Horizontal sync in pixel clocks.
57 * @param hbp Horizontal back porch in pixel clocks.
58 * @param vfp Vertical front porch in scan lines.
59 * @param v_sync Vertical sync in scan lines.
60 * @param vbp Vertical back porch in scan lines.
61 */
62 DisplayTimings(unsigned width, unsigned height,
63 unsigned hbp, unsigned h_sync, unsigned hfp,
64 unsigned vbp, unsigned v_sync, unsigned vfp);
65
66 void serialize(CheckpointOut &cp) const override;
67 void unserialize(CheckpointIn &cp) override;
68
69 /** How many pixel clocks are required for one line? */
70 Cycles
71 cyclesPerLine() const
72 {
73 return Cycles(hSync + hBackPorch + width + hBackPorch);
74 }
75
76 /** How many pixel clocks are required for one frame? */
77 Cycles
78 cyclesPerFrame() const
79 {
80 return Cycles(cyclesPerLine() * linesPerFrame());
81 }
82
83 /** Calculate the first line of the vsync signal */
84 unsigned
85 lineVSyncStart() const
86 {
87 return 0;
88 }
89
90 /** Calculate the first line of the vertical back porch */
91 unsigned
92 lineVBackPorchStart() const
93 {
94 return lineVSyncStart() + vSync;
95 }
96
97 /** Calculate the first line of the visible region */
98 unsigned
99 lineFirstVisible() const
100 {
101 return lineVBackPorchStart() + vBackPorch;
102 }
103
104 /** Calculate the first line of the back porch */
105 unsigned
106 lineFrontPorchStart() const
107 {
108 return lineFirstVisible() + height;
109 }
110
111 /** Calculate the total number of lines in a frame */
112 unsigned
113 linesPerFrame() const
114 {
115 return lineFrontPorchStart() + vFrontPorch;
116 }
117
118 /** Display width in pixels */
119 unsigned width;
120 /** Display height in pixels */
121 unsigned height;
122
123 /** Horizontal back porch in pixels */
124 unsigned hBackPorch;
125 /** Horizontal front porch in pixels */
126 unsigned hFrontPorch;
127 /** Horizontal sync signal length in pixels */
128 unsigned hSync;
129
130 /** Vertical back porch in lines */
131 unsigned vBackPorch;
132 /** Vertical front porch in lines */
133 unsigned vFrontPorch;
134 /** Vertical sync signal in lines */
135 unsigned vSync;
136
137 static const DisplayTimings vga;
138 };
139
140 /**
141 * Timing generator for a pixel-based display.
142 *
143 * Pixels are ordered relative to the top left corner of the
144 * display. Scan lines appear in the following order:
145 * <ol>
146 * <li>Vertical Sync (starting at line 0)
147 * <li>Vertical back porch
148 * <li>Visible lines
149 * <li>Vertical front porch
150 * </ol>
151 *
152 * Pixel order within a scan line:
153 * <ol>
154 * <li>Horizontal Sync
155 * <li>Horizontal Back Porch
156 * <li>Visible pixels
157 * <li>Horizontal Front Porch
158 * </ol>
159 */
160 class BasePixelPump
161 : public EventManager, public Clocked,
162 public Serializable
163 {
164 public:
165 BasePixelPump(EventManager &em, ClockDomain &pxl_clk,
166 unsigned pixel_chunk);
167 virtual ~BasePixelPump();
168
169 void serialize(CheckpointOut &cp) const override;
170 void unserialize(CheckpointIn &cp) override;
171
172 public: // Public API
173 /** Update frame size using display timing */
174 void updateTimings(const DisplayTimings &timings);
175
176 /** Render an entire frame in non-caching mode */
177 void renderFrame();
178
179 /** Starting pushing pixels in timing mode */
180 void start();
181
182 /** Immediately stop pushing pixels */
183 void stop();
184
185 /** Get a constant reference of the current display timings */
186 const DisplayTimings &timings() const { return _timings; }
187
188 /** Is the pixel pump active and refreshing the display? */
189 bool active() const { return evBeginLine.active(); }
190
191 /** Did a buffer underrun occur within this refresh interval? */
192 bool underrun() const { return _underrun; }
193
194 /** Is the current line within the visible range? */
195 bool
196 visibleLine() const
197 {
198 return line >= _timings.lineFirstVisible() &&
199 line < _timings.lineFrontPorchStart();
200 }
201
202 /** Current pixel position within the visible area */
203 unsigned posX() const { return _posX; }
204
205 /** Current pixel position within the visible area */
206 unsigned
207 posY() const
208 {
209 return visibleLine() ? line - _timings.lineFirstVisible() : 0;
210 }
211
212 /** Output frame buffer */
213 FrameBuffer fb;
214
215 protected: // Callbacks
216 /**
217 * Get the next pixel from the scan line buffer.
218 *
219 * @param p Output pixel value, undefined on underrun
220 * @return true on success, false on buffer underrun
221 */
222 virtual bool nextPixel(Pixel &p) = 0;
223
224 /**
225 * Get the next line of pixels directly from memory. This is for use from
226 * the renderFrame which is called in non-caching mode.
227 *
228 * The default implementation falls back to calling nextPixel over and
229 * over, but a more efficient implementation could retrieve the entire line
230 * of pixels all at once using fewer access to memory which bypass any
231 * intermediate structures like an incoming FIFO.
232 *
233 * @param ps A vector iterator to store retrieved pixels into.
234 * @param line_length The number of pixels being requested.
235 * @return The number of pixels actually retrieved.
236 */
237 virtual size_t
238 nextLine(std::vector<Pixel>::iterator ps, size_t line_length)
239 {
240 size_t count = 0;
241 while (count < line_length && nextPixel(*ps++))
242 count++;
243 return count;
244 }
245
246 /** First pixel clock of the first VSync line. */
247 virtual void onVSyncBegin() {};
248
249 /**
250 * Callback on the first pixel of the line after the end VSync
251 * region (typically the first pixel of the vertical back porch).
252 */
253 virtual void onVSyncEnd() {};
254
255 /**
256 * Start of the HSync region.
257 *
258 * @note This is called even for scan lines outside of the visible
259 * region.
260 */
261 virtual void onHSyncBegin() {};
262
263 /**
264 * Start of the first pixel after the HSync region.
265 *
266 * @note This is called even for scan lines outside of the visible
267 * region.
268 */
269 virtual void onHSyncEnd() {};
270
271 /**
272 * Buffer underrun occurred on a frame.
273 *
274 * This method is called once if there is buffer underrun while
275 * refreshing the display. The underrun state is reset on the next
276 * refresh.
277 *
278 * @param x Coordinate within the visible region.
279 * @param y Coordinate within the visible region.
280 */
281 virtual void onUnderrun(unsigned x, unsigned y) {};
282
283 /** Finished displaying the visible region of a frame */
284 virtual void onFrameDone() {};
285
286 private: // Params
287 /** Maximum number of pixels to handle per render callback */
288 const unsigned pixelChunk;
289
290 private:
291 /**
292 * Callback helper class with suspend support.
293 *
294 * Unlike a normal EventWrapper, this class suspends an event on
295 * drain() and restarts it at drainResume(). The suspend operation
296 * stores the tick relative to curTick() and then deschedules the
297 * event. The resume operation schedules the event at curTick()
298 * plus the relative tick stored when the event was suspended.
299 */
300 class PixelEvent : public Event, public Drainable
301 {
302 typedef void (BasePixelPump::* CallbackType)();
303
304 public:
305 PixelEvent(const char *name, BasePixelPump *parent, CallbackType func);
306
307 DrainState drain() override;
308 void drainResume() override;
309
310 void serialize(CheckpointOut &cp) const override;
311 void unserialize(CheckpointIn &cp) override;
312
313 const std::string name() const override { return _name; }
314
315 void
316 process() override
317 {
318 (parent.*func)();
319 }
320
321 bool active() const { return scheduled() || suspended; }
322
323 private:
324 void suspend();
325 void resume();
326
327 const std::string _name;
328 BasePixelPump &parent;
329 const CallbackType func;
330
331 bool suspended;
332 Tick relativeTick;
333 };
334
335 void beginLine();
336 void renderPixels();
337
338 /** Fast and event-free line rendering function */
339 void renderLine();
340
341 /** Convenience vector when doing operations on all events */
342 std::vector<PixelEvent *> pixelEvents;
343
344 PixelEvent evVSyncBegin;
345 PixelEvent evVSyncEnd;
346 PixelEvent evHSyncBegin;
347 PixelEvent evHSyncEnd;
348 PixelEvent evBeginLine;
349 PixelEvent evRenderPixels;
350
351 DisplayTimings _timings;
352
353 /**
354 * Current line (including back porch, front porch, and vsync)
355 * within a frame.
356 */
357 unsigned line;
358 /** X-coordinate within the visible region of a frame */
359 unsigned _posX;
360
361 /** Did a buffer underrun occur within this refresh interval? */
362 bool _underrun;
363 };
364
365 #endif // __DEV_PIXELPUMP_HH__