|
@@ -48,11 +48,11 @@
|
|
*
|
|
*
|
|
**********************************************************************************************/
|
|
**********************************************************************************************/
|
|
|
|
|
|
-#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
|
|
|
-#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
|
|
|
-#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
|
|
|
-#include <pthread.h> // POSIX threads management (inputs reading)
|
|
|
|
-#include <dirent.h> // POSIX directory browsing
|
|
|
|
|
|
+#include <fcntl.h> // POSIX file control definitions - open(), creat(), fcntl()
|
|
|
|
+#include <unistd.h> // POSIX standard function definitions - read(), close(), STDIN_FILENO
|
|
|
|
+#include <termios.h> // POSIX terminal control definitions - tcgetattr(), tcsetattr()
|
|
|
|
+#include <pthread.h> // POSIX threads management (inputs reading)
|
|
|
|
+#include <dirent.h> // POSIX directory browsing
|
|
|
|
|
|
#include <sys/ioctl.h> // Required for: ioctl() - UNIX System call for device-specific input/output operations
|
|
#include <sys/ioctl.h> // Required for: ioctl() - UNIX System call for device-specific input/output operations
|
|
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
|
#include <linux/kd.h> // Linux: KDSKBMODE, K_MEDIUMRAM constants definition
|
|
@@ -71,23 +71,13 @@
|
|
#include "EGL/egl.h" // Native platform windowing system interface
|
|
#include "EGL/egl.h" // Native platform windowing system interface
|
|
#include "EGL/eglext.h" // EGL extensions
|
|
#include "EGL/eglext.h" // EGL extensions
|
|
|
|
|
|
|
|
+// NOTE: DRM cache enables triple buffered DRM caching
|
|
#if defined(SUPPORT_DRM_CACHE)
|
|
#if defined(SUPPORT_DRM_CACHE)
|
|
-#include <poll.h> // for drmHandleEvent poll
|
|
|
|
-#include <errno.h> //for EBUSY, EAGAIN
|
|
|
|
|
|
+ #include <poll.h> // Required for: drmHandleEvent() poll
|
|
|
|
+ #include <errno.h> // Required for: EBUSY, EAGAIN
|
|
|
|
|
|
-#define MAX_CACHED_BOS 3
|
|
|
|
-
|
|
|
|
-typedef struct {
|
|
|
|
- struct gbm_bo *bo;
|
|
|
|
- uint32_t fbId; // DRM framebuffer ID
|
|
|
|
-} FramebufferCache;
|
|
|
|
-
|
|
|
|
-static FramebufferCache fbCache[MAX_CACHED_BOS] = {0};
|
|
|
|
-static volatile int fbCacheCount = 0;
|
|
|
|
-static volatile bool pendingFlip = false;
|
|
|
|
-static bool crtcSet = false;
|
|
|
|
-
|
|
|
|
-#endif //SUPPORT_DRM_CACHE
|
|
|
|
|
|
+ #define MAX_DRM_CACHED_BUFFERS 3
|
|
|
|
+#endif // SUPPORT_DRM_CACHE
|
|
|
|
|
|
#ifndef EGL_OPENGL_ES3_BIT
|
|
#ifndef EGL_OPENGL_ES3_BIT
|
|
#define EGL_OPENGL_ES3_BIT 0x40
|
|
#define EGL_OPENGL_ES3_BIT 0x40
|
|
@@ -96,18 +86,16 @@ static bool crtcSet = false;
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
// Defines and Macros
|
|
// Defines and Macros
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
-#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
|
|
|
|
|
+#define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event<N> number
|
|
|
|
|
|
-#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
|
|
|
|
|
+#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events
|
|
|
|
|
|
-// So actually the biggest key is KEY_CNT but we only really map the keys up to
|
|
|
|
-// KEY_ALS_TOGGLE
|
|
|
|
|
|
+// Actually biggest key is KEY_CNT but we only really map the keys up to KEY_ALS_TOGGLE
|
|
#define KEYMAP_SIZE KEY_ALS_TOGGLE
|
|
#define KEYMAP_SIZE KEY_ALS_TOGGLE
|
|
|
|
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
// Types and Structures Definition
|
|
// Types and Structures Definition
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
-
|
|
|
|
typedef struct {
|
|
typedef struct {
|
|
// Display data
|
|
// Display data
|
|
int fd; // File descriptor for /dev/dri/...
|
|
int fd; // File descriptor for /dev/dri/...
|
|
@@ -147,6 +135,18 @@ typedef struct {
|
|
int gamepadCount; // The number of gamepads registered
|
|
int gamepadCount; // The number of gamepads registered
|
|
} PlatformData;
|
|
} PlatformData;
|
|
|
|
|
|
|
|
+#if defined(SUPPORT_DRM_CACHE)
|
|
|
|
+typedef struct {
|
|
|
|
+ struct gbm_bo *bo; // Graphics buffer object
|
|
|
|
+ uint32_t fbId; // DRM framebuffer ID
|
|
|
|
+} FramebufferCache;
|
|
|
|
+
|
|
|
|
+static FramebufferCache fbCache[MAX_DRM_CACHED_BUFFERS] = { 0 };
|
|
|
|
+static volatile int fbCacheCount = 0;
|
|
|
|
+static volatile bool pendingFlip = false;
|
|
|
|
+static bool crtcSet = false;
|
|
|
|
+#endif // SUPPORT_DRM_CACHE
|
|
|
|
+
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
// Global Variables Definition
|
|
// Global Variables Definition
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
@@ -570,18 +570,23 @@ void DisableCursor(void)
|
|
}
|
|
}
|
|
|
|
|
|
#if defined(SUPPORT_DRM_CACHE)
|
|
#if defined(SUPPORT_DRM_CACHE)
|
|
-//callback to destroy cached framebuffer, set by gbm_bo_set_user_data()
|
|
|
|
-static void DestroyFrameBufferCallback(struct gbm_bo *bo, void *data) {
|
|
|
|
|
|
+
|
|
|
|
+// Destroy cached framebuffer callback, set by gbm_bo_set_user_data()
|
|
|
|
+static void DestroyFrameBufferCallback(struct gbm_bo *bo, void *data)
|
|
|
|
+{
|
|
uint32_t fbId = (uintptr_t)data;
|
|
uint32_t fbId = (uintptr_t)data;
|
|
|
|
+
|
|
// Remove from cache
|
|
// Remove from cache
|
|
- for (int i = 0; i < fbCacheCount; i++) {
|
|
|
|
- if (fbCache[i].bo == bo) {
|
|
|
|
- TRACELOG(LOG_INFO, "DRM: fb removed %u", (uintptr_t)fbId);
|
|
|
|
|
|
+ for (int i = 0; i < fbCacheCount; i++)
|
|
|
|
+ {
|
|
|
|
+ if (fbCache[i].bo == bo)
|
|
|
|
+ {
|
|
|
|
+ TRACELOG(LOG_INFO, "DISPLAY: DRM: Framebuffer removed [%u]", (uintptr_t)fbId);
|
|
drmModeRmFB(platform.fd, fbCache[i].fbId); // Release DRM FB
|
|
drmModeRmFB(platform.fd, fbCache[i].fbId); // Release DRM FB
|
|
|
|
+
|
|
// Shift remaining entries
|
|
// Shift remaining entries
|
|
- for (int j = i; j < fbCacheCount - 1; j++) {
|
|
|
|
- fbCache[j] = fbCache[j + 1];
|
|
|
|
- }
|
|
|
|
|
|
+ for (int j = i; j < fbCacheCount - 1; j++) fbCache[j] = fbCache[j + 1];
|
|
|
|
+
|
|
fbCacheCount--;
|
|
fbCacheCount--;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -589,56 +594,53 @@ static void DestroyFrameBufferCallback(struct gbm_bo *bo, void *data) {
|
|
}
|
|
}
|
|
|
|
|
|
// Create or retrieve cached DRM FB for BO
|
|
// Create or retrieve cached DRM FB for BO
|
|
-static uint32_t GetOrCreateFbForBo(struct gbm_bo *bo) {
|
|
|
|
|
|
+static uint32_t GetOrCreateFbForBo(struct gbm_bo *bo)
|
|
|
|
+{
|
|
// Try to find existing cache entry
|
|
// Try to find existing cache entry
|
|
- for (int i = 0; i < fbCacheCount; i++) {
|
|
|
|
- if (fbCache[i].bo == bo) {
|
|
|
|
- return fbCache[i].fbId;
|
|
|
|
- }
|
|
|
|
|
|
+ for (int i = 0; i < fbCacheCount; i++)
|
|
|
|
+ {
|
|
|
|
+ if (fbCache[i].bo == bo) return fbCache[i].fbId;
|
|
}
|
|
}
|
|
|
|
|
|
// Create new entry if cache not full
|
|
// Create new entry if cache not full
|
|
- if (fbCacheCount >= MAX_CACHED_BOS) {
|
|
|
|
- //FB cache full!
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ if (fbCacheCount >= MAX_DRM_CACHED_BUFFERS) return 0; // FB cache full
|
|
|
|
|
|
uint32_t handle = gbm_bo_get_handle(bo).u32;
|
|
uint32_t handle = gbm_bo_get_handle(bo).u32;
|
|
uint32_t stride = gbm_bo_get_stride(bo);
|
|
uint32_t stride = gbm_bo_get_stride(bo);
|
|
uint32_t width = gbm_bo_get_width(bo);
|
|
uint32_t width = gbm_bo_get_width(bo);
|
|
uint32_t height = gbm_bo_get_height(bo);
|
|
uint32_t height = gbm_bo_get_height(bo);
|
|
|
|
|
|
- uint32_t fbId;
|
|
|
|
- if (drmModeAddFB(platform.fd, width, height, 24, 32, stride, handle, &fbId)) {
|
|
|
|
- //rmModeAddFB failed
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ uint32_t fbId = 0;
|
|
|
|
+ if (drmModeAddFB(platform.fd, width, height, 24, 32, stride, handle, &fbId)) return 0;
|
|
|
|
|
|
// Store in cache
|
|
// Store in cache
|
|
fbCache[fbCacheCount] = (FramebufferCache){ .bo = bo, .fbId = fbId };
|
|
fbCache[fbCacheCount] = (FramebufferCache){ .bo = bo, .fbId = fbId };
|
|
fbCacheCount++;
|
|
fbCacheCount++;
|
|
|
|
|
|
// Set destroy callback to auto-cleanup
|
|
// Set destroy callback to auto-cleanup
|
|
- gbm_bo_set_user_data(bo, (void*)(uintptr_t)fbId, DestroyFrameBufferCallback);
|
|
|
|
|
|
+ gbm_bo_set_user_data(bo, (void *)(uintptr_t)fbId, DestroyFrameBufferCallback);
|
|
|
|
+
|
|
|
|
+ TRACELOG(LOG_INFO, "DISPLAY: DRM: Added new buffer object [%u]" , (uintptr_t)fbId);
|
|
|
|
|
|
- TRACELOG(LOG_INFO, "DRM: added new bo %u" , (uintptr_t)fbId);
|
|
|
|
return fbId;
|
|
return fbId;
|
|
}
|
|
}
|
|
|
|
|
|
// Renders a blank frame to allocate initial buffers
|
|
// Renders a blank frame to allocate initial buffers
|
|
-void RenderBlankFrame() {
|
|
|
|
|
|
+// TODO: WARNING: Platform layers do not include OpenGL code!
|
|
|
|
+void RenderBlankFrame()
|
|
|
|
+{
|
|
glClearColor(0, 0, 0, 1);
|
|
glClearColor(0, 0, 0, 1);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
eglSwapBuffers(platform.device, platform.surface);
|
|
eglSwapBuffers(platform.device, platform.surface);
|
|
-
|
|
|
|
- // Ensure the buffer is processed
|
|
|
|
- glFinish();
|
|
|
|
|
|
+ glFinish(); // Ensure the buffer is processed
|
|
}
|
|
}
|
|
|
|
|
|
// Initialize with first buffer only
|
|
// Initialize with first buffer only
|
|
-int InitSwapScreenBuffer() {
|
|
|
|
- if (!platform.gbmSurface || platform.fd < 0) {
|
|
|
|
- TRACELOG(LOG_ERROR, "DRM not initialized");
|
|
|
|
|
|
+int InitSwapScreenBuffer()
|
|
|
|
+{
|
|
|
|
+ if (!platform.gbmSurface || (platform.fd < 0))
|
|
|
|
+ {
|
|
|
|
+ TRACELOG(LOG_ERROR, "DISPLAY: DRM: Swap buffers can not be initialized");
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -647,23 +649,24 @@ int InitSwapScreenBuffer() {
|
|
|
|
|
|
// Get first buffer
|
|
// Get first buffer
|
|
struct gbm_bo *bo = gbm_surface_lock_front_buffer(platform.gbmSurface);
|
|
struct gbm_bo *bo = gbm_surface_lock_front_buffer(platform.gbmSurface);
|
|
- if (!bo) {
|
|
|
|
- TRACELOG(LOG_ERROR, "Failed to lock initial buffer");
|
|
|
|
|
|
+ if (!bo)
|
|
|
|
+ {
|
|
|
|
+ TRACELOG(LOG_ERROR, "DISPLAY: DRM: Failed to lock initial swap buffer");
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
// Create FB for first buffer
|
|
// Create FB for first buffer
|
|
uint32_t fbId = GetOrCreateFbForBo(bo);
|
|
uint32_t fbId = GetOrCreateFbForBo(bo);
|
|
- if (!fbId) {
|
|
|
|
|
|
+ if (!fbId)
|
|
|
|
+ {
|
|
gbm_surface_release_buffer(platform.gbmSurface, bo);
|
|
gbm_surface_release_buffer(platform.gbmSurface, bo);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
// Initial CRTC setup
|
|
// Initial CRTC setup
|
|
- if (drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, fbId,
|
|
|
|
- 0, 0, &platform.connector->connector_id, 1,
|
|
|
|
- &platform.connector->modes[platform.modeIndex])) {
|
|
|
|
- TRACELOG(LOG_ERROR, "Initial CRTC setup failed: %s", strerror(errno));
|
|
|
|
|
|
+ if (drmModeSetCrtc(platform.fd, platform.crtc->crtc_id, fbId, 0, 0, &platform.connector->connector_id, 1, &platform.connector->modes[platform.modeIndex]))
|
|
|
|
+ {
|
|
|
|
+ TRACELOG(LOG_ERROR, "DISPLAY: DRM: Failed to initialize CRTC setup. ERROR: %s", strerror(errno));
|
|
gbm_surface_release_buffer(platform.gbmSurface, bo);
|
|
gbm_surface_release_buffer(platform.gbmSurface, bo);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
@@ -671,32 +674,38 @@ int InitSwapScreenBuffer() {
|
|
// Keep first buffer locked until flipped
|
|
// Keep first buffer locked until flipped
|
|
platform.prevBO = bo;
|
|
platform.prevBO = bo;
|
|
crtcSet = true;
|
|
crtcSet = true;
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-// Static page flip handler
|
|
|
|
-// this will be called once the drmModePageFlip() finished from the drmHandleEvent(platform.fd, &evctx); context
|
|
|
|
-static void PageFlipHandler(int fd, unsigned int frame,
|
|
|
|
- unsigned int sec, unsigned int usec,
|
|
|
|
- void *data) {
|
|
|
|
- (void)fd; (void)frame; (void)sec; (void)usec; // Unused
|
|
|
|
|
|
+// Static page flip handler
|
|
|
|
+// NOTE: Called once the drmModePageFlip() finished from the drmHandleEvent() context
|
|
|
|
+static void PageFlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
|
|
|
|
+{
|
|
|
|
+ // Unused inputs
|
|
|
|
+ (void)fd;
|
|
|
|
+ (void)frame;
|
|
|
|
+ (void)sec;
|
|
|
|
+ (void)usec;
|
|
|
|
+
|
|
pendingFlip = false;
|
|
pendingFlip = false;
|
|
- struct gbm_bo *bo_to_release = (struct gbm_bo *)data;
|
|
|
|
- //Buffers are released after the flip completes (via page_flip_handler), ensuring they're no longer in use.
|
|
|
|
|
|
+ struct gbm_bo *boToRelease = (struct gbm_bo *)data;
|
|
|
|
+
|
|
|
|
+ // Buffers are released after the flip completes (via page_flip_handler), ensuring they're no longer in use
|
|
// Prevents the GPU from writing to a buffer being scanned out
|
|
// Prevents the GPU from writing to a buffer being scanned out
|
|
- if (bo_to_release) {
|
|
|
|
- gbm_surface_release_buffer(platform.gbmSurface, bo_to_release);
|
|
|
|
- }
|
|
|
|
|
|
+ if (boToRelease) gbm_surface_release_buffer(platform.gbmSurface, boToRelease);
|
|
}
|
|
}
|
|
|
|
|
|
// Swap implementation with proper caching
|
|
// Swap implementation with proper caching
|
|
-void SwapScreenBuffer() {
|
|
|
|
|
|
+void SwapScreenBuffer()
|
|
|
|
+{
|
|
|
|
+ if (!crtcSet || !platform.gbmSurface) return;
|
|
|
|
+
|
|
static int loopCnt = 0;
|
|
static int loopCnt = 0;
|
|
- loopCnt++;
|
|
|
|
static int errCnt[5] = {0};
|
|
static int errCnt[5] = {0};
|
|
- if (!crtcSet || !platform.gbmSurface) return;
|
|
|
|
|
|
+ loopCnt++;
|
|
|
|
|
|
- //call this only, if pendingFlip is not set
|
|
|
|
|
|
+ // Call this only, if pendingFlip is not set
|
|
eglSwapBuffers(platform.device, platform.surface);
|
|
eglSwapBuffers(platform.device, platform.surface);
|
|
|
|
|
|
// Process pending events non-blocking
|
|
// Process pending events non-blocking
|
|
@@ -704,76 +713,68 @@ void SwapScreenBuffer() {
|
|
.version = DRM_EVENT_CONTEXT_VERSION,
|
|
.version = DRM_EVENT_CONTEXT_VERSION,
|
|
.page_flip_handler = PageFlipHandler
|
|
.page_flip_handler = PageFlipHandler
|
|
};
|
|
};
|
|
-
|
|
|
|
|
|
+
|
|
struct pollfd pfd = { .fd = platform.fd, .events = POLLIN };
|
|
struct pollfd pfd = { .fd = platform.fd, .events = POLLIN };
|
|
- //polling for event for 0ms
|
|
|
|
- while (poll(&pfd, 1, 0) > 0) {
|
|
|
|
- drmHandleEvent(platform.fd, &evctx);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ // Polling for event for 0ms
|
|
|
|
+ while (poll(&pfd, 1, 0) > 0) drmHandleEvent(platform.fd, &evctx);
|
|
|
|
|
|
// Skip if previous flip pending
|
|
// Skip if previous flip pending
|
|
- if (pendingFlip) {
|
|
|
|
- //Skip frame: flip pending
|
|
|
|
- errCnt[0]++;
|
|
|
|
|
|
+ if (pendingFlip)
|
|
|
|
+ {
|
|
|
|
+ errCnt[0]++; // Skip frame: flip pending
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
// Get new front buffer
|
|
// Get new front buffer
|
|
- struct gbm_bo *next_bo = gbm_surface_lock_front_buffer(platform.gbmSurface);
|
|
|
|
- if (!next_bo) {
|
|
|
|
- //Failed to lock front buffer
|
|
|
|
|
|
+ struct gbm_bo *nextBO = gbm_surface_lock_front_buffer(platform.gbmSurface);
|
|
|
|
+ if (!nextBO) // Failed to lock front buffer
|
|
|
|
+ {
|
|
errCnt[1]++;
|
|
errCnt[1]++;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
// Get FB ID (creates new one if needed)
|
|
// Get FB ID (creates new one if needed)
|
|
- uint32_t fbId = GetOrCreateFbForBo(next_bo);
|
|
|
|
- if (!fbId) {
|
|
|
|
- gbm_surface_release_buffer(platform.gbmSurface, next_bo);
|
|
|
|
|
|
+ uint32_t fbId = GetOrCreateFbForBo(nextBO);
|
|
|
|
+ if (!fbId)
|
|
|
|
+ {
|
|
|
|
+ gbm_surface_release_buffer(platform.gbmSurface, nextBO);
|
|
errCnt[2]++;
|
|
errCnt[2]++;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
// Attempt page flip
|
|
// Attempt page flip
|
|
- /* rmModePageFlip() schedules a buffer-flip for the next vblank and then
|
|
|
|
- * notifies us about it. It takes a CRTC-id, fb-id and an arbitrary
|
|
|
|
- * data-pointer and then schedules the page-flip. This is fully asynchronous and
|
|
|
|
- * When the page-flip happens, the DRM-fd will become readable and we can call
|
|
|
|
- * drmHandleEvent(). This will read all vblank/page-flip events and call our
|
|
|
|
- * modeset_page_flip_event() callback with the data-pointer that we passed to
|
|
|
|
- * drmModePageFlip(). We simply call modeset_draw_dev() then so the next frame
|
|
|
|
- * is rendered..
|
|
|
|
- * returns immediately.
|
|
|
|
- */
|
|
|
|
- if (drmModePageFlip(platform.fd, platform.crtc->crtc_id, fbId,
|
|
|
|
- DRM_MODE_PAGE_FLIP_EVENT, platform.prevBO)) {
|
|
|
|
- if (errno == EBUSY) {
|
|
|
|
- //Display busy - skip flip
|
|
|
|
- errCnt[3]++;
|
|
|
|
- } else {
|
|
|
|
- //Page flip failed
|
|
|
|
- errCnt[4]++;
|
|
|
|
- }
|
|
|
|
- gbm_surface_release_buffer(platform.gbmSurface, next_bo);
|
|
|
|
|
|
+ // NOTE: rmModePageFlip() schedules a buffer-flip for the next vblank and then notifies us about it.
|
|
|
|
+ // It takes a CRTC-id, fb-id and an arbitrary data-pointer and then schedules the page-flip.
|
|
|
|
+ // This is fully asynchronous and when the page-flip happens, the DRM-fd will become readable and we can call drmHandleEvent().
|
|
|
|
+ // This will read all vblank/page-flip events and call our modeset_page_flip_event() callback with the data-pointer that we passed to drmModePageFlip().
|
|
|
|
+ // We simply call modeset_draw_dev() then so the next frame is rendered... returns immediately.
|
|
|
|
+ if (drmModePageFlip(platform.fd, platform.crtc->crtc_id, fbId, DRM_MODE_PAGE_FLIP_EVENT, platform.prevBO))
|
|
|
|
+ {
|
|
|
|
+ if (errno == EBUSY) errCnt[3]++; // Display busy - skip flip
|
|
|
|
+ else errCnt[4]++; // Page flip failed
|
|
|
|
+
|
|
|
|
+ gbm_surface_release_buffer(platform.gbmSurface, nextBO);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
// Success: update state
|
|
// Success: update state
|
|
pendingFlip = true;
|
|
pendingFlip = true;
|
|
-
|
|
|
|
- platform.prevBO = next_bo;
|
|
|
|
- //successful usage, do benchmarking
|
|
|
|
- //in every 10 sec, at 60FPS 60*10 -> 600
|
|
|
|
- if(loopCnt >= 600) {
|
|
|
|
- TRACELOG(LOG_INFO, "DRM err counters: %d, %d, %d, %d, %d, %d",errCnt[0],errCnt[1],errCnt[2],errCnt[3],errCnt[4], loopCnt);
|
|
|
|
- //reinit the errors
|
|
|
|
- for(int i=0;i<5;i++) {
|
|
|
|
- errCnt[i] = 0;
|
|
|
|
- }
|
|
|
|
|
|
+ platform.prevBO = nextBO;
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ // Some benchmarking code
|
|
|
|
+ if (loopCnt >= 600)
|
|
|
|
+ {
|
|
|
|
+ TRACELOG(LOG_INFO, "DRM: Error counters: %d, %d, %d, %d, %d, %d", errCnt[0], errCnt[1], errCnt[2], errCnt[3], errCnt[4], loopCnt);
|
|
|
|
+ for (int i = 0; i < 5; i++) errCnt[i] = 0;
|
|
loopCnt = 0;
|
|
loopCnt = 0;
|
|
}
|
|
}
|
|
|
|
+*/
|
|
}
|
|
}
|
|
-#else //SUPPORT_DRM_CACHE is not defined
|
|
|
|
|
|
+
|
|
|
|
+#else // !SUPPORT_DRM_CACHE
|
|
|
|
+
|
|
// Swap back buffer with front buffer (screen drawing)
|
|
// Swap back buffer with front buffer (screen drawing)
|
|
void SwapScreenBuffer(void)
|
|
void SwapScreenBuffer(void)
|
|
{
|
|
{
|
|
@@ -803,7 +804,8 @@ void SwapScreenBuffer(void)
|
|
|
|
|
|
platform.prevBO = bo;
|
|
platform.prevBO = bo;
|
|
}
|
|
}
|
|
-#endif //SUPPORT_DRM_CACHE
|
|
|
|
|
|
+#endif // SUPPORT_DRM_CACHE
|
|
|
|
+
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
// Module Functions Definition: Misc
|
|
// Module Functions Definition: Misc
|
|
//----------------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------------
|
|
@@ -1307,17 +1309,20 @@ int InitPlatform(void)
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
#if defined(SUPPORT_DRM_CACHE)
|
|
#if defined(SUPPORT_DRM_CACHE)
|
|
- if(InitSwapScreenBuffer() == 0) {
|
|
|
|
-#endif//SUPPORT_DRM_CACHE
|
|
|
|
|
|
+ if (InitSwapScreenBuffer() == 0)
|
|
|
|
+ {
|
|
TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized successfully");
|
|
TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized successfully");
|
|
return 0;
|
|
return 0;
|
|
-#if defined(SUPPORT_DRM_CACHE)
|
|
|
|
- } else {
|
|
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized failed");
|
|
TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized failed");
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
-#endif //SUPPORT_DRM_CACHE
|
|
|
|
-
|
|
|
|
|
|
+#else // !SUPPORT_DRM_CACHE
|
|
|
|
+ TRACELOG(LOG_INFO, "PLATFORM: DRM: Initialized successfully");
|
|
|
|
+ return 0;
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
|
|
// Close platform
|
|
// Close platform
|