mirror of
https://github.com/lupyuen/pinephone-nuttx.git
synced 2025-01-12 20:58:34 +08:00
242 lines
9 KiB
C
242 lines
9 KiB
C
// Test Code for Allwinner A64 Display Engine
|
|
// Add `#include "../../pinephone-nuttx/test/test_a64_de.c"` to the end of this file:
|
|
// https://github.com/apache/nuttx/blob/master/arch/arm64/src/a64/a64_de.c
|
|
|
|
#define CHANNELS 3
|
|
|
|
// TODO: Sync with test.c
|
|
#define PANEL_WIDTH 720
|
|
#define PANEL_HEIGHT 1440
|
|
|
|
#include <nuttx/video/fb.h>
|
|
#include "a64_tcon0.h"
|
|
|
|
static void test_pattern(void);
|
|
|
|
/// NuttX Video Controller for PinePhone (3 UI Channels)
|
|
static struct fb_videoinfo_s videoInfo =
|
|
{
|
|
.fmt = FB_FMT_RGBA32, // Pixel format (XRGB 8888)
|
|
.xres = PANEL_WIDTH, // Horizontal resolution in pixel columns
|
|
.yres = PANEL_HEIGHT, // Vertical resolution in pixel rows
|
|
.nplanes = 1, // Number of color planes supported (Base UI Channel)
|
|
.noverlays = 2 // Number of overlays supported (2 Overlay UI Channels)
|
|
};
|
|
|
|
// Framebuffer 0: (Base UI Channel)
|
|
// Fullscreen 720 x 1440 (4 bytes per XRGB 8888 pixel)
|
|
static uint32_t fb0[PANEL_WIDTH * PANEL_HEIGHT];
|
|
|
|
// Framebuffer 1: (First Overlay UI Channel)
|
|
// Square 600 x 600 (4 bytes per ARGB 8888 pixel)
|
|
#define FB1_WIDTH 600
|
|
#define FB1_HEIGHT 600
|
|
static uint32_t fb1[FB1_WIDTH * FB1_HEIGHT];
|
|
|
|
// Framebuffer 2: (Second Overlay UI Channel)
|
|
// Fullscreen 720 x 1440 (4 bytes per ARGB 8888 pixel)
|
|
static uint32_t fb2[PANEL_WIDTH * PANEL_HEIGHT];
|
|
|
|
/// NuttX Color Plane for PinePhone (Base UI Channel):
|
|
/// Fullscreen 720 x 1440 (4 bytes per XRGB 8888 pixel)
|
|
static struct fb_planeinfo_s planeInfo =
|
|
{
|
|
.fbmem = &fb0, // Start of frame buffer memory
|
|
.fblen = sizeof(fb0), // Length of frame buffer memory in bytes
|
|
.stride = PANEL_WIDTH * 4, // Length of a line in bytes (4 bytes per pixel)
|
|
.display = 0, // Display number (Unused)
|
|
.bpp = 32, // Bits per pixel (XRGB 8888)
|
|
.xres_virtual = PANEL_WIDTH, // Virtual Horizontal resolution in pixel columns
|
|
.yres_virtual = PANEL_HEIGHT, // Virtual Vertical resolution in pixel rows
|
|
.xoffset = 0, // Offset from virtual to visible resolution
|
|
.yoffset = 0 // Offset from virtual to visible resolution
|
|
};
|
|
|
|
/// NuttX Overlays for PinePhone (2 Overlay UI Channels)
|
|
static struct fb_overlayinfo_s overlayInfo[2] =
|
|
{
|
|
// First Overlay UI Channel:
|
|
// Square 600 x 600 (4 bytes per ARGB 8888 pixel)
|
|
{
|
|
.fbmem = &fb1, // Start of frame buffer memory
|
|
.fblen = sizeof(fb1), // Length of frame buffer memory in bytes
|
|
.stride = FB1_WIDTH * 4, // Length of a line in bytes
|
|
.overlay = 0, // Overlay number (First Overlay)
|
|
.bpp = 32, // Bits per pixel (ARGB 8888)
|
|
.blank = 0, // TODO: Blank or unblank
|
|
.chromakey = 0, // TODO: Chroma key argb8888 formatted
|
|
.color = 0, // TODO: Color argb8888 formatted
|
|
.transp = { .transp = 0, .transp_mode = 0 }, // TODO: Transparency
|
|
.sarea = { .x = 52, .y = 52, .w = FB1_WIDTH, .h = FB1_HEIGHT }, // Selected area within the overlay
|
|
.accl = 0 // TODO: Supported hardware acceleration
|
|
},
|
|
// Second Overlay UI Channel:
|
|
// Fullscreen 720 x 1440 (4 bytes per ARGB 8888 pixel)
|
|
{
|
|
.fbmem = &fb2, // Start of frame buffer memory
|
|
.fblen = sizeof(fb2), // Length of frame buffer memory in bytes
|
|
.stride = PANEL_WIDTH * 4, // Length of a line in bytes
|
|
.overlay = 1, // Overlay number (Second Overlay)
|
|
.bpp = 32, // Bits per pixel (ARGB 8888)
|
|
.blank = 0, // TODO: Blank or unblank
|
|
.chromakey = 0, // TODO: Chroma key argb8888 formatted
|
|
.color = 0, // TODO: Color argb8888 formatted
|
|
.transp = { .transp = 0, .transp_mode = 0 }, // TODO: Transparency
|
|
.sarea = { .x = 0, .y = 0, .w = PANEL_WIDTH, .h = PANEL_HEIGHT }, // Selected area within the overlay
|
|
.accl = 0 // TODO: Supported hardware acceleration
|
|
},
|
|
};
|
|
|
|
int pinephone_render_graphics(void)
|
|
{
|
|
// Validate the Framebuffer Sizes at Compile Time
|
|
// ginfo("fb0=%p, fb1=%p, fb2=%p\n", fb0, fb1, fb2);
|
|
DEBUGASSERT(CHANNELS == 1 || CHANNELS == 3);
|
|
DEBUGASSERT(planeInfo.xres_virtual == videoInfo.xres);
|
|
DEBUGASSERT(planeInfo.yres_virtual == videoInfo.yres);
|
|
DEBUGASSERT(planeInfo.fblen == planeInfo.xres_virtual * planeInfo.yres_virtual * 4);
|
|
DEBUGASSERT(planeInfo.stride == planeInfo.xres_virtual * 4);
|
|
DEBUGASSERT(overlayInfo[0].fblen == (overlayInfo[0].sarea.w) * overlayInfo[0].sarea.h * 4);
|
|
DEBUGASSERT(overlayInfo[0].stride == overlayInfo[0].sarea.w * 4);
|
|
DEBUGASSERT(overlayInfo[1].fblen == (overlayInfo[1].sarea.w) * overlayInfo[1].sarea.h * 4);
|
|
DEBUGASSERT(overlayInfo[1].stride == overlayInfo[1].sarea.w * 4);
|
|
|
|
// Init the UI Blender for PinePhone's A64 Display Engine
|
|
int ret = a64_de_blender_init();
|
|
DEBUGASSERT(ret == OK);
|
|
|
|
#ifndef __NuttX__
|
|
// For Local Testing: Only 32-bit addresses allowed
|
|
planeInfo.fbmem = (void *)0x12345678;
|
|
overlayInfo[0].fbmem = (void *)0x23456789;
|
|
overlayInfo[1].fbmem = (void *)0x34567890;
|
|
#endif // !__NuttX__
|
|
|
|
// Init the Base UI Channel
|
|
// https://github.com/lupyuen2/wip-pinephone-nuttx/blob/tcon2/arch/arm64/src/a64/a64_de.c
|
|
ret = a64_de_ui_channel_init(
|
|
1, // UI Channel Number (1 for Base UI Channel)
|
|
planeInfo.fbmem, // Start of Frame Buffer Memory (address should be 32-bit)
|
|
planeInfo.fblen, // Length of Frame Buffer Memory in bytes
|
|
planeInfo.xres_virtual, // Horizontal resolution in pixel columns
|
|
planeInfo.yres_virtual, // Vertical resolution in pixel rows
|
|
planeInfo.xoffset, // Horizontal offset in pixel columns
|
|
planeInfo.yoffset // Vertical offset in pixel rows
|
|
);
|
|
DEBUGASSERT(ret == OK);
|
|
|
|
// Init the 2 Overlay UI Channels
|
|
// https://github.com/lupyuen2/wip-pinephone-nuttx/blob/tcon2/arch/arm64/src/a64/a64_de.c
|
|
int i;
|
|
for (i = 0; i < sizeof(overlayInfo) / sizeof(overlayInfo[0]); i++)
|
|
{
|
|
const struct fb_overlayinfo_s *ov = &overlayInfo[i];
|
|
ret = a64_de_ui_channel_init(
|
|
i + 2, // UI Channel Number (2 and 3 for Overlay UI Channels)
|
|
(CHANNELS == 3) ? ov->fbmem : NULL, // Start of Frame Buffer Memory (address should be 32-bit)
|
|
ov->fblen, // Length of Frame Buffer Memory in bytes
|
|
ov->sarea.w, // Horizontal resolution in pixel columns
|
|
ov->sarea.h, // Vertical resolution in pixel rows
|
|
ov->sarea.x, // Horizontal offset in pixel columns
|
|
ov->sarea.y // Vertical offset in pixel rows
|
|
);
|
|
DEBUGASSERT(ret == OK);
|
|
}
|
|
|
|
// Set UI Blender Route, enable Blender Pipes and apply the settings
|
|
// https://github.com/lupyuen2/wip-pinephone-nuttx/blob/tcon2/arch/arm64/src/a64/a64_de.c
|
|
ret = a64_de_enable(CHANNELS);
|
|
DEBUGASSERT(ret == OK);
|
|
|
|
// Fill Framebuffer with Test Pattern.
|
|
// Must be called after Display Engine is Enabled, or black rows will appear.
|
|
test_pattern();
|
|
|
|
return OK;
|
|
}
|
|
|
|
// Fill the Framebuffers with a Test Pattern.
|
|
// Must be called after Display Engine is Enabled, or black rows will appear.
|
|
static void test_pattern(void)
|
|
{
|
|
// Zero the Framebuffers
|
|
memset(fb0, 0, sizeof(fb0));
|
|
memset(fb1, 0, sizeof(fb1));
|
|
memset(fb2, 0, sizeof(fb2));
|
|
|
|
// Init Framebuffer 0:
|
|
// Fill with Blue, Green and Red
|
|
int i;
|
|
const int fb0_len = sizeof(fb0) / sizeof(fb0[0]);
|
|
for (i = 0; i < fb0_len; i++)
|
|
{
|
|
// Colours are in XRGB 8888 format
|
|
if (i < fb0_len / 4)
|
|
{
|
|
// Blue for top quarter
|
|
fb0[i] = 0x80000080;
|
|
}
|
|
else if (i < fb0_len / 2)
|
|
{
|
|
// Green for next quarter
|
|
fb0[i] = 0x80008000;
|
|
}
|
|
else
|
|
{
|
|
// Red for lower half
|
|
fb0[i] = 0x80800000;
|
|
}
|
|
|
|
// Needed to fix black rows, not sure why
|
|
ARM64_DMB();
|
|
ARM64_DSB();
|
|
ARM64_ISB();
|
|
}
|
|
|
|
// Init Framebuffer 1:
|
|
// Fill with Semi-Transparent White
|
|
const int fb1_len = sizeof(fb1) / sizeof(fb1[0]);
|
|
for (i = 0; i < fb1_len; i++)
|
|
{
|
|
// Colours are in ARGB 8888 format
|
|
fb1[i] = 0x40FFFFFF;
|
|
|
|
// Needed to fix black rows, not sure why
|
|
ARM64_DMB();
|
|
ARM64_DSB();
|
|
ARM64_ISB();
|
|
}
|
|
|
|
// Init Framebuffer 2:
|
|
// Fill with Semi-Transparent Green Circle
|
|
const int fb2_len = sizeof(fb2) / sizeof(fb2[0]);
|
|
int y;
|
|
for (y = 0; y < PANEL_HEIGHT; y++)
|
|
{
|
|
int x;
|
|
for (x = 0; x < PANEL_WIDTH; x++)
|
|
{
|
|
// Get pixel index
|
|
const int p = (y * PANEL_WIDTH) + x;
|
|
DEBUGASSERT(p < fb2_len);
|
|
|
|
// Shift coordinates so that centre of screen is (0,0)
|
|
const int half_width = PANEL_WIDTH / 2;
|
|
const int half_height = PANEL_HEIGHT / 2;
|
|
const int x_shift = x - half_width;
|
|
const int y_shift = y - half_height;
|
|
|
|
// If x^2 + y^2 < radius^2, set the pixel to Semi-Transparent Green
|
|
if (x_shift*x_shift + y_shift*y_shift < half_width*half_width) {
|
|
fb2[p] = 0x80008000; // Semi-Transparent Green in ARGB 8888 Format
|
|
} else { // Otherwise set to Transparent Black
|
|
fb2[p] = 0x00000000; // Transparent Black in ARGB 8888 Format
|
|
}
|
|
|
|
// Needed to fix black rows, not sure why
|
|
ARM64_DMB();
|
|
ARM64_DSB();
|
|
ARM64_ISB();
|
|
}
|
|
}
|
|
}
|