Skip to content

Commit afca6d8

Browse files
committed
cogl/onscreen: Add API to scanout a buffer directly
Instead of always swapping buffers and flipping the back buffer, make it possible to scan out a provided buffer directly without swapping any EGL buffers. A buffer is passed as an object implementing the empty CoglScanout interface. It is only possible to do this in the native backend; and the interface is implemented by MetaDrmBufferGbm. When directly scanned out, instead of calling gbm_surface_lock_front_buffer() to get the gbm_bo and fbid, get it directly from the MetaDrmBufferGbm, and use that to create the page flip KMS update. Original Mutter commit: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/798/diffs?commit_id=3da8c1bfdc1fa486111c1e1dff363fb931612468
1 parent 4ff0a69 commit afca6d8

File tree

9 files changed

+186
-16
lines changed

9 files changed

+186
-16
lines changed

cogl/cogl/cogl-onscreen.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,27 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen)
405405
return winsys->onscreen_get_buffer_age (onscreen);
406406
}
407407

408+
void
409+
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
410+
CoglScanout *scanout)
411+
{
412+
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
413+
const CoglWinsysVtable *winsys;
414+
CoglFrameInfo *info;
415+
416+
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
417+
g_return_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT));
418+
419+
info = _cogl_frame_info_new ();
420+
info->frame_counter = onscreen->frame_counter;
421+
g_queue_push_tail (&onscreen->pending_frame_infos, info);
422+
423+
winsys = _cogl_framebuffer_get_winsys (framebuffer);
424+
winsys->onscreen_direct_scanout (onscreen, scanout);
425+
426+
onscreen->frame_counter++;
427+
}
428+
408429
#ifdef COGL_HAS_X11_SUPPORT
409430
uint32_t
410431
cogl_x11_onscreen_get_window_xid (CoglOnscreen *onscreen)

cogl/cogl/cogl-onscreen.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ G_BEGIN_DECLS
5050
typedef struct _CoglOnscreen CoglOnscreen;
5151
#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
5252

53+
typedef struct _CoglScanout CoglScanout;
54+
5355
/**
5456
* cogl_onscreen_get_gtype:
5557
*
@@ -284,6 +286,13 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
284286
const int *rectangles,
285287
int n_rectangles);
286288

289+
/**
290+
* cogl_onscreen_direct_scanout: (skip)
291+
*/
292+
void
293+
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
294+
CoglScanout *scanout);
295+
287296
/**
288297
* cogl_onscreen_swap_region:
289298
* @onscreen: A #CoglOnscreen framebuffer

cogl/cogl/cogl-scanout.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (C) 2019 Red Hat Inc.
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "cogl-config.h"
19+
20+
#include "cogl-scanout.h"
21+
22+
G_DEFINE_INTERFACE (CoglScanout, cogl_scanout, G_TYPE_OBJECT)
23+
24+
static void
25+
cogl_scanout_default_init (CoglScanoutInterface *iface)
26+
{
27+
}

cogl/cogl/cogl-scanout.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) 2019 Red Hat Inc.
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#ifndef COGL_SCANOUT_H
19+
#define COGL_SCANOUT_H
20+
21+
#include "cogl/cogl-types.h"
22+
23+
#include <glib-object.h>
24+
25+
#define COGL_TYPE_SCANOUT (cogl_scanout_get_type ())
26+
COGL_EXPORT
27+
G_DECLARE_INTERFACE (CoglScanout, cogl_scanout,
28+
COGL, SCANOUT, GObject)
29+
30+
struct _CoglScanoutInterface
31+
{
32+
GTypeInterface parent_iface;
33+
};
34+
35+
#endif /* COGL_SCANOUT_H */

cogl/cogl/cogl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
#include <cogl/cogl-fence.h>
123123
#include <cogl/cogl-glib-source.h>
124124
#include <cogl/cogl-trace.h>
125+
#include <cogl/cogl-scanout.h>
125126
/* XXX: This will definitly go away once all the Clutter winsys
126127
* code has been migrated down into Cogl! */
127128
#include <cogl/deprecated/cogl-clutter.h>

cogl/cogl/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ cogl_nonintrospected_headers = [
122122
'cogl-version.h',
123123
'cogl-gtype-private.h',
124124
'cogl-glib-source.h',
125+
'cogl-scanout.h',
125126
]
126127

127128
cogl_nodist_headers = [
@@ -347,6 +348,7 @@ cogl_sources = [
347348
'cogl-closure-list.c',
348349
'cogl-fence.c',
349350
'cogl-fence-private.h',
351+
'cogl-scanout.c',
350352
'deprecated/cogl-material-compat.c',
351353
'deprecated/cogl-program.c',
352354
'deprecated/cogl-program-private.h',

cogl/cogl/winsys/cogl-winsys-private.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
#include "cogl-renderer.h"
3535
#include "cogl-onscreen.h"
36+
#include "cogl-scanout.h"
3637

3738
#ifdef COGL_HAS_XLIB_SUPPORT
3839
#include "cogl-texture-pixmap-x11-private.h"
@@ -117,6 +118,10 @@ typedef struct _CoglWinsysVtable
117118
const int *rectangles,
118119
int n_rectangles);
119120

121+
void
122+
(*onscreen_direct_scanout) (CoglOnscreen *onscreen,
123+
CoglScanout *scanout);
124+
120125
void
121126
(*onscreen_set_visibility) (CoglOnscreen *onscreen,
122127
gboolean visibility);

src/backends/native/meta-drm-buffer-gbm.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ struct _MetaDrmBufferGbm
4444
uint32_t fb_id;
4545
};
4646

47-
G_DEFINE_TYPE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER)
47+
static void
48+
cogl_scanout_iface_init (CoglScanoutInterface *iface);
49+
50+
G_DEFINE_TYPE_WITH_CODE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER,
51+
G_IMPLEMENT_INTERFACE (COGL_TYPE_SCANOUT,
52+
cogl_scanout_iface_init))
4853

4954
struct gbm_bo *
5055
meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm)
@@ -160,6 +165,11 @@ meta_drm_buffer_gbm_get_fb_id (MetaDrmBuffer *buffer)
160165
return META_DRM_BUFFER_GBM (buffer)->fb_id;
161166
}
162167

168+
static void
169+
cogl_scanout_iface_init (CoglScanoutInterface *iface)
170+
{
171+
}
172+
163173
static void
164174
meta_drm_buffer_gbm_finalize (GObject *object)
165175
{

src/backends/native/meta-renderer-native.c

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,35 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
20132013
}
20142014
}
20152015

2016+
static void
2017+
ensure_crtc_modes (CoglOnscreen *onscreen,
2018+
MetaKmsUpdate *kms_update)
2019+
{
2020+
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
2021+
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
2022+
CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
2023+
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
2024+
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
2025+
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
2026+
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
2027+
MetaRenderer *renderer = META_RENDERER (renderer_native);
2028+
MetaBackend *backend = meta_renderer_get_backend (renderer);
2029+
MetaMonitorManager *monitor_manager =
2030+
meta_backend_get_monitor_manager (backend);
2031+
MetaPowerSave power_save_mode;
2032+
2033+
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
2034+
if (onscreen_native->pending_set_crtc &&
2035+
power_save_mode == META_POWER_SAVE_ON)
2036+
{
2037+
meta_onscreen_native_set_crtc_mode (onscreen,
2038+
renderer_gpu_data,
2039+
kms_update);
2040+
onscreen_native->pending_set_crtc = FALSE;
2041+
}
2042+
}
2043+
2044+
20162045
static MetaKmsUpdate *
20172046
unset_disabled_crtcs (MetaBackend *backend,
20182047
MetaKms *kms)
@@ -2068,8 +2097,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
20682097
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
20692098
MetaRenderer *renderer = META_RENDERER (renderer_native);
20702099
MetaBackend *backend = meta_renderer_get_backend (renderer);
2071-
MetaMonitorManager *monitor_manager =
2072-
meta_backend_get_monitor_manager (backend);
20732100
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
20742101
MetaKms *kms = meta_backend_native_get_kms (backend_native);
20752102
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
@@ -2078,7 +2105,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
20782105
CoglFrameInfo *frame_info;
20792106
gboolean egl_context_changed = FALSE;
20802107
MetaKmsUpdate *kms_update;
2081-
MetaPowerSave power_save_mode;
20822108
g_autoptr (GError) error = NULL;
20832109
MetaDrmBufferGbm *buffer_gbm;
20842110
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
@@ -2137,18 +2163,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
21372163

21382164
update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed);
21392165

2140-
/* If this is the first framebuffer to be presented then we now setup the
2141-
* crtc modes, else we flip from the previous buffer */
2142-
2143-
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
2144-
if (onscreen_native->pending_set_crtc &&
2145-
power_save_mode == META_POWER_SAVE_ON)
2146-
{
2147-
meta_onscreen_native_set_crtc_mode (onscreen,
2148-
renderer_gpu_data,
2149-
kms_update);
2150-
onscreen_native->pending_set_crtc = FALSE;
2151-
}
2166+
ensure_crtc_modes (onscreen, kms_update);
21522167

21532168
onscreen_native->pending_queue_swap_notify_frame_count = renderer_native->frame_counter;
21542169
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
@@ -2239,6 +2254,50 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
22392254
return NULL;
22402255
}
22412256

2257+
static void
2258+
meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
2259+
CoglScanout *scanout)
2260+
{
2261+
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
2262+
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
2263+
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
2264+
CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
2265+
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
2266+
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
2267+
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
2268+
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
2269+
MetaRenderer *renderer = META_RENDERER (renderer_native);
2270+
MetaBackend *backend = meta_renderer_get_backend (renderer);
2271+
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
2272+
MetaKms *kms = meta_backend_native_get_kms (backend_native);
2273+
CoglFrameInfo *frame_info;
2274+
MetaKmsUpdate *kms_update;
2275+
g_autoptr (GError) error = NULL;
2276+
2277+
kms_update = meta_kms_ensure_pending_update (kms);
2278+
2279+
wait_for_pending_flips (onscreen);
2280+
2281+
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
2282+
frame_info->global_frame_counter = renderer_native->frame_counter;
2283+
2284+
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
2285+
render_gpu);
2286+
2287+
g_return_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM);
2288+
2289+
g_warn_if_fail (!onscreen_native->gbm.next_fb);
2290+
g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout));
2291+
2292+
ensure_crtc_modes (onscreen, kms_update);
2293+
2294+
onscreen_native->pending_queue_swap_notify_frame_count =
2295+
renderer_native->frame_counter;
2296+
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
2297+
2298+
meta_kms_post_pending_update_sync (kms);
2299+
}
2300+
22422301
static gboolean
22432302
meta_renderer_native_init_egl_context (CoglContext *cogl_context,
22442303
GError **error)
@@ -2962,6 +3021,7 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
29623021
vtable.onscreen_swap_region = NULL;
29633022
vtable.onscreen_swap_buffers_with_damage =
29643023
meta_onscreen_native_swap_buffers_with_damage;
3024+
vtable.onscreen_direct_scanout = meta_onscreen_native_direct_scanout;
29653025

29663026
vtable.context_get_clock_time = meta_renderer_native_get_clock_time;
29673027

0 commit comments

Comments
 (0)