kmsdrm: Use SDL_PremultiplySurfaceAlphaToARGB8888() for cursor surface Instead of taking a direct copy of the mouse cursor surface, and then premultiplying on every BO upload (using the custom legacy_alpha_premultiply_ARGB8888 function), use the new SDL_PremultiplySurfaceAlphaToARGB8888() function, which converts a whole surface at a time, once and save the result. The already-premultiplied data is then copied from that to the BO on each upload, adjusting for the stride (which the previous implementation required to be equal to the width), thereby making the extra copy slightly useful.. This also adds support for non-SDL_PIXELFORMAT_ARGB8888 surfaces.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c
index 57cb35c..c9b1854 100644
--- a/src/video/kmsdrm/SDL_kmsdrmmouse.c
+++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c
@@ -30,6 +30,8 @@
#include "../../events/SDL_mouse_c.h"
#include "../../events/default_cursor.h"
+#include "../SDL_pixels_c.h"
+
static SDL_Cursor *KMSDRM_CreateDefaultCursor(void);
static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y);
static int KMSDRM_ShowCursor(SDL_Cursor * cursor);
@@ -59,30 +61,6 @@ KMSDRM_CreateDefaultCursor(void)
return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
}
-/* 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);
-}
-
/* Given a display's driverdata, destroy the cursor BO for it.
To be called from KMSDRM_DestroyWindow(), as that's where we
destroy the driverdata for the window's display. */
@@ -171,10 +149,10 @@ KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor)
uint32_t bo_handle;
size_t bo_stride;
size_t bufsize;
- uint32_t *ready_buffer = NULL;
- uint32_t pixel;
+ uint8_t *ready_buffer = NULL;
+ uint8_t *src_row;
- int i,j;
+ int i;
int ret;
if (!curdata || !dispdata->cursor_bo) {
@@ -186,21 +164,17 @@ KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor)
bo_stride = KMSDRM_gbm_bo_get_stride(dispdata->cursor_bo);
bufsize = bo_stride * dispdata->cursor_h;
- ready_buffer = (uint32_t*)SDL_calloc(1, bufsize);
+ ready_buffer = (uint8_t*)SDL_calloc(1, bufsize);
if (!ready_buffer) {
ret = SDL_OutOfMemory();
goto cleanup;
}
- /* 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. */
+ /* Copy from the cursor buffer to a buffer that we can dump to the GBM BO. */
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);
- }
+ src_row = &((uint8_t*)curdata->buffer)[i * curdata->w * 4];
+ SDL_memcpy(ready_buffer + (i * bo_stride), src_row, 4 * curdata->w);
}
/* Dump the cursor buffer to our GBM BO. */
@@ -271,13 +245,6 @@ KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
curdata = NULL;
ret = NULL;
- /* All code below assumes ARGB8888 format for the cursor surface,
- like other backends do. Also, the GBM BO pixels have to be
- 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));
if (!cursor) {
SDL_OutOfMemory();
@@ -298,8 +265,8 @@ KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
/* Configure the cursor buffer info.
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_pitch = surface->w;
+ curdata->buffer_size = surface->w * surface->h * 4;
curdata->buffer = (uint32_t*)SDL_malloc(curdata->buffer_size);
if (!curdata->buffer) {
@@ -307,19 +274,11 @@ KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
goto cleanup;
}
- if (SDL_MUSTLOCK(surface)) {
- if (SDL_LockSurface(surface) < 0) {
- /* Could not lock surface */
- goto cleanup;
- }
- }
-
- /* Copy the surface pixels to the cursor buffer, for future use in ShowCursor() */
- SDL_memcpy(curdata->buffer, surface->pixels, curdata->buffer_size);
-
- if (SDL_MUSTLOCK(surface)) {
- SDL_UnlockSurface(surface);
- }
+ /* All code below assumes ARGB8888 format for the cursor surface,
+ like other backends do. Also, the GBM BO pixels have to be
+ alpha-premultiplied, but the SDL surface we receive has
+ straight-alpha pixels, so we always have to convert. */
+ SDL_PremultiplySurfaceAlphaToARGB8888(surface, curdata->buffer);
cursor->driverdata = curdata;