fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed

Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
This commit is contained in:
2026-05-05 20:20:37 +01:00
parent a5f97b6632
commit f31522130f
81834 changed files with 11051982 additions and 108 deletions
@@ -0,0 +1,54 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(customrendernode LANGUAGES CXX)
find_package(Qt6 REQUIRED COMPONENTS Core GuiPrivate Qml Quick ShaderTools)
qt_standard_project_setup(REQUIRES 6.9)
qt_add_executable(customrendernode WIN32 MACOSX_BUNDLE
main.cpp
customrender.cpp customrender.h
)
target_link_libraries(customrendernode PRIVATE
Qt6::Core
Qt6::GuiPrivate
Qt6::Qml
Qt6::Quick
)
qt_add_qml_module(customrendernode
URI SceneGraphRendering
QML_FILES
main.qml
RESOURCE_PREFIX /scenegraph/customrendernode
NO_RESOURCE_TARGET_PATH
)
qt6_add_shaders(customrendernode "shaders"
# gl_VertexId is in earliest OpenGL ES 3.00, and GLSL 130
GLSL "300 es,130"
PREFIX
"/scenegraph/customrendernode"
FILES
"shaders/customrender.vert"
"shaders/customrender.frag"
)
install(TARGETS customrendernode
BUNDLE DESTINATION .
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
qt_generate_deploy_qml_app_script(
TARGET customrendernode
OUTPUT_SCRIPT deploy_script
MACOS_BUNDLE_POST_BUILD
NO_UNSUPPORTED_PLATFORM_ERROR
DEPLOY_USER_QML_MODULES_ON_UNSUPPORTED_PLATFORM
)
install(SCRIPT ${deploy_script})
@@ -0,0 +1,217 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "customrender.h"
#include <QSGTextureProvider>
#include <QSGRenderNode>
#include <QSGTransformNode>
#include <QQuickWindow>
#include <QFile>
#include <rhi/qrhi.h>
//![node]
class CustomRenderNode : public QSGRenderNode
{
public:
CustomRenderNode(QQuickWindow *window);
void setVertices(const QList<QVector2D> &vertices);
void prepare() override;
void render(const RenderState *state) override;
void releaseResources() override;
RenderingFlags flags() const override;
QSGRenderNode::StateFlags changedStates() const override;
protected:
QQuickWindow *m_window;
std::unique_ptr<QRhiBuffer> m_vertexBuffer;
std::unique_ptr<QRhiBuffer> m_uniformBuffer;
std::unique_ptr<QRhiShaderResourceBindings> m_resourceBindings;
std::unique_ptr<QRhiGraphicsPipeline> m_pipeline;
QList<QRhiShaderStage> m_shaders;
bool m_verticesDirty = true;
QList<QVector2D> m_vertices;
};
//![node]
CustomRenderNode::CustomRenderNode(QQuickWindow *window)
: m_window(window)
{
QFile file;
file.setFileName(":/scenegraph/customrendernode/shaders/customrender.vert.qsb");
if (!file.open(QFile::ReadOnly))
qFatal("Failed to load vertex shader");
m_shaders.append(QRhiShaderStage(QRhiShaderStage::Vertex, QShader::fromSerialized(file.readAll())));
file.close();
file.setFileName(":/scenegraph/customrendernode/shaders/customrender.frag.qsb");
if (!file.open(QFile::ReadOnly))
qFatal("Failed to load fragment shader");
m_shaders.append(QRhiShaderStage(QRhiShaderStage::Fragment, QShader::fromSerialized(file.readAll())));
}
void CustomRenderNode::setVertices(const QList<QVector2D> &vertices)
{
if (m_vertices == vertices)
return;
m_verticesDirty = true;
m_vertices = vertices;
markDirty(QSGNode::DirtyGeometry);
}
//![node-release]
void CustomRenderNode::releaseResources()
{
m_vertexBuffer.reset();
m_uniformBuffer.reset();
m_pipeline.reset();
m_resourceBindings.reset();
}
//![node-release]
//![node-flags]
QSGRenderNode::RenderingFlags CustomRenderNode::flags() const
{
// We are rendering 2D content directly into the scene graph using QRhi, no
// direct usage of a 3D API. Hence NoExternalRendering. This is a minor
// optimization.
// Additionally, the node takes the item transform into account by relying
// on projectionMatrix() and matrix() (see prepare()) and never rendering at
// other Z coordinates. Hence DepthAwareRendering. This is a potentially
// bigger optimization.
return QSGRenderNode::NoExternalRendering | QSGRenderNode::DepthAwareRendering;
}
//![node-flags]
QSGRenderNode::StateFlags CustomRenderNode::changedStates() const
{
// In Qt 6 only ViewportState and ScissorState matter, the rest is ignored.
return QSGRenderNode::StateFlag::ViewportState | QSGRenderNode::StateFlag::CullState;
}
//![node-prepare]
void CustomRenderNode::prepare()
{
QRhi *rhi = m_window->rhi();
QRhiResourceUpdateBatch *resourceUpdates = rhi->nextResourceUpdateBatch();
if (m_verticesDirty) {
m_vertexBuffer.reset();
m_verticesDirty = false;
}
if (!m_vertexBuffer) {
m_vertexBuffer.reset(rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer,
m_vertices.count() * sizeof(QVector2D)));
m_vertexBuffer->create();
resourceUpdates->uploadStaticBuffer(m_vertexBuffer.get(), m_vertices.constData());
}
//![node-prepare]
if (!m_uniformBuffer) {
m_uniformBuffer.reset(rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68));
m_uniformBuffer->create();
}
if (!m_resourceBindings) {
m_resourceBindings.reset(rhi->newShaderResourceBindings());
m_resourceBindings->setBindings({ QRhiShaderResourceBinding::uniformBuffer(
0,
QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
m_uniformBuffer.get()) });
m_resourceBindings->create();
}
if (!m_pipeline) {
m_pipeline.reset(rhi->newGraphicsPipeline());
// If layer.enabled == true on our QQuickItem and layer.textureMirroring is the
// default MirrorVertically, the winding order needs to be inverted when
// isYUpInFrameBuffer == true (OpenGL). This does not happen with other backends,
// unless textureMirroring is changed so that the situation is inverted, meaning
// GL needs no adjustments while others need the opposite winding order. Here we
// choose the replicate, to a degree, what the scenegraph renderer does, but note that
// this is only correct as long as textureMirroring is not changed from the default.
m_pipeline->setFrontFace(renderTarget()->resourceType() == QRhiResource::TextureRenderTarget
&& rhi->isYUpInFramebuffer()
? QRhiGraphicsPipeline::CW
: QRhiGraphicsPipeline::CCW);
m_pipeline->setCullMode(QRhiGraphicsPipeline::Back);
m_pipeline->setTopology(QRhiGraphicsPipeline::TriangleStrip);
QRhiGraphicsPipeline::TargetBlend blend;
blend.enable = true;
m_pipeline->setTargetBlends({ blend });
m_pipeline->setShaderResourceBindings(m_resourceBindings.get());
m_pipeline->setShaderStages(m_shaders.cbegin(), m_shaders.cend());
m_pipeline->setDepthTest(true);
QRhiVertexInputLayout inputLayout;
inputLayout.setBindings({ { 2 * sizeof(float) } });
inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float2, 0 } });
m_pipeline->setVertexInputLayout(inputLayout);
m_pipeline->setRenderPassDescriptor(renderTarget()->renderPassDescriptor());
m_pipeline->create();
}
const QMatrix4x4 mvp = *projectionMatrix() * *matrix();
const float opacity = inheritedOpacity();
resourceUpdates->updateDynamicBuffer(m_uniformBuffer.get(), 0, 64, mvp.constData());
resourceUpdates->updateDynamicBuffer(m_uniformBuffer.get(), 64, 4, &opacity);
commandBuffer()->resourceUpdate(resourceUpdates);
}
//![node-render]
void CustomRenderNode::render(const RenderState *)
{
QRhiCommandBuffer *cb = commandBuffer();
cb->setGraphicsPipeline(m_pipeline.get());
QSize renderTargetSize = renderTarget()->pixelSize();
cb->setViewport(QRhiViewport(0, 0, renderTargetSize.width(), renderTargetSize.height()));
cb->setShaderResources();
QRhiCommandBuffer::VertexInput vertexBindings[] = { { m_vertexBuffer.get(), 0 } };
cb->setVertexInput(0, 1, vertexBindings);
cb->draw(m_vertices.count());
}
//![node-render]
//![item-ctor]
CustomRender::CustomRender(QQuickItem *parent)
: QQuickItem(parent)
{
setFlag(ItemHasContents, true);
connect(this, &CustomRender::verticesChanged, this, &CustomRender::update);
}
//![item-ctor]
QList<QVector2D> CustomRender::vertices() const
{
return m_vertices;
}
void CustomRender::setVertices(const QList<QVector2D> &newVertices)
{
if (m_vertices == newVertices)
return;
m_vertices = newVertices;
emit verticesChanged();
}
//![item-update]
QSGNode *CustomRender::updatePaintNode(QSGNode *old, UpdatePaintNodeData *)
{
CustomRenderNode *node = static_cast<CustomRenderNode *>(old);
if (!node)
node = new CustomRenderNode(window());
node->setVertices(m_vertices);
return node;
}
//![item-update]
@@ -0,0 +1,34 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef CUSTOMRENDER_H
#define CUSTOMRENDER_H
#include <QQuickItem>
#include <QVector2D>
//![item]
class CustomRender : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QList<QVector2D> vertices READ vertices WRITE setVertices NOTIFY verticesChanged)
QML_ELEMENT
public:
explicit CustomRender(QQuickItem *parent = nullptr);
QList<QVector2D> vertices() const;
void setVertices(const QList<QVector2D> &newVertices);
signals:
void verticesChanged();
protected:
QSGNode *updatePaintNode(QSGNode *old, UpdatePaintNodeData *) override;
private:
QList<QVector2D> m_vertices;
};
//![item]
#endif // CUSTOMRENDER_H
@@ -0,0 +1,128 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example scenegraph/customrendernode
\title Scene Graph - Custom QSGRenderNode
\examplecategory {Graphics}
\ingroup qtquickexamples
\brief Shows how to use QSGRenderNode to implement custom rendering in the Qt Quick scenegraph.
The custom render node example shows how to implement a QQuickItem subclass
that is backed by a scene graph node derived from QSGRenderNode, providing
it's own QRhi-based rendering.
\image customrendernode-example.jpg
\note This example demonstrates advanced, low-level functionality performing
portable, cross-platform 3D rendering, while relying on APIs with limited
compatibility guarantee from the Qt Gui module. To be able to use the QRhi
APIs, the application links to \c{Qt::GuiPrivate} and includes
\c{<rhi/qrhi.h>}.
QSGRenderNode allows direct access to the Render Hardware Interface (RHI)
within the scenegraph. This example demonstrates how to create QSGRenderNode
based render node and manage it with a custom item. The render node creates
an RHI pipeline, updates vertex and uniform buffers, and renders into the
RHI command buffer.
In practice this is a portable, cross-platform approach to perform custom
rendering inline with the scenegraph's own rendering, without resorting to a
native 3D API such as OpenGL, Metal, or Vulkan. Rather, the application uses
Qt's graphics and shader abstraction layer.
QSGRenderNode is the enabler for one of the three ways to integrate custom
2D/3D rendering into a Qt Quick scene. The other two options are to perform
the rendering \c before or \c after the Qt Quick scene's own rendering,
or to generate a whole separate render pass targeting a dedicated render
target (a texture) and then have an item in the scene display the texture.
The QSGRenderNode-based approach is similar to the former, in the sense
that no additional render passes or render targets are involved, and allows
injecting custom rendering commands "inline" with the Qt Quick scene's
own rendering.
Refer to the following examples for these three approaches:
\list
\li \l{Scene Graph - RHI Under QML} - Demonstrates an "underlay" approach
based on the \l{QQuickWindow::beforeRendering()} signal. No additional
render pass and resources are needed, but composition and blending with the
rest of the Qt Quick scene is quite limited. Rendering "under" or "over" the
Qt Quick scene is the simplest approach.
\li \l{Scene Graph - RHI Texture Item} - Demonstrates creating a custom
QQuickItem that renders into a texture and displays a quad textured with the
generated content. This is very flexible and allows complete blending and
composition of the resulting 2D image with the rest of the Qt Quick scene.
That comes at the expense of an additional render pass and render target.
\li This example - Demonstrates the "inline" approach, where the Qt Quick
scene graph calls into the custom item and node implementation during the
main render pass. This approach can be great for performance (no extra
render passes, texturing, and blending are involved), but has potential
pitfalls and is the most complicated method.
\endlist
The custom item derives from QQuickItem. Most importantly, it reimplements
\l{QQuickItem::}{updatePaintNode()}.
\snippet scenegraph/customrendernode/customrender.h item
The constructor sets the \l{QQuickItem::}{ItemHasContents} flag to indicate
that this is a visual item.
\snippet scenegraph/customrendernode/customrender.cpp item-ctor
The updatePaintNode() implementation creates an instance of the custom
scenegraph node, if not yet done. The backing QSGNode tree for this item
consists of a single node, an instance of a QSGRenderNode-derived class.
When Qt Quick's threaded rendering model is in use, this function is called
on the render thread with the main thread blocked. That is why it is safe to
access main thread data (such as data stored in QQuickItems). The node, the
instance of the QSGRenderNode subclass, is going to "live on" the render
thread.
\snippet scenegraph/customrendernode/customrender.cpp item-update
The \c CustomRenderNode class derives from QSGRenderNode, reimplementing a
number of virtual functions. To manage QRhi resources (buffers, pipelines,
etc.), smart pointers are quite useful in this case, because the node is
destroyed by the scene graph together with the rest of the scene on the
render thread (if there is one) while the QRhi is still available, and
therefore releasing resources from the destructor or via smart pointers is
legal and safe.
\snippet scenegraph/customrendernode/customrender.cpp node
Well-behaving QSGRenderNode subclasses also reimplement
\l{QSGRenderNode::}{releaseResources()}, which in this case can be a simple
set of reset() calls.
\snippet scenegraph/customrendernode/customrender.cpp node-release
This QSGRenderNode is performing its rendering through the QRhi APIs (and
not directly through OpenGL, Vulkan, Metal, etc.), and it takes the item
transform into account (as it only really does 2D rendering). Hence
specifying the appropriate flags, which may bring a small performance
improvement.
\snippet scenegraph/customrendernode/customrender.cpp node-flags
The prepare() and render() functions are called every time the Qt Quick
scene renders. The first is called when preparing (but not yet recording)
the render pass. This typically creates resources, such as buffers,
textures, and graphics pipelines, if not yet done, and enqueues uploading
data to them.
\snippet scenegraph/customrendernode/customrender.cpp node-prepare
The render() function is called while the recording of a render pass,
targeting either the QQuickWindow's swapchain, or a texture (in case of
layered items, or when within a ShaderEffectSource), is active.
\snippet scenegraph/customrendernode/customrender.cpp node-render
\sa QSGRenderNode, QRhi, {Scene Graph - RHI Under QML}, {Scene Graph - RHI Texture Item}, {Qt Quick Scene Graph}
*/
@@ -0,0 +1,56 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QGuiApplication>
#include <QQuickView>
#include <QSurfaceFormat>
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
// On macOS, request a core profile context in the unlikely case of using OpenGL.
#ifdef Q_OS_MACOS
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setMajorVersion(4);
format.setMinorVersion(1);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
#endif
QQuickView view;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:///scenegraph/customrendernode/main.qml"));
view.setColor(Qt::black);
view.show();
QString api;
switch (view.graphicsApi()) {
case QSGRendererInterface::OpenGL:
api = "RHI OpenGL";
break;
case QSGRendererInterface::Direct3D11:
api = "RHI Direct 3D 11";
break;
case QSGRendererInterface::Direct3D12:
api = "RHI Direct 3D 12";
break;
case QSGRendererInterface::Vulkan:
api = "RHI Vulkan";
break;
case QSGRendererInterface::Metal:
api = "RHI Metal";
break;
case QSGRendererInterface::Null:
api = "RHI Null";
break;
default:
api = "unknown";
break;
}
view.setTitle(QStringLiteral("Custom QSGRenderNode - ") + api);
return app.exec();
}
@@ -0,0 +1,132 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick.Controls
import SceneGraphRendering
Item {
id: root
width: 640
height: 480
SplitView {
anchors.fill: parent
Text {
text: qsTr("Direct")
color: 'white'
SplitView.preferredWidth: root.width/2
Loader {
anchors.fill: parent
sourceComponent: customComponent
}
}
Text {
text: qsTr("Layer")
color: 'white'
SplitView.preferredWidth: root.width/2
Loader {
anchors.fill: parent
sourceComponent: customComponent
onLoaded: item.custom.layer.enabled=true
}
}
}
Text {
id: description
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 20
wrapMode: Text.WordWrap
text: qsTr("This example creates a custom QQuickItem backed by a QSGRenderNode in the scene graph. " +
"The render node is placed in front of a red rectangle, and behind a white rectangle. " +
"Rendering is demonstrated directly into the scenegraph, and as a layered, texture-backed item (layer.enabled set to true). " +
"Opacity and rotation transform changes are exercised as well.")
Rectangle {
z:-1
anchors.fill: parent
anchors.margins: -10
color: 'white'
opacity: 0.5
radius: 10
}
}
Component {
id: customComponent
Item {
id: componentRoot
property alias custom: custom
Rectangle {
width: parent.width/5
height: parent.height/5
anchors.centerIn: parent
color: '#ff0000'
}
SequentialAnimation {
running: true
loops: Animation.Infinite
OpacityAnimator {
target: custom
from: 0
to: 1
duration: 3500
}
OpacityAnimator {
target: custom
from: 1
to: 0
duration: 3500
}
}
RotationAnimation {
target: custom
from: 0
to: 360
running: true
loops: Animation.Infinite
duration: 11000
}
Button {
text: qsTr("Toggle custom item visibility")
onClicked: custom.visible = !custom.visible
}
CustomRender {
id: custom
width: Math.min(parent.width, parent.height)
height: width
anchors.centerIn: parent
property real a: width/2
property real b: Math.sqrt(3.0)*a/2;
vertices: [Qt.vector2d(width/2 - a/2, height/2 + b/3),
Qt.vector2d(width/2 + a/2, height/2 + b/3),
Qt.vector2d(width/2, height/2 - b*2/3)]
}
Rectangle {
width: parent.width/10
height: parent.height/10
anchors.centerIn: parent
color: '#ffffff'
}
}
}
}
@@ -0,0 +1,18 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#version 440
layout(location = 0) in vec3 color;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform buf {
mat4 qt_Matrix;
float qt_Opacity;
};
void main()
{
fragColor = vec4(color, 1.0)*qt_Opacity;
}
@@ -0,0 +1,31 @@
#version 440
layout(location = 0) in vec2 vertex;
layout(location = 0) out vec3 color;
layout(std140, binding = 0) uniform buf {
mat4 qt_Matrix;
float qt_Opacity;
};
out gl_PerVertex { vec4 gl_Position; };
void main()
{
switch (gl_VertexIndex%3) {
case 0:
color = vec3(1.0, 0.0, 0.0);
break;
case 1:
color = vec3(0.0, 1.0, 0.0);
break;
case 2:
color = vec3(0.0, 0.0, 1.0);
break;
}
gl_Position = qt_Matrix * vec4(vertex, 0.0, 1.0);
}