Skip to content

Commit

Permalink
wayland-egl: eliminate vulkan producer ABI
Browse files Browse the repository at this point in the history
Earlier, vulkan producer was allocating WlEglSurface, fill some members and
pass it to wayland-egl through wlEglInitializeSurfaceExport() API,
accessing the eglStream handle from the WlEglSurface.

Since the allocation happens at vulkan producer, addition of any new
members to WlEglSurface struct breaks the ABI with vulkan producer.

This change moves the allocation to wayland-egl, and
wlEglInitializeSurfaceExport() accepts some arguments which will be set to
the allocated wlEglSurface struct. A new API is added to query the
Eglstream handle from wlEglSurface instance. This will break the ABI for
one last time and avoid any future breakages.
  • Loading branch information
maniraj87 authored and Erik Kurzinger committed May 31, 2022
1 parent c6fb3d3 commit e7a2f70
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 167 deletions.
189 changes: 189 additions & 0 deletions include/wayland-eglsurface-internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/

#ifndef WAYLAND_EGLSURFACE_INTERNAL_H
#define WAYLAND_EGLSURFACE_INTERNAL_H

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <pthread.h>
#include <wayland-client.h>
#include "wayland-egldisplay.h"
#include "wayland-eglutils.h"
#include "wayland-eglsurface.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct WlEglStreamImageRec {
/* Pointer back to the parent surface for use in Wayland callbacks */
struct WlEglSurfaceRec *surface;

/*
* Use an individual mutex to guard access to each image's data. This avoids
* sharing the surface lock between the app and buffer release event
* threads, resulting in simplified lock management and smaller critical
* sections.
*/
pthread_mutex_t mutex;

EGLImageKHR eglImage;
struct wl_buffer *buffer;
EGLBoolean attached;
struct wl_list acquiredLink;
} WlEglStreamImage;

typedef struct WlEglSurfaceCtxRec {
EGLBoolean isOffscreen;
EGLSurface eglSurface;
EGLStreamKHR eglStream;
void *wlStreamResource;
EGLBoolean isAttached;

int useDamageThread;
pthread_t damageThreadId;
EGLSyncKHR damageThreadSync;
int damageThreadFlush;
int damageThreadShutdown;
EGLuint64KHR framesProduced;
EGLuint64KHR framesFinished;
EGLuint64KHR framesProcessed;

/*
* The double pointer is because of the need to allocate the data for each
* image slot separately to avoid clobbering the acquiredLink member
* whenever the streamImages arrary is resized with realloc().
*/
WlEglStreamImage **streamImages;
struct wl_list acquiredImages;
struct wl_buffer *currentBuffer;
uint32_t numStreamImages;

struct wl_list link;
} WlEglSurfaceCtx;

struct WlEglSurfaceRec {
WlEglDisplay *wlEglDpy;
EGLConfig eglConfig;
EGLint *attribs;
EGLBoolean pendingSwapIntervalUpdate;

struct wl_egl_window *wlEglWin;
long int wlEglWinVer;
struct wl_surface *wlSurface;
int width, height;
int dx, dy;

WlEglSurfaceCtx ctx;
struct wl_list oldCtxList;

EGLint swapInterval;
EGLint fifoLength;

struct wl_callback *throttleCallback;
struct wl_event_queue *wlEventQueue;

/* Asynchronous wl_buffer.release event processing */
struct {
struct wl_event_queue *wlBufferEventQueue;
pthread_t bufferReleaseThreadId;
int bufferReleaseThreadPipe[2];
};

struct wl_list link;

EGLBoolean isSurfaceProducer;

/* The refCount is initialized to 1 during EGLSurface creation,
* gets incremented/decrementsd in wlEglSurfaceRef()/wlEglSurfaceUnref(),
* when we enter/exit from eglSwapBuffers().
*/
unsigned int refCount;
/*
* Set to EGL_TRUE before destroying the EGLSurface in eglDestroySurface().
*/
EGLBoolean isDestroyed;

/* The lock is used to serialize eglSwapBuffers()/eglDestroySurface(),
* Using wlExternalApiLock() for this requires that we release lock
* before dispatching frame sync events in wlEglWaitFrameSync().
*/
pthread_mutex_t mutexLock;

/* True when the EGL_PRESENT_OPAQUE_EXT surface attrib is set by the app */
EGLBoolean presentOpaque;

/* We want to delay the resizing of the window surface until the next
* eglSwapBuffers(), so just set a resize flag.
*/
EGLBoolean isResized;
};

void wlEglResizeSurfaceIfRequired(WlEglDisplay *display,
WlEglPlatformData *pData,
WlEglSurface *surface);

EGLSurface wlEglCreatePlatformWindowSurfaceHook(EGLDisplay dpy,
EGLConfig config,
void *nativeWin,
const EGLAttrib *attribs);
EGLSurface wlEglCreatePlatformPixmapSurfaceHook(EGLDisplay dpy,
EGLConfig config,
void *nativePixmap,
const EGLAttrib *attribs);
EGLSurface wlEglCreatePbufferSurfaceHook(EGLDisplay dpy,
EGLConfig config,
const EGLint *attribs);
EGLSurface wlEglCreateStreamProducerSurfaceHook(EGLDisplay dpy,
EGLConfig config,
EGLStreamKHR stream,
const EGLint *attribs);
EGLBoolean wlEglDestroySurfaceHook(EGLDisplay dpy, EGLSurface eglSurface);
EGLBoolean wlEglDestroyAllSurfaces(WlEglDisplay *display);

EGLBoolean wlEglIsWaylandWindowValid(struct wl_egl_window *window);
EGLBoolean wlEglIsWlEglSurfaceForDisplay(WlEglDisplay *display, WlEglSurface *wlEglSurface);

EGLBoolean wlEglQuerySurfaceHook(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value);

EGLBoolean wlEglQueryNativeResourceHook(EGLDisplay dpy,
void *nativeResource,
EGLint attribute,
int *value);

EGLBoolean wlEglSendDamageEvent(WlEglSurface *surface,
struct wl_event_queue *queue);

void wlEglCreateFrameSync(WlEglSurface *surface);
EGLint wlEglWaitFrameSync(WlEglSurface *surface);

EGLBoolean wlEglSurfaceRef(WlEglDisplay *display, WlEglSurface *surface);
void wlEglSurfaceUnref(WlEglSurface *surface);

EGLint wlEglHandleImageStreamEvents(WlEglSurface *surface);

#ifdef __cplusplus
}
#endif

#endif
156 changes: 9 additions & 147 deletions include/wayland-eglsurface.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
Expand Down Expand Up @@ -34,155 +34,17 @@
extern "C" {
#endif

typedef struct WlEglStreamImageRec {
/* Pointer back to the parent surface for use in Wayland callbacks */
struct WlEglSurfaceRec *surface;

/*
* Use an individual mutex to guard access to each image's data. This avoids
* sharing the surface lock between the app and buffer release event
* threads, resulting in simplified lock management and smaller critical
* sections.
*/
pthread_mutex_t mutex;

EGLImageKHR eglImage;
struct wl_buffer *buffer;
EGLBoolean attached;
struct wl_list acquiredLink;
} WlEglStreamImage;

typedef struct WlEglSurfaceCtxRec {
EGLBoolean isOffscreen;
EGLSurface eglSurface;
EGLStreamKHR eglStream;
void *wlStreamResource;
EGLBoolean isAttached;

int useDamageThread;
pthread_t damageThreadId;
EGLSyncKHR damageThreadSync;
int damageThreadFlush;
int damageThreadShutdown;
EGLuint64KHR framesProduced;
EGLuint64KHR framesFinished;
EGLuint64KHR framesProcessed;

/*
* The double pointer is because of the need to allocate the data for each
* image slot separately to avoid clobbering the acquiredLink member
* whenever the streamImages arrary is resized with realloc().
*/
WlEglStreamImage **streamImages;
struct wl_list acquiredImages;
struct wl_buffer *currentBuffer;
uint32_t numStreamImages;

struct wl_list link;
} WlEglSurfaceCtx;

typedef struct WlEglSurfaceRec {
WlEglDisplay *wlEglDpy;
EGLConfig eglConfig;
EGLint *attribs;
EGLBoolean pendingSwapIntervalUpdate;

struct wl_egl_window *wlEglWin;
long int wlEglWinVer;
struct wl_surface *wlSurface;
int width, height;
int dx, dy;

WlEglSurfaceCtx ctx;
struct wl_list oldCtxList;

EGLint swapInterval;
EGLint fifoLength;

struct wl_callback *throttleCallback;
struct wl_event_queue *wlEventQueue;

/* Asynchronous wl_buffer.release event processing */
struct {
struct wl_event_queue *wlBufferEventQueue;
pthread_t bufferReleaseThreadId;
int bufferReleaseThreadPipe[2];
};

struct wl_list link;

EGLBoolean isSurfaceProducer;

/* The refCount is initialized to 1 during EGLSurface creation,
* gets incremented/decrementsd in wlEglSurfaceRef()/wlEglSurfaceUnref(),
* when we enter/exit from eglSwapBuffers().
*/
unsigned int refCount;
/*
* Set to EGL_TRUE before destroying the EGLSurface in eglDestroySurface().
*/
EGLBoolean isDestroyed;

/* The lock is used to serialize eglSwapBuffers()/eglDestroySurface(),
* Using wlExternalApiLock() for this requires that we release lock
* before dispatching frame sync events in wlEglWaitFrameSync().
*/
pthread_mutex_t mutexLock;

/* We want to delay the resizing of the window surface until the next
* eglSwapBuffers(), so just set a resize flag.
*/
EGLBoolean isResized;

/* True when the EGL_PRESENT_OPAQUE_EXT surface attrib is set by the app */
EGLBoolean presentOpaque;
} WlEglSurface;
typedef struct WlEglSurfaceRec WlEglSurface;

WL_EXPORT
EGLBoolean wlEglInitializeSurfaceExport(WlEglSurface *surface);

void wlEglResizeSurfaceIfRequired(WlEglDisplay *display,
WlEglPlatformData *pData,
WlEglSurface *surface);

EGLSurface wlEglCreatePlatformWindowSurfaceHook(EGLDisplay dpy,
EGLConfig config,
void *nativeWin,
const EGLAttrib *attribs);
EGLSurface wlEglCreatePlatformPixmapSurfaceHook(EGLDisplay dpy,
EGLConfig config,
void *nativePixmap,
const EGLAttrib *attribs);
EGLSurface wlEglCreatePbufferSurfaceHook(EGLDisplay dpy,
EGLConfig config,
const EGLint *attribs);
EGLSurface wlEglCreateStreamProducerSurfaceHook(EGLDisplay dpy,
EGLConfig config,
EGLStreamKHR stream,
const EGLint *attribs);
EGLBoolean wlEglDestroySurfaceHook(EGLDisplay dpy, EGLSurface eglSurface);
EGLBoolean wlEglDestroyAllSurfaces(WlEglDisplay *display);

EGLBoolean wlEglIsWaylandWindowValid(struct wl_egl_window *window);
EGLBoolean wlEglIsWlEglSurfaceForDisplay(WlEglDisplay *display, WlEglSurface *wlEglSurface);
EGLStreamKHR wlEglGetSurfaceStreamExport(WlEglSurface *surface);

EGLBoolean wlEglQuerySurfaceHook(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value);

EGLBoolean wlEglQueryNativeResourceHook(EGLDisplay dpy,
void *nativeResource,
EGLint attribute,
int *value);

EGLBoolean wlEglSendDamageEvent(WlEglSurface *surface,
struct wl_event_queue *queue);

void wlEglCreateFrameSync(WlEglSurface *surface);
EGLint wlEglWaitFrameSync(WlEglSurface *surface);

EGLBoolean wlEglSurfaceRef(WlEglDisplay *display, WlEglSurface *surface);
void wlEglSurfaceUnref(WlEglSurface *surface);

EGLint wlEglHandleImageStreamEvents(WlEglSurface *surface);
WL_EXPORT
WlEglSurface *wlEglInitializeSurfaceExport(EGLDisplay dpy,
int width,
int height,
struct wl_surface *native_surface,
int fifo_length);

#ifdef __cplusplus
}
Expand Down
4 changes: 2 additions & 2 deletions src/wayland-egldisplay.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
Expand All @@ -26,7 +26,7 @@
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "wayland-eglstream-server.h"
#include "wayland-thread.h"
#include "wayland-eglsurface.h"
#include "wayland-eglsurface-internal.h"
#include "wayland-eglhandle.h"
#include "wayland-eglutils.h"
#include "wayland-drm-client-protocol.h"
Expand Down
4 changes: 2 additions & 2 deletions src/wayland-eglhandle.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
Expand All @@ -22,7 +22,7 @@

#include "wayland-eglhandle.h"
#include "wayland-egldisplay.h"
#include "wayland-eglsurface.h"
#include "wayland-eglsurface-internal.h"
#include "wayland-thread.h"
#include <stdlib.h>
#include <errno.h>
Expand Down
Loading

0 comments on commit e7a2f70

Please sign in to comment.