EGLFS KMS Hooks: Get rid of flashing

Change-Id: I590572ceb0f64d3e6a1d687874d549e84f20f60a
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
This commit is contained in:
Louai Al-Khanji 2014-09-16 09:57:46 +03:00
parent fabef06f33
commit 4f25bdd21a

View File

@ -113,14 +113,22 @@ public:
QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE; QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE;
void presentBuffer() Q_DECL_OVERRIDE; void presentBuffer() Q_DECL_OVERRIDE;
private:
bool setup_kms(); bool setup_kms();
struct FrameBuffer { struct FrameBuffer {
FrameBuffer() : fb(0) {} FrameBuffer() : fb(0) {}
uint32_t fb; uint32_t fb;
}; };
static void bufferDestroyedHandler(gbm_bo *bo, void *data);
FrameBuffer *framebufferForBufferObject(gbm_bo *bo); FrameBuffer *framebufferForBufferObject(gbm_bo *bo);
static void pageFlipHandler(int fd,
unsigned int sequence,
unsigned int tv_sec,
unsigned int tv_usec,
void *user_data);
private: private:
// device bits // device bits
QByteArray m_device; QByteArray m_device;
@ -135,6 +143,10 @@ private:
// Drawing bits // Drawing bits
gbm_surface *m_gbm_surface; gbm_surface *m_gbm_surface;
gbm_bo *m_gbm_bo_current;
gbm_bo *m_gbm_bo_next;
bool m_flipping;
bool m_mode_set;
}; };
static QEglKmsHooks kms_hooks; static QEglKmsHooks kms_hooks;
@ -147,6 +159,10 @@ QEglKmsHooks::QEglKmsHooks()
, m_drm_encoder(Q_NULLPTR) , m_drm_encoder(Q_NULLPTR)
, m_drm_crtc(0) , m_drm_crtc(0)
, m_gbm_surface(Q_NULLPTR) , m_gbm_surface(Q_NULLPTR)
, m_gbm_bo_current(Q_NULLPTR)
, m_gbm_bo_next(Q_NULLPTR)
, m_flipping(false)
, m_mode_set(false)
{ {
} }
@ -257,7 +273,6 @@ bool QEglKmsHooks::hasCapability(QPlatformIntegration::Capability cap) const
case QPlatformIntegration::ThreadedPixmaps: case QPlatformIntegration::ThreadedPixmaps:
case QPlatformIntegration::OpenGL: case QPlatformIntegration::OpenGL:
case QPlatformIntegration::ThreadedOpenGL: case QPlatformIntegration::ThreadedOpenGL:
case QPlatformIntegration::BufferQueueingOpenGL:
return true; return true;
default: default:
return false; return false;
@ -270,7 +285,7 @@ QPlatformCursor *QEglKmsHooks::createCursor(QPlatformScreen *screen) const
return new QKmsCursor(m_gbm_device, m_dri_fd, m_drm_crtc); return new QKmsCursor(m_gbm_device, m_dri_fd, m_drm_crtc);
} }
static void gbm_bo_destroyed_callback(gbm_bo *bo, void *data) void QEglKmsHooks::bufferDestroyedHandler(gbm_bo *bo, void *data)
{ {
QEglKmsHooks::FrameBuffer *fb = static_cast<QEglKmsHooks::FrameBuffer *>(data); QEglKmsHooks::FrameBuffer *fb = static_cast<QEglKmsHooks::FrameBuffer *>(data);
@ -305,23 +320,32 @@ QEglKmsHooks::FrameBuffer *QEglKmsHooks::framebufferForBufferObject(gbm_bo *bo)
return Q_NULLPTR; return Q_NULLPTR;
} }
gbm_bo_set_user_data(bo, fb.data(), gbm_bo_destroyed_callback); gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler);
return fb.take(); return fb.take();
} }
static void page_flip_handler(int fd, void QEglKmsHooks::pageFlipHandler(int fd,
unsigned int sequence, unsigned int sequence,
unsigned int tv_sec, unsigned int tv_sec,
unsigned int tv_usec, unsigned int tv_usec,
void *user_data) void *user_data)
{ {
Q_UNUSED(fd); Q_UNUSED(fd);
Q_UNUSED(sequence); Q_UNUSED(sequence);
Q_UNUSED(tv_sec); Q_UNUSED(tv_sec);
Q_UNUSED(tv_usec); Q_UNUSED(tv_usec);
QEglKmsHooks *hooks = static_cast<QEglKmsHooks *>(user_data);
if (hooks->m_gbm_bo_current)
gbm_surface_release_buffer(hooks->m_gbm_surface,
hooks->m_gbm_bo_current);
hooks->m_gbm_bo_current = hooks->m_gbm_bo_next;
hooks->m_gbm_bo_next = Q_NULLPTR;
// We are no longer flipping // We are no longer flipping
*static_cast<bool *>(user_data) = false; hooks->m_flipping = false;
} }
void QEglKmsHooks::presentBuffer() void QEglKmsHooks::presentBuffer()
@ -331,64 +355,55 @@ void QEglKmsHooks::presentBuffer()
return; return;
} }
if (!gbm_surface_has_free_buffers(m_gbm_surface)) { m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface);
qWarning("Out of free GBM buffers!"); if (!m_gbm_bo_next) {
return;
}
gbm_bo *front_buffer = gbm_surface_lock_front_buffer(m_gbm_surface);
if (!front_buffer) {
qWarning("Could not lock GBM surface front buffer!"); qWarning("Could not lock GBM surface front buffer!");
return; return;
} }
QEglKmsHooks::FrameBuffer *fb = framebufferForBufferObject(front_buffer); QEglKmsHooks::FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
int ret = drmModeSetCrtc(m_dri_fd, if (!m_mode_set) {
m_drm_crtc, int ret = drmModeSetCrtc(m_dri_fd,
fb->fb, m_drm_crtc,
0, 0, fb->fb,
&m_drm_connector->connector_id, 1, 0, 0,
&m_drm_mode); &m_drm_connector->connector_id, 1,
if (ret) { &m_drm_mode);
qErrnoWarning("Could not set DRM mode!"); if (ret) {
return; qErrnoWarning("Could not set DRM mode!");
} else {
m_mode_set = true;
}
} }
bool flipping = true; int ret = drmModePageFlip(m_dri_fd,
ret = drmModePageFlip(m_dri_fd, m_drm_encoder->crtc_id,
m_drm_encoder->crtc_id, fb->fb,
fb->fb, DRM_MODE_PAGE_FLIP_EVENT,
DRM_MODE_PAGE_FLIP_EVENT, this);
&flipping);
if (ret) { if (ret) {
qErrnoWarning("Could not queue DRM page flip!"); qErrnoWarning("Could not queue DRM page flip!");
return; return;
} }
m_flipping = true;
drmEventContext drmEvent = { drmEventContext drmEvent = {
DRM_EVENT_CONTEXT_VERSION, DRM_EVENT_CONTEXT_VERSION,
Q_NULLPTR, // vblank handler Q_NULLPTR, // vblank handler
page_flip_handler // page flip handler pageFlipHandler // page flip handler
}; };
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(m_dri_fd, &fds); FD_SET(m_dri_fd, &fds);
time_t start, cur; while (m_flipping) {
time(&start); ret = qt_safe_select(m_dri_fd + 1, &fds, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR);
while (flipping && (time(&cur) < start + 1)) {
timespec v;
memset(&v, 0, sizeof(v));
v.tv_sec = start + 1 - cur;
ret = qt_safe_select(m_dri_fd + 1, &fds, Q_NULLPTR, Q_NULLPTR, &v);
if (ret == 0) { if (ret == 0) {
// timeout // timeout
break;
} else if (ret == -1) { } else if (ret == -1) {
qErrnoWarning("Error while selecting on DRM fd"); qErrnoWarning("Error while selecting on DRM fd");
break; break;
@ -396,8 +411,6 @@ void QEglKmsHooks::presentBuffer()
qWarning("Could not handle DRM event!"); qWarning("Could not handle DRM event!");
} }
} }
gbm_surface_release_buffer(m_gbm_surface, front_buffer);
} }
bool QEglKmsHooks::setup_kms() bool QEglKmsHooks::setup_kms()
@ -464,6 +477,7 @@ bool QEglKmsHooks::setup_kms()
return true; return true;
} }
QKmsCursor::QKmsCursor(gbm_device *gbm_device, int dri_fd, uint32_t crtcId) QKmsCursor::QKmsCursor(gbm_device *gbm_device, int dri_fd, uint32_t crtcId)
: m_gbm_device(gbm_device) : m_gbm_device(gbm_device)
, m_dri_fd(dri_fd) , m_dri_fd(dri_fd)