hc
2023-12-04 f33f61bdb7ca6d5ebe7a78f9d8694b91360279ac
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
From 5672f48fc04b95e7468f152508d7b356dda5e7db Mon Sep 17 00:00:00 2001
From: Hertz Wang <wangh@rock-chips.com>
Date: Fri, 16 Nov 2018 17:03:43 +0800
Subject: [PATCH] force display of video on overlay plane
 
note: control the video display layer according
      to the SDL2_DISPLAY_PLANE_TYPE environment variable
 
Signed-off-by: Hertz Wang <wangh@rock-chips.com>
---
 src/video/kmsdrm/SDL_kmsdrmopengles.c | 62 +++++++++++++++-----------
 src/video/kmsdrm/SDL_kmsdrmsym.h      | 18 +++++++-
 src/video/kmsdrm/SDL_kmsdrmvideo.c    | 83 ++++++++++++++++++++++++++++++++++-
 src/video/kmsdrm/SDL_kmsdrmvideo.h    |  2 +
 4 files changed, 136 insertions(+), 29 deletions(-)
 
diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
index 7ba663f..ff0ce6c 100644
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
@@ -140,36 +140,46 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
     if (fb_info == NULL) {
         return 0;
     }
-    if (_this->egl_data->egl_swapinterval == 0) {
-        /* Swap buffers instantly, possible tearing */
-        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
+
+    if (!wdata->plane_id) {
+        if (_this->egl_data->egl_swapinterval == 0) {
+            /* Swap buffers instantly, possible tearing */
+            /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
             vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id,
             displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */
-        ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
-                                    0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode);
-        if(ret != 0) {
-            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret);
+            ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
+                0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode);
+            if(ret != 0) {
+                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret);
+            }
+        } else {
+            /* Queue page flip at vsync */
+
+            /* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not,
+            or FlipPage won't work in some cases. */
+            if (!wdata->crtc_ready) {
+                if(!KMSDRM_GLES_SetupCrtc(_this, window)) {
+                    SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing vsync-ed pageflips");
+                    return 0;
+                }
+            }
+
+            /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
+            vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
+            ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
+            DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip);
+            if (ret == 0) {
+                wdata->waiting_for_flip = SDL_TRUE;
+            } else {
+                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
+            }
         }
     } else {
-        /* Queue page flip at vsync */
-
-    /* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not,
-           or FlipPage won't work in some cases. */
-    if (!wdata->crtc_ready) {
-            if(!KMSDRM_GLES_SetupCrtc(_this, window)) {
-                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing vsync-ed pageflips");
-                return 0;
-            } 
-    }
-
-        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
-            vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
-        ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
-                                     DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip);
-        if (ret == 0) {
-            wdata->waiting_for_flip = SDL_TRUE;
-        } else {
-            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
+        ret = KMSDRM_drmModeSetPlane(vdata->drm_fd, wdata->plane_id, displaydata->crtc_id, fb_info->fb_id,
+            0, 0, 0, displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay,
+            0, 0, KMSDRM_gbm_bo_get_width(wdata->next_bo) << 16, KMSDRM_gbm_bo_get_height(wdata->next_bo) << 16);
+        if(ret != 0) {
+            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not drmModeSetPlane: %d", ret);
         }
     }
 
diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h
index 72c07a9..87e9397 100644
--- a/src/video/kmsdrm/SDL_kmsdrmsym.h
+++ b/src/video/kmsdrm/SDL_kmsdrmsym.h
@@ -40,13 +40,23 @@ SDL_KMSDRM_SYM(void,drmModeFreeFB,(drmModeFBPtr ptr))
 SDL_KMSDRM_SYM(void,drmModeFreeCrtc,(drmModeCrtcPtr ptr))
 SDL_KMSDRM_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr))
 SDL_KMSDRM_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr))
+SDL_KMSDRM_SYM(void,drmModeFreePlane,(drmModePlanePtr ptr))
+SDL_KMSDRM_SYM(void,drmModeFreePlaneResources,(drmModePlaneResPtr ptr))
+SDL_KMSDRM_SYM(void,drmModeFreeProperty,(drmModePropertyPtr ptr))
+SDL_KMSDRM_SYM(void,drmModeFreeObjectProperties,(drmModeObjectPropertiesPtr ptr))
+
 SDL_KMSDRM_SYM(drmModeResPtr,drmModeGetResources,(int fd))
+SDL_KMSDRM_SYM(drmModePlaneResPtr,drmModeGetPlaneResources,(int fd))
 SDL_KMSDRM_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth,
                                  uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
                                  uint32_t *buf_id))
 SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId))
 SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf))
 SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId))
+SDL_KMSDRM_SYM(drmModePlanePtr,drmModeGetPlane,(int fd, uint32_t plane_id))
+SDL_KMSDRM_SYM(drmModePropertyPtr,drmModeGetProperty,(int fd, uint32_t propertyId))
+SDL_KMSDRM_SYM(drmModeObjectPropertiesPtr,drmModeObjectGetProperties,
+               (int fd, uint32_t object_id, uint32_t object_type))
 SDL_KMSDRM_SYM(int,drmModeSetCrtc,(int fd, uint32_t crtcId, uint32_t bufferId,
                                    uint32_t x, uint32_t y, uint32_t *connectors, int count,
                                    drmModeModeInfoPtr mode))
@@ -55,13 +65,19 @@ SDL_KMSDRM_SYM(int,drmModeSetCursor,(int fd, uint32_t crtcId, uint32_t bo_handle
 SDL_KMSDRM_SYM(int,drmModeSetCursor2,(int fd, uint32_t crtcId, uint32_t bo_handle,
                                       uint32_t width, uint32_t height,
                                       int32_t hot_x, int32_t hot_y))
+SDL_KMSDRM_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))
 SDL_KMSDRM_SYM(int,drmModeMoveCursor,(int fd, uint32_t crtcId, int x, int y))
 SDL_KMSDRM_SYM(drmModeEncoderPtr,drmModeGetEncoder,(int fd, uint32_t encoder_id))
 SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connector_id))
 SDL_KMSDRM_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx))
 SDL_KMSDRM_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id,
                                     uint32_t flags, void *user_data))
-
+SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value))
 
 SDL_KMSDRM_MODULE(GBM)
 SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm))
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index ee3ac05..0e75156 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -224,12 +224,19 @@ KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout) {
     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
 
     while (wdata->waiting_for_flip) {
+        int ret;
+
         vdata->drm_pollfd.revents = 0;
-        if (poll(&vdata->drm_pollfd, 1, timeout) < 0) {
+        ret = poll(&vdata->drm_pollfd, 1, timeout);
+        if (ret < 0) {
             SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error");
             return SDL_FALSE;
         }
 
+        if (ret == 0) {
+            SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "DRM poll timeout");
+        }
+
         if (vdata->drm_pollfd.revents & (POLLHUP | POLLERR)) {
             SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error");
             return SDL_FALSE;
@@ -268,6 +275,7 @@ KMSDRM_VideoInit(_THIS)
     drmModeRes *resources = NULL;
     drmModeConnector *connector = NULL;
     drmModeEncoder *encoder = NULL;
+    drmModePlaneRes *plane_res = NULL;
     SDL_DisplayMode current_mode;
     SDL_VideoDisplay display;
 
@@ -295,6 +303,9 @@ KMSDRM_VideoInit(_THIS)
     }
     SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opened DRM FD (%d)", vdata->drm_fd);
 
+    KMSDRM_drmSetClientCap(vdata->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+    KMSDRM_drmSetClientCap(vdata->drm_fd, DRM_CLIENT_CAP_ATOMIC, 1);
+
     vdata->gbm = KMSDRM_gbm_create_device(vdata->drm_fd);
     if (vdata->gbm == NULL) {
         ret = SDL_SetError("Couldn't create gbm device.");
@@ -362,6 +373,56 @@ KMSDRM_VideoInit(_THIS)
     data->crtc_id = encoder->crtc_id;
     data->cur_mode = vdata->saved_crtc->mode;
 
+    plane_res = KMSDRM_drmModeGetPlaneResources(vdata->drm_fd);
+    if (!plane_res) {
+        ret = SDL_SetError("drmModeGetPlaneResources(%d) failed", vdata->drm_fd);
+        goto cleanup;
+    }
+    for (i = 0; i < plane_res->count_planes; i++) {
+        int j;
+        drmModeObjectPropertiesPtr props;
+        uint32_t plane_id = plane_res->planes[i];
+        drmModePlane *plane = KMSDRM_drmModeGetPlane(vdata->drm_fd, plane_id);
+        if (!plane) {
+            ret = SDL_SetError("drmModeGetPlane(%d)(%d) failed", vdata->drm_fd, plane_id);
+            goto cleanup;
+        }
+        props = KMSDRM_drmModeObjectGetProperties(vdata->drm_fd, plane_id, DRM_MODE_OBJECT_PLANE);
+        if (!props) {
+            ret = SDL_SetError("drmModeObjectGetProperties(%d)(%d) failed", vdata->drm_fd, plane_id);
+            KMSDRM_drmModeFreePlane(plane);
+            goto cleanup;
+        }
+        for (j = 0; j < props->count_props; j++) {
+            int z;
+            drmModePropertyPtr p = KMSDRM_drmModeGetProperty(vdata->drm_fd, props->props[j]);
+            uint64_t value = props->prop_values[j];
+
+            if (!p) {
+                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "drmModeGetProperty(%d)(%d) failed\n",
+                             vdata->drm_fd, plane_id);
+                continue;
+            }
+            if (strcmp(p->name, "type"))
+                continue;
+            for (z = 0; z < p->count_enums; z++) {
+                int n;
+                static const char* names[3] = { "Overlay", "Primary", "Cursor" };
+                if (p->enums[z].value != value)
+                    continue;
+                for (n = 0; n < 3; n++) {
+                    if (!strcmp(p->enums[z].name, names[n])) {
+                        data->plane_ids[n] = plane_id;
+                        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "%s : %d\n", names[n], plane_id);
+                        break;
+                    }
+                }
+            }
+            KMSDRM_drmModeFreeProperty(p);
+        }
+        KMSDRM_drmModeFreeObjectProperties(props);
+    }
+
     SDL_zero(current_mode);
 
     current_mode.w = vdata->saved_crtc->mode.hdisplay;
@@ -404,6 +465,8 @@ cleanup:
         KMSDRM_drmModeFreeConnector(connector);
     if (resources != NULL)
         KMSDRM_drmModeFreeResources(resources);
+    if (plane_res != NULL)
+        KMSDRM_drmModeFreePlaneResources(plane_res);
 
     if (ret != 0) {
         /* Error (complete) cleanup */
@@ -482,6 +545,7 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
     SDL_VideoDisplay *display;
     SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
     Uint32 surface_fmt, surface_flags;
+    char *display_plane_type = NULL;
 
     /* Allocate window internal data */
     wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
@@ -526,7 +590,22 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
        drmModePageFlip to work, and we can't do it until EGL is completely setup, because we
        need to do eglSwapBuffers so we can get a valid GBM buffer object to call 
        drmModeSetCrtc on it. */
-    wdata->crtc_ready = SDL_FALSE;    
+    wdata->crtc_ready = SDL_FALSE;
+    display_plane_type = getenv("SDL2_DISPLAY_PLANE_TYPE");
+
+    if (!display_plane_type)
+        wdata->plane_id = 0;
+    else {
+        if (!strcmp(display_plane_type, "OVERLAY"))
+            wdata->plane_id = ((SDL_DisplayData *)display->driverdata)->plane_ids[0];
+        else if (!strcmp(display_plane_type, "PRIMARY"))
+            wdata->plane_id = ((SDL_DisplayData *)display->driverdata)->plane_ids[1];
+        else if (!strcmp(display_plane_type, "CURSOR"))
+            wdata->plane_id = ((SDL_DisplayData *)display->driverdata)->plane_ids[2];
+        else
+            wdata->plane_id = 0;
+    }
+    SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Window set to plane id : %d\n", wdata->plane_id);
 
     /* Setup driver data for this window */
     window->driverdata = wdata;
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index 71f0de7..df41115 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -53,6 +53,7 @@ typedef struct SDL_DisplayData
     uint32_t encoder_id;
     uint32_t crtc_id;
     drmModeModeInfo cur_mode;
+    uint32_t plane_ids[3];  /* Overlay, Primary, Cursor */
 } SDL_DisplayData;
 
 
@@ -63,6 +64,7 @@ typedef struct SDL_WindowData
     struct gbm_bo *next_bo;
     SDL_bool waiting_for_flip;
     SDL_bool crtc_ready;
+    uint32_t plane_id;
 #if SDL_VIDEO_OPENGL_EGL
     EGLSurface egl_surface;
 #endif
-- 
2.7.4