Skip to content

Renderer Plugin Collection

Description

The Renderer plugin collection provides comprehensive cross-platform rendering and visualization capabilities for CVEDIA-RT. It enables video output, user interface rendering, and remote visualization across different graphics APIs and windowing systems, supporting diverse deployment scenarios from high-performance workstations to headless servers.

Key Features

  • Multi-Graphics API Support: DirectX 11, OpenGL 3.0+, and OpenGL ES 2.0 compatibility
  • Cross-Platform Rendering: Windows, Linux, macOS, and mobile platform support
  • Remote Visualization: Network-based remote UI streaming via NetImgui protocol
  • ImGui Integration: Complete Dear ImGui support with docking and multi-viewport capabilities
  • Hardware Acceleration: GPU-accelerated rendering with automatic fallback to software
  • Multi-Monitor Support: Native multi-display configurations with DPI awareness
  • Performance Optimization: Efficient texture streaming and memory management

Use Cases

  • Interactive Applications: Real-time video processing with GUI controls
  • Remote Monitoring: Headless server deployments with remote visualization
  • Multi-Display Setups: Security monitoring across multiple screens
  • Cross-Platform Deployment: Consistent rendering across different operating systems
  • Embedded Systems: Lightweight rendering for edge computing devices

Renderer Implementations

DirectX 11 Renderer

Platform: Windows only
Graphics API: DirectX 11.0+
Performance: High-performance GPU acceleration

Features: - Native Windows integration with Win32 API - Hardware-accelerated rendering via ID3D11Device - Multi-monitor support through DirectX display management - DPI awareness with automatic scaling - Efficient texture streaming via DirectX surfaces

GLFW Renderer

Platform: Windows, Linux, macOS
Graphics API: OpenGL 3.0+ / OpenGL ES 2.0
Performance: Cross-platform hardware acceleration

Features: - Modern OpenGL rendering pipeline - Cross-platform windowing and input handling - Automatic OpenGL version detection and context creation - macOS Core Profile support (OpenGL 3.2 + GLSL 150) - Platform-optimized OpenGL configurations

Remote Renderer

Platform: Multi-platform
Protocol: NetImgui network streaming
Performance: Bandwidth-optimized remote visualization

Features: - Network-based client-server architecture - UDP broadcast discovery for automatic client detection - TCP streaming with configurable compression - Texture downscaling and grayscale conversion for optimization - Multi-client support with headless operation

SDL Renderer

Platform: Windows, Linux, macOS, mobile
Graphics API: OpenGL via SDL2
Performance: Universal compatibility with hardware acceleration

Features: - Comprehensive multimedia support via SDL2 - Mobile platform compatibility - Per-monitor DPI awareness (SDL 2.0.4+) - Cross-platform input handling (keyboard, mouse, gamepad) - Embedded system support

Requirements

Hardware Requirements

DirectX 11 Renderer: - DirectX 11.0 compatible GPU - Windows Display Driver Model (WDDM) drivers - 512MB+ VRAM recommended

OpenGL Renderers (GLFW/SDL): - OpenGL 3.0+ capable GPU or software fallback - Graphics drivers with OpenGL support - 256MB+ VRAM recommended

Remote Renderer: - Network interface (Ethernet/Wi-Fi) - Minimal local graphics requirements - Bandwidth: 1Mbps+ for optimal experience

Software Dependencies

Windows Dependencies:

# DirectX 11
d3d11.lib, dxgi.lib
Windows SDK 10.0+

# GLFW
glfw3.lib, opengl32.lib
Windows graphics drivers

# SDL
SDL2.lib, SDL2main.lib
OpenGL drivers

Linux Dependencies:

# GLFW
sudo apt-get install libglfw3-dev libgl1-mesa-dev

# SDL
sudo apt-get install libsdl2-dev

# Remote
Standard networking libraries

macOS Dependencies:

# GLFW
brew install glfw

# SDL  
brew install sdl2

# System Frameworks
OpenGL.framework, Cocoa.framework

Configuration

Basic Renderer Configuration

{
  "renderer": {
    "type": "dx11",
    "window": {
      "title": "CVEDIA-RT",
      "width": 1920,
      "height": 1080,
      "fullscreen": false,
      "vsync": true
    },
    "performance": {
      "hardwareAcceleration": true,
      "textureStreaming": true,
      "memoryOptimization": true
    }
  }
}

Remote Renderer Configuration

{
  "renderer": {
    "type": "remote",
    "network": {
      "clientPort": 8889,
      "broadcastPort": 49888,
      "enableBroadcast": true,
      "serverName": "CVEDIA-RT Server"
    },
    "optimization": {
      "textureUpdateDelay": 250,
      "downscaleFactor": 4,
      "maxTextureDimension": 768,
      "grayscaleTextures": false,
      "compressionEnabled": true
    },
    "quality": {
      "targetFps": 30,
      "bandwidthLimit": "10Mbps",
      "adaptiveQuality": true
    }
  }
}

Multi-Monitor Configuration

{
  "renderer": {
    "type": "dx11",
    "displays": {
      "primary": {
        "monitor": 0,
        "resolution": [1920, 1080],
        "refreshRate": 60,
        "dpiScaling": "auto"
      },
      "secondary": {
        "monitor": 1,
        "resolution": [1920, 1080],
        "refreshRate": 60,
        "extendedDesktop": true
      }
    }
  }
}

Configuration Schema

Parameter Type Default Description
type string "auto" Renderer type (dx11, glfw, sdl, remote)
window.title string "CVEDIA-RT" Window title text
window.width integer 1920 Initial window width
window.height integer 1080 Initial window height
window.fullscreen boolean false Start in fullscreen mode
window.vsync boolean true Enable vertical synchronization
performance.hardwareAcceleration boolean true Enable GPU acceleration
performance.textureStreaming boolean true Enable optimized texture streaming
network.clientPort integer 8889 Remote renderer client port
network.broadcastPort integer 49888 UDP broadcast discovery port
network.enableBroadcast boolean true Enable automatic server discovery
optimization.textureUpdateDelay integer 250 Milliseconds between texture updates
optimization.downscaleFactor integer 4 Texture downscaling ratio for bandwidth
optimization.maxTextureDimension integer 768 Maximum texture size for streaming
optimization.grayscaleTextures boolean false Convert textures to grayscale
quality.targetFps integer 30 Target frames per second
quality.bandwidthLimit string "10Mbps" Network bandwidth limit
quality.adaptiveQuality boolean true Automatically adjust quality for bandwidth

API Reference

Core Renderer Interface

All renderers implement the unified iface::Renderer interface:

namespace cvedia::rt::iface {
    class Renderer {
    public:
        // Context management
        virtual void setCurrentContext(ImGuiContext* ctx) = 0;
        virtual ImGuiContext* getCurrentContext() = 0;
        virtual void setAllocatorFunctions(ImGuiMemAllocFunc alloc_func, 
                                         ImGuiMemFreeFunc free_func, 
                                         void* user_data) = 0;

        // Texture operations
        virtual void* matToTexture(cv::Mat img) = 0;
        virtual void* matToTexture(std::string const& name, cv::Mat img, bool update) = 0;

        // Window lifecycle
        virtual void createWindow(std::string const& windowTitle, 
                                 int windowWidth, int windowHeight) = 0;
        virtual bool messageLoop() = 0;
        virtual bool startFrame() = 0;
        virtual void endFrame() = 0;
        virtual void cleanup() = 0;

        // Display management
        virtual std::vector<DisplayInfo> getAvailableDisplays() const = 0;
        virtual expected<void> setDisplayConfiguration(const DisplayConfig& config) = 0;
        virtual bool supportsMultiViewport() const = 0;
    };
}

Renderer Factory

namespace cvedia::rt::api::factory {
    class Renderer {
    public:
        static std::unique_ptr<iface::Renderer> create(const std::string& type = "auto");
        static std::vector<std::string> getAvailableRenderers();
        static bool isRendererAvailable(const std::string& type);

        // Registration for plugin system
        static void registerImplementation(const std::string& name, 
                                         std::function<std::unique_ptr<iface::Renderer>()> factory);
    };
}

ImGui Integration API

namespace cvedia::rt::ui {
    // Texture management
    class TextureManager {
    public:
        static void* uploadTexture(const cv::Mat& image);
        static void* updateTexture(void* textureId, const cv::Mat& image);
        static void releaseTexture(void* textureId);
        static cv::Size getTextureSize(void* textureId);
    };

    // Window management
    class WindowManager {
    public:
        static expected<void> createWindow(const std::string& title, 
                                          int width, int height);
        static expected<void> setWindowPosition(int x, int y);
        static expected<void> setWindowSize(int width, int height);
        static bool isWindowMinimized();
        static void setWindowIcon(const cv::Mat& icon);
    };
}

Remote Renderer Network API

namespace cvedia::rt::network {
    class RemoteRenderer {
    public:
        // Server management
        expected<void> startServer(int port = 8889);
        expected<void> stopServer();
        bool isServerRunning() const;

        // Client management
        std::vector<ClientInfo> getConnectedClients() const;
        expected<void> disconnectClient(const std::string& clientId);

        // Broadcasting
        expected<void> enableBroadcast(int port = 49888);
        expected<void> disableBroadcast();

        // Quality control
        void setCompressionLevel(int level); // 0-9
        void setTextureQuality(float quality); // 0.0-1.0
        void enableAdaptiveQuality(bool enable);

        // Statistics
        NetworkStats getNetworkStatistics() const;
        BandwidthInfo getBandwidthUsage() const;
    };
}

Examples

Basic Renderer Setup

#include "api/factory/renderer.h"
#include "interface/renderer.h"

// Create renderer with automatic selection
auto renderer = api::factory::Renderer::create();
if (!renderer) {
    PLOG_ERROR << "Failed to create renderer";
    return -1;
}

// Initialize window
renderer->createWindow("CVEDIA-RT Application", 1920, 1080);

// Main render loop
while (renderer->messageLoop()) {
    if (!renderer->startFrame()) {
        continue;
    }

    // ImGui rendering
    ImGui::Begin("Main Window");
    ImGui::Text("Hello, CVEDIA-RT!");
    ImGui::End();

    // Upload and display texture
    cv::Mat frame = getVideoFrame();
    void* textureId = renderer->matToTexture(frame);

    ImGui::Begin("Video Display");
    ImGui::Image(textureId, ImVec2(640, 480));
    ImGui::End();

    renderer->endFrame();
}

// Cleanup
renderer->cleanup();

Platform-Specific Renderer Creation

// Create DirectX 11 renderer for Windows
#ifdef _WIN32
auto dx11Renderer = api::factory::Renderer::create("dx11");
if (dx11Renderer) {
    PLOG_INFO << "Using DirectX 11 renderer";
}
#endif

// Create GLFW renderer for cross-platform
auto glfwRenderer = api::factory::Renderer::create("glfw");
if (glfwRenderer) {
    PLOG_INFO << "Using GLFW OpenGL renderer";
}

// Create SDL renderer for maximum compatibility
auto sdlRenderer = api::factory::Renderer::create("sdl");
if (sdlRenderer) {
    PLOG_INFO << "Using SDL renderer";
}

Remote Renderer Server Setup

#include "renderer/remote/remote_renderer.h"

// Create and configure remote renderer
auto remoteRenderer = std::make_unique<RemoteRenderer>();

// Configure network settings
remoteRenderer->setClientPort(8889);
remoteRenderer->setBroadcastPort(49888);
remoteRenderer->enableBroadcast(true);

// Configure optimization
remoteRenderer->setTextureUpdateDelay(250);
remoteRenderer->setDownscaleFactor(4);
remoteRenderer->setMaxTextureDimension(768);
remoteRenderer->enableGrayscaleTextures(false);

// Start server
if (auto result = remoteRenderer->startServer(); !result) {
    PLOG_ERROR << "Failed to start remote renderer server: " << result.error();
    return -1;
}

PLOG_INFO << "Remote renderer server started on port 8889";

// Main application loop
while (applicationRunning) {
    if (remoteRenderer->hasConnectedClients()) {
        // Process UI when clients are connected
        if (remoteRenderer->startFrame()) {
            renderUserInterface();
            remoteRenderer->endFrame();
        }
    }

    // Monitor client connections
    auto clients = remoteRenderer->getConnectedClients();
    for (const auto& client : clients) {
        PLOG_INFO << "Client connected: " << client.address << ":" << client.port;
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS
}

// Cleanup
remoteRenderer->stopServer();

Multi-Monitor Display Setup

#include "renderer/display_manager.h"

// Enumerate available displays
auto displays = renderer->getAvailableDisplays();
PLOG_INFO << "Found " << displays.size() << " displays";

for (const auto& display : displays) {
    PLOG_INFO << "Display " << display.id << ": "
              << display.width << "x" << display.height
              << " @ " << display.refreshRate << "Hz"
              << " (DPI: " << display.dpi << ")";
}

// Configure primary display
DisplayConfig primaryConfig;
primaryConfig.displayId = 0;
primaryConfig.resolution = {1920, 1080};
primaryConfig.refreshRate = 60;
primaryConfig.primary = true;

// Configure secondary display
DisplayConfig secondaryConfig;
secondaryConfig.displayId = 1;
secondaryConfig.resolution = {1920, 1080};
secondaryConfig.refreshRate = 60;
secondaryConfig.position = {1920, 0}; // Extended desktop
secondaryConfig.primary = false;

// Apply display configuration
if (auto result = renderer->setDisplayConfiguration(primaryConfig); !result) {
    PLOG_ERROR << "Failed to configure primary display";
}

if (auto result = renderer->setDisplayConfiguration(secondaryConfig); !result) {
    PLOG_ERROR << "Failed to configure secondary display";
}

Texture Streaming Optimization

#include "renderer/texture_streamer.h"

class OptimizedTextureStreamer {
public:
    OptimizedTextureStreamer(iface::Renderer* renderer) : renderer_(renderer) {
        // Initialize texture cache
        textureCache_.reserve(100);
    }

    void* streamTexture(const std::string& name, const cv::Mat& image, bool forceUpdate = false) {
        auto it = textureCache_.find(name);

        if (it != textureCache_.end() && !forceUpdate) {
            // Use cached texture
            return it->second.textureId;
        }

        // Optimize image for streaming
        cv::Mat optimized = optimizeImageForStreaming(image);

        // Upload or update texture
        void* textureId;
        if (it != textureCache_.end()) {
            textureId = renderer_->matToTexture(name, optimized, true);
        } else {
            textureId = renderer_->matToTexture(optimized);

            TextureInfo info;
            info.textureId = textureId;
            info.lastUpdate = std::chrono::steady_clock::now();
            info.size = optimized.size();

            textureCache_[name] = info;
        }

        return textureId;
    }

private:
    cv::Mat optimizeImageForStreaming(const cv::Mat& input) {
        cv::Mat output;

        // Resize if too large
        if (input.cols > maxDimension_ || input.rows > maxDimension_) {
            double scale = static_cast<double>(maxDimension_) / 
                          std::max(input.cols, input.rows);
            cv::resize(input, output, cv::Size(), scale, scale, cv::INTER_LINEAR);
        } else {
            output = input;
        }

        // Convert to grayscale if enabled
        if (grayscaleMode_ && output.channels() == 3) {
            cv::cvtColor(output, output, cv::COLOR_BGR2GRAY);
        }

        return output;
    }

    struct TextureInfo {
        void* textureId;
        std::chrono::steady_clock::time_point lastUpdate;
        cv::Size size;
    };

    iface::Renderer* renderer_;
    std::unordered_map<std::string, TextureInfo> textureCache_;
    int maxDimension_ = 1024;
    bool grayscaleMode_ = false;
};

Performance Monitoring

#include "renderer/performance_monitor.h"

class RendererPerformanceMonitor {
public:
    void recordFrameTime(std::chrono::milliseconds frameTime) {
        frameTimes_.push_back(frameTime);

        if (frameTimes_.size() > 100) {
            frameTimes_.erase(frameTimes_.begin());
        }
    }

    void recordTextureUpload(size_t textureSize, std::chrono::milliseconds uploadTime) {
        textureUploads_.push_back({textureSize, uploadTime});

        if (textureUploads_.size() > 50) {
            textureUploads_.erase(textureUploads_.begin());
        }
    }

    double getAverageFps() const {
        if (frameTimes_.empty()) return 0.0;

        auto totalTime = std::accumulate(frameTimes_.begin(), frameTimes_.end(), 
                                        std::chrono::milliseconds{0});
        double avgTime = totalTime.count() / static_cast<double>(frameTimes_.size());
        return avgTime > 0.0 ? 1000.0 / avgTime : 0.0;
    }

    double getTextureUploadRate() const {
        if (textureUploads_.empty()) return 0.0;

        size_t totalSize = 0;
        auto totalTime = std::chrono::milliseconds{0};

        for (const auto& upload : textureUploads_) {
            totalSize += upload.size;
            totalTime += upload.time;
        }

        double avgTime = totalTime.count() / static_cast<double>(textureUploads_.size());
        double avgSize = totalSize / static_cast<double>(textureUploads_.size());

        return avgTime > 0.0 ? (avgSize / 1024.0) / (avgTime / 1000.0) : 0.0; // KB/s
    }

    void printStatistics() const {
        PLOG_INFO << "Renderer Performance Statistics:";
        PLOG_INFO << "  Average FPS: " << std::fixed << std::setprecision(1) << getAverageFps();
        PLOG_INFO << "  Texture Upload Rate: " << std::fixed << std::setprecision(2) 
                  << getTextureUploadRate() << " KB/s";
    }

private:
    struct TextureUpload {
        size_t size;
        std::chrono::milliseconds time;
    };

    std::vector<std::chrono::milliseconds> frameTimes_;
    std::vector<TextureUpload> textureUploads_;
};

Platform Compatibility

Graphics API Support Matrix

Platform DirectX 11 OpenGL 3.0+ OpenGL ES 2.0 Remote
Windows ✅ Native ✅ GLFW/SDL ✅ SDL ✅ Network
Linux ❌ N/A ✅ GLFW/SDL ✅ SDL ✅ Network
macOS ❌ N/A ✅ GLFW/SDL ❌ N/A ✅ Network
Mobile ❌ N/A ❌ N/A ✅ SDL ✅ Network
Embedded ❌ N/A ⚠️ Limited ✅ SDL ✅ Network

Hardware Acceleration Support

Feature DX11 GLFW SDL Remote
GPU Acceleration ✅ Full ✅ Full ✅ Full ⚠️ Server-side
Multi-GPU ✅ Yes ⚠️ Limited ⚠️ Limited ❌ N/A
Zero-Copy ✅ DirectX ⚠️ OpenGL ⚠️ OpenGL ❌ N/A
Hardware Decode ✅ Yes ✅ Yes ✅ Yes ⚠️ Server-side

Performance Optimization

Texture Management Optimization

// Efficient texture streaming
class TextureStreamOptimizer {
public:
    struct OptimizationSettings {
        int maxTextureDimension = 1024;
        float compressionRatio = 0.8f;
        bool enableCaching = true;
        bool enableDownscaling = true;
        int cacheSize = 100;
    };

    void* optimizeAndUploadTexture(iface::Renderer* renderer,
                                   const cv::Mat& image,
                                   const OptimizationSettings& settings) {

        cv::Mat optimized = image;

        // Apply optimizations
        if (settings.enableDownscaling) {
            optimized = downscaleTexture(optimized, settings.maxTextureDimension);
        }

        if (settings.compressionRatio < 1.0f) {
            optimized = compressTexture(optimized, settings.compressionRatio);
        }

        // Upload to GPU
        return renderer->matToTexture(optimized);
    }

private:
    cv::Mat downscaleTexture(const cv::Mat& input, int maxDimension) {
        if (input.cols <= maxDimension && input.rows <= maxDimension) {
            return input;
        }

        double scale = static_cast<double>(maxDimension) / std::max(input.cols, input.rows);

        cv::Mat output;
        cv::resize(input, output, cv::Size(), scale, scale, cv::INTER_LINEAR);
        return output;
    }

    cv::Mat compressTexture(const cv::Mat& input, float ratio) {
        std::vector<int> compression_params;
        compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
        compression_params.push_back(static_cast<int>(ratio * 100));

        std::vector<uchar> compressed;
        cv::imencode(".jpg", input, compressed, compression_params);

        return cv::imdecode(compressed, cv::IMREAD_COLOR);
    }
};

Memory Management

// GPU memory pool for texture management
class GPUMemoryPool {
public:
    GPUMemoryPool(size_t poolSize) : poolSize_(poolSize) {
        // Pre-allocate texture slots
        texturePool_.reserve(poolSize);
    }

    void* allocateTexture(const cv::Size& size, int channels) {
        std::lock_guard<std::mutex> lock(poolMutex_);

        // Try to find existing texture of same size
        for (auto& slot : texturePool_) {
            if (!slot.inUse && slot.size == size && slot.channels == channels) {
                slot.inUse = true;
                return slot.textureId;
            }
        }

        // Create new texture if pool not full
        if (texturePool_.size() < poolSize_) {
            TextureSlot slot;
            slot.textureId = createNewTexture(size, channels);
            slot.size = size;
            slot.channels = channels;
            slot.inUse = true;

            texturePool_.push_back(slot);
            return slot.textureId;
        }

        // Pool is full, return null
        return nullptr;
    }

    void releaseTexture(void* textureId) {
        std::lock_guard<std::mutex> lock(poolMutex_);

        for (auto& slot : texturePool_) {
            if (slot.textureId == textureId && slot.inUse) {
                slot.inUse = false;
                break;
            }
        }
    }

private:
    struct TextureSlot {
        void* textureId;
        cv::Size size;
        int channels;
        bool inUse = false;
    };

    std::vector<TextureSlot> texturePool_;
    std::mutex poolMutex_;
    size_t poolSize_;

    void* createNewTexture(const cv::Size& size, int channels) {
        // Platform-specific texture creation
        // Implementation depends on graphics API
        return nullptr; // Placeholder
    }
};

Troubleshooting

Common Issues

Graphics Driver Issues

// Check graphics driver compatibility
class GraphicsDriverChecker {
public:
    static bool checkDirectXSupport() {
        #ifdef _WIN32
        // Check DirectX 11 support
        ID3D11Device* device = nullptr;
        HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE,
                                      nullptr, 0, nullptr, 0,
                                      D3D11_SDK_VERSION, &device, nullptr, nullptr);

        if (device) {
            device->Release();
            return SUCCEEDED(hr);
        }
        return false;
        #else
        return false;
        #endif
    }

    static bool checkOpenGLSupport() {
        // Create minimal OpenGL context to check support
        glfwInit();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        GLFWwindow* window = glfwCreateWindow(1, 1, "Test", nullptr, nullptr);

        if (!window) {
            glfwTerminate();
            return false;
        }

        glfwMakeContextCurrent(window);

        const char* version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
        bool supported = version != nullptr;

        glfwDestroyWindow(window);
        glfwTerminate();

        return supported;
    }
};

Memory Leak Prevention

// RAII wrapper for renderer resources
class RendererResourceManager {
public:
    RendererResourceManager(std::unique_ptr<iface::Renderer> renderer) 
        : renderer_(std::move(renderer)) {}

    ~RendererResourceManager() {
        // Cleanup all textures
        for (auto textureId : allocatedTextures_) {
            // Platform-specific texture cleanup
            cleanupTexture(textureId);
        }

        // Cleanup renderer
        if (renderer_) {
            renderer_->cleanup();
        }
    }

    void* createTexture(const cv::Mat& image) {
        void* textureId = renderer_->matToTexture(image);
        if (textureId) {
            allocatedTextures_.insert(textureId);
        }
        return textureId;
    }

    void releaseTexture(void* textureId) {
        if (allocatedTextures_.erase(textureId) > 0) {
            cleanupTexture(textureId);
        }
    }

private:
    std::unique_ptr<iface::Renderer> renderer_;
    std::unordered_set<void*> allocatedTextures_;

    void cleanupTexture(void* textureId) {
        // Platform-specific cleanup implementation
    }
};

Network Issues (Remote Renderer)

// Network diagnostics for remote renderer
class NetworkDiagnostics {
public:
    static bool testNetworkConnectivity(const std::string& host, int port) {
        try {
            // Test TCP connection
            asio::io_context io_context;
            tcp::socket socket(io_context);
            tcp::resolver resolver(io_context);

            auto endpoints = resolver.resolve(host, std::to_string(port));
            asio::connect(socket, endpoints);

            socket.close();
            return true;
        } catch (const std::exception& e) {
            PLOG_ERROR << "Network connectivity test failed: " << e.what();
            return false;
        }
    }

    static double measureLatency(const std::string& host, int port) {
        auto start = std::chrono::high_resolution_clock::now();

        bool connected = testNetworkConnectivity(host, port);

        auto end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

        return connected ? duration.count() / 1000.0 : -1.0; // ms
    }

    static double measureBandwidth(const std::string& host, int port, size_t testDataSize = 1024 * 1024) {
        // Implementation for bandwidth measurement
        // Send test data and measure transfer rate
        return 0.0; // Placeholder
    }
};

Error Recovery

// Robust renderer with automatic recovery
class RobustRenderer {
public:
    RobustRenderer() {
        initializeRenderer();
    }

    bool renderFrame() {
        if (!renderer_) {
            if (!initializeRenderer()) {
                return false;
            }
        }

        try {
            if (!renderer_->startFrame()) {
                handleRenderError();
                return false;
            }

            // Render UI here
            renderUserInterface();

            renderer_->endFrame();
            errorCount_ = 0; // Reset error counter on success
            return true;

        } catch (const std::exception& e) {
            PLOG_ERROR << "Render error: " << e.what();
            handleRenderError();
            return false;
        }
    }

private:
    std::unique_ptr<iface::Renderer> renderer_;
    int errorCount_ = 0;
    static const int maxErrors_ = 5;

    bool initializeRenderer() {
        // Try different renderer types in order of preference
        std::vector<std::string> rendererTypes = {"dx11", "glfw", "sdl", "remote"};

        for (const auto& type : rendererTypes) {
            try {
                renderer_ = api::factory::Renderer::create(type);
                if (renderer_) {
                    renderer_->createWindow("CVEDIA-RT", 1920, 1080);
                    PLOG_INFO << "Successfully initialized " << type << " renderer";
                    return true;
                }
            } catch (const std::exception& e) {
                PLOG_WARNING << "Failed to initialize " << type << " renderer: " << e.what();
            }
        }

        PLOG_ERROR << "Failed to initialize any renderer";
        return false;
    }

    void handleRenderError() {
        errorCount_++;

        if (errorCount_ >= maxErrors_) {
            PLOG_ERROR << "Too many render errors, reinitializing renderer";
            renderer_.reset();
            errorCount_ = 0;
        }
    }

    void renderUserInterface() {
        // Application-specific UI rendering
        ImGui::Begin("Status");
        ImGui::Text("Renderer: %s", renderer_ ? "Active" : "Inactive");
        ImGui::Text("Error Count: %d", errorCount_);
        ImGui::End();
    }
};

Best Practices

Renderer Selection Strategy

  1. Platform Optimization: Use DirectX 11 on Windows for best performance, OpenGL on other platforms
  2. Fallback Chain: Implement automatic fallback from hardware to software rendering
  3. Resource Management: Use RAII patterns for automatic resource cleanup
  4. Error Handling: Implement comprehensive error handling with recovery mechanisms

Performance Guidelines

  1. Texture Management: Use texture caching and pooling for frequently updated images
  2. Memory Optimization: Monitor GPU memory usage and implement cleanup strategies
  3. Frame Rate Management: Implement VSync and frame rate limiting to prevent resource waste
  4. Network Optimization: Use compression and quality adaptation for remote rendering

Integration Best Practices

  1. Factory Pattern: Use the renderer factory for consistent renderer creation
  2. Configuration Management: Centralize renderer configuration through CVEDIA-RT config system
  3. Thread Safety: Ensure thread-safe access to renderer resources
  4. Testing: Validate renderer functionality across different hardware configurations

See Also