C
Monitor: Verifying the Rendering Output
// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial // This file is part of the Qt Safe Renderer module #include "goldencrccalculator.h" #include <QtSafeRenderer/qsafelayoutresourcereader.h> #include <QtSafeRenderer/qsaferenderer.h> #include <QtSafeRenderer/qsafelayout.h> #include <QtSafeRenderer/qsafewindow.h> #include <QtSafeRenderer/qsafesize.h> #include <QtSafeRenderer/qsafepoint.h> #include <QtSafeRenderer/qsafestring.h> #include <QtSafeRenderer/qsafeexceptionhandler.h> #include <QtSafeRenderer/qsafeexceptionhandlerinterface.h> #include "offscreensurface.h" #include <QtSafePlatformAdaptation/outputverifier.h> #include <QtSafePlatformAdaptation/verifyregion.h> #include <QtSafeOutputVerifierAdaptation/calcmisr.h> #include <cstring> #include <new> #include <cstdio> #include <cstdlib> class GoldenCrcCalculatorImpl { public: GoldenCrcCalculatorImpl(SafeRenderer::QSafeLayout *layoutPtr) : m_layout(layoutPtr) , m_surface(m_layout->size()) , m_renderer(&m_surface, m_layout) , m_misrCalculator(*m_surface.framebuffer(), m_layout->size()) { SafeRenderer::QSafeExceptionHandler::installExceptionHandler(&m_exceptionHandler); } qint32 calculateItemCRCById(quint32 itemId, quint32 stateId, quint32* crcOut) { qint32 returnValue = -1; if (crcOut != NULL) { /* Clear then render the item; custom exception handler will abort on errors */ (void)m_renderer.clearBitmap(itemId, false); SafeRenderer::QSafeRect dirtyRect = m_renderer.drawBitmap(itemId); SafeRenderer::VerifyRegion verifyRegion(itemId, stateId, dirtyRect); m_misrCalculator.getCRC(verifyRegion); *crcOut = verifyRegion.crc(); returnValue = 0; } return returnValue; } private: SafeRenderer::QSafeLayout* m_layout; OffscreenSurface m_surface; SafeRenderer::QSafeRenderer m_renderer; SafeRenderer::MISRCalculator m_misrCalculator; class ExceptionHandler : public SafeRenderer::QSafeExceptionHandlerInterface { public: virtual bool onException(const SafeRenderer::QSafeException &exception) { std::fprintf(stderr, "GoldenCrcCalculator fatal error: %s\n", exception.what()); std::abort(); } }; ExceptionHandler m_exceptionHandler; }; // C API Implementation extern "C" { SafeLayoutHandle qsrCreateLayoutFromResource(const qchar* resourcePath) { SafeLayoutHandle layoutHandle = NULL; if (resourcePath != NULL) { // Use QSafeRenderer allocator to allocate the memory from the memory pool. SafeRenderer::quint8 *implMem = SafeRenderer::allocAlignedFromMemoryPool(sizeof(SafeRenderer::QSafeLayoutResourceReader)); SafeRenderer::QSafeLayoutResourceReader *layoutReader = new (implMem) SafeRenderer::QSafeLayoutResourceReader(resourcePath); layoutHandle = layoutReader; } return layoutHandle; } void qsrDestroyLayout(SafeLayoutHandle layoutHandle) { if (layoutHandle != NULL) { SafeRenderer::QSafeLayoutResourceReader *layoutReader = static_cast<SafeRenderer::QSafeLayoutResourceReader *>(layoutHandle); layoutReader->~QSafeLayoutResourceReader(); // The default allocator in QSR does not support dealloc, but this is // used here in case the allocator is customized. SafeRenderer::deallocFromMemoryPool(reinterpret_cast<SafeRenderer::quint8*>(layoutReader)); } } qint32 qsrSetTextForItem(quint32 itemId, const qchar *text, SafeLayoutHandle layoutHandle) { qint32 returnValue = -1; if (layoutHandle != NULL) { SafeRenderer::QSafeLayout *layoutPtr = static_cast<SafeRenderer::QSafeLayout *>(layoutHandle); layoutPtr->setTextForItem(itemId, text); returnValue = 0; } return returnValue; } GoldenCrcCalculatorHandle qsrGoldenCrcCalculatorCreate(SafeLayoutHandle layoutHandle) { GoldenCrcCalculatorHandle crcCalc = NULL; if (layoutHandle != NULL) { // Use QSafeRenderer allocator to allocate the memory from the memory pool. SafeRenderer::QSafeLayout *layoutPtr = static_cast<SafeRenderer::QSafeLayout *>(layoutHandle); SafeRenderer::quint8* implMem = SafeRenderer::allocAlignedFromMemoryPool(sizeof(GoldenCrcCalculatorImpl)); crcCalc = new (implMem) GoldenCrcCalculatorImpl(layoutPtr); } return crcCalc; } void qsrGoldenCrcCalculatorDestroy(GoldenCrcCalculatorHandle handle) { if (handle) { GoldenCrcCalculatorImpl* impl = static_cast<GoldenCrcCalculatorImpl*>(handle); impl->~GoldenCrcCalculatorImpl(); // The default allocator in QSR does not support dealloc, but this is // used here in case the allocator is customized. SafeRenderer::deallocFromMemoryPool(reinterpret_cast<SafeRenderer::quint8*>(impl)); } } qint32 qsrCalculateItemCrc(GoldenCrcCalculatorHandle handle, const quint32 itemId, const quint32 stateId, quint32* crcOut) { qint32 returnValue = -1; if (handle != NULL) { GoldenCrcCalculatorImpl* impl = static_cast<GoldenCrcCalculatorImpl*>(handle); returnValue = impl->calculateItemCRCById(itemId, stateId, crcOut); } return returnValue; } } // extern "C"