@@ -28,6 +28,25 @@ void Renderer::IncrementCursorTime(const double ns) noexcept
2828 }
2929}
3030
31+ std::pair<uint16_t , uint16_t > Renderer::DrawLine (const uint8_t * lineA, const uint8_t * lineB, uint16_t lineNumber) noexcept
32+ {
33+ m_lineNumber = lineNumber;
34+ if (m_lineNumber == 0 ) [[unlikely]]
35+ {
36+ const uint16_t width = getDisplayWidth (m_displayFormat);
37+ const uint16_t height = GetDisplayHeight ();
38+
39+ m_screen.m_width = m_plane[A].m_width = m_plane[B].m_width = width * 2 ;
40+ m_screen.m_height = m_plane[A].m_height = m_plane[B].m_height = m_backdropPlane.m_height = height;
41+ }
42+
43+ ResetMatte ();
44+
45+ DrawLineBackdrop ();
46+
47+ return DrawLineImpl (lineA, lineB);
48+ }
49+
3150/* * \brief To be called when the whole frame is drawn.
3251 * \return The final screen.
3352 *
@@ -47,288 +66,4 @@ const Plane& Renderer::RenderFrame() noexcept
4766 return m_screen;
4867}
4968
50- /* * \brief Handles the transparency of the current pixel for each plane.
51- * \tparam PLANE The video plane to operate on.
52- * \tparam TRANSPARENT The low 3-bits of the transparency instruction.
53- * \tparam BOOL_FLAG True if bit 3 is 0, false if bit 3 is 1.
54- * \param pixel The ARGB pixel.
55- * TODO: do not compute colorKey if not CLUT.
56- */
57- template <ImagePlane PLANE, Renderer::TransparentIf TRANSPARENT, bool BOOL_FLAG>
58- constexpr void Renderer::HandleTransparency (Pixel& pixel) noexcept
59- {
60- uint32_t color = static_cast <uint32_t >(pixel) & 0x00'FF'FF'FF ;
61- color = clutColorKey (color | m_maskColorRgb[PLANE]);
62- const bool colorKey = color == clutColorKey (m_transparentColorRgb[PLANE] | m_maskColorRgb[PLANE]);
63-
64- pixel.a = PIXEL_FULL_INTENSITY;
65-
66- switch (TRANSPARENT)
67- {
68- case TransparentIf::AlwaysNever: // Always/Never.
69- pixel.a = static_cast <uint8_t >(PIXEL_FULL_INTENSITY + BOOL_FLAG); // Branchless.
70- break ;
71-
72- case TransparentIf::ColorKey: // Color Key.
73- if (colorKey == BOOL_FLAG)
74- pixel.a = PIXEL_TRANSPARENT;
75- break ;
76-
77- case TransparentIf::TransparencyBit: // Transparent Bit.
78- // TODO: currently decodeRGB555 make the pixel visible if the bit is set.
79- // TODO: disable if not RGB555.
80- if ((pixel.a == PIXEL_FULL_INTENSITY) != BOOL_FLAG)
81- pixel.a = PIXEL_TRANSPARENT;
82- break ;
83-
84- case TransparentIf::MatteFlag0: // Matte Flag 0.
85- if (m_matteFlags[A] == BOOL_FLAG)
86- pixel.a = PIXEL_TRANSPARENT;
87- break ;
88-
89- case TransparentIf::MatteFlag1: // Matte Flag 1.
90- if (m_matteFlags[B] == BOOL_FLAG)
91- pixel.a = PIXEL_TRANSPARENT;
92- break ;
93-
94- case TransparentIf::MatteFlag0OrColorKey: // Matte Flag 0 or Color Key.
95- if (m_matteFlags[A] == BOOL_FLAG || colorKey == BOOL_FLAG)
96- pixel.a = PIXEL_TRANSPARENT;
97- break ;
98-
99- case TransparentIf::MatteFlag1OrColorKey: // Matte Flag 1 or Color Key.
100- if (m_matteFlags[B] == BOOL_FLAG || colorKey == BOOL_FLAG)
101- pixel.a = PIXEL_TRANSPARENT;
102- break ;
103-
104- default : // Reserved.
105- std::unreachable ();
106- break ;
107- }
108- }
109-
110- /* * \brief Applies matte and transparency to the two video planes. */
111- void Renderer::HandleMatteAndTransparency (const uint16_t lineNumber) noexcept
112- {
113- const bool booleanA = !bit<3 >(m_transparencyControl[A]);
114- const uint8_t controlA = bits<0 , 2 >(m_transparencyControl[A]);
115-
116- switch (static_cast <TransparentIf>(controlA))
117- {
118- case TransparentIf::AlwaysNever: // Always/Never.
119- if (booleanA)
120- HandleMatteAndTransparencyDispatchB<TransparentIf::AlwaysNever, true >(lineNumber);
121- else
122- HandleMatteAndTransparencyDispatchB<TransparentIf::AlwaysNever, false >(lineNumber);
123- break ;
124-
125- case TransparentIf::ColorKey: // Color Key.
126- if (booleanA)
127- HandleMatteAndTransparencyDispatchB<TransparentIf::ColorKey, true >(lineNumber);
128- else
129- HandleMatteAndTransparencyDispatchB<TransparentIf::ColorKey, false >(lineNumber);
130- break ;
131-
132- case TransparentIf::TransparencyBit: // Transparent Bit.
133- // TODO: currently decodeRGB555 make the pixel visible if the bit is set.
134- // TODO: disable if not RGB555.
135- if (booleanA)
136- HandleMatteAndTransparencyDispatchB<TransparentIf::TransparencyBit, true >(lineNumber);
137- else
138- HandleMatteAndTransparencyDispatchB<TransparentIf::TransparencyBit, false >(lineNumber);
139- break ;
140-
141- case TransparentIf::MatteFlag0: // Matte Flag 0.
142- if (booleanA)
143- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag0, true >(lineNumber);
144- else
145- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag0, false >(lineNumber);
146- break ;
147-
148- case TransparentIf::MatteFlag1: // Matte Flag 1.
149- if (booleanA)
150- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag1, true >(lineNumber);
151- else
152- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag1, false >(lineNumber);
153- break ;
154-
155- case TransparentIf::MatteFlag0OrColorKey: // Matte Flag 0 or Color Key.
156- if (booleanA)
157- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag0OrColorKey, true >(lineNumber);
158- else
159- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag0OrColorKey, false >(lineNumber);
160- break ;
161-
162- case TransparentIf::MatteFlag1OrColorKey: // Matte Flag 1 or Color Key.
163- if (booleanA)
164- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag1OrColorKey, true >(lineNumber);
165- else
166- HandleMatteAndTransparencyDispatchB<TransparentIf::MatteFlag1OrColorKey, false >(lineNumber);
167- break ;
168-
169- default : // Reserved.
170- std::unreachable ();
171- break ;
172- }
173- }
174-
175- /* * \brief Takes the template transparency control of A and mixes it with B's and handle them both. */
176- template <Renderer::TransparentIf TRANSPARENCY_A, bool FLAG_A>
177- void Renderer::HandleMatteAndTransparencyDispatchB (const uint16_t lineNumber) noexcept
178- {
179- const bool booleanB = !bit<3 >(m_transparencyControl[B]);
180- const uint8_t controlB = bits<0 , 2 >(m_transparencyControl[B]);
181-
182- switch (static_cast <TransparentIf>(controlB))
183- {
184- case TransparentIf::AlwaysNever: // Always/Never.
185- if (booleanB)
186- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::AlwaysNever, true >(lineNumber);
187- else
188- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::AlwaysNever, false >(lineNumber);
189- break ;
190-
191- case TransparentIf::ColorKey: // Color Key.
192- if (booleanB)
193- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::ColorKey, true >(lineNumber);
194- else
195- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::ColorKey, false >(lineNumber);
196- break ;
197-
198- case TransparentIf::TransparencyBit: // Transparent Bit.
199- // TODO: currently decodeRGB555 make the pixel visible if the bit is set.
200- // TODO: disable if not RGB555.
201- if (booleanB)
202- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::TransparencyBit, true >(lineNumber);
203- else
204- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::TransparencyBit, false >(lineNumber);
205- break ;
206-
207- case TransparentIf::MatteFlag0: // Matte Flag 0.
208- if (booleanB)
209- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag0, true >(lineNumber);
210- else
211- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag0, false >(lineNumber);
212- break ;
213-
214- case TransparentIf::MatteFlag1: // Matte Flag 1.
215- if (booleanB)
216- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag1, true >(lineNumber);
217- else
218- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag1, false >(lineNumber);
219- break ;
220-
221- case TransparentIf::MatteFlag0OrColorKey: // Matte Flag 0 or Color Key.
222- if (booleanB)
223- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag0OrColorKey, true >(lineNumber);
224- else
225- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag0OrColorKey, false >(lineNumber);
226- break ;
227-
228- case TransparentIf::MatteFlag1OrColorKey: // Matte Flag 1 or Color Key.
229- if (booleanB)
230- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag1OrColorKey, true >(lineNumber);
231- else
232- HandleMatteAndTransparencyLoop<TRANSPARENCY_A, FLAG_A, TransparentIf::MatteFlag1OrColorKey, false >(lineNumber);
233- break ;
234-
235- default : // Reserved.
236- std::unreachable ();
237- break ;
238- }
239- }
240-
241- /* * \brief Actually handles matte and transparency for both planes statically. */
242- template <Renderer::TransparentIf TRANSPARENCY_A, bool FLAG_A, Renderer::TransparentIf TRANSPARENCY_B, bool FLAG_B>
243- void Renderer::HandleMatteAndTransparencyLoop (const uint16_t lineNumber) noexcept
244- {
245- Pixel* planeA = m_plane[A].GetLinePointer (lineNumber);
246- Pixel* planeB = m_plane[B].GetLinePointer (lineNumber);
247-
248- for (uint16_t i = 0 ; i < m_plane[A].m_width ; ++i) // Plane B has the same width.
249- {
250- HandleMatte<A>(i);
251- HandleMatte<B>(i);
252- m_icfLine[A][i] = m_icf[A];
253- m_icfLine[B][i] = m_icf[B];
254- HandleTransparency<A, TRANSPARENCY_A, FLAG_A>(*planeA++);
255- HandleTransparency<B, TRANSPARENCY_B, FLAG_B>(*planeB++);
256- }
257- }
258-
259- /* * \brief Handles the matte flags for the given plane at the given pixel position.
260- * \param pos The current pixel position (in double resolution).
261- */
262- template <ImagePlane PLANE>
263- void Renderer::HandleMatte (uint16_t pos) noexcept
264- {
265- if (!m_matteNumber) // One matte.
266- {
267- if (m_nextMatte[PLANE] >= m_matteControl.size ())
268- return ;
269- }
270- else // Two mattes.
271- {
272- if constexpr (PLANE == A)
273- {
274- if (m_nextMatte[A] >= MATTE_HALF)
275- return ;
276- }
277- else
278- if (m_nextMatte[B] >= m_matteControl.size ())
279- return ;
280- }
281-
282- const uint32_t command = m_matteControl[m_nextMatte[PLANE]];
283- if (matteXPosition (command) > pos)
284- return ;
285-
286- ++m_nextMatte[PLANE];
287-
288- /* TODO: matte flag index changed should be based on its index. V.5.10.2 note 8 */
289- const uint8_t op = matteOp (command);
290- switch (op)
291- {
292- case 0b0000 :
293- m_nextMatte[PLANE] = m_matteControl.size ();
294- break ;
295-
296- case 0b0100 :
297- m_icf[A] = matteICF (command);
298- break ;
299-
300- case 0b0110 :
301- m_icf[B] = matteICF (command);
302- break ;
303-
304- case 0b1000 :
305- m_matteFlags[PLANE] = false ;
306- break ;
307-
308- case 0b1001 :
309- m_matteFlags[PLANE] = true ;
310- break ;
311-
312- case 0b1100 :
313- m_icf[A] = matteICF (command);
314- m_matteFlags[PLANE] = false ;
315- break ;
316-
317- case 0b1101 :
318- m_icf[A] = matteICF (command);
319- m_matteFlags[PLANE] = true ;
320- break ;
321-
322- case 0b1110 :
323- m_icf[B] = matteICF (command);
324- m_matteFlags[PLANE] = false ;
325- break ;
326-
327- case 0b1111 :
328- m_icf[B] = matteICF (command);
329- m_matteFlags[PLANE] = true ;
330- break ;
331- }
332- }
333-
33469} // namespace Video
0 commit comments