mirror of
https://github.com/Ryujinx/SDL.git
synced 2024-12-23 17:35:34 +00:00
[Video/KMSDRM] Don't copy the cursor bitmap to the cursor GBM BO until we're showing it.
This commit is contained in:
parent
67e9132dd5
commit
a8dbcab132
|
@ -98,20 +98,13 @@ KMSDRM_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This simply copies over the cursor bitmap from the SDLSurface we receive to the
|
/* This simply gets the cursor soft-buffer ready. We don't copy it to a GBO BO until ShowCursor()
|
||||||
cursor GBM BO. Setting up the cursor plane, creating the cursor FB BO, etc.. is
|
because the cusor GBM BO (living in dispata) is destroyed and recreated when we recreate windows, etc. */
|
||||||
done in KMSDRM_InitMouse(): when we get here. everything must be ready. */
|
|
||||||
static SDL_Cursor *
|
static SDL_Cursor *
|
||||||
KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
||||||
{
|
{
|
||||||
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
|
|
||||||
KMSDRM_CursorData *curdata;
|
KMSDRM_CursorData *curdata;
|
||||||
SDL_Cursor *cursor;
|
SDL_Cursor *cursor, *ret;
|
||||||
|
|
||||||
uint32_t bo_stride, pixel;
|
|
||||||
uint32_t *buffer = NULL;
|
|
||||||
size_t bufsize;
|
|
||||||
unsigned int i, j;
|
|
||||||
|
|
||||||
/* All code below assumes ARGB8888 format for the cursor surface,
|
/* All code below assumes ARGB8888 format for the cursor surface,
|
||||||
like other backends do. Also, the GBM BO pixels have to be
|
like other backends do. Also, the GBM BO pixels have to be
|
||||||
|
@ -123,30 +116,30 @@ KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
||||||
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;
|
ret = NULL;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
curdata = (KMSDRM_CursorData *) SDL_calloc(1, sizeof(*curdata));
|
curdata = (KMSDRM_CursorData *) SDL_calloc(1, sizeof(*curdata));
|
||||||
if (!curdata) {
|
if (!curdata) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
SDL_free(cursor);
|
ret = NULL;
|
||||||
return NULL;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hox_x and hot_y are the coordinates of the "tip of the cursor" from it's base. */
|
/* 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 = dispdata->cursor_w;
|
curdata->w = surface->w;
|
||||||
curdata->h = dispdata->cursor_h;
|
curdata->h = surface->h;
|
||||||
|
curdata->buffer = NULL;
|
||||||
|
|
||||||
bo_stride = KMSDRM_gbm_bo_get_stride(dispdata->cursor_bo);
|
/* Configure the cursor buffer info.
|
||||||
bufsize = bo_stride * curdata->h;
|
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);
|
||||||
|
|
||||||
/* Always use a temp buffer: it serves the purpose of storing the
|
if (!curdata->buffer) {
|
||||||
alpha-premultiplied pixels (so we can copy them to the gbm BO
|
|
||||||
with a single gb_bo_write() call), and also copying from the
|
|
||||||
SDL surface, line by line, to a gbm BO with different pitch. */
|
|
||||||
buffer = (uint32_t*)SDL_malloc(bufsize);
|
|
||||||
if (!buffer) {
|
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -158,47 +151,31 @@ KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean the whole temporary buffer. */
|
/* Copy the surface pixels to the cursor buffer, for future use in ShowCursor() */
|
||||||
SDL_memset(buffer, 0x00, bo_stride * curdata->h);
|
SDL_memcpy(curdata->buffer, surface->pixels, curdata->buffer_size);
|
||||||
|
|
||||||
/* Copy from SDL surface to buffer, pre-multiplying by alpha each pixel as we go. */
|
|
||||||
for (i = 0; i < surface->h; i++) {
|
|
||||||
for (j = 0; j < surface->w; j++) {
|
|
||||||
pixel = ((uint32_t*)surface->pixels)[i * surface->w + j];
|
|
||||||
alpha_premultiply_ARGB8888 (&pixel);
|
|
||||||
SDL_memcpy(buffer + (i * curdata->w) + j, &pixel, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_MUSTLOCK(surface)) {
|
if (SDL_MUSTLOCK(surface)) {
|
||||||
SDL_UnlockSurface(surface);
|
SDL_UnlockSurface(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KMSDRM_gbm_bo_write(dispdata->cursor_bo, buffer, bufsize)) {
|
|
||||||
SDL_SetError("Could not write to GBM cursor BO");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free temporary buffer */
|
|
||||||
SDL_free(buffer);
|
|
||||||
buffer = NULL;
|
|
||||||
|
|
||||||
cursor->driverdata = curdata;
|
cursor->driverdata = curdata;
|
||||||
|
|
||||||
return cursor;
|
ret = cursor;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (buffer) {
|
if (ret == NULL) {
|
||||||
SDL_free(buffer);
|
if (curdata->buffer) {
|
||||||
}
|
SDL_free(curdata->buffer);
|
||||||
if (cursor) {
|
}
|
||||||
SDL_free(cursor);
|
if (cursor) {
|
||||||
}
|
SDL_free(cursor);
|
||||||
if (curdata) {
|
}
|
||||||
SDL_free(curdata);
|
if (curdata) {
|
||||||
|
SDL_free(curdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show the specified cursor, or hide if cursor is NULL.
|
/* Show the specified cursor, or hide if cursor is NULL.
|
||||||
|
@ -218,6 +195,14 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
|
||||||
KMSDRM_FBInfo *fb;
|
KMSDRM_FBInfo *fb;
|
||||||
KMSDRM_PlaneInfo info = {0};
|
KMSDRM_PlaneInfo info = {0};
|
||||||
|
|
||||||
|
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.");
|
||||||
|
@ -268,8 +253,39 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
|
||||||
return SDL_SetError("Cursor not initialized properly.");
|
return SDL_SetError("Cursor not initialized properly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare a buffer we can dump to our GBM BO (different size, alpha premultiplication...) */
|
||||||
|
bo_stride = KMSDRM_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];
|
||||||
|
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_gbm_bo_write(dispdata->cursor_bo, ready_buffer, bufsize)) {
|
||||||
|
ret = SDL_SetError("Could not write to GBM cursor BO");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the fb_id for the GBM BO so we can show it on the cursor plane. */
|
||||||
fb = KMSDRM_FBFromBO(video_device, dispdata->cursor_bo);
|
fb = KMSDRM_FBFromBO(video_device, dispdata->cursor_bo);
|
||||||
|
|
||||||
|
/* Show the GBM BO buffer on the cursor plane. */
|
||||||
info.plane = dispdata->cursor_plane;
|
info.plane = dispdata->cursor_plane;
|
||||||
info.crtc_id = dispdata->crtc->crtc->crtc_id;
|
info.crtc_id = dispdata->crtc->crtc->crtc_id;
|
||||||
info.fb_id = fb->fb_id;
|
info.fb_id = fb->fb_id;
|
||||||
|
@ -283,10 +299,18 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
|
||||||
drm_atomic_set_plane_props(&info);
|
drm_atomic_set_plane_props(&info);
|
||||||
|
|
||||||
if (drm_atomic_commit(display->device, SDL_TRUE)) {
|
if (drm_atomic_commit(display->device, SDL_TRUE)) {
|
||||||
return SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
|
ret = SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
if (ready_buffer) {
|
||||||
|
SDL_free(ready_buffer);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have destroyed the cursor by now, in KMSDRM_DestroyCursor.
|
/* We have destroyed the cursor by now, in KMSDRM_DestroyCursor.
|
||||||
|
@ -294,9 +318,20 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
|
||||||
static void
|
static void
|
||||||
KMSDRM_FreeCursor(SDL_Cursor * cursor)
|
KMSDRM_FreeCursor(SDL_Cursor * cursor)
|
||||||
{
|
{
|
||||||
|
KMSDRM_CursorData *curdata;
|
||||||
|
|
||||||
/* Even if the cursor is not ours, free it. */
|
/* Even if the cursor is not ours, free it. */
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
SDL_free(cursor->driverdata);
|
curdata = (KMSDRM_CursorData *) cursor->driverdata;
|
||||||
|
/* Free cursor buffer */
|
||||||
|
if (curdata->buffer) {
|
||||||
|
SDL_free(curdata->buffer);
|
||||||
|
curdata->buffer = NULL;
|
||||||
|
}
|
||||||
|
/* Free cursor itself */
|
||||||
|
if (cursor->driverdata) {
|
||||||
|
SDL_free(cursor->driverdata);
|
||||||
|
}
|
||||||
SDL_free(cursor);
|
SDL_free(cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,12 @@ typedef struct _KMSDRM_CursorData
|
||||||
uint16_t hot_x, hot_y;
|
uint16_t hot_x, hot_y;
|
||||||
uint16_t w, h;
|
uint16_t 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_CursorData;
|
} KMSDRM_CursorData;
|
||||||
|
|
||||||
extern void KMSDRM_InitMouse(_THIS);
|
extern void KMSDRM_InitMouse(_THIS);
|
||||||
|
|
Loading…
Reference in a new issue