### Execute Main Rendering Loop Source: https://context7.com/mesa/kmscube/llms.txt Implement a rendering loop that handles buffer swapping, page flipping, and event synchronization. ```c #include "common.h" #include "drm-common.h" // Run the main rendering loop // The drm->run function pointer handles mode-specific rendering int result = drm->run(gbm, egl, cube); // Manual rendering loop example (legacy mode): unsigned int frame = 0; struct gbm_bo *bo = NULL; while (frame < drm->count) { // Draw the current frame cube->draw(frame++); // Swap buffers eglSwapBuffers(egl->display, egl->surface); // Get the front buffer struct gbm_bo *next_bo = gbm_surface_lock_front_buffer(gbm->surface); struct drm_fb *fb = drm_fb_get_from_bo(next_bo); // Page flip (waits for vsync) int ret = drmModePageFlip(drm->fd, drm->crtc_id, fb->fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL); if (ret) { printf("page flip failed: %s\n", strerror(errno)); break; } // Wait for page flip event drmHandleEvent(drm->fd, &evctx); // Release previous buffer if (bo) gbm_surface_release_buffer(gbm->surface, bo); bo = next_bo; } ``` -------------------------------- ### Initialize DRM Legacy Mode Source: https://context7.com/mesa/kmscube/llms.txt Initializes the DRM subsystem using legacy modesetting APIs. Requires a valid DRM device path and optional mode parameters. ```c #include "drm-common.h" // Initialize DRM with legacy modesetting // Parameters: // device: DRM device path (e.g., "/dev/dri/card0") or NULL for auto-detect // mode_str: Video mode string (e.g., "1920x1080") or empty for preferred mode // connector_id: Specific connector ID or -1 for auto-detect // vrefresh: Vertical refresh rate (0 for default) // count: Number of frames to render (~0u for unlimited) // nonblocking: true to disable input polling const struct drm *drm = init_drm_legacy( "/dev/dri/card0", // device path "1920x1080", // video mode -1, // auto-detect connector 60, // 60 Hz refresh 1000, // render 1000 frames false // poll for input ); if (!drm) { printf("failed to initialize legacy DRM\n"); return -1; } // Access display mode information printf("Display: %dx%d @ %d Hz\n", drm->mode->hdisplay, drm->mode->vdisplay, drm->mode->vrefresh); ``` -------------------------------- ### Initialize DRM Offscreen Rendering Source: https://context7.com/mesa/kmscube/llms.txt Initializes DRM for headless systems using render nodes. Requires a mode string for resolution and supports optional PNG output. ```c #include "drm-common.h" // Initialize for offscreen rendering (render nodes) // Always requires a mode string for resolution // Set write=true to enable PNG output const struct drm *drm = init_drm_offscreen( NULL, // auto-detect render device "1024x768", // required: output resolution 100, // render 100 frames true // enable PNG file output ); if (!drm) { printf("failed to initialize offscreen DRM\n"); return -1; } // Offscreen mode uses render nodes (/dev/dri/renderD*) instead of // primary nodes, allowing rendering without display access ``` -------------------------------- ### Initialize DRM Atomic Mode Source: https://context7.com/mesa/kmscube/llms.txt Initializes DRM with atomic modesetting for explicit synchronization. Requires kernel and driver support for atomic commits. ```c #include "drm-common.h" // Initialize DRM with atomic modesetting and fence synchronization // Requires kernel and driver support for atomic commits const struct drm *drm = init_drm_atomic( NULL, // auto-detect device "1280x720", // video mode -1, // auto-detect connector 0, // default refresh rate ~0u, // unlimited frames false // blocking mode with input polling ); if (!drm) { printf("failed to initialize atomic DRM\n"); printf("Note: atomic modesetting requires driver support\n"); return -1; } // The atomic interface provides explicit fence synchronization: // - drm->kms_in_fence_fd: GPU completion fence passed to KMS // - drm->kms_out_fence_fd: Display completion fence from KMS ``` -------------------------------- ### Initialize Cube Rendering Modes Source: https://context7.com/mesa/kmscube/llms.txt Initializes different cube rendering modes, including smooth-shaded, textured (RGBA, NV12), gears, shadertoy, and video textures. Requires EGL and GBM to be initialized. ```c #include "common.h" // The cube structure provides a draw callback for rendering const struct cube *cube; // Option 1: Smooth-shaded cube with per-vertex colors and lighting cube = init_cube_smooth(egl, gbm); // Option 2: Textured cube with RGBA or NV12 textures // Modes: RGBA, NV12_2IMG (two textures), NV12_1IMG (single planar) cube = init_cube_tex(egl, gbm, RGBA); // Option 3: Animated gears rendered on each cube face cube = init_cube_gears(egl, gbm); // Option 4: Shadertoy shader (requires GLES3) cube = init_cube_shadertoy(egl, gbm, "shader.glsl"); // Option 5: Video textured cube using GStreamer (requires GST support) cube = init_cube_video(egl, gbm, "video.mp4"); if (!cube) { printf("failed to initialize cube renderer\n"); return -1; } ``` -------------------------------- ### Initialize GBM Buffer Management Source: https://context7.com/mesa/kmscube/llms.txt Initializes the GBM device and creates a rendering surface. Supports both surface-based and surfaceless rendering modes. ```c #include "common.h" // Initialize GBM device and create rendering surface // Parameters: // drm_fd: DRM file descriptor // w, h: Width and height in pixels // format: DRM fourcc format (e.g., DRM_FORMAT_XRGB8888) // modifier: Buffer modifier (DRM_FORMAT_MOD_LINEAR for compatibility) // surfaceless: false for GBM surface, true for explicit buffer objects const struct gbm *gbm = init_gbm( drm->fd, drm->mode->hdisplay, drm->mode->vdisplay, DRM_FORMAT_XRGB8888, // 32-bit RGB format DRM_FORMAT_MOD_LINEAR, // linear layout for compatibility false // use GBM surface (not surfaceless) ); if (!gbm) { printf("failed to initialize GBM\n"); return -1; } // GBM surface for swapchain-style rendering printf("GBM surface: %dx%d format 0x%x\n", gbm->width, gbm->height, gbm->format); // For surfaceless mode, access pre-allocated buffer objects: // gbm->bos[0] and gbm->bos[1] for double-buffering ``` -------------------------------- ### Run kmscube via Command Line Source: https://context7.com/mesa/kmscube/llms.txt Common command line arguments for configuring the kmscube executable. ```bash # Basic usage - smooth shaded rotating cube kmscube # Specify DRM device explicitly kmscube -D /dev/dri/card0 # Set video mode and refresh rate kmscube -v 1920x1080-60 # Use atomic modesetting with explicit fence synchronization kmscube -A # Render textured cube (RGBA format) kmscube -M rgba # Render with NV12 YUV texture (two-image shader conversion) kmscube -M nv12-2img # Render with NV12 YUV texture (single planar EGLImage) kmscube -M nv12-1img # Animated gears mode kmscube -g # Custom Shadertoy shader (requires GLES3) kmscube -S /path/to/shader.glsl # Video textured cube (requires GStreamer) kmscube -V /path/to/video.mp4 # Offscreen rendering with PNG output kmscube -O -v 1024x768 -c 10 -w # Enable 4x MSAA antialiasing kmscube -s 4 ``` -------------------------------- ### Create OpenGL ES Shader Program Source: https://context7.com/mesa/kmscube/llms.txt Compiles and links vertex and fragment shaders to create an OpenGL ES shader program. Retrieves uniform and attribute locations for later use. ```c #include "common.h" // Vertex shader with transformation matrices static const char *vertex_shader_source = "uniform mat4 modelviewMatrix; \n" "uniform mat4 modelviewprojectionMatrix; \n" "attribute vec4 in_position; \n" "attribute vec3 in_normal; \n" "attribute vec4 in_color; \n" "varying vec4 vVaryingColor; \n" "void main() { \n" " gl_Position = modelviewprojectionMatrix * in_position; \n" " vec3 vEyeNormal = mat3(modelviewMatrix) * in_normal; \n" " vec3 lightDir = normalize(vec3(2.0, 2.0, 20.0)); \n" " float diff = max(0.0, dot(vEyeNormal, lightDir)); \n" " vVaryingColor = vec4(diff * in_color.rgb, 1.0); \n" "} \n"; // Fragment shader static const char *fragment_shader_source = "precision mediump float; \n" "varying vec4 vVaryingColor; \n" "void main() { \n" " gl_FragColor = vVaryingColor; \n" "} \n"; // Create and link shader program GLuint program; int ret = create_program(vertex_shader_source, fragment_shader_source, &program); if (ret < 0) { printf("failed to create shader program\n"); return -1; } glUseProgram(program); // Get uniform locations for transformation matrices GLint modelviewLoc = glGetUniformLocation(program, "modelviewMatrix"); GLint mvpLoc = glGetUniformLocation(program, "modelviewprojectionMatrix"); // Get attribute locations GLint positionLoc = glGetAttribLocation(program, "in_position"); GLint normalLoc = glGetAttribLocation(program, "in_normal"); GLint colorLoc = glGetAttribLocation(program, "in_color"); ``` -------------------------------- ### Initialize EGL Context Source: https://context7.com/mesa/kmscube/llms.txt Initializes EGL display, context, and surface for OpenGL ES rendering. Supports optional MSAA. Ensure GBM is initialized before calling. ```c #include "common.h" // Initialize EGL with OpenGL ES 2.0 context // Parameters: // gbm: Initialized GBM structure // samples: MSAA sample count (0 for no antialiasing) struct egl *egl = init_egl(gbm, 4); // 4x MSAA if (!egl) { printf("failed to initialize EGL\n"); return -1; } // EGL is now configured and context is current // Available function pointers for advanced features: // egl->eglCreateImageKHR - Create EGLImage from DMA-BUF // egl->eglDestroyImageKHR - Destroy EGLImage // egl->glEGLImageTargetTexture2DOES - Bind EGLImage to texture // egl->eglCreateSyncKHR - Create sync object (for atomic mode) // egl->eglDupNativeFenceFDANDROID - Export fence as file descriptor // For surfaceless rendering, bind to framebuffer: if (gbm->surface == NULL) { glBindFramebuffer(GL_FRAMEBUFFER, egl->fbs[0].fb); } ``` -------------------------------- ### Capture Frames to PNG Source: https://context7.com/mesa/kmscube/llms.txt Read pixels from the current framebuffer and write them to a PNG file, requiring libpng support. ```c #include "common.h" // Available when built with libpng support (HAVE_LIBPNG) // Used with offscreen rendering mode // Read pixels from framebuffer int width = drm->mode->hdisplay; int height = drm->mode->vdisplay; uint8_t *pixels = malloc(width * height * 4); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Write to PNG file char filename[64]; snprintf(filename, sizeof(filename), "frame_%04d.png", frame_number); write_png_file(filename, width, height, pixels); free(pixels); ``` -------------------------------- ### Manage Framebuffers from GBM Buffers Source: https://context7.com/mesa/kmscube/llms.txt Convert GBM buffer objects into DRM framebuffers for display output, supporting both surface and surfaceless modes. ```c #include "drm-common.h" // Get framebuffer from GBM buffer object // This function handles multiple fallback paths: // 1. drmModeAddFB2WithModifiers (with buffer modifiers) // 2. drmModeAddFB2 (without modifiers) // 3. drmModeAddFB (legacy single-plane) struct gbm_bo *bo; // For GBM surface mode: lock front buffer after eglSwapBuffers if (gbm->surface) { eglSwapBuffers(egl->display, egl->surface); bo = gbm_surface_lock_front_buffer(gbm->surface); } else { // For surfaceless mode: use pre-allocated buffer bo = gbm->bos[frame % NUM_BUFFERS]; } // Convert to DRM framebuffer struct drm_fb *fb = drm_fb_get_from_bo(bo); if (!fb) { printf("failed to get framebuffer from buffer object\n"); return -1; } // fb->fb_id can now be used with drmModeSetCrtc or atomic commit printf("Framebuffer ID: %u\n", fb->fb_id); // Release buffer after page flip (for surface mode only) if (previous_bo && gbm->surface) { gbm_surface_release_buffer(gbm->surface, previous_bo); } ``` -------------------------------- ### Perform 3D Matrix Operations Source: https://context7.com/mesa/kmscube/llms.txt Use ESMatrix utilities to define projection and modelview matrices for 3D transformations. These matrices are uploaded to shaders via glUniformMatrix4fv. ```c #include "esUtil.h" // Create projection matrix (frustum-based perspective) ESMatrix projection; GLfloat aspect = (GLfloat)height / (GLfloat)width; esMatrixLoadIdentity(&projection); esFrustum(&projection, -2.8f, +2.8f, -2.8f * aspect, +2.8f * aspect, 6.0f, 10.0f); // Alternative: field-of-view based perspective ESMatrix perspProj; esMatrixLoadIdentity(&perspProj); esPerspective(&perspProj, 45.0f, (float)width/height, 0.1f, 100.0f); // Create modelview matrix with translation and rotation ESMatrix modelview; esMatrixLoadIdentity(&modelview); esTranslate(&modelview, 0.0f, 0.0f, -8.0f); // Move back esRotate(&modelview, 45.0f + (0.25f * frame), 1.0f, 0.0f, 0.0f); // X rotation esRotate(&modelview, 45.0f - (0.5f * frame), 0.0f, 1.0f, 0.0f); // Y rotation esRotate(&modelview, 10.0f + (0.15f * frame), 0.0f, 0.0f, 1.0f); // Z rotation // Compute combined modelview-projection matrix ESMatrix mvp; esMatrixLoadIdentity(&mvp); esMatrixMultiply(&mvp, &modelview, &projection); // Upload matrices to shader glUniformMatrix4fv(modelviewLoc, 1, GL_FALSE, &modelview.m[0][0]); glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, &mvp.m[0][0]); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.