ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_drw.c
Go to the documentation of this file.
1
88
89#include <stdint.h>
90#include <stdio.h>
91
92#include "board_periph_block.h"
95
97typedef enum : uint64_t {
98 k_drw_base = 0x40444000UL,
99 k_drw_span = 0x104UL,
100} drw_geom_t;
101
103typedef enum : uint64_t {
108 k_drw_off_size = 0x078UL,
109 k_drw_off_pitch = 0x07CUL,
113} drw_off_t;
114
141
143typedef enum : uint32_t {
146
148typedef enum : uint32_t {
151 k_drw_c2_useacb = (1U << 3U),
152 k_drw_c2_bsfa = (1U << 6U),
153 k_drw_c2_bdfa = (1U << 7U),
154 k_drw_c2_wfmt_hi_bit = (1U << 8U),
155 k_drw_c2_bsf = (1U << 9U),
156 k_drw_c2_bdf = (1U << 10U),
157 k_drw_c2_bsi = (1U << 11U),
158 k_drw_c2_bdi = (1U << 12U),
163 k_drw_c2_bsia = (1U << 28U),
164 k_drw_c2_bdia = (1U << 29U),
165} drw_c2_t;
166
168typedef enum : uint32_t {
171
179
187
205
207typedef enum : uint32_t {
211} drw_bpp_t;
212
219typedef enum : uint32_t {
222
224typedef enum : uint32_t {
227
242typedef struct {
243 uint32_t control;
244 uint32_t control2;
245 uint32_t color1;
246 uint32_t color2;
247 uint32_t size;
248 uint32_t pitch;
249 uint32_t origin;
250 uint32_t cachectl;
251 uint32_t renders;
252 uint32_t skipped;
253 uint32_t last_w;
254 uint32_t last_h;
256
264
277RA8_INTERNAL static uint32_t internal_drw_chan(uint32_t argb, uint32_t shift)
278{
279 return (argb >> shift) & (uint32_t)k_drw_byte_mask;
280}
281
292RA8_INTERNAL static uint32_t internal_drw_bpp(void)
293{
294 const uint32_t lo =
295 (s_drw.control2 >> (uint32_t)k_drw_c2_wfmt_lo_pos) & (uint32_t)k_drw_c2_wfmt_lo_mask;
296 const uint32_t hi = ((s_drw.control2 & (uint32_t)k_drw_c2_wfmt_hi_bit) != 0U) ? 0x4U : 0x0U;
297 switch (lo | hi) {
298 case (uint32_t)k_drw_wfmt_a8:
299 return (uint32_t)k_drw_bpp_8;
300 case (uint32_t)k_drw_wfmt_rgb565:
301 case (uint32_t)k_drw_wfmt_argb4444:
302 return (uint32_t)k_drw_bpp_16;
303 default:
304 /* ARGB8888 and the prohibited codes both take the 32-bit width. */
305 return (uint32_t)k_drw_bpp_32;
306 }
307}
308
335RA8_INTERNAL static uint32_t internal_drw_factor(bool is_alpha, bool invert, uint32_t alpha)
336{
337 if (is_alpha) {
338 return invert ? ((uint32_t)k_drw_alpha_full - alpha) : alpha;
339 }
340 return invert ? 0U : (uint32_t)k_drw_alpha_full;
341}
342
361RA8_INTERNAL static uint32_t internal_drw_mix(uint32_t src, uint32_t dst, uint32_t fs, uint32_t fd)
362{
363 const uint32_t num = (src * fs) + (dst * fd) + (uint32_t)k_drw_alpha_round;
364 const uint32_t out = num / (uint32_t)k_drw_alpha_full;
365 return (out > (uint32_t)k_drw_byte_mask) ? (uint32_t)k_drw_byte_mask : out;
366}
367
380RA8_INTERNAL static uint32_t internal_drw_out_alpha(uint32_t src_a, uint32_t dst_a)
381{
382 if ((s_drw.control2 & (uint32_t)k_drw_c2_useacb) != 0U) {
383 /* HUM Ch 62.6.5.2 "Alpha Channel Blending" p 3734 */
384 const uint32_t fsa = internal_drw_factor((s_drw.control2 & (uint32_t)k_drw_c2_bsfa) != 0U,
385 (s_drw.control2 & (uint32_t)k_drw_c2_bsia) != 0U,
386 src_a);
387 const uint32_t fda = internal_drw_factor((s_drw.control2 & (uint32_t)k_drw_c2_bdfa) != 0U,
388 (s_drw.control2 & (uint32_t)k_drw_c2_bdia) != 0U,
389 src_a);
390 return internal_drw_mix(src_a, dst_a, fsa, fda);
391 }
392 /* HUM Ch 62.2.2 "WRITEALPHA[1:0]" p 3694 -- Figure 62.23 p 3734 */
393 const uint32_t code =
394 (s_drw.control2 >> (uint32_t)k_drw_c2_walpha_pos) & (uint32_t)k_drw_c2_walpha_mask;
395 switch (code) {
396 case (uint32_t)k_drw_walpha_color2:
397 return internal_drw_chan(s_drw.color2, (uint32_t)k_drw_a_shift);
398 case (uint32_t)k_drw_walpha_pixel_cov:
399 return src_a;
400 case (uint32_t)k_drw_walpha_zero:
401 return 0U;
402 default:
403 return dst_a;
404 }
405}
406
418RA8_INTERNAL static uint32_t internal_drw_shade(uint32_t dst)
419{
420 const uint32_t src_a = internal_drw_chan(s_drw.color1, (uint32_t)k_drw_a_shift);
421 const uint32_t fs = internal_drw_factor((s_drw.control2 & (uint32_t)k_drw_c2_bsf) != 0U,
422 (s_drw.control2 & (uint32_t)k_drw_c2_bsi) != 0U,
423 src_a);
424 const uint32_t fd = internal_drw_factor((s_drw.control2 & (uint32_t)k_drw_c2_bdf) != 0U,
425 (s_drw.control2 & (uint32_t)k_drw_c2_bdi) != 0U,
426 src_a);
427
428 const uint32_t r = internal_drw_mix(internal_drw_chan(s_drw.color1, (uint32_t)k_drw_r_shift),
429 internal_drw_chan(dst, (uint32_t)k_drw_r_shift),
430 fs,
431 fd);
432 const uint32_t g = internal_drw_mix(internal_drw_chan(s_drw.color1, (uint32_t)k_drw_g_shift),
433 internal_drw_chan(dst, (uint32_t)k_drw_g_shift),
434 fs,
435 fd);
436 const uint32_t b =
437 internal_drw_mix(internal_drw_chan(s_drw.color1, 0U), internal_drw_chan(dst, 0U), fs, fd);
438 const uint32_t a = internal_drw_out_alpha(src_a, internal_drw_chan(dst, (uint32_t)k_drw_a_shift));
439
440 return (a << (uint32_t)k_drw_a_shift) | (r << (uint32_t)k_drw_r_shift) |
441 (g << (uint32_t)k_drw_g_shift) | b;
442}
443
456RA8_INTERNAL static uint32_t internal_drw_pack(uint32_t argb, uint32_t bpp)
457{
458 if (bpp == (uint32_t)k_drw_bpp_32) {
459 return argb;
460 }
461 const uint32_t a = internal_drw_chan(argb, (uint32_t)k_drw_a_shift);
462 if (bpp == (uint32_t)k_drw_bpp_8) {
463 return a;
464 }
465 const uint32_t r = internal_drw_chan(argb, (uint32_t)k_drw_r_shift);
466 const uint32_t g = internal_drw_chan(argb, (uint32_t)k_drw_g_shift);
467 const uint32_t b = internal_drw_chan(argb, 0U);
468 const uint32_t lo =
469 (s_drw.control2 >> (uint32_t)k_drw_c2_wfmt_lo_pos) & (uint32_t)k_drw_c2_wfmt_lo_mask;
470 if (lo == (uint32_t)k_drw_wfmt_argb4444) {
471 return ((a >> (uint32_t)k_drw_nibble_shift) << (uint32_t)k_drw_argb4444_a_pos) |
472 ((r >> (uint32_t)k_drw_nibble_shift) << (uint32_t)k_drw_g_shift) |
473 ((g >> (uint32_t)k_drw_nibble_shift) << (uint32_t)k_drw_nibble_shift) |
474 (b >> (uint32_t)k_drw_nibble_shift);
475 }
476 return ((r >> (uint32_t)k_drw_r565_shift) << (uint32_t)k_drw_rgb565_r_pos) |
477 ((g >> (uint32_t)k_drw_g565_shift) << (uint32_t)k_drw_rgb565_g_pos) |
478 (b >> (uint32_t)k_drw_r565_shift);
479}
480
500RA8_INTERNAL static bool internal_drw_render_modelled(uint32_t w, uint32_t h)
501{
503 return false; /* Dark domain: writes are lost on silicon. */
504 }
505 if ((w == 0U) || (h == 0U) || (s_drw.pitch == 0U) || (s_drw.origin == 0U)) {
506 return false; /* Nothing programmed yet -- e.g. the init ORIGIN write. */
507 }
508 if ((s_drw.control & (uint32_t)k_drw_control_limiter_mask) != 0U) {
509 return false; /* Limiter semantics uncharacterised -- see file header. */
510 }
511 if ((s_drw.cachectl & (uint32_t)k_drw_cachectl_cenablefx) != 0U) {
512 return false; /* FB cache holds the pixels -- see file header. */
513 }
514 const uint32_t sources = (uint32_t)k_drw_c2_patternenable | (uint32_t)k_drw_c2_textureenable;
515 return (s_drw.control2 & sources) == 0U;
516}
517
527RA8_INTERNAL static void internal_drw_render(uc_engine* uc)
528{
529 const uint32_t w = s_drw.size & (uint32_t)k_drw_size_w_mask;
530 const uint32_t h = (s_drw.size >> (uint32_t)k_drw_size_h_pos) & (uint32_t)k_drw_size_w_mask;
531
532 if (!internal_drw_render_modelled(w, h)) {
533 if ((w != 0U) && (h != 0U) && (s_drw.origin != 0U)) {
534 s_drw.skipped++;
535 }
536 return;
537 }
538
539 const uint32_t bpp = internal_drw_bpp();
540 for (uint32_t row = 0U; row < h; ++row) {
541 const uint64_t line =
542 (uint64_t)s_drw.origin + ((uint64_t)row * (uint64_t)s_drw.pitch * (uint64_t)bpp);
543 for (uint32_t col = 0U; col < w; ++col) {
544 const uint64_t addr = line + ((uint64_t)col * (uint64_t)bpp);
545 uint32_t dst = 0U;
546 (void)emu_mem_read(uc, addr, &dst, (size_t)bpp);
547 const uint32_t out = internal_drw_pack(internal_drw_shade(dst), bpp);
548 (void)emu_mem_write(uc, addr, &out, (size_t)bpp);
549 }
550 }
551 s_drw.renders++;
552 s_drw.last_w = w;
553 s_drw.last_h = h;
554}
555
569RA8_INTERNAL static uint64_t internal_drw_read(uc_engine* uc, uint64_t addr, unsigned size)
570{
571 (void)uc;
572 (void)size;
573 const uint64_t off = addr - (uint64_t)k_drw_base;
574 switch (off) {
575 case (uint64_t)k_drw_off_control:
576 /* HUM Ch 62.2.5 "STATUS: Status Control Register" p 3695. The model
577 * rasterizes synchronously on the ORIGIN write, so the engine is never
578 * observably busy and latches no IRQ or bus error: STATUS reads
579 * all-zero and ra8_drw_wait_idle succeeds on its first poll.
580 *
581 * This MUST return explicitly rather than fall through to HWREVISION:
582 * the two registers are read aliases at different offsets carrying
583 * different values, and sharing an arm made ra8_drw_wait_idle poll
584 * STATUS, see the revision stamp, never observe idle, and time out. */
585 return 0U;
586 case (uint64_t)k_drw_off_control2:
587 /* HUM Ch 62.2.6 "HWREVISION: Hardware Revision Register" p 3696.
588 * Reads 0 while the graphics power domain is gated (HUM Ch 11.2.14
589 * p 452) and 0x0FBE0107 once it is powered -- both bench-captured, so
590 * firmware that skips the power-domain bring-up sees the dead register
591 * here exactly as it does on the bench. */
593 return 0U;
594 }
595 return (uint64_t)k_drw_hwrevision_value;
596 default:
597 /* Every other DRW register is write-only on silicon (HUM Ch 62.2) and
598 * the driver shadows what it needs, so a deterministic zero is both
599 * harmless and faithful. */
600 return 0U;
601 }
602}
603
616RA8_INTERNAL static bool internal_drw_latch(uint64_t off, uint32_t val)
617{
618 switch (off) {
619 case (uint64_t)k_drw_off_control:
620 s_drw.control = val;
621 return true;
622 case (uint64_t)k_drw_off_control2:
623 s_drw.control2 = val;
624 return true;
625 case (uint64_t)k_drw_off_color1:
626 s_drw.color1 = val;
627 return true;
628 case (uint64_t)k_drw_off_color2:
629 s_drw.color2 = val;
630 return true;
631 case (uint64_t)k_drw_off_size:
632 s_drw.size = val;
633 return true;
634 case (uint64_t)k_drw_off_pitch:
635 s_drw.pitch = val;
636 return true;
637 case (uint64_t)k_drw_off_cachectl:
638 s_drw.cachectl = val;
639 return true;
640 default:
641 /* Limiter, texture, CLUT and IRQ registers are accepted and discarded:
642 * the modelled render path does not consume them. */
643 return false;
644 }
645}
646
658RA8_INTERNAL static void internal_drw_dlr_exec_reg(uc_engine* uc, uint32_t index, uint32_t val)
659{
660 const uint64_t off = (uint64_t)index * (uint64_t)k_drw_dlr_bytes_per_word;
661 if (off == (uint64_t)k_drw_off_origin) {
662 /* Same trigger as a CPU ORIGIN write: anchor the box and rasterize. */
663 s_drw.origin = val;
665 return;
666 }
667 (void)internal_drw_latch(off, val);
668}
669
689RA8_INTERNAL static void internal_drw_run_dlist(uc_engine* uc, uint32_t dlist_addr)
690{
691 uint32_t addr = dlist_addr;
692 for (uint32_t fetched = 0U; fetched < (uint32_t)k_drw_dlr_max_words; ++fetched) {
693 uint32_t tag = 0U;
694 (void)emu_mem_read(uc, (uint64_t)addr, &tag, sizeof(tag));
695 addr += (uint32_t)k_drw_dlr_bytes_per_word;
696
697 if ((tag & (uint32_t)k_drw_dlr_b1_boundary) != 0U) {
698 /* One-index entry: byte 0 is a register, one value word follows. */
699 const uint32_t index = tag & (uint32_t)k_drw_dlr_index_mask;
700 if (index == (uint32_t)k_drw_dlr_idx_dliststart) {
701 return; /* display-list jump / stop */
702 }
703 uint32_t val = 0U;
704 (void)emu_mem_read(uc, (uint64_t)addr, &val, sizeof(val));
705 addr += (uint32_t)k_drw_dlr_bytes_per_word;
706 internal_drw_dlr_exec_reg(uc, index, val);
707 continue;
708 }
709 if ((tag & (uint32_t)k_drw_dlr_index_mask) == (uint32_t)k_drw_dlr_eol_low) {
710 /* End-of-list word: byte 1 is the argument. The builder emits only the
711 * pipeline+cache wait (2, a synchronous no-op here); every other value
712 * terminates. */
713 const uint32_t arg =
714 (tag >> (uint32_t)k_drw_dlr_eol_arg_pos) & (uint32_t)k_drw_dlr_index_mask;
715 if (arg == (uint32_t)k_drw_dlr_arg_wait) {
716 continue;
717 }
718 return; /* terminate */
719 }
720 return; /* unmodelled multi-index packing: stop, do not guess */
721 }
722}
723
736RA8_INTERNAL static void
737internal_drw_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
738{
739 (void)size;
740 const uint64_t off = addr - (uint64_t)k_drw_base;
741 const uint32_t val = (uint32_t)value;
742
743 /* While the graphics power domain is gated the block is unpowered and every
744 * write is LOST on silicon (HUM Ch 11.2.14 p 452), so the shadow must not
745 * latch it either -- otherwise firmware that skips the bring-up would
746 * render here and not on the bench. */
748 return;
749 }
750
751 if (off == (uint64_t)k_drw_off_origin) {
752 /* HUM Ch 62.2.31 p 3705: writing ORIGIN both anchors the bounding box and
753 * TRIGGERS the render. */
754 s_drw.origin = val;
756 return;
757 }
758 if (off == (uint64_t)k_drw_off_dliststart) {
759 /* HUM Ch 62.2.32 p 3705: writing DLISTSTART kicks the display-list reader,
760 * which executes the list from RAM (issue #247 loop-stable clear+fill). */
761 internal_drw_run_dlist(uc, val);
762 return;
763 }
764 (void)internal_drw_latch(off, val);
765}
766
776{
777 s_drw = (drw_state_t){};
778}
779
789{
790 if ((s_drw.renders == 0U) && (s_drw.skipped == 0U)) {
791 return;
792 }
793 if (s_drw.skipped != 0U) {
794 /* Loud: an app reached a DRW configuration this model declines to
795 * reproduce, so the emulated framebuffer is NOT what the bench shows. */
796 (void)priv_emu_io_errf(" DRW : %u boxes rasterized (last %ux%u), "
797 "%u DECLINED (limiter / FB-cache / textured path unmodelled)\n",
798 s_drw.renders,
799 s_drw.last_w,
800 s_drw.last_h,
801 s_drw.skipped);
802 return;
803 }
804 (void)priv_emu_io_errf(" DRW : %u boxes rasterized (last %ux%u)\n",
805 s_drw.renders,
806 s_drw.last_w,
807 s_drw.last_h);
808}
809
812 .base = (uint64_t)k_drw_base,
813 .span = (uint64_t)k_drw_span,
814 .order = (uint32_t)k_drw_block_order,
815 .read = internal_drw_read,
817 .tick = nullptr,
818 .reset = internal_drw_reset,
819 .report = internal_drw_report,
820 .name = "DRW",
821};
822
824[[gnu::constructor]] RA8_INTERNAL static void internal_drw_block_register(void)
825{
827}
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
static uint32_t internal_drw_factor(bool is_alpha, bool invert, uint32_t alpha)
Resolve one blend factor to its 0..255 numerator.
static void internal_drw_render(uc_engine *uc)
Rasterize the programmed bounding box into emulated memory.
drw_order_t
Per-tick order slot for the DRW block (relative order only).
@ k_drw_block_order
After the DOC block; report order.
static uint32_t internal_drw_bpp(void)
Framebuffer bytes per pixel for the programmed WRITEFORMAT.
static uint32_t internal_drw_pack(uint32_t argb, uint32_t bpp)
Narrow an ARGB8888 result to the programmed framebuffer format.
static void internal_drw_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the DRW window; ORIGIN or DLISTSTART renders.
drw_cachectl_t
CACHECTL bit-field constants (HUM Ch 62.2.4 p 3694).
@ k_drw_cachectl_cenablefx
Framebuffer cache enable.
drw_dlr_t
Display-list encoding constants (HUM Ch 62.6; TES D/AVE format).
@ k_drw_dlr_idx_dliststart
DLISTSTART index (jump / stop).
@ k_drw_dlr_bytes_per_word
Register index -> byte offset.
@ k_drw_dlr_arg_wait
Wait pipe+cache, keep reading.
@ k_drw_dlr_b1_boundary
Byte 1 bit 7 -> one-index entry.
@ k_drw_dlr_eol_arg_pos
End-of-list argument position.
@ k_drw_dlr_index_mask
Register index in a tag byte.
@ k_drw_dlr_eol_low
Low byte of an end-of-list word.
@ k_drw_dlr_max_words
NASA Rule 2 fetch bound.
drw_layout_t
ARGB8888 channel layout + fixed-point blend constants.
@ k_drw_byte_mask
One colour channel.
@ k_drw_r_shift
ARGB8888 red byte position.
@ k_drw_rgb565_g_pos
RGB565 green position.
@ k_drw_alpha_full
Blend factor 1.0.
@ k_drw_alpha_round
Round-to-nearest bias.
@ k_drw_argb4444_a_pos
ARGB4444 alpha position.
@ k_drw_r565_shift
8 bpc -> 5 bpc.
@ k_drw_g_shift
ARGB8888 green byte position.
@ k_drw_a_shift
ARGB8888 alpha byte position.
@ k_drw_g565_shift
8 bpc -> 6 bpc.
@ k_drw_size_w_mask
SIZE width / height field.
@ k_drw_rgb565_r_pos
RGB565 red position.
@ k_drw_nibble_shift
8 bpc -> 4 bpc.
@ k_drw_size_h_pos
SIZE height in [31:16].
static bool internal_drw_render_modelled(uint32_t w, uint32_t h)
Decide whether this render is one the model reproduces faithfully.
static const board_periph_block_t s_k_drw_block
DRW block descriptor (self-registered with the core).
drw_wfmt_t
WRITEFORMAT[2:0] codes (HUM Ch 62.2.2 p 3692).
@ k_drw_wfmt_argb8888
32 bpp ARGB8888.
@ k_drw_wfmt_rgb565
16 bpp RGB565.
@ k_drw_wfmt_argb4444
16 bpp ARGB4444.
@ k_drw_wfmt_a8
8 bpp A8.
static drw_state_t s_drw
Module-private DRW model state.
drw_control_t
CONTROL bit-field constants (HUM Ch 62.2.1 p 3689).
@ k_drw_control_limiter_mask
LIM1..LIM6 enable bits [5:0].
static void internal_drw_dlr_exec_reg(uc_engine *uc, uint32_t index, uint32_t val)
Apply one display-list register write; ORIGIN triggers a render.
static bool internal_drw_latch(uint64_t off, uint32_t val)
Latch one shadowed DRW register; returns false for unknown offsets.
static void internal_drw_run_dlist(uc_engine *uc, uint32_t dlist_addr)
Execute a display list the DLR fetches from emulated memory.
static uint32_t internal_drw_chan(uint32_t argb, uint32_t shift)
Extract one 8-bit channel of an ARGB8888 word.
static uint64_t internal_drw_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the DRW window.
drw_geom_t
DRW block geometry (ra8_drw_regs.h, HUM Ch 62).
@ k_drw_span
Register window (260 bytes).
@ k_drw_base
DRW Secure base (HUM Ch 62).
drw_hwrev_t
Hardware revision stamp read back from real EK-RA8D2 silicon.
@ k_drw_hwrevision_value
Bench-observed HWREVISION.
static void internal_drw_reset(void)
Reset the DRW model to power-on state.
static void internal_drw_report(void)
End-of-run summary line.
drw_bpp_t
Bytes per framebuffer pixel (HUM Ch 62.3.1.1 p 3707).
@ k_drw_bpp_16
RGB565 / ARGB4444.
@ k_drw_bpp_32
ARGB8888.
@ k_drw_bpp_8
A8.
static void internal_drw_block_register(void)
Register the DRW block before main (host constructor).
static uint32_t internal_drw_mix(uint32_t src, uint32_t dst, uint32_t fs, uint32_t fd)
Apply one channel of src * fs + dst * fd, rounded and saturated.
drw_walpha_t
WRITEALPHA[1:0] codes (HUM Ch 62.2.2 p 3694, USEACB = 0).
@ k_drw_walpha_zero
Forced 0.0.
@ k_drw_walpha_fb
Alpha from framebuffer.
@ k_drw_walpha_pixel_cov
Source alpha (coverage).
@ k_drw_walpha_color2
Alpha from COLOR2.
drw_c2_t
CONTROL2 bit-field constants (HUM Ch 62.2.2 pp 3691-3694).
@ k_drw_c2_bsfa
Alpha src factor is a.
@ k_drw_c2_wfmt_hi_bit
WRITEFORMAT[2].
@ k_drw_c2_wfmt_lo_mask
WRITEFORMAT[1:0] mask.
@ k_drw_c2_bsf
Colour src factor is a.
@ k_drw_c2_bsi
Colour src factor invert.
@ k_drw_c2_walpha_pos
WRITEALPHA[1:0] @ 22.
@ k_drw_c2_textureenable
Texture source.
@ k_drw_c2_patternenable
Pattern source.
@ k_drw_c2_bdia
Alpha dst factor invert.
@ k_drw_c2_bdfa
Alpha dst factor is a.
@ k_drw_c2_useacb
Alpha channel blending.
@ k_drw_c2_bdf
Colour dst factor is a.
@ k_drw_c2_bdi
Colour dst factor invert.
@ k_drw_c2_bsia
Alpha src factor invert.
@ k_drw_c2_wfmt_lo_pos
WRITEFORMAT[1:0] @ 20.
@ k_drw_c2_walpha_mask
WRITEALPHA[1:0] mask.
static uint32_t internal_drw_shade(uint32_t dst)
Composite COLOR1 over one destination pixel, in ARGB8888 space.
static uint32_t internal_drw_out_alpha(uint32_t src_a, uint32_t dst_a)
Framebuffer alpha byte per the WRITEALPHA mux or the alpha blend.
drw_off_t
Register offsets this model tracks (HUM Ch 62.2, ra8_drw_regs.h).
@ k_drw_off_dliststart
W DLISTSTART: kick display list.
@ k_drw_off_color2
W COLOR2: secondary colour.
@ k_drw_off_size
W SIZE: bounding box W/H.
@ k_drw_off_color1
W COLOR1: base colour.
@ k_drw_off_control
W CONTROL / R STATUS.
@ k_drw_off_pitch
W PITCH: framebuffer pitch.
@ k_drw_off_control2
W CONTROL2 / R HWREVISION.
@ k_drw_off_cachectl
W CACHECTL: cache enable / flush.
@ k_drw_off_origin
W ORIGIN: bbox anchor + trigger.
Module-private graphics power-domain state for the gated blocks.
bool priv_board_pdctr_graphics_powered(void)
Report whether the graphics power domain is currently powered.
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
uc_err emu_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t count)
Read guest memory through the central access seam.
uc_err emu_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t count)
Write guest memory through the central access seam.
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
A modelled peripheral block's self-description for the core registry.
Shadow of the write-only DRW register file plus render statistics.
uint32_t origin
ORIGIN: bounding box anchor.
uint32_t color1
COLOR1: source colour.
uint32_t last_h
Height of the last render.
uint32_t skipped
Renders declined as unmodelled.
uint32_t last_w
Width of the last render.
uint32_t control
CONTROL: limiter enables.
uint32_t pitch
PITCH: framebuffer pitch, pixels.
uint32_t color2
COLOR2: secondary colour.
uint32_t size
SIZE: packed bounding box W/H.
uint32_t control2
CONTROL2: format / blend / alpha.
uint32_t cachectl
CACHECTL: cache enables.
uint32_t renders
Bounding boxes rasterized.