mirror of https://github.com/encounter/SDL.git
[KMS/DRM] Rewrite KMSDRM_LEGACY backend to accomodate Vulkan compatibility. Fix several bugs on that backend.
This commit is contained in:
parent
57a5c45372
commit
67e0b1dd4e
|
@ -44,7 +44,32 @@ KMSDRM_LEGACY_CreateDefaultCursor(void)
|
||||||
return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
|
return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate if a given cursor size is supported or not. Notably, current Intel gfx only support 64x64 and up. */
|
/* Converts a pixel from straight-alpha [AA, RR, GG, BB], which the SDL cursor surface has,
|
||||||
|
to premultiplied-alpha [AA. AA*RR, AA*GG, AA*BB].
|
||||||
|
These multiplications have to be done with floats instead of uint32_t's,
|
||||||
|
and the resulting values have to be converted to be relative to the 0-255 interval,
|
||||||
|
where 255 is 1.00 and anything between 0 and 255 is 0.xx. */
|
||||||
|
void legacy_alpha_premultiply_ARGB8888 (uint32_t *pixel) {
|
||||||
|
|
||||||
|
uint32_t A, R, G, B;
|
||||||
|
|
||||||
|
/* Component bytes extraction. */
|
||||||
|
A = (*pixel >> (3 << 3)) & 0xFF;
|
||||||
|
R = (*pixel >> (2 << 3)) & 0xFF;
|
||||||
|
G = (*pixel >> (1 << 3)) & 0xFF;
|
||||||
|
B = (*pixel >> (0 << 3)) & 0xFF;
|
||||||
|
|
||||||
|
/* Alpha pre-multiplication of each component. */
|
||||||
|
R = (float)A * ((float)R /255);
|
||||||
|
G = (float)A * ((float)G /255);
|
||||||
|
B = (float)A * ((float)B /255);
|
||||||
|
|
||||||
|
/* ARGB8888 pixel recomposition. */
|
||||||
|
(*pixel) = (((uint32_t)A << 24) | ((uint32_t)R << 16) | ((uint32_t)G << 8)) | ((uint32_t)B << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Evaluate if a given cursor size is supported or not.
|
||||||
|
Notably, current Intel gfx only support 64x64 and up. */
|
||||||
static SDL_bool
|
static SDL_bool
|
||||||
KMSDRM_LEGACY_IsCursorSizeSupported (int w, int h, uint32_t bo_format) {
|
KMSDRM_LEGACY_IsCursorSizeSupported (int w, int h, uint32_t bo_format) {
|
||||||
|
|
||||||
|
@ -54,7 +79,7 @@ KMSDRM_LEGACY_IsCursorSizeSupported (int w, int h, uint32_t bo_format) {
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t bo_handle;
|
uint32_t bo_handle;
|
||||||
struct gbm_bo *bo = KMSDRM_LEGACY_gbm_bo_create(viddata->gbm, w, h, bo_format,
|
struct gbm_bo *bo = KMSDRM_LEGACY_gbm_bo_create(viddata->gbm_dev, w, h, bo_format,
|
||||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||||
|
|
||||||
if (!bo) {
|
if (!bo) {
|
||||||
|
@ -63,7 +88,7 @@ KMSDRM_LEGACY_IsCursorSizeSupported (int w, int h, uint32_t bo_format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bo_handle = KMSDRM_LEGACY_gbm_bo_get_handle(bo).u32;
|
bo_handle = KMSDRM_LEGACY_gbm_bo_get_handle(bo).u32;
|
||||||
ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd, dispdata->crtc_id, bo_handle, w, h);
|
ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd, dispdata->crtc->crtc_id, bo_handle, w, h);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -80,328 +105,236 @@ cleanup:
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a cursor from a surface */
|
/* This simply gets the cursor soft-buffer ready.
|
||||||
|
We don't copy it to a GBO BO until ShowCursor() because the cusor GBM BO (living
|
||||||
|
in dispata) is destroyed and recreated when we recreate windows, etc. */
|
||||||
static SDL_Cursor *
|
static SDL_Cursor *
|
||||||
KMSDRM_LEGACY_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
KMSDRM_LEGACY_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
||||||
{
|
{
|
||||||
SDL_VideoDevice *dev = SDL_GetVideoDevice();
|
|
||||||
SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
|
|
||||||
SDL_PixelFormat *pixlfmt = surface->format;
|
|
||||||
KMSDRM_LEGACY_CursorData *curdata;
|
KMSDRM_LEGACY_CursorData *curdata;
|
||||||
SDL_Cursor *cursor;
|
SDL_Cursor *cursor, *ret;
|
||||||
SDL_bool cursor_supported = SDL_FALSE;
|
|
||||||
int i, ret, usable_cursor_w, usable_cursor_h;
|
|
||||||
uint32_t bo_format, bo_stride;
|
|
||||||
char *buffer = NULL;
|
|
||||||
size_t bufsize;
|
|
||||||
|
|
||||||
switch(pixlfmt->format) {
|
curdata = NULL;
|
||||||
case SDL_PIXELFORMAT_RGB332:
|
ret = NULL;
|
||||||
bo_format = GBM_FORMAT_RGB332;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ARGB4444:
|
|
||||||
bo_format = GBM_FORMAT_ARGB4444;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGBA4444:
|
|
||||||
bo_format = GBM_FORMAT_RGBA4444;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ABGR4444:
|
|
||||||
bo_format = GBM_FORMAT_ABGR4444;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGRA4444:
|
|
||||||
bo_format = GBM_FORMAT_BGRA4444;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ARGB1555:
|
|
||||||
bo_format = GBM_FORMAT_ARGB1555;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGBA5551:
|
|
||||||
bo_format = GBM_FORMAT_RGBA5551;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ABGR1555:
|
|
||||||
bo_format = GBM_FORMAT_ABGR1555;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGRA5551:
|
|
||||||
bo_format = GBM_FORMAT_BGRA5551;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGB565:
|
|
||||||
bo_format = GBM_FORMAT_RGB565;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGR565:
|
|
||||||
bo_format = GBM_FORMAT_BGR565;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGB888:
|
|
||||||
case SDL_PIXELFORMAT_RGB24:
|
|
||||||
bo_format = GBM_FORMAT_RGB888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
|
||||||
case SDL_PIXELFORMAT_BGR24:
|
|
||||||
bo_format = GBM_FORMAT_BGR888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGBX8888:
|
|
||||||
bo_format = GBM_FORMAT_RGBX8888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGRX8888:
|
|
||||||
bo_format = GBM_FORMAT_BGRX8888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
|
||||||
bo_format = GBM_FORMAT_ARGB8888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGBA8888:
|
|
||||||
bo_format = GBM_FORMAT_RGBA8888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
|
||||||
bo_format = GBM_FORMAT_ABGR8888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGRA8888:
|
|
||||||
bo_format = GBM_FORMAT_BGRA8888;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ARGB2101010:
|
|
||||||
bo_format = GBM_FORMAT_ARGB2101010;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SDL_SetError("Unsupported pixel format for cursor");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!KMSDRM_LEGACY_gbm_device_is_format_supported(viddata->gbm, bo_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) {
|
/* All code below assumes ARGB8888 format for the cursor surface,
|
||||||
SDL_SetError("Unsupported pixel format for cursor");
|
like other backends do. Also, the GBM BO pixels have to be
|
||||||
return NULL;
|
alpha-premultiplied, but the SDL surface we receive has
|
||||||
}
|
straight-alpha pixels, so we always have to convert. */
|
||||||
|
SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
|
||||||
|
SDL_assert(surface->pitch == surface->w * 4);
|
||||||
|
|
||||||
cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
|
cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
|
||||||
if (!cursor) {
|
if (!cursor) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
return NULL;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
curdata = (KMSDRM_LEGACY_CursorData *) SDL_calloc(1, sizeof(*curdata));
|
curdata = (KMSDRM_LEGACY_CursorData *) SDL_calloc(1, sizeof(*curdata));
|
||||||
if (!curdata) {
|
if (!curdata) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
SDL_free(cursor);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We have to know beforehand if a cursor with the same size as the surface is supported.
|
|
||||||
* If it's not, we have to find an usable cursor size and use an intermediate and clean buffer.
|
|
||||||
* If we can't find a cursor size supported by the hardware, we won't go on trying to
|
|
||||||
* call SDL_SetCursor() later. */
|
|
||||||
|
|
||||||
usable_cursor_w = surface->w;
|
|
||||||
usable_cursor_h = surface->h;
|
|
||||||
|
|
||||||
while (usable_cursor_w <= MAX_CURSOR_W && usable_cursor_h <= MAX_CURSOR_H) {
|
|
||||||
if (KMSDRM_LEGACY_IsCursorSizeSupported(usable_cursor_w, usable_cursor_h, bo_format)) {
|
|
||||||
cursor_supported = SDL_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
usable_cursor_w += usable_cursor_w;
|
|
||||||
usable_cursor_h += usable_cursor_h;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cursor_supported) {
|
|
||||||
SDL_SetError("Could not find a cursor size supported by the kernel driver");
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* hox_x and hot_y are the coordinates of the "tip of the cursor" from it's base. */
|
||||||
curdata->hot_x = hot_x;
|
curdata->hot_x = hot_x;
|
||||||
curdata->hot_y = hot_y;
|
curdata->hot_y = hot_y;
|
||||||
curdata->w = usable_cursor_w;
|
curdata->w = surface->w;
|
||||||
curdata->h = usable_cursor_h;
|
curdata->h = surface->h;
|
||||||
|
curdata->buffer = NULL;
|
||||||
|
|
||||||
curdata->bo = KMSDRM_LEGACY_gbm_bo_create(viddata->gbm, usable_cursor_w, usable_cursor_h, bo_format,
|
/* Configure the cursor buffer info.
|
||||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
This buffer has the original size of the cursor surface we are given. */
|
||||||
|
curdata->buffer_pitch = surface->pitch;
|
||||||
|
curdata->buffer_size = surface->pitch * surface->h;
|
||||||
|
curdata->buffer = (uint32_t*)SDL_malloc(curdata->buffer_size);
|
||||||
|
|
||||||
if (!curdata->bo) {
|
if (!curdata->buffer) {
|
||||||
SDL_SetError("Could not create GBM cursor BO");
|
SDL_OutOfMemory();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
bo_stride = KMSDRM_LEGACY_gbm_bo_get_stride(curdata->bo);
|
if (SDL_MUSTLOCK(surface)) {
|
||||||
bufsize = bo_stride * curdata->h;
|
if (SDL_LockSurface(surface) < 0) {
|
||||||
|
/* Could not lock surface */
|
||||||
if (surface->pitch != bo_stride) {
|
|
||||||
/* pitch doesn't match stride, must be copied to temp buffer */
|
|
||||||
buffer = SDL_malloc(bufsize);
|
|
||||||
if (!buffer) {
|
|
||||||
SDL_OutOfMemory();
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_MUSTLOCK(surface)) {
|
/* Copy the surface pixels to the cursor buffer, for future use in ShowCursor() */
|
||||||
if (SDL_LockSurface(surface) < 0) {
|
SDL_memcpy(curdata->buffer, surface->pixels, curdata->buffer_size);
|
||||||
/* Could not lock surface */
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean the whole temporary buffer */
|
if (SDL_MUSTLOCK(surface)) {
|
||||||
SDL_memset(buffer, 0x00, bo_stride * curdata->h);
|
SDL_UnlockSurface(surface);
|
||||||
|
|
||||||
/* Copy to temporary buffer */
|
|
||||||
for (i = 0; i < surface->h; i++) {
|
|
||||||
SDL_memcpy(buffer + (i * bo_stride),
|
|
||||||
((char *)surface->pixels) + (i * surface->pitch),
|
|
||||||
surface->w * pixlfmt->BytesPerPixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_MUSTLOCK(surface)) {
|
|
||||||
SDL_UnlockSurface(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KMSDRM_LEGACY_gbm_bo_write(curdata->bo, buffer, bufsize)) {
|
|
||||||
SDL_SetError("Could not write to GBM cursor BO");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free temporary buffer */
|
|
||||||
SDL_free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
} else {
|
|
||||||
/* surface matches BO format */
|
|
||||||
if (SDL_MUSTLOCK(surface)) {
|
|
||||||
if (SDL_LockSurface(surface) < 0) {
|
|
||||||
/* Could not lock surface */
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = KMSDRM_LEGACY_gbm_bo_write(curdata->bo, surface->pixels, bufsize);
|
|
||||||
|
|
||||||
if (SDL_MUSTLOCK(surface)) {
|
|
||||||
SDL_UnlockSurface(surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
SDL_SetError("Could not write to GBM cursor BO");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor->driverdata = curdata;
|
cursor->driverdata = curdata;
|
||||||
|
|
||||||
return cursor;
|
ret = cursor;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (buffer) {
|
if (ret == NULL) {
|
||||||
SDL_free(buffer);
|
if (curdata) {
|
||||||
|
if (curdata->buffer) {
|
||||||
|
SDL_free(curdata->buffer);
|
||||||
|
}
|
||||||
|
SDL_free(curdata);
|
||||||
|
}
|
||||||
|
if (cursor) {
|
||||||
|
SDL_free(cursor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (cursor) {
|
|
||||||
SDL_free(cursor);
|
return ret;
|
||||||
}
|
|
||||||
if (curdata) {
|
|
||||||
if (curdata->bo) {
|
|
||||||
KMSDRM_LEGACY_gbm_bo_destroy(curdata->bo);
|
|
||||||
}
|
|
||||||
SDL_free(curdata);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the specified cursor, or hide if cursor is NULL */
|
/* When we create a window, we have to test if we have to show the cursor,
|
||||||
|
and explicily do so if necessary.
|
||||||
|
This is because when we destroy a window, we take the cursor away from the
|
||||||
|
cursor plane, and destroy the cusror GBM BO. So we have to re-show it,
|
||||||
|
so to say. */
|
||||||
|
void
|
||||||
|
KMSDRM_LEGACY_InitCursor()
|
||||||
|
{
|
||||||
|
SDL_Mouse *mouse = NULL;
|
||||||
|
mouse = SDL_GetMouse();
|
||||||
|
|
||||||
|
if (!mouse) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(mouse->cur_cursor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(mouse->cursor_shown)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KMSDRM_LEGACY_ShowCursor(mouse->cur_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show the specified cursor, or hide if cursor is NULL. */
|
||||||
static int
|
static int
|
||||||
KMSDRM_LEGACY_ShowCursor(SDL_Cursor * cursor)
|
KMSDRM_LEGACY_ShowCursor(SDL_Cursor * cursor)
|
||||||
{
|
{
|
||||||
SDL_VideoDevice *dev = SDL_GetVideoDevice();
|
SDL_VideoDevice *video_device = SDL_GetVideoDevice();
|
||||||
SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
|
SDL_VideoData *viddata = ((SDL_VideoData *)video_device->driverdata);
|
||||||
|
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
|
||||||
SDL_Mouse *mouse;
|
SDL_Mouse *mouse;
|
||||||
KMSDRM_LEGACY_CursorData *curdata;
|
KMSDRM_LEGACY_CursorData *curdata;
|
||||||
SDL_VideoDisplay *display = NULL;
|
|
||||||
SDL_DisplayData *dispdata = NULL;
|
|
||||||
int ret;
|
|
||||||
uint32_t bo_handle;
|
uint32_t bo_handle;
|
||||||
|
|
||||||
|
size_t bo_stride;
|
||||||
|
size_t bufsize;
|
||||||
|
uint32_t *ready_buffer = NULL;
|
||||||
|
uint32_t pixel;
|
||||||
|
|
||||||
|
int i,j;
|
||||||
|
int ret;
|
||||||
|
|
||||||
mouse = SDL_GetMouse();
|
mouse = SDL_GetMouse();
|
||||||
if (!mouse) {
|
if (!mouse) {
|
||||||
return SDL_SetError("No mouse.");
|
return SDL_SetError("No mouse.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse->focus) {
|
/*********************************************************/
|
||||||
display = SDL_GetDisplayForWindow(mouse->focus);
|
/* Hide cursor if it's NULL or it has no focus(=winwow). */
|
||||||
if (display) {
|
/*********************************************************/
|
||||||
dispdata = (SDL_DisplayData*) display->driverdata;
|
if (!cursor || !mouse->focus) {
|
||||||
}
|
/* Hide the drm cursor with no more considerations because
|
||||||
}
|
SDL_VideoQuit() takes us here after disabling the mouse
|
||||||
|
so there is no mouse->cur_cursor by now. */
|
||||||
if (!cursor) {
|
ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd,
|
||||||
/* Hide current cursor */
|
dispdata->crtc->crtc_id, 0, 0, 0);
|
||||||
if (mouse->cur_cursor && mouse->cur_cursor->driverdata) {
|
if (ret) {
|
||||||
curdata = (KMSDRM_LEGACY_CursorData *) mouse->cur_cursor->driverdata;
|
ret = SDL_SetError("Could not hide current cursor with drmModeSetCursor().");
|
||||||
|
}
|
||||||
if (curdata->crtc_id != 0) {
|
|
||||||
ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd, curdata->crtc_id, 0, 0, 0);
|
|
||||||
if (ret) {
|
|
||||||
SDL_SetError("Could not hide current cursor with drmModeSetCursor().");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
/* Mark previous cursor as not-displayed */
|
|
||||||
curdata->crtc_id = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* otherwise if possible, hide global cursor */
|
|
||||||
if (dispdata && dispdata->crtc_id != 0) {
|
|
||||||
ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd, dispdata->crtc_id, 0, 0, 0);
|
|
||||||
if (ret) {
|
|
||||||
SDL_SetError("Could not hide display's cursor with drmModeSetCursor().");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SDL_SetError("Couldn't find cursor to hide.");
|
|
||||||
}
|
|
||||||
/* If cursor != NULL, show new cursor on display */
|
|
||||||
if (!display) {
|
|
||||||
return SDL_SetError("Could not get display for mouse.");
|
|
||||||
}
|
|
||||||
if (!dispdata) {
|
|
||||||
return SDL_SetError("Could not get display driverdata.");
|
|
||||||
}
|
|
||||||
|
|
||||||
curdata = (KMSDRM_LEGACY_CursorData *) cursor->driverdata;
|
|
||||||
if (!curdata || !curdata->bo) {
|
|
||||||
return SDL_SetError("Cursor not initialized properly.");
|
|
||||||
}
|
|
||||||
|
|
||||||
bo_handle = KMSDRM_LEGACY_gbm_bo_get_handle(curdata->bo).u32;
|
|
||||||
if (curdata->hot_x == 0 && curdata->hot_y == 0) {
|
|
||||||
ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd, dispdata->crtc_id, bo_handle,
|
|
||||||
curdata->w, curdata->h);
|
|
||||||
} else {
|
|
||||||
ret = KMSDRM_LEGACY_drmModeSetCursor2(viddata->drm_fd, dispdata->crtc_id, bo_handle,
|
|
||||||
curdata->w, curdata->h, curdata->hot_x, curdata->hot_y);
|
|
||||||
}
|
|
||||||
if (ret) {
|
|
||||||
SDL_SetError("drmModeSetCursor failed.");
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
curdata->crtc_id = dispdata->crtc_id;
|
/************************************************/
|
||||||
|
/* If cursor != NULL, DO show cursor on display */
|
||||||
|
/************************************************/
|
||||||
|
if (!dispdata) {
|
||||||
|
return SDL_SetError("Could not get display driverdata.");
|
||||||
|
}
|
||||||
|
|
||||||
|
curdata = (KMSDRM_LEGACY_CursorData *) cursor->driverdata;
|
||||||
|
|
||||||
return 0;
|
if (!curdata || !dispdata->cursor_bo) {
|
||||||
|
return SDL_SetError("Cursor not initialized properly.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare a buffer we can dump to our GBM BO (different
|
||||||
|
size, alpha premultiplication...) */
|
||||||
|
bo_stride = KMSDRM_LEGACY_gbm_bo_get_stride(dispdata->cursor_bo);
|
||||||
|
bufsize = bo_stride * curdata->h;
|
||||||
|
|
||||||
|
ready_buffer = (uint32_t*)SDL_malloc(bufsize);
|
||||||
|
if (!ready_buffer) {
|
||||||
|
ret = SDL_OutOfMemory();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean the whole buffer we are preparing. */
|
||||||
|
SDL_memset(ready_buffer, 0x00, bo_stride * curdata->h);
|
||||||
|
|
||||||
|
/* Copy from the cursor buffer to a buffer that we can dump to the GBM BO,
|
||||||
|
pre-multiplying by alpha each pixel as we go. */
|
||||||
|
for (i = 0; i < curdata->h; i++) {
|
||||||
|
for (j = 0; j < curdata->w; j++) {
|
||||||
|
pixel = ((uint32_t*)curdata->buffer)[i * curdata->w + j];
|
||||||
|
legacy_alpha_premultiply_ARGB8888 (&pixel);
|
||||||
|
SDL_memcpy(ready_buffer + (i * dispdata->cursor_w) + j, &pixel, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump the cursor buffer to our GBM BO. */
|
||||||
|
if (KMSDRM_LEGACY_gbm_bo_write(dispdata->cursor_bo, ready_buffer, bufsize)) {
|
||||||
|
ret = SDL_SetError("Could not write to GBM cursor BO");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put the GBM BO buffer on screen using the DRM interface. */
|
||||||
|
bo_handle = KMSDRM_LEGACY_gbm_bo_get_handle(dispdata->cursor_bo).u32;
|
||||||
|
if (curdata->hot_x == 0 && curdata->hot_y == 0) {
|
||||||
|
ret = KMSDRM_LEGACY_drmModeSetCursor(viddata->drm_fd, dispdata->crtc->crtc_id,
|
||||||
|
bo_handle, curdata->w, curdata->h);
|
||||||
|
} else {
|
||||||
|
ret = KMSDRM_LEGACY_drmModeSetCursor2(viddata->drm_fd, dispdata->crtc->crtc_id,
|
||||||
|
bo_handle, curdata->w, curdata->h, curdata->hot_x, curdata->hot_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
ret = SDL_SetError("Failed to set DRM cursor.");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
if (ready_buffer) {
|
||||||
|
SDL_free(ready_buffer);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free a window manager cursor */
|
/* We have destroyed the cursor by now, in KMSDRM_DestroyCursor.
|
||||||
|
This is only for freeing the SDL_cursor.*/
|
||||||
static void
|
static void
|
||||||
KMSDRM_LEGACY_FreeCursor(SDL_Cursor * cursor)
|
KMSDRM_LEGACY_FreeCursor(SDL_Cursor * cursor)
|
||||||
{
|
{
|
||||||
KMSDRM_LEGACY_CursorData *curdata;
|
KMSDRM_LEGACY_CursorData *curdata;
|
||||||
int drm_fd;
|
|
||||||
|
|
||||||
|
/* Even if the cursor is not ours, free it. */
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
curdata = (KMSDRM_LEGACY_CursorData *) cursor->driverdata;
|
curdata = (KMSDRM_LEGACY_CursorData *) cursor->driverdata;
|
||||||
|
/* Free cursor buffer */
|
||||||
if (curdata) {
|
if (curdata->buffer) {
|
||||||
if (curdata->bo) {
|
SDL_free(curdata->buffer);
|
||||||
if (curdata->crtc_id != 0) {
|
curdata->buffer = NULL;
|
||||||
drm_fd = KMSDRM_LEGACY_gbm_device_get_fd(KMSDRM_LEGACY_gbm_bo_get_device(curdata->bo));
|
}
|
||||||
/* Hide the cursor if previously shown on a CRTC */
|
/* Free cursor itself */
|
||||||
KMSDRM_LEGACY_drmModeSetCursor(drm_fd, curdata->crtc_id, 0, 0, 0);
|
if (cursor->driverdata) {
|
||||||
curdata->crtc_id = 0;
|
|
||||||
}
|
|
||||||
KMSDRM_LEGACY_gbm_bo_destroy(curdata->bo);
|
|
||||||
curdata->bo = NULL;
|
|
||||||
}
|
|
||||||
SDL_free(cursor->driverdata);
|
SDL_free(cursor->driverdata);
|
||||||
}
|
}
|
||||||
SDL_free(cursor);
|
SDL_free(cursor);
|
||||||
|
@ -420,44 +353,57 @@ KMSDRM_LEGACY_WarpMouse(SDL_Window * window, int x, int y)
|
||||||
static int
|
static int
|
||||||
KMSDRM_LEGACY_WarpMouseGlobal(int x, int y)
|
KMSDRM_LEGACY_WarpMouseGlobal(int x, int y)
|
||||||
{
|
{
|
||||||
KMSDRM_LEGACY_CursorData *curdata;
|
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
|
||||||
|
|
||||||
if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) {
|
if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) {
|
||||||
/* Update internal mouse position. */
|
/* Update internal mouse position. */
|
||||||
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);
|
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);
|
||||||
|
|
||||||
/* And now update the cursor graphic position on screen. */
|
/* And now update the cursor graphic position on screen. */
|
||||||
curdata = (KMSDRM_LEGACY_CursorData *) mouse->cur_cursor->driverdata;
|
if (dispdata->cursor_bo) {
|
||||||
if (curdata->bo) {
|
int ret, drm_fd;
|
||||||
|
drm_fd = KMSDRM_LEGACY_gbm_device_get_fd(
|
||||||
|
KMSDRM_LEGACY_gbm_bo_get_device(dispdata->cursor_bo));
|
||||||
|
ret = KMSDRM_LEGACY_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, x, y);
|
||||||
|
|
||||||
if (curdata->crtc_id != 0) {
|
if (ret) {
|
||||||
int ret, drm_fd;
|
SDL_SetError("drmModeMoveCursor() failed.");
|
||||||
drm_fd = KMSDRM_LEGACY_gbm_device_get_fd(KMSDRM_LEGACY_gbm_bo_get_device(curdata->bo));
|
}
|
||||||
ret = KMSDRM_LEGACY_drmModeMoveCursor(drm_fd, curdata->crtc_id, x, y);
|
|
||||||
|
|
||||||
if (ret) {
|
return ret;
|
||||||
SDL_SetError("drmModeMoveCursor() failed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
} else {
|
|
||||||
return SDL_SetError("Cursor is not currently shown.");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return SDL_SetError("Cursor not initialized properly.");
|
return SDL_SetError("Cursor not initialized properly.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return SDL_SetError("No mouse or current cursor.");
|
return SDL_SetError("No mouse or current cursor.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* UNDO WHAT WE DID IN KMSDRM_InitMouse(). */
|
||||||
|
void
|
||||||
|
KMSDRM_LEGACY_DeinitMouse(_THIS)
|
||||||
|
{
|
||||||
|
SDL_VideoDevice *video_device = SDL_GetVideoDevice();
|
||||||
|
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
|
||||||
|
|
||||||
|
/* Destroy the curso GBM BO. */
|
||||||
|
if (video_device && dispdata->cursor_bo) {
|
||||||
|
KMSDRM_LEGACY_gbm_bo_destroy(dispdata->cursor_bo);
|
||||||
|
dispdata->cursor_bo = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create cursor BO. */
|
||||||
void
|
void
|
||||||
KMSDRM_LEGACY_InitMouse(_THIS)
|
KMSDRM_LEGACY_InitMouse(_THIS)
|
||||||
{
|
{
|
||||||
/* FIXME: Using UDEV it should be possible to scan all mice
|
SDL_VideoDevice *dev = SDL_GetVideoDevice();
|
||||||
* but there's no point in doing so as there's no multimice support...yet!
|
SDL_VideoData *viddata = ((SDL_VideoData *)dev->driverdata);
|
||||||
*/
|
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
|
|
||||||
mouse->CreateCursor = KMSDRM_LEGACY_CreateCursor;
|
mouse->CreateCursor = KMSDRM_LEGACY_CreateCursor;
|
||||||
|
@ -467,7 +413,53 @@ KMSDRM_LEGACY_InitMouse(_THIS)
|
||||||
mouse->WarpMouse = KMSDRM_LEGACY_WarpMouse;
|
mouse->WarpMouse = KMSDRM_LEGACY_WarpMouse;
|
||||||
mouse->WarpMouseGlobal = KMSDRM_LEGACY_WarpMouseGlobal;
|
mouse->WarpMouseGlobal = KMSDRM_LEGACY_WarpMouseGlobal;
|
||||||
|
|
||||||
|
/************************************************/
|
||||||
|
/* Create the cursor GBM BO, if we haven't yet. */
|
||||||
|
/************************************************/
|
||||||
|
if (!dispdata->cursor_bo) {
|
||||||
|
|
||||||
|
if (!KMSDRM_LEGACY_gbm_device_is_format_supported(viddata->gbm_dev,
|
||||||
|
GBM_FORMAT_ARGB8888,
|
||||||
|
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
|
||||||
|
{
|
||||||
|
SDL_SetError("Unsupported pixel format for cursor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KMSDRM_LEGACY_drmGetCap(viddata->drm_fd,
|
||||||
|
DRM_CAP_CURSOR_WIDTH, &dispdata->cursor_w) ||
|
||||||
|
KMSDRM_LEGACY_drmGetCap(viddata->drm_fd, DRM_CAP_CURSOR_HEIGHT,
|
||||||
|
&dispdata->cursor_h))
|
||||||
|
{
|
||||||
|
SDL_SetError("Could not get the recommended GBM cursor size");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dispdata->cursor_w == 0 || dispdata->cursor_h == 0) {
|
||||||
|
SDL_SetError("Could not get an usable GBM cursor size");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispdata->cursor_bo = KMSDRM_LEGACY_gbm_bo_create(viddata->gbm_dev,
|
||||||
|
dispdata->cursor_w, dispdata->cursor_h,
|
||||||
|
GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||||
|
|
||||||
|
if (!dispdata->cursor_bo) {
|
||||||
|
SDL_SetError("Could not create GBM cursor BO");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SDL expects to set the default cursor on screen when we init the mouse. */
|
||||||
SDL_SetDefaultCursor(KMSDRM_LEGACY_CreateDefaultCursor());
|
SDL_SetDefaultCursor(KMSDRM_LEGACY_CreateDefaultCursor());
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (dispdata->cursor_bo) {
|
||||||
|
KMSDRM_LEGACY_gbm_bo_destroy(dispdata->cursor_bo);
|
||||||
|
dispdata->cursor_bo = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -481,15 +473,14 @@ static void
|
||||||
KMSDRM_LEGACY_MoveCursor(SDL_Cursor * cursor)
|
KMSDRM_LEGACY_MoveCursor(SDL_Cursor * cursor)
|
||||||
{
|
{
|
||||||
SDL_Mouse *mouse = SDL_GetMouse();
|
SDL_Mouse *mouse = SDL_GetMouse();
|
||||||
KMSDRM_LEGACY_CursorData *curdata;
|
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
|
||||||
int drm_fd, ret;
|
int drm_fd, ret;
|
||||||
|
|
||||||
/* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity!
|
/* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity!
|
||||||
That's why we move the cursor graphic ONLY. */
|
That's why we move the cursor graphic ONLY. */
|
||||||
if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) {
|
if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) {
|
||||||
curdata = (KMSDRM_LEGACY_CursorData *) mouse->cur_cursor->driverdata;
|
drm_fd = KMSDRM_LEGACY_gbm_device_get_fd(KMSDRM_LEGACY_gbm_bo_get_device(dispdata->cursor_bo));
|
||||||
drm_fd = KMSDRM_LEGACY_gbm_device_get_fd(KMSDRM_LEGACY_gbm_bo_get_device(curdata->bo));
|
ret = KMSDRM_LEGACY_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, mouse->x, mouse->y);
|
||||||
ret = KMSDRM_LEGACY_drmModeMoveCursor(drm_fd, curdata->crtc_id, mouse->x, mouse->y);
|
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
SDL_SetError("drmModeMoveCursor() failed.");
|
SDL_SetError("drmModeMoveCursor() failed.");
|
||||||
|
|
|
@ -31,15 +31,24 @@
|
||||||
|
|
||||||
typedef struct _KMSDRM_LEGACY_CursorData
|
typedef struct _KMSDRM_LEGACY_CursorData
|
||||||
{
|
{
|
||||||
struct gbm_bo *bo;
|
|
||||||
uint32_t crtc_id;
|
|
||||||
int hot_x, hot_y;
|
int hot_x, hot_y;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
|
||||||
|
/* The buffer where we store the mouse bitmap ready to be used.
|
||||||
|
We get it ready and filled in CreateCursor(), and copy it
|
||||||
|
to a GBM BO in ShowCursor().*/
|
||||||
|
uint32_t *buffer;
|
||||||
|
size_t buffer_size;
|
||||||
|
size_t buffer_pitch;
|
||||||
|
|
||||||
} KMSDRM_LEGACY_CursorData;
|
} KMSDRM_LEGACY_CursorData;
|
||||||
|
|
||||||
extern void KMSDRM_LEGACY_InitMouse(_THIS);
|
extern void KMSDRM_LEGACY_InitMouse(_THIS);
|
||||||
|
extern void KMSDRM_LEGACY_DeinitMouse(_THIS);
|
||||||
extern void KMSDRM_LEGACY_QuitMouse(_THIS);
|
extern void KMSDRM_LEGACY_QuitMouse(_THIS);
|
||||||
|
|
||||||
|
extern void KMSDRM_LEGACY_InitCursor();
|
||||||
|
|
||||||
#endif /* SDL_KMSDRM_LEGACY_mouse_h_ */
|
#endif /* SDL_KMSDRM_LEGACY_mouse_h_ */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -35,10 +35,36 @@
|
||||||
|
|
||||||
/* EGL implementation of SDL OpenGL support */
|
/* EGL implementation of SDL OpenGL support */
|
||||||
|
|
||||||
|
void
|
||||||
|
KMSDRM_LEGACY_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor)
|
||||||
|
{
|
||||||
|
/* if SDL was _also_ built with the Raspberry Pi driver (so we're
|
||||||
|
definitely a Pi device), default to GLES2. */
|
||||||
|
#if SDL_VIDEO_DRIVER_RPI
|
||||||
|
*mask = SDL_GL_CONTEXT_PROFILE_ES;
|
||||||
|
*major = 2;
|
||||||
|
*minor = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
KMSDRM_LEGACY_GLES_LoadLibrary(_THIS, const char *path) {
|
KMSDRM_LEGACY_GLES_LoadLibrary(_THIS, const char *path) {
|
||||||
NativeDisplayType display = (NativeDisplayType)((SDL_VideoData *)_this->driverdata)->gbm;
|
/* Just pretend you do this here, but don't do it until KMSDRM_CreateWindow(),
|
||||||
|
where we do the same library load we would normally do here.
|
||||||
|
because this gets called by SDL_CreateWindow() before KMSDR_CreateWindow(),
|
||||||
|
so gbm dev isn't yet created when this is called, AND we can't alter the
|
||||||
|
call order in SDL_CreateWindow(). */
|
||||||
|
#if 0
|
||||||
|
NativeDisplayType display = (NativeDisplayType)((SDL_VideoData *)_this->driverdata)->gbm_dev;
|
||||||
return SDL_EGL_LoadLibrary(_this, path, display, EGL_PLATFORM_GBM_MESA);
|
return SDL_EGL_LoadLibrary(_this, path, display, EGL_PLATFORM_GBM_MESA);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
KMSDRM_LEGACY_GLES_UnloadLibrary(_THIS) {
|
||||||
|
/* As with KMSDRM_GLES_LoadLibrary(), we define our own "dummy" unloading function
|
||||||
|
so we manually unload the library whenever we want. */
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_EGL_CreateContext_impl(KMSDRM_LEGACY)
|
SDL_EGL_CreateContext_impl(KMSDRM_LEGACY)
|
||||||
|
@ -81,16 +107,17 @@ KMSDRM_LEGACY_GLES_SwapWindow(_THIS, SDL_Window * window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the previous front buffer */
|
/* Release the previous front buffer */
|
||||||
if (windata->curr_bo) {
|
if (windata->bo) {
|
||||||
KMSDRM_LEGACY_gbm_surface_release_buffer(windata->gs, windata->curr_bo);
|
KMSDRM_LEGACY_gbm_surface_release_buffer(windata->gs, windata->bo);
|
||||||
/* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)windata->curr_bo); */
|
windata->bo = NULL;
|
||||||
windata->curr_bo = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
windata->curr_bo = windata->next_bo;
|
windata->bo = windata->next_bo;
|
||||||
|
|
||||||
/* Make the current back buffer the next front buffer */
|
/* Mark a buffer to becume the next front buffer.
|
||||||
if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface))) {
|
This won't happen until pagelip completes. */
|
||||||
|
if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display,
|
||||||
|
windata->egl_surface))) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -100,46 +127,60 @@ KMSDRM_LEGACY_GLES_SwapWindow(_THIS, SDL_Window * window) {
|
||||||
if (!windata->next_bo) {
|
if (!windata->next_bo) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
|
||||||
return 0;
|
return 0;
|
||||||
/* } else {
|
|
||||||
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)windata->next_bo); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the fb_info for the next front buffer. */
|
||||||
fb_info = KMSDRM_LEGACY_FBFromBO(_this, windata->next_bo);
|
fb_info = KMSDRM_LEGACY_FBFromBO(_this, windata->next_bo);
|
||||||
if (!fb_info) {
|
if (!fb_info) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!windata->curr_bo) {
|
if (!windata->bo) {
|
||||||
/* On the first swap, immediately present the new front buffer. Before
|
/***************************************************************************/
|
||||||
drmModePageFlip can be used the CRTC has to be configured to use
|
/* This is fundamental. */
|
||||||
the current connector and mode with drmModeSetCrtc */
|
/* We can't display an fb smaller than the resolution currently configured */
|
||||||
ret = KMSDRM_LEGACY_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id, 0,
|
/* on the CRTC, because the CRTC would be scanning out of bounds. */
|
||||||
0, &dispdata->conn->connector_id, 1, &dispdata->mode);
|
/* So instead of using drmModeSetCrtc() to tell CRTC to scan the fb */
|
||||||
|
/* directly, we use a plane (overlay or primary, doesn't mind if we */
|
||||||
|
/* activated the UNVERSAL PLANES cap) to scale the buffer to the */
|
||||||
|
/* resolution currently configured on the CRTC. */
|
||||||
|
/* */
|
||||||
|
/* We can't do this sooner, on CreateWindow(), because we don't have a */
|
||||||
|
/* framebuffer there yet, and DRM doesn't like 0 or -1 as the fb_id. */
|
||||||
|
/***************************************************************************/
|
||||||
|
ret = KMSDRM_LEGACY_drmModeSetPlane(viddata->drm_fd, dispdata->plane_id,
|
||||||
|
dispdata->crtc->crtc_id, fb_info->fb_id, 0,
|
||||||
|
windata->output_x, 0,
|
||||||
|
windata->output_w, windata->output_h,
|
||||||
|
0, 0,
|
||||||
|
windata->src_w << 16, windata->src_h << 16);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not configure CRTC");
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set PLANE");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* On subsequent swaps, queue the new front buffer to be flipped during
|
|
||||||
the next vertical blank */
|
|
||||||
ret = KMSDRM_LEGACY_drmModePageFlip(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id,
|
|
||||||
DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip);
|
|
||||||
/* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip)",
|
|
||||||
viddata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
|
|
||||||
|
|
||||||
if (_this->egl_data->egl_swapinterval == 1) {
|
|
||||||
if (ret == 0) {
|
|
||||||
windata->waiting_for_flip = SDL_TRUE;
|
|
||||||
} else {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait immediately for vsync (as if we only had two buffers), for low input-lag scenarios.
|
return 0;
|
||||||
Run your SDL2 program with "SDL_KMSDRM_LEGACY_DOUBLE_BUFFER=1 <program_name>" to enable this. */
|
}
|
||||||
if (_this->egl_data->egl_swapinterval == 1 && windata->double_buffer) {
|
|
||||||
KMSDRM_LEGACY_WaitPageFlip(_this, windata, -1);
|
/* Issue pageflip on the next front buffer.
|
||||||
}
|
The pageflip will be done during the next vblank. */
|
||||||
|
ret = KMSDRM_LEGACY_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id,
|
||||||
|
fb_info->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip);
|
||||||
|
|
||||||
|
if (_this->egl_data->egl_swapinterval == 1) {
|
||||||
|
if (ret == 0) {
|
||||||
|
windata->waiting_for_flip = SDL_TRUE;
|
||||||
|
} else {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are in double-buffer mode, wait immediately for vsync
|
||||||
|
(as if we only had two buffers),
|
||||||
|
Run your SDL2 program with "SDL_KMSDRM_LEGACY_DOUBLE_BUFFER=1 <program_name>"
|
||||||
|
to enable this. */
|
||||||
|
if (_this->egl_data->egl_swapinterval == 1 && windata->double_buffer) {
|
||||||
|
KMSDRM_LEGACY_WaitPageFlip(_this, windata, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -31,10 +31,10 @@
|
||||||
/* OpenGLES functions */
|
/* OpenGLES functions */
|
||||||
#define KMSDRM_LEGACY_GLES_GetAttribute SDL_EGL_GetAttribute
|
#define KMSDRM_LEGACY_GLES_GetAttribute SDL_EGL_GetAttribute
|
||||||
#define KMSDRM_LEGACY_GLES_GetProcAddress SDL_EGL_GetProcAddress
|
#define KMSDRM_LEGACY_GLES_GetProcAddress SDL_EGL_GetProcAddress
|
||||||
#define KMSDRM_LEGACY_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
|
|
||||||
#define KMSDRM_LEGACY_GLES_DeleteContext SDL_EGL_DeleteContext
|
#define KMSDRM_LEGACY_GLES_DeleteContext SDL_EGL_DeleteContext
|
||||||
#define KMSDRM_LEGACY_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
|
#define KMSDRM_LEGACY_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
|
||||||
|
|
||||||
|
extern void KMSDRM_LEGACY_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor);
|
||||||
extern int KMSDRM_LEGACY_GLES_SetSwapInterval(_THIS, int interval);
|
extern int KMSDRM_LEGACY_GLES_SetSwapInterval(_THIS, int interval);
|
||||||
extern int KMSDRM_LEGACY_GLES_LoadLibrary(_THIS, const char *path);
|
extern int KMSDRM_LEGACY_GLES_LoadLibrary(_THIS, const char *path);
|
||||||
extern SDL_GLContext KMSDRM_LEGACY_GLES_CreateContext(_THIS, SDL_Window * window);
|
extern SDL_GLContext KMSDRM_LEGACY_GLES_CreateContext(_THIS, SDL_Window * window);
|
||||||
|
|
|
@ -40,6 +40,7 @@ SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeFB,(drmModeFBPtr ptr))
|
||||||
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeCrtc,(drmModeCrtcPtr ptr))
|
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeCrtc,(drmModeCrtcPtr ptr))
|
||||||
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr))
|
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr))
|
||||||
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr))
|
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(int,drmGetCap,(int fd, uint64_t capability, uint64_t *value))
|
||||||
SDL_KMSDRM_LEGACY_SYM(drmModeResPtr,drmModeGetResources,(int fd))
|
SDL_KMSDRM_LEGACY_SYM(drmModeResPtr,drmModeGetResources,(int fd))
|
||||||
SDL_KMSDRM_LEGACY_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth,
|
SDL_KMSDRM_LEGACY_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth,
|
||||||
uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
|
uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
|
||||||
|
@ -62,6 +63,24 @@ SDL_KMSDRM_LEGACY_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx))
|
||||||
SDL_KMSDRM_LEGACY_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id,
|
SDL_KMSDRM_LEGACY_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id,
|
||||||
uint32_t flags, void *user_data))
|
uint32_t flags, void *user_data))
|
||||||
|
|
||||||
|
/* Planes stuff. */
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(drmModePlaneResPtr,drmModeGetPlaneResources,(int fd))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(drmModePlanePtr,drmModeGetPlane,(int fd, uint32_t plane_id))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(drmModeObjectPropertiesPtr,drmModeObjectGetProperties,(int fd,uint32_t object_id,uint32_t object_type))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(drmModePropertyPtr,drmModeGetProperty,(int fd, uint32_t propertyId))
|
||||||
|
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeProperty,(drmModePropertyPtr ptr))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreeObjectProperties,(drmModeObjectPropertiesPtr ptr))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreePlane,(drmModePlanePtr ptr))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(void,drmModeFreePlaneResources,(drmModePlaneResPtr ptr))
|
||||||
|
SDL_KMSDRM_LEGACY_SYM(int,drmModeSetPlane,(int fd, uint32_t plane_id, uint32_t crtc_id,
|
||||||
|
uint32_t fb_id, uint32_t flags,
|
||||||
|
int32_t crtc_x, int32_t crtc_y,
|
||||||
|
uint32_t crtc_w, uint32_t crtc_h,
|
||||||
|
uint32_t src_x, uint32_t src_y,
|
||||||
|
uint32_t src_w, uint32_t src_h))
|
||||||
|
/* Planes stuff ends. */
|
||||||
|
|
||||||
SDL_KMSDRM_LEGACY_MODULE(GBM)
|
SDL_KMSDRM_LEGACY_MODULE(GBM)
|
||||||
SDL_KMSDRM_LEGACY_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm))
|
SDL_KMSDRM_LEGACY_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm))
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -37,7 +37,12 @@ typedef struct SDL_VideoData
|
||||||
{
|
{
|
||||||
int devindex; /* device index that was passed on creation */
|
int devindex; /* device index that was passed on creation */
|
||||||
int drm_fd; /* DRM file desc */
|
int drm_fd; /* DRM file desc */
|
||||||
struct gbm_device *gbm;
|
char devpath[32]; /* DRM dev path. */
|
||||||
|
|
||||||
|
struct gbm_device *gbm_dev;
|
||||||
|
|
||||||
|
SDL_bool video_init; /* Has VideoInit succeeded? */
|
||||||
|
SDL_bool vulkan_mode; /* Are we in Vulkan mode? One VK window is enough to be. */
|
||||||
|
|
||||||
SDL_Window **windows;
|
SDL_Window **windows;
|
||||||
int max_windows;
|
int max_windows;
|
||||||
|
@ -53,26 +58,53 @@ typedef struct SDL_DisplayModeData
|
||||||
|
|
||||||
typedef struct SDL_DisplayData
|
typedef struct SDL_DisplayData
|
||||||
{
|
{
|
||||||
uint32_t crtc_id;
|
drmModeConnector *connector;
|
||||||
drmModeConnector *conn;
|
drmModeCrtc *crtc;
|
||||||
drmModeModeInfo mode;
|
drmModeModeInfo mode;
|
||||||
drmModeCrtc *saved_crtc; /* CRTC to restore on quit */
|
drmModeModeInfo original_mode;
|
||||||
} SDL_DisplayData;
|
drmModeModeInfo preferred_mode;
|
||||||
|
|
||||||
|
drmModeCrtc *saved_crtc; /* CRTC to restore on quit */
|
||||||
|
|
||||||
|
uint32_t plane_id; /* ID of the primary plane used by the CRTC */
|
||||||
|
|
||||||
|
SDL_bool gbm_init;
|
||||||
|
|
||||||
|
/* DRM & GBM cursor stuff lives here, not in an SDL_Cursor's driverdata struct,
|
||||||
|
because setting/unsetting up these is done on window creation/destruction,
|
||||||
|
where we may not have an SDL_Cursor at all (so no SDL_Cursor driverdata).
|
||||||
|
There's only one cursor GBM BO because we only support one cursor. */
|
||||||
|
struct gbm_bo *cursor_bo;
|
||||||
|
uint64_t cursor_w, cursor_h;
|
||||||
|
|
||||||
|
SDL_bool modeset_pending;
|
||||||
|
|
||||||
|
} SDL_DisplayData;
|
||||||
|
|
||||||
typedef struct SDL_WindowData
|
typedef struct SDL_WindowData
|
||||||
{
|
{
|
||||||
SDL_VideoData *viddata;
|
SDL_VideoData *viddata;
|
||||||
|
/* SDL internals expect EGL surface to be here, and in KMSDRM the GBM surface is
|
||||||
|
what supports the EGL surface on the driver side, so all these surfaces and buffers
|
||||||
|
are expected to be here, in the struct pointed by SDL_Window driverdata pointer:
|
||||||
|
this one. So don't try to move these to dispdata! */
|
||||||
struct gbm_surface *gs;
|
struct gbm_surface *gs;
|
||||||
struct gbm_bo *curr_bo;
|
struct gbm_bo *bo;
|
||||||
struct gbm_bo *next_bo;
|
struct gbm_bo *next_bo;
|
||||||
struct gbm_bo *crtc_bo;
|
|
||||||
SDL_bool waiting_for_flip;
|
SDL_bool waiting_for_flip;
|
||||||
SDL_bool double_buffer;
|
SDL_bool double_buffer;
|
||||||
|
|
||||||
int egl_surface_dirty;
|
int egl_surface_dirty;
|
||||||
EGLSurface egl_surface;
|
EGLSurface egl_surface;
|
||||||
|
|
||||||
|
/* For scaling and AR correction. */
|
||||||
|
int32_t src_w;
|
||||||
|
int32_t src_h;
|
||||||
|
int32_t output_w;
|
||||||
|
int32_t output_h;
|
||||||
|
int32_t output_x;
|
||||||
|
|
||||||
} SDL_WindowData;
|
} SDL_WindowData;
|
||||||
|
|
||||||
typedef struct KMSDRM_LEGACY_FBInfo
|
typedef struct KMSDRM_LEGACY_FBInfo
|
||||||
|
@ -101,6 +133,7 @@ void KMSDRM_LEGACY_SetWindowTitle(_THIS, SDL_Window * window);
|
||||||
void KMSDRM_LEGACY_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
|
void KMSDRM_LEGACY_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
|
||||||
void KMSDRM_LEGACY_SetWindowPosition(_THIS, SDL_Window * window);
|
void KMSDRM_LEGACY_SetWindowPosition(_THIS, SDL_Window * window);
|
||||||
void KMSDRM_LEGACY_SetWindowSize(_THIS, SDL_Window * window);
|
void KMSDRM_LEGACY_SetWindowSize(_THIS, SDL_Window * window);
|
||||||
|
void KMSDRM_LEGACY_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen);
|
||||||
void KMSDRM_LEGACY_ShowWindow(_THIS, SDL_Window * window);
|
void KMSDRM_LEGACY_ShowWindow(_THIS, SDL_Window * window);
|
||||||
void KMSDRM_LEGACY_HideWindow(_THIS, SDL_Window * window);
|
void KMSDRM_LEGACY_HideWindow(_THIS, SDL_Window * window);
|
||||||
void KMSDRM_LEGACY_RaiseWindow(_THIS, SDL_Window * window);
|
void KMSDRM_LEGACY_RaiseWindow(_THIS, SDL_Window * window);
|
||||||
|
|
Loading…
Reference in New Issue