LinuxDRMEntryPoint

 /*!*********************************************************************************************************************
 \File         OpenGLESHelloAPI_LinuxDRM.cpp
 \Title        OpenGL ES 2.0 HelloAPI Tutorial
 \Author       PowerVR by Imagination, Developer Technology Team
 \Copyright    Copyright (c) Imagination Technologies Limited.
 \Description  Basic Tutorial that shows step-by-step how to initialise OpenGL ES 2.0, use it for drawing a triangle and terminate it.
 			   Entry Point: main
 ***********************************************************************************************************************/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
 #include "OpenGLESHelloAPI.h"
 
 #define DRIDEVNAME "/dev/dri/card0"
 
 struct DRMVariables
 {
 	unsigned int drmDisplayId;
 	int drmFile;
 	unsigned int drmCrtcId;
 	unsigned int drmConnectorId;
 	unsigned int drmEncoderId;
 	drmModeResPtr drmResources;
 	drmModeCrtcPtr drmCrtc;
 	drmModeEncoderPtr drmEncoder;
 	drmModeModeInfoPtr drmMode;
 	drmModeConnectorPtr drmConnector;
 
 	OpenGLESAPI helloAPI;
 
 	DRMVariables()
 		: drmDisplayId(0), drmFile(0), drmCrtcId(0), drmConnectorId(0), drmEncoderId(0), drmResources(NULL), drmCrtc(NULL), drmEncoder(NULL), drmMode(NULL), drmConnector(NULL)
 	{}
 };
 

Helper function used in RenderScene.

 struct SDrmFbWrapper
 {
 	struct gbm_bo* psGbmBo;
 	unsigned int ui32FbId;
 	int i32Fd;
 };
 
 /*******************************************************************************************************************************************
  Helper Functions
 ***********************************************************************************************************************/
 static void pfnCallbackDrmFbDestroy(struct gbm_bo* bo, void* data)
 {
 	struct SDrmFbWrapper* psFb = (struct SDrmFbWrapper*)data;
 
 	if (psFb->ui32FbId)
 	{
 		drmModeRmFB(psFb->i32Fd, psFb->ui32FbId);
 	}
 
 	delete psFb;
 }
 
 static void pfnCallbackDrmPageFlip(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void* data)
 {
 	int* pi32WaitFlip = (int*)data;
 	*pi32WaitFlip = 0;
 }
 
 struct SDrmFbWrapper* DrmFbGetFromBo(DRMVariables& data, struct gbm_bo* bo)
 {
 	struct SDrmFbWrapper* fb = (struct SDrmFbWrapper*)gbm_bo_get_user_data(bo);
 	uint32_t width, height, stride, handle;
 	int ret;
 
 	if (fb)
 	{
 		return fb;
 	}
 
 	fb = new struct SDrmFbWrapper;
 	fb->psGbmBo = bo;
 	fb->i32Fd = data.drmFile;
 
 	width = gbm_bo_get_width(bo);
 	height = gbm_bo_get_height(bo);
 	stride = gbm_bo_get_stride(bo);
 	handle = gbm_bo_get_handle(bo).u32;
 
 	ret = drmModeAddFB(data.drmFile, width, height, 24, 32, stride, handle, &fb->ui32FbId);
 
 	if (ret)
 	{
 		delete fb;
 		return NULL;
 	}
 
 	gbm_bo_set_user_data(bo, fb, pfnCallbackDrmFbDestroy);
 	return fb;
 }
 
 /*******************************************************************************************************************************************
  Application Functions
 ***********************************************************************************************************************/
 
 /*!*********************************************************************************************************************
 \Function		CreateNativeDisplay
 \Output		data Variables used for the windowing system
 \Return		Whether the function succeeded or not.
 \Description	Creates a native isplay for the application to render into.
 ***********************************************************************************************************************/
 bool CreateNativeDevice(DRMVariables& data)
 {
 	/*
 		In the future it may be possible to get the drm device from udev.
 		By default just use card0.
 	*/
 	if ((data.drmFile = open(DRIDEVNAME, O_RDWR)) < 0)
 	{
 		printf("failed to open drm device %s : %s\n", DRIDEVNAME, strerror(errno));
 		return false;
 	}
 
 	data.drmResources = drmModeGetResources(data.drmFile);
 
 	if (!data.drmResources)
 	{
 		drmClose(data.drmFile);
 		printf("drmModeGetResources failed: %s\n", strerror(errno));
 		return false;
 	}
 

Find a connected connector.

 	unsigned int drmDisplayId = 0;
 	bool found = false;
 
 	for (int i = 0; i < data.drmResources->count_connectors; ++i)
 	{
 		data.drmConnector = drmModeGetConnector(data.drmFile, data.drmResources->connectors[i]);
 
 		if (data.drmConnector->connection != DRM_MODE_CONNECTED)
 		{
 			drmModeFreeConnector(data.drmConnector);
 			continue;
 		}
 
 		if (drmDisplayId == 0)
 		{
 			found = true;
 			break;
 		}
 
 		if (drmDisplayId == data.drmConnector->connector_id)
 		{
 			found = true;
 			break;
 		}
 	}
 
 	if (found == false)
 	{
 		drmModeFreeResources(data.drmResources);
 		drmClose(data.drmFile);
 		printf("No Connector found for requested device\n");
 		return false;
 	}
 
 	data.drmConnectorId = data.drmConnector->connector_id;
 	data.drmMode = &data.drmConnector->modes[0];
 
 	found = false;
 
 	for (int j = 0; j < data.drmResources->count_encoders; ++j)
 	{
 		data.drmEncoder = drmModeGetEncoder(data.drmFile, data.drmResources->encoders[j]);
 
 		if (data.drmEncoder->encoder_id == data.drmConnector->encoder_id)
 		{
 			found = true;
 			break;
 		}
 
 		drmModeFreeEncoder(data.drmEncoder);
 	}
 
 	if (!found)
 	{
 		drmModeFreeConnector(data.drmConnector);
 		drmModeFreeResources(data.drmResources);
 		drmClose(data.drmFile);
 		printf("No Encoder found for requested Connector\n");
 		return false;
 	}
 
 	data.drmEncoderId = data.drmEncoder->encoder_id;
 	data.drmCrtcId = data.drmEncoder->crtc_id;
 
 	for (int j = 0; j < data.drmResources->count_crtcs; ++j)
 	{
 		data.drmCrtc = drmModeGetCrtc(data.drmFile, data.drmResources->crtcs[j]);
 
 		if (data.drmCrtc->crtc_id == data.drmCrtcId)
 		{
 			break;
 		}
 
 		drmModeFreeCrtc(data.drmCrtc);
 	}
 
 	data.helloAPI._surfaceData.deviceContext = gbm_create_device(data.drmFile);
 	return true;
 }
 
 /*!*********************************************************************************************************************
 \Function		CreateNativeWindow
  @Input			data Variables used for the windowing system
 \Return		Whether the function succeeded or not.
 \Description	Creates a native window for the application to render into.
 ***********************************************************************************************************************/
 bool CreateNativeWindow(DRMVariables& data)
 {
 	data.helloAPI._surfaceData.window =
 		gbm_surface_create(data.helloAPI._surfaceData.deviceContext, data.drmMode->hdisplay, data.drmMode->vdisplay, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
 
 	return true;
 }
 
 /*!*********************************************************************************************************************
 \Function		ReleaseWindowAndDisplay
  @Input			data Variables used for the windowing system
 \Description	Releases all resources allocated by the windowing system
 ***********************************************************************************************************************/
 void ReleaseNativeResources(DRMVariables& data)
 {
 	gbm_surface_destroy(data.helloAPI._surfaceData.window);
 	gbm_device_destroy(data.helloAPI._surfaceData.deviceContext);
 	drmModeFreeCrtc(data.drmCrtc);
 	drmModeFreeEncoder(data.drmEncoder);
 	drmModeFreeConnector(data.drmConnector);
 	drmModeFreeResources(data.drmResources);
 	drmClose(data.drmFile);
 }
 
 /*!*********************************************************************************************************************
 \Function		main
  @Input			argc                        Number of arguments passed to the application, ignored.
  @Input			argv           Command line strings passed to the application, ignored.
 \Return		Result code to send to the Operating System
 \Description	Main function of the program, executes other functions.
 ***********************************************************************************************************************/
 int main(int /*argc*/, char** /*argv*/)
 {

Structure for the DRM variables.

 	DRMVariables data;
 

Get access to a native display.

 	CreateNativeDevice(data);
 

Setup the windowing system, create a window.

 	CreateNativeWindow(data);
 
 	data.helloAPI.initializeEGL();
 	data.helloAPI.initializeGLES();
 

Renders a triangle for 800 frames using the state setup in the previous function.

 	for (int i = 0; i < 800; ++i)
 	{
 		if (!data.helloAPI.drawFrame() || !data.helloAPI.swapEGLBuffers())
 		{
 			break;
 		}
 

Perform the flip.

 		struct gbm_bo* bo = gbm_surface_lock_front_buffer(data.helloAPI._surfaceData.window);
 		struct SDrmFbWrapper* fb = DrmFbGetFromBo(data, bo);
 
 		int ret = drmModeSetCrtc(data.drmFile, data.drmCrtcId, fb->ui32FbId, 0, 0, &data.drmConnectorId, 1, data.drmMode);
 
 		if (ret)
 		{
 			printf("display failed to set mode: %s\n", strerror(errno));
 			break;
 		}
 	}
 
 	data.helloAPI.releaseGLState();
 	data.helloAPI.releaseEGLState();
 

Release the windowing system resources.

 	ReleaseNativeResources(data);
 

Destroy the eglWindow.

 	return 0;
 }