mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-11-01 03:18:02 +03:00
init
This commit is contained in:
12511 files changed
+6156641
No files matched your search
@@ -0,0 +1,5 @@
|
||||
BasedOnStyle: InheritParentConfig
|
||||
DisableFormat: false
|
||||
|
||||
ColumnLimit: 80
|
||||
AlwaysBreakAfterReturnType: All
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* 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 (including the next
|
||||
* paragraph) 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.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef EGL_DRI2_INCLUDED
|
||||
#define EGL_DRI2_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xfixes.h>
|
||||
|
||||
#include "loader_dri_helper.h"
|
||||
#ifdef HAVE_LIBDRM
|
||||
#include "loader_dri3_helper.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
#include "loader_wayland_helper.h"
|
||||
|
||||
/* forward declarations to avoid pulling wayland headers everywhere */
|
||||
struct wl_egl_window;
|
||||
struct wl_event_queue;
|
||||
struct wl_callback;
|
||||
struct wl_display;
|
||||
struct wl_drm;
|
||||
struct wl_registry;
|
||||
struct wl_shm;
|
||||
struct wl_surface;
|
||||
struct wl_fixes;
|
||||
struct zwp_linux_dmabuf_v1;
|
||||
struct zwp_linux_dmabuf_feedback_v1;
|
||||
#endif
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include "mesa_interface.h"
|
||||
#include "kopper_interface.h"
|
||||
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
#include <gbm_driint.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID_PLATFORM
|
||||
#define LOG_TAG "EGL-DRI2"
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#include "util/u_gralloc/u_gralloc.h"
|
||||
|
||||
#if ANDROID_API_LEVEL >= 26
|
||||
#include <vndk/window.h>
|
||||
#else
|
||||
#include <system/window.h>
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_ANDROID_PLATFORM */
|
||||
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "eglcurrent.h"
|
||||
#include "egldevice.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglimage.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglsync.h"
|
||||
|
||||
#include "util/bitset.h"
|
||||
#include "util/u_dynarray.h"
|
||||
#include "util/u_vector.h"
|
||||
#include "util/format/u_format.h"
|
||||
|
||||
struct wl_buffer;
|
||||
|
||||
struct dri2_egl_display_vtbl {
|
||||
/* mandatory on Wayland, unused otherwise */
|
||||
int (*authenticate)(_EGLDisplay *disp, uint32_t id);
|
||||
|
||||
/* mandatory */
|
||||
_EGLSurface *(*create_window_surface)(_EGLDisplay *disp, _EGLConfig *config,
|
||||
void *native_window,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
/* optional */
|
||||
_EGLSurface *(*create_pixmap_surface)(_EGLDisplay *disp, _EGLConfig *config,
|
||||
void *native_pixmap,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
/* optional */
|
||||
_EGLSurface *(*create_pbuffer_surface)(_EGLDisplay *disp, _EGLConfig *config,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
/* mandatory */
|
||||
EGLBoolean (*destroy_surface)(_EGLDisplay *disp, _EGLSurface *surface);
|
||||
|
||||
/* optional */
|
||||
EGLBoolean (*swap_interval)(_EGLDisplay *disp, _EGLSurface *surf,
|
||||
EGLint interval);
|
||||
|
||||
/* mandatory */
|
||||
_EGLImage *(*create_image)(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
EGLenum target, EGLClientBuffer buffer,
|
||||
const EGLint *attr_list);
|
||||
|
||||
/* mandatory */
|
||||
EGLBoolean (*swap_buffers)(_EGLDisplay *disp, _EGLSurface *surf);
|
||||
|
||||
/* optional - falls back to .swap_buffers */
|
||||
EGLBoolean (*swap_buffers_with_damage)(_EGLDisplay *disp,
|
||||
_EGLSurface *surface,
|
||||
const EGLint *rects, EGLint n_rects);
|
||||
|
||||
/* optional */
|
||||
EGLBoolean (*copy_buffers)(_EGLDisplay *disp, _EGLSurface *surf,
|
||||
void *native_pixmap_target);
|
||||
|
||||
/* optional */
|
||||
EGLint (*query_buffer_age)(_EGLDisplay *disp, _EGLSurface *surf);
|
||||
|
||||
/* optional */
|
||||
EGLBoolean (*query_surface)(_EGLDisplay *disp, _EGLSurface *surf,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
/* optional */
|
||||
struct wl_buffer *(*create_wayland_buffer_from_image)(_EGLDisplay *disp,
|
||||
_EGLImage *img);
|
||||
|
||||
/* optional */
|
||||
EGLBoolean (*get_sync_values)(_EGLDisplay *display, _EGLSurface *surface,
|
||||
EGLuint64KHR *ust, EGLuint64KHR *msc,
|
||||
EGLuint64KHR *sbc);
|
||||
|
||||
/* optional */
|
||||
EGLBoolean (*get_msc_rate)(_EGLDisplay *display, _EGLSurface *surface,
|
||||
EGLint *numerator, EGLint *denominator);
|
||||
|
||||
/* mandatory */
|
||||
struct dri_drawable *(*get_dri_drawable)(_EGLSurface *surf);
|
||||
|
||||
/* optional */
|
||||
void (*close_screen_notify)(_EGLDisplay *disp);
|
||||
|
||||
/* Used in EGL_KHR_mutable_render_buffer to update the native window's
|
||||
* shared buffer mode.
|
||||
* optional
|
||||
*/
|
||||
bool (*set_shared_buffer_mode)(_EGLDisplay *disp, _EGLSurface *surf,
|
||||
bool mode);
|
||||
};
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
struct dri2_wl_formats {
|
||||
unsigned int num_formats;
|
||||
|
||||
/* Bitmap referencing dri2_wl_visuals */
|
||||
unsigned int *formats_bitmap;
|
||||
|
||||
/* Array of vectors. Contains one modifier vector per format */
|
||||
struct u_vector *modifiers;
|
||||
};
|
||||
|
||||
struct dmabuf_feedback_format_table {
|
||||
unsigned int size;
|
||||
struct {
|
||||
uint32_t format;
|
||||
uint32_t padding; /* unused */
|
||||
uint64_t modifier;
|
||||
} *data;
|
||||
};
|
||||
|
||||
struct dmabuf_feedback_tranche {
|
||||
dev_t target_device;
|
||||
uint32_t flags;
|
||||
struct dri2_wl_formats formats;
|
||||
};
|
||||
|
||||
struct dmabuf_feedback {
|
||||
dev_t main_device;
|
||||
struct dmabuf_feedback_format_table format_table;
|
||||
struct util_dynarray tranches;
|
||||
struct dmabuf_feedback_tranche pending_tranche;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct dri2_egl_display {
|
||||
const struct dri2_egl_display_vtbl *vtbl;
|
||||
|
||||
mtx_t lock;
|
||||
|
||||
struct dri_screen *dri_screen_render_gpu;
|
||||
/* dri_screen_display_gpu holds display GPU in case of prime gpu offloading
|
||||
* else dri_screen_render_gpu and dri_screen_display_gpu is same. In case of
|
||||
* prime gpu offloading, if display and render driver names are different
|
||||
* (potentially not compatible), dri_screen_display_gpu will be NULL but
|
||||
* fd_display_gpu will still hold fd for display driver.
|
||||
*/
|
||||
struct dri_screen *dri_screen_display_gpu;
|
||||
bool own_dri_screen;
|
||||
const struct dri_config **driver_configs;
|
||||
/* fd of the GPU used for rendering. */
|
||||
int fd_render_gpu;
|
||||
/* fd of the GPU used for display. If the same GPU is used for display
|
||||
* and rendering, then fd_render_gpu == fd_display_gpu (no need to use
|
||||
* os_same_file_description).
|
||||
*/
|
||||
int fd_display_gpu;
|
||||
|
||||
/* dri2_initialize/dri2_terminate increment/decrement this count, so does
|
||||
* dri2_make_current (tracks if there are active contexts/surfaces). */
|
||||
int ref_count;
|
||||
|
||||
bool has_compression_modifiers;
|
||||
bool own_device;
|
||||
bool kopper;
|
||||
bool swrast;
|
||||
bool swrast_not_kms;
|
||||
int min_swap_interval;
|
||||
int max_swap_interval;
|
||||
int default_swap_interval;
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
struct gbm_dri_device *gbm_dri;
|
||||
#endif
|
||||
|
||||
char *driver_name;
|
||||
|
||||
const __DRIextension **loader_extensions;
|
||||
|
||||
bool has_dmabuf_import;
|
||||
bool has_dmabuf_export;
|
||||
bool explicit_modifiers;
|
||||
bool multibuffers_available;
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
xcb_connection_t *conn;
|
||||
xcb_screen_t *screen;
|
||||
bool swap_available;
|
||||
#ifdef HAVE_LIBDRM
|
||||
struct loader_screen_resources screen_resources;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
struct wl_display *wl_dpy;
|
||||
struct wl_display *wl_dpy_wrapper;
|
||||
struct wl_registry *wl_registry;
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
struct wl_drm *wl_server_drm;
|
||||
struct wl_drm *wl_drm;
|
||||
uint32_t wl_drm_version, wl_drm_name;
|
||||
bool authenticated;
|
||||
uint32_t capabilities;
|
||||
#endif
|
||||
struct wl_shm *wl_shm;
|
||||
struct wl_event_queue *wl_queue;
|
||||
struct wl_fixes *wl_fixes;
|
||||
struct zwp_linux_dmabuf_v1 *wl_dmabuf;
|
||||
struct wp_presentation *wp_presentation;
|
||||
struct dri2_wl_formats formats;
|
||||
struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback;
|
||||
struct dmabuf_feedback_format_table format_table;
|
||||
char *device_name;
|
||||
bool is_render_node;
|
||||
clockid_t presentation_clock_id;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID_PLATFORM
|
||||
struct u_gralloc *gralloc;
|
||||
/* gralloc vendor usage bit for front rendering */
|
||||
uint32_t front_rendering_usage;
|
||||
bool has_native_fence_fd;
|
||||
bool pure_swrast;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dri2_egl_context {
|
||||
_EGLContext base;
|
||||
struct dri_context *dri_context;
|
||||
};
|
||||
|
||||
struct dri2_egl_surface {
|
||||
_EGLSurface base;
|
||||
struct dri_drawable *dri_drawable;
|
||||
__DRIbuffer buffers[5];
|
||||
bool have_fake_front;
|
||||
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
xcb_drawable_t drawable;
|
||||
xcb_xfixes_region_t region;
|
||||
int depth;
|
||||
int bytes_per_pixel;
|
||||
xcb_gcontext_t gc;
|
||||
xcb_gcontext_t swapgc;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
struct wl_egl_window *wl_win;
|
||||
int dx;
|
||||
int dy;
|
||||
struct wl_event_queue *wl_queue;
|
||||
struct loader_wayland_surface wayland_surface;
|
||||
struct wl_display *wl_dpy_wrapper;
|
||||
struct wl_drm *wl_drm_wrapper;
|
||||
struct wl_callback *throttle_callback;
|
||||
struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback;
|
||||
struct dmabuf_feedback dmabuf_feedback, pending_dmabuf_feedback;
|
||||
struct loader_wayland_presentation wayland_presentation;
|
||||
bool compositor_using_another_device;
|
||||
int format;
|
||||
bool resized;
|
||||
bool received_dmabuf_feedback;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
struct gbm_dri_surface *gbm_surf;
|
||||
unsigned excess_bo_frames;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM)
|
||||
struct dri2_egl_buffer {
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
struct loader_wayland_buffer wayland_buffer;
|
||||
bool wl_release;
|
||||
struct dri_image *dri_image;
|
||||
/* for is_different_gpu case. NULL else */
|
||||
struct dri_image *linear_copy;
|
||||
/* for swrast */
|
||||
void *data;
|
||||
int data_size;
|
||||
#endif
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
struct gbm_bo *bo;
|
||||
#endif
|
||||
bool locked;
|
||||
int age;
|
||||
} color_buffers[4], *back, *current;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID_PLATFORM
|
||||
struct ANativeWindow *window;
|
||||
struct ANativeWindowBuffer *buffer;
|
||||
|
||||
/* in-fence associated with buffer, -1 once passed down to dri layer: */
|
||||
int in_fence_fd;
|
||||
|
||||
struct dri_image *dri_image_back;
|
||||
struct dri_image *dri_image_front;
|
||||
|
||||
/* Used to record all the buffers created by ANativeWindow and their ages.
|
||||
* Allocate number of color_buffers based on query to android bufferqueue
|
||||
* and save color_buffers_count.
|
||||
*/
|
||||
int color_buffers_count;
|
||||
struct {
|
||||
struct ANativeWindowBuffer *buffer;
|
||||
int age;
|
||||
} *color_buffers, *back;
|
||||
uint32_t gralloc_usage;
|
||||
#endif
|
||||
|
||||
/* surfaceless and device */
|
||||
struct dri_image *front;
|
||||
enum pipe_format visual;
|
||||
|
||||
int out_fence_fd;
|
||||
EGLBoolean enable_out_fence;
|
||||
|
||||
/* swrast device */
|
||||
char *swrast_device_buffer;
|
||||
};
|
||||
|
||||
struct dri2_egl_config {
|
||||
_EGLConfig base;
|
||||
const struct dri_config *dri_config[2][2];
|
||||
};
|
||||
|
||||
struct dri2_egl_image {
|
||||
_EGLImage base;
|
||||
struct dri_image *dri_image;
|
||||
};
|
||||
|
||||
struct dri2_egl_sync {
|
||||
_EGLSync base;
|
||||
mtx_t mutex;
|
||||
cnd_t cond;
|
||||
int refcount;
|
||||
void *fence;
|
||||
};
|
||||
|
||||
/* standard typecasts */
|
||||
_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
|
||||
_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
|
||||
_EGL_DRIVER_TYPECAST(dri2_egl_sync, _EGLSync, obj)
|
||||
|
||||
static inline struct dri2_egl_display *
|
||||
dri2_egl_display_lock(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
if (dri2_dpy)
|
||||
mtx_lock(&dri2_dpy->lock);
|
||||
|
||||
return dri2_dpy;
|
||||
}
|
||||
|
||||
static inline EGLBoolean
|
||||
dri2_egl_error_unlock(struct dri2_egl_display *dri2_dpy, EGLint err,
|
||||
const char *msg)
|
||||
{
|
||||
mtx_unlock(&dri2_dpy->lock);
|
||||
return _eglError(err, msg);
|
||||
}
|
||||
|
||||
extern const __DRIimageLookupExtension image_lookup_extension;
|
||||
extern const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension;
|
||||
extern const __DRIkopperLoaderExtension kopper_pbuffer_loader_extension;
|
||||
|
||||
void
|
||||
dri2_detect_swrast_kopper(_EGLDisplay *disp);
|
||||
|
||||
/* Helper for platforms not using dri2_create_screen */
|
||||
void
|
||||
dri2_setup_screen(_EGLDisplay *disp);
|
||||
|
||||
void
|
||||
dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval);
|
||||
|
||||
EGLBoolean
|
||||
dri2_create_screen(_EGLDisplay *disp);
|
||||
|
||||
EGLBoolean
|
||||
dri2_setup_device(_EGLDisplay *disp, EGLBoolean software);
|
||||
|
||||
struct dri_drawable *
|
||||
dri2_surface_get_dri_drawable(_EGLSurface *surf);
|
||||
|
||||
GLboolean
|
||||
dri2_validate_egl_image(void *image, void *data);
|
||||
|
||||
struct dri_image *
|
||||
dri2_lookup_egl_image_validated(void *image, void *data);
|
||||
|
||||
void
|
||||
dri2_get_shifts_and_sizes(const struct dri_config *config, int *shifts,
|
||||
unsigned int *sizes);
|
||||
|
||||
enum pipe_format
|
||||
dri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy,
|
||||
const struct dri_config *config);
|
||||
|
||||
struct dri2_egl_config *
|
||||
dri2_add_config(_EGLDisplay *disp, const struct dri_config *dri_config,
|
||||
EGLint surface_type, const EGLint *attr_list);
|
||||
|
||||
void
|
||||
dri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp);
|
||||
|
||||
EGLint
|
||||
dri2_from_dri_compression_rate(enum __DRIFixedRateCompression rate);
|
||||
|
||||
enum __DRIFixedRateCompression
|
||||
dri2_to_dri_compression_rate(EGLint rate);
|
||||
|
||||
_EGLImage *
|
||||
dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
|
||||
EGLClientBuffer buffer, const EGLint *attr_list);
|
||||
|
||||
_EGLImage *
|
||||
dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
EGLClientBuffer buffer, const EGLint *attr_list);
|
||||
|
||||
_EGLImage *
|
||||
dri2_create_image_from_dri(_EGLDisplay *disp, struct dri_image *dri_image);
|
||||
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
EGLBoolean
|
||||
dri2_initialize_x11(_EGLDisplay *disp);
|
||||
void
|
||||
dri2_teardown_x11(struct dri2_egl_display *dri2_dpy);
|
||||
unsigned int
|
||||
dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth);
|
||||
#else
|
||||
static inline EGLBoolean
|
||||
dri2_initialize_x11(_EGLDisplay *disp)
|
||||
{
|
||||
return _eglError(EGL_NOT_INITIALIZED, "X11 platform not built");
|
||||
}
|
||||
static inline void
|
||||
dri2_teardown_x11(struct dri2_egl_display *dri2_dpy)
|
||||
{
|
||||
}
|
||||
static inline unsigned int
|
||||
dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
EGLBoolean
|
||||
dri2_initialize_drm(_EGLDisplay *disp);
|
||||
void
|
||||
dri2_teardown_drm(struct dri2_egl_display *dri2_dpy);
|
||||
#else
|
||||
static inline EGLBoolean
|
||||
dri2_initialize_drm(_EGLDisplay *disp)
|
||||
{
|
||||
return _eglError(EGL_NOT_INITIALIZED, "GBM/DRM platform not built");
|
||||
}
|
||||
static inline void
|
||||
dri2_teardown_drm(struct dri2_egl_display *dri2_dpy)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
EGLBoolean
|
||||
dri2_initialize_wayland(_EGLDisplay *disp);
|
||||
void
|
||||
dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy);
|
||||
bool
|
||||
dri2_wl_is_format_supported(void *user_data, uint32_t format);
|
||||
#else
|
||||
static inline EGLBoolean
|
||||
dri2_initialize_wayland(_EGLDisplay *disp)
|
||||
{
|
||||
return _eglError(EGL_NOT_INITIALIZED, "Wayland platform not built");
|
||||
}
|
||||
static inline void
|
||||
dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANDROID_PLATFORM
|
||||
EGLBoolean
|
||||
dri2_initialize_android(_EGLDisplay *disp);
|
||||
#else
|
||||
static inline EGLBoolean
|
||||
dri2_initialize_android(_EGLDisplay *disp)
|
||||
{
|
||||
return _eglError(EGL_NOT_INITIALIZED, "Android platform not built");
|
||||
}
|
||||
#endif
|
||||
|
||||
EGLBoolean
|
||||
dri2_initialize_surfaceless(_EGLDisplay *disp);
|
||||
|
||||
EGLBoolean
|
||||
dri2_initialize_device(_EGLDisplay *disp);
|
||||
static inline void
|
||||
dri2_teardown_device(struct dri2_egl_display *dri2_dpy)
|
||||
{ /* noop */
|
||||
}
|
||||
|
||||
void
|
||||
dri2_flush_drawable_for_swapbuffers_flags(
|
||||
_EGLDisplay *disp, _EGLSurface *draw,
|
||||
enum __DRI2throttleReason throttle_reason);
|
||||
void
|
||||
dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw);
|
||||
|
||||
const struct dri_config *
|
||||
dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
|
||||
EGLenum colorspace);
|
||||
#include "dri_util.h"
|
||||
static inline void
|
||||
dri2_set_WL_bind_wayland_display(_EGLDisplay *disp)
|
||||
{
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
disp->Extensions.WL_bind_wayland_display =
|
||||
dri2_dpy->fd_render_gpu >= 0 &&
|
||||
dri2_dpy->has_dmabuf_import && dri2_dpy->has_dmabuf_export;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
dri2_display_destroy(_EGLDisplay *disp);
|
||||
|
||||
struct dri2_egl_display *
|
||||
dri2_display_create(_EGLDisplay *disp);
|
||||
|
||||
EGLBoolean
|
||||
dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
|
||||
_EGLConfig *conf, const EGLint *attrib_list,
|
||||
EGLBoolean enable_out_fence, void *native_surface);
|
||||
|
||||
void
|
||||
dri2_fini_surface(_EGLSurface *surf);
|
||||
|
||||
EGLBoolean
|
||||
dri2_create_drawable(struct dri2_egl_display *dri2_dpy,
|
||||
const struct dri_config *config,
|
||||
struct dri2_egl_surface *dri2_surf, void *loaderPrivate);
|
||||
|
||||
static inline uint64_t
|
||||
combine_u32_into_u64(uint32_t hi, uint32_t lo)
|
||||
{
|
||||
return (((uint64_t)hi) << 32) | (((uint64_t)lo) & 0xffffffff);
|
||||
}
|
||||
|
||||
#endif /* EGL_DRI2_INCLUDED */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright © 2021, Google Inc.
|
||||
* Copyright (C) 2021, GlobalLogic Ukraine
|
||||
*
|
||||
* 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 (including the next
|
||||
* paragraph) 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 EGL_ANDROID_INCLUDED
|
||||
#define EGL_ANDROID_INCLUDED
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mesa_interface.h"
|
||||
#include "egl_dri2.h"
|
||||
|
||||
#if ANDROID_API_LEVEL < 26
|
||||
/* Shim layer to map ANativeWindow_* onto the legacy system internal APIs */
|
||||
enum ANativeWindowQuery {
|
||||
ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS = 3,
|
||||
ANATIVEWINDOW_QUERY_DEFAULT_WIDTH = 6,
|
||||
ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT = 7,
|
||||
};
|
||||
|
||||
static inline void
|
||||
ANativeWindow_acquire(struct ANativeWindow *window)
|
||||
{
|
||||
window->common.incRef(&window->common);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ANativeWindow_release(struct ANativeWindow *window)
|
||||
{
|
||||
window->common.decRef(&window->common);
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
ANativeWindow_getFormat(struct ANativeWindow *window)
|
||||
{
|
||||
int32_t format = 0;
|
||||
int res = window->query(window, NATIVE_WINDOW_FORMAT, &format);
|
||||
return res < 0 ? res : format;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ANativeWindow_dequeueBuffer(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer **buffer, int *fenceFd)
|
||||
{
|
||||
return window->dequeueBuffer(window, buffer, fenceFd);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ANativeWindow_queueBuffer(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer *buffer, int fenceFd)
|
||||
{
|
||||
return window->queueBuffer(window, buffer, fenceFd);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ANativeWindow_cancelBuffer(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer *buffer, int fenceFd)
|
||||
{
|
||||
return window->cancelBuffer(window, buffer, fenceFd);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ANativeWindow_setUsage(struct ANativeWindow *window, uint64_t usage)
|
||||
{
|
||||
return native_window_set_usage(window, usage);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ANativeWindow_setSharedBufferMode(struct ANativeWindow *window,
|
||||
bool sharedBufferMode)
|
||||
{
|
||||
return native_window_set_shared_buffer_mode(window, sharedBufferMode);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ANativeWindow_setSwapInterval(struct ANativeWindow *window, int interval)
|
||||
{
|
||||
return window->setSwapInterval(window, interval);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ANativeWindow_query(const struct ANativeWindow *window,
|
||||
enum ANativeWindowQuery what, int *value)
|
||||
{
|
||||
switch (what) {
|
||||
case ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS:
|
||||
case ANATIVEWINDOW_QUERY_DEFAULT_WIDTH:
|
||||
case ANATIVEWINDOW_QUERY_DEFAULT_HEIGHT:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return window->query(window, (int)what, value);
|
||||
}
|
||||
#endif // ANDROID_API_LEVEL < 26
|
||||
|
||||
#endif /* EGL_ANDROID_INCLUDED */
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright 2018 Collabora
|
||||
*
|
||||
* Based on platform_surfaceless, which has:
|
||||
*
|
||||
* Copyright (c) 2014 The Chromium OS Authors.
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifdef HAVE_LIBDRM
|
||||
#include <xf86drm.h>
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "util/u_debug.h"
|
||||
#include "egl_dri2.h"
|
||||
#include "kopper_interface.h"
|
||||
#include "loader.h"
|
||||
#include "dri_util.h"
|
||||
|
||||
static struct dri_image *
|
||||
device_alloc_image(struct dri2_egl_display *dri2_dpy,
|
||||
struct dri2_egl_surface *dri2_surf)
|
||||
{
|
||||
return dri_create_image(
|
||||
dri2_dpy->dri_screen_render_gpu, dri2_surf->base.Width,
|
||||
dri2_surf->base.Height, dri2_surf->visual, NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
device_free_images(struct dri2_egl_surface *dri2_surf)
|
||||
{
|
||||
if (dri2_surf->front) {
|
||||
dri2_destroy_image(dri2_surf->front);
|
||||
dri2_surf->front = NULL;
|
||||
}
|
||||
|
||||
free(dri2_surf->swrast_device_buffer);
|
||||
dri2_surf->swrast_device_buffer = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
device_image_get_buffers(struct dri_drawable *driDrawable, unsigned int format,
|
||||
uint32_t *stamp, void *loaderPrivate,
|
||||
uint32_t buffer_mask, struct __DRIimageList *buffers)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = loaderPrivate;
|
||||
struct dri2_egl_display *dri2_dpy =
|
||||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
|
||||
buffers->image_mask = 0;
|
||||
buffers->front = NULL;
|
||||
buffers->back = NULL;
|
||||
|
||||
/* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
|
||||
* the spec states that they have a back buffer but no front buffer, in
|
||||
* contrast to pixmaps, which have a front buffer but no back buffer.
|
||||
*
|
||||
* Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
|
||||
* from the spec, following the precedent of Mesa's EGL X11 platform. The
|
||||
* X11 platform correctly assigns pbuffers to single-buffered configs, but
|
||||
* assigns the pbuffer a front buffer instead of a back buffer.
|
||||
*
|
||||
* Pbuffers in the X11 platform mostly work today, so let's just copy its
|
||||
* behavior instead of trying to fix (and hence potentially breaking) the
|
||||
* world.
|
||||
*/
|
||||
|
||||
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
|
||||
|
||||
if (!dri2_surf->front)
|
||||
dri2_surf->front = device_alloc_image(dri2_dpy, dri2_surf);
|
||||
|
||||
buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
|
||||
buffers->front = dri2_surf->front;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri2_device_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
|
||||
struct dri2_egl_surface *dri2_surf;
|
||||
const struct dri_config *config;
|
||||
|
||||
/* Make sure to calloc so all pointers
|
||||
* are originally NULL.
|
||||
*/
|
||||
dri2_surf = calloc(1, sizeof *dri2_surf);
|
||||
|
||||
if (!dri2_surf) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
|
||||
false, NULL))
|
||||
goto cleanup_surface;
|
||||
|
||||
config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace);
|
||||
|
||||
if (!config) {
|
||||
_eglError(EGL_BAD_MATCH,
|
||||
"Unsupported surfacetype/colorspace configuration");
|
||||
goto cleanup_surface;
|
||||
}
|
||||
|
||||
dri2_surf->visual = dri2_image_format_for_pbuffer_config(dri2_dpy, config);
|
||||
if (dri2_surf->visual == PIPE_FORMAT_NONE)
|
||||
goto cleanup_surface;
|
||||
|
||||
if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
|
||||
goto cleanup_surface;
|
||||
|
||||
return &dri2_surf->base;
|
||||
|
||||
cleanup_surface:
|
||||
free(dri2_surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
device_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
|
||||
|
||||
device_free_images(dri2_surf);
|
||||
|
||||
driDestroyDrawable(dri2_surf->dri_drawable);
|
||||
|
||||
dri2_fini_surface(surf);
|
||||
free(dri2_surf);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri2_device_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
return dri2_device_create_surface(disp, EGL_PBUFFER_BIT, conf, attrib_list);
|
||||
}
|
||||
|
||||
static const struct dri2_egl_display_vtbl dri2_device_display_vtbl = {
|
||||
.create_pbuffer_surface = dri2_device_create_pbuffer_surface,
|
||||
.destroy_surface = device_destroy_surface,
|
||||
.create_image = dri2_create_image_khr,
|
||||
.get_dri_drawable = dri2_surface_get_dri_drawable,
|
||||
};
|
||||
|
||||
static void
|
||||
device_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
static unsigned
|
||||
device_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
|
||||
{
|
||||
/* Note: loaderPrivate is _EGLDisplay* */
|
||||
switch (cap) {
|
||||
case DRI_LOADER_CAP_FP16:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const __DRIimageLoaderExtension image_loader_extension = {
|
||||
.base = {__DRI_IMAGE_LOADER, 2},
|
||||
.getBuffers = device_image_get_buffers,
|
||||
.flushFrontBuffer = device_flush_front_buffer,
|
||||
.getCapability = device_get_capability,
|
||||
};
|
||||
|
||||
static const __DRIextension *image_loader_extensions[] = {
|
||||
&image_loader_extension.base,
|
||||
&image_lookup_extension.base,
|
||||
&kopper_pbuffer_loader_extension.base,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const __DRIextension *swrast_loader_extensions[] = {
|
||||
&swrast_pbuffer_loader_extension.base,
|
||||
&image_lookup_extension.base,
|
||||
&kopper_pbuffer_loader_extension.base,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int
|
||||
device_get_fd(_EGLDisplay *disp, _EGLDevice *dev)
|
||||
{
|
||||
#ifdef HAVE_LIBDRM
|
||||
int fd = disp->Options.fd;
|
||||
bool kms_swrast = disp->Options.ForceSoftware;
|
||||
/* The fcntl() code in _eglGetDeviceDisplay() ensures that valid fd >= 3,
|
||||
* and invalid one is 0.
|
||||
*/
|
||||
if (fd) {
|
||||
/* According to the spec - if the FD does not match the EGLDevice
|
||||
* behaviour is undefined.
|
||||
*
|
||||
* Add a trivial sanity check since it doesn't cost us anything.
|
||||
*/
|
||||
if (dev != _eglFindDevice(fd, false))
|
||||
return -1;
|
||||
|
||||
/* kms_swrast only work with primary node. It used to work with render
|
||||
* node in the past because some downstream kernel carry a patch to enable
|
||||
* dumb bo ioctl on render nodes.
|
||||
*/
|
||||
char *node = kms_swrast ? drmGetPrimaryDeviceNameFromFd(fd)
|
||||
: drmGetRenderDeviceNameFromFd(fd);
|
||||
|
||||
/* Don't close the internal fd, get render node one based on it. */
|
||||
fd = loader_open_device(node);
|
||||
free(node);
|
||||
return fd;
|
||||
}
|
||||
const char *node = _eglQueryDeviceStringEXT(
|
||||
dev, kms_swrast ? EGL_DRM_DEVICE_FILE_EXT : EGL_DRM_RENDER_NODE_FILE_EXT);
|
||||
return loader_open_device(node);
|
||||
#else
|
||||
_eglLog(_EGL_FATAL,
|
||||
"Driver bug: Built without libdrm, yet using a HW device");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
device_probe_device(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
dri2_dpy->fd_render_gpu = device_get_fd(disp, disp->Device);
|
||||
if (dri2_dpy->fd_render_gpu < 0)
|
||||
return false;
|
||||
|
||||
dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu;
|
||||
|
||||
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd_render_gpu);
|
||||
if (!dri2_dpy->driver_name)
|
||||
goto err_name;
|
||||
|
||||
/* this is software fallback */
|
||||
if (disp->Options.ForceSoftware) {
|
||||
/* When doing software rendering, some times user still want to explicitly
|
||||
* choose the render node device since cross node import doesn't work between
|
||||
* vgem/virtio_gpu yet. It would be nice to have a new EXTENSION for this.
|
||||
* For now, just fallback to kms_swrast. */
|
||||
if (strcmp(dri2_dpy->driver_name, "vgem") == 0 ||
|
||||
strcmp(dri2_dpy->driver_name, "virtio_gpu") == 0) {
|
||||
free(dri2_dpy->driver_name);
|
||||
_eglLog(_EGL_WARNING, "NEEDS EXTENSION: falling back to kms_swrast");
|
||||
dri2_dpy->driver_name = strdup("kms_swrast");
|
||||
} else if (strcmp(dri2_dpy->driver_name, "vmwgfx")) {
|
||||
/* this is software fallback; deny progress since a hardware device was requested */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dri2_detect_swrast_kopper(disp);
|
||||
|
||||
dri2_dpy->loader_extensions = image_loader_extensions;
|
||||
return true;
|
||||
|
||||
err_name:
|
||||
close(dri2_dpy->fd_render_gpu);
|
||||
dri2_dpy->fd_render_gpu = dri2_dpy->fd_display_gpu = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
device_probe_device_sw(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
dri2_dpy->fd_render_gpu = -1;
|
||||
dri2_dpy->fd_display_gpu = -1;
|
||||
dri2_dpy->driver_name = strdup(disp->Options.Zink ? "zink" : "swrast");
|
||||
if (!dri2_dpy->driver_name)
|
||||
return false;
|
||||
|
||||
/* HACK: should be driver_swrast_null */
|
||||
dri2_detect_swrast_kopper(disp);
|
||||
|
||||
dri2_dpy->loader_extensions = swrast_loader_extensions;
|
||||
return true;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
dri2_initialize_device(_EGLDisplay *disp)
|
||||
{
|
||||
const char *err;
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
bool request_software =
|
||||
debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false);
|
||||
|
||||
/* Extension requires a PlatformDisplay - the EGLDevice. */
|
||||
disp->Device = disp->PlatformDisplay;
|
||||
|
||||
if (request_software)
|
||||
_eglLog(_EGL_WARNING, "Not allowed to force software rendering when "
|
||||
"API explicitly selects a hardware device.");
|
||||
|
||||
err = "DRI2: failed to load driver";
|
||||
/* device-drm platform cannot be explicit sw (because explicit sw is llvmpipe) */
|
||||
if (!request_software && _eglDeviceSupports(disp->Device, _EGL_DEVICE_DRM)) {
|
||||
if (!device_probe_device(disp))
|
||||
goto cleanup;
|
||||
} else if (request_software || _eglDeviceSupports(disp->Device, _EGL_DEVICE_SOFTWARE)) {
|
||||
if (!device_probe_device_sw(disp))
|
||||
goto cleanup;
|
||||
} else {
|
||||
_eglLog(_EGL_FATAL,
|
||||
"Driver bug: exposed device is neither DRM nor SOFTWARE one");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!dri2_create_screen(disp)) {
|
||||
err = "DRI2: failed to create screen";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_setup_screen(disp);
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
dri2_dpy->device_name =
|
||||
loader_get_device_name_for_fd(dri2_dpy->fd_render_gpu);
|
||||
#endif
|
||||
dri2_set_WL_bind_wayland_display(disp);
|
||||
|
||||
dri2_add_pbuffer_configs_for_visuals(disp);
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
* initialization.
|
||||
*/
|
||||
dri2_dpy->vtbl = &dri2_device_display_vtbl;
|
||||
|
||||
return EGL_TRUE;
|
||||
|
||||
cleanup:
|
||||
return _eglError(EGL_NOT_INITIALIZED, err);
|
||||
}
|
||||
@@ -0,0 +1,733 @@
|
||||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* 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 (including the next
|
||||
* paragraph) 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.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg <[email protected]>
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "util/os_file.h"
|
||||
|
||||
#include "main/glconfig.h"
|
||||
|
||||
#include "egl_dri2.h"
|
||||
#include "egldevice.h"
|
||||
#include "eglglobals.h"
|
||||
#include "loader.h"
|
||||
#include "dri_util.h"
|
||||
|
||||
static struct gbm_bo *
|
||||
lock_front_buffer(struct gbm_surface *_surf)
|
||||
{
|
||||
struct gbm_dri_surface *surf = gbm_dri_surface(_surf);
|
||||
struct dri2_egl_surface *dri2_surf = surf->dri_private;
|
||||
struct gbm_dri_device *device = gbm_dri_device(_surf->gbm);
|
||||
struct gbm_bo *bo;
|
||||
|
||||
if (dri2_surf->current == NULL) {
|
||||
_eglError(EGL_BAD_SURFACE, "no front buffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bo = dri2_surf->current->bo;
|
||||
|
||||
if (!device->swrast) {
|
||||
dri2_surf->current->locked = true;
|
||||
dri2_surf->current = NULL;
|
||||
}
|
||||
|
||||
return bo;
|
||||
}
|
||||
|
||||
static void
|
||||
release_buffer(struct gbm_surface *_surf, struct gbm_bo *bo)
|
||||
{
|
||||
struct gbm_dri_surface *surf = gbm_dri_surface(_surf);
|
||||
struct dri2_egl_surface *dri2_surf = surf->dri_private;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
|
||||
if (dri2_surf->color_buffers[i].bo == bo) {
|
||||
dri2_surf->color_buffers[i].locked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
has_free_buffers(struct gbm_surface *_surf)
|
||||
{
|
||||
struct gbm_dri_surface *surf = gbm_dri_surface(_surf);
|
||||
struct dri2_egl_surface *dri2_surf = surf->dri_private;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
|
||||
if (!dri2_surf->color_buffers[i].locked)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
dri2_drm_config_is_compatible(struct dri2_egl_display *dri2_dpy,
|
||||
const struct dri_config *config,
|
||||
struct gbm_surface *surface)
|
||||
{
|
||||
const struct gl_config *gl_config = (struct gl_config *) config;
|
||||
const struct gbm_dri_visual *visual = NULL;
|
||||
int i;
|
||||
|
||||
/* Check that the EGLConfig being used to render to the surface is
|
||||
* compatible with the surface format. Since mixing ARGB and XRGB of
|
||||
* otherwise-compatible formats is relatively common, explicitly allow
|
||||
* this.
|
||||
*/
|
||||
for (i = 0; i < dri2_dpy->gbm_dri->num_visuals; i++) {
|
||||
visual = &dri2_dpy->gbm_dri->visual_table[i];
|
||||
if (visual->gbm_format == surface->v0.format)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == dri2_dpy->gbm_dri->num_visuals)
|
||||
return false;
|
||||
|
||||
|
||||
const struct util_format_description *fmt_c =
|
||||
util_format_description(gl_config->color_format);
|
||||
const struct util_format_description *fmt_s =
|
||||
util_format_description(visual->pipe_format);
|
||||
|
||||
if (util_is_format_compatible(fmt_c, fmt_s) ||
|
||||
util_is_format_compatible(fmt_s, fmt_c))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri2_drm_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
void *native_surface, const EGLint *attrib_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
|
||||
struct dri2_egl_surface *dri2_surf;
|
||||
struct gbm_surface *surface = native_surface;
|
||||
struct gbm_dri_surface *surf;
|
||||
const struct dri_config *config;
|
||||
|
||||
dri2_surf = calloc(1, sizeof *dri2_surf);
|
||||
if (!dri2_surf) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_create_surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf,
|
||||
attrib_list, false, native_surface))
|
||||
goto cleanup_surf;
|
||||
|
||||
config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT,
|
||||
dri2_surf->base.GLColorspace);
|
||||
|
||||
if (!config) {
|
||||
_eglError(EGL_BAD_MATCH,
|
||||
"Unsupported surfacetype/colorspace configuration");
|
||||
goto cleanup_surf;
|
||||
}
|
||||
|
||||
if (!dri2_drm_config_is_compatible(dri2_dpy, config, surface)) {
|
||||
_eglError(EGL_BAD_MATCH, "EGL config not compatible with GBM format");
|
||||
goto cleanup_surf;
|
||||
}
|
||||
|
||||
surf = gbm_dri_surface(surface);
|
||||
dri2_surf->gbm_surf = surf;
|
||||
dri2_surf->base.Width = surf->base.v0.width;
|
||||
dri2_surf->base.Height = surf->base.v0.height;
|
||||
surf->dri_private = dri2_surf;
|
||||
|
||||
if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf->gbm_surf))
|
||||
goto cleanup_surf;
|
||||
|
||||
return &dri2_surf->base;
|
||||
|
||||
cleanup_surf:
|
||||
free(dri2_surf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri2_drm_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
void *native_window, const EGLint *attrib_list)
|
||||
{
|
||||
/* From the EGL_MESA_platform_gbm spec, version 5:
|
||||
*
|
||||
* It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy>
|
||||
* that belongs to the GBM platform. Any such call fails and generates
|
||||
* EGL_BAD_PARAMETER.
|
||||
*/
|
||||
_eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on GBM");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri2_drm_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
|
||||
|
||||
driDestroyDrawable(dri2_surf->dri_drawable);
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
|
||||
if (dri2_surf->color_buffers[i].bo)
|
||||
gbm_bo_destroy(dri2_surf->color_buffers[i].bo);
|
||||
}
|
||||
|
||||
dri2_fini_surface(surf);
|
||||
free(surf);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_oldest_unused_bo(struct dri2_egl_surface *dri2_surf)
|
||||
{
|
||||
struct dri2_egl_buffer *oldest_buffer = NULL;
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
|
||||
struct dri2_egl_buffer *buffer = &dri2_surf->color_buffers[i];
|
||||
|
||||
if (buffer->locked ||
|
||||
buffer == dri2_surf->back ||
|
||||
buffer == dri2_surf->current)
|
||||
continue;
|
||||
|
||||
if (!oldest_buffer || buffer->age > oldest_buffer->age)
|
||||
oldest_buffer = buffer;
|
||||
}
|
||||
|
||||
gbm_bo_destroy(oldest_buffer->bo);
|
||||
oldest_buffer->bo = NULL;
|
||||
oldest_buffer->age = 0;
|
||||
|
||||
dri2_surf->excess_bo_frames = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_back_bo(struct dri2_egl_surface *dri2_surf)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy =
|
||||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
|
||||
int min_age = 0, max_age = 0;
|
||||
|
||||
if (dri2_surf->back == NULL) {
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
|
||||
if (!dri2_surf->color_buffers[i].locked) {
|
||||
int age = dri2_surf->color_buffers[i].age;
|
||||
|
||||
if (!min_age || age < min_age)
|
||||
min_age = age;
|
||||
|
||||
if (!max_age || age > max_age) {
|
||||
dri2_surf->back = &dri2_surf->color_buffers[i];
|
||||
max_age = age;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (min_age && min_age < max_age) {
|
||||
if (++dri2_surf->excess_bo_frames == 1000)
|
||||
destroy_oldest_unused_bo(dri2_surf);
|
||||
} else {
|
||||
dri2_surf->excess_bo_frames = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dri2_surf->back == NULL)
|
||||
return -1;
|
||||
if (dri2_surf->back->bo == NULL) {
|
||||
if (surf->base.v0.modifiers && surf->base.v0.flags)
|
||||
dri2_surf->back->bo = gbm_bo_create_with_modifiers2(
|
||||
&dri2_dpy->gbm_dri->base, surf->base.v0.width, surf->base.v0.height,
|
||||
surf->base.v0.format, surf->base.v0.modifiers, surf->base.v0.count,
|
||||
surf->base.v0.flags);
|
||||
else if (surf->base.v0.modifiers)
|
||||
dri2_surf->back->bo = gbm_bo_create_with_modifiers(
|
||||
&dri2_dpy->gbm_dri->base, surf->base.v0.width, surf->base.v0.height,
|
||||
surf->base.v0.format, surf->base.v0.modifiers, surf->base.v0.count);
|
||||
else {
|
||||
unsigned flags = surf->base.v0.flags;
|
||||
if (dri2_surf->base.ProtectedContent)
|
||||
flags |= GBM_BO_USE_PROTECTED;
|
||||
dri2_surf->back->bo =
|
||||
gbm_bo_create(&dri2_dpy->gbm_dri->base, surf->base.v0.width,
|
||||
surf->base.v0.height, surf->base.v0.format, flags);
|
||||
}
|
||||
}
|
||||
if (dri2_surf->back->bo == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_swrast_front_bo(struct dri2_egl_surface *dri2_surf)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy =
|
||||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
|
||||
|
||||
if (dri2_surf->current == NULL) {
|
||||
assert(!dri2_surf->color_buffers[0].locked);
|
||||
dri2_surf->current = &dri2_surf->color_buffers[0];
|
||||
}
|
||||
|
||||
if (dri2_surf->current->bo == NULL)
|
||||
dri2_surf->current->bo = gbm_bo_create(
|
||||
&dri2_dpy->gbm_dri->base, surf->base.v0.width, surf->base.v0.height,
|
||||
surf->base.v0.format, surf->base.v0.flags);
|
||||
if (dri2_surf->current->bo == NULL)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dri2_drm_image_get_buffers(struct dri_drawable *driDrawable, unsigned int format,
|
||||
uint32_t *stamp, void *loaderPrivate,
|
||||
uint32_t buffer_mask, struct __DRIimageList *buffers)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = loaderPrivate;
|
||||
struct gbm_dri_bo *bo;
|
||||
|
||||
if (get_back_bo(dri2_surf) < 0)
|
||||
return 0;
|
||||
|
||||
bo = gbm_dri_bo(dri2_surf->back->bo);
|
||||
buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
|
||||
buffers->back = bo->image;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
dri2_drm_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate)
|
||||
{
|
||||
(void)driDrawable;
|
||||
(void)loaderPrivate;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri2_drm_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
|
||||
|
||||
if (dri2_dpy->swrast_not_kms) {
|
||||
driSwapBuffers(dri2_surf->dri_drawable);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
if (dri2_surf->current)
|
||||
_eglError(EGL_BAD_SURFACE, "dri2_swap_buffers");
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++)
|
||||
if (dri2_surf->color_buffers[i].age > 0)
|
||||
dri2_surf->color_buffers[i].age++;
|
||||
|
||||
/* Flushing must be done before get_back_bo to make sure glthread's
|
||||
* unmarshalling thread is idle otherwise it might concurrently
|
||||
* call get_back_bo (eg: through dri2_drm_image_get_buffers).
|
||||
*/
|
||||
dri2_flush_drawable_for_swapbuffers(disp, draw);
|
||||
dri_invalidate_drawable(dri2_surf->dri_drawable);
|
||||
|
||||
/* Make sure we have a back buffer in case we're swapping without
|
||||
* ever rendering. */
|
||||
if (get_back_bo(dri2_surf) < 0)
|
||||
return _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
|
||||
|
||||
dri2_surf->current = dri2_surf->back;
|
||||
dri2_surf->current->age = 1;
|
||||
dri2_surf->back = NULL;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLint
|
||||
dri2_drm_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
|
||||
|
||||
if (get_back_bo(dri2_surf) < 0) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return dri2_surf->back->age;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri2_drm_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
EGLClientBuffer buffer,
|
||||
const EGLint *attr_list)
|
||||
{
|
||||
struct gbm_dri_bo *dri_bo = gbm_dri_bo((struct gbm_bo *)buffer);
|
||||
struct dri2_egl_image *dri2_img;
|
||||
|
||||
dri2_img = malloc(sizeof *dri2_img);
|
||||
if (!dri2_img) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_eglInitImage(&dri2_img->base, disp);
|
||||
|
||||
dri2_img->dri_image = dri2_dup_image(dri_bo->image, dri2_img);
|
||||
if (dri2_img->dri_image == NULL) {
|
||||
free(dri2_img);
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr_pixmap");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &dri2_img->base;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri2_drm_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
|
||||
EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
switch (target) {
|
||||
case EGL_NATIVE_PIXMAP_KHR:
|
||||
return dri2_drm_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
|
||||
default:
|
||||
return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
return drmAuthMagic(dri2_dpy->fd_render_gpu, id);
|
||||
}
|
||||
|
||||
static void
|
||||
swrast_put_image2(struct dri_drawable *driDrawable, int op, int x, int y, int width,
|
||||
int height, int stride, char *data, void *loaderPrivate)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = loaderPrivate;
|
||||
int internal_stride;
|
||||
struct gbm_dri_bo *bo;
|
||||
uint32_t bpp;
|
||||
int x_bytes, width_bytes;
|
||||
char *src, *dst;
|
||||
|
||||
if (op != __DRI_SWRAST_IMAGE_OP_DRAW && op != __DRI_SWRAST_IMAGE_OP_SWAP)
|
||||
return;
|
||||
|
||||
if (get_swrast_front_bo(dri2_surf) < 0)
|
||||
return;
|
||||
|
||||
bo = gbm_dri_bo(dri2_surf->current->bo);
|
||||
|
||||
bpp = gbm_bo_get_bpp(&bo->base);
|
||||
if (bpp == 0)
|
||||
return;
|
||||
|
||||
x_bytes = x * (bpp >> 3);
|
||||
width_bytes = width * (bpp >> 3);
|
||||
|
||||
if (gbm_dri_bo_map_dumb(bo) == NULL)
|
||||
return;
|
||||
|
||||
internal_stride = bo->base.v0.stride;
|
||||
|
||||
dst = bo->map + x_bytes + (y * internal_stride);
|
||||
src = data;
|
||||
|
||||
for (int i = 0; i < height; i++) {
|
||||
memcpy(dst, src, width_bytes);
|
||||
dst += internal_stride;
|
||||
src += stride;
|
||||
}
|
||||
|
||||
gbm_dri_bo_unmap_dumb(bo);
|
||||
}
|
||||
|
||||
static void
|
||||
swrast_get_image(struct dri_drawable *driDrawable, int x, int y, int width,
|
||||
int height, char *data, void *loaderPrivate)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = loaderPrivate;
|
||||
int internal_stride, stride;
|
||||
struct gbm_dri_bo *bo;
|
||||
uint32_t bpp;
|
||||
int x_bytes, width_bytes;
|
||||
char *src, *dst;
|
||||
|
||||
if (get_swrast_front_bo(dri2_surf) < 0)
|
||||
return;
|
||||
|
||||
bo = gbm_dri_bo(dri2_surf->current->bo);
|
||||
|
||||
bpp = gbm_bo_get_bpp(&bo->base);
|
||||
if (bpp == 0)
|
||||
return;
|
||||
|
||||
x_bytes = x * (bpp >> 3);
|
||||
width_bytes = width * (bpp >> 3);
|
||||
|
||||
internal_stride = bo->base.v0.stride;
|
||||
stride = width_bytes;
|
||||
|
||||
if (gbm_dri_bo_map_dumb(bo) == NULL)
|
||||
return;
|
||||
|
||||
dst = data;
|
||||
src = bo->map + x_bytes + (y * internal_stride);
|
||||
|
||||
for (int i = 0; i < height; i++) {
|
||||
memcpy(dst, src, width_bytes);
|
||||
dst += stride;
|
||||
src += internal_stride;
|
||||
}
|
||||
|
||||
gbm_dri_bo_unmap_dumb(bo);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_add_configs_for_visuals(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
const struct gbm_dri_visual *visuals = dri2_dpy->gbm_dri->visual_table;
|
||||
int num_visuals = dri2_dpy->gbm_dri->num_visuals;
|
||||
unsigned int format_count[num_visuals];
|
||||
|
||||
memset(format_count, 0, num_visuals * sizeof(unsigned int));
|
||||
|
||||
for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
|
||||
const struct dri_config *config = dri2_dpy->driver_configs[i];
|
||||
struct gl_config *gl_config = (struct gl_config *) config;
|
||||
|
||||
for (unsigned j = 0; j < num_visuals; j++) {
|
||||
struct dri2_egl_config *dri2_conf;
|
||||
EGLint config_group = 0;
|
||||
|
||||
if (visuals[j].pipe_format != gl_config->color_format)
|
||||
continue;
|
||||
|
||||
/* Put the 16 bpc rgb[a] unorm formats into a lower priority EGL config
|
||||
* group 1, so they don't get preferably chosen by eglChooseConfig().
|
||||
*/
|
||||
if (util_format_is_unorm16(util_format_description(visuals[j].pipe_format)))
|
||||
config_group = 1;
|
||||
|
||||
const EGLint attr_list[] = {
|
||||
EGL_NATIVE_VISUAL_ID,
|
||||
visuals[j].gbm_format,
|
||||
EGL_CONFIG_SELECT_GROUP_EXT,
|
||||
config_group,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
dri2_conf =
|
||||
dri2_add_config(disp, dri2_dpy->driver_configs[i], EGL_WINDOW_BIT,
|
||||
attr_list);
|
||||
if (dri2_conf)
|
||||
format_count[j]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) {
|
||||
if (!format_count[i]) {
|
||||
struct gbm_format_name_desc desc;
|
||||
_eglLog(_EGL_DEBUG, "No DRI config supports native format %s",
|
||||
gbm_format_get_name(visuals[i].gbm_format, &desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
|
||||
.authenticate = dri2_drm_authenticate,
|
||||
.create_window_surface = dri2_drm_create_window_surface,
|
||||
.create_pixmap_surface = dri2_drm_create_pixmap_surface,
|
||||
.destroy_surface = dri2_drm_destroy_surface,
|
||||
.create_image = dri2_drm_create_image_khr,
|
||||
.swap_buffers = dri2_drm_swap_buffers,
|
||||
.query_buffer_age = dri2_drm_query_buffer_age,
|
||||
.get_dri_drawable = dri2_surface_get_dri_drawable,
|
||||
};
|
||||
|
||||
static int
|
||||
get_fd_render_gpu_drm(struct gbm_dri_device *gbm_dri, int fd_display_gpu)
|
||||
{
|
||||
/* This doesn't make sense for the software case. */
|
||||
assert(!gbm_dri->software);
|
||||
|
||||
/* Render-capable device, so just return the same fd. */
|
||||
if (loader_is_device_render_capable(fd_display_gpu))
|
||||
return fd_display_gpu;
|
||||
|
||||
/* Display-only device, so return a compatible render-only device. */
|
||||
return dri_query_compatible_render_only_device_fd(fd_display_gpu);
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
dri2_initialize_drm(_EGLDisplay *disp)
|
||||
{
|
||||
struct gbm_device *gbm;
|
||||
const char *err;
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
gbm = disp->PlatformDisplay;
|
||||
if (gbm == NULL) {
|
||||
if (disp->Device) {
|
||||
drmDevicePtr drm = _eglDeviceDrm(disp->Device);
|
||||
|
||||
if (!_eglDeviceSupports(disp->Device, _EGL_DEVICE_DRM)) {
|
||||
err = "DRI2: Device isn't of _EGL_DEVICE_DRM type";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(drm->available_nodes & (1 << DRM_NODE_PRIMARY))) {
|
||||
err = "DRI2: Device does not have DRM_NODE_PRIMARY node";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_dpy->fd_display_gpu =
|
||||
loader_open_device(drm->nodes[DRM_NODE_PRIMARY]);
|
||||
} else {
|
||||
_EGLDevice *dev_list = _eglGlobal.DeviceList;
|
||||
drmDevicePtr drm;
|
||||
while (dev_list) {
|
||||
if (!_eglDeviceSupports(dev_list, _EGL_DEVICE_DRM))
|
||||
goto next;
|
||||
|
||||
drm = _eglDeviceDrm(dev_list);
|
||||
|
||||
if (!(drm->available_nodes & (1 << DRM_NODE_PRIMARY)))
|
||||
goto next;
|
||||
|
||||
dri2_dpy->fd_display_gpu =
|
||||
loader_open_device(drm->nodes[DRM_NODE_PRIMARY]);
|
||||
if (dri2_dpy->fd_display_gpu < 0)
|
||||
goto next;
|
||||
|
||||
break;
|
||||
next:
|
||||
dev_list = _eglDeviceNext(dev_list);
|
||||
}
|
||||
}
|
||||
|
||||
gbm = gbm_create_device(dri2_dpy->fd_display_gpu);
|
||||
if (gbm == NULL) {
|
||||
err = "DRI2: failed to create gbm device";
|
||||
goto cleanup;
|
||||
}
|
||||
dri2_dpy->own_device = true;
|
||||
} else {
|
||||
dri2_dpy->fd_display_gpu = os_dupfd_cloexec(gbm_device_get_fd(gbm));
|
||||
if (dri2_dpy->fd_display_gpu < 0) {
|
||||
err = "DRI2: failed to fcntl() existing gbm device";
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
dri2_dpy->gbm_dri = gbm_dri_device(gbm);
|
||||
if (!dri2_dpy->gbm_dri->software) {
|
||||
dri2_dpy->fd_render_gpu =
|
||||
get_fd_render_gpu_drm(dri2_dpy->gbm_dri, dri2_dpy->fd_display_gpu);
|
||||
if (dri2_dpy->fd_render_gpu < 0) {
|
||||
err = "DRI2: failed to get compatible render device";
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
|
||||
err = "DRI2: gbm device using incorrect/incompatible backend";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->driver_name);
|
||||
|
||||
dri2_detect_swrast_kopper(disp);
|
||||
|
||||
dri2_dpy->dri_screen_render_gpu = dri2_dpy->gbm_dri->screen;
|
||||
dri2_dpy->driver_configs = dri2_dpy->gbm_dri->driver_configs;
|
||||
|
||||
dri2_dpy->gbm_dri->validate_image = dri2_validate_egl_image;
|
||||
dri2_dpy->gbm_dri->lookup_image_validated = dri2_lookup_egl_image_validated;
|
||||
dri2_dpy->gbm_dri->lookup_user_data = disp;
|
||||
|
||||
dri2_dpy->gbm_dri->flush_front_buffer = dri2_drm_flush_front_buffer;
|
||||
dri2_dpy->gbm_dri->image_get_buffers = dri2_drm_image_get_buffers;
|
||||
dri2_dpy->gbm_dri->swrast_put_image2 = swrast_put_image2;
|
||||
dri2_dpy->gbm_dri->swrast_get_image = swrast_get_image;
|
||||
|
||||
dri2_dpy->gbm_dri->base.v0.surface_lock_front_buffer = lock_front_buffer;
|
||||
dri2_dpy->gbm_dri->base.v0.surface_release_buffer = release_buffer;
|
||||
dri2_dpy->gbm_dri->base.v0.surface_has_free_buffers = has_free_buffers;
|
||||
|
||||
if (!dri2_setup_device(disp, dri2_dpy->gbm_dri->software)) {
|
||||
err = "DRI2: failed to setup EGLDevice";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_setup_screen(disp);
|
||||
|
||||
drm_add_configs_for_visuals(disp);
|
||||
|
||||
disp->Extensions.KHR_image_pixmap = EGL_TRUE;
|
||||
disp->Extensions.EXT_buffer_age = EGL_TRUE;
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
dri2_dpy->device_name =
|
||||
loader_get_device_name_for_fd(dri2_dpy->fd_render_gpu);
|
||||
#endif
|
||||
dri2_set_WL_bind_wayland_display(disp);
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
* initialization.
|
||||
*/
|
||||
dri2_dpy->vtbl = &dri2_drm_display_vtbl;
|
||||
|
||||
return EGL_TRUE;
|
||||
|
||||
cleanup:
|
||||
return _eglError(EGL_NOT_INITIALIZED, err);
|
||||
}
|
||||
|
||||
void
|
||||
dri2_teardown_drm(struct dri2_egl_display *dri2_dpy)
|
||||
{
|
||||
if (dri2_dpy->own_device)
|
||||
gbm_device_destroy(&dri2_dpy->gbm_dri->base);
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (c) 2014 The Chromium OS Authors.
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "pipe/p_screen.h"
|
||||
#include "util/libdrm.h"
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "egl_dri2.h"
|
||||
#include "eglglobals.h"
|
||||
#include "kopper_interface.h"
|
||||
#include "loader.h"
|
||||
#include "loader_dri_helper.h"
|
||||
#include "dri_util.h"
|
||||
#include "dri_screen.h"
|
||||
|
||||
static struct dri_image *
|
||||
surfaceless_alloc_image(struct dri2_egl_display *dri2_dpy,
|
||||
struct dri2_egl_surface *dri2_surf)
|
||||
{
|
||||
return dri_create_image(
|
||||
dri2_dpy->dri_screen_render_gpu, dri2_surf->base.Width,
|
||||
dri2_surf->base.Height, dri2_surf->visual, NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
surfaceless_free_images(struct dri2_egl_surface *dri2_surf)
|
||||
{
|
||||
if (dri2_surf->front) {
|
||||
dri2_destroy_image(dri2_surf->front);
|
||||
dri2_surf->front = NULL;
|
||||
}
|
||||
|
||||
free(dri2_surf->swrast_device_buffer);
|
||||
dri2_surf->swrast_device_buffer = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
surfaceless_image_get_buffers(struct dri_drawable *driDrawable, unsigned int format,
|
||||
uint32_t *stamp, void *loaderPrivate,
|
||||
uint32_t buffer_mask,
|
||||
struct __DRIimageList *buffers)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = loaderPrivate;
|
||||
struct dri2_egl_display *dri2_dpy =
|
||||
dri2_egl_display(dri2_surf->base.Resource.Display);
|
||||
|
||||
buffers->image_mask = 0;
|
||||
buffers->front = NULL;
|
||||
buffers->back = NULL;
|
||||
|
||||
/* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
|
||||
* the spec states that they have a back buffer but no front buffer, in
|
||||
* contrast to pixmaps, which have a front buffer but no back buffer.
|
||||
*
|
||||
* Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
|
||||
* from the spec, following the precedent of Mesa's EGL X11 platform. The
|
||||
* X11 platform correctly assigns pbuffers to single-buffered configs, but
|
||||
* assigns the pbuffer a front buffer instead of a back buffer.
|
||||
*
|
||||
* Pbuffers in the X11 platform mostly work today, so let's just copy its
|
||||
* behavior instead of trying to fix (and hence potentially breaking) the
|
||||
* world.
|
||||
*/
|
||||
|
||||
if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
|
||||
|
||||
if (!dri2_surf->front) {
|
||||
dri2_surf->front = surfaceless_alloc_image(dri2_dpy, dri2_surf);
|
||||
if (!dri2_surf->front)
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
|
||||
buffers->front = dri2_surf->front;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri2_surfaceless_create_surface(_EGLDisplay *disp, EGLint type,
|
||||
_EGLConfig *conf, const EGLint *attrib_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
|
||||
struct dri2_egl_surface *dri2_surf;
|
||||
const struct dri_config *config;
|
||||
|
||||
/* Make sure to calloc so all pointers
|
||||
* are originally NULL.
|
||||
*/
|
||||
dri2_surf = calloc(1, sizeof *dri2_surf);
|
||||
|
||||
if (!dri2_surf) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
|
||||
false, NULL))
|
||||
goto cleanup_surface;
|
||||
|
||||
config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace);
|
||||
|
||||
if (!config) {
|
||||
_eglError(EGL_BAD_MATCH,
|
||||
"Unsupported surfacetype/colorspace configuration");
|
||||
goto cleanup_surface;
|
||||
}
|
||||
|
||||
dri2_surf->visual = dri2_image_format_for_pbuffer_config(dri2_dpy, config);
|
||||
if (dri2_surf->visual == PIPE_FORMAT_NONE)
|
||||
goto cleanup_surface;
|
||||
|
||||
if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
|
||||
goto cleanup_surface;
|
||||
|
||||
return &dri2_surf->base;
|
||||
|
||||
cleanup_surface:
|
||||
free(dri2_surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
surfaceless_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
|
||||
|
||||
surfaceless_free_images(dri2_surf);
|
||||
|
||||
driDestroyDrawable(dri2_surf->dri_drawable);
|
||||
|
||||
dri2_fini_surface(surf);
|
||||
free(dri2_surf);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri2_surfaceless_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
return dri2_surfaceless_create_surface(disp, EGL_PBUFFER_BIT, conf,
|
||||
attrib_list);
|
||||
}
|
||||
|
||||
static const struct dri2_egl_display_vtbl dri2_surfaceless_display_vtbl = {
|
||||
.create_pbuffer_surface = dri2_surfaceless_create_pbuffer_surface,
|
||||
.destroy_surface = surfaceless_destroy_surface,
|
||||
.create_image = dri2_create_image_khr,
|
||||
.get_dri_drawable = dri2_surface_get_dri_drawable,
|
||||
};
|
||||
|
||||
static void
|
||||
surfaceless_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
static unsigned
|
||||
surfaceless_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
|
||||
{
|
||||
/* Note: loaderPrivate is _EGLDisplay* */
|
||||
switch (cap) {
|
||||
case DRI_LOADER_CAP_FP16:
|
||||
return 1;
|
||||
case DRI_LOADER_CAP_RGBA_ORDERING:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const __DRIimageLoaderExtension image_loader_extension = {
|
||||
.base = {__DRI_IMAGE_LOADER, 2},
|
||||
.getBuffers = surfaceless_image_get_buffers,
|
||||
.flushFrontBuffer = surfaceless_flush_front_buffer,
|
||||
.getCapability = surfaceless_get_capability,
|
||||
};
|
||||
|
||||
static const __DRIextension *image_loader_extensions[] = {
|
||||
&image_loader_extension.base, &image_lookup_extension.base, NULL,
|
||||
};
|
||||
|
||||
static const __DRIextension *swrast_loader_extensions[] = {
|
||||
&swrast_pbuffer_loader_extension.base, &image_loader_extension.base,
|
||||
&image_lookup_extension.base, NULL,
|
||||
};
|
||||
|
||||
static const __DRIextension *kopper_loader_extensions[] = {
|
||||
&kopper_pbuffer_loader_extension.base, &image_lookup_extension.base,
|
||||
&image_lookup_extension.base, NULL,
|
||||
};
|
||||
|
||||
static bool
|
||||
surfaceless_probe_device(_EGLDisplay *disp, bool swrast, bool zink)
|
||||
{
|
||||
const unsigned node_type = swrast ? DRM_NODE_PRIMARY : DRM_NODE_RENDER;
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
_EGLDevice *dev_list = _eglGlobal.DeviceList;
|
||||
drmDevicePtr device;
|
||||
|
||||
while (dev_list) {
|
||||
if (!_eglDeviceSupports(dev_list, _EGL_DEVICE_DRM))
|
||||
goto next;
|
||||
|
||||
if (_eglHasAttrib(disp, EGL_DEVICE_EXT) && dev_list != disp->Device) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
device = _eglDeviceDrm(dev_list);
|
||||
assert(device);
|
||||
|
||||
if (!(device->available_nodes & (1 << node_type)))
|
||||
goto next;
|
||||
|
||||
dri2_dpy->fd_render_gpu = loader_open_device(device->nodes[node_type]);
|
||||
if (dri2_dpy->fd_render_gpu < 0)
|
||||
goto next;
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
loader_get_user_preferred_fd(&dri2_dpy->fd_render_gpu,
|
||||
&dri2_dpy->fd_display_gpu);
|
||||
|
||||
if (dri2_dpy->fd_render_gpu != dri2_dpy->fd_display_gpu) {
|
||||
free(dri2_dpy->device_name);
|
||||
dri2_dpy->device_name =
|
||||
loader_get_device_name_for_fd(dri2_dpy->fd_render_gpu);
|
||||
if (!dri2_dpy->device_name) {
|
||||
_eglError(EGL_BAD_ALLOC, "surfaceless-egl: failed to get device name "
|
||||
"for requested GPU");
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
/* we have to do the check now, because loader_get_user_preferred_fd
|
||||
* will return a render-node when the requested gpu is different
|
||||
* to the server, but also if the client asks for the same gpu than
|
||||
* the server by requesting its pci-id */
|
||||
dri2_dpy->is_render_node =
|
||||
drmGetNodeTypeFromFd(dri2_dpy->fd_render_gpu) == DRM_NODE_RENDER;
|
||||
#endif
|
||||
char *driver_name = loader_get_driver_for_fd(dri2_dpy->fd_render_gpu);
|
||||
|
||||
disp->Device = dev_list;
|
||||
if (swrast) {
|
||||
/* Use kms swrast only with vgem / virtio_gpu.
|
||||
* virtio-gpu fallbacks to software rendering when 3D features
|
||||
* are unavailable since 6c5ab, and kms_swrast is more
|
||||
* feature complete than swrast.
|
||||
*/
|
||||
if (driver_name && (strcmp(driver_name, "vgem") == 0 ||
|
||||
strcmp(driver_name, "virtio_gpu") == 0))
|
||||
dri2_dpy->driver_name = strdup("kms_swrast");
|
||||
free(driver_name);
|
||||
} else {
|
||||
/* Use the given hardware driver */
|
||||
dri2_dpy->driver_name = driver_name;
|
||||
}
|
||||
|
||||
if (dri2_dpy->driver_name) {
|
||||
dri2_detect_swrast_kopper(disp);
|
||||
if (dri2_dpy->kopper)
|
||||
dri2_dpy->loader_extensions = kopper_loader_extensions;
|
||||
else if (swrast)
|
||||
dri2_dpy->loader_extensions = swrast_loader_extensions;
|
||||
else
|
||||
dri2_dpy->loader_extensions = image_loader_extensions;
|
||||
|
||||
if (!dri2_create_screen(disp)) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: failed to create screen");
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (!dri2_dpy->dri_screen_render_gpu->base.screen->caps.graphics) {
|
||||
|
||||
_eglLog(_EGL_DEBUG, "DRI2: Driver %s doesn't support graphics, skipping.", dri2_dpy->driver_name);
|
||||
|
||||
if (dri2_dpy->dri_screen_display_gpu != dri2_dpy->dri_screen_render_gpu) {
|
||||
driDestroyScreen(dri2_dpy->dri_screen_display_gpu);
|
||||
dri2_dpy->dri_screen_display_gpu = NULL;
|
||||
}
|
||||
|
||||
driDestroyScreen(dri2_dpy->dri_screen_render_gpu);
|
||||
dri2_dpy->dri_screen_render_gpu = NULL;
|
||||
|
||||
dri2_dpy->own_dri_screen = false;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
retry:
|
||||
free(dri2_dpy->driver_name);
|
||||
dri2_dpy->driver_name = NULL;
|
||||
if (dri2_dpy->fd_display_gpu != dri2_dpy->fd_render_gpu)
|
||||
close(dri2_dpy->fd_display_gpu);
|
||||
dri2_dpy->fd_display_gpu = -1;
|
||||
close(dri2_dpy->fd_render_gpu);
|
||||
dri2_dpy->fd_render_gpu = -1;
|
||||
|
||||
next:
|
||||
dev_list = _eglDeviceNext(dev_list);
|
||||
}
|
||||
|
||||
if (!dev_list)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
surfaceless_probe_device_sw(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct _egl_device *device = _eglFindDevice(dri2_dpy->fd_render_gpu, true);
|
||||
|
||||
dri2_dpy->fd_render_gpu = -1;
|
||||
|
||||
if (_eglHasAttrib(disp, EGL_DEVICE_EXT) && disp->Device != device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
disp->Device = device;
|
||||
assert(disp->Device);
|
||||
|
||||
dri2_dpy->driver_name = strdup(disp->Options.Zink ? "zink" : "swrast");
|
||||
if (!dri2_dpy->driver_name)
|
||||
return false;
|
||||
|
||||
dri2_detect_swrast_kopper(disp);
|
||||
|
||||
if (dri2_dpy->kopper)
|
||||
dri2_dpy->loader_extensions = kopper_loader_extensions;
|
||||
else
|
||||
dri2_dpy->loader_extensions = swrast_loader_extensions;
|
||||
|
||||
dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu;
|
||||
|
||||
if (!dri2_create_screen(disp)) {
|
||||
_eglLog(_EGL_WARNING, "DRI2: failed to create screen");
|
||||
free(dri2_dpy->driver_name);
|
||||
dri2_dpy->driver_name = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
dri2_initialize_surfaceless(_EGLDisplay *disp)
|
||||
{
|
||||
const char *err;
|
||||
bool driver_loaded = false;
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
/* When ForceSoftware is false, we try the HW driver. When ForceSoftware
|
||||
* is true, we try kms_swrast and swrast in order.
|
||||
*/
|
||||
driver_loaded = surfaceless_probe_device(disp, disp->Options.ForceSoftware,
|
||||
disp->Options.Zink);
|
||||
if (!driver_loaded && disp->Options.ForceSoftware) {
|
||||
_eglLog(_EGL_DEBUG, "Falling back to surfaceless swrast without DRM.");
|
||||
driver_loaded = surfaceless_probe_device_sw(disp);
|
||||
}
|
||||
|
||||
if (!driver_loaded) {
|
||||
err = "DRI2: failed to load driver";
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dri2_setup_screen(disp);
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
dri2_dpy->device_name =
|
||||
loader_get_device_name_for_fd(dri2_dpy->fd_render_gpu);
|
||||
#endif
|
||||
dri2_set_WL_bind_wayland_display(disp);
|
||||
|
||||
dri2_add_pbuffer_configs_for_visuals(disp);
|
||||
|
||||
/* Fill vtbl last to prevent accidentally calling virtual function during
|
||||
* initialization.
|
||||
*/
|
||||
dri2_dpy->vtbl = &dri2_surfaceless_display_vtbl;
|
||||
|
||||
return EGL_TRUE;
|
||||
|
||||
cleanup:
|
||||
return _eglError(EGL_NOT_INITIALIZED, err);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2022 Yonggang Luo
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EGL_X11_INCLUDED
|
||||
#define EGL_X11_INCLUDED
|
||||
|
||||
#include "egl_dri2.h"
|
||||
|
||||
uint32_t
|
||||
dri2_fourcc_for_depth(struct dri2_egl_display *dri2_dpy, uint32_t depth);
|
||||
|
||||
EGLBoolean
|
||||
dri2_x11_get_msc_rate(_EGLDisplay *display, _EGLSurface *surface,
|
||||
EGLint *numerator, EGLint *denominator);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
* Copyright © 2015 Boyan Ding
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <xcb/dri3.h>
|
||||
#include <xcb/present.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#if defined(HAVE_WAYLAND_PLATFORM)
|
||||
#include "util/libdrm.h"
|
||||
#endif
|
||||
#include "drm-uapi/drm_fourcc.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
#include "egl_dri2.h"
|
||||
#include "platform_x11_dri3.h"
|
||||
|
||||
#include "loader.h"
|
||||
#include "x11_dri3.h"
|
||||
#include "loader_dri3_helper.h"
|
||||
|
||||
static struct dri3_egl_surface *
|
||||
loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
size_t offset = offsetof(struct dri3_egl_surface, loader_drawable);
|
||||
return (struct dri3_egl_surface *)(((void *)draw) - offset);
|
||||
}
|
||||
|
||||
static void
|
||||
egl_dri3_set_drawable_size(struct loader_dri3_drawable *draw, int width,
|
||||
int height)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
|
||||
dri3_surf->surf.base.Width = width;
|
||||
dri3_surf->surf.base.Height = height;
|
||||
}
|
||||
|
||||
static bool
|
||||
egl_dri3_in_current_context(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
|
||||
return ctx->Resource.Display == dri3_surf->surf.base.Resource.Display;
|
||||
}
|
||||
|
||||
static struct dri_context *
|
||||
egl_dri3_get_dri_context(struct loader_dri3_drawable *draw)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct dri2_egl_context *dri2_ctx;
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
dri2_ctx = dri2_egl_context(ctx);
|
||||
return dri2_ctx->dri_context;
|
||||
}
|
||||
|
||||
static struct dri_screen *
|
||||
egl_dri3_get_dri_screen(void)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct dri2_egl_context *dri2_ctx;
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
dri2_ctx = dri2_egl_context(ctx);
|
||||
return dri2_egl_display(dri2_ctx->base.Resource.Display)
|
||||
->dri_screen_render_gpu;
|
||||
}
|
||||
|
||||
static void
|
||||
egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
|
||||
_EGLDisplay *disp = dri3_surf->surf.base.Resource.Display;
|
||||
|
||||
dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->surf.base);
|
||||
}
|
||||
|
||||
static const struct loader_dri3_vtable egl_dri3_vtable = {
|
||||
.set_drawable_size = egl_dri3_set_drawable_size,
|
||||
.in_current_context = egl_dri3_in_current_context,
|
||||
.get_dri_context = egl_dri3_get_dri_context,
|
||||
.get_dri_screen = egl_dri3_get_dri_screen,
|
||||
.flush_drawable = egl_dri3_flush_drawable,
|
||||
};
|
||||
|
||||
static EGLBoolean
|
||||
dri3_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
xcb_drawable_t drawable = dri3_surf->loader_drawable.drawable;
|
||||
|
||||
loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
|
||||
|
||||
if (surf->Type == EGL_PBUFFER_BIT)
|
||||
xcb_free_pixmap(dri2_dpy->conn, drawable);
|
||||
|
||||
dri2_fini_surface(surf);
|
||||
free(surf);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_set_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
dri3_surf->surf.base.SwapInterval = interval;
|
||||
loader_dri3_set_swap_interval(&dri3_surf->loader_drawable, interval);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static enum loader_dri3_drawable_type
|
||||
egl_to_loader_dri3_drawable_type(EGLint type)
|
||||
{
|
||||
switch (type) {
|
||||
case EGL_WINDOW_BIT:
|
||||
return LOADER_DRI3_DRAWABLE_WINDOW;
|
||||
case EGL_PIXMAP_BIT:
|
||||
return LOADER_DRI3_DRAWABLE_PIXMAP;
|
||||
case EGL_PBUFFER_BIT:
|
||||
return LOADER_DRI3_DRAWABLE_PBUFFER;
|
||||
default:
|
||||
return LOADER_DRI3_DRAWABLE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
|
||||
void *native_surface, const EGLint *attrib_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
|
||||
struct dri3_egl_surface *dri3_surf;
|
||||
const struct dri_config *dri_config;
|
||||
xcb_drawable_t drawable;
|
||||
|
||||
dri3_surf = calloc(1, sizeof *dri3_surf);
|
||||
if (!dri3_surf) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri3_create_surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf, attrib_list,
|
||||
false, native_surface))
|
||||
goto cleanup_surf;
|
||||
|
||||
if (type == EGL_PBUFFER_BIT) {
|
||||
drawable = xcb_generate_id(dri2_dpy->conn);
|
||||
xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, drawable,
|
||||
dri2_dpy->screen->root, dri3_surf->surf.base.Width,
|
||||
dri3_surf->surf.base.Height);
|
||||
} else {
|
||||
STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
|
||||
drawable = (uintptr_t)native_surface;
|
||||
}
|
||||
|
||||
dri_config =
|
||||
dri2_get_dri_config(dri2_conf, type, dri3_surf->surf.base.GLColorspace);
|
||||
|
||||
if (!dri_config) {
|
||||
_eglError(EGL_BAD_MATCH,
|
||||
"Unsupported surfacetype/colorspace configuration");
|
||||
goto cleanup_pixmap;
|
||||
}
|
||||
|
||||
if (loader_dri3_drawable_init(
|
||||
dri2_dpy->conn, drawable, egl_to_loader_dri3_drawable_type(type),
|
||||
dri2_dpy->dri_screen_render_gpu, dri2_dpy->dri_screen_display_gpu,
|
||||
dri2_dpy->multibuffers_available, true, dri_config,
|
||||
&egl_dri3_vtable,
|
||||
&dri3_surf->loader_drawable)) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri3_surface_create");
|
||||
goto cleanup_pixmap;
|
||||
}
|
||||
|
||||
if (dri3_surf->surf.base.ProtectedContent &&
|
||||
dri2_dpy->fd_render_gpu != dri2_dpy->fd_display_gpu) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri3_surface_create");
|
||||
goto cleanup_pixmap;
|
||||
}
|
||||
|
||||
dri3_surf->loader_drawable.is_protected_content =
|
||||
dri3_surf->surf.base.ProtectedContent;
|
||||
|
||||
return &dri3_surf->surf.base;
|
||||
|
||||
cleanup_pixmap:
|
||||
if (type == EGL_PBUFFER_BIT)
|
||||
xcb_free_pixmap(dri2_dpy->conn, drawable);
|
||||
cleanup_surf:
|
||||
free(dri3_surf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
dri3_authenticate(_EGLDisplay *disp, uint32_t id)
|
||||
{
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
if (!dri2_dpy->swrast) {
|
||||
_eglLog(_EGL_WARNING,
|
||||
"Wayland client render node authentication is unnecessary");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_eglLog(_EGL_WARNING,
|
||||
"Wayland client primary node authentication isn't supported");
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
|
||||
*/
|
||||
static _EGLSurface *
|
||||
dri3_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
void *native_window, const EGLint *attrib_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
_EGLSurface *surf;
|
||||
|
||||
surf = dri3_create_surface(disp, EGL_WINDOW_BIT, conf, native_window,
|
||||
attrib_list);
|
||||
if (surf != NULL)
|
||||
dri3_set_swap_interval(disp, surf, dri2_dpy->default_swap_interval);
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri3_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
void *native_pixmap, const EGLint *attrib_list)
|
||||
{
|
||||
return dri3_create_surface(disp, EGL_PIXMAP_BIT, conf, native_pixmap,
|
||||
attrib_list);
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
dri3_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
return dri3_create_surface(disp, EGL_PBUFFER_BIT, conf, NULL, attrib_list);
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_get_sync_values(_EGLDisplay *display, _EGLSurface *surface,
|
||||
EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surface);
|
||||
|
||||
return loader_dri3_wait_for_msc(&dri3_surf->loader_drawable, 0, 0, 0,
|
||||
(int64_t *)ust, (int64_t *)msc,
|
||||
(int64_t *)sbc)
|
||||
? EGL_TRUE
|
||||
: EGL_FALSE;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_image *dri2_img;
|
||||
xcb_drawable_t drawable;
|
||||
xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
|
||||
xcb_dri3_buffer_from_pixmap_reply_t *bp_reply;
|
||||
unsigned int fourcc;
|
||||
|
||||
drawable = (xcb_drawable_t)(uintptr_t)buffer;
|
||||
bp_cookie = xcb_dri3_buffer_from_pixmap(dri2_dpy->conn, drawable);
|
||||
bp_reply =
|
||||
xcb_dri3_buffer_from_pixmap_reply(dri2_dpy->conn, bp_cookie, NULL);
|
||||
if (!bp_reply) {
|
||||
_eglError(EGL_BAD_ALLOC, "xcb_dri3_buffer_from_pixmap");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fourcc = dri2_fourcc_for_depth(dri2_dpy, bp_reply->depth);
|
||||
if (fourcc == DRM_FORMAT_INVALID) {
|
||||
_eglError(EGL_BAD_PARAMETER,
|
||||
"dri3_create_image_khr: unsupported pixmap depth");
|
||||
free(bp_reply);
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
dri2_img = malloc(sizeof *dri2_img);
|
||||
if (!dri2_img) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
|
||||
free(bp_reply);
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
_eglInitImage(&dri2_img->base, disp);
|
||||
|
||||
dri2_img->dri_image = loader_dri3_create_image(
|
||||
dri2_dpy->conn, bp_reply, fourcc, dri2_dpy->dri_screen_render_gpu,
|
||||
dri2_img);
|
||||
|
||||
free(bp_reply);
|
||||
|
||||
return &dri2_img->base;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
EGLClientBuffer buffer,
|
||||
const EGLint *attr_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_image *dri2_img;
|
||||
xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie;
|
||||
xcb_dri3_buffers_from_pixmap_reply_t *bp_reply;
|
||||
xcb_drawable_t drawable;
|
||||
unsigned int fourcc;
|
||||
|
||||
drawable = (xcb_drawable_t)(uintptr_t)buffer;
|
||||
bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable);
|
||||
bp_reply =
|
||||
xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn, bp_cookie, NULL);
|
||||
|
||||
if (!bp_reply) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
fourcc = dri2_fourcc_for_depth(dri2_dpy, bp_reply->depth);
|
||||
if (fourcc == DRM_FORMAT_INVALID) {
|
||||
_eglError(EGL_BAD_PARAMETER,
|
||||
"dri3_create_image_khr: unsupported pixmap depth");
|
||||
free(bp_reply);
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
dri2_img = malloc(sizeof *dri2_img);
|
||||
if (!dri2_img) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
|
||||
free(bp_reply);
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
_eglInitImage(&dri2_img->base, disp);
|
||||
|
||||
dri2_img->dri_image = loader_dri3_create_image_from_buffers(
|
||||
dri2_dpy->conn, bp_reply, fourcc, dri2_dpy->dri_screen_render_gpu,
|
||||
dri2_img);
|
||||
free(bp_reply);
|
||||
|
||||
if (!dri2_img->dri_image) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
|
||||
free(dri2_img);
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
return &dri2_img->base;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri3_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
|
||||
EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
switch (target) {
|
||||
case EGL_NATIVE_PIXMAP_KHR:
|
||||
if (dri2_dpy->multibuffers_available)
|
||||
return dri3_create_image_khr_pixmap_from_buffers(disp, ctx, buffer,
|
||||
attr_list);
|
||||
return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
|
||||
default:
|
||||
return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the driver when it needs to update the real front buffer with the
|
||||
* contents of its fake front buffer.
|
||||
*/
|
||||
static void
|
||||
dri3_flush_front_buffer(struct dri_drawable *driDrawable, void *loaderPrivate)
|
||||
{
|
||||
struct loader_dri3_drawable *draw = loaderPrivate;
|
||||
(void)driDrawable;
|
||||
|
||||
/* There does not seem to be any kind of consensus on whether we should
|
||||
* support front-buffer rendering or not:
|
||||
* http://lists.freedesktop.org/archives/mesa-dev/2013-June/040129.html
|
||||
*/
|
||||
if (draw->type == LOADER_DRI3_DRAWABLE_WINDOW)
|
||||
_eglLog(_EGL_WARNING,
|
||||
"FIXME: egl/x11 doesn't support front buffer rendering.");
|
||||
}
|
||||
|
||||
const __DRIimageLoaderExtension dri3_image_loader_extension = {
|
||||
.base = {__DRI_IMAGE_LOADER, 1},
|
||||
|
||||
.getBuffers = loader_dri3_get_buffers,
|
||||
.flushFrontBuffer = dri3_flush_front_buffer,
|
||||
};
|
||||
|
||||
static EGLBoolean
|
||||
dri3_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *draw,
|
||||
const EGLint *rects, EGLint n_rects)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
|
||||
|
||||
return loader_dri3_swap_buffers_msc(
|
||||
&dri3_surf->loader_drawable, 0, 0, 0, 0, rects, n_rects,
|
||||
draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
|
||||
{
|
||||
return dri3_swap_buffers_with_damage(disp, draw, NULL, 0);
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf,
|
||||
void *native_pixmap_target)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
xcb_pixmap_t target;
|
||||
|
||||
STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_pixmap_target));
|
||||
target = (uintptr_t)native_pixmap_target;
|
||||
|
||||
loader_dri3_copy_drawable(&dri3_surf->loader_drawable, target,
|
||||
dri3_surf->loader_drawable.drawable);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
dri3_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri3_query_surface(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
|
||||
EGLint *value)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
switch (attribute) {
|
||||
case EGL_WIDTH:
|
||||
case EGL_HEIGHT:
|
||||
loader_dri3_update_drawable_geometry(&dri3_surf->loader_drawable);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return _eglQuerySurface(disp, surf, attribute, value);
|
||||
}
|
||||
|
||||
static struct dri_drawable *
|
||||
dri3_get_dri_drawable(_EGLSurface *surf)
|
||||
{
|
||||
struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
|
||||
|
||||
return dri3_surf->loader_drawable.dri_drawable;
|
||||
}
|
||||
|
||||
static void
|
||||
dri3_close_screen_notify(_EGLDisplay *disp)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
|
||||
loader_dri3_close_screen(dri2_dpy->dri_screen_render_gpu);
|
||||
}
|
||||
|
||||
struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
|
||||
.authenticate = dri3_authenticate,
|
||||
.create_window_surface = dri3_create_window_surface,
|
||||
.create_pixmap_surface = dri3_create_pixmap_surface,
|
||||
.create_pbuffer_surface = dri3_create_pbuffer_surface,
|
||||
.destroy_surface = dri3_destroy_surface,
|
||||
.create_image = dri3_create_image_khr,
|
||||
.swap_interval = dri3_set_swap_interval,
|
||||
.swap_buffers = dri3_swap_buffers,
|
||||
.swap_buffers_with_damage = dri3_swap_buffers_with_damage,
|
||||
.copy_buffers = dri3_copy_buffers,
|
||||
.query_buffer_age = dri3_query_buffer_age,
|
||||
.query_surface = dri3_query_surface,
|
||||
.get_sync_values = dri3_get_sync_values,
|
||||
.get_msc_rate = dri2_x11_get_msc_rate,
|
||||
.get_dri_drawable = dri3_get_dri_drawable,
|
||||
.close_screen_notify = dri3_close_screen_notify,
|
||||
};
|
||||
|
||||
bool
|
||||
dri3_x11_connect(struct dri2_egl_display *dri2_dpy, bool swrast)
|
||||
{
|
||||
dri2_dpy->fd_render_gpu =
|
||||
x11_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0);
|
||||
if (dri2_dpy->fd_render_gpu < 0) {
|
||||
int conn_error = xcb_connection_has_error(dri2_dpy->conn);
|
||||
if (!swrast) {
|
||||
_eglLog(_EGL_WARNING, "DRI3 error: Could not get DRI3 device");
|
||||
_eglLog(_EGL_WARNING, "Ensure your X server supports DRI3 to get accelerated rendering");
|
||||
if (conn_error)
|
||||
_eglLog(_EGL_WARNING, "DRI3: Failed to initialize");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
loader_get_user_preferred_fd(&dri2_dpy->fd_render_gpu,
|
||||
&dri2_dpy->fd_display_gpu);
|
||||
|
||||
if (!dri2_dpy->driver_name)
|
||||
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd_render_gpu);
|
||||
|
||||
if (!dri2_dpy->driver_name) {
|
||||
_eglLog(_EGL_WARNING, "DRI3: No driver found");
|
||||
close(dri2_dpy->fd_render_gpu);
|
||||
dri2_dpy->fd_render_gpu = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
/* Only try to get a render device name since dri3 doesn't provide a
|
||||
* mechanism for authenticating client opened device node fds. If this
|
||||
* fails then don't advertise the extension. */
|
||||
dri2_dpy->device_name =
|
||||
drmGetRenderDeviceNameFromFd(dri2_dpy->fd_render_gpu);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2015 Boyan Ding
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef EGL_X11_DRI3_INCLUDED
|
||||
#define EGL_X11_DRI3_INCLUDED
|
||||
|
||||
#include "platform_x11.h"
|
||||
#if !defined(HAVE_LIBDRM)
|
||||
#include "loader_dri3_helper.h"
|
||||
#endif
|
||||
_EGL_DRIVER_TYPECAST(dri3_egl_surface, _EGLSurface, obj)
|
||||
|
||||
struct dri3_egl_surface {
|
||||
struct dri2_egl_surface surf;
|
||||
struct loader_dri3_drawable loader_drawable;
|
||||
};
|
||||
|
||||
extern const __DRIimageLoaderExtension dri3_image_loader_extension;
|
||||
extern struct dri2_egl_display_vtbl dri3_x11_display_vtbl;
|
||||
|
||||
bool
|
||||
dri3_x11_connect(struct dri2_egl_display *dri2_dpy, bool swrast);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
[*.cpp]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
*
|
||||
* Copyright (C) 2014 Adrián Arroyo Calle <[email protected]>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "eglcurrent.h"
|
||||
#include "egldevice.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglimage.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "mesa/glapi/glapi/glapi.h"
|
||||
|
||||
#include "hgl/hgl_sw_winsys.h"
|
||||
#include "hgl_context.h"
|
||||
|
||||
#include <Bitmap.h>
|
||||
|
||||
extern "C" {
|
||||
#include "target-helpers/inline_sw_helper.h"
|
||||
}
|
||||
|
||||
#if MESA_DEBUG
|
||||
#define TRACE(x...) printf("egl_haiku: " x)
|
||||
#define CALLED() TRACE("CALLED: %s\n", __PRETTY_FUNCTION__)
|
||||
#else
|
||||
#define TRACE(x...)
|
||||
#define CALLED()
|
||||
#endif
|
||||
#define ERROR(x...) printf("egl_haiku: " x)
|
||||
|
||||
_EGL_DRIVER_STANDARD_TYPECASTS(haiku_egl)
|
||||
|
||||
struct haiku_egl_display {
|
||||
int ref_count;
|
||||
struct hgl_display *disp;
|
||||
};
|
||||
|
||||
struct haiku_egl_config {
|
||||
_EGLConfig base;
|
||||
};
|
||||
|
||||
struct haiku_egl_context {
|
||||
_EGLContext base;
|
||||
struct hgl_context *ctx;
|
||||
};
|
||||
|
||||
struct haiku_egl_surface {
|
||||
_EGLSurface base;
|
||||
struct hgl_buffer *fb;
|
||||
struct pipe_fence_handle *throttle_fence;
|
||||
};
|
||||
|
||||
// #pragma mark EGLSurface
|
||||
|
||||
// Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
|
||||
static _EGLSurface *
|
||||
haiku_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
void *native_window, const EGLint *attrib_list)
|
||||
{
|
||||
printf("haiku_create_window_surface\n");
|
||||
struct haiku_egl_display *hgl_dpy = haiku_egl_display(disp);
|
||||
|
||||
struct haiku_egl_surface *wgl_surf =
|
||||
(struct haiku_egl_surface *)calloc(1, sizeof(*wgl_surf));
|
||||
if (!wgl_surf)
|
||||
return NULL;
|
||||
|
||||
if (!_eglInitSurface(&wgl_surf->base, disp, EGL_WINDOW_BIT, conf,
|
||||
attrib_list, NULL)) {
|
||||
free(wgl_surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct st_visual visual;
|
||||
hgl_get_st_visual(&visual, HGL_DOUBLE | HGL_DEPTH);
|
||||
|
||||
wgl_surf->fb =
|
||||
hgl_create_st_framebuffer(hgl_dpy->disp, &visual, native_window);
|
||||
if (!wgl_surf->fb) {
|
||||
free(wgl_surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Unset and delete previously set bitmap if any.
|
||||
delete ((BitmapHook *)native_window)->SetBitmap(NULL);
|
||||
|
||||
return &wgl_surf->base;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
haiku_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
void *native_pixmap, const EGLint *attrib_list)
|
||||
{
|
||||
printf("haiku_create_pixmap_surface\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static _EGLSurface *
|
||||
haiku_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
printf("haiku_create_pbuffer_surface\n");
|
||||
struct haiku_egl_display *hgl_dpy = haiku_egl_display(disp);
|
||||
|
||||
struct haiku_egl_surface *wgl_surf =
|
||||
(struct haiku_egl_surface *)calloc(1, sizeof(*wgl_surf));
|
||||
if (!wgl_surf)
|
||||
return NULL;
|
||||
|
||||
if (!_eglInitSurface(&wgl_surf->base, disp, EGL_PBUFFER_BIT, conf,
|
||||
attrib_list, NULL)) {
|
||||
free(wgl_surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct st_visual visual;
|
||||
hgl_get_st_visual(&visual, HGL_DOUBLE | HGL_DEPTH);
|
||||
|
||||
wgl_surf->fb = hgl_create_st_framebuffer(hgl_dpy->disp, &visual, NULL);
|
||||
if (!wgl_surf->fb) {
|
||||
free(wgl_surf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wgl_surf->fb->newWidth = wgl_surf->base.Width;
|
||||
wgl_surf->fb->newHeight = wgl_surf->base.Height;
|
||||
p_atomic_inc(&wgl_surf->fb->base.stamp);
|
||||
|
||||
return &wgl_surf->base;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
haiku_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct haiku_egl_display *hgl_dpy = haiku_egl_display(disp);
|
||||
if (_eglPutSurface(surf)) {
|
||||
struct haiku_egl_surface *hgl_surf = haiku_egl_surface(surf);
|
||||
struct pipe_screen *screen = hgl_dpy->disp->fscreen->screen;
|
||||
screen->fence_reference(screen, &hgl_surf->throttle_fence, NULL);
|
||||
|
||||
// Unset bitmap to release ownership. Bitmap will be deleted later
|
||||
// when destroying framebuffer.
|
||||
BitmapHook *bitmapHook = (BitmapHook*)hgl_surf->fb->winsysContext;
|
||||
if (bitmapHook != NULL)
|
||||
bitmapHook->SetBitmap(NULL);
|
||||
|
||||
hgl_destroy_st_framebuffer(hgl_surf->fb);
|
||||
free(surf);
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_size(struct hgl_buffer *buffer)
|
||||
{
|
||||
uint32_t newWidth, newHeight;
|
||||
((BitmapHook *)buffer->winsysContext)->GetSize(newWidth, newHeight);
|
||||
if (buffer->newWidth != newWidth || buffer->newHeight != newHeight) {
|
||||
buffer->newWidth = newWidth;
|
||||
buffer->newHeight = newHeight;
|
||||
p_atomic_inc(&buffer->base.stamp);
|
||||
}
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
haiku_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf)
|
||||
{
|
||||
struct haiku_egl_display *hgl_dpy = haiku_egl_display(disp);
|
||||
struct haiku_egl_surface *hgl_surf = haiku_egl_surface(surf);
|
||||
struct haiku_egl_context *hgl_ctx = haiku_egl_context(surf->CurrentContext);
|
||||
if (hgl_ctx == NULL)
|
||||
return EGL_FALSE;
|
||||
|
||||
struct st_context *st = hgl_ctx->ctx->st;
|
||||
struct pipe_screen *screen = hgl_dpy->disp->fscreen->screen;
|
||||
|
||||
struct hgl_buffer *buffer = hgl_surf->fb;
|
||||
auto &frontBuffer = buffer->textures[ST_ATTACHMENT_FRONT_LEFT];
|
||||
auto &backBuffer = buffer->textures[ST_ATTACHMENT_BACK_LEFT];
|
||||
|
||||
// Inform ST of a flush if double buffering is used
|
||||
if (backBuffer != NULL)
|
||||
st->pipe->flush_resource(st->pipe, backBuffer);
|
||||
|
||||
_mesa_glthread_finish(st->ctx);
|
||||
|
||||
struct pipe_fence_handle *new_fence = NULL;
|
||||
st_context_flush(st, ST_FLUSH_FRONT, &new_fence, NULL, NULL);
|
||||
if (hgl_surf->throttle_fence) {
|
||||
screen->fence_finish(screen, NULL, hgl_surf->throttle_fence,
|
||||
OS_TIMEOUT_INFINITE);
|
||||
screen->fence_reference(screen, &hgl_surf->throttle_fence, NULL);
|
||||
}
|
||||
hgl_surf->throttle_fence = new_fence;
|
||||
|
||||
// flush back buffer and swap buffers if double buffering is used
|
||||
if (backBuffer != NULL) {
|
||||
screen->flush_frontbuffer(screen, st->pipe, backBuffer, 0, 0,
|
||||
buffer->winsysContext, 1, NULL);
|
||||
std::swap(frontBuffer, backBuffer);
|
||||
p_atomic_inc(&buffer->base.stamp);
|
||||
}
|
||||
|
||||
// XXX: right front / back if HGL_STEREO?
|
||||
|
||||
update_size(buffer);
|
||||
|
||||
st_context_invalidate_state(st, ST_INVALIDATE_FB_STATE);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// #pragma mark EGLDisplay
|
||||
|
||||
static EGLBoolean
|
||||
haiku_add_configs_for_visuals(_EGLDisplay *disp)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
struct haiku_egl_config *conf;
|
||||
conf = (struct haiku_egl_config *)calloc(1, sizeof(*conf));
|
||||
if (!conf)
|
||||
return _eglError(EGL_BAD_ALLOC, "haiku_add_configs_for_visuals");
|
||||
|
||||
_eglInitConfig(&conf->base, disp, 1);
|
||||
TRACE("Config inited\n");
|
||||
|
||||
conf->base.RedSize = 8;
|
||||
conf->base.BlueSize = 8;
|
||||
conf->base.GreenSize = 8;
|
||||
conf->base.LuminanceSize = 0;
|
||||
conf->base.AlphaSize = 8;
|
||||
conf->base.ColorBufferType = EGL_RGB_BUFFER;
|
||||
conf->base.BufferSize = conf->base.RedSize + conf->base.GreenSize +
|
||||
conf->base.BlueSize + conf->base.AlphaSize;
|
||||
conf->base.ConfigCaveat = EGL_NONE;
|
||||
conf->base.ConfigID = 1;
|
||||
conf->base.BindToTextureRGB = EGL_FALSE;
|
||||
conf->base.BindToTextureRGBA = EGL_FALSE;
|
||||
conf->base.StencilSize = 0;
|
||||
conf->base.TransparentType = EGL_NONE;
|
||||
conf->base.NativeRenderable = EGL_TRUE; // Let's say yes
|
||||
conf->base.NativeVisualID = 0; // No visual
|
||||
conf->base.NativeVisualType = EGL_NONE; // No visual
|
||||
conf->base.RenderableType = 0x8;
|
||||
conf->base.SampleBuffers = 0; // TODO: How to get the right value ?
|
||||
conf->base.Samples = conf->base.SampleBuffers == 0 ? 0 : 0;
|
||||
conf->base.DepthSize = 24; // TODO: How to get the right value ?
|
||||
conf->base.Level = 0;
|
||||
conf->base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH;
|
||||
conf->base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT;
|
||||
conf->base.MaxPbufferPixels = 0; // TODO: How to get the right value ?
|
||||
conf->base.SurfaceType = EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT;
|
||||
|
||||
TRACE("Config configuated\n");
|
||||
if (!_eglValidateConfig(&conf->base, EGL_FALSE)) {
|
||||
_eglLog(_EGL_DEBUG, "Haiku: failed to validate config");
|
||||
goto cleanup;
|
||||
}
|
||||
TRACE("Validated config\n");
|
||||
|
||||
_eglLinkConfig(&conf->base);
|
||||
if (!_eglGetArraySize(disp->Configs)) {
|
||||
_eglLog(_EGL_WARNING, "Haiku: failed to create any config");
|
||||
goto cleanup;
|
||||
}
|
||||
TRACE("Config successful\n");
|
||||
|
||||
return EGL_TRUE;
|
||||
|
||||
cleanup:
|
||||
free(conf);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
haiku_display_destroy(_EGLDisplay *disp)
|
||||
{
|
||||
if (!disp)
|
||||
return;
|
||||
|
||||
struct haiku_egl_display *hgl_dpy = haiku_egl_display(disp);
|
||||
|
||||
assert(hgl_dpy->ref_count > 0);
|
||||
if (!p_atomic_dec_zero(&hgl_dpy->ref_count))
|
||||
return;
|
||||
|
||||
struct pipe_screen *screen = hgl_dpy->disp->fscreen->screen;
|
||||
hgl_destroy_display(hgl_dpy->disp);
|
||||
hgl_dpy->disp = NULL;
|
||||
screen->destroy(screen); // destroy will deallocate object
|
||||
|
||||
free(hgl_dpy);
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
haiku_initialize_impl(_EGLDisplay *disp, void *platformDisplay)
|
||||
{
|
||||
struct haiku_egl_display *hgl_dpy;
|
||||
|
||||
hgl_dpy =
|
||||
(struct haiku_egl_display *)calloc(1, sizeof(struct haiku_egl_display));
|
||||
if (!hgl_dpy)
|
||||
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
|
||||
|
||||
hgl_dpy->ref_count = 1;
|
||||
disp->DriverData = (void *)hgl_dpy;
|
||||
|
||||
struct sw_winsys *winsys = hgl_create_sw_winsys();
|
||||
struct pipe_screen *screen = sw_screen_create(winsys);
|
||||
hgl_dpy->disp = hgl_create_display(screen);
|
||||
|
||||
disp->ClientAPIs = 0;
|
||||
if (_eglIsApiValid(EGL_OPENGL_API))
|
||||
disp->ClientAPIs |= EGL_OPENGL_BIT;
|
||||
if (_eglIsApiValid(EGL_OPENGL_ES_API))
|
||||
disp->ClientAPIs |=
|
||||
EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
|
||||
|
||||
disp->Extensions.KHR_no_config_context = EGL_TRUE;
|
||||
disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
|
||||
disp->Extensions.MESA_query_driver = EGL_TRUE;
|
||||
|
||||
/* Report back to EGL the bitmask of priorities supported */
|
||||
disp->Extensions.IMG_context_priority =
|
||||
hgl_dpy->disp->fscreen->screen->caps.context_priority_mask;
|
||||
disp->Extensions.NV_context_priority_realtime =
|
||||
disp->Extensions.IMG_context_priority &
|
||||
(1 << __EGL_CONTEXT_PRIORITY_REALTIME_BIT);
|
||||
|
||||
disp->Extensions.EXT_pixel_format_float = EGL_TRUE;
|
||||
|
||||
if (hgl_dpy->disp->fscreen->screen->is_format_supported(
|
||||
hgl_dpy->disp->fscreen->screen, PIPE_FORMAT_B8G8R8A8_SRGB,
|
||||
PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_RENDER_TARGET))
|
||||
disp->Extensions.KHR_gl_colorspace = EGL_TRUE;
|
||||
|
||||
disp->Extensions.KHR_create_context = EGL_TRUE;
|
||||
disp->Extensions.KHR_reusable_sync = EGL_TRUE;
|
||||
|
||||
haiku_add_configs_for_visuals(disp);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
haiku_initialize(_EGLDisplay *disp)
|
||||
{
|
||||
EGLBoolean ret = EGL_FALSE;
|
||||
struct haiku_egl_display *hgl_dpy = haiku_egl_display(disp);
|
||||
|
||||
if (hgl_dpy) {
|
||||
hgl_dpy->ref_count++;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
switch (disp->Platform) {
|
||||
case _EGL_PLATFORM_SURFACELESS:
|
||||
case _EGL_PLATFORM_HAIKU:
|
||||
ret = haiku_initialize_impl(disp, NULL);
|
||||
break;
|
||||
case _EGL_PLATFORM_DEVICE:
|
||||
ret = haiku_initialize_impl(disp, disp->PlatformDisplay);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("Callers ensure we cannot get here.");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
return EGL_FALSE;
|
||||
|
||||
hgl_dpy = haiku_egl_display(disp);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
haiku_terminate(_EGLDisplay *disp)
|
||||
{
|
||||
haiku_display_destroy(disp);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// #pragma mark EGLContext
|
||||
|
||||
static _EGLContext *
|
||||
haiku_create_context(_EGLDisplay *disp, _EGLConfig *conf,
|
||||
_EGLContext *share_list, const EGLint *attrib_list)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
struct haiku_egl_display *hgl_dpy = haiku_egl_display(disp);
|
||||
|
||||
struct st_visual visual;
|
||||
hgl_get_st_visual(&visual, HGL_DOUBLE | HGL_DEPTH);
|
||||
|
||||
struct haiku_egl_context *context =
|
||||
(struct haiku_egl_context *)calloc(1, sizeof(*context));
|
||||
if (!context) {
|
||||
_eglError(EGL_BAD_ALLOC, "haiku_create_context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitContext(&context->base, disp, conf, share_list, attrib_list))
|
||||
goto cleanup;
|
||||
|
||||
context->ctx = hgl_create_context(
|
||||
hgl_dpy->disp, &visual,
|
||||
share_list == NULL ? NULL : haiku_egl_context(share_list)->ctx->st);
|
||||
if (context->ctx == NULL)
|
||||
goto cleanup;
|
||||
|
||||
return &context->base;
|
||||
|
||||
cleanup:
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
haiku_destroy_context(_EGLDisplay *disp, _EGLContext *ctx)
|
||||
{
|
||||
if (_eglPutContext(ctx)) {
|
||||
struct haiku_egl_context *hgl_ctx = haiku_egl_context(ctx);
|
||||
hgl_destroy_context(hgl_ctx->ctx);
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
haiku_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, _EGLSurface *rsurf,
|
||||
_EGLContext *ctx)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
struct haiku_egl_context *hgl_ctx = haiku_egl_context(ctx);
|
||||
struct haiku_egl_surface *hgl_dsurf = haiku_egl_surface(dsurf);
|
||||
struct haiku_egl_surface *hgl_rsurf = haiku_egl_surface(rsurf);
|
||||
_EGLContext *old_ctx;
|
||||
_EGLSurface *old_dsurf, *old_rsurf;
|
||||
|
||||
if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
|
||||
return EGL_FALSE;
|
||||
|
||||
if (old_ctx == ctx && old_dsurf == dsurf && old_rsurf == rsurf) {
|
||||
_eglPutSurface(old_dsurf);
|
||||
_eglPutSurface(old_rsurf);
|
||||
_eglPutContext(old_ctx);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
st_api_make_current(NULL, NULL, NULL);
|
||||
} else {
|
||||
if (dsurf != NULL && dsurf != old_dsurf)
|
||||
update_size(hgl_dsurf->fb);
|
||||
|
||||
st_api_make_current(hgl_ctx->ctx->st,
|
||||
hgl_dsurf == NULL ? NULL : &hgl_dsurf->fb->base,
|
||||
hgl_rsurf == NULL ? NULL : &hgl_rsurf->fb->base);
|
||||
}
|
||||
|
||||
if (old_dsurf != NULL)
|
||||
haiku_destroy_surface(disp, old_dsurf);
|
||||
if (old_rsurf != NULL)
|
||||
haiku_destroy_surface(disp, old_rsurf);
|
||||
if (old_ctx != NULL)
|
||||
haiku_destroy_context(disp, old_ctx);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
extern "C" const _EGLDriver _eglDriver = {
|
||||
.Initialize = haiku_initialize,
|
||||
.Terminate = haiku_terminate,
|
||||
.CreateContext = haiku_create_context,
|
||||
.DestroyContext = haiku_destroy_context,
|
||||
.MakeCurrent = haiku_make_current,
|
||||
.CreateWindowSurface = haiku_create_window_surface,
|
||||
.CreatePixmapSurface = haiku_create_pixmap_surface,
|
||||
.CreatePbufferSurface = haiku_create_pbuffer_surface,
|
||||
.DestroySurface = haiku_destroy_surface,
|
||||
.SwapBuffers = haiku_swap_buffers,
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright © Microsoft Corporation
|
||||
*
|
||||
* 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 (including the next
|
||||
* paragraph) 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <eglconfig.h>
|
||||
#include <egldisplay.h>
|
||||
#include <egldriver.h>
|
||||
#include <eglimage.h>
|
||||
#include <eglsync.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <stw_pixelformat.h>
|
||||
|
||||
struct wgl_egl_display {
|
||||
struct pipe_frontend_screen base;
|
||||
_EGLDisplay *parent;
|
||||
int ref_count;
|
||||
struct pipe_screen *screen;
|
||||
};
|
||||
|
||||
struct wgl_egl_config {
|
||||
_EGLConfig base;
|
||||
const struct stw_pixelformat_info *stw_config[2];
|
||||
};
|
||||
|
||||
struct wgl_egl_context {
|
||||
_EGLContext base;
|
||||
struct stw_context *ctx;
|
||||
};
|
||||
|
||||
struct wgl_egl_surface {
|
||||
_EGLSurface base;
|
||||
struct stw_framebuffer *fb;
|
||||
};
|
||||
|
||||
struct wgl_egl_image {
|
||||
_EGLImage base;
|
||||
struct stw_image *img;
|
||||
};
|
||||
|
||||
struct wgl_egl_sync {
|
||||
_EGLSync base;
|
||||
int refcount;
|
||||
struct pipe_fence_handle *fence;
|
||||
HANDLE event;
|
||||
};
|
||||
|
||||
_EGL_DRIVER_STANDARD_TYPECASTS(wgl_egl)
|
||||
_EGL_DRIVER_TYPECAST(wgl_egl_image, _EGLImage, obj)
|
||||
_EGL_DRIVER_TYPECAST(wgl_egl_sync, _EGLSync, obj)
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
from generate.eglFunctionList import EGL_FUNCTIONS as GLVND_ENTRYPOINTS
|
||||
|
||||
|
||||
PREFIX1 = 'EGL_ENTRYPOINT('
|
||||
PREFIX2 = 'EGL_ENTRYPOINT2('
|
||||
SUFFIX = ')'
|
||||
|
||||
|
||||
# These entrypoints should *not* be in the GLVND entrypoints
|
||||
GLVND_EXCLUDED_ENTRYPOINTS = [
|
||||
# EGL_KHR_debug
|
||||
'eglDebugMessageControlKHR',
|
||||
'eglQueryDebugKHR',
|
||||
'eglLabelObjectKHR',
|
||||
]
|
||||
|
||||
|
||||
def check_entrypoint_sorted(entrypoints):
|
||||
print('Checking that EGL API entrypoints are sorted...')
|
||||
|
||||
for i, _ in enumerate(entrypoints):
|
||||
# Can't compare the first one with the previous
|
||||
if i == 0:
|
||||
continue
|
||||
if entrypoints[i - 1] > entrypoints[i]:
|
||||
print('ERROR: ' + entrypoints[i] +
|
||||
' should come before ' + entrypoints[i - 1])
|
||||
exit(1)
|
||||
|
||||
print('All good :)')
|
||||
|
||||
|
||||
def check_glvnd_entrypoints(egl_entrypoints, glvnd_entrypoints):
|
||||
print('Checking the GLVND entrypoints against the plain EGL ones...')
|
||||
success = True
|
||||
|
||||
for egl_entrypoint in egl_entrypoints:
|
||||
if egl_entrypoint in GLVND_EXCLUDED_ENTRYPOINTS:
|
||||
continue
|
||||
if egl_entrypoint not in glvnd_entrypoints:
|
||||
print('ERROR: ' + egl_entrypoint +
|
||||
' is missing from the GLVND entrypoints (src/egl/generate/eglFunctionList.py)')
|
||||
success = False
|
||||
|
||||
for glvnd_entrypoint in glvnd_entrypoints:
|
||||
if glvnd_entrypoint not in egl_entrypoints:
|
||||
print('ERROR: ' + glvnd_entrypoint +
|
||||
' is missing from the plain EGL entrypoints (src/egl/main/eglentrypoint.h)')
|
||||
success = False
|
||||
|
||||
for glvnd_entrypoint in GLVND_EXCLUDED_ENTRYPOINTS:
|
||||
if glvnd_entrypoint in glvnd_entrypoints:
|
||||
print('ERROR: ' + glvnd_entrypoint +
|
||||
' is should *not* be in the GLVND entrypoints (src/egl/generate/eglFunctionList.py)')
|
||||
success = False
|
||||
|
||||
if success:
|
||||
print('All good :)')
|
||||
else:
|
||||
exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('header')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.header) as header:
|
||||
lines = header.readlines()
|
||||
|
||||
entrypoints = []
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if line.startswith(PREFIX1):
|
||||
assert line.endswith(SUFFIX)
|
||||
entrypoints.append(line[len(PREFIX1):-len(SUFFIX)])
|
||||
if line.startswith(PREFIX2):
|
||||
assert line.endswith(SUFFIX)
|
||||
entrypoint = line[len(PREFIX2):-len(SUFFIX)]
|
||||
entrypoint = entrypoint.split(',')[0].strip()
|
||||
entrypoints.append(entrypoint)
|
||||
|
||||
check_entrypoint_sorted(entrypoints)
|
||||
|
||||
glvnd_entrypoints = [x[0] for x in GLVND_ENTRYPOINTS]
|
||||
|
||||
check_glvnd_entrypoints(entrypoints, glvnd_entrypoints)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,4 @@
|
||||
__egl_Main
|
||||
MesaGLInteropEGLQueryDeviceInfo
|
||||
MesaGLInteropEGLExportObject
|
||||
MesaGLInteropEGLFlushObjects
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
global:
|
||||
__egl_Main;
|
||||
MesaGLInteropEGLQueryDeviceInfo;
|
||||
MesaGLInteropEGLExportObject;
|
||||
MesaGLInteropEGLFlushObjects;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
eglBindAPI
|
||||
eglBindTexImage
|
||||
eglChooseConfig
|
||||
eglClientWaitSync
|
||||
eglCopyBuffers
|
||||
eglCreateContext
|
||||
eglCreateImage
|
||||
eglCreatePbufferFromClientBuffer
|
||||
eglCreatePbufferSurface
|
||||
eglCreatePixmapSurface
|
||||
eglCreatePlatformPixmapSurface
|
||||
eglCreatePlatformWindowSurface
|
||||
eglCreateSync
|
||||
eglCreateWindowSurface
|
||||
eglDestroyContext
|
||||
eglDestroyImage
|
||||
eglDestroySurface
|
||||
eglDestroySync
|
||||
eglGetConfigAttrib
|
||||
eglGetConfigs
|
||||
eglGetCurrentContext
|
||||
eglGetCurrentDisplay
|
||||
eglGetCurrentSurface
|
||||
eglGetDisplay
|
||||
eglGetError
|
||||
eglGetPlatformDisplay
|
||||
eglGetProcAddress
|
||||
eglGetSyncAttrib
|
||||
eglInitialize
|
||||
eglMakeCurrent
|
||||
eglQueryAPI
|
||||
eglQueryContext
|
||||
eglQueryString
|
||||
eglQuerySurface
|
||||
eglReleaseTexImage
|
||||
eglReleaseThread
|
||||
eglSurfaceAttrib
|
||||
eglSwapBuffers
|
||||
eglSwapInterval
|
||||
eglTerminate
|
||||
eglWaitClient
|
||||
eglWaitGL
|
||||
eglWaitNative
|
||||
eglWaitSync
|
||||
MesaGLInteropEGLQueryDeviceInfo
|
||||
MesaGLInteropEGLExportObject
|
||||
MesaGLInteropEGLFlushObjects
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
global:
|
||||
egl*;
|
||||
MesaGLInteropEGL*;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,247 @@
|
||||
# (C) Copyright 2016, 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
|
||||
# on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
# license, 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 (including the next
|
||||
# paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
# IBM AND/OR ITS SUPPLIERS 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.
|
||||
#
|
||||
# Authors:
|
||||
# Kyle Brenneman <[email protected]>
|
||||
|
||||
"""
|
||||
Contains a list of EGL functions to generate dispatch functions for.
|
||||
|
||||
This is used from gen_egl_dispatch.py.
|
||||
|
||||
EGL_FUNCTIONS is a sequence of (name, eglData) pairs, where name is the name
|
||||
of the function, and eglData is a dictionary containing data about that
|
||||
function.
|
||||
|
||||
The values in the eglData dictionary are:
|
||||
- method (string):
|
||||
How to select a vendor library. See "Method values" below.
|
||||
|
||||
- prefix (string):
|
||||
This string is prepended to the name of the dispatch function. If
|
||||
unspecified, the default is "" (an empty string).
|
||||
|
||||
- static (boolean)
|
||||
If True, this function should be declared static.
|
||||
|
||||
- "public" (boolean)
|
||||
If True, the function should be exported from the library. Vendor libraries
|
||||
generally should not use this.
|
||||
|
||||
- extension (string):
|
||||
If specified, this is the name of a macro to check for before defining a
|
||||
function. Used for checking for extension macros and such.
|
||||
|
||||
- retval (string):
|
||||
If specified, this is a C expression with the default value to return if we
|
||||
can't find a function to call. By default, it will try to guess from the
|
||||
return type: EGL_NO_whatever for the various handle types, NULL for
|
||||
pointers, and zero for everything else.
|
||||
|
||||
method values:
|
||||
- "custom"
|
||||
The dispatch stub will be hand-written instead of generated.
|
||||
|
||||
- "none"
|
||||
No dispatch function exists at all, but the function should still have an
|
||||
entry in the index array. This is for other functions that a stub may need
|
||||
to call that are implemented in libEGL itself.
|
||||
|
||||
- "display"
|
||||
Select a vendor from an EGLDisplay argument.
|
||||
|
||||
- "device"
|
||||
Select a vendor from an EGLDeviceEXT argument.
|
||||
|
||||
- "current"
|
||||
Select the vendor that owns the current context.
|
||||
"""
|
||||
|
||||
|
||||
def _eglFunc(name, method, static=None, public=False, inheader=None, prefix="dispatch_", extension=None, retval=None):
|
||||
"""
|
||||
A convenience function to define an entry in the EGL function list.
|
||||
"""
|
||||
if static is None:
|
||||
static = (not public and method != "custom")
|
||||
if inheader is None:
|
||||
inheader = (not static)
|
||||
values = {
|
||||
"method": method,
|
||||
"prefix": prefix,
|
||||
"extension": extension,
|
||||
"retval": retval,
|
||||
"static": static,
|
||||
"public": public,
|
||||
"inheader": inheader,
|
||||
}
|
||||
return (name, values)
|
||||
|
||||
|
||||
EGL_FUNCTIONS = (
|
||||
# EGL_VERSION_1_0
|
||||
_eglFunc("eglChooseConfig", "none"),
|
||||
_eglFunc("eglCopyBuffers", "none"),
|
||||
_eglFunc("eglCreateContext", "none"),
|
||||
_eglFunc("eglCreatePbufferSurface", "none"),
|
||||
_eglFunc("eglCreatePixmapSurface", "none"),
|
||||
_eglFunc("eglCreateWindowSurface", "none"),
|
||||
_eglFunc("eglDestroyContext", "none"),
|
||||
_eglFunc("eglDestroySurface", "none"),
|
||||
_eglFunc("eglGetConfigAttrib", "none"),
|
||||
_eglFunc("eglGetConfigs", "none"),
|
||||
_eglFunc("eglQueryContext", "none"),
|
||||
_eglFunc("eglQuerySurface", "none"),
|
||||
_eglFunc("eglSwapBuffers", "none"),
|
||||
_eglFunc("eglWaitGL", "none"),
|
||||
_eglFunc("eglWaitNative", "none"),
|
||||
_eglFunc("eglTerminate", "none"),
|
||||
_eglFunc("eglInitialize", "none"),
|
||||
|
||||
_eglFunc("eglGetCurrentDisplay", "none"),
|
||||
_eglFunc("eglGetCurrentSurface", "none"),
|
||||
_eglFunc("eglGetDisplay", "none"),
|
||||
_eglFunc("eglGetError", "none"),
|
||||
_eglFunc("eglGetProcAddress", "none"),
|
||||
_eglFunc("eglMakeCurrent", "none"),
|
||||
_eglFunc("eglQueryString", "none"),
|
||||
|
||||
# EGL_VERSION_1_1
|
||||
_eglFunc("eglBindTexImage", "none"),
|
||||
_eglFunc("eglReleaseTexImage", "none"),
|
||||
_eglFunc("eglSurfaceAttrib", "none"),
|
||||
_eglFunc("eglSwapInterval", "none"),
|
||||
|
||||
# EGL_VERSION_1_2
|
||||
_eglFunc("eglCreatePbufferFromClientBuffer", "none"),
|
||||
_eglFunc("eglWaitClient", "none"),
|
||||
_eglFunc("eglBindAPI", "none"),
|
||||
_eglFunc("eglQueryAPI", "none"),
|
||||
_eglFunc("eglReleaseThread", "none"),
|
||||
|
||||
# EGL_VERSION_1_4
|
||||
_eglFunc("eglGetCurrentContext", "none"),
|
||||
|
||||
# EGL_VERSION_1_5
|
||||
_eglFunc("eglCreateSync", "none"),
|
||||
_eglFunc("eglDestroySync", "none"),
|
||||
_eglFunc("eglClientWaitSync", "none"),
|
||||
_eglFunc("eglGetSyncAttrib", "none"),
|
||||
_eglFunc("eglCreateImage", "none"),
|
||||
_eglFunc("eglDestroyImage", "none"),
|
||||
_eglFunc("eglCreatePlatformWindowSurface", "none"),
|
||||
_eglFunc("eglCreatePlatformPixmapSurface", "none"),
|
||||
_eglFunc("eglWaitSync", "none"),
|
||||
_eglFunc("eglGetPlatformDisplay", "none"),
|
||||
|
||||
# EGL_EXT_platform_base
|
||||
_eglFunc("eglCreatePlatformWindowSurfaceEXT", "display"),
|
||||
_eglFunc("eglCreatePlatformPixmapSurfaceEXT", "display"),
|
||||
_eglFunc("eglGetPlatformDisplayEXT", "none"),
|
||||
|
||||
# TODO: Most of these extensions should be provided by the vendor
|
||||
# libraries, not by libEGL. They're here now to make testing everything
|
||||
# else easier.
|
||||
|
||||
# EGL_EXT_swap_buffers_with_damage
|
||||
_eglFunc("eglSwapBuffersWithDamageEXT", "display"),
|
||||
|
||||
# KHR_EXT_swap_buffers_with_damage
|
||||
_eglFunc("eglSwapBuffersWithDamageKHR", "display"),
|
||||
|
||||
# EGL_KHR_cl_event2
|
||||
_eglFunc("eglCreateSync64KHR", "display"),
|
||||
|
||||
# EGL_KHR_fence_sync
|
||||
_eglFunc("eglCreateSyncKHR", "display"),
|
||||
_eglFunc("eglDestroySyncKHR", "display"),
|
||||
_eglFunc("eglClientWaitSyncKHR", "display"),
|
||||
_eglFunc("eglGetSyncAttribKHR", "display"),
|
||||
|
||||
# EGL_KHR_image
|
||||
_eglFunc("eglCreateImageKHR", "display"),
|
||||
_eglFunc("eglDestroyImageKHR", "display"),
|
||||
|
||||
# EGL_KHR_image_base
|
||||
# eglCreateImageKHR already defined in EGL_KHR_image
|
||||
# eglDestroyImageKHR already defined in EGL_KHR_image
|
||||
|
||||
# EGL_KHR_reusable_sync
|
||||
_eglFunc("eglSignalSyncKHR", "display"),
|
||||
# eglCreateSyncKHR already defined in EGL_KHR_fence_sync
|
||||
# eglDestroySyncKHR already defined in EGL_KHR_fence_sync
|
||||
# eglClientWaitSyncKHR already defined in EGL_KHR_fence_sync
|
||||
# eglGetSyncAttribKHR already defined in EGL_KHR_fence_sync
|
||||
|
||||
# EGL_KHR_wait_sync
|
||||
_eglFunc("eglWaitSyncKHR", "display"),
|
||||
|
||||
# EGL_MESA_image_dma_buf_export
|
||||
_eglFunc("eglExportDMABUFImageQueryMESA", "display"),
|
||||
_eglFunc("eglExportDMABUFImageMESA", "display"),
|
||||
|
||||
# EGL_WL_bind_wayland_display
|
||||
_eglFunc("eglCreateWaylandBufferFromImageWL", "display"),
|
||||
_eglFunc("eglUnbindWaylandDisplayWL", "display"),
|
||||
_eglFunc("eglQueryWaylandBufferWL", "display"),
|
||||
_eglFunc("eglBindWaylandDisplayWL", "display"),
|
||||
|
||||
# EGL_CHROMIUM_get_sync_values
|
||||
_eglFunc("eglGetSyncValuesCHROMIUM", "display"),
|
||||
|
||||
# EGL_ANGLE_sync_control_rate
|
||||
_eglFunc("eglGetMscRateANGLE", "display"),
|
||||
|
||||
# EGL_ANDROID_native_fence_sync
|
||||
_eglFunc("eglDupNativeFenceFDANDROID", "display"),
|
||||
|
||||
# EGL_ANDROID_blob_cache
|
||||
_eglFunc("eglSetBlobCacheFuncsANDROID", "display"),
|
||||
|
||||
# EGL_EXT_image_dma_buf_import_modifiers
|
||||
_eglFunc("eglQueryDmaBufFormatsEXT", "display"),
|
||||
_eglFunc("eglQueryDmaBufModifiersEXT", "display"),
|
||||
|
||||
# EGL_EXT_device_base
|
||||
_eglFunc("eglQueryDeviceAttribEXT", "device"),
|
||||
_eglFunc("eglQueryDeviceStringEXT", "device"),
|
||||
_eglFunc("eglQueryDevicesEXT", "none"),
|
||||
_eglFunc("eglQueryDisplayAttribEXT", "display"),
|
||||
|
||||
# EGL_MESA_query_driver
|
||||
_eglFunc("eglGetDisplayDriverName", "display"),
|
||||
_eglFunc("eglGetDisplayDriverConfig", "display"),
|
||||
|
||||
# EGL_KHR_partial_update
|
||||
_eglFunc("eglSetDamageRegionKHR", "display"),
|
||||
|
||||
# EGL_MESA_gl_interop
|
||||
_eglFunc("eglGLInteropQueryDeviceInfoMESA", "display"),
|
||||
_eglFunc("eglGLInteropExportObjectMESA", "display"),
|
||||
_eglFunc("eglGLInteropFlushObjectsMESA", "display"),
|
||||
|
||||
# EGL_EXT_surface_compression
|
||||
_eglFunc("eglQuerySupportedCompressionRatesEXT", "display"),
|
||||
|
||||
# EGL_EXT_device_persistent_id
|
||||
_eglFunc("eglQueryDeviceBinaryEXT", "device"),
|
||||
)
|
||||
@@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<registry>
|
||||
<!--
|
||||
(C) Copyright 2016, 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
|
||||
on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
license, 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 (including the next
|
||||
paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
IBM AND/OR ITS SUPPLIERS 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.
|
||||
|
||||
Authors:
|
||||
Kyle Brenneman <[email protected]>
|
||||
-->
|
||||
|
||||
<comment>
|
||||
This file contains any EGL extension functions that are missing from
|
||||
the normal egl.xml list.
|
||||
</comment>
|
||||
<types>
|
||||
<type>struct <name>mesa_glinterop_device_info</name>;</type>
|
||||
<type>struct <name>mesa_glinterop_export_in</name>;</type>
|
||||
<type>struct <name>mesa_glinterop_export_out</name>;</type>
|
||||
<type>struct <name>mesa_glinterop_flush_out</name>;</type>
|
||||
</types>
|
||||
<commands namespace="EGL">
|
||||
<!-- EGL_WL_bind_wayland_display -->
|
||||
<command>
|
||||
<proto>struct wl_buffer * <name>eglCreateWaylandBufferFromImageWL</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
|
||||
<param><ptype>EGLImage</ptype> <name>image</name></param>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<proto>EGLBoolean <name>eglUnbindWaylandDisplayWL</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
|
||||
<param><ptype>struct wl_display *</ptype> <name>display</name></param>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<proto>EGLBoolean <name>eglQueryWaylandBufferWL</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
|
||||
<param><ptype>struct wl_resource *</ptype> <name>buffer</name></param>
|
||||
<param><ptype>EGLint</ptype> <name>attribute</name></param>
|
||||
<param><ptype>EGLint *</ptype> <name>value</name></param>
|
||||
</command>
|
||||
|
||||
<command>
|
||||
<proto>EGLBoolean <name>eglBindWaylandDisplayWL</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
|
||||
<param><ptype>struct wl_display *</ptype> <name>display</name></param>
|
||||
</command>
|
||||
|
||||
<!-- EGL_CHROMIUM_get_sync_values -->
|
||||
<command>
|
||||
<proto>EGLBoolean <name>eglGetSyncValuesCHROMIUM</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>display</name></param>
|
||||
<param><ptype>EGLSurface</ptype> <name>surface</name></param>
|
||||
<param><ptype>EGLuint64KHR *</ptype> <name>ust</name></param>
|
||||
<param><ptype>EGLuint64KHR *</ptype> <name>msc</name></param>
|
||||
<param><ptype>EGLuint64KHR *</ptype> <name>sbc</name></param>
|
||||
</command>
|
||||
|
||||
<!-- EGL_ANGLE_sync_control_rate -->
|
||||
<command>
|
||||
<proto>EGLBoolean <name>eglGetMscRateANGLE</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>display</name></param>
|
||||
<param><ptype>EGLSurface</ptype> <name>surface</name></param>
|
||||
<param><ptype>EGLint *</ptype> <name>numerator</name></param>
|
||||
<param><ptype>EGLint *</ptype> <name>denominator</name></param>
|
||||
</command>
|
||||
|
||||
<!-- EGL_MESA_gl_interop -->
|
||||
<command>
|
||||
<proto><ptype>EGLint</ptype> <name>eglGLInteropQueryDeviceInfoMESA</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
|
||||
<param><ptype>EGLContext</ptype> <name>ctx</name></param>
|
||||
<param>struct <ptype>mesa_glinterop_device_info</ptype> *<name>out</name></param>
|
||||
</command>
|
||||
<command>
|
||||
<proto><ptype>EGLint</ptype> <name>eglGLInteropExportObjectMESA</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
|
||||
<param><ptype>EGLContext</ptype> <name>ctx</name></param>
|
||||
<param>struct <ptype>mesa_glinterop_export_in</ptype> *<name>in</name></param>
|
||||
<param>struct <ptype>mesa_glinterop_export_out</ptype> *<name>out</name></param>
|
||||
</command>
|
||||
<command>
|
||||
<proto><ptype>EGLint</ptype> <name>eglGLInteropFlushObjectsMESA</name></proto>
|
||||
<param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
|
||||
<param><ptype>EGLContext</ptype> <name>ctx</name></param>
|
||||
<param>unsigned <name>count</name></param>
|
||||
<param>struct <ptype>mesa_glinterop_export_in</ptype> *<name>objects</name></param>
|
||||
<param>struct <ptype>mesa_glinterop_flush_out</ptype> *<name>out</name></param>
|
||||
</command>
|
||||
</commands>
|
||||
</registry>
|
||||
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# (C) Copyright 2016, 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
|
||||
# on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
# license, 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 (including the next
|
||||
# paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
# IBM AND/OR ITS SUPPLIERS 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.
|
||||
#
|
||||
# Authors:
|
||||
# Kyle Brenneman <[email protected]>
|
||||
|
||||
"""
|
||||
Generates dispatch functions for EGL.
|
||||
|
||||
The list of functions and arguments is read from the Khronos's XML files, with
|
||||
additional information defined in the module eglFunctionList.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import collections
|
||||
import eglFunctionList
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
import os
|
||||
NEWAPI = os.path.join(os.path.dirname(__file__), "..", "..", "mesa", "glapi", "new")
|
||||
sys.path.insert(0, NEWAPI)
|
||||
import genCommon
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--bind-wl-display", action="store_true",
|
||||
help="Include EGL_WL_bind_wayland_display")
|
||||
parser.add_argument("target", choices=("header", "source"),
|
||||
help="Whether to build the source or header file.")
|
||||
parser.add_argument("xml_files", nargs="+",
|
||||
help="The XML files with the EGL function lists.")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
xmlFunctions = genCommon.getFunctions(args.xml_files)
|
||||
xmlByName = dict((f.name, f) for f in xmlFunctions)
|
||||
functions = []
|
||||
for (name, eglFunc) in eglFunctionList.EGL_FUNCTIONS:
|
||||
if not args.bind_wl_display and "Wayland" in name:
|
||||
continue
|
||||
func = xmlByName[name]
|
||||
eglFunc = fixupEglFunc(func, eglFunc)
|
||||
functions.append((func, eglFunc))
|
||||
|
||||
# Sort the function list by name.
|
||||
functions = sorted(functions, key=lambda f: f[0].name)
|
||||
|
||||
if args.target == "header":
|
||||
text = generateHeader(functions)
|
||||
elif args.target == "source":
|
||||
text = generateSource(functions)
|
||||
sys.stdout.write(text)
|
||||
|
||||
|
||||
def fixupEglFunc(func, eglFunc):
|
||||
result = dict(eglFunc)
|
||||
if result.get("prefix") is None:
|
||||
result["prefix"] = ""
|
||||
|
||||
if result.get("extension") is not None:
|
||||
text = "defined(" + result["extension"] + ")"
|
||||
result["extension"] = text
|
||||
|
||||
if result["method"] in ("none", "custom"):
|
||||
return result
|
||||
|
||||
if result["method"] not in ("display", "device", "current"):
|
||||
raise ValueError("Invalid dispatch method %r for function %r" %
|
||||
(result["method"], func.name))
|
||||
|
||||
if func.hasReturn():
|
||||
if result.get("retval") is None:
|
||||
result["retval"] = getDefaultReturnValue(func.rt)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def generateHeader(functions):
|
||||
text = textwrap.dedent(r"""
|
||||
#ifndef G_EGLDISPATCH_STUBS_H
|
||||
#define G_EGLDISPATCH_STUBS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/eglmesaext.h>
|
||||
#include <EGL/eglext_angle.h>
|
||||
#include <GL/mesa_glinterop.h>
|
||||
#include "glvnd/libeglabi.h"
|
||||
|
||||
""".lstrip("\n"))
|
||||
|
||||
text += "enum {\n"
|
||||
for (func, eglFunc) in functions:
|
||||
text += generateGuardBegin(func, eglFunc)
|
||||
text += " __EGL_DISPATCH_" + func.name + ",\n"
|
||||
text += generateGuardEnd(func, eglFunc)
|
||||
text += " __EGL_DISPATCH_COUNT\n"
|
||||
text += "};\n"
|
||||
|
||||
for (func, eglFunc) in functions:
|
||||
if eglFunc["inheader"]:
|
||||
text += generateGuardBegin(func, eglFunc)
|
||||
text += "{f.rt} EGLAPIENTRY {ex[prefix]}{f.name}({f.decArgs});\n".format(
|
||||
f=func, ex=eglFunc)
|
||||
text += generateGuardEnd(func, eglFunc)
|
||||
|
||||
text += textwrap.dedent(r"""
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // G_EGLDISPATCH_STUBS_H
|
||||
""")
|
||||
return text
|
||||
|
||||
|
||||
def generateSource(functions):
|
||||
# First, sort the function list by name.
|
||||
text = ""
|
||||
text += '#include "egldispatchstubs.h"\n'
|
||||
text += '#include "g_egldispatchstubs.h"\n'
|
||||
text += '#include <stddef.h>\n'
|
||||
text += "\n"
|
||||
|
||||
for (func, eglFunc) in functions:
|
||||
if eglFunc["method"] not in ("custom", "none"):
|
||||
text += generateGuardBegin(func, eglFunc)
|
||||
text += generateDispatchFunc(func, eglFunc)
|
||||
text += generateGuardEnd(func, eglFunc)
|
||||
|
||||
text += "\n"
|
||||
text += "const char * const __EGL_DISPATCH_FUNC_NAMES[__EGL_DISPATCH_COUNT + 1] = {\n"
|
||||
for (func, eglFunc) in functions:
|
||||
text += generateGuardBegin(func, eglFunc)
|
||||
text += ' "' + func.name + '",\n'
|
||||
text += generateGuardEnd(func, eglFunc)
|
||||
text += " NULL\n"
|
||||
text += "};\n"
|
||||
|
||||
text += "const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[__EGL_DISPATCH_COUNT + 1] = {\n"
|
||||
for (func, eglFunc) in functions:
|
||||
text += generateGuardBegin(func, eglFunc)
|
||||
if eglFunc["method"] != "none":
|
||||
text += " (__eglMustCastToProperFunctionPointerType) " + \
|
||||
eglFunc.get("prefix", "") + func.name + ",\n"
|
||||
else:
|
||||
text += " NULL, // " + func.name + "\n"
|
||||
text += generateGuardEnd(func, eglFunc)
|
||||
text += " NULL\n"
|
||||
text += "};\n"
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def generateGuardBegin(func, eglFunc):
|
||||
ext = eglFunc.get("extension")
|
||||
if ext is not None:
|
||||
return "#if " + ext + "\n"
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
def generateGuardEnd(func, eglFunc):
|
||||
if eglFunc.get("extension") is not None:
|
||||
return "#endif\n"
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
def generateDispatchFunc(func, eglFunc):
|
||||
text = ""
|
||||
|
||||
if eglFunc.get("static"):
|
||||
text += "static "
|
||||
elif eglFunc.get("public"):
|
||||
text += "PUBLIC "
|
||||
text += textwrap.dedent(
|
||||
r"""
|
||||
{f.rt} EGLAPIENTRY {ef[prefix]}{f.name}({f.decArgs})
|
||||
{{
|
||||
typedef {f.rt} EGLAPIENTRY (* _pfn_{f.name})({f.decArgs});
|
||||
""").lstrip("\n").format(f=func, ef=eglFunc)
|
||||
|
||||
if func.hasReturn():
|
||||
text += " {f.rt} _ret = {ef[retval]};\n".format(f=func, ef=eglFunc)
|
||||
|
||||
text += " _pfn_{f.name} _ptr_{f.name} = (_pfn_{f.name}) ".format(f=func)
|
||||
if eglFunc["method"] == "current":
|
||||
text += "__eglDispatchFetchByCurrent(__EGL_DISPATCH_{f.name});\n".format(
|
||||
f=func)
|
||||
|
||||
elif eglFunc["method"] in ("display", "device"):
|
||||
if eglFunc["method"] == "display":
|
||||
lookupFunc = "__eglDispatchFetchByDisplay"
|
||||
lookupType = "EGLDisplay"
|
||||
else:
|
||||
assert eglFunc["method"] == "device"
|
||||
lookupFunc = "__eglDispatchFetchByDevice"
|
||||
lookupType = "EGLDeviceEXT"
|
||||
|
||||
lookupArg = None
|
||||
for arg in func.args:
|
||||
if arg.type == lookupType:
|
||||
lookupArg = arg.name
|
||||
break
|
||||
if lookupArg is None:
|
||||
raise ValueError("Can't find %s argument for function %s" %
|
||||
(lookupType, func.name,))
|
||||
|
||||
text += "{lookupFunc}({lookupArg}, __EGL_DISPATCH_{f.name});\n".format(
|
||||
f=func, lookupFunc=lookupFunc, lookupArg=lookupArg)
|
||||
else:
|
||||
raise ValueError("Unknown dispatch method: %r" % (eglFunc["method"],))
|
||||
|
||||
text += " if(_ptr_{f.name} != NULL) {{\n".format(f=func)
|
||||
text += " "
|
||||
if func.hasReturn():
|
||||
text += "_ret = "
|
||||
text += "_ptr_{f.name}({f.callArgs});\n".format(f=func)
|
||||
text += " }\n"
|
||||
|
||||
if func.hasReturn():
|
||||
text += " return _ret;\n"
|
||||
text += "}\n"
|
||||
return text
|
||||
|
||||
|
||||
def getDefaultReturnValue(typename):
|
||||
if typename.endswith("*"):
|
||||
return "NULL"
|
||||
elif typename == "EGLDisplay":
|
||||
return "EGL_NO_DISPLAY"
|
||||
elif typename == "EGLContext":
|
||||
return "EGL_NO_CONTEXT"
|
||||
elif typename == "EGLSurface":
|
||||
return "EGL_NO_SURFACE"
|
||||
elif typename == "EGLBoolean":
|
||||
return "EGL_FALSE"
|
||||
|
||||
return "0"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"file_format_version" : "1.0.0",
|
||||
"ICD" : {
|
||||
"library_path" : "@library_path@"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
; stdcall calling convention have @number suffix on 32 bits architecture for gcc
|
||||
eglBindAPI@4
|
||||
eglBindTexImage@12
|
||||
eglChooseConfig@20
|
||||
eglClientWaitSync@20
|
||||
eglCopyBuffers@12
|
||||
eglCreateContext@16
|
||||
eglCreateImage@20
|
||||
eglCreatePbufferFromClientBuffer@20
|
||||
eglCreatePbufferSurface@12
|
||||
eglCreatePixmapSurface@16
|
||||
eglCreatePlatformPixmapSurface@16
|
||||
eglCreatePlatformWindowSurface@16
|
||||
eglCreateSync@12
|
||||
eglCreateWindowSurface@16
|
||||
eglDestroyContext@8
|
||||
eglDestroyImage@8
|
||||
eglDestroySurface@8
|
||||
eglDestroySync@8
|
||||
eglGetConfigAttrib@16
|
||||
eglGetConfigs@16
|
||||
eglGetCurrentContext@0
|
||||
eglGetCurrentDisplay@0
|
||||
eglGetCurrentSurface@4
|
||||
eglGetDisplay@4
|
||||
eglGetError@0
|
||||
eglGetPlatformDisplay@12
|
||||
eglGetProcAddress@4
|
||||
eglGetSyncAttrib@16
|
||||
eglInitialize@12
|
||||
eglMakeCurrent@16
|
||||
eglQueryAPI@0
|
||||
eglQueryContext@16
|
||||
eglQueryString@8
|
||||
eglQuerySurface@16
|
||||
eglReleaseTexImage@12
|
||||
eglReleaseThread@0
|
||||
eglSurfaceAttrib@16
|
||||
eglSwapBuffers@8
|
||||
eglSwapInterval@8
|
||||
eglTerminate@4
|
||||
eglWaitClient@0
|
||||
eglWaitGL@0
|
||||
eglWaitNative@4
|
||||
eglWaitSync@12
|
||||
|
||||
; __cdecl calling convention have no @number suffix
|
||||
MesaGLInteropEGLQueryDeviceInfo
|
||||
MesaGLInteropEGLExportObject
|
||||
MesaGLInteropEGLFlushObjects
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,193 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eglarray.h"
|
||||
#include "egllog.h"
|
||||
|
||||
/**
|
||||
* Grow the size of the array.
|
||||
*/
|
||||
static EGLBoolean
|
||||
_eglGrowArray(_EGLArray *array)
|
||||
{
|
||||
EGLint new_size;
|
||||
void **elems;
|
||||
|
||||
new_size = array->MaxSize;
|
||||
while (new_size <= array->Size)
|
||||
new_size *= 2;
|
||||
|
||||
elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
|
||||
if (!elems) {
|
||||
_eglLog(_EGL_DEBUG, "failed to grow %s array to %d", array->Name,
|
||||
new_size);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
array->Elements = elems;
|
||||
array->MaxSize = new_size;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array.
|
||||
*/
|
||||
_EGLArray *
|
||||
_eglCreateArray(const char *name, EGLint init_size)
|
||||
{
|
||||
_EGLArray *array;
|
||||
|
||||
array = calloc(1, sizeof(*array));
|
||||
if (array) {
|
||||
array->Name = name;
|
||||
array->MaxSize = (init_size > 0) ? init_size : 1;
|
||||
if (!_eglGrowArray(array)) {
|
||||
free(array);
|
||||
array = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an array, optionally free the data.
|
||||
*/
|
||||
void
|
||||
_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
|
||||
{
|
||||
if (free_cb) {
|
||||
EGLint i;
|
||||
for (i = 0; i < array->Size; i++)
|
||||
free_cb(array->Elements[i]);
|
||||
}
|
||||
free(array->Elements);
|
||||
free(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a element to an array.
|
||||
*/
|
||||
void
|
||||
_eglAppendArray(_EGLArray *array, void *elem)
|
||||
{
|
||||
if (array->Size >= array->MaxSize && !_eglGrowArray(array))
|
||||
return;
|
||||
|
||||
array->Elements[array->Size++] = elem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase an element from an array.
|
||||
*/
|
||||
void
|
||||
_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
|
||||
{
|
||||
if (free_cb)
|
||||
free_cb(array->Elements[i]);
|
||||
if (i < array->Size - 1) {
|
||||
memmove(&array->Elements[i], &array->Elements[i + 1],
|
||||
(array->Size - i - 1) * sizeof(array->Elements[0]));
|
||||
}
|
||||
array->Size--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find in an array for the given element.
|
||||
*/
|
||||
void *
|
||||
_eglFindArray(_EGLArray *array, void *elem)
|
||||
{
|
||||
EGLint i;
|
||||
|
||||
if (!array)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < array->Size; i++)
|
||||
if (array->Elements[i] == elem)
|
||||
return elem;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter an array and return the number of filtered elements.
|
||||
*/
|
||||
EGLint
|
||||
_eglFilterArray(_EGLArray *array, void **data, EGLint size,
|
||||
_EGLArrayForEach filter, void *filter_data)
|
||||
{
|
||||
EGLint count = 0, i;
|
||||
|
||||
if (!array)
|
||||
return 0;
|
||||
|
||||
assert(filter);
|
||||
for (i = 0; i < array->Size; i++) {
|
||||
if (filter(array->Elements[i], filter_data)) {
|
||||
if (data && count < size)
|
||||
data[count] = array->Elements[i];
|
||||
count++;
|
||||
}
|
||||
if (data && count >= size)
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array by converting array elements into another form and store
|
||||
* them in a buffer.
|
||||
*/
|
||||
EGLint
|
||||
_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
|
||||
_EGLArrayForEach flatten)
|
||||
{
|
||||
EGLint i, count;
|
||||
|
||||
if (!array)
|
||||
return 0;
|
||||
|
||||
count = array->Size;
|
||||
if (buffer) {
|
||||
/* clamp size to 0 */
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
/* do not exceed buffer size */
|
||||
if (count > size)
|
||||
count = size;
|
||||
for (i = 0; i < count; i++)
|
||||
flatten(array->Elements[i], (void *)((char *)buffer + elem_size * i));
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLARRAY_INCLUDED
|
||||
#define EGLARRAY_INCLUDED
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef EGLBoolean (*_EGLArrayForEach)(void *elem, void *foreach_data);
|
||||
|
||||
struct _egl_array {
|
||||
const char *Name;
|
||||
EGLint MaxSize;
|
||||
|
||||
void **Elements;
|
||||
EGLint Size;
|
||||
};
|
||||
|
||||
extern _EGLArray *
|
||||
_eglCreateArray(const char *name, EGLint init_size);
|
||||
|
||||
extern void
|
||||
_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *));
|
||||
|
||||
extern void
|
||||
_eglAppendArray(_EGLArray *array, void *elem);
|
||||
|
||||
extern void
|
||||
_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *));
|
||||
|
||||
void *
|
||||
_eglFindArray(_EGLArray *array, void *elem);
|
||||
|
||||
extern EGLint
|
||||
_eglFilterArray(_EGLArray *array, void **data, EGLint size,
|
||||
_EGLArrayForEach filter, void *filter_data);
|
||||
|
||||
EGLint
|
||||
_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
|
||||
_EGLArrayForEach flatten);
|
||||
|
||||
static inline EGLint
|
||||
_eglGetArraySize(_EGLArray *array)
|
||||
{
|
||||
return (array) ? array->Size : 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLARRAY_INCLUDED */
|
||||
@@ -0,0 +1,835 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* EGL Configuration (pixel format) functions.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util/macros.h"
|
||||
|
||||
#include "eglconfig.h"
|
||||
#include "eglconfigdebug.h"
|
||||
#include "eglcurrent.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egllog.h"
|
||||
|
||||
/**
|
||||
* Init the given _EGLconfig to default values.
|
||||
* \param id the configuration's ID.
|
||||
*
|
||||
* Note that id must be positive for the config to be valid.
|
||||
* It is also recommended that when there are N configs, their
|
||||
* IDs are from 1 to N respectively.
|
||||
*/
|
||||
void
|
||||
_eglInitConfig(_EGLConfig *conf, _EGLDisplay *disp, EGLint id)
|
||||
{
|
||||
memset(conf, 0, sizeof(*conf));
|
||||
|
||||
conf->Display = disp;
|
||||
|
||||
/* some attributes take non-zero default values */
|
||||
conf->ConfigID = id;
|
||||
conf->ConfigCaveat = EGL_NONE;
|
||||
conf->TransparentType = EGL_NONE;
|
||||
conf->NativeVisualType = EGL_NONE;
|
||||
conf->ColorBufferType = EGL_RGB_BUFFER;
|
||||
conf->ComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a config to its display and return the handle of the link.
|
||||
* The handle can be passed to client directly.
|
||||
*
|
||||
* Note that we just save the ptr to the config (we don't copy the config).
|
||||
*/
|
||||
EGLConfig
|
||||
_eglLinkConfig(_EGLConfig *conf)
|
||||
{
|
||||
_EGLDisplay *disp = conf->Display;
|
||||
|
||||
/* sanity check */
|
||||
assert(disp);
|
||||
assert(conf->ConfigID > 0);
|
||||
|
||||
if (!disp->Configs) {
|
||||
disp->Configs = _eglCreateArray("Config", 16);
|
||||
if (!disp->Configs)
|
||||
return (EGLConfig)NULL;
|
||||
}
|
||||
|
||||
_eglAppendArray(disp->Configs, (void *)conf);
|
||||
|
||||
return (EGLConfig)conf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a handle to find the linked config.
|
||||
* Return NULL if the handle has no corresponding linked config.
|
||||
*/
|
||||
_EGLConfig *
|
||||
_eglLookupConfig(EGLConfig config, _EGLDisplay *disp)
|
||||
{
|
||||
_EGLConfig *conf;
|
||||
|
||||
if (!disp)
|
||||
return NULL;
|
||||
|
||||
conf = (_EGLConfig *)_eglFindArray(disp->Configs, (void *)config);
|
||||
if (conf)
|
||||
assert(conf->Display == disp);
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
enum type {
|
||||
ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_TYPE_BOOLEAN,
|
||||
ATTRIB_TYPE_BITMASK,
|
||||
ATTRIB_TYPE_ENUM,
|
||||
ATTRIB_TYPE_PSEUDO, /* non-queryable */
|
||||
ATTRIB_TYPE_PLATFORM, /* platform-dependent */
|
||||
};
|
||||
|
||||
enum criterion {
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
ATTRIB_CRITERION_MASK,
|
||||
ATTRIB_CRITERION_SPECIAL,
|
||||
ATTRIB_CRITERION_IGNORE
|
||||
};
|
||||
|
||||
/* EGL spec Table 3.1 and 3.4 */
|
||||
static const struct {
|
||||
EGLint attr;
|
||||
enum type type;
|
||||
enum criterion criterion;
|
||||
EGLint default_value;
|
||||
} _eglValidationTable[] = {
|
||||
/* clang-format off */
|
||||
/* core */
|
||||
{ EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_RED_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_RGB_BUFFER },
|
||||
{ EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_CONFORMANT, ATTRIB_TYPE_BITMASK,
|
||||
ATTRIB_CRITERION_MASK,
|
||||
0 },
|
||||
{ EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_LEVEL, ATTRIB_TYPE_PLATFORM,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
0 },
|
||||
{ EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_IGNORE,
|
||||
0 },
|
||||
{ EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_IGNORE,
|
||||
0 },
|
||||
{ EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_IGNORE,
|
||||
0 },
|
||||
{ EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM,
|
||||
ATTRIB_CRITERION_IGNORE,
|
||||
0 },
|
||||
{ EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK,
|
||||
ATTRIB_CRITERION_MASK,
|
||||
EGL_OPENGL_ES_BIT },
|
||||
{ EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_SAMPLES, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_ATLEAST,
|
||||
0 },
|
||||
{ EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK,
|
||||
ATTRIB_CRITERION_MASK,
|
||||
EGL_WINDOW_BIT },
|
||||
{ EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_NONE },
|
||||
{ EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO,
|
||||
ATTRIB_CRITERION_SPECIAL,
|
||||
EGL_NONE },
|
||||
/* extensions */
|
||||
{ EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_FRAMEBUFFER_TARGET_ANDROID, ATTRIB_TYPE_BOOLEAN,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_RECORDABLE_ANDROID, ATTRIB_TYPE_BOOLEAN,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_DONT_CARE },
|
||||
{ EGL_COLOR_COMPONENT_TYPE_EXT, ATTRIB_TYPE_ENUM,
|
||||
ATTRIB_CRITERION_EXACT,
|
||||
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT },
|
||||
{ EGL_CONFIG_SELECT_GROUP_EXT, ATTRIB_TYPE_INTEGER,
|
||||
ATTRIB_CRITERION_IGNORE,
|
||||
0 },
|
||||
/* clang-format on */
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if a config is valid. When for_matching is true,
|
||||
* EGL_DONT_CARE is accepted as a valid attribute value, and checks
|
||||
* for conflicting attribute values are skipped.
|
||||
*
|
||||
* Note that some attributes are platform-dependent and are not
|
||||
* checked.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
|
||||
{
|
||||
_EGLDisplay *disp = conf->Display;
|
||||
EGLint i, attr, val;
|
||||
EGLBoolean valid = EGL_TRUE;
|
||||
|
||||
/* check attributes by their types */
|
||||
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
|
||||
EGLint mask;
|
||||
|
||||
attr = _eglValidationTable[i].attr;
|
||||
val = _eglGetConfigKey(conf, attr);
|
||||
|
||||
switch (_eglValidationTable[i].type) {
|
||||
case ATTRIB_TYPE_INTEGER:
|
||||
switch (attr) {
|
||||
case EGL_CONFIG_ID:
|
||||
/* config id must be positive */
|
||||
if (val <= 0)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case EGL_SAMPLE_BUFFERS:
|
||||
/* there can be at most 1 sample buffer */
|
||||
if (val > 1 || val < 0)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case EGL_CONFIG_SELECT_GROUP_EXT:
|
||||
break;
|
||||
default:
|
||||
if (val < 0)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ATTRIB_TYPE_BOOLEAN:
|
||||
if (val != EGL_TRUE && val != EGL_FALSE)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case ATTRIB_TYPE_ENUM:
|
||||
switch (attr) {
|
||||
case EGL_CONFIG_CAVEAT:
|
||||
if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
|
||||
val != EGL_NON_CONFORMANT_CONFIG)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case EGL_TRANSPARENT_TYPE:
|
||||
if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case EGL_COLOR_BUFFER_TYPE:
|
||||
if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case EGL_COLOR_COMPONENT_TYPE_EXT:
|
||||
if (val != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT &&
|
||||
val != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("check _eglValidationTable[]");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ATTRIB_TYPE_BITMASK:
|
||||
switch (attr) {
|
||||
case EGL_SURFACE_TYPE:
|
||||
mask = EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT |
|
||||
EGL_VG_COLORSPACE_LINEAR_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT |
|
||||
EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
|
||||
EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
|
||||
if (disp->Extensions.KHR_mutable_render_buffer)
|
||||
mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
|
||||
break;
|
||||
case EGL_RENDERABLE_TYPE:
|
||||
case EGL_CONFORMANT:
|
||||
mask = EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT |
|
||||
EGL_OPENGL_ES3_BIT_KHR | EGL_OPENGL_BIT;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("check _eglValidationTable[]");
|
||||
mask = 0;
|
||||
break;
|
||||
}
|
||||
if (val & ~mask)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case ATTRIB_TYPE_PLATFORM:
|
||||
/* unable to check platform-dependent attributes here */
|
||||
break;
|
||||
case ATTRIB_TYPE_PSEUDO:
|
||||
/* pseudo attributes should not be set */
|
||||
if (val != 0)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!valid && for_matching) {
|
||||
/* accept EGL_DONT_CARE as a valid value */
|
||||
if (val == EGL_DONT_CARE)
|
||||
valid = EGL_TRUE;
|
||||
if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
|
||||
valid = EGL_TRUE;
|
||||
}
|
||||
if (!valid) {
|
||||
_eglLog(_EGL_DEBUG, "attribute 0x%04x has an invalid value 0x%x", attr,
|
||||
val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* any invalid attribute value should have been caught */
|
||||
if (!valid || for_matching)
|
||||
return valid;
|
||||
|
||||
/* now check for conflicting attribute values */
|
||||
|
||||
switch (conf->ColorBufferType) {
|
||||
case EGL_RGB_BUFFER:
|
||||
if (conf->LuminanceSize)
|
||||
valid = EGL_FALSE;
|
||||
if (conf->RedSize + conf->GreenSize + conf->BlueSize + conf->AlphaSize !=
|
||||
conf->BufferSize)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
case EGL_LUMINANCE_BUFFER:
|
||||
if (conf->RedSize || conf->GreenSize || conf->BlueSize)
|
||||
valid = EGL_FALSE;
|
||||
if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize)
|
||||
valid = EGL_FALSE;
|
||||
break;
|
||||
}
|
||||
if (!valid) {
|
||||
_eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!conf->SampleBuffers && conf->Samples)
|
||||
valid = EGL_FALSE;
|
||||
if (!valid) {
|
||||
_eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
|
||||
if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE)
|
||||
valid = EGL_FALSE;
|
||||
}
|
||||
if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) {
|
||||
if (conf->BindToTextureRGB || conf->BindToTextureRGBA)
|
||||
valid = EGL_FALSE;
|
||||
}
|
||||
if (!valid) {
|
||||
_eglLog(_EGL_DEBUG,
|
||||
"conflicting surface type and native visual/texture binding");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a config matches the criteria. This and
|
||||
* _eglParseConfigAttribList together implement the algorithm
|
||||
* described in "Selection of EGLConfigs".
|
||||
*
|
||||
* Note that attributes that are special (currently, only
|
||||
* EGL_MATCH_NATIVE_PIXMAP) are ignored.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
|
||||
{
|
||||
EGLint attr, val, i;
|
||||
EGLBoolean matched = EGL_TRUE;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
|
||||
EGLint cmp;
|
||||
if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
|
||||
continue;
|
||||
|
||||
attr = _eglValidationTable[i].attr;
|
||||
cmp = _eglGetConfigKey(criteria, attr);
|
||||
if (cmp == EGL_DONT_CARE)
|
||||
continue;
|
||||
|
||||
val = _eglGetConfigKey(conf, attr);
|
||||
switch (_eglValidationTable[i].criterion) {
|
||||
case ATTRIB_CRITERION_EXACT:
|
||||
if (val != cmp)
|
||||
matched = EGL_FALSE;
|
||||
break;
|
||||
case ATTRIB_CRITERION_ATLEAST:
|
||||
if (val < cmp)
|
||||
matched = EGL_FALSE;
|
||||
break;
|
||||
case ATTRIB_CRITERION_MASK:
|
||||
if ((val & cmp) != cmp)
|
||||
matched = EGL_FALSE;
|
||||
break;
|
||||
case ATTRIB_CRITERION_SPECIAL:
|
||||
/* ignored here */
|
||||
break;
|
||||
case ATTRIB_CRITERION_IGNORE:
|
||||
UNREACHABLE("already handled above");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
#if !MESA_DEBUG
|
||||
/* only print the common errors when MESA_DEBUG is defined to 0 */
|
||||
if (attr != EGL_RENDERABLE_TYPE)
|
||||
break;
|
||||
#endif
|
||||
_eglLog(_EGL_DEBUG,
|
||||
"the value (0x%x) of attribute 0x%04x did not meet the "
|
||||
"criteria (0x%x)",
|
||||
val, attr, cmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
static inline EGLBoolean
|
||||
_eglIsConfigAttribValid(const _EGLConfig *conf, EGLint attr)
|
||||
{
|
||||
if (_eglOffsetOfConfig(attr) < 0)
|
||||
return EGL_FALSE;
|
||||
|
||||
switch (attr) {
|
||||
case EGL_Y_INVERTED_NOK:
|
||||
return conf->Display->Extensions.NOK_texture_from_pixmap;
|
||||
case EGL_FRAMEBUFFER_TARGET_ANDROID:
|
||||
return conf->Display->Extensions.ANDROID_framebuffer_target;
|
||||
case EGL_RECORDABLE_ANDROID:
|
||||
return conf->Display->Extensions.ANDROID_recordable;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a criteria config from the given attribute list.
|
||||
* Return EGL_FALSE if any of the attribute is invalid.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *disp,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
EGLint attr, val, i;
|
||||
|
||||
_eglInitConfig(conf, disp, EGL_DONT_CARE);
|
||||
|
||||
/* reset to default values */
|
||||
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
|
||||
attr = _eglValidationTable[i].attr;
|
||||
val = _eglValidationTable[i].default_value;
|
||||
_eglSetConfigKey(conf, attr, val);
|
||||
}
|
||||
|
||||
/* parse the list */
|
||||
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
|
||||
attr = attrib_list[i];
|
||||
val = attrib_list[i + 1];
|
||||
|
||||
if (!_eglIsConfigAttribValid(conf, attr))
|
||||
return EGL_FALSE;
|
||||
|
||||
_eglSetConfigKey(conf, attr, val);
|
||||
}
|
||||
|
||||
if (!_eglValidateConfig(conf, EGL_TRUE))
|
||||
return EGL_FALSE;
|
||||
|
||||
/* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */
|
||||
if (conf->Level == EGL_DONT_CARE || conf->MatchNativePixmap == EGL_DONT_CARE)
|
||||
return EGL_FALSE;
|
||||
|
||||
/* ignore other attributes when EGL_CONFIG_ID is given */
|
||||
if (conf->ConfigID != EGL_DONT_CARE) {
|
||||
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
|
||||
attr = _eglValidationTable[i].attr;
|
||||
if (attr != EGL_CONFIG_ID)
|
||||
_eglSetConfigKey(conf, attr, EGL_DONT_CARE);
|
||||
}
|
||||
} else {
|
||||
if (!(conf->SurfaceType & EGL_WINDOW_BIT))
|
||||
conf->NativeVisualType = EGL_DONT_CARE;
|
||||
|
||||
if (conf->TransparentType == EGL_NONE) {
|
||||
conf->TransparentRedValue = EGL_DONT_CARE;
|
||||
conf->TransparentGreenValue = EGL_DONT_CARE;
|
||||
conf->TransparentBlueValue = EGL_DONT_CARE;
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide the ordering of conf1 and conf2, under the given criteria.
|
||||
* When compare_id is true, this implements the algorithm described
|
||||
* in "Sorting of EGLConfigs". When compare_id is false,
|
||||
* EGL_CONFIG_ID is not compared.
|
||||
*
|
||||
* It returns a negative integer if conf1 is considered to come
|
||||
* before conf2; a positive integer if conf2 is considered to come
|
||||
* before conf1; zero if the ordering cannot be decided.
|
||||
*
|
||||
* Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
|
||||
* ignored here.
|
||||
*/
|
||||
EGLint
|
||||
_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
|
||||
const _EGLConfig *criteria, EGLBoolean compare_id)
|
||||
{
|
||||
const EGLint compare_attribs[] = {
|
||||
EGL_BUFFER_SIZE, EGL_SAMPLE_BUFFERS, EGL_SAMPLES,
|
||||
EGL_DEPTH_SIZE, EGL_STENCIL_SIZE, EGL_ALPHA_MASK_SIZE,
|
||||
};
|
||||
EGLint val1, val2;
|
||||
EGLint i;
|
||||
|
||||
if (conf1 == conf2)
|
||||
return 0;
|
||||
|
||||
val1 = conf1->ConfigSelectGroup - conf2->ConfigSelectGroup;
|
||||
if (val1)
|
||||
return val1;
|
||||
|
||||
/* the enum values have the desired ordering */
|
||||
STATIC_ASSERT(EGL_NONE < EGL_SLOW_CONFIG);
|
||||
STATIC_ASSERT(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
|
||||
val1 = conf1->ConfigCaveat - conf2->ConfigCaveat;
|
||||
if (val1)
|
||||
return val1;
|
||||
|
||||
/* the enum values have the desired ordering */
|
||||
STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
|
||||
val1 = conf1->ColorBufferType - conf2->ColorBufferType;
|
||||
if (val1)
|
||||
return val1;
|
||||
|
||||
if (criteria) {
|
||||
val1 = val2 = 0;
|
||||
if (conf1->ColorBufferType == EGL_RGB_BUFFER) {
|
||||
if (criteria->RedSize > 0) {
|
||||
val1 += conf1->RedSize;
|
||||
val2 += conf2->RedSize;
|
||||
}
|
||||
if (criteria->GreenSize > 0) {
|
||||
val1 += conf1->GreenSize;
|
||||
val2 += conf2->GreenSize;
|
||||
}
|
||||
if (criteria->BlueSize > 0) {
|
||||
val1 += conf1->BlueSize;
|
||||
val2 += conf2->BlueSize;
|
||||
}
|
||||
} else {
|
||||
if (criteria->LuminanceSize > 0) {
|
||||
val1 += conf1->LuminanceSize;
|
||||
val2 += conf2->LuminanceSize;
|
||||
}
|
||||
}
|
||||
if (criteria->AlphaSize > 0) {
|
||||
val1 += conf1->AlphaSize;
|
||||
val2 += conf2->AlphaSize;
|
||||
}
|
||||
} else {
|
||||
/* assume the default criteria, which gives no specific ordering */
|
||||
val1 = val2 = 0;
|
||||
}
|
||||
|
||||
/* for color bits, larger one is preferred */
|
||||
if (val1 != val2)
|
||||
return (val2 - val1);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
|
||||
val1 = _eglGetConfigKey(conf1, compare_attribs[i]);
|
||||
val2 = _eglGetConfigKey(conf2, compare_attribs[i]);
|
||||
if (val1 != val2)
|
||||
return (val1 - val2);
|
||||
}
|
||||
|
||||
/* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
|
||||
|
||||
return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
|
||||
{
|
||||
const _EGLConfig *tmp = *conf1;
|
||||
*conf1 = *conf2;
|
||||
*conf2 = tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick sort an array of configs. This differs from the standard
|
||||
* qsort() in that the compare function accepts an additional
|
||||
* argument.
|
||||
*/
|
||||
static void
|
||||
_eglSortConfigs(const _EGLConfig **configs, EGLint count,
|
||||
EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
|
||||
void *),
|
||||
void *priv_data)
|
||||
{
|
||||
const EGLint pivot = 0;
|
||||
EGLint i, j;
|
||||
|
||||
if (count <= 1)
|
||||
return;
|
||||
|
||||
_eglSwapConfigs(&configs[pivot], &configs[count / 2]);
|
||||
i = 1;
|
||||
j = count - 1;
|
||||
do {
|
||||
while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
|
||||
i++;
|
||||
while (compare(configs[j], configs[pivot], priv_data) > 0)
|
||||
j--;
|
||||
if (i < j) {
|
||||
_eglSwapConfigs(&configs[i], &configs[j]);
|
||||
i++;
|
||||
j--;
|
||||
} else if (i == j) {
|
||||
i++;
|
||||
j--;
|
||||
break;
|
||||
}
|
||||
} while (i <= j);
|
||||
_eglSwapConfigs(&configs[pivot], &configs[j]);
|
||||
|
||||
_eglSortConfigs(configs, j, compare, priv_data);
|
||||
_eglSortConfigs(configs + i, count - i, compare, priv_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function for implementing eglChooseConfig. See _eglFilterArray and
|
||||
* _eglSortConfigs for the meanings of match and compare.
|
||||
*/
|
||||
static EGLBoolean
|
||||
_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs, EGLint config_size,
|
||||
EGLint *num_configs,
|
||||
EGLBoolean (*match)(const _EGLConfig *,
|
||||
const _EGLConfig *),
|
||||
EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
|
||||
void *),
|
||||
void *priv_data)
|
||||
{
|
||||
_EGLConfig **configList;
|
||||
EGLint i, count;
|
||||
|
||||
/* get the number of matched configs */
|
||||
count = _eglFilterArray(array, NULL, 0, (_EGLArrayForEach)match, priv_data);
|
||||
if (!count) {
|
||||
*num_configs = count;
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
configList = malloc(sizeof(*configList) * count);
|
||||
if (!configList)
|
||||
return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
|
||||
|
||||
/* get the matched configs */
|
||||
_eglFilterArray(array, (void **)configList, count, (_EGLArrayForEach)match,
|
||||
priv_data);
|
||||
|
||||
/* perform sorting of configs */
|
||||
if (configs && count) {
|
||||
_eglSortConfigs((const _EGLConfig **)configList, count, compare,
|
||||
priv_data);
|
||||
count = MIN2(count, config_size);
|
||||
for (i = 0; i < count; i++)
|
||||
configs[i] = _eglGetConfigHandle(configList[i]);
|
||||
}
|
||||
|
||||
free(configList);
|
||||
|
||||
*num_configs = count;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLint
|
||||
_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2,
|
||||
void *priv_data)
|
||||
{
|
||||
return _eglCompareConfigs(conf1, conf2, (const _EGLConfig *)priv_data,
|
||||
EGL_TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Typical fallback routine for eglChooseConfig
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglChooseConfig(_EGLDisplay *disp, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size, EGLint *num_configs)
|
||||
{
|
||||
_EGLConfig criteria;
|
||||
EGLBoolean result;
|
||||
|
||||
if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
|
||||
|
||||
result = _eglFilterConfigArray(disp->Configs, configs, config_size,
|
||||
num_configs, _eglMatchConfig,
|
||||
_eglFallbackCompare, (void *)&criteria);
|
||||
|
||||
if (result && (_eglGetLogLevel() == _EGL_DEBUG))
|
||||
eglPrintConfigDebug(disp, configs, *num_configs, EGL_TRUE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback for eglGetConfigAttrib.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglGetConfigAttrib(const _EGLDisplay *disp, const _EGLConfig *conf,
|
||||
EGLint attribute, EGLint *value)
|
||||
{
|
||||
if (!_eglIsConfigAttribValid(conf, attribute))
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
|
||||
|
||||
/* nonqueryable attributes */
|
||||
switch (attribute) {
|
||||
case EGL_MATCH_NATIVE_PIXMAP:
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!value)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
|
||||
|
||||
*value = _eglGetConfigKey(conf, attribute);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
_eglFlattenConfig(void *elem, void *buffer)
|
||||
{
|
||||
_EGLConfig *conf = (_EGLConfig *)elem;
|
||||
EGLConfig *handle = (EGLConfig *)buffer;
|
||||
*handle = _eglGetConfigHandle(conf);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback for eglGetConfigs.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglGetConfigs(_EGLDisplay *disp, EGLConfig *configs, EGLint config_size,
|
||||
EGLint *num_config)
|
||||
{
|
||||
*num_config =
|
||||
_eglFlattenArray(disp->Configs, (void *)configs, sizeof(configs[0]),
|
||||
config_size, _eglFlattenConfig);
|
||||
|
||||
if (_eglGetLogLevel() == _EGL_DEBUG)
|
||||
eglPrintConfigDebug(disp, configs, *num_config, EGL_FALSE);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLCONFIG_INCLUDED
|
||||
#define EGLCONFIG_INCLUDED
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* update _eglValidationTable and _eglOffsetOfConfig before updating this
|
||||
* struct */
|
||||
struct _egl_config {
|
||||
_EGLDisplay *Display;
|
||||
|
||||
/* core */
|
||||
EGLint BufferSize;
|
||||
EGLint AlphaSize;
|
||||
EGLint BlueSize;
|
||||
EGLint GreenSize;
|
||||
EGLint RedSize;
|
||||
EGLint DepthSize;
|
||||
EGLint StencilSize;
|
||||
EGLint ConfigCaveat;
|
||||
EGLint ConfigID;
|
||||
EGLint Level;
|
||||
EGLint MaxPbufferHeight;
|
||||
EGLint MaxPbufferPixels;
|
||||
EGLint MaxPbufferWidth;
|
||||
EGLint NativeRenderable;
|
||||
EGLint NativeVisualID;
|
||||
EGLint NativeVisualType;
|
||||
EGLint Samples;
|
||||
EGLint SampleBuffers;
|
||||
EGLint SurfaceType;
|
||||
EGLint TransparentType;
|
||||
EGLint TransparentBlueValue;
|
||||
EGLint TransparentGreenValue;
|
||||
EGLint TransparentRedValue;
|
||||
EGLint BindToTextureRGB;
|
||||
EGLint BindToTextureRGBA;
|
||||
EGLint MinSwapInterval;
|
||||
EGLint MaxSwapInterval;
|
||||
EGLint LuminanceSize;
|
||||
EGLint AlphaMaskSize;
|
||||
EGLint ColorBufferType;
|
||||
EGLint RenderableType;
|
||||
EGLint MatchNativePixmap;
|
||||
EGLint Conformant;
|
||||
|
||||
/* extensions */
|
||||
EGLint YInvertedNOK;
|
||||
EGLint FramebufferTargetAndroid;
|
||||
EGLint RecordableAndroid;
|
||||
EGLint ComponentType;
|
||||
EGLint ConfigSelectGroup;
|
||||
};
|
||||
|
||||
/**
|
||||
* Map an EGL attribute enum to the offset of the member in _EGLConfig.
|
||||
*/
|
||||
static inline EGLint
|
||||
_eglOffsetOfConfig(EGLint attr)
|
||||
{
|
||||
switch (attr) {
|
||||
#define ATTRIB_MAP(attr, memb) \
|
||||
case attr: \
|
||||
return offsetof(_EGLConfig, memb)
|
||||
/* core */
|
||||
ATTRIB_MAP(EGL_BUFFER_SIZE, BufferSize);
|
||||
ATTRIB_MAP(EGL_ALPHA_SIZE, AlphaSize);
|
||||
ATTRIB_MAP(EGL_BLUE_SIZE, BlueSize);
|
||||
ATTRIB_MAP(EGL_GREEN_SIZE, GreenSize);
|
||||
ATTRIB_MAP(EGL_RED_SIZE, RedSize);
|
||||
ATTRIB_MAP(EGL_DEPTH_SIZE, DepthSize);
|
||||
ATTRIB_MAP(EGL_STENCIL_SIZE, StencilSize);
|
||||
ATTRIB_MAP(EGL_CONFIG_CAVEAT, ConfigCaveat);
|
||||
ATTRIB_MAP(EGL_CONFIG_ID, ConfigID);
|
||||
ATTRIB_MAP(EGL_LEVEL, Level);
|
||||
ATTRIB_MAP(EGL_MAX_PBUFFER_HEIGHT, MaxPbufferHeight);
|
||||
ATTRIB_MAP(EGL_MAX_PBUFFER_PIXELS, MaxPbufferPixels);
|
||||
ATTRIB_MAP(EGL_MAX_PBUFFER_WIDTH, MaxPbufferWidth);
|
||||
ATTRIB_MAP(EGL_NATIVE_RENDERABLE, NativeRenderable);
|
||||
ATTRIB_MAP(EGL_NATIVE_VISUAL_ID, NativeVisualID);
|
||||
ATTRIB_MAP(EGL_NATIVE_VISUAL_TYPE, NativeVisualType);
|
||||
ATTRIB_MAP(EGL_SAMPLES, Samples);
|
||||
ATTRIB_MAP(EGL_SAMPLE_BUFFERS, SampleBuffers);
|
||||
ATTRIB_MAP(EGL_SURFACE_TYPE, SurfaceType);
|
||||
ATTRIB_MAP(EGL_TRANSPARENT_TYPE, TransparentType);
|
||||
ATTRIB_MAP(EGL_TRANSPARENT_BLUE_VALUE, TransparentBlueValue);
|
||||
ATTRIB_MAP(EGL_TRANSPARENT_GREEN_VALUE, TransparentGreenValue);
|
||||
ATTRIB_MAP(EGL_TRANSPARENT_RED_VALUE, TransparentRedValue);
|
||||
ATTRIB_MAP(EGL_BIND_TO_TEXTURE_RGB, BindToTextureRGB);
|
||||
ATTRIB_MAP(EGL_BIND_TO_TEXTURE_RGBA, BindToTextureRGBA);
|
||||
ATTRIB_MAP(EGL_MIN_SWAP_INTERVAL, MinSwapInterval);
|
||||
ATTRIB_MAP(EGL_MAX_SWAP_INTERVAL, MaxSwapInterval);
|
||||
ATTRIB_MAP(EGL_LUMINANCE_SIZE, LuminanceSize);
|
||||
ATTRIB_MAP(EGL_ALPHA_MASK_SIZE, AlphaMaskSize);
|
||||
ATTRIB_MAP(EGL_COLOR_BUFFER_TYPE, ColorBufferType);
|
||||
ATTRIB_MAP(EGL_RENDERABLE_TYPE, RenderableType);
|
||||
ATTRIB_MAP(EGL_MATCH_NATIVE_PIXMAP, MatchNativePixmap);
|
||||
ATTRIB_MAP(EGL_CONFORMANT, Conformant);
|
||||
/* extensions */
|
||||
ATTRIB_MAP(EGL_Y_INVERTED_NOK, YInvertedNOK);
|
||||
ATTRIB_MAP(EGL_FRAMEBUFFER_TARGET_ANDROID, FramebufferTargetAndroid);
|
||||
ATTRIB_MAP(EGL_RECORDABLE_ANDROID, RecordableAndroid);
|
||||
ATTRIB_MAP(EGL_COLOR_COMPONENT_TYPE_EXT, ComponentType);
|
||||
ATTRIB_MAP(EGL_CONFIG_SELECT_GROUP_EXT, ConfigSelectGroup);
|
||||
#undef ATTRIB_MAP
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a config for a given key.
|
||||
*
|
||||
* Note that a valid key is not necessarily a valid attribute. There are gaps
|
||||
* in the attribute enums. The separation is to catch application errors.
|
||||
* Drivers should never set a key that is an invalid attribute.
|
||||
*/
|
||||
static inline void
|
||||
_eglSetConfigKey(_EGLConfig *conf, EGLint key, EGLint val)
|
||||
{
|
||||
EGLint offset = _eglOffsetOfConfig(key);
|
||||
assert(offset >= 0);
|
||||
*((EGLint *)((char *)conf + offset)) = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value for a given key.
|
||||
*/
|
||||
static inline EGLint
|
||||
_eglGetConfigKey(const _EGLConfig *conf, EGLint key)
|
||||
{
|
||||
EGLint offset = _eglOffsetOfConfig(key);
|
||||
assert(offset >= 0);
|
||||
return *((EGLint *)((char *)conf + offset));
|
||||
}
|
||||
|
||||
extern void
|
||||
_eglInitConfig(_EGLConfig *config, _EGLDisplay *disp, EGLint id);
|
||||
|
||||
extern EGLConfig
|
||||
_eglLinkConfig(_EGLConfig *conf);
|
||||
|
||||
extern _EGLConfig *
|
||||
_eglLookupConfig(EGLConfig config, _EGLDisplay *disp);
|
||||
|
||||
/**
|
||||
* Return the handle of a linked config.
|
||||
*/
|
||||
static inline EGLConfig
|
||||
_eglGetConfigHandle(_EGLConfig *conf)
|
||||
{
|
||||
return (EGLConfig)conf;
|
||||
}
|
||||
|
||||
extern EGLBoolean
|
||||
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *disp,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
extern EGLint
|
||||
_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
|
||||
const _EGLConfig *criteria, EGLBoolean compare_id);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglChooseConfig(_EGLDisplay *disp, const EGLint *attrib_list,
|
||||
EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetConfigAttrib(const _EGLDisplay *disp, const _EGLConfig *conf,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetConfigs(_EGLDisplay *disp, EGLConfig *configs, EGLint config_size,
|
||||
EGLint *num_config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLCONFIG_INCLUDED */
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright 2019 Imagination Technologies.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Based on eglinfo, which has copyright:
|
||||
* Copyright (C) 2005 Brian Paul 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
|
||||
* BRIAN PAUL 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.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/macros.h"
|
||||
#include "eglarray.h"
|
||||
#include "eglconfig.h"
|
||||
#include "eglconfigdebug.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egllog.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
/* Max debug message length */
|
||||
#define CONFIG_DEBUG_MSG_MAX 1000
|
||||
|
||||
/*
|
||||
* These are X visual types, so if you're running eglinfo under
|
||||
* something not X, they probably don't make sense.
|
||||
*/
|
||||
static const char *const vnames[] = {"SG", "GS", "SC", "PC", "TC", "DC"};
|
||||
|
||||
static void
|
||||
_printHeaderFormat(void)
|
||||
{
|
||||
/*
|
||||
* EGL configuration output legend:
|
||||
*
|
||||
* chosen --------------- eglChooseConfig returned config priority,
|
||||
* only relevant when eglChooseConfig is called.
|
||||
* id ------------------- EGL_CONFIG_ID
|
||||
* bfsz ----------------- EGL_BUFFER_SIZE
|
||||
* lvl ------------------ EGL_LEVEL
|
||||
*
|
||||
* colourbuffer
|
||||
* r -------------------- EGL_RED_SIZE
|
||||
* g -------------------- EGL_GREEN_SIZE
|
||||
* b -------------------- EGL_BLUE_SIZE
|
||||
* a -------------------- EGL_ALPHA_SIZE
|
||||
* dpth ----------------- EGL_DEPTH_SIZE
|
||||
* stcl ----------------- EGL_STENCIL_SIZE
|
||||
*
|
||||
* multisample
|
||||
* ns ------------------- EGL_SAMPLES
|
||||
* b -------------------- EGL_SAMPLE_BUFFERS
|
||||
* visid ---------------- EGL_NATIVE_VISUAL_ID/EGL_NATIVE_VISUAL_TYPE
|
||||
* caveat --------------- EGL_CONFIG_CAVEAT
|
||||
* bind ----------------- EGL_BIND_TO_TEXTURE_RGB/EGL_BIND_TO_TEXTURE_RGBA
|
||||
*
|
||||
* renderable
|
||||
* gl, es, es2, es3, vg - EGL_RENDERABLE_TYPE
|
||||
*
|
||||
* supported
|
||||
* surfaces ------------- EGL_SURFACE_TYPE
|
||||
*/
|
||||
/* clang-format off */
|
||||
_eglLog(_EGL_DEBUG, "---------------");
|
||||
_eglLog(_EGL_DEBUG, "Configurations:");
|
||||
_eglLog(_EGL_DEBUG, "cho bf lv colourbuffer dp st ms vis cav bi renderable supported");
|
||||
_eglLog(_EGL_DEBUG, "sen id sz l r g b a th cl ns b id eat nd gl es es2 es3 vg surfaces");
|
||||
_eglLog(_EGL_DEBUG, "---------------");
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
/* Append a formatted string to the buffer, up to the buffer size */
|
||||
static inline void
|
||||
_strnAppend(char *const buf, const int bufSize, const char *fmt, ...)
|
||||
{
|
||||
int maxAllowed;
|
||||
va_list args;
|
||||
size_t bufLen = strlen(buf);
|
||||
|
||||
maxAllowed = bufSize - bufLen;
|
||||
assert(maxAllowed >= 0);
|
||||
|
||||
va_start(args, fmt);
|
||||
(void)vsnprintf(&buf[bufLen], maxAllowed, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void
|
||||
_eglPrintConfig(_EGLConfig *const conf, const int chosenIndex)
|
||||
{
|
||||
const char padding[] = " ";
|
||||
char printMsg[CONFIG_DEBUG_MSG_MAX] = "";
|
||||
char surfString[32] = "";
|
||||
EGLint renderable, surfaces, vtype, bindRgb, bindRgba;
|
||||
|
||||
vtype = conf->NativeVisualType;
|
||||
surfaces = conf->SurfaceType;
|
||||
|
||||
STATIC_ASSERT(sizeof(surfString) >= sizeof("win,pb,pix,str,prsv"));
|
||||
|
||||
if (surfaces & EGL_WINDOW_BIT)
|
||||
strcat(surfString, "win,");
|
||||
if (surfaces & EGL_PBUFFER_BIT)
|
||||
strcat(surfString, "pb,");
|
||||
if (surfaces & EGL_PIXMAP_BIT)
|
||||
strcat(surfString, "pix,");
|
||||
if (surfaces & EGL_STREAM_BIT_KHR)
|
||||
strcat(surfString, "str,");
|
||||
if (surfaces & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
|
||||
strcat(surfString, "prsv");
|
||||
|
||||
/* If one of chosen configs, print its index in the returned config array */
|
||||
if (chosenIndex >= 0)
|
||||
_strnAppend(printMsg, sizeof(printMsg), "%*d ", (int)strlen(padding),
|
||||
chosenIndex);
|
||||
else
|
||||
_strnAppend(printMsg, sizeof(printMsg), "%s ", &padding[0]);
|
||||
|
||||
_strnAppend(printMsg, sizeof(printMsg),
|
||||
"0x%03x %2d %2d %2d %2d %2d %2d %2d %2d %2d%2d 0x%08x%2s ",
|
||||
conf->ConfigID, conf->BufferSize, conf->Level, conf->RedSize,
|
||||
conf->GreenSize, conf->BlueSize, conf->AlphaSize,
|
||||
conf->DepthSize, conf->StencilSize, conf->Samples,
|
||||
conf->SampleBuffers, conf->NativeVisualID,
|
||||
vtype < 6 ? vnames[vtype] : "--");
|
||||
|
||||
bindRgb = conf->BindToTextureRGB;
|
||||
bindRgba = conf->BindToTextureRGBA;
|
||||
renderable = conf->RenderableType;
|
||||
|
||||
_strnAppend(printMsg, sizeof(printMsg),
|
||||
"%c %c %c %c %c %c %c %15s",
|
||||
(conf->ConfigCaveat != EGL_NONE) ? 'y' : ' ',
|
||||
(bindRgba) ? 'a'
|
||||
: (bindRgb) ? 'y'
|
||||
: ' ',
|
||||
(renderable & EGL_OPENGL_BIT) ? 'y' : ' ',
|
||||
(renderable & EGL_OPENGL_ES_BIT) ? 'y' : ' ',
|
||||
(renderable & EGL_OPENGL_ES2_BIT) ? 'y' : ' ',
|
||||
(renderable & EGL_OPENGL_ES3_BIT) ? 'y' : ' ',
|
||||
(renderable & EGL_OPENVG_BIT) ? 'y' : ' ', surfString);
|
||||
|
||||
_eglLog(_EGL_DEBUG, printMsg);
|
||||
}
|
||||
|
||||
void
|
||||
eglPrintConfigDebug(const _EGLDisplay *const disp,
|
||||
const EGLConfig *const configs, const EGLint numConfigs,
|
||||
const EGLBoolean printChosen)
|
||||
{
|
||||
EGLint numConfigsToPrint;
|
||||
_EGLConfig **configsToPrint;
|
||||
_EGLConfig **chosenConfigs;
|
||||
|
||||
if (!numConfigs || !configs) {
|
||||
_eglLog(_EGL_DEBUG, "%s: nothing to print", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the printout request came from the 'eglChooseConfig', all
|
||||
* configs are printed, and the "chosen" configs are marked.
|
||||
*/
|
||||
if (printChosen) {
|
||||
configsToPrint = (_EGLConfig **)disp->Configs->Elements;
|
||||
numConfigsToPrint = disp->Configs->Size;
|
||||
chosenConfigs = (_EGLConfig **)configs;
|
||||
} else {
|
||||
configsToPrint = (_EGLConfig **)configs;
|
||||
numConfigsToPrint = numConfigs;
|
||||
chosenConfigs = NULL;
|
||||
}
|
||||
|
||||
_printHeaderFormat();
|
||||
for (EGLint i = 0; i < numConfigsToPrint; i++) {
|
||||
_EGLConfig *configToPrint = configsToPrint[i];
|
||||
EGLint chosenIndex = -1;
|
||||
|
||||
/* See if the current config to print is one of the chosen configs */
|
||||
if (chosenConfigs)
|
||||
for (EGLint j = 0; j < numConfigs; j++)
|
||||
if (configToPrint == chosenConfigs[j])
|
||||
chosenIndex = j;
|
||||
|
||||
_eglPrintConfig(configToPrint, chosenIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**************************************************************************
|
||||
* Copyright 2017 Imagination Technologies.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLCONFIGDEBUG_INCLUDED
|
||||
#define EGLCONFIGDEBUG_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
/**
|
||||
* Print the list of configs and the associated attributes.
|
||||
*/
|
||||
void
|
||||
eglPrintConfigDebug(const _EGLDisplay *const disp,
|
||||
const EGLConfig *const configs, EGLint numConfigs,
|
||||
EGLBoolean printChosen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLCONFIGDEBUG_INCLUDED */
|
||||
@@ -0,0 +1,964 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "eglcontext.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util/macros.h"
|
||||
#include "eglconfig.h"
|
||||
#include "eglcurrent.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
/**
|
||||
* Return the API bit (one of EGL_xxx_BIT) of the context.
|
||||
*/
|
||||
static EGLint
|
||||
_eglGetContextAPIBit(_EGLContext *ctx)
|
||||
{
|
||||
EGLint bit = 0;
|
||||
|
||||
switch (ctx->ClientAPI) {
|
||||
case EGL_OPENGL_ES_API:
|
||||
switch (ctx->ClientMajorVersion) {
|
||||
case 1:
|
||||
bit = EGL_OPENGL_ES_BIT;
|
||||
break;
|
||||
case 2:
|
||||
bit = EGL_OPENGL_ES2_BIT;
|
||||
break;
|
||||
case 3:
|
||||
bit = EGL_OPENGL_ES3_BIT_KHR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EGL_OPENVG_API:
|
||||
bit = EGL_OPENVG_BIT;
|
||||
break;
|
||||
case EGL_OPENGL_API:
|
||||
bit = EGL_OPENGL_BIT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the list of context attributes and return the proper error code.
|
||||
*/
|
||||
static EGLint
|
||||
_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
EGLenum api = ctx->ClientAPI;
|
||||
EGLint i, err = EGL_SUCCESS;
|
||||
|
||||
if (!attrib_list)
|
||||
return EGL_SUCCESS;
|
||||
|
||||
if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
|
||||
_eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
|
||||
return EGL_BAD_ATTRIBUTE;
|
||||
}
|
||||
|
||||
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
|
||||
EGLint attr = attrib_list[i++];
|
||||
EGLint val = attrib_list[i];
|
||||
|
||||
switch (attr) {
|
||||
case EGL_CONTEXT_CLIENT_VERSION:
|
||||
/* The EGL 1.4 spec says:
|
||||
*
|
||||
* "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
|
||||
* current rendering API is EGL_OPENGL_ES_API"
|
||||
*
|
||||
* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
|
||||
* (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
|
||||
*
|
||||
* "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
|
||||
* EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
|
||||
* version. They are only meaningful for OpenGL and OpenGL ES
|
||||
* contexts, and specifying them for other types of contexts will
|
||||
* generate an error."
|
||||
*/
|
||||
if ((api != EGL_OPENGL_ES_API &&
|
||||
(!disp->Extensions.KHR_create_context ||
|
||||
api != EGL_OPENGL_API))) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->ClientMajorVersion = val;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_MINOR_VERSION_KHR:
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
|
||||
* EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
|
||||
* version. They are only meaningful for OpenGL and OpenGL ES
|
||||
* contexts, and specifying them for other types of contexts will
|
||||
* generate an error."
|
||||
*/
|
||||
if (!disp->Extensions.KHR_create_context ||
|
||||
(api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->ClientMinorVersion = val;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_FLAGS_KHR:
|
||||
if (!disp->Extensions.KHR_create_context) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
|
||||
* EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
|
||||
* [...]
|
||||
* In some cases a debug context may be identical to a non-debug
|
||||
* context. This bit is supported for OpenGL and OpenGL ES
|
||||
* contexts."
|
||||
*/
|
||||
if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
|
||||
(api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
|
||||
* is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
|
||||
* context will be created. Forward-compatible contexts are
|
||||
* defined only for OpenGL versions 3.0 and later. They must not
|
||||
* support functionality marked as <deprecated> by that version of
|
||||
* the API, while a non-forward-compatible context must support
|
||||
* all functionality in that version, deprecated or not. This bit
|
||||
* is supported for OpenGL contexts, and requesting a
|
||||
* forward-compatible context for OpenGL versions less than 3.0
|
||||
* will generate an error."
|
||||
*
|
||||
* Note: since the forward-compatible flag can be set more than one
|
||||
* way, the OpenGL version check is performed once, below.
|
||||
*/
|
||||
if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
|
||||
api != EGL_OPENGL_API) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
|
||||
api != EGL_OPENGL_API) {
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* 10) Which error should be generated if robust buffer access
|
||||
* or reset notifications are requested under OpenGL ES?
|
||||
*
|
||||
* As per Issue 6, this extension does not support creating
|
||||
* robust contexts for OpenGL ES. This is only supported via
|
||||
* the EGL_EXT_create_context_robustness extension.
|
||||
*
|
||||
* Attempting to use this extension to create robust OpenGL
|
||||
* ES context will generate an EGL_BAD_ATTRIBUTE error. This
|
||||
* specific error is generated because this extension does
|
||||
* not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
|
||||
* and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
|
||||
* bits for OpenGL ES contexts. Thus, use of these bits fall
|
||||
* under condition described by: "If an attribute is
|
||||
* specified that is not meaningful for the client API
|
||||
* type.." in the above specification.
|
||||
*
|
||||
* The spec requires that we emit the error even if the display
|
||||
* supports EGL_EXT_create_context_robustness. To create a robust
|
||||
* GLES context, the *attribute*
|
||||
* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
|
||||
* *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
|
||||
*/
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
* "If <config> does not support a client API context compatible
|
||||
* with the requested API major and minor version, context flags,
|
||||
* and context reset notification behavior (for client API types
|
||||
* where these attributes are supported), then an EGL_BAD_MATCH
|
||||
* error is generated."
|
||||
*/
|
||||
if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
|
||||
!disp->RobustBufferAccess) {
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->Flags |= val;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
|
||||
if (!disp->Extensions.KHR_create_context) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
|
||||
* OpenGL contexts, and specifying it for other types of
|
||||
* contexts, including OpenGL ES contexts, will generate an
|
||||
* error."
|
||||
*/
|
||||
if (api != EGL_OPENGL_API) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->Profile = val;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
|
||||
* meaningful for OpenGL contexts, and specifying it for other
|
||||
* types of contexts, including OpenGL ES contexts, will generate
|
||||
* an error."
|
||||
*
|
||||
* EGL 1.5 defines EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY
|
||||
* (without a suffix) which has the same value as the KHR token,
|
||||
* and specifies that it now works with both GL and ES contexts:
|
||||
*
|
||||
* "This attribute is supported only for OpenGL and OpenGL ES
|
||||
* contexts."
|
||||
*/
|
||||
if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API) &&
|
||||
disp->Version < 15) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL 1.5 spec says:
|
||||
* "An EGL_BAD_MATCH error is generated if an OpenGL or OpenGL ES
|
||||
* context is requested with robust buffer access and with a
|
||||
* specified reset notification behavior, and the implementation
|
||||
* does not support that behavior."
|
||||
*
|
||||
* and the EGL_KHR_create_context spec says:
|
||||
* "If <config> does not support a client API context compatible
|
||||
* with the requested API major and minor version, context flags,
|
||||
* and context reset notification behavior (for client API types
|
||||
* where these attributes are supported), then an EGL_BAD_MATCH
|
||||
* error is generated."
|
||||
*/
|
||||
if (val != EGL_NO_RESET_NOTIFICATION_KHR &&
|
||||
!disp->Extensions.EXT_create_context_robustness) {
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->ResetNotificationStrategy = val;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
|
||||
/* The EGL_EXT_create_context_robustness spec says:
|
||||
*
|
||||
* "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
|
||||
* meaningful for OpenGL ES contexts, and specifying it for other
|
||||
* types of contexts will generate an EGL_BAD_ATTRIBUTE error."
|
||||
*/
|
||||
if (!disp->Extensions.EXT_create_context_robustness ||
|
||||
api != EGL_OPENGL_ES_API) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->ResetNotificationStrategy = val;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
|
||||
if (!disp->Extensions.EXT_create_context_robustness) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL_EXT_create_context_robustness spec says:
|
||||
*
|
||||
* "EGL_BAD_CONFIG is generated if
|
||||
* [EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT] is set to EGL_TRUE and
|
||||
* no GL context supporting the GL_EXT_robustness extension and
|
||||
* robust access as described therein can be created."
|
||||
*/
|
||||
if (val == EGL_TRUE && !disp->RobustBufferAccess) {
|
||||
err = EGL_BAD_CONFIG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == EGL_TRUE)
|
||||
ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
|
||||
if (disp->Version < 15) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL 1.5 spec says:
|
||||
* "An EGL_BAD_MATCH error is generated if an OpenGL or OpenGL ES
|
||||
* context is requested with robust buffer access, and the
|
||||
* implementation does not support the corresponding OpenGL or
|
||||
* OpenGL ES extension".
|
||||
*/
|
||||
if (val == EGL_TRUE && !disp->RobustBufferAccess) {
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == EGL_TRUE)
|
||||
ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_DEBUG:
|
||||
if (disp->Version < 15) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == EGL_TRUE)
|
||||
ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
|
||||
if (disp->Version < 15) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val == EGL_TRUE)
|
||||
ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
|
||||
if (disp->Version < 14 ||
|
||||
!disp->Extensions.KHR_create_context_no_error) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The KHR_no_error spec only applies against OpenGL 2.0+ and
|
||||
* OpenGL ES 2.0+
|
||||
*/
|
||||
if (((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
|
||||
ctx->ClientMajorVersion < 2) &&
|
||||
val == EGL_TRUE) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
|
||||
ctx->NoError = !!val;
|
||||
break;
|
||||
|
||||
case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
|
||||
/* The EGL_IMG_context_priority spec says:
|
||||
*
|
||||
* "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
|
||||
* the context to be created. This attribute is a hint, as an
|
||||
* implementation may not support multiple contexts at some
|
||||
* priority levels and system policy may limit access to high
|
||||
* priority contexts to appropriate system privilege level. The
|
||||
* default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
|
||||
* EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
|
||||
*/
|
||||
{
|
||||
int bit;
|
||||
|
||||
switch (val) {
|
||||
case EGL_CONTEXT_PRIORITY_REALTIME_NV:
|
||||
if (disp->Extensions.NV_context_priority_realtime)
|
||||
bit = __EGL_CONTEXT_PRIORITY_REALTIME_BIT;
|
||||
else
|
||||
bit = -1;
|
||||
break;
|
||||
case EGL_CONTEXT_PRIORITY_HIGH_IMG:
|
||||
bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
|
||||
break;
|
||||
case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
|
||||
bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
|
||||
break;
|
||||
case EGL_CONTEXT_PRIORITY_LOW_IMG:
|
||||
bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
|
||||
break;
|
||||
default:
|
||||
bit = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bit < 0) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* "This extension allows an EGLContext to be created with a
|
||||
* priority hint. It is possible that an implementation will not
|
||||
* honour the hint, especially if there are constraints on the
|
||||
* number of high priority contexts available in the system, or
|
||||
* system policy limits access to high priority contexts to
|
||||
* appropriate system privilege level. A query is provided to find
|
||||
* the real priority level assigned to the context after creation."
|
||||
*
|
||||
* We currently assume that the driver applies the priority hint
|
||||
* and filters out any it cannot handle during the screen setup,
|
||||
* e.g. dri2_setup_screen(). As such we can mask any change that
|
||||
* the driver would fail, and ctx->ContextPriority matches the
|
||||
* hint applied to the driver/hardware backend.
|
||||
*/
|
||||
if (disp->Extensions.IMG_context_priority & (1 << bit))
|
||||
ctx->ContextPriority = val;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
|
||||
if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
|
||||
val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
|
||||
ctx->ReleaseBehavior = val;
|
||||
} else {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
}
|
||||
break;
|
||||
|
||||
case EGL_PROTECTED_CONTENT_EXT:
|
||||
if (!disp->Extensions.EXT_protected_content) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
ctx->Protected = val == EGL_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS) {
|
||||
_eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (api == EGL_OPENGL_API) {
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "If the requested OpenGL version is less than 3.2,
|
||||
* EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
|
||||
* functionality of the context is determined solely by the
|
||||
* requested version."
|
||||
*
|
||||
* Since the value is ignored, only validate the setting if the version
|
||||
* is >= 3.2.
|
||||
*/
|
||||
if (ctx->ClientMajorVersion >= 4 ||
|
||||
(ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
|
||||
switch (ctx->Profile) {
|
||||
case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
|
||||
case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "* If an OpenGL context is requested, the requested version
|
||||
* is greater than 3.2, and the value for attribute
|
||||
* EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
|
||||
* any bits set other than
|
||||
* EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
|
||||
* EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
|
||||
* one of these bits set; or if the implementation does not support
|
||||
* the requested profile, then an EGL_BAD_MATCH error is generated."
|
||||
*/
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "* If an OpenGL context is requested and the values for
|
||||
* attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
|
||||
* EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
|
||||
* the value for attribute
|
||||
* EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
|
||||
* version and feature set that are not defined, than an
|
||||
* EGL_BAD_MATCH error is generated.
|
||||
*
|
||||
* ... Thus, examples of invalid combinations of attributes
|
||||
* include:
|
||||
*
|
||||
* - Major version < 1 or > 4
|
||||
* - Major version == 1 and minor version < 0 or > 5
|
||||
* - Major version == 2 and minor version < 0 or > 1
|
||||
* - Major version == 3 and minor version < 0 or > 2
|
||||
* - Major version == 4 and minor version < 0 or > 2
|
||||
* - Forward-compatible flag set and major version < 3"
|
||||
*/
|
||||
if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
|
||||
err = EGL_BAD_MATCH;
|
||||
|
||||
switch (ctx->ClientMajorVersion) {
|
||||
case 1:
|
||||
if (ctx->ClientMinorVersion > 5 ||
|
||||
(ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (ctx->ClientMinorVersion > 1 ||
|
||||
(ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* Note: The text above is incorrect. There *is* an OpenGL 3.3!
|
||||
*/
|
||||
if (ctx->ClientMinorVersion > 3)
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
default:
|
||||
/* Don't put additional version checks here. We don't know that
|
||||
* there won't be versions > 4.2.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
} else if (api == EGL_OPENGL_ES_API) {
|
||||
/* The EGL_KHR_create_context spec says:
|
||||
*
|
||||
* "* If an OpenGL ES context is requested and the values for
|
||||
* attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
|
||||
* EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
|
||||
* is not defined, than an EGL_BAD_MATCH error is generated.
|
||||
*
|
||||
* ... Examples of invalid combinations of attributes include:
|
||||
*
|
||||
* - Major version < 1 or > 2
|
||||
* - Major version == 1 and minor version < 0 or > 1
|
||||
* - Major version == 2 and minor version != 0
|
||||
*/
|
||||
if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
|
||||
err = EGL_BAD_MATCH;
|
||||
|
||||
switch (ctx->ClientMajorVersion) {
|
||||
case 1:
|
||||
if (ctx->ClientMinorVersion > 1)
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (ctx->ClientMinorVersion > 0)
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* Don't put additional version checks here. We don't know that
|
||||
* there won't be versions > 3.0.
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ctx->ResetNotificationStrategy) {
|
||||
case EGL_NO_RESET_NOTIFICATION_KHR:
|
||||
case EGL_LOSE_CONTEXT_ON_RESET_KHR:
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* The EGL_KHR_create_context_no_error spec says:
|
||||
*
|
||||
* "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE
|
||||
* at the same time as a debug or robustness context is specified."
|
||||
*/
|
||||
if (ctx->NoError &&
|
||||
(ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
|
||||
ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
|
||||
err = EGL_BAD_MATCH;
|
||||
}
|
||||
|
||||
if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
|
||||
EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR |
|
||||
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the given _EGLContext object to defaults and/or the values
|
||||
* in the attrib_list.
|
||||
*
|
||||
* According to EGL 1.5 Section 3.7:
|
||||
*
|
||||
* "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
|
||||
* purposes except eglCreateContext."
|
||||
*
|
||||
* And since we only support GL and GLES, this is the only place where the
|
||||
* bound API matters at all. We look up the current API from the current
|
||||
* thread, and stash that in the context we're initializing. Our caller is
|
||||
* responsible for determining whether that's an API it supports.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,
|
||||
_EGLContext *share_list, const EGLint *attrib_list)
|
||||
{
|
||||
const EGLenum api = eglQueryAPI();
|
||||
EGLint err;
|
||||
|
||||
if (api == EGL_NONE)
|
||||
return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
|
||||
|
||||
_eglInitResource(&ctx->Resource, sizeof(*ctx), disp);
|
||||
ctx->ClientAPI = api;
|
||||
ctx->Config = conf;
|
||||
ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||
|
||||
ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
|
||||
ctx->ClientMinorVersion = 0;
|
||||
ctx->Flags = 0;
|
||||
ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
|
||||
ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
|
||||
ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
|
||||
|
||||
err = _eglParseContextAttribList(ctx, disp, attrib_list);
|
||||
if (err == EGL_SUCCESS && ctx->Config) {
|
||||
EGLint api_bit;
|
||||
|
||||
api_bit = _eglGetContextAPIBit(ctx);
|
||||
if (!(ctx->Config->RenderableType & api_bit)) {
|
||||
_eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
|
||||
api_bit, ctx->Config->RenderableType);
|
||||
err = EGL_BAD_CONFIG;
|
||||
}
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
return _eglError(err, "eglCreateContext");
|
||||
|
||||
/* The EGL_EXT_create_context_robustness spec says:
|
||||
*
|
||||
* "Add to the eglCreateContext context creation errors: [...]
|
||||
*
|
||||
* * If the reset notification behavior of <share_context> and the
|
||||
* newly created context are different then an EGL_BAD_MATCH error is
|
||||
* generated."
|
||||
*/
|
||||
if (share_list && share_list->ResetNotificationStrategy !=
|
||||
ctx->ResetNotificationStrategy) {
|
||||
return _eglError(
|
||||
EGL_BAD_MATCH,
|
||||
"eglCreateContext() share list notification strategy mismatch");
|
||||
}
|
||||
|
||||
/* The EGL_KHR_create_context_no_error spec says:
|
||||
*
|
||||
* "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
|
||||
* used to create <share_context> does not match the value of
|
||||
* EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
|
||||
*/
|
||||
if (share_list && share_list->NoError != ctx->NoError) {
|
||||
return _eglError(EGL_BAD_MATCH,
|
||||
"eglCreateContext() share list no-error mismatch");
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLint
|
||||
_eglQueryContextRenderBuffer(_EGLContext *ctx)
|
||||
{
|
||||
_EGLSurface *surf = ctx->DrawSurface;
|
||||
|
||||
/* From the EGL 1.5 spec:
|
||||
*
|
||||
* - If the context is not bound to a surface, then EGL_NONE will be
|
||||
* returned.
|
||||
*/
|
||||
if (!surf)
|
||||
return EGL_NONE;
|
||||
|
||||
switch (surf->Type) {
|
||||
default:
|
||||
UNREACHABLE("bad EGLSurface type");
|
||||
case EGL_PIXMAP_BIT:
|
||||
/* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
|
||||
* will be returned.
|
||||
*/
|
||||
return EGL_SINGLE_BUFFER;
|
||||
case EGL_PBUFFER_BIT:
|
||||
/* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
|
||||
* will be returned.
|
||||
*/
|
||||
return EGL_BACK_BUFFER;
|
||||
case EGL_WINDOW_BIT:
|
||||
/* - If the context is bound to a window surface, then either
|
||||
* EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
|
||||
* returned depends on both the buffer requested by the setting of the
|
||||
* EGL_RENDER_BUFFER property of the surface [...], and on the client
|
||||
* API (not all client APIs support single-buffer Rendering to window
|
||||
* surfaces). Some client APIs allow control of whether rendering goes
|
||||
* to the front or back buffer. This client API-specific choice is not
|
||||
* reflected in the returned value, which only describes the buffer
|
||||
* that will be rendered to by default if not overridden by the client
|
||||
* API.
|
||||
*/
|
||||
return surf->ActiveRenderBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLDisplay *disp = c->Resource.Display;
|
||||
EGLenum api = c->ClientAPI;
|
||||
|
||||
if (!value)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
|
||||
|
||||
switch (attribute) {
|
||||
case EGL_CONFIG_ID:
|
||||
/*
|
||||
* From EGL_KHR_no_config_context:
|
||||
*
|
||||
* "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
|
||||
* respect to which the context was created, or zero if created
|
||||
* without respect to an EGLConfig."
|
||||
*/
|
||||
*value = c->Config ? c->Config->ConfigID : 0;
|
||||
break;
|
||||
case EGL_CONTEXT_CLIENT_VERSION:
|
||||
*value = c->ClientMajorVersion;
|
||||
break;
|
||||
case EGL_CONTEXT_CLIENT_TYPE:
|
||||
*value = c->ClientAPI;
|
||||
break;
|
||||
case EGL_RENDER_BUFFER:
|
||||
*value = _eglQueryContextRenderBuffer(c);
|
||||
break;
|
||||
case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
|
||||
*value = c->ContextPriority;
|
||||
break;
|
||||
case EGL_PROTECTED_CONTENT_EXT:
|
||||
if (!disp->Extensions.EXT_protected_content)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
||||
*value = c->Protected;
|
||||
break;
|
||||
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
|
||||
if (!disp->Extensions.EXT_create_context_robustness ||
|
||||
api != EGL_OPENGL_ES_API)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
||||
*value = c->ResetNotificationStrategy;
|
||||
break;
|
||||
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
|
||||
if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API) &&
|
||||
disp->Version < 15)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
||||
*value = c->ResetNotificationStrategy;
|
||||
break;
|
||||
default:
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the context to the thread and return the previous context.
|
||||
*
|
||||
* Note that the context may be NULL.
|
||||
*/
|
||||
_EGLContext *
|
||||
_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
|
||||
{
|
||||
_EGLContext *oldCtx;
|
||||
|
||||
oldCtx = t->CurrentContext;
|
||||
if (ctx != oldCtx) {
|
||||
if (oldCtx)
|
||||
oldCtx->Binding = NULL;
|
||||
if (ctx)
|
||||
ctx->Binding = t;
|
||||
|
||||
t->CurrentContext = ctx;
|
||||
}
|
||||
|
||||
return oldCtx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given context and surfaces can be made current.
|
||||
*/
|
||||
static EGLBoolean
|
||||
_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
_EGLDisplay *disp;
|
||||
|
||||
/* this is easy */
|
||||
if (!ctx) {
|
||||
if (draw || read)
|
||||
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
disp = ctx->Resource.Display;
|
||||
if (!disp->Extensions.KHR_surfaceless_context &&
|
||||
(draw == NULL || read == NULL))
|
||||
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
|
||||
/*
|
||||
* The spec says
|
||||
*
|
||||
* "If ctx is current to some other thread, or if either draw or read are
|
||||
* bound to contexts in another thread, an EGL_BAD_ACCESS error is
|
||||
* generated."
|
||||
*
|
||||
* and
|
||||
*
|
||||
* "at most one context may be bound to a particular surface at a given
|
||||
* time"
|
||||
*/
|
||||
if (ctx->Binding && ctx->Binding != t)
|
||||
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
||||
if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
|
||||
if (draw->CurrentContext->Binding != t)
|
||||
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
||||
}
|
||||
if (read && read->CurrentContext && read->CurrentContext != ctx) {
|
||||
if (read->CurrentContext->Binding != t)
|
||||
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
||||
}
|
||||
|
||||
/* If the context has a config then it must match that of the two
|
||||
* surfaces */
|
||||
if (ctx->Config) {
|
||||
if ((draw && draw->Config != ctx->Config) ||
|
||||
(read && read->Config != ctx->Config))
|
||||
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
||||
} else {
|
||||
/* Otherwise we must be using the EGL_KHR_no_config_context
|
||||
* extension */
|
||||
assert(disp->Extensions.KHR_no_config_context);
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the context to the current thread and given surfaces. Return the
|
||||
* previous bound context and surfaces. The caller should unreference the
|
||||
* returned context and surfaces.
|
||||
*
|
||||
* Making a second call with the resources returned by the first call
|
||||
* unsurprisingly undoes the first call, except for the resource reference
|
||||
* counts.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
|
||||
_EGLContext **old_ctx, _EGLSurface **old_draw,
|
||||
_EGLSurface **old_read)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
_EGLContext *prev_ctx;
|
||||
_EGLSurface *prev_draw, *prev_read;
|
||||
|
||||
if (!_eglCheckMakeCurrent(ctx, draw, read))
|
||||
return EGL_FALSE;
|
||||
|
||||
/* increment refcounts before binding */
|
||||
_eglGetContext(ctx);
|
||||
_eglGetSurface(draw);
|
||||
_eglGetSurface(read);
|
||||
|
||||
/* bind the new context */
|
||||
prev_ctx = _eglBindContextToThread(ctx, t);
|
||||
|
||||
/* break previous bindings */
|
||||
if (prev_ctx) {
|
||||
prev_draw = prev_ctx->DrawSurface;
|
||||
prev_read = prev_ctx->ReadSurface;
|
||||
|
||||
if (prev_draw)
|
||||
prev_draw->CurrentContext = NULL;
|
||||
if (prev_read)
|
||||
prev_read->CurrentContext = NULL;
|
||||
|
||||
prev_ctx->DrawSurface = NULL;
|
||||
prev_ctx->ReadSurface = NULL;
|
||||
} else {
|
||||
prev_draw = prev_read = NULL;
|
||||
}
|
||||
|
||||
/* establish new bindings */
|
||||
if (ctx) {
|
||||
if (draw)
|
||||
draw->CurrentContext = ctx;
|
||||
if (read)
|
||||
read->CurrentContext = ctx;
|
||||
|
||||
ctx->DrawSurface = draw;
|
||||
ctx->ReadSurface = read;
|
||||
}
|
||||
|
||||
assert(old_ctx && old_draw && old_read);
|
||||
*old_ctx = prev_ctx;
|
||||
*old_draw = prev_draw;
|
||||
*old_read = prev_read;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLCONTEXT_INCLUDED
|
||||
#define EGLCONTEXT_INCLUDED
|
||||
|
||||
#include "egldisplay.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* "Base" class for device driver contexts.
|
||||
*/
|
||||
struct _egl_context {
|
||||
/* A context is a display resource */
|
||||
_EGLResource Resource;
|
||||
|
||||
/* The bound status of the context */
|
||||
_EGLThreadInfo *Binding;
|
||||
_EGLSurface *DrawSurface;
|
||||
_EGLSurface *ReadSurface;
|
||||
|
||||
_EGLConfig *Config;
|
||||
|
||||
EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */
|
||||
EGLint ClientMajorVersion;
|
||||
EGLint ClientMinorVersion;
|
||||
EGLint Flags;
|
||||
EGLint Profile;
|
||||
EGLint ResetNotificationStrategy;
|
||||
EGLint ContextPriority;
|
||||
EGLBoolean NoError;
|
||||
EGLint ReleaseBehavior;
|
||||
EGLBoolean Protected; /* EGL_EXT_protected_content */
|
||||
};
|
||||
|
||||
extern EGLBoolean
|
||||
_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *config,
|
||||
_EGLContext *share_list, const EGLint *attrib_list);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQueryContext(_EGLContext *ctx, EGLint attribute, EGLint *value);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
|
||||
_EGLContext **old_ctx, _EGLSurface **old_draw,
|
||||
_EGLSurface **old_read);
|
||||
|
||||
extern _EGLContext *
|
||||
_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t);
|
||||
|
||||
/**
|
||||
* Increment reference count for the context.
|
||||
*/
|
||||
static inline _EGLContext *
|
||||
_eglGetContext(_EGLContext *ctx)
|
||||
{
|
||||
if (ctx)
|
||||
_eglGetResource(&ctx->Resource);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement reference count for the context.
|
||||
*/
|
||||
static inline EGLBoolean
|
||||
_eglPutContext(_EGLContext *ctx)
|
||||
{
|
||||
return (ctx) ? _eglPutResource(&ctx->Resource) : EGL_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a context to its display and return the handle of the link.
|
||||
* The handle can be passed to client directly.
|
||||
*/
|
||||
static inline EGLContext
|
||||
_eglLinkContext(_EGLContext *ctx)
|
||||
{
|
||||
_eglLinkResource(&ctx->Resource, _EGL_RESOURCE_CONTEXT);
|
||||
return (EGLContext)ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a linked context from its display.
|
||||
* Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
|
||||
*/
|
||||
static inline void
|
||||
_eglUnlinkContext(_EGLContext *ctx)
|
||||
{
|
||||
_eglUnlinkResource(&ctx->Resource, _EGL_RESOURCE_CONTEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a handle to find the linked context.
|
||||
* Return NULL if the handle has no corresponding linked context.
|
||||
*/
|
||||
static inline _EGLContext *
|
||||
_eglLookupContext(EGLContext context, _EGLDisplay *disp)
|
||||
{
|
||||
_EGLContext *ctx = (_EGLContext *)context;
|
||||
if (!disp || !_eglCheckResource((void *)ctx, _EGL_RESOURCE_CONTEXT, disp))
|
||||
ctx = NULL;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the handle of a linked context, or EGL_NO_CONTEXT.
|
||||
*/
|
||||
static inline EGLContext
|
||||
_eglGetContextHandle(_EGLContext *ctx)
|
||||
{
|
||||
_EGLResource *res = (_EGLResource *)ctx;
|
||||
return (res && _eglIsResourceLinked(res)) ? (EGLContext)ctx : EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLCONTEXT_INCLUDED */
|
||||
@@ -0,0 +1,210 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "c11/threads.h"
|
||||
#include "util/u_string.h"
|
||||
#include "util/u_thread.h"
|
||||
|
||||
#include "eglcurrent.h"
|
||||
#include "eglglobals.h"
|
||||
#include "egllog.h"
|
||||
|
||||
static __THREAD_INITIAL_EXEC _EGLThreadInfo _egl_TLS = {
|
||||
.inited = false,
|
||||
};
|
||||
|
||||
static void
|
||||
_eglInitThreadInfo(_EGLThreadInfo *t)
|
||||
{
|
||||
t->LastError = EGL_SUCCESS;
|
||||
/* default, per EGL spec */
|
||||
t->CurrentAPI = EGL_OPENGL_ES_API;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calling thread's thread info.
|
||||
* If the calling thread never calls this function before, or if its thread
|
||||
* info was destroyed, reinitialize it. This function never returns NULL.
|
||||
*/
|
||||
_EGLThreadInfo *
|
||||
_eglGetCurrentThread(void)
|
||||
{
|
||||
_EGLThreadInfo *current = &_egl_TLS;
|
||||
if (unlikely(!current->inited)) {
|
||||
memset(current, 0, sizeof(current[0]));
|
||||
_eglInitThreadInfo(current);
|
||||
current->inited = true;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the calling thread's thread info.
|
||||
*/
|
||||
void
|
||||
_eglDestroyCurrentThread(void)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
t->inited = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently bound context of the current API, or NULL.
|
||||
*/
|
||||
_EGLContext *
|
||||
_eglGetCurrentContext(void)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
return t->CurrentContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record EGL error code and return EGL_FALSE.
|
||||
*/
|
||||
static EGLBoolean
|
||||
_eglInternalError(EGLint errCode, const char *msg)
|
||||
{
|
||||
_EGLThreadInfo *t = _eglGetCurrentThread();
|
||||
|
||||
t->LastError = errCode;
|
||||
|
||||
if (errCode != EGL_SUCCESS) {
|
||||
const char *s;
|
||||
|
||||
switch (errCode) {
|
||||
case EGL_BAD_ACCESS:
|
||||
s = "EGL_BAD_ACCESS";
|
||||
break;
|
||||
case EGL_BAD_ALLOC:
|
||||
s = "EGL_BAD_ALLOC";
|
||||
break;
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
s = "EGL_BAD_ATTRIBUTE";
|
||||
break;
|
||||
case EGL_BAD_CONFIG:
|
||||
s = "EGL_BAD_CONFIG";
|
||||
break;
|
||||
case EGL_BAD_CONTEXT:
|
||||
s = "EGL_BAD_CONTEXT";
|
||||
break;
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
s = "EGL_BAD_CURRENT_SURFACE";
|
||||
break;
|
||||
case EGL_BAD_DISPLAY:
|
||||
s = "EGL_BAD_DISPLAY";
|
||||
break;
|
||||
case EGL_BAD_MATCH:
|
||||
s = "EGL_BAD_MATCH";
|
||||
break;
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
s = "EGL_BAD_NATIVE_PIXMAP";
|
||||
break;
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
s = "EGL_BAD_NATIVE_WINDOW";
|
||||
break;
|
||||
case EGL_BAD_PARAMETER:
|
||||
s = "EGL_BAD_PARAMETER";
|
||||
break;
|
||||
case EGL_BAD_SURFACE:
|
||||
s = "EGL_BAD_SURFACE";
|
||||
break;
|
||||
case EGL_NOT_INITIALIZED:
|
||||
s = "EGL_NOT_INITIALIZED";
|
||||
break;
|
||||
default:
|
||||
s = "other EGL error";
|
||||
}
|
||||
_eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg);
|
||||
}
|
||||
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglError(EGLint errCode, const char *msg)
|
||||
{
|
||||
if (errCode != EGL_SUCCESS) {
|
||||
EGLint type;
|
||||
if (errCode == EGL_BAD_ALLOC)
|
||||
type = EGL_DEBUG_MSG_CRITICAL_KHR;
|
||||
else
|
||||
type = EGL_DEBUG_MSG_ERROR_KHR;
|
||||
|
||||
_eglDebugReport(errCode, NULL, type, msg);
|
||||
} else
|
||||
_eglInternalError(errCode, msg);
|
||||
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_eglDebugReport(EGLenum error, const char *funcName, EGLint type,
|
||||
const char *message, ...)
|
||||
{
|
||||
_EGLThreadInfo *thr = _eglGetCurrentThread();
|
||||
EGLDEBUGPROCKHR callback = NULL;
|
||||
va_list args;
|
||||
|
||||
if (funcName == NULL)
|
||||
funcName = thr->CurrentFuncName;
|
||||
|
||||
simple_mtx_lock(_eglGlobal.Mutex);
|
||||
if (_eglGlobal.debugTypesEnabled & DebugBitFromType(type))
|
||||
callback = _eglGlobal.debugCallback;
|
||||
|
||||
simple_mtx_unlock(_eglGlobal.Mutex);
|
||||
|
||||
char *message_buf = NULL;
|
||||
if (message != NULL) {
|
||||
va_start(args, message);
|
||||
if (vasprintf(&message_buf, message, args) < 0)
|
||||
message_buf = NULL;
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
if (callback != NULL) {
|
||||
callback(error, funcName, type, thr->Label, thr->CurrentObjectLabel,
|
||||
message_buf);
|
||||
}
|
||||
|
||||
if (type == EGL_DEBUG_MSG_CRITICAL_KHR || type == EGL_DEBUG_MSG_ERROR_KHR) {
|
||||
char *func_message_buf = NULL;
|
||||
/* Note: _eglError() is often called with msg == thr->currentFuncName */
|
||||
if (message_buf && funcName && strcmp(message_buf, funcName) != 0) {
|
||||
if (asprintf(&func_message_buf, "%s: %s", funcName, message_buf) < 0)
|
||||
func_message_buf = NULL;
|
||||
}
|
||||
_eglInternalError(error, func_message_buf ? func_message_buf : funcName);
|
||||
free(func_message_buf);
|
||||
}
|
||||
free(message_buf);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLCURRENT_INCLUDED
|
||||
#define EGLCURRENT_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util/detect_os.h"
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _EGL_API_ALL_BITS \
|
||||
(EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT | \
|
||||
EGL_OPENGL_ES3_BIT_KHR | EGL_OPENGL_BIT)
|
||||
|
||||
/**
|
||||
* Per-thread info
|
||||
*/
|
||||
struct _egl_thread_info {
|
||||
bool inited;
|
||||
EGLint LastError;
|
||||
_EGLContext *CurrentContext;
|
||||
EGLenum CurrentAPI;
|
||||
EGLLabelKHR Label;
|
||||
|
||||
/**
|
||||
* The name of the EGL function that's being called at the moment. This is
|
||||
* used to report the function name to the EGL_KHR_debug callback.
|
||||
*/
|
||||
const char *CurrentFuncName;
|
||||
EGLLabelKHR CurrentObjectLabel;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return true if a client API enum is recognized.
|
||||
*/
|
||||
static inline EGLBoolean
|
||||
_eglIsApiValid(EGLenum api)
|
||||
{
|
||||
#if HAVE_OPENGL && !DETECT_OS_ANDROID
|
||||
/* OpenGL is not a valid/supported API on Android */
|
||||
if (api == EGL_OPENGL_API)
|
||||
return true;
|
||||
#endif
|
||||
#if HAVE_OPENGL_ES_1 || HAVE_OPENGL_ES_2
|
||||
if (api == EGL_OPENGL_ES_API)
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
extern _EGLThreadInfo *
|
||||
_eglGetCurrentThread(void);
|
||||
|
||||
extern void
|
||||
_eglDestroyCurrentThread(void);
|
||||
|
||||
extern _EGLContext *
|
||||
_eglGetCurrentContext(void);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglError(EGLint errCode, const char *msg);
|
||||
|
||||
extern void
|
||||
_eglDebugReport(EGLenum error, const char *funcName, EGLint type,
|
||||
const char *message, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLCURRENT_INCLUDED */
|
||||
@@ -0,0 +1,53 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Internal EGL defines
|
||||
*/
|
||||
|
||||
#ifndef EGLDEFINES_INCLUDED
|
||||
#define EGLDEFINES_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _EGL_MAX_EXTENSIONS_LEN 2048
|
||||
|
||||
/* Hardcoded, conservative default for EGL_LARGEST_PBUFFER,
|
||||
* this is used to implement EGL_LARGEST_PBUFFER.
|
||||
*/
|
||||
#define _EGL_MAX_PBUFFER_WIDTH 4096
|
||||
#define _EGL_MAX_PBUFFER_HEIGHT 4096
|
||||
|
||||
#define _EGL_VENDOR_STRING "Mesa Project"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLDEFINES_INCLUDED */
|
||||
@@ -0,0 +1,523 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2015, 2018 Collabora
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
#include <xf86drm.h>
|
||||
#endif
|
||||
#include "util/compiler.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/u_debug.h"
|
||||
|
||||
#include "eglcurrent.h"
|
||||
#include "egldevice.h"
|
||||
#include "eglglobals.h"
|
||||
#include "egllog.h"
|
||||
#include "egltypedefs.h"
|
||||
#include "egldriver.h"
|
||||
|
||||
struct _egl_device {
|
||||
_EGLDevice *Next;
|
||||
|
||||
const char *extensions;
|
||||
|
||||
EGLBoolean MESA_device_software;
|
||||
EGLBoolean EXT_device_drm;
|
||||
EGLBoolean EXT_device_drm_render_node;
|
||||
EGLBoolean EXT_device_query_name;
|
||||
EGLBoolean EXT_device_persistent_id;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
drmDevicePtr device;
|
||||
#endif
|
||||
|
||||
/* Cache for EGL_EXT_device_query_name and EXT_device_persistent_id. */
|
||||
struct egl_device_info device_info;
|
||||
};
|
||||
|
||||
void
|
||||
_eglFiniDevice(void)
|
||||
{
|
||||
_EGLDevice *dev_list, *dev;
|
||||
|
||||
/* atexit function is called with global mutex locked */
|
||||
|
||||
dev_list = _eglGlobal.DeviceList;
|
||||
|
||||
/* The first device is static allocated SW device */
|
||||
assert(dev_list);
|
||||
assert(_eglDeviceSupports(dev_list, _EGL_DEVICE_SOFTWARE));
|
||||
dev_list = dev_list->Next;
|
||||
|
||||
while (dev_list) {
|
||||
/* pop list head */
|
||||
dev = dev_list;
|
||||
dev_list = dev_list->Next;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_DRM));
|
||||
drmFreeDevice(&dev->device);
|
||||
#endif
|
||||
free(dev->device_info.vendor_name);
|
||||
free(dev->device_info.renderer_name);
|
||||
free(dev->device_info.driver_name);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
_eglGlobal.DeviceList = NULL;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglCheckDeviceHandle(EGLDeviceEXT device)
|
||||
{
|
||||
_EGLDevice *cur;
|
||||
|
||||
simple_mtx_lock(_eglGlobal.Mutex);
|
||||
cur = _eglGlobal.DeviceList;
|
||||
while (cur) {
|
||||
if (cur == (_EGLDevice *)device)
|
||||
break;
|
||||
cur = cur->Next;
|
||||
}
|
||||
simple_mtx_unlock(_eglGlobal.Mutex);
|
||||
return (cur != NULL);
|
||||
}
|
||||
|
||||
_EGLDevice _eglSoftwareDevice = {
|
||||
/* TODO: EGL_EXT_device_drm support for KMS + llvmpipe */
|
||||
.extensions = "EGL_MESA_device_software EGL_EXT_device_drm_render_node",
|
||||
.MESA_device_software = EGL_TRUE,
|
||||
.EXT_device_drm_render_node = EGL_TRUE,
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
extern const _EGLDriver _eglDriver;
|
||||
/*
|
||||
* Negative value on error, zero if newly added, one if already in list.
|
||||
*/
|
||||
static int
|
||||
_eglAddDRMDevice(drmDevicePtr device)
|
||||
{
|
||||
_EGLDevice *dev;
|
||||
|
||||
assert(device->available_nodes & ((1 << DRM_NODE_RENDER)));
|
||||
|
||||
/* TODO: uncomment this assert, which is a sanity check.
|
||||
*
|
||||
* assert(device->available_nodes & ((1 << DRM_NODE_PRIMARY)));
|
||||
*
|
||||
* DRM shim does not expose a primary node, so the CI would fail if we had
|
||||
* this assert. DRM shim is being used to run shader-db. We need to
|
||||
* investigate what should be done (probably fixing DRM shim).
|
||||
*/
|
||||
|
||||
dev = _eglGlobal.DeviceList;
|
||||
|
||||
/* The first device is always software */
|
||||
assert(dev);
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
|
||||
|
||||
while (dev->Next) {
|
||||
dev = dev->Next;
|
||||
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_DRM));
|
||||
if (drmDevicesEqual(device, dev->device) != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev->Next = calloc(1, sizeof(_EGLDevice));
|
||||
if (!dev->Next)
|
||||
return -1;
|
||||
|
||||
dev = dev->Next;
|
||||
|
||||
/* Need to have render node for query to work. */
|
||||
bool supports_info_query =
|
||||
device->available_nodes & (1 << DRM_NODE_RENDER) &&
|
||||
_eglDriver.QueryDeviceInfo;
|
||||
|
||||
if (supports_info_query)
|
||||
dev->extensions =
|
||||
"EGL_EXT_device_drm EGL_EXT_device_drm_render_node "
|
||||
"EGL_EXT_device_query_name EGL_EXT_device_persistent_id";
|
||||
else
|
||||
dev->extensions = "EGL_EXT_device_drm EGL_EXT_device_drm_render_node";
|
||||
dev->EXT_device_drm = EGL_TRUE;
|
||||
dev->EXT_device_drm_render_node = EGL_TRUE;
|
||||
if (supports_info_query) {
|
||||
dev->EXT_device_query_name = EGL_TRUE;
|
||||
dev->EXT_device_persistent_id = EGL_TRUE;
|
||||
}
|
||||
dev->device = device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Finds a device in DeviceList, for the given fd.
|
||||
*
|
||||
* The fd must be of a render-capable device, as there are only render-capable
|
||||
* devices in DeviceList.
|
||||
*
|
||||
* If a software device, the fd is ignored.
|
||||
*/
|
||||
_EGLDevice *
|
||||
_eglFindDevice(int fd, bool software)
|
||||
{
|
||||
_EGLDevice *dev;
|
||||
|
||||
simple_mtx_lock(_eglGlobal.Mutex);
|
||||
dev = _eglGlobal.DeviceList;
|
||||
|
||||
/* The first device is always software */
|
||||
assert(dev);
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
|
||||
if (software)
|
||||
goto out;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
drmDevicePtr device;
|
||||
|
||||
if (drmGetDevice2(fd, 0, &device) != 0) {
|
||||
dev = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (dev->Next) {
|
||||
dev = dev->Next;
|
||||
|
||||
if (_eglDeviceSupports(dev, _EGL_DEVICE_DRM) &&
|
||||
drmDevicesEqual(device, dev->device) != 0) {
|
||||
goto cleanup_drm;
|
||||
}
|
||||
}
|
||||
|
||||
/* Couldn't find an EGLDevice for the device. */
|
||||
dev = NULL;
|
||||
|
||||
cleanup_drm:
|
||||
drmFreeDevice(&device);
|
||||
|
||||
#else
|
||||
_eglLog(_EGL_FATAL,
|
||||
"Driver bug: Built without libdrm, yet looking for HW device");
|
||||
dev = NULL;
|
||||
#endif
|
||||
|
||||
out:
|
||||
simple_mtx_unlock(_eglGlobal.Mutex);
|
||||
return dev;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
drmDevicePtr
|
||||
_eglDeviceDrm(_EGLDevice *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
return dev->device;
|
||||
}
|
||||
#endif
|
||||
|
||||
_EGLDevice *
|
||||
_eglDeviceNext(_EGLDevice *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
return dev->Next;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext)
|
||||
{
|
||||
switch (ext) {
|
||||
case _EGL_DEVICE_SOFTWARE:
|
||||
return dev->MESA_device_software;
|
||||
case _EGL_DEVICE_DRM:
|
||||
return dev->EXT_device_drm;
|
||||
case _EGL_DEVICE_DRM_RENDER_NODE:
|
||||
return dev->EXT_device_drm_render_node;
|
||||
case _EGL_DEVICE_QUERY_NAME:
|
||||
return dev->EXT_device_query_name;
|
||||
case _EGL_DEVICE_PERSISTENT_ID:
|
||||
return dev->EXT_device_persistent_id;
|
||||
default:
|
||||
assert(0);
|
||||
return EGL_FALSE;
|
||||
};
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute, EGLAttrib *value)
|
||||
{
|
||||
switch (attribute) {
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryDeviceAttribEXT");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryDeviceBinaryEXT(_EGLDevice *dev, EGLint name, EGLint max_size,
|
||||
void *value, EGLint *size)
|
||||
{
|
||||
if (!_eglDeviceSupports(dev, _EGL_DEVICE_DRM) ||
|
||||
!_eglDeviceSupports(dev, _EGL_DEVICE_PERSISTENT_ID) ||
|
||||
!(name == EGL_DEVICE_UUID_EXT || name == EGL_DRIVER_UUID_EXT) ||
|
||||
(value != NULL && max_size < EGL_UUID_SIZE) ||
|
||||
size == NULL) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryDeviceBinaryEXT");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
drmDevicePtr device = _eglDeviceDrm(dev);
|
||||
/* Software device does not have render node. */
|
||||
const char *render_node =
|
||||
_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE) ?
|
||||
"" : device->nodes[DRM_NODE_RENDER];
|
||||
if (!_eglDriver.QueryDeviceInfo(render_node, &dev->device_info)) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglQueryDeviceBinaryEXT");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (value && name == EGL_DEVICE_UUID_EXT) {
|
||||
memcpy(value, dev->device_info.device_uuid, EGL_UUID_SIZE);
|
||||
}
|
||||
if (value && name == EGL_DRIVER_UUID_EXT) {
|
||||
memcpy(value, dev->device_info.driver_uuid, EGL_UUID_SIZE);
|
||||
}
|
||||
*size = EGL_UUID_SIZE;
|
||||
return EGL_TRUE;
|
||||
#else
|
||||
/* This should never happen: we don't yet support EGL_DEVICE_DRM nor
|
||||
* EGL_DEVICE_PERSISTENT_ID for the software device, and physical devices are
|
||||
* only exposed when libdrm is available. */
|
||||
assert(0);
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryDeviceBinaryEXT");
|
||||
return EGL_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
_eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name)
|
||||
{
|
||||
#ifdef HAVE_LIBDRM
|
||||
drmDevicePtr device = _eglDeviceDrm(dev);
|
||||
/* Software device does not have render node. */
|
||||
const char *render_node =
|
||||
_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE) ?
|
||||
"" : device->nodes[DRM_NODE_RENDER];
|
||||
#endif
|
||||
|
||||
switch (name) {
|
||||
case EGL_EXTENSIONS:
|
||||
return dev->extensions;
|
||||
case EGL_DRM_DEVICE_FILE_EXT:
|
||||
if (!_eglDeviceSupports(dev, _EGL_DEVICE_DRM))
|
||||
break;
|
||||
#ifdef HAVE_LIBDRM
|
||||
return dev->device->nodes[DRM_NODE_PRIMARY];
|
||||
#else
|
||||
/* This should never happen: we don't yet support EGL_DEVICE_DRM for the
|
||||
* software device, and physical devices are only exposed when libdrm is
|
||||
* available. */
|
||||
assert(0);
|
||||
break;
|
||||
#endif
|
||||
case EGL_DRM_RENDER_NODE_FILE_EXT:
|
||||
if (!_eglDeviceSupports(dev, _EGL_DEVICE_DRM_RENDER_NODE))
|
||||
break;
|
||||
#ifdef HAVE_LIBDRM
|
||||
/* EGLDevice represents a software device, so no render node
|
||||
* should be advertised. */
|
||||
if (_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE))
|
||||
return NULL;
|
||||
/* We create EGLDevice's only for render capable devices. */
|
||||
assert(dev->device->available_nodes & (1 << DRM_NODE_RENDER));
|
||||
return dev->device->nodes[DRM_NODE_RENDER];
|
||||
#else
|
||||
/* Physical devices are only exposed when libdrm is available. */
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
|
||||
return NULL;
|
||||
#endif
|
||||
/* EGL_EXT_device_query_name */
|
||||
case EGL_VENDOR:
|
||||
if (!_eglDeviceSupports(dev, _EGL_DEVICE_QUERY_NAME))
|
||||
break;
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (!_eglDriver.QueryDeviceInfo(render_node, &dev->device_info)) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglQueryDeviceStringEXT");
|
||||
return NULL;
|
||||
}
|
||||
return dev->device_info.vendor_name;
|
||||
#else
|
||||
/* Physical devices are only exposed when libdrm is available. */
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
|
||||
return NULL;
|
||||
#endif
|
||||
case EGL_RENDERER_EXT:
|
||||
if (!_eglDeviceSupports(dev, _EGL_DEVICE_QUERY_NAME))
|
||||
break;
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (!_eglDriver.QueryDeviceInfo(render_node, &dev->device_info)) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglQueryDeviceStringEXT");
|
||||
return NULL;
|
||||
}
|
||||
return dev->device_info.renderer_name;
|
||||
#else
|
||||
/* Physical devices are only exposed when libdrm is available. */
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
|
||||
return NULL;
|
||||
#endif
|
||||
/* EGL_EXT_device_persistent_id */
|
||||
case EGL_DRIVER_NAME_EXT:
|
||||
if (!_eglDeviceSupports(dev, _EGL_DEVICE_PERSISTENT_ID))
|
||||
break;
|
||||
#ifdef HAVE_LIBDRM
|
||||
if (!_eglDriver.QueryDeviceInfo(render_node, &dev->device_info)) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglQueryDeviceStringEXT");
|
||||
return NULL;
|
||||
}
|
||||
return dev->device_info.driver_name;
|
||||
#else
|
||||
/* Physical devices are only exposed when libdrm is available. */
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
_eglError(EGL_BAD_PARAMETER, "eglQueryDeviceStringEXT");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Do a fresh lookup for devices.
|
||||
*
|
||||
* Walks through the DeviceList, discarding no longer available ones
|
||||
* and adding new ones as applicable.
|
||||
*
|
||||
* Must be called with the global lock held.
|
||||
*/
|
||||
int
|
||||
_eglDeviceRefreshList(void)
|
||||
{
|
||||
ASSERTED _EGLDevice *dev;
|
||||
int count = 0;
|
||||
|
||||
dev = _eglGlobal.DeviceList;
|
||||
|
||||
/* The first device is always software */
|
||||
assert(dev);
|
||||
assert(_eglDeviceSupports(dev, _EGL_DEVICE_SOFTWARE));
|
||||
count++;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
drmDevicePtr devices[64];
|
||||
int num_devs, ret;
|
||||
|
||||
num_devs = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
|
||||
for (int i = 0; i < num_devs; i++) {
|
||||
if (!(devices[i]->available_nodes & (1 << DRM_NODE_RENDER))) {
|
||||
drmFreeDevice(&devices[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = _eglAddDRMDevice(devices[i]);
|
||||
|
||||
/* Device is not added - error or already present */
|
||||
if (ret != 0)
|
||||
drmFreeDevice(&devices[i]);
|
||||
|
||||
if (ret >= 0)
|
||||
count++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryDevicesEXT(EGLint max_devices, _EGLDevice **devices,
|
||||
EGLint *num_devices)
|
||||
{
|
||||
_EGLDevice *dev, *devs, *swrast;
|
||||
int i = 0, num_devs;
|
||||
bool request_software =
|
||||
debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false);
|
||||
|
||||
if ((devices && max_devices <= 0) || !num_devices)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglQueryDevicesEXT");
|
||||
|
||||
simple_mtx_lock(_eglGlobal.Mutex);
|
||||
|
||||
num_devs = _eglDeviceRefreshList();
|
||||
devs = _eglGlobal.DeviceList;
|
||||
|
||||
#ifdef HAVE_SWRAST
|
||||
swrast = devs;
|
||||
#else
|
||||
swrast = NULL;
|
||||
num_devs--;
|
||||
#endif
|
||||
|
||||
/* The first device is swrast. Start with the non-swrast device. */
|
||||
devs = devs->Next;
|
||||
|
||||
/* bail early if we only care about the count */
|
||||
if (!devices) {
|
||||
*num_devices = request_software ? !!swrast : num_devs;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (request_software) {
|
||||
*num_devices = !!swrast;
|
||||
devices[0] = swrast;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*num_devices = MIN2(num_devs, max_devices);
|
||||
|
||||
/* Add non-swrast devices first and add swrast last.
|
||||
*
|
||||
* By default, the user is likely to pick the first device so having the
|
||||
* software (aka least performant) one is not a good idea.
|
||||
*/
|
||||
for (i = 0, dev = devs; dev && i < max_devices; i++) {
|
||||
devices[i] = dev;
|
||||
dev = dev->Next;
|
||||
}
|
||||
|
||||
/* User requested the full device list, add the software device. */
|
||||
if (max_devices >= num_devs && swrast) {
|
||||
assert(_eglDeviceSupports(swrast, _EGL_DEVICE_SOFTWARE));
|
||||
devices[num_devs - 1] = swrast;
|
||||
}
|
||||
|
||||
out:
|
||||
simple_mtx_unlock(_eglGlobal.Mutex);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2015, 2018 Collabora
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLDEVICE_INCLUDED
|
||||
#define EGLDEVICE_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#ifdef HAVE_LIBDRM
|
||||
#include <xf86drm.h>
|
||||
#endif
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern _EGLDevice _eglSoftwareDevice;
|
||||
|
||||
void
|
||||
_eglFiniDevice(void);
|
||||
|
||||
EGLBoolean
|
||||
_eglCheckDeviceHandle(EGLDeviceEXT device);
|
||||
|
||||
static inline _EGLDevice *
|
||||
_eglLookupDevice(EGLDeviceEXT device)
|
||||
{
|
||||
_EGLDevice *dev = (_EGLDevice *)device;
|
||||
if (!_eglCheckDeviceHandle(device))
|
||||
dev = NULL;
|
||||
return dev;
|
||||
}
|
||||
|
||||
_EGLDevice *
|
||||
_eglFindDevice(int fd, bool software);
|
||||
|
||||
enum _egl_device_extension {
|
||||
_EGL_DEVICE_SOFTWARE,
|
||||
_EGL_DEVICE_DRM,
|
||||
_EGL_DEVICE_DRM_RENDER_NODE,
|
||||
_EGL_DEVICE_QUERY_NAME,
|
||||
_EGL_DEVICE_PERSISTENT_ID,
|
||||
};
|
||||
|
||||
typedef enum _egl_device_extension _EGLDeviceExtension;
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
drmDevicePtr
|
||||
_eglDeviceDrm(_EGLDevice *dev);
|
||||
#else
|
||||
#define _eglDeviceDrm(dev) NULL
|
||||
#endif
|
||||
|
||||
_EGLDevice *
|
||||
_eglDeviceNext(_EGLDevice *dev);
|
||||
|
||||
EGLBoolean
|
||||
_eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext);
|
||||
|
||||
int
|
||||
_eglDeviceRefreshList(void);
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute, EGLAttrib *value);
|
||||
|
||||
const char *
|
||||
_eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name);
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryDevicesEXT(EGLint max_devices, _EGLDevice **devices,
|
||||
EGLint *num_devices);
|
||||
|
||||
EGLBoolean
|
||||
_eglQueryDeviceBinaryEXT(_EGLDevice* dev,
|
||||
EGLint name,
|
||||
EGLint max_size,
|
||||
void *value,
|
||||
EGLint *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLDEVICE_INCLUDED */
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* (C) Copyright 2016, 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 (including the next
|
||||
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* Authors:
|
||||
* Kyle Brenneman <[email protected]>
|
||||
*/
|
||||
|
||||
#include "egldispatchstubs.h"
|
||||
#include "g_egldispatchstubs.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eglcurrent.h"
|
||||
|
||||
static const __EGLapiExports *exports;
|
||||
|
||||
const int __EGL_DISPATCH_FUNC_COUNT = __EGL_DISPATCH_COUNT;
|
||||
int __EGL_DISPATCH_FUNC_INDICES[__EGL_DISPATCH_COUNT + 1];
|
||||
|
||||
static int
|
||||
Compare(const void *l, const void *r)
|
||||
{
|
||||
const char *s = *(const char **)r;
|
||||
return strcmp(l, s);
|
||||
}
|
||||
|
||||
static int
|
||||
FindProcIndex(const char *name)
|
||||
{
|
||||
const char * const *match =
|
||||
bsearch(name, __EGL_DISPATCH_FUNC_NAMES, __EGL_DISPATCH_COUNT,
|
||||
sizeof(const char *), Compare);
|
||||
|
||||
if (match == NULL)
|
||||
return __EGL_DISPATCH_COUNT;
|
||||
|
||||
return match - __EGL_DISPATCH_FUNC_NAMES;
|
||||
}
|
||||
|
||||
void
|
||||
__eglInitDispatchStubs(const __EGLapiExports *exportsTable)
|
||||
{
|
||||
int i;
|
||||
exports = exportsTable;
|
||||
for (i = 0; i < __EGL_DISPATCH_FUNC_COUNT; i++) {
|
||||
__EGL_DISPATCH_FUNC_INDICES[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__eglSetDispatchIndex(const char *name, int dispatchIndex)
|
||||
{
|
||||
int index = FindProcIndex(name);
|
||||
__EGL_DISPATCH_FUNC_INDICES[index] = dispatchIndex;
|
||||
}
|
||||
|
||||
void *
|
||||
__eglDispatchFindDispatchFunction(const char *name)
|
||||
{
|
||||
int index = FindProcIndex(name);
|
||||
return (void *)__EGL_DISPATCH_FUNCS[index];
|
||||
}
|
||||
|
||||
static __eglMustCastToProperFunctionPointerType
|
||||
FetchVendorFunc(__EGLvendorInfo *vendor, int index, EGLint errorCode)
|
||||
{
|
||||
__eglMustCastToProperFunctionPointerType func = NULL;
|
||||
|
||||
if (vendor != NULL) {
|
||||
func = exports->fetchDispatchEntry(vendor,
|
||||
__EGL_DISPATCH_FUNC_INDICES[index]);
|
||||
}
|
||||
if (func == NULL) {
|
||||
if (errorCode != EGL_SUCCESS) {
|
||||
// Since we have no vendor, the follow-up eglGetError() call will
|
||||
// end up using the GLVND error code. Set it here.
|
||||
if (vendor == NULL) {
|
||||
exports->setEGLError(errorCode);
|
||||
}
|
||||
_eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!exports->setLastVendor(vendor)) {
|
||||
// Don't bother trying to set an error code in libglvnd. If
|
||||
// setLastVendor failed, then setEGLError would also fail.
|
||||
_eglError(errorCode, __EGL_DISPATCH_FUNC_NAMES[index]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
__eglMustCastToProperFunctionPointerType
|
||||
__eglDispatchFetchByCurrent(int index)
|
||||
{
|
||||
__EGLvendorInfo *vendor;
|
||||
|
||||
// Note: This is only used for the eglWait* functions. For those, if
|
||||
// there's no current context, then they're supposed to do nothing but
|
||||
// return success.
|
||||
exports->threadInit();
|
||||
vendor = exports->getCurrentVendor();
|
||||
return FetchVendorFunc(vendor, index, EGL_SUCCESS);
|
||||
}
|
||||
|
||||
__eglMustCastToProperFunctionPointerType
|
||||
__eglDispatchFetchByDisplay(EGLDisplay dpy, int index)
|
||||
{
|
||||
__EGLvendorInfo *vendor;
|
||||
|
||||
exports->threadInit();
|
||||
vendor = exports->getVendorFromDisplay(dpy);
|
||||
return FetchVendorFunc(vendor, index, EGL_BAD_DISPLAY);
|
||||
}
|
||||
|
||||
__eglMustCastToProperFunctionPointerType
|
||||
__eglDispatchFetchByDevice(EGLDeviceEXT dev, int index)
|
||||
{
|
||||
__EGLvendorInfo *vendor;
|
||||
|
||||
exports->threadInit();
|
||||
vendor = exports->getVendorFromDevice(dev);
|
||||
return FetchVendorFunc(vendor, index, EGL_BAD_DEVICE_EXT);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* (C) Copyright 2016, 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 (including the next
|
||||
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* Authors:
|
||||
* Kyle Brenneman <[email protected]>
|
||||
*/
|
||||
|
||||
#ifndef EGLDISPATCHSTUBS_H
|
||||
#define EGLDISPATCHSTUBS_H
|
||||
|
||||
#include "glvnd/libeglabi.h"
|
||||
|
||||
// These variables are all generated along with the dispatch stubs.
|
||||
extern const int __EGL_DISPATCH_FUNC_COUNT;
|
||||
extern const char *const __EGL_DISPATCH_FUNC_NAMES[];
|
||||
extern int __EGL_DISPATCH_FUNC_INDICES[];
|
||||
extern const __eglMustCastToProperFunctionPointerType __EGL_DISPATCH_FUNCS[];
|
||||
|
||||
void
|
||||
__eglInitDispatchStubs(const __EGLapiExports *exportsTable);
|
||||
void
|
||||
__eglSetDispatchIndex(const char *name, int index);
|
||||
|
||||
/**
|
||||
* Returns the dispatch function for the given name, or \c NULL if the function
|
||||
* isn't supported.
|
||||
*/
|
||||
void *
|
||||
__eglDispatchFindDispatchFunction(const char *name);
|
||||
|
||||
// Helper functions used by the generated stubs.
|
||||
__eglMustCastToProperFunctionPointerType
|
||||
__eglDispatchFetchByDisplay(EGLDisplay dpy, int index);
|
||||
__eglMustCastToProperFunctionPointerType
|
||||
__eglDispatchFetchByDevice(EGLDeviceEXT dpy, int index);
|
||||
__eglMustCastToProperFunctionPointerType
|
||||
__eglDispatchFetchByCurrent(int index);
|
||||
|
||||
#endif // EGLDISPATCHSTUBS_H
|
||||
@@ -0,0 +1,753 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Functions related to EGLDisplay.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "c11/threads.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/os_file.h"
|
||||
#include "util/os_misc.h"
|
||||
#include "util/u_atomic.h"
|
||||
|
||||
#include "eglcontext.h"
|
||||
#include "eglcurrent.h"
|
||||
#include "egldevice.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "eglglobals.h"
|
||||
#include "eglimage.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglsync.h"
|
||||
|
||||
/* Includes for _eglNativePlatformDetectNativeDisplay */
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
#include <gbm.h>
|
||||
#endif
|
||||
#ifdef HAVE_WINDOWS_PLATFORM
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Map build-system platform names to platform types.
|
||||
*/
|
||||
static const struct {
|
||||
_EGLPlatformType platform;
|
||||
const char *name;
|
||||
} egl_platforms[] = {
|
||||
{_EGL_PLATFORM_X11, "x11"},
|
||||
{_EGL_PLATFORM_XCB, "xcb"},
|
||||
{_EGL_PLATFORM_WAYLAND, "wayland"},
|
||||
{_EGL_PLATFORM_DRM, "drm"},
|
||||
{_EGL_PLATFORM_ANDROID, "android"},
|
||||
{_EGL_PLATFORM_HAIKU, "haiku"},
|
||||
{_EGL_PLATFORM_SURFACELESS, "surfaceless"},
|
||||
{_EGL_PLATFORM_DEVICE, "device"},
|
||||
{_EGL_PLATFORM_WINDOWS, "windows"},
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the native platform by parsing EGL_PLATFORM.
|
||||
*/
|
||||
static _EGLPlatformType
|
||||
_eglGetNativePlatformFromEnv(void)
|
||||
{
|
||||
_EGLPlatformType plat = _EGL_INVALID_PLATFORM;
|
||||
const char *plat_name;
|
||||
EGLint i;
|
||||
|
||||
static_assert(ARRAY_SIZE(egl_platforms) == _EGL_NUM_PLATFORMS,
|
||||
"Missing platform");
|
||||
|
||||
plat_name = os_get_option("EGL_PLATFORM");
|
||||
/* try deprecated env variable */
|
||||
if (!plat_name || !plat_name[0])
|
||||
plat_name = os_get_option("EGL_DISPLAY");
|
||||
if (!plat_name || !plat_name[0])
|
||||
return _EGL_INVALID_PLATFORM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(egl_platforms); i++) {
|
||||
if (strcmp(egl_platforms[i].name, plat_name) == 0) {
|
||||
plat = egl_platforms[i].platform;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (plat == _EGL_INVALID_PLATFORM)
|
||||
_eglLog(_EGL_WARNING, "invalid EGL_PLATFORM given");
|
||||
|
||||
return plat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try detecting native platform with the help of native display characteristics.
|
||||
*/
|
||||
static _EGLPlatformType
|
||||
_eglNativePlatformDetectNativeDisplay(void *nativeDisplay)
|
||||
{
|
||||
if (nativeDisplay == EGL_DEFAULT_DISPLAY)
|
||||
return _EGL_INVALID_PLATFORM;
|
||||
|
||||
#ifdef HAVE_WINDOWS_PLATFORM
|
||||
if (GetObjectType(nativeDisplay) == OBJ_DC)
|
||||
return _EGL_PLATFORM_WINDOWS;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM)
|
||||
if (_eglPointerIsDereferenceable(nativeDisplay)) {
|
||||
void *first_pointer = *(void **)nativeDisplay;
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
/* wl_display is a wl_proxy, which is a wl_object.
|
||||
* wl_object's first element points to the interfacetype. */
|
||||
if (first_pointer == &wl_display_interface)
|
||||
return _EGL_PLATFORM_WAYLAND;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
/* gbm has a pointer to its constructor as first element. */
|
||||
if (first_pointer == gbm_create_device)
|
||||
return _EGL_PLATFORM_DRM;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return _EGL_INVALID_PLATFORM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the native platform. It is the platform of the EGL native types.
|
||||
*/
|
||||
_EGLPlatformType
|
||||
_eglGetNativePlatform(void *nativeDisplay)
|
||||
{
|
||||
_EGLPlatformType detected_platform = _eglGetNativePlatformFromEnv();
|
||||
const char *detection_method = "environment";
|
||||
|
||||
if (detected_platform == _EGL_INVALID_PLATFORM) {
|
||||
detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
|
||||
detection_method = "autodetected";
|
||||
}
|
||||
|
||||
if (detected_platform == _EGL_INVALID_PLATFORM) {
|
||||
detected_platform = _EGL_NATIVE_PLATFORM;
|
||||
detection_method = "build-time configuration";
|
||||
}
|
||||
|
||||
_eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
|
||||
egl_platforms[detected_platform].name, detection_method);
|
||||
|
||||
return detected_platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish display management.
|
||||
*/
|
||||
void
|
||||
_eglFiniDisplay(void)
|
||||
{
|
||||
_EGLDisplay *dispList, *disp;
|
||||
|
||||
/* atexit function is called with global mutex locked */
|
||||
dispList = _eglGlobal.DisplayList;
|
||||
while (dispList) {
|
||||
EGLint i;
|
||||
|
||||
/* pop list head */
|
||||
disp = dispList;
|
||||
dispList = dispList->Next;
|
||||
|
||||
for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
|
||||
if (disp->ResourceLists[i]) {
|
||||
_eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", disp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The fcntl() code in _eglGetDeviceDisplay() ensures that valid fd >= 3,
|
||||
* and invalid one is 0.
|
||||
*/
|
||||
if (disp->Options.fd)
|
||||
close(disp->Options.fd);
|
||||
|
||||
free(disp->Options.Attribs);
|
||||
free(disp);
|
||||
}
|
||||
_eglGlobal.DisplayList = NULL;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
_eglSameAttribs(const EGLAttrib *a, const EGLAttrib *b)
|
||||
{
|
||||
size_t na = _eglNumAttribs(a);
|
||||
size_t nb = _eglNumAttribs(b);
|
||||
|
||||
/* different numbers of attributes must be different */
|
||||
if (na != nb)
|
||||
return EGL_FALSE;
|
||||
|
||||
/* both lists NULL are the same */
|
||||
if (!a && !b)
|
||||
return EGL_TRUE;
|
||||
|
||||
/* otherwise, compare the lists */
|
||||
return memcmp(a, b, na * sizeof(a[0])) == 0 ? EGL_TRUE : EGL_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the display corresponding to the specified native display, or create a
|
||||
* new one. EGL 1.5 says:
|
||||
*
|
||||
* Multiple calls made to eglGetPlatformDisplay with the same parameters
|
||||
* will return the same EGLDisplay handle.
|
||||
*
|
||||
* We read this extremely strictly, and treat a call with NULL attribs as
|
||||
* different from a call with attribs only equal to { EGL_NONE }. Similarly
|
||||
* we do not sort the attribute list, so even if all attribute _values_ are
|
||||
* identical, different attribute orders will be considered different
|
||||
* parameters.
|
||||
*/
|
||||
_EGLDisplay *
|
||||
_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy,
|
||||
const EGLAttrib *attrib_list)
|
||||
{
|
||||
_EGLDisplay *disp;
|
||||
size_t num_attribs;
|
||||
|
||||
if (plat == _EGL_INVALID_PLATFORM)
|
||||
return NULL;
|
||||
|
||||
simple_mtx_lock(_eglGlobal.Mutex);
|
||||
|
||||
/* search the display list first */
|
||||
for (disp = _eglGlobal.DisplayList; disp; disp = disp->Next) {
|
||||
if (disp->Platform == plat && disp->PlatformDisplay == plat_dpy &&
|
||||
_eglSameAttribs(disp->Options.Attribs, attrib_list))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* create a new display */
|
||||
assert(!disp);
|
||||
disp = calloc(1, sizeof(_EGLDisplay));
|
||||
if (!disp)
|
||||
goto out;
|
||||
|
||||
simple_mtx_init(&disp->Mutex, mtx_plain);
|
||||
u_rwlock_init(&disp->TerminateLock);
|
||||
disp->Platform = plat;
|
||||
disp->PlatformDisplay = plat_dpy;
|
||||
num_attribs = _eglNumAttribs(attrib_list);
|
||||
if (num_attribs) {
|
||||
disp->Options.Attribs = calloc(num_attribs, sizeof(EGLAttrib));
|
||||
if (!disp->Options.Attribs) {
|
||||
free(disp);
|
||||
disp = NULL;
|
||||
goto out;
|
||||
}
|
||||
memcpy(disp->Options.Attribs, attrib_list,
|
||||
num_attribs * sizeof(EGLAttrib));
|
||||
}
|
||||
|
||||
/* add to the display list */
|
||||
disp->Next = _eglGlobal.DisplayList;
|
||||
_eglGlobal.DisplayList = disp;
|
||||
|
||||
out:
|
||||
simple_mtx_unlock(_eglGlobal.Mutex);
|
||||
|
||||
return disp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the contexts and surfaces that are linked to the display.
|
||||
*/
|
||||
void
|
||||
_eglReleaseDisplayResources(_EGLDisplay *display)
|
||||
{
|
||||
_EGLResource *list;
|
||||
const _EGLDriver *drv = display->Driver;
|
||||
|
||||
simple_mtx_assert_locked(&display->Mutex);
|
||||
|
||||
list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
|
||||
while (list) {
|
||||
_EGLContext *ctx = (_EGLContext *)list;
|
||||
list = list->Next;
|
||||
|
||||
_eglUnlinkContext(ctx);
|
||||
drv->DestroyContext(display, ctx);
|
||||
}
|
||||
assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
|
||||
|
||||
list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
|
||||
while (list) {
|
||||
_EGLSurface *surf = (_EGLSurface *)list;
|
||||
list = list->Next;
|
||||
|
||||
_eglUnlinkSurface(surf);
|
||||
drv->DestroySurface(display, surf);
|
||||
}
|
||||
assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
|
||||
|
||||
list = display->ResourceLists[_EGL_RESOURCE_IMAGE];
|
||||
while (list) {
|
||||
_EGLImage *image = (_EGLImage *)list;
|
||||
list = list->Next;
|
||||
|
||||
_eglUnlinkImage(image);
|
||||
drv->DestroyImageKHR(display, image);
|
||||
}
|
||||
assert(!display->ResourceLists[_EGL_RESOURCE_IMAGE]);
|
||||
|
||||
list = display->ResourceLists[_EGL_RESOURCE_SYNC];
|
||||
while (list) {
|
||||
_EGLSync *sync = (_EGLSync *)list;
|
||||
list = list->Next;
|
||||
|
||||
_eglUnlinkSync(sync);
|
||||
drv->DestroySyncKHR(display, sync);
|
||||
}
|
||||
assert(!display->ResourceLists[_EGL_RESOURCE_SYNC]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all the data hanging of an _EGLDisplay object, but not
|
||||
* the object itself.
|
||||
*/
|
||||
void
|
||||
_eglCleanupDisplay(_EGLDisplay *disp)
|
||||
{
|
||||
if (disp->Configs) {
|
||||
_eglDestroyArray(disp->Configs, free);
|
||||
disp->Configs = NULL;
|
||||
}
|
||||
|
||||
/* XXX incomplete */
|
||||
}
|
||||
|
||||
/**
|
||||
* Return EGL_TRUE if the given resource is valid. That is, the display does
|
||||
* own the resource.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *disp)
|
||||
{
|
||||
_EGLResource *list = disp->ResourceLists[type];
|
||||
|
||||
simple_mtx_assert_locked(&disp->Mutex);
|
||||
|
||||
if (!res)
|
||||
return EGL_FALSE;
|
||||
|
||||
while (list) {
|
||||
if (res == (void *)list) {
|
||||
assert(list->Display == disp);
|
||||
break;
|
||||
}
|
||||
list = list->Next;
|
||||
}
|
||||
|
||||
return (list != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a display resource. The size of the subclass object is
|
||||
* specified.
|
||||
*
|
||||
* This is supposed to be called from the initializers of subclasses, such as
|
||||
* _eglInitContext or _eglInitSurface.
|
||||
*/
|
||||
void
|
||||
_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *disp)
|
||||
{
|
||||
memset(res, 0, size);
|
||||
res->Display = disp;
|
||||
res->RefCount = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment reference count for the resource.
|
||||
*/
|
||||
void
|
||||
_eglGetResource(_EGLResource *res)
|
||||
{
|
||||
assert(res && res->RefCount > 0);
|
||||
p_atomic_inc(&res->RefCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement reference count for the resource.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglPutResource(_EGLResource *res)
|
||||
{
|
||||
assert(res && res->RefCount > 0);
|
||||
return p_atomic_dec_zero(&res->RefCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a resource to its display.
|
||||
*/
|
||||
void
|
||||
_eglLinkResource(_EGLResource *res, _EGLResourceType type)
|
||||
{
|
||||
assert(res->Display);
|
||||
simple_mtx_assert_locked(&res->Display->Mutex);
|
||||
|
||||
res->IsLinked = EGL_TRUE;
|
||||
res->Next = res->Display->ResourceLists[type];
|
||||
res->Display->ResourceLists[type] = res;
|
||||
_eglGetResource(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a linked resource from its display.
|
||||
*/
|
||||
void
|
||||
_eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
|
||||
{
|
||||
_EGLResource *prev;
|
||||
|
||||
simple_mtx_assert_locked(&res->Display->Mutex);
|
||||
|
||||
prev = res->Display->ResourceLists[type];
|
||||
if (prev != res) {
|
||||
while (prev) {
|
||||
if (prev->Next == res)
|
||||
break;
|
||||
prev = prev->Next;
|
||||
}
|
||||
assert(prev);
|
||||
prev->Next = res->Next;
|
||||
} else {
|
||||
res->Display->ResourceLists[type] = res->Next;
|
||||
}
|
||||
|
||||
res->Next = NULL;
|
||||
res->IsLinked = EGL_FALSE;
|
||||
_eglPutResource(res);
|
||||
|
||||
/* We always unlink before destroy. The driver still owns a reference */
|
||||
assert(res->RefCount);
|
||||
}
|
||||
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
_EGLDisplay *
|
||||
_eglGetX11Display(Display *native_display, const EGLAttrib *attrib_list)
|
||||
{
|
||||
_EGLDisplay *dpy;
|
||||
_EGLDevice *dev = NULL;
|
||||
|
||||
/* EGL_EXT_platform_x11 adds EGL_PLATFORM_X11_SCREEN_EXT,
|
||||
* which is optional.
|
||||
*/
|
||||
if (attrib_list != NULL) {
|
||||
for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
|
||||
EGLAttrib attrib = attrib_list[i];
|
||||
EGLAttrib value = attrib_list[i + 1];
|
||||
|
||||
switch (attrib) {
|
||||
case EGL_DEVICE_EXT:
|
||||
dev = _eglLookupDevice((void *)value);
|
||||
if (!dev) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
/* EGL_EXT_platform_x11 adds EGL_PLATFORM_X11_SCREEN_EXT,
|
||||
* which is optional.
|
||||
*/
|
||||
case EGL_PLATFORM_X11_SCREEN_EXT:
|
||||
break;
|
||||
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dpy = _eglFindDisplay(_EGL_PLATFORM_X11, native_display, attrib_list);
|
||||
if (dpy) {
|
||||
dpy->Device = dev;
|
||||
}
|
||||
|
||||
return dpy;
|
||||
}
|
||||
#endif /* HAVE_X11_PLATFORM */
|
||||
|
||||
#ifdef HAVE_XCB_PLATFORM
|
||||
_EGLDisplay *
|
||||
_eglGetXcbDisplay(xcb_connection_t *native_display,
|
||||
const EGLAttrib *attrib_list)
|
||||
{
|
||||
_EGLDisplay *dpy;
|
||||
_EGLDevice *dev = NULL;
|
||||
|
||||
/* EGL_EXT_platform_xcb recognizes exactly one attribute,
|
||||
* EGL_PLATFORM_XCB_SCREEN_EXT, which is optional.
|
||||
*/
|
||||
if (attrib_list != NULL) {
|
||||
for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
|
||||
EGLAttrib attrib = attrib_list[i];
|
||||
EGLAttrib value = attrib_list[i + 1];
|
||||
|
||||
switch (attrib) {
|
||||
case EGL_DEVICE_EXT:
|
||||
dev = _eglLookupDevice((void *)value);
|
||||
if (!dev) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case EGL_PLATFORM_XCB_SCREEN_EXT:
|
||||
break;
|
||||
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dpy = _eglFindDisplay(_EGL_PLATFORM_XCB, native_display, attrib_list);
|
||||
if (dpy) {
|
||||
dpy->Device = dev;
|
||||
}
|
||||
|
||||
return dpy;
|
||||
}
|
||||
#endif /* HAVE_XCB_PLATFORM */
|
||||
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
_EGLDisplay *
|
||||
_eglGetGbmDisplay(struct gbm_device *native_display,
|
||||
const EGLAttrib *attrib_list)
|
||||
{
|
||||
_EGLDisplay *dpy;
|
||||
_EGLDevice *dev = NULL;
|
||||
|
||||
/* This platform recognizes only EXT_explicit_device */
|
||||
if (attrib_list) {
|
||||
for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
|
||||
EGLAttrib attrib = attrib_list[i];
|
||||
EGLAttrib value = attrib_list[i + 1];
|
||||
|
||||
switch (attrib) {
|
||||
case EGL_DEVICE_EXT:
|
||||
dev = _eglLookupDevice((void *)value);
|
||||
if (!dev) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, native_display, attrib_list);
|
||||
if (dpy) {
|
||||
dpy->Device = dev;
|
||||
}
|
||||
|
||||
return dpy;
|
||||
}
|
||||
#endif /* HAVE_DRM_PLATFORM */
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
_EGLDisplay *
|
||||
_eglGetWaylandDisplay(struct wl_display *native_display,
|
||||
const EGLAttrib *attrib_list)
|
||||
{
|
||||
_EGLDisplay *dpy;
|
||||
_EGLDevice *dev = NULL;
|
||||
|
||||
/* This platform recognizes only EXT_explicit_device */
|
||||
if (attrib_list) {
|
||||
for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
|
||||
EGLAttrib attrib = attrib_list[i];
|
||||
EGLAttrib value = attrib_list[i + 1];
|
||||
|
||||
switch (attrib) {
|
||||
case EGL_DEVICE_EXT:
|
||||
dev = _eglLookupDevice((void *)value);
|
||||
if (!dev) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dpy = _eglFindDisplay(_EGL_PLATFORM_WAYLAND, native_display, attrib_list);
|
||||
if (dpy) {
|
||||
dpy->Device = dev;
|
||||
}
|
||||
|
||||
return dpy;
|
||||
}
|
||||
#endif /* HAVE_WAYLAND_PLATFORM */
|
||||
|
||||
_EGLDisplay *
|
||||
_eglGetSurfacelessDisplay(void *native_display, const EGLAttrib *attrib_list)
|
||||
{
|
||||
_EGLDisplay *dpy;
|
||||
_EGLDevice *dev = NULL;
|
||||
|
||||
/* Any native display must be an EGLDeviceEXT we know about */
|
||||
if (native_display != NULL) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This platform recognizes only EXT_explicit_device */
|
||||
if (attrib_list) {
|
||||
for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
|
||||
EGLAttrib attrib = attrib_list[i];
|
||||
EGLAttrib value = attrib_list[i + 1];
|
||||
|
||||
switch (attrib) {
|
||||
case EGL_DEVICE_EXT:
|
||||
dev = _eglLookupDevice((void *)value);
|
||||
if (!dev) {
|
||||
_eglError(EGL_BAD_DEVICE_EXT, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dpy = _eglFindDisplay(_EGL_PLATFORM_SURFACELESS, NULL, attrib_list);
|
||||
if (dpy) {
|
||||
dpy->Device = dev;
|
||||
}
|
||||
|
||||
return dpy;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ANDROID_PLATFORM
|
||||
_EGLDisplay *
|
||||
_eglGetAndroidDisplay(void *native_display, const EGLAttrib *attrib_list)
|
||||
{
|
||||
|
||||
/* This platform recognizes no display attributes. */
|
||||
if (attrib_list != NULL && attrib_list[0] != EGL_NONE) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _eglFindDisplay(_EGL_PLATFORM_ANDROID, native_display, attrib_list);
|
||||
}
|
||||
#endif /* HAVE_ANDROID_PLATFORM */
|
||||
|
||||
_EGLDisplay *
|
||||
_eglGetDeviceDisplay(void *native_display, const EGLAttrib *attrib_list)
|
||||
{
|
||||
_EGLDevice *dev;
|
||||
_EGLDisplay *display;
|
||||
int fd = -1;
|
||||
|
||||
dev = _eglLookupDevice(native_display);
|
||||
if (!dev) {
|
||||
_eglError(EGL_BAD_PARAMETER, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (attrib_list) {
|
||||
for (int i = 0; attrib_list[i] != EGL_NONE; i += 2) {
|
||||
EGLAttrib attrib = attrib_list[i];
|
||||
EGLAttrib value = attrib_list[i + 1];
|
||||
|
||||
/* EGL_EXT_platform_device does not recognize any attributes,
|
||||
* EGL_EXT_device_drm adds the optional EGL_DRM_MASTER_FD_EXT.
|
||||
*/
|
||||
|
||||
if (!_eglDeviceSupports(dev, _EGL_DEVICE_DRM) ||
|
||||
attrib != EGL_DRM_MASTER_FD_EXT) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = (int)value;
|
||||
}
|
||||
}
|
||||
|
||||
display = _eglFindDisplay(_EGL_PLATFORM_DEVICE, native_display, attrib_list);
|
||||
if (!display) {
|
||||
_eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the fd is explicitly provided and we did not dup() it yet, do so.
|
||||
* The spec mandates that we do so, since we'll need it past the
|
||||
* eglGetPlatformDisplay call.
|
||||
*
|
||||
* The new fd is guaranteed to be 3 or greater.
|
||||
*/
|
||||
if (fd != -1 && display->Options.fd == 0) {
|
||||
display->Options.fd = os_dupfd_cloexec(fd);
|
||||
if (display->Options.fd == -1) {
|
||||
/* Do not (really) need to teardown the display */
|
||||
_eglError(EGL_BAD_ALLOC, "eglGetPlatformDisplay");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
@@ -0,0 +1,361 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLDISPLAY_INCLUDED
|
||||
#define EGLDISPLAY_INCLUDED
|
||||
|
||||
#include "util/rwlock.h"
|
||||
#include "util/simple_mtx.h"
|
||||
|
||||
#include "eglarray.h"
|
||||
#include "egldefines.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum _egl_platform_type {
|
||||
_EGL_PLATFORM_X11,
|
||||
_EGL_PLATFORM_XCB,
|
||||
_EGL_PLATFORM_WAYLAND,
|
||||
_EGL_PLATFORM_DRM,
|
||||
_EGL_PLATFORM_ANDROID,
|
||||
_EGL_PLATFORM_HAIKU,
|
||||
_EGL_PLATFORM_SURFACELESS,
|
||||
_EGL_PLATFORM_DEVICE,
|
||||
_EGL_PLATFORM_WINDOWS,
|
||||
|
||||
_EGL_NUM_PLATFORMS,
|
||||
_EGL_INVALID_PLATFORM = -1
|
||||
};
|
||||
typedef enum _egl_platform_type _EGLPlatformType;
|
||||
|
||||
enum _egl_resource_type {
|
||||
_EGL_RESOURCE_CONTEXT,
|
||||
_EGL_RESOURCE_SURFACE,
|
||||
_EGL_RESOURCE_IMAGE,
|
||||
_EGL_RESOURCE_SYNC,
|
||||
|
||||
_EGL_NUM_RESOURCES
|
||||
};
|
||||
/* this cannot and need not go into egltypedefs.h */
|
||||
typedef enum _egl_resource_type _EGLResourceType;
|
||||
|
||||
/**
|
||||
* A resource of a display.
|
||||
*/
|
||||
struct _egl_resource {
|
||||
/* which display the resource belongs to */
|
||||
_EGLDisplay *Display;
|
||||
EGLBoolean IsLinked;
|
||||
EGLint RefCount;
|
||||
|
||||
EGLLabelKHR Label;
|
||||
|
||||
/* used to link resources of the same type */
|
||||
_EGLResource *Next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Optional EGL extensions info.
|
||||
*/
|
||||
struct _egl_extensions {
|
||||
/* Please keep these sorted alphabetically. */
|
||||
EGLBoolean ANDROID_blob_cache;
|
||||
EGLBoolean ANDROID_framebuffer_target;
|
||||
EGLBoolean ANDROID_image_native_buffer;
|
||||
EGLBoolean ANDROID_native_fence_sync;
|
||||
EGLBoolean ANDROID_recordable;
|
||||
|
||||
EGLBoolean ANGLE_sync_control_rate;
|
||||
EGLBoolean CHROMIUM_sync_control;
|
||||
|
||||
EGLBoolean EXT_buffer_age;
|
||||
EGLBoolean EXT_config_select_group;
|
||||
EGLBoolean EXT_create_context_robustness;
|
||||
EGLBoolean EXT_image_dma_buf_import;
|
||||
EGLBoolean EXT_image_dma_buf_import_modifiers;
|
||||
EGLBoolean EXT_pixel_format_float;
|
||||
EGLBoolean EXT_present_opaque;
|
||||
EGLBoolean EXT_protected_content;
|
||||
EGLBoolean EXT_protected_surface;
|
||||
EGLBoolean EXT_query_reset_notification_strategy;
|
||||
EGLBoolean EXT_surface_compression;
|
||||
EGLBoolean EXT_surface_CTA861_3_metadata;
|
||||
EGLBoolean EXT_surface_SMPTE2086_metadata;
|
||||
EGLBoolean EXT_swap_buffers_with_damage;
|
||||
|
||||
unsigned int IMG_context_priority;
|
||||
#define __EGL_CONTEXT_PRIORITY_LOW_BIT 0
|
||||
#define __EGL_CONTEXT_PRIORITY_MEDIUM_BIT 1
|
||||
#define __EGL_CONTEXT_PRIORITY_HIGH_BIT 2
|
||||
#define __EGL_CONTEXT_PRIORITY_REALTIME_BIT 3
|
||||
|
||||
EGLBoolean KHR_cl_event2;
|
||||
EGLBoolean KHR_config_attribs;
|
||||
EGLBoolean KHR_context_flush_control;
|
||||
EGLBoolean KHR_create_context;
|
||||
EGLBoolean KHR_create_context_no_error;
|
||||
EGLBoolean KHR_fence_sync;
|
||||
EGLBoolean KHR_get_all_proc_addresses;
|
||||
EGLBoolean KHR_gl_colorspace;
|
||||
EGLBoolean KHR_gl_renderbuffer_image;
|
||||
EGLBoolean KHR_gl_texture_2D_image;
|
||||
EGLBoolean KHR_gl_texture_3D_image;
|
||||
EGLBoolean KHR_gl_texture_cubemap_image;
|
||||
EGLBoolean KHR_image;
|
||||
EGLBoolean KHR_image_base;
|
||||
EGLBoolean KHR_image_pixmap;
|
||||
EGLBoolean KHR_mutable_render_buffer;
|
||||
EGLBoolean KHR_no_config_context;
|
||||
EGLBoolean KHR_partial_update;
|
||||
EGLBoolean KHR_reusable_sync;
|
||||
EGLBoolean KHR_surfaceless_context;
|
||||
EGLBoolean KHR_wait_sync;
|
||||
|
||||
EGLBoolean MESA_gl_interop;
|
||||
EGLBoolean MESA_image_dma_buf_export;
|
||||
EGLBoolean MESA_query_driver;
|
||||
EGLBoolean MESA_x11_native_visual_id;
|
||||
|
||||
EGLBoolean NOK_texture_from_pixmap;
|
||||
|
||||
EGLBoolean NV_context_priority_realtime;
|
||||
|
||||
EGLBoolean WL_bind_wayland_display;
|
||||
EGLBoolean WL_create_wayland_buffer_from_image;
|
||||
};
|
||||
|
||||
struct _egl_display {
|
||||
/* used to link displays */
|
||||
_EGLDisplay *Next;
|
||||
|
||||
/**
|
||||
* The big-display-lock (BDL) which protects our internal state. EGL
|
||||
* drivers should use their own locking, as needed, to protect their
|
||||
* own state, rather than relying on this.
|
||||
*/
|
||||
simple_mtx_t Mutex;
|
||||
|
||||
/**
|
||||
* The spec appears to allow eglTerminate() to race with more or less
|
||||
* any other egl call. To allow for this, while relaxing the BDL to
|
||||
* allow other egl calls to happen in parallel, a rwlock is used. All
|
||||
* points where the BDL lock is acquired also acquire TerminateLock
|
||||
* for reading, while eglTerminate() itself acquires the TerminateLock
|
||||
* for writing.
|
||||
*
|
||||
* Note, we could conceivably just replace the BDL with a single
|
||||
* rwlock. But there are a couple shortcomings of u_rwlock:
|
||||
*
|
||||
* 1) The WIN32 implementation does not allow promoting a read-
|
||||
* lock to write-lock, nor recursive locking, whereas the
|
||||
* pthread based implementation does. Because of this, it
|
||||
* would be difficult to keep the eglapi layer portable if
|
||||
* we depended on any less-than-trivial rwlock usage.
|
||||
*
|
||||
* 2) We'd lose simple_mtx_assert_locked().
|
||||
*/
|
||||
struct u_rwlock TerminateLock;
|
||||
|
||||
_EGLPlatformType Platform; /**< The type of the platform display */
|
||||
void *PlatformDisplay; /**< A pointer to the platform display */
|
||||
|
||||
_EGLDevice *Device; /**< Device backing the display */
|
||||
const _EGLDriver *Driver; /**< Matched driver of the display */
|
||||
EGLBoolean Initialized; /**< True if the display is initialized */
|
||||
|
||||
/* options that affect how the driver initializes the display */
|
||||
struct {
|
||||
EGLBoolean Zink; /**< Use kopper only */
|
||||
EGLBoolean ForceSoftware; /**< Use software path only */
|
||||
EGLBoolean GalliumHudWarn; /**< Using hud, warn when querying buffer age */
|
||||
EGLAttrib *Attribs; /**< Platform-specific options */
|
||||
int fd; /**< Platform device specific, local fd */
|
||||
} Options;
|
||||
|
||||
/* these fields are set by the driver during init */
|
||||
void *DriverData; /**< Driver private data */
|
||||
EGLint Version; /**< EGL version major*10+minor */
|
||||
EGLint ClientAPIs; /**< Bitmask of APIs supported (EGL_xxx_BIT) */
|
||||
_EGLExtensions Extensions; /**< Extensions supported */
|
||||
EGLBoolean RobustBufferAccess; /**< Supports robust buffer access behavior */
|
||||
|
||||
/* these fields are derived from above */
|
||||
char VersionString[100]; /**< EGL_VERSION */
|
||||
char ClientAPIsString[100]; /**< EGL_CLIENT_APIS */
|
||||
char ExtensionsString[_EGL_MAX_EXTENSIONS_LEN]; /**< EGL_EXTENSIONS */
|
||||
|
||||
_EGLArray *Configs;
|
||||
|
||||
/* lists of resources */
|
||||
_EGLResource *ResourceLists[_EGL_NUM_RESOURCES];
|
||||
|
||||
EGLLabelKHR Label;
|
||||
|
||||
EGLSetBlobFuncANDROID BlobCacheSet;
|
||||
EGLGetBlobFuncANDROID BlobCacheGet;
|
||||
};
|
||||
|
||||
extern _EGLDisplay *
|
||||
_eglLockDisplay(EGLDisplay dpy);
|
||||
|
||||
extern void
|
||||
_eglUnlockDisplay(_EGLDisplay *disp);
|
||||
|
||||
extern _EGLPlatformType
|
||||
_eglGetNativePlatform(void *nativeDisplay);
|
||||
|
||||
extern void
|
||||
_eglFiniDisplay(void);
|
||||
|
||||
extern _EGLDisplay *
|
||||
_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy, const EGLAttrib *attr);
|
||||
|
||||
extern void
|
||||
_eglReleaseDisplayResources(_EGLDisplay *disp);
|
||||
|
||||
extern void
|
||||
_eglCleanupDisplay(_EGLDisplay *disp);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *disp);
|
||||
|
||||
/**
|
||||
* Return the handle of a linked display, or EGL_NO_DISPLAY.
|
||||
*/
|
||||
static inline EGLDisplay
|
||||
_eglGetDisplayHandle(_EGLDisplay *disp)
|
||||
{
|
||||
return (EGLDisplay)((disp) ? disp : EGL_NO_DISPLAY);
|
||||
}
|
||||
|
||||
static inline EGLBoolean
|
||||
_eglHasAttrib(_EGLDisplay *disp, EGLAttrib attrib)
|
||||
{
|
||||
EGLAttrib *attribs = disp->Options.Attribs;
|
||||
|
||||
if (!attribs) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
for (int i = 0; attribs[i] != EGL_NONE; i += 2) {
|
||||
if (attrib == attribs[i]) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
}
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
extern void
|
||||
_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *disp);
|
||||
|
||||
extern void
|
||||
_eglGetResource(_EGLResource *res);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglPutResource(_EGLResource *res);
|
||||
|
||||
extern void
|
||||
_eglLinkResource(_EGLResource *res, _EGLResourceType type);
|
||||
|
||||
extern void
|
||||
_eglUnlinkResource(_EGLResource *res, _EGLResourceType type);
|
||||
|
||||
/**
|
||||
* Return true if the resource is linked.
|
||||
*/
|
||||
static inline EGLBoolean
|
||||
_eglIsResourceLinked(_EGLResource *res)
|
||||
{
|
||||
return res->IsLinked;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
_eglNumAttribs(const EGLAttrib *attribs)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (attribs) {
|
||||
while (attribs[len] != EGL_NONE)
|
||||
len += 2;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
_EGLDisplay *
|
||||
_eglGetX11Display(Display *native_display, const EGLAttrib *attrib_list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XCB_PLATFORM
|
||||
typedef struct xcb_connection_t xcb_connection_t;
|
||||
_EGLDisplay *
|
||||
_eglGetXcbDisplay(xcb_connection_t *native_display,
|
||||
const EGLAttrib *attrib_list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
struct gbm_device;
|
||||
|
||||
_EGLDisplay *
|
||||
_eglGetGbmDisplay(struct gbm_device *native_display,
|
||||
const EGLAttrib *attrib_list);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
struct wl_display;
|
||||
|
||||
_EGLDisplay *
|
||||
_eglGetWaylandDisplay(struct wl_display *native_display,
|
||||
const EGLAttrib *attrib_list);
|
||||
#endif
|
||||
|
||||
_EGLDisplay *
|
||||
_eglGetSurfacelessDisplay(void *native_display, const EGLAttrib *attrib_list);
|
||||
|
||||
#ifdef HAVE_ANDROID_PLATFORM
|
||||
_EGLDisplay *
|
||||
_eglGetAndroidDisplay(void *native_display, const EGLAttrib *attrib_list);
|
||||
#endif
|
||||
|
||||
_EGLDisplay *
|
||||
_eglGetDeviceDisplay(void *native_display, const EGLAttrib *attrib_list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLDISPLAY_INCLUDED */
|
||||
@@ -0,0 +1,246 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLDRIVER_INCLUDED
|
||||
#define EGLDRIVER_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Define an inline driver typecast function.
|
||||
*
|
||||
* Note that this macro defines a function and should not be ended with a
|
||||
* semicolon when used.
|
||||
*/
|
||||
#define _EGL_DRIVER_TYPECAST(drvtype, egltype, code) \
|
||||
static inline struct drvtype *drvtype(const egltype *obj) \
|
||||
{ \
|
||||
return (struct drvtype *)code; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the driver typecast functions for _EGLDisplay,
|
||||
* _EGLContext, _EGLSurface, and _EGLConfig.
|
||||
*
|
||||
* Note that this macro defines several functions and should not be ended with
|
||||
* a semicolon when used.
|
||||
*/
|
||||
#define _EGL_DRIVER_STANDARD_TYPECASTS(drvname) \
|
||||
/* note that this is not a direct cast */ \
|
||||
_EGL_DRIVER_TYPECAST(drvname##_display, _EGLDisplay, obj->DriverData) \
|
||||
_EGL_DRIVER_TYPECAST(drvname##_context, _EGLContext, obj) \
|
||||
_EGL_DRIVER_TYPECAST(drvname##_surface, _EGLSurface, obj) \
|
||||
_EGL_DRIVER_TYPECAST(drvname##_config, _EGLConfig, obj)
|
||||
|
||||
/**
|
||||
* A generic function ptr type
|
||||
*/
|
||||
typedef void (*_EGLProc)(void);
|
||||
|
||||
struct wl_display;
|
||||
struct mesa_glinterop_device_info;
|
||||
struct mesa_glinterop_export_in;
|
||||
struct mesa_glinterop_export_out;
|
||||
struct mesa_glinterop_flush_out;
|
||||
typedef struct __GLsync *GLsync;
|
||||
|
||||
#define EGL_UUID_SIZE 16
|
||||
|
||||
/**
|
||||
* For use in EGL_EXT_device_query_name and EGL_EXT_device_persistent_id
|
||||
*/
|
||||
struct egl_device_info {
|
||||
uint8_t device_uuid[EGL_UUID_SIZE];
|
||||
uint8_t driver_uuid[EGL_UUID_SIZE];
|
||||
/* Data below needs to be freed manually */
|
||||
char *vendor_name;
|
||||
char *renderer_name;
|
||||
char *driver_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* The API dispatcher jumps through these functions
|
||||
*/
|
||||
struct _egl_driver {
|
||||
/* driver funcs */
|
||||
EGLBoolean (*Initialize)(_EGLDisplay *disp);
|
||||
EGLBoolean (*Terminate)(_EGLDisplay *disp);
|
||||
|
||||
/* context funcs */
|
||||
_EGLContext *(*CreateContext)(_EGLDisplay *disp, _EGLConfig *config,
|
||||
_EGLContext *share_list,
|
||||
const EGLint *attrib_list);
|
||||
EGLBoolean (*DestroyContext)(_EGLDisplay *disp, _EGLContext *ctx);
|
||||
/* this is the only function (other than Initialize) that may be called
|
||||
* with an uninitialized display
|
||||
*/
|
||||
EGLBoolean (*MakeCurrent)(_EGLDisplay *disp, _EGLSurface *draw,
|
||||
_EGLSurface *read, _EGLContext *ctx);
|
||||
|
||||
/* surface funcs */
|
||||
_EGLSurface *(*CreateWindowSurface)(_EGLDisplay *disp, _EGLConfig *config,
|
||||
void *native_window,
|
||||
const EGLint *attrib_list);
|
||||
_EGLSurface *(*CreatePixmapSurface)(_EGLDisplay *disp, _EGLConfig *config,
|
||||
void *native_pixmap,
|
||||
const EGLint *attrib_list);
|
||||
_EGLSurface *(*CreatePbufferSurface)(_EGLDisplay *disp, _EGLConfig *config,
|
||||
const EGLint *attrib_list);
|
||||
EGLBoolean (*DestroySurface)(_EGLDisplay *disp, _EGLSurface *surface);
|
||||
EGLBoolean (*QuerySurface)(_EGLDisplay *disp, _EGLSurface *surface,
|
||||
EGLint attribute, EGLint *value);
|
||||
EGLBoolean (*BindTexImage)(_EGLDisplay *disp, _EGLSurface *surface,
|
||||
EGLint buffer);
|
||||
EGLBoolean (*ReleaseTexImage)(_EGLDisplay *disp, _EGLSurface *surface,
|
||||
EGLint buffer);
|
||||
EGLBoolean (*SwapInterval)(_EGLDisplay *disp, _EGLSurface *surf,
|
||||
EGLint interval);
|
||||
EGLBoolean (*SwapBuffers)(_EGLDisplay *disp, _EGLSurface *draw);
|
||||
EGLBoolean (*CopyBuffers)(_EGLDisplay *disp, _EGLSurface *surface,
|
||||
void *native_pixmap_target);
|
||||
|
||||
/* for EGL_KHR_partial_update */
|
||||
EGLBoolean (*SetDamageRegion)(_EGLDisplay *disp, _EGLSurface *surface,
|
||||
EGLint *rects, EGLint n_rects);
|
||||
|
||||
/* misc functions */
|
||||
EGLBoolean (*WaitClient)(_EGLDisplay *disp, _EGLContext *ctx);
|
||||
EGLBoolean (*WaitNative)(EGLint engine);
|
||||
|
||||
/* for EGL_KHR_image_base */
|
||||
_EGLImage *(*CreateImageKHR)(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
EGLenum target, EGLClientBuffer buffer,
|
||||
const EGLint *attr_list);
|
||||
EGLBoolean (*DestroyImageKHR)(_EGLDisplay *disp, _EGLImage *image);
|
||||
|
||||
/* for EGL_KHR_reusable_sync/EGL_KHR_fence_sync */
|
||||
_EGLSync *(*CreateSyncKHR)(_EGLDisplay *disp, EGLenum type,
|
||||
const EGLAttrib *attrib_list);
|
||||
EGLBoolean (*DestroySyncKHR)(_EGLDisplay *disp, _EGLSync *sync);
|
||||
EGLint (*ClientWaitSyncKHR)(_EGLDisplay *disp, _EGLSync *sync, EGLint flags,
|
||||
EGLTime timeout);
|
||||
EGLint (*WaitSyncKHR)(_EGLDisplay *disp, _EGLSync *sync);
|
||||
/* for EGL_KHR_reusable_sync */
|
||||
EGLBoolean (*SignalSyncKHR)(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode);
|
||||
|
||||
/* for EGL_ANDROID_native_fence_sync */
|
||||
EGLint (*DupNativeFenceFDANDROID)(_EGLDisplay *disp, _EGLSync *sync);
|
||||
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
/* for EGL_WL_bind_wayland_display */
|
||||
EGLBoolean (*BindWaylandDisplayWL)(_EGLDisplay *disp,
|
||||
struct wl_display *display);
|
||||
EGLBoolean (*UnbindWaylandDisplayWL)(_EGLDisplay *disp,
|
||||
struct wl_display *display);
|
||||
EGLBoolean (*QueryWaylandBufferWL)(_EGLDisplay *displ,
|
||||
struct wl_resource *buffer,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
/* for EGL_WL_create_wayland_buffer_from_image */
|
||||
struct wl_buffer *(*CreateWaylandBufferFromImageWL)(_EGLDisplay *disp,
|
||||
_EGLImage *img);
|
||||
#endif
|
||||
|
||||
/* for EGL_EXT_swap_buffers_with_damage */
|
||||
EGLBoolean (*SwapBuffersWithDamageEXT)(_EGLDisplay *disp,
|
||||
_EGLSurface *surface,
|
||||
const EGLint *rects, EGLint n_rects);
|
||||
|
||||
/* for EGL_EXT_buffer_age/EGL_KHR_partial_update */
|
||||
EGLint (*QueryBufferAge)(_EGLDisplay *disp, _EGLSurface *surface);
|
||||
|
||||
/* for EGL_CHROMIUM_sync_control */
|
||||
EGLBoolean (*GetSyncValuesCHROMIUM)(_EGLDisplay *disp, _EGLSurface *surface,
|
||||
EGLuint64KHR *ust, EGLuint64KHR *msc,
|
||||
EGLuint64KHR *sbc);
|
||||
|
||||
EGLBoolean (*GetMscRateANGLE)(_EGLDisplay *disp, _EGLSurface *surface,
|
||||
EGLint *numerator, EGLint *denominator);
|
||||
|
||||
/* for EGL_MESA_image_dma_buf_export */
|
||||
EGLBoolean (*ExportDMABUFImageQueryMESA)(_EGLDisplay *disp, _EGLImage *img,
|
||||
EGLint *fourcc, EGLint *nplanes,
|
||||
EGLuint64KHR *modifiers);
|
||||
EGLBoolean (*ExportDMABUFImageMESA)(_EGLDisplay *disp, _EGLImage *img,
|
||||
EGLint *fds, EGLint *strides,
|
||||
EGLint *offsets);
|
||||
|
||||
/* for EGL_MESA_query_driver */
|
||||
const char *(*QueryDriverName)(_EGLDisplay *disp);
|
||||
char *(*QueryDriverConfig)(_EGLDisplay *disp);
|
||||
|
||||
/* for EGL_EXT_device_query_name and EGL_EXT_device_persistent_id */
|
||||
bool (*QueryDeviceInfo)(const void* driver_device_identifier,
|
||||
struct egl_device_info *device_info);
|
||||
|
||||
/* for OpenGL-OpenCL interop; see include/GL/mesa_glinterop.h */
|
||||
int (*GLInteropQueryDeviceInfo)(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
struct mesa_glinterop_device_info *out);
|
||||
int (*GLInteropExportObject)(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
struct mesa_glinterop_export_in *in,
|
||||
struct mesa_glinterop_export_out *out);
|
||||
int (*GLInteropFlushObjects)(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
unsigned count,
|
||||
struct mesa_glinterop_export_in *in,
|
||||
struct mesa_glinterop_flush_out *out);
|
||||
|
||||
/* for EGL_EXT_image_dma_buf_import_modifiers */
|
||||
EGLBoolean (*QueryDmaBufFormatsEXT)(_EGLDisplay *disp, EGLint max_formats,
|
||||
EGLint *formats, EGLint *num_formats);
|
||||
EGLBoolean (*QueryDmaBufModifiersEXT)(_EGLDisplay *disp, EGLint format,
|
||||
EGLint max_modifiers,
|
||||
EGLuint64KHR *modifiers,
|
||||
EGLBoolean *external_only,
|
||||
EGLint *num_modifiers);
|
||||
|
||||
/* for EGL_ANDROID_blob_cache */
|
||||
void (*SetBlobCacheFuncsANDROID)(_EGLDisplay *disp,
|
||||
EGLSetBlobFuncANDROID set,
|
||||
EGLGetBlobFuncANDROID get);
|
||||
|
||||
/* for EGL_EXT_surface_compression */
|
||||
EGLBoolean (*QuerySupportedCompressionRatesEXT)(_EGLDisplay *disp,
|
||||
_EGLConfig *config,
|
||||
const EGLAttrib *attr_list,
|
||||
EGLint *rates,
|
||||
EGLint rate_size,
|
||||
EGLint *num_rates);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLDRIVER_INCLUDED */
|
||||
@@ -0,0 +1,98 @@
|
||||
/* core functions queryable in the presence of
|
||||
* EGL_KHR_get_all_proc_addresses or EGL 1.5
|
||||
*/
|
||||
/* clang-format off */
|
||||
/* alphabetical order */
|
||||
EGL_ENTRYPOINT(eglBindAPI)
|
||||
EGL_ENTRYPOINT(eglBindTexImage)
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
EGL_ENTRYPOINT(eglBindWaylandDisplayWL)
|
||||
#endif
|
||||
EGL_ENTRYPOINT(eglChooseConfig)
|
||||
EGL_ENTRYPOINT(eglClientWaitSync)
|
||||
EGL_ENTRYPOINT(eglClientWaitSyncKHR)
|
||||
EGL_ENTRYPOINT(eglCopyBuffers)
|
||||
EGL_ENTRYPOINT(eglCreateContext)
|
||||
EGL_ENTRYPOINT(eglCreateImage)
|
||||
EGL_ENTRYPOINT(eglCreateImageKHR)
|
||||
EGL_ENTRYPOINT(eglCreatePbufferFromClientBuffer)
|
||||
EGL_ENTRYPOINT(eglCreatePbufferSurface)
|
||||
EGL_ENTRYPOINT(eglCreatePixmapSurface)
|
||||
EGL_ENTRYPOINT(eglCreatePlatformPixmapSurface)
|
||||
EGL_ENTRYPOINT(eglCreatePlatformPixmapSurfaceEXT)
|
||||
EGL_ENTRYPOINT(eglCreatePlatformWindowSurface)
|
||||
EGL_ENTRYPOINT(eglCreatePlatformWindowSurfaceEXT)
|
||||
EGL_ENTRYPOINT(eglCreateSync)
|
||||
EGL_ENTRYPOINT(eglCreateSync64KHR)
|
||||
EGL_ENTRYPOINT(eglCreateSyncKHR)
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
EGL_ENTRYPOINT(eglCreateWaylandBufferFromImageWL)
|
||||
#endif
|
||||
EGL_ENTRYPOINT(eglCreateWindowSurface)
|
||||
EGL_ENTRYPOINT(eglDebugMessageControlKHR)
|
||||
EGL_ENTRYPOINT(eglDestroyContext)
|
||||
EGL_ENTRYPOINT(eglDestroyImage)
|
||||
EGL_ENTRYPOINT(eglDestroyImageKHR)
|
||||
EGL_ENTRYPOINT(eglDestroySurface)
|
||||
EGL_ENTRYPOINT(eglDestroySync)
|
||||
EGL_ENTRYPOINT(eglDestroySyncKHR)
|
||||
EGL_ENTRYPOINT(eglDupNativeFenceFDANDROID)
|
||||
EGL_ENTRYPOINT(eglExportDMABUFImageMESA)
|
||||
EGL_ENTRYPOINT(eglExportDMABUFImageQueryMESA)
|
||||
EGL_ENTRYPOINT2(eglGLInteropExportObjectMESA, MesaGLInteropEGLExportObject)
|
||||
EGL_ENTRYPOINT2(eglGLInteropFlushObjectsMESA, MesaGLInteropEGLFlushObjects)
|
||||
EGL_ENTRYPOINT2(eglGLInteropQueryDeviceInfoMESA, MesaGLInteropEGLQueryDeviceInfo)
|
||||
EGL_ENTRYPOINT(eglGetConfigAttrib)
|
||||
EGL_ENTRYPOINT(eglGetConfigs)
|
||||
EGL_ENTRYPOINT(eglGetCurrentContext)
|
||||
EGL_ENTRYPOINT(eglGetCurrentDisplay)
|
||||
EGL_ENTRYPOINT(eglGetCurrentSurface)
|
||||
EGL_ENTRYPOINT(eglGetDisplay)
|
||||
EGL_ENTRYPOINT(eglGetDisplayDriverConfig)
|
||||
EGL_ENTRYPOINT(eglGetDisplayDriverName)
|
||||
EGL_ENTRYPOINT(eglGetError)
|
||||
EGL_ENTRYPOINT(eglGetMscRateANGLE)
|
||||
EGL_ENTRYPOINT(eglGetPlatformDisplay)
|
||||
EGL_ENTRYPOINT(eglGetPlatformDisplayEXT)
|
||||
EGL_ENTRYPOINT(eglGetProcAddress)
|
||||
EGL_ENTRYPOINT(eglGetSyncAttrib)
|
||||
EGL_ENTRYPOINT(eglGetSyncAttribKHR)
|
||||
EGL_ENTRYPOINT(eglGetSyncValuesCHROMIUM)
|
||||
EGL_ENTRYPOINT(eglInitialize)
|
||||
EGL_ENTRYPOINT(eglLabelObjectKHR)
|
||||
EGL_ENTRYPOINT(eglMakeCurrent)
|
||||
EGL_ENTRYPOINT(eglQueryAPI)
|
||||
EGL_ENTRYPOINT(eglQueryContext)
|
||||
EGL_ENTRYPOINT(eglQueryDebugKHR)
|
||||
EGL_ENTRYPOINT(eglQueryDeviceAttribEXT)
|
||||
EGL_ENTRYPOINT(eglQueryDeviceBinaryEXT)
|
||||
EGL_ENTRYPOINT(eglQueryDeviceStringEXT)
|
||||
EGL_ENTRYPOINT(eglQueryDevicesEXT)
|
||||
EGL_ENTRYPOINT(eglQueryDisplayAttribEXT)
|
||||
EGL_ENTRYPOINT(eglQueryDmaBufFormatsEXT)
|
||||
EGL_ENTRYPOINT(eglQueryDmaBufModifiersEXT)
|
||||
EGL_ENTRYPOINT(eglQueryString)
|
||||
EGL_ENTRYPOINT(eglQuerySupportedCompressionRatesEXT)
|
||||
EGL_ENTRYPOINT(eglQuerySurface)
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
EGL_ENTRYPOINT(eglQueryWaylandBufferWL)
|
||||
#endif
|
||||
EGL_ENTRYPOINT(eglReleaseTexImage)
|
||||
EGL_ENTRYPOINT(eglReleaseThread)
|
||||
EGL_ENTRYPOINT(eglSetBlobCacheFuncsANDROID)
|
||||
EGL_ENTRYPOINT(eglSetDamageRegionKHR)
|
||||
EGL_ENTRYPOINT(eglSignalSyncKHR)
|
||||
EGL_ENTRYPOINT(eglSurfaceAttrib)
|
||||
EGL_ENTRYPOINT(eglSwapBuffers)
|
||||
EGL_ENTRYPOINT(eglSwapBuffersWithDamageEXT)
|
||||
EGL_ENTRYPOINT(eglSwapBuffersWithDamageKHR)
|
||||
EGL_ENTRYPOINT(eglSwapInterval)
|
||||
EGL_ENTRYPOINT(eglTerminate)
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
EGL_ENTRYPOINT(eglUnbindWaylandDisplayWL)
|
||||
#endif
|
||||
EGL_ENTRYPOINT(eglWaitClient)
|
||||
EGL_ENTRYPOINT(eglWaitGL)
|
||||
EGL_ENTRYPOINT(eglWaitNative)
|
||||
EGL_ENTRYPOINT(eglWaitSync)
|
||||
EGL_ENTRYPOINT(eglWaitSyncKHR)
|
||||
@@ -0,0 +1,163 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util/simple_mtx.h"
|
||||
|
||||
#include "egldevice.h"
|
||||
#include "egldisplay.h"
|
||||
#include "eglglobals.h"
|
||||
|
||||
#include "util/macros.h"
|
||||
#include "util/os_misc.h"
|
||||
|
||||
#ifdef HAVE_MINCORE
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
static simple_mtx_t _eglGlobalMutex = SIMPLE_MTX_INITIALIZER;
|
||||
|
||||
struct _egl_global _eglGlobal = {
|
||||
.Mutex = &_eglGlobalMutex,
|
||||
.DisplayList = NULL,
|
||||
.DeviceList = &_eglSoftwareDevice,
|
||||
|
||||
#if USE_LIBGLVND
|
||||
.ClientOnlyExtensionString =
|
||||
#else
|
||||
.ClientExtensionString =
|
||||
#endif
|
||||
"EGL_EXT_client_extensions"
|
||||
#if !DETECT_OS_WINDOWS
|
||||
" EGL_EXT_device_base"
|
||||
" EGL_EXT_device_enumeration"
|
||||
" EGL_EXT_device_query"
|
||||
#endif
|
||||
" EGL_EXT_platform_base"
|
||||
" EGL_KHR_client_get_all_proc_addresses"
|
||||
" EGL_KHR_debug"
|
||||
|
||||
#if USE_LIBGLVND
|
||||
,
|
||||
.PlatformExtensionString =
|
||||
#else
|
||||
" "
|
||||
#endif
|
||||
|
||||
#if !DETECT_OS_WINDOWS
|
||||
"EGL_EXT_platform_device"
|
||||
" EGL_EXT_explicit_device"
|
||||
#endif
|
||||
#ifdef HAVE_WAYLAND_PLATFORM
|
||||
" EGL_EXT_platform_wayland"
|
||||
" EGL_KHR_platform_wayland"
|
||||
#endif
|
||||
#ifdef HAVE_X11_PLATFORM
|
||||
" EGL_EXT_platform_x11"
|
||||
" EGL_KHR_platform_x11"
|
||||
#endif
|
||||
#ifdef HAVE_XCB_PLATFORM
|
||||
" EGL_EXT_platform_xcb"
|
||||
#endif
|
||||
#ifdef HAVE_DRM_PLATFORM
|
||||
" EGL_MESA_platform_gbm"
|
||||
" EGL_KHR_platform_gbm"
|
||||
#endif
|
||||
" EGL_MESA_platform_surfaceless"
|
||||
"",
|
||||
|
||||
.debugCallback = NULL,
|
||||
.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR,
|
||||
};
|
||||
|
||||
static void
|
||||
_eglAtExit(void)
|
||||
{
|
||||
_eglFiniDisplay();
|
||||
_eglFiniDevice(); /* always called last */
|
||||
}
|
||||
|
||||
void
|
||||
_eglRegisterAtExit(void)
|
||||
{
|
||||
static EGLBoolean registered = EGL_FALSE;
|
||||
|
||||
simple_mtx_lock(_eglGlobal.Mutex);
|
||||
|
||||
if (!registered) {
|
||||
atexit(_eglAtExit);
|
||||
registered = EGL_TRUE;
|
||||
}
|
||||
|
||||
simple_mtx_unlock(_eglGlobal.Mutex);
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglPointerIsDereferenceable(void *p)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
uint64_t page_size = 0;
|
||||
os_get_page_size(&page_size);
|
||||
#ifdef HAVE_MINCORE
|
||||
unsigned char valid = 0;
|
||||
|
||||
if (p == NULL)
|
||||
return EGL_FALSE;
|
||||
|
||||
/* align addr to page_size */
|
||||
addr &= ~(page_size - 1);
|
||||
|
||||
/* mincore expects &valid to be unsigned char* on Linux but char* on BSD:
|
||||
* we cast pointers to void, to fix type mismatch warnings in all systems
|
||||
*/
|
||||
if (mincore((void *)addr, page_size, (void *)&valid) < 0) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
/* mincore() returns 0 on success, and -1 on failure. The last parameter
|
||||
* is a vector of bytes with one entry for each page queried. mincore
|
||||
* returns page residency information in the first bit of each byte in the
|
||||
* vector.
|
||||
*
|
||||
* Residency doesn't actually matter when determining whether a pointer is
|
||||
* dereferenceable, so the output vector can be ignored. What matters is
|
||||
* whether mincore succeeds. See:
|
||||
*
|
||||
* http://man7.org/linux/man-pages/man2/mincore.2.html
|
||||
*/
|
||||
return EGL_TRUE;
|
||||
#else
|
||||
// Without mincore(), we just assume that the first page is unmapped.
|
||||
return addr >= page_size;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLGLOBALS_INCLUDED
|
||||
#define EGLGLOBALS_INCLUDED
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "util/simple_mtx.h"
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
enum {
|
||||
_EGL_DEBUG_BIT_CRITICAL = 0x1,
|
||||
_EGL_DEBUG_BIT_ERROR = 0x2,
|
||||
_EGL_DEBUG_BIT_WARN = 0x4,
|
||||
_EGL_DEBUG_BIT_INFO = 0x8,
|
||||
};
|
||||
|
||||
/**
|
||||
* Global library data
|
||||
*/
|
||||
struct _egl_global {
|
||||
simple_mtx_t *Mutex;
|
||||
|
||||
/* the list of all displays */
|
||||
_EGLDisplay *DisplayList;
|
||||
|
||||
_EGLDevice *DeviceList;
|
||||
|
||||
/*
|
||||
* Under libglvnd, the client extension string has to be split into two
|
||||
* strings, one for platform extensions, and one for everything else.
|
||||
* For a non-glvnd build create a concatenated one.
|
||||
*/
|
||||
#if USE_LIBGLVND
|
||||
const char *ClientOnlyExtensionString;
|
||||
const char *PlatformExtensionString;
|
||||
#else
|
||||
const char *ClientExtensionString;
|
||||
#endif
|
||||
|
||||
EGLDEBUGPROCKHR debugCallback;
|
||||
unsigned int debugTypesEnabled;
|
||||
};
|
||||
|
||||
extern struct _egl_global _eglGlobal;
|
||||
|
||||
extern void
|
||||
_eglRegisterAtExit(void);
|
||||
|
||||
extern void
|
||||
_eglAddAtExitCall(void (*func)(void));
|
||||
|
||||
static inline unsigned int
|
||||
DebugBitFromType(EGLenum type)
|
||||
{
|
||||
assert(type >= EGL_DEBUG_MSG_CRITICAL_KHR && type <= EGL_DEBUG_MSG_INFO_KHR);
|
||||
return (1 << (type - EGL_DEBUG_MSG_CRITICAL_KHR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform validity checks on a generic pointer.
|
||||
*/
|
||||
extern EGLBoolean
|
||||
_eglPointerIsDereferenceable(void *p);
|
||||
|
||||
#endif /* EGLGLOBALS_INCLUDED */
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* (C) Copyright 2016, 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
|
||||
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||
* license, 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 (including the next
|
||||
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* IBM AND/OR ITS SUPPLIERS 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.
|
||||
*
|
||||
* Authors:
|
||||
* Kyle Brenneman <[email protected]>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glvnd/libeglabi.h>
|
||||
|
||||
#include "eglcurrent.h"
|
||||
#include "egldispatchstubs.h"
|
||||
#include "eglglobals.h"
|
||||
|
||||
static const __EGLapiExports *__eglGLVNDApiExports = NULL;
|
||||
|
||||
static const char *EGLAPIENTRY
|
||||
__eglGLVNDQueryString(EGLDisplay dpy, EGLenum name)
|
||||
{
|
||||
// For client extensions, return the list of non-platform extensions. The
|
||||
// platform extensions are returned by __eglGLVNDGetVendorString.
|
||||
if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
|
||||
return _eglGlobal.ClientOnlyExtensionString;
|
||||
|
||||
// For everything else, forward to the normal eglQueryString function.
|
||||
return eglQueryString(dpy, name);
|
||||
}
|
||||
|
||||
static const char *
|
||||
__eglGLVNDGetVendorString(int name)
|
||||
{
|
||||
if (name == __EGL_VENDOR_STRING_PLATFORM_EXTENSIONS)
|
||||
return _eglGlobal.PlatformExtensionString;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static EGLDisplay
|
||||
__eglGLVNDGetPlatformDisplay(EGLenum platform, void *native_display,
|
||||
const EGLAttrib *attrib_list)
|
||||
{
|
||||
if (platform == EGL_NONE) {
|
||||
assert(native_display == (void *)EGL_DEFAULT_DISPLAY);
|
||||
assert(attrib_list == NULL);
|
||||
return eglGetDisplay((EGLNativeDisplayType)native_display);
|
||||
} else {
|
||||
return eglGetPlatformDisplay(platform, native_display, attrib_list);
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
__eglGLVNDGetProcAddress(const char *procName)
|
||||
{
|
||||
if (strcmp(procName, "eglQueryString") == 0)
|
||||
return (void *)__eglGLVNDQueryString;
|
||||
|
||||
return (void *)eglGetProcAddress(procName);
|
||||
}
|
||||
|
||||
PUBLIC EGLAPI EGLBoolean
|
||||
__egl_Main(uint32_t version, const __EGLapiExports *exports,
|
||||
__EGLvendorInfo *vendor, __EGLapiImports *imports)
|
||||
{
|
||||
if (EGL_VENDOR_ABI_GET_MAJOR_VERSION(version) !=
|
||||
EGL_VENDOR_ABI_MAJOR_VERSION)
|
||||
return EGL_FALSE;
|
||||
|
||||
__eglGLVNDApiExports = exports;
|
||||
__eglInitDispatchStubs(exports);
|
||||
|
||||
imports->getPlatformDisplay = __eglGLVNDGetPlatformDisplay;
|
||||
imports->getSupportsAPI = _eglIsApiValid;
|
||||
imports->getVendorString = __eglGLVNDGetVendorString;
|
||||
imports->getProcAddress = __eglGLVNDGetProcAddress;
|
||||
imports->getDispatchAddress = __eglDispatchFindDispatchFunction;
|
||||
imports->setDispatchIndex = __eglSetDispatchIndex;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eglcurrent.h"
|
||||
#include "eglimage.h"
|
||||
#include "egllog.h"
|
||||
|
||||
static EGLint
|
||||
_eglParseKHRImageAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
|
||||
EGLint attr, EGLint val)
|
||||
{
|
||||
switch (attr) {
|
||||
case EGL_IMAGE_PRESERVED_KHR:
|
||||
if (!disp->Extensions.KHR_image_base)
|
||||
return EGL_BAD_PARAMETER;
|
||||
|
||||
attrs->ImagePreserved = val;
|
||||
break;
|
||||
|
||||
case EGL_GL_TEXTURE_LEVEL_KHR:
|
||||
if (!disp->Extensions.KHR_gl_texture_2D_image)
|
||||
return EGL_BAD_PARAMETER;
|
||||
|
||||
attrs->GLTextureLevel = val;
|
||||
break;
|
||||
case EGL_GL_TEXTURE_ZOFFSET_KHR:
|
||||
if (!disp->Extensions.KHR_gl_texture_3D_image)
|
||||
return EGL_BAD_PARAMETER;
|
||||
|
||||
attrs->GLTextureZOffset = val;
|
||||
break;
|
||||
case EGL_PROTECTED_CONTENT_EXT:
|
||||
if (!disp->Extensions.EXT_protected_content &&
|
||||
!disp->Extensions.EXT_protected_surface)
|
||||
return EGL_BAD_PARAMETER;
|
||||
|
||||
attrs->ProtectedContent = val;
|
||||
break;
|
||||
default:
|
||||
return EGL_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
return EGL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
static EGLint
|
||||
_eglParseWLBindWaylandDisplayAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
|
||||
EGLint attr, EGLint val)
|
||||
{
|
||||
if (!disp->Extensions.WL_bind_wayland_display)
|
||||
return EGL_BAD_PARAMETER;
|
||||
|
||||
switch (attr) {
|
||||
case EGL_WAYLAND_PLANE_WL:
|
||||
attrs->PlaneWL = val;
|
||||
break;
|
||||
default:
|
||||
return EGL_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
return EGL_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static EGLint
|
||||
_eglParseEXTImageDmaBufImportAttribs(_EGLImageAttribs *attrs, _EGLDisplay *disp,
|
||||
EGLint attr, EGLint val)
|
||||
{
|
||||
if (!disp->Extensions.EXT_image_dma_buf_import)
|
||||
return EGL_BAD_PARAMETER;
|
||||
|
||||
switch (attr) {
|
||||
case EGL_WIDTH:
|
||||
attrs->Width = val;
|
||||
break;
|
||||
case EGL_HEIGHT:
|
||||
attrs->Height = val;
|
||||
break;
|
||||
case EGL_LINUX_DRM_FOURCC_EXT:
|
||||
attrs->DMABufFourCC.Value = val;
|
||||
attrs->DMABufFourCC.IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE0_FD_EXT:
|
||||
attrs->DMABufPlaneFds[0].Value = val;
|
||||
attrs->DMABufPlaneFds[0].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
|
||||
attrs->DMABufPlaneOffsets[0].Value = val;
|
||||
attrs->DMABufPlaneOffsets[0].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE0_PITCH_EXT:
|
||||
attrs->DMABufPlanePitches[0].Value = val;
|
||||
attrs->DMABufPlanePitches[0].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE1_FD_EXT:
|
||||
attrs->DMABufPlaneFds[1].Value = val;
|
||||
attrs->DMABufPlaneFds[1].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
|
||||
attrs->DMABufPlaneOffsets[1].Value = val;
|
||||
attrs->DMABufPlaneOffsets[1].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE1_PITCH_EXT:
|
||||
attrs->DMABufPlanePitches[1].Value = val;
|
||||
attrs->DMABufPlanePitches[1].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE2_FD_EXT:
|
||||
attrs->DMABufPlaneFds[2].Value = val;
|
||||
attrs->DMABufPlaneFds[2].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
|
||||
attrs->DMABufPlaneOffsets[2].Value = val;
|
||||
attrs->DMABufPlaneOffsets[2].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE2_PITCH_EXT:
|
||||
attrs->DMABufPlanePitches[2].Value = val;
|
||||
attrs->DMABufPlanePitches[2].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_YUV_COLOR_SPACE_HINT_EXT:
|
||||
if (val != EGL_ITU_REC601_EXT && val != EGL_ITU_REC709_EXT &&
|
||||
val != EGL_ITU_REC2020_EXT)
|
||||
return EGL_BAD_ATTRIBUTE;
|
||||
|
||||
attrs->DMABufYuvColorSpaceHint.Value = val;
|
||||
attrs->DMABufYuvColorSpaceHint.IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_SAMPLE_RANGE_HINT_EXT:
|
||||
if (val != EGL_YUV_FULL_RANGE_EXT && val != EGL_YUV_NARROW_RANGE_EXT)
|
||||
return EGL_BAD_ATTRIBUTE;
|
||||
|
||||
attrs->DMABufSampleRangeHint.Value = val;
|
||||
attrs->DMABufSampleRangeHint.IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
|
||||
if (val != EGL_YUV_CHROMA_SITING_0_EXT &&
|
||||
val != EGL_YUV_CHROMA_SITING_0_5_EXT)
|
||||
return EGL_BAD_ATTRIBUTE;
|
||||
|
||||
attrs->DMABufChromaHorizontalSiting.Value = val;
|
||||
attrs->DMABufChromaHorizontalSiting.IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
|
||||
if (val != EGL_YUV_CHROMA_SITING_0_EXT &&
|
||||
val != EGL_YUV_CHROMA_SITING_0_5_EXT)
|
||||
return EGL_BAD_ATTRIBUTE;
|
||||
|
||||
attrs->DMABufChromaVerticalSiting.Value = val;
|
||||
attrs->DMABufChromaVerticalSiting.IsPresent = EGL_TRUE;
|
||||
break;
|
||||
default:
|
||||
return EGL_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
return EGL_SUCCESS;
|
||||
}
|
||||
|
||||
static EGLint
|
||||
_eglParseEXTImageDmaBufImportModifiersAttribs(_EGLImageAttribs *attrs,
|
||||
_EGLDisplay *disp, EGLint attr,
|
||||
EGLint val)
|
||||
{
|
||||
if (!disp->Extensions.EXT_image_dma_buf_import_modifiers)
|
||||
return EGL_BAD_PARAMETER;
|
||||
|
||||
switch (attr) {
|
||||
case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
|
||||
attrs->DMABufPlaneModifiersLo[0].Value = val;
|
||||
attrs->DMABufPlaneModifiersLo[0].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
|
||||
attrs->DMABufPlaneModifiersHi[0].Value = val;
|
||||
attrs->DMABufPlaneModifiersHi[0].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
|
||||
attrs->DMABufPlaneModifiersLo[1].Value = val;
|
||||
attrs->DMABufPlaneModifiersLo[1].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
|
||||
attrs->DMABufPlaneModifiersHi[1].Value = val;
|
||||
attrs->DMABufPlaneModifiersHi[1].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
|
||||
attrs->DMABufPlaneModifiersLo[2].Value = val;
|
||||
attrs->DMABufPlaneModifiersLo[2].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
|
||||
attrs->DMABufPlaneModifiersHi[2].Value = val;
|
||||
attrs->DMABufPlaneModifiersHi[2].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE3_FD_EXT:
|
||||
attrs->DMABufPlaneFds[3].Value = val;
|
||||
attrs->DMABufPlaneFds[3].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
|
||||
attrs->DMABufPlaneOffsets[3].Value = val;
|
||||
attrs->DMABufPlaneOffsets[3].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE3_PITCH_EXT:
|
||||
attrs->DMABufPlanePitches[3].Value = val;
|
||||
attrs->DMABufPlanePitches[3].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
|
||||
attrs->DMABufPlaneModifiersLo[3].Value = val;
|
||||
attrs->DMABufPlaneModifiersLo[3].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
|
||||
attrs->DMABufPlaneModifiersHi[3].Value = val;
|
||||
attrs->DMABufPlaneModifiersHi[3].IsPresent = EGL_TRUE;
|
||||
break;
|
||||
default:
|
||||
return EGL_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
return EGL_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the list of image attributes.
|
||||
*
|
||||
* Returns EGL_TRUE on success and EGL_FALSE otherwise.
|
||||
* Function calls _eglError to set the correct error code.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *disp,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
EGLint i, err;
|
||||
|
||||
memset(attrs, 0, sizeof(*attrs));
|
||||
|
||||
if (!attrib_list)
|
||||
return EGL_TRUE;
|
||||
|
||||
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
|
||||
EGLint attr = attrib_list[i++];
|
||||
EGLint val = attrib_list[i];
|
||||
|
||||
err = _eglParseKHRImageAttribs(attrs, disp, attr, val);
|
||||
if (err == EGL_SUCCESS)
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_BIND_WL_DISPLAY
|
||||
err = _eglParseWLBindWaylandDisplayAttribs(attrs, disp, attr, val);
|
||||
if (err == EGL_SUCCESS)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
err = _eglParseEXTImageDmaBufImportAttribs(attrs, disp, attr, val);
|
||||
if (err == EGL_SUCCESS)
|
||||
continue;
|
||||
|
||||
/* EXT_image_dma_buf_import states that if invalid value is provided for
|
||||
* its attributes, we should return EGL_BAD_ATTRIBUTE.
|
||||
* Bail out ASAP, since follow-up calls can return another EGL_BAD error.
|
||||
*/
|
||||
if (err == EGL_BAD_ATTRIBUTE)
|
||||
return _eglError(err, __func__);
|
||||
|
||||
err =
|
||||
_eglParseEXTImageDmaBufImportModifiersAttribs(attrs, disp, attr, val);
|
||||
if (err == EGL_SUCCESS)
|
||||
continue;
|
||||
|
||||
return _eglError(err, __func__);
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010-2011 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLIMAGE_INCLUDED
|
||||
#define EGLIMAGE_INCLUDED
|
||||
|
||||
#include "egldisplay.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _egl_image_attrib_int {
|
||||
EGLint Value;
|
||||
EGLBoolean IsPresent;
|
||||
};
|
||||
|
||||
#define DMA_BUF_MAX_PLANES 4
|
||||
|
||||
struct _egl_image_attribs {
|
||||
/* EGL_KHR_image_base */
|
||||
EGLBoolean ImagePreserved;
|
||||
|
||||
/* EGL_KHR_gl_image */
|
||||
EGLint GLTextureLevel;
|
||||
EGLint GLTextureZOffset;
|
||||
|
||||
/* EGL_WL_bind_wayland_display */
|
||||
EGLint PlaneWL;
|
||||
|
||||
/* EGL_EXT_image_dma_buf_import and
|
||||
* EGL_EXT_image_dma_buf_import_modifiers */
|
||||
EGLint Width;
|
||||
EGLint Height;
|
||||
struct _egl_image_attrib_int DMABufFourCC;
|
||||
struct _egl_image_attrib_int DMABufPlaneFds[DMA_BUF_MAX_PLANES];
|
||||
struct _egl_image_attrib_int DMABufPlaneOffsets[DMA_BUF_MAX_PLANES];
|
||||
struct _egl_image_attrib_int DMABufPlanePitches[DMA_BUF_MAX_PLANES];
|
||||
struct _egl_image_attrib_int DMABufPlaneModifiersLo[DMA_BUF_MAX_PLANES];
|
||||
struct _egl_image_attrib_int DMABufPlaneModifiersHi[DMA_BUF_MAX_PLANES];
|
||||
struct _egl_image_attrib_int DMABufYuvColorSpaceHint;
|
||||
struct _egl_image_attrib_int DMABufSampleRangeHint;
|
||||
struct _egl_image_attrib_int DMABufChromaHorizontalSiting;
|
||||
struct _egl_image_attrib_int DMABufChromaVerticalSiting;
|
||||
|
||||
/* EGL_EXT_protected_content || EGL_EXT_protected_surface */
|
||||
EGLBoolean ProtectedContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* "Base" class for device driver images.
|
||||
*/
|
||||
struct _egl_image {
|
||||
/* An image is a display resource */
|
||||
_EGLResource Resource;
|
||||
};
|
||||
|
||||
EGLBoolean
|
||||
_eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *disp,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
static inline void
|
||||
_eglInitImage(_EGLImage *img, _EGLDisplay *disp)
|
||||
{
|
||||
_eglInitResource(&img->Resource, sizeof(*img), disp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment reference count for the image.
|
||||
*/
|
||||
static inline _EGLImage *
|
||||
_eglGetImage(_EGLImage *img)
|
||||
{
|
||||
if (img)
|
||||
_eglGetResource(&img->Resource);
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement reference count for the image.
|
||||
*/
|
||||
static inline EGLBoolean
|
||||
_eglPutImage(_EGLImage *img)
|
||||
{
|
||||
return (img) ? _eglPutResource(&img->Resource) : EGL_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link an image to its display and return the handle of the link.
|
||||
* The handle can be passed to client directly.
|
||||
*/
|
||||
static inline EGLImage
|
||||
_eglLinkImage(_EGLImage *img)
|
||||
{
|
||||
_eglLinkResource(&img->Resource, _EGL_RESOURCE_IMAGE);
|
||||
return (EGLImage)img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a linked image from its display.
|
||||
* Accessing an unlinked image should generate EGL_BAD_PARAMETER error.
|
||||
*/
|
||||
static inline void
|
||||
_eglUnlinkImage(_EGLImage *img)
|
||||
{
|
||||
_eglUnlinkResource(&img->Resource, _EGL_RESOURCE_IMAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a handle to find the linked image.
|
||||
* Return NULL if the handle has no corresponding linked image.
|
||||
*/
|
||||
static inline _EGLImage *
|
||||
_eglLookupImage(EGLImage image, _EGLDisplay *disp)
|
||||
{
|
||||
_EGLImage *img = (_EGLImage *)image;
|
||||
if (!disp || !_eglCheckResource((void *)img, _EGL_RESOURCE_IMAGE, disp))
|
||||
img = NULL;
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the handle of a linked image, or EGL_NO_IMAGE_KHR.
|
||||
*/
|
||||
static inline EGLImage
|
||||
_eglGetImageHandle(_EGLImage *img)
|
||||
{
|
||||
_EGLResource *res = (_EGLResource *)img;
|
||||
return (res && _eglIsResourceLinked(res)) ? (EGLImage)img : EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLIMAGE_INCLUDED */
|
||||
@@ -0,0 +1,161 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Logging facility for debug/info messages.
|
||||
* _EGL_FATAL messages are printed to stderr
|
||||
* The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "c11/threads.h"
|
||||
#include "util/log.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/os_misc.h"
|
||||
#include "util/simple_mtx.h"
|
||||
#include "util/u_string.h"
|
||||
|
||||
#include "egllog.h"
|
||||
|
||||
#define MAXSTRING 1000
|
||||
#define FALLBACK_LOG_LEVEL _EGL_WARNING
|
||||
|
||||
static struct {
|
||||
simple_mtx_t mutex;
|
||||
|
||||
EGLBoolean initialized;
|
||||
EGLint level;
|
||||
} logging = {
|
||||
.mutex = SIMPLE_MTX_INITIALIZER,
|
||||
.initialized = EGL_FALSE,
|
||||
.level = FALLBACK_LOG_LEVEL,
|
||||
};
|
||||
|
||||
static const char *level_strings[] = {
|
||||
[_EGL_FATAL] = "fatal",
|
||||
[_EGL_WARNING] = "warning",
|
||||
[_EGL_INFO] = "info",
|
||||
[_EGL_DEBUG] = "debug",
|
||||
};
|
||||
|
||||
/**
|
||||
* The default logger.
|
||||
*/
|
||||
static void
|
||||
_eglDefaultLogger(EGLint level, const char *msg)
|
||||
{
|
||||
static const int egl2log[] = {
|
||||
[_EGL_FATAL] = MESA_LOG_ERROR,
|
||||
[_EGL_WARNING] = MESA_LOG_WARN,
|
||||
[_EGL_INFO] = MESA_LOG_INFO,
|
||||
[_EGL_DEBUG] = MESA_LOG_DEBUG,
|
||||
};
|
||||
|
||||
mesa_log(egl2log[level], "MESA-EGL", "%s", msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the logging facility.
|
||||
*/
|
||||
static void
|
||||
_eglInitLogger(void)
|
||||
{
|
||||
const char *log_env;
|
||||
EGLint i, level = -1;
|
||||
|
||||
if (logging.initialized)
|
||||
return;
|
||||
|
||||
log_env = os_get_option("EGL_LOG_LEVEL");
|
||||
if (log_env) {
|
||||
for (i = 0; i < ARRAY_SIZE(level_strings); i++) {
|
||||
if (strcasecmp(log_env, level_strings[i]) == 0) {
|
||||
level = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL;
|
||||
logging.initialized = EGL_TRUE;
|
||||
|
||||
/* it is fine to call _eglLog now */
|
||||
if (log_env && level < 0) {
|
||||
_eglLog(_EGL_WARNING,
|
||||
"Unrecognized EGL_LOG_LEVEL environment variable value. "
|
||||
"Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
|
||||
"Got \"%s\". Falling back to \"%s\".",
|
||||
log_env, level_strings[FALLBACK_LOG_LEVEL]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the log level.
|
||||
*/
|
||||
EGLint
|
||||
_eglGetLogLevel(void)
|
||||
{
|
||||
return logging.level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message with message logger.
|
||||
* \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
|
||||
*/
|
||||
void
|
||||
_eglLog(EGLint level, const char *fmtStr, ...)
|
||||
{
|
||||
va_list args;
|
||||
char msg[MAXSTRING];
|
||||
int ret;
|
||||
|
||||
/* one-time initialization; a little race here is fine */
|
||||
if (!logging.initialized)
|
||||
_eglInitLogger();
|
||||
if (level > logging.level || level < 0)
|
||||
return;
|
||||
|
||||
simple_mtx_lock(&logging.mutex);
|
||||
|
||||
va_start(args, fmtStr);
|
||||
ret = vsnprintf(msg, MAXSTRING, fmtStr, args);
|
||||
if (ret < 0 || ret >= MAXSTRING)
|
||||
strcpy(msg, "<message truncated>");
|
||||
va_end(args);
|
||||
|
||||
_eglDefaultLogger(level, msg);
|
||||
|
||||
simple_mtx_unlock(&logging.mutex);
|
||||
|
||||
if (level == _EGL_FATAL)
|
||||
exit(1); /* or abort()? */
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLLOG_INCLUDED
|
||||
#define EGLLOG_INCLUDED
|
||||
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _EGL_FATAL 0 /* unrecoverable error */
|
||||
#define _EGL_WARNING 1 /* recoverable error/problem */
|
||||
#define _EGL_INFO 2 /* just useful info */
|
||||
#define _EGL_DEBUG 3 /* useful info for debugging */
|
||||
|
||||
extern EGLint
|
||||
_eglGetLogLevel(void);
|
||||
|
||||
extern void
|
||||
_eglLog(EGLint level, const char *fmtStr, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLLOG_INCLUDED */
|
||||
@@ -0,0 +1,837 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Surface-related functions.
|
||||
*/
|
||||
|
||||
#include "eglsurface.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "eglcurrent.h"
|
||||
#include "egldefines.h"
|
||||
#include "egldisplay.h"
|
||||
#include "egldriver.h"
|
||||
#include "egllog.h"
|
||||
|
||||
#include "util/macros.h"
|
||||
|
||||
/**
|
||||
* Parse the list of surface attributes and return the proper error code.
|
||||
*/
|
||||
static EGLint
|
||||
_eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDisplay *disp = surf->Resource.Display;
|
||||
EGLint type = surf->Type;
|
||||
EGLint texture_type = EGL_PBUFFER_BIT;
|
||||
EGLint i, err = EGL_SUCCESS;
|
||||
EGLint attr = EGL_NONE;
|
||||
EGLint val = EGL_NONE;
|
||||
|
||||
if (!attrib_list)
|
||||
return EGL_SUCCESS;
|
||||
|
||||
if (disp->Extensions.NOK_texture_from_pixmap)
|
||||
texture_type |= EGL_PIXMAP_BIT;
|
||||
|
||||
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
|
||||
attr = attrib_list[i++];
|
||||
val = attrib_list[i];
|
||||
|
||||
switch (attr) {
|
||||
/* common attributes */
|
||||
case EGL_GL_COLORSPACE_KHR:
|
||||
if (!disp->Extensions.KHR_gl_colorspace) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
switch (val) {
|
||||
case EGL_GL_COLORSPACE_SRGB_KHR:
|
||||
case EGL_GL_COLORSPACE_LINEAR_KHR:
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
surf->GLColorspace = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.display_primary_r.x = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.display_primary_r.y = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.display_primary_g.x = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.display_primary_g.y = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.display_primary_b.x = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.display_primary_b.y = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_WHITE_POINT_X_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.white_point.x = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.white_point.y = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.max_luminance = val;
|
||||
break;
|
||||
case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
|
||||
if (!disp->Extensions.EXT_surface_SMPTE2086_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.min_luminance = val;
|
||||
break;
|
||||
case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
|
||||
if (!disp->Extensions.EXT_surface_CTA861_3_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.max_cll = val;
|
||||
break;
|
||||
case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
|
||||
if (!disp->Extensions.EXT_surface_CTA861_3_metadata) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->HdrMetadata.max_fall = val;
|
||||
break;
|
||||
case EGL_VG_COLORSPACE:
|
||||
switch (val) {
|
||||
case EGL_VG_COLORSPACE_sRGB:
|
||||
case EGL_VG_COLORSPACE_LINEAR:
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
surf->VGColorspace = val;
|
||||
break;
|
||||
case EGL_VG_ALPHA_FORMAT:
|
||||
switch (val) {
|
||||
case EGL_VG_ALPHA_FORMAT_NONPRE:
|
||||
case EGL_VG_ALPHA_FORMAT_PRE:
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
surf->VGAlphaFormat = val;
|
||||
break;
|
||||
/* window surface attributes */
|
||||
case EGL_RENDER_BUFFER:
|
||||
if (type != EGL_WINDOW_BIT) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->RequestedRenderBuffer = val;
|
||||
if (surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) {
|
||||
/* Unlike normal EGLSurfaces, one with a mutable render buffer
|
||||
* uses the application-chosen render buffer.
|
||||
*/
|
||||
surf->ActiveRenderBuffer = val;
|
||||
}
|
||||
break;
|
||||
case EGL_PRESENT_OPAQUE_EXT:
|
||||
if (!disp->Extensions.EXT_present_opaque) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (type != EGL_WINDOW_BIT) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (val != EGL_TRUE && val != EGL_FALSE) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
surf->PresentOpaque = val;
|
||||
break;
|
||||
case EGL_SURFACE_COMPRESSION_EXT:
|
||||
if (type != EGL_WINDOW_BIT) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (val < EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT ||
|
||||
val > EGL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
surf->CompressionRate = val;
|
||||
break;
|
||||
/* pbuffer surface attributes */
|
||||
case EGL_WIDTH:
|
||||
if (type != EGL_PBUFFER_BIT) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (val < 0) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
surf->Width = val;
|
||||
break;
|
||||
case EGL_HEIGHT:
|
||||
if (type != EGL_PBUFFER_BIT) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (val < 0) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
surf->Height = val;
|
||||
break;
|
||||
case EGL_LARGEST_PBUFFER:
|
||||
if (type != EGL_PBUFFER_BIT) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->LargestPbuffer = !!val;
|
||||
break;
|
||||
/* for eglBindTexImage */
|
||||
case EGL_TEXTURE_FORMAT:
|
||||
if (!(type & texture_type)) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case EGL_TEXTURE_RGB:
|
||||
case EGL_TEXTURE_RGBA:
|
||||
case EGL_NO_TEXTURE:
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
surf->TextureFormat = val;
|
||||
break;
|
||||
case EGL_TEXTURE_TARGET:
|
||||
if (!(type & texture_type)) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case EGL_TEXTURE_2D:
|
||||
case EGL_NO_TEXTURE:
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
surf->TextureTarget = val;
|
||||
break;
|
||||
case EGL_MIPMAP_TEXTURE:
|
||||
if (!(type & texture_type)) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->MipmapTexture = !!val;
|
||||
break;
|
||||
case EGL_PROTECTED_CONTENT_EXT:
|
||||
if (!disp->Extensions.EXT_protected_content &&
|
||||
!disp->Extensions.EXT_protected_surface) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
surf->ProtectedContent = val;
|
||||
break;
|
||||
|
||||
/* no pixmap surface specific attributes */
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) {
|
||||
if ((surf->TextureTarget == EGL_NO_TEXTURE &&
|
||||
surf->TextureFormat != EGL_NO_TEXTURE) ||
|
||||
(surf->TextureFormat == EGL_NO_TEXTURE &&
|
||||
surf->TextureTarget != EGL_NO_TEXTURE)) {
|
||||
attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET
|
||||
: EGL_TEXTURE_FORMAT;
|
||||
err = EGL_BAD_MATCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS)
|
||||
_eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do error check on parameters and initialize the given _EGLSurface object.
|
||||
* \return EGL_TRUE if no errors, EGL_FALSE otherwise.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglInitSurface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
|
||||
_EGLConfig *conf, const EGLint *attrib_list,
|
||||
void *native_surface)
|
||||
{
|
||||
const char *func;
|
||||
EGLint renderBuffer = EGL_BACK_BUFFER;
|
||||
EGLint swapBehavior = EGL_BUFFER_DESTROYED;
|
||||
EGLint err;
|
||||
|
||||
/* Swap behavior can be preserved only if config supports this. */
|
||||
if (conf->SurfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
|
||||
swapBehavior = EGL_BUFFER_PRESERVED;
|
||||
|
||||
switch (type) {
|
||||
case EGL_WINDOW_BIT:
|
||||
func = "eglCreateWindowSurface";
|
||||
swapBehavior = EGL_BUFFER_DESTROYED;
|
||||
break;
|
||||
case EGL_PIXMAP_BIT:
|
||||
func = "eglCreatePixmapSurface";
|
||||
renderBuffer = EGL_SINGLE_BUFFER;
|
||||
break;
|
||||
case EGL_PBUFFER_BIT:
|
||||
func = "eglCreatePBufferSurface";
|
||||
break;
|
||||
default:
|
||||
_eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if ((conf->SurfaceType & type) == 0)
|
||||
/* The config can't be used to create a surface of this type */
|
||||
return _eglError(EGL_BAD_MATCH, func);
|
||||
|
||||
_eglInitResource(&surf->Resource, sizeof(*surf), disp);
|
||||
surf->Type = type;
|
||||
surf->Config = conf;
|
||||
surf->Lost = EGL_FALSE;
|
||||
|
||||
surf->Width = 0;
|
||||
surf->Height = 0;
|
||||
surf->TextureFormat = EGL_NO_TEXTURE;
|
||||
surf->TextureTarget = EGL_NO_TEXTURE;
|
||||
surf->MipmapTexture = EGL_FALSE;
|
||||
surf->LargestPbuffer = EGL_FALSE;
|
||||
surf->RequestedRenderBuffer = renderBuffer;
|
||||
surf->ActiveRenderBuffer = renderBuffer;
|
||||
surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
|
||||
surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
|
||||
surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
|
||||
surf->ProtectedContent = EGL_FALSE;
|
||||
surf->PresentOpaque = EGL_FALSE;
|
||||
surf->CompressionRate = EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT;
|
||||
|
||||
surf->MipmapLevel = 0;
|
||||
surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
|
||||
surf->SwapBehavior = swapBehavior;
|
||||
|
||||
surf->HorizontalResolution = EGL_UNKNOWN;
|
||||
surf->VerticalResolution = EGL_UNKNOWN;
|
||||
surf->AspectRatio = EGL_UNKNOWN;
|
||||
|
||||
surf->SetDamageRegionCalled = EGL_FALSE;
|
||||
surf->BufferAgeRead = EGL_FALSE;
|
||||
|
||||
/* the default swap interval is 1 */
|
||||
surf->SwapInterval = 1;
|
||||
|
||||
surf->HdrMetadata.display_primary_r.x = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.display_primary_r.y = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.display_primary_g.x = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.display_primary_g.y = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.display_primary_b.x = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.display_primary_b.y = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.white_point.x = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.white_point.y = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.max_luminance = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.min_luminance = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.max_cll = EGL_DONT_CARE;
|
||||
surf->HdrMetadata.max_fall = EGL_DONT_CARE;
|
||||
|
||||
err = _eglParseSurfaceAttribList(surf, attrib_list);
|
||||
if (err != EGL_SUCCESS)
|
||||
return _eglError(err, func);
|
||||
|
||||
/* if EGL_LARGEST_PBUFFER in use, clamp width and height */
|
||||
if (surf->LargestPbuffer) {
|
||||
surf->Width = MIN2(surf->Width, _EGL_MAX_PBUFFER_WIDTH);
|
||||
surf->Height = MIN2(surf->Height, _EGL_MAX_PBUFFER_HEIGHT);
|
||||
}
|
||||
|
||||
surf->NativeSurface = native_surface;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surface, EGLint attribute,
|
||||
EGLint *value)
|
||||
{
|
||||
switch (attribute) {
|
||||
case EGL_WIDTH:
|
||||
*value = surface->Width;
|
||||
break;
|
||||
case EGL_HEIGHT:
|
||||
*value = surface->Height;
|
||||
break;
|
||||
case EGL_CONFIG_ID:
|
||||
*value = surface->Config->ConfigID;
|
||||
break;
|
||||
case EGL_LARGEST_PBUFFER:
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->LargestPbuffer;
|
||||
break;
|
||||
case EGL_TEXTURE_FORMAT:
|
||||
/* texture attributes: only for pbuffers, no error otherwise */
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->TextureFormat;
|
||||
break;
|
||||
case EGL_TEXTURE_TARGET:
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->TextureTarget;
|
||||
break;
|
||||
case EGL_MIPMAP_TEXTURE:
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->MipmapTexture;
|
||||
break;
|
||||
case EGL_MIPMAP_LEVEL:
|
||||
if (surface->Type == EGL_PBUFFER_BIT)
|
||||
*value = surface->MipmapLevel;
|
||||
break;
|
||||
case EGL_SWAP_BEHAVIOR:
|
||||
*value = surface->SwapBehavior;
|
||||
break;
|
||||
case EGL_RENDER_BUFFER:
|
||||
/* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* Querying EGL_RENDER_BUFFER returns the buffer which client API
|
||||
* rendering is requested to use. For a window surface, this is the
|
||||
* attribute value specified when the surface was created or last set
|
||||
* via eglSurfaceAttrib.
|
||||
*
|
||||
* In other words, querying a window surface returns the value most
|
||||
* recently *requested* by the user.
|
||||
*
|
||||
* The paragraph continues in the EGL 1.5 spec (2014.08.27):
|
||||
*
|
||||
* For a pbuffer surface, it is always EGL_BACK_BUFFER . For a pixmap
|
||||
* surface, it is always EGL_SINGLE_BUFFER . To determine the actual
|
||||
* buffer being rendered to by a context, call eglQueryContext.
|
||||
*/
|
||||
switch (surface->Type) {
|
||||
default:
|
||||
UNREACHABLE("bad EGLSurface type");
|
||||
case EGL_WINDOW_BIT:
|
||||
*value = surface->RequestedRenderBuffer;
|
||||
break;
|
||||
case EGL_PBUFFER_BIT:
|
||||
*value = EGL_BACK_BUFFER;
|
||||
break;
|
||||
case EGL_PIXMAP_BIT:
|
||||
*value = EGL_SINGLE_BUFFER;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EGL_PIXEL_ASPECT_RATIO:
|
||||
*value = surface->AspectRatio;
|
||||
break;
|
||||
case EGL_HORIZONTAL_RESOLUTION:
|
||||
*value = surface->HorizontalResolution;
|
||||
break;
|
||||
case EGL_VERTICAL_RESOLUTION:
|
||||
*value = surface->VerticalResolution;
|
||||
break;
|
||||
case EGL_MULTISAMPLE_RESOLVE:
|
||||
*value = surface->MultisampleResolve;
|
||||
break;
|
||||
case EGL_VG_ALPHA_FORMAT:
|
||||
*value = surface->VGAlphaFormat;
|
||||
break;
|
||||
case EGL_VG_COLORSPACE:
|
||||
*value = surface->VGColorspace;
|
||||
break;
|
||||
case EGL_GL_COLORSPACE_KHR:
|
||||
if (!disp->Extensions.KHR_gl_colorspace)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
|
||||
|
||||
*value = surface->GLColorspace;
|
||||
break;
|
||||
case EGL_BUFFER_AGE_EXT:
|
||||
/* Both EXT_buffer_age and KHR_partial_update accept EGL_BUFFER_AGE_EXT.
|
||||
* To be precise, the KHR one accepts EGL_BUFFER_AGE_KHR which is an
|
||||
* alias with the same numeric value.
|
||||
*/
|
||||
if (!disp->Extensions.EXT_buffer_age &&
|
||||
!disp->Extensions.KHR_partial_update)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
|
||||
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
|
||||
ctx->DrawSurface != surface)
|
||||
return _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
|
||||
|
||||
EGLint result = disp->Driver->QueryBufferAge(disp, surface);
|
||||
if (result < 0)
|
||||
return EGL_FALSE;
|
||||
|
||||
if (disp->Options.GalliumHudWarn && result > 0) {
|
||||
_eglLog(_EGL_WARNING,
|
||||
"GALLIUM_HUD is not accounted for when querying "
|
||||
"buffer age, possibly causing artifacts, try running with "
|
||||
"MESA_EXTENSION_OVERRIDE=\"-EGL_EXT_buffer_age "
|
||||
"-EGL_KHR_partial_update\"");
|
||||
disp->Options.GalliumHudWarn = EGL_FALSE;
|
||||
}
|
||||
|
||||
*value = result;
|
||||
surface->BufferAgeRead = EGL_TRUE;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
|
||||
*value = surface->HdrMetadata.display_primary_r.x;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
|
||||
*value = surface->HdrMetadata.display_primary_r.y;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
|
||||
*value = surface->HdrMetadata.display_primary_g.x;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
|
||||
*value = surface->HdrMetadata.display_primary_g.y;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
|
||||
*value = surface->HdrMetadata.display_primary_b.x;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
|
||||
*value = surface->HdrMetadata.display_primary_b.y;
|
||||
break;
|
||||
case EGL_SMPTE2086_WHITE_POINT_X_EXT:
|
||||
*value = surface->HdrMetadata.white_point.x;
|
||||
break;
|
||||
case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
|
||||
*value = surface->HdrMetadata.white_point.y;
|
||||
break;
|
||||
case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
|
||||
*value = surface->HdrMetadata.max_luminance;
|
||||
break;
|
||||
case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
|
||||
*value = surface->HdrMetadata.min_luminance;
|
||||
break;
|
||||
case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
|
||||
*value = surface->HdrMetadata.max_cll;
|
||||
break;
|
||||
case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
|
||||
*value = surface->HdrMetadata.max_fall;
|
||||
break;
|
||||
case EGL_PROTECTED_CONTENT_EXT:
|
||||
if (!disp->Extensions.EXT_protected_content &&
|
||||
!disp->Extensions.EXT_protected_surface)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
|
||||
*value = surface->ProtectedContent;
|
||||
break;
|
||||
case EGL_PRESENT_OPAQUE_EXT:
|
||||
if (!disp->Extensions.EXT_present_opaque)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
|
||||
*value = surface->PresentOpaque;
|
||||
break;
|
||||
case EGL_SURFACE_COMPRESSION_EXT:
|
||||
*value = surface->CompressionRate;
|
||||
break;
|
||||
default:
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default fallback routine - drivers might override this.
|
||||
*/
|
||||
EGLBoolean
|
||||
_eglSurfaceAttrib(_EGLDisplay *disp, _EGLSurface *surface, EGLint attribute,
|
||||
EGLint value)
|
||||
{
|
||||
EGLint confval;
|
||||
EGLint err = EGL_SUCCESS;
|
||||
EGLint all_es_bits =
|
||||
EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR;
|
||||
|
||||
switch (attribute) {
|
||||
case EGL_MIPMAP_LEVEL:
|
||||
confval = surface->Config->RenderableType;
|
||||
if (!(confval & all_es_bits)) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
surface->MipmapLevel = value;
|
||||
break;
|
||||
case EGL_MULTISAMPLE_RESOLVE:
|
||||
switch (value) {
|
||||
case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
|
||||
break;
|
||||
case EGL_MULTISAMPLE_RESOLVE_BOX:
|
||||
confval = surface->Config->SurfaceType;
|
||||
if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
surface->MultisampleResolve = value;
|
||||
break;
|
||||
case EGL_RENDER_BUFFER:
|
||||
if (!disp->Extensions.KHR_mutable_render_buffer) {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* If attribute is EGL_RENDER_BUFFER, and the EGL_SURFACE_TYPE
|
||||
* attribute of the EGLConfig used to create surface does not contain
|
||||
* EGL_MUTABLE_RENDER_BUFFER_BIT_KHR, [...] an EGL_BAD_MATCH error is
|
||||
* generated [...].
|
||||
*/
|
||||
if (!(surface->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR)) {
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
surface->RequestedRenderBuffer = value;
|
||||
break;
|
||||
case EGL_SWAP_BEHAVIOR:
|
||||
switch (value) {
|
||||
case EGL_BUFFER_DESTROYED:
|
||||
break;
|
||||
case EGL_BUFFER_PRESERVED:
|
||||
confval = surface->Config->SurfaceType;
|
||||
if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
|
||||
err = EGL_BAD_MATCH;
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
break;
|
||||
surface->SwapBehavior = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
|
||||
surface->HdrMetadata.display_primary_r.x = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
|
||||
surface->HdrMetadata.display_primary_r.y = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
|
||||
surface->HdrMetadata.display_primary_g.x = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
|
||||
surface->HdrMetadata.display_primary_g.y = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
|
||||
surface->HdrMetadata.display_primary_b.x = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
|
||||
surface->HdrMetadata.display_primary_b.y = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_WHITE_POINT_X_EXT:
|
||||
surface->HdrMetadata.white_point.x = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
|
||||
surface->HdrMetadata.white_point.y = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
|
||||
surface->HdrMetadata.max_luminance = value;
|
||||
break;
|
||||
case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
|
||||
surface->HdrMetadata.min_luminance = value;
|
||||
break;
|
||||
case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
|
||||
surface->HdrMetadata.max_cll = value;
|
||||
break;
|
||||
case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
|
||||
surface->HdrMetadata.max_fall = value;
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS)
|
||||
return _eglError(err, "eglSurfaceAttrib");
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglBindTexImage(_EGLDisplay *disp, _EGLSurface *surface, EGLint buffer)
|
||||
{
|
||||
EGLint texture_type = EGL_PBUFFER_BIT;
|
||||
|
||||
/* Just do basic error checking and return success/fail.
|
||||
* Drivers must implement the real stuff.
|
||||
*/
|
||||
|
||||
if (disp->Extensions.NOK_texture_from_pixmap)
|
||||
texture_type |= EGL_PIXMAP_BIT;
|
||||
|
||||
if (!(surface->Type & texture_type))
|
||||
return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
|
||||
|
||||
if (surface->TextureFormat == EGL_NO_TEXTURE)
|
||||
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
|
||||
|
||||
if (surface->TextureTarget == EGL_NO_TEXTURE)
|
||||
return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
|
||||
|
||||
if (buffer != EGL_BACK_BUFFER)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
|
||||
|
||||
surface->BoundToTexture = EGL_TRUE;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglReleaseTexImage(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
|
||||
{
|
||||
/* Just do basic error checking and return success/fail.
|
||||
* Drivers must implement the real stuff.
|
||||
*/
|
||||
|
||||
EGLint texture_type = EGL_PBUFFER_BIT;
|
||||
|
||||
if (surf == EGL_NO_SURFACE)
|
||||
return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
|
||||
|
||||
if (!surf->BoundToTexture) {
|
||||
/* Not an error, simply nothing to do */
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
if (surf->TextureFormat == EGL_NO_TEXTURE)
|
||||
return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage");
|
||||
|
||||
if (buffer != EGL_BACK_BUFFER)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
|
||||
|
||||
if (disp->Extensions.NOK_texture_from_pixmap)
|
||||
texture_type |= EGL_PIXMAP_BIT;
|
||||
|
||||
if (!(surf->Type & texture_type))
|
||||
return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
|
||||
|
||||
surf->BoundToTexture = EGL_FALSE;
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf)
|
||||
{
|
||||
return surf->Type == EGL_WINDOW_BIT && surf->Config &&
|
||||
(surf->Config->SurfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR);
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglSurfaceInSharedBufferMode(_EGLSurface *surf)
|
||||
{
|
||||
return _eglSurfaceHasMutableRenderBuffer(surf) &&
|
||||
surf->ActiveRenderBuffer == EGL_SINGLE_BUFFER;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLSURFACE_INCLUDED
|
||||
#define EGLSURFACE_INCLUDED
|
||||
|
||||
#include "egldisplay.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _egl_xy {
|
||||
EGLint x;
|
||||
EGLint y;
|
||||
};
|
||||
|
||||
struct _egl_hdr_metadata {
|
||||
struct _egl_xy display_primary_r;
|
||||
struct _egl_xy display_primary_g;
|
||||
struct _egl_xy display_primary_b;
|
||||
struct _egl_xy white_point;
|
||||
EGLint max_luminance;
|
||||
EGLint min_luminance;
|
||||
EGLint max_cll;
|
||||
EGLint max_fall;
|
||||
};
|
||||
|
||||
/**
|
||||
* "Base" class for device driver surfaces.
|
||||
*/
|
||||
struct _egl_surface {
|
||||
/* A surface is a display resource */
|
||||
_EGLResource Resource;
|
||||
|
||||
/* The context that is currently bound to the surface */
|
||||
_EGLContext *CurrentContext;
|
||||
|
||||
_EGLConfig *Config;
|
||||
|
||||
EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */
|
||||
|
||||
/* The native surface is lost. The EGL spec requires certain functions
|
||||
* to generate EGL_BAD_NATIVE_WINDOW when given this surface.
|
||||
*/
|
||||
EGLBoolean Lost;
|
||||
|
||||
/* attributes set by attribute list */
|
||||
EGLint Width, Height;
|
||||
EGLenum TextureFormat;
|
||||
EGLenum TextureTarget;
|
||||
EGLBoolean MipmapTexture;
|
||||
EGLBoolean LargestPbuffer;
|
||||
|
||||
/**
|
||||
* Value of EGL_RENDER_BUFFER selected at creation.
|
||||
*
|
||||
* The user may select, for window surfaces, the EGL_RENDER_BUFFER through
|
||||
* the attribute list of eglCreateWindowSurface(). The EGL spec allows the
|
||||
* implementation to ignore request, though; hence why we maintain both
|
||||
* RequestedRenderBuffer and ActiveRenderBuffer. For pbuffer and pixmap
|
||||
* surfaces, the EGL spec hard-codes the EGL_RENDER_BUFFER value and the
|
||||
* user must not provide it in the attribute list.
|
||||
*
|
||||
* Normally, the attribute is immutable and after surface creation.
|
||||
* However, EGL_KHR_mutable_render_buffer allows the user to change it in
|
||||
* window surfaces via eglSurfaceAttrib, in which case
|
||||
* eglQuerySurface(EGL_RENDER_BUFFER) will immediately afterwards return
|
||||
* the requested value but the actual render buffer used by the context
|
||||
* does not change until completion of the next eglSwapBuffers call.
|
||||
*
|
||||
* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* Querying EGL_RENDER_BUFFER returns the buffer which client API
|
||||
* rendering is requested to use. For a window surface, this is the
|
||||
* attribute value specified when the surface was created or last set
|
||||
* via eglSurfaceAttrib.
|
||||
*
|
||||
* eglQueryContext(EGL_RENDER_BUFFER) ignores this.
|
||||
*/
|
||||
EGLenum RequestedRenderBuffer;
|
||||
|
||||
/**
|
||||
* The EGL_RENDER_BUFFER in use by the context.
|
||||
*
|
||||
* This is valid only when bound as the draw surface. This may differ from
|
||||
* the RequestedRenderBuffer.
|
||||
*
|
||||
* Refer to eglQueryContext(EGL_RENDER_BUFFER) in the EGL spec.
|
||||
* eglQuerySurface(EGL_RENDER_BUFFER) ignores this.
|
||||
*
|
||||
* If a window surface is bound as the draw surface and has a pending,
|
||||
* user-requested change to EGL_RENDER_BUFFER, then the next eglSwapBuffers
|
||||
* will flush the pending change. (The flush of EGL_RENDER_BUFFER state may
|
||||
* occur without the implicit glFlush induced by eglSwapBuffers). The spec
|
||||
* requires that the flush occur at that time and nowhere else. During the
|
||||
* state-flush, we copy RequestedRenderBuffer to ActiveRenderBuffer.
|
||||
*
|
||||
* From the EGL_KHR_mutable_render_buffer spec (v12):
|
||||
*
|
||||
* If [...] there is a pending change to the EGL_RENDER_BUFFER
|
||||
* attribute, eglSwapBuffers performs an implicit flush operation on the
|
||||
* context and effects the attribute change.
|
||||
*/
|
||||
EGLenum ActiveRenderBuffer;
|
||||
|
||||
EGLenum VGAlphaFormat;
|
||||
EGLenum VGColorspace;
|
||||
EGLenum GLColorspace;
|
||||
|
||||
/* EGL_EXT_surface_compression
|
||||
* Value of EGL_SURFACE_COMPRESSION_EXT attribute selected at creation.
|
||||
*/
|
||||
EGLint CompressionRate;
|
||||
|
||||
/* attributes set by eglSurfaceAttrib */
|
||||
EGLint MipmapLevel;
|
||||
EGLenum MultisampleResolve;
|
||||
EGLenum SwapBehavior;
|
||||
|
||||
EGLint HorizontalResolution, VerticalResolution;
|
||||
EGLint AspectRatio;
|
||||
|
||||
EGLint SwapInterval;
|
||||
|
||||
/* EGL_KHR_partial_update
|
||||
* True if the damage region is already set
|
||||
* between frame boundaries.
|
||||
*/
|
||||
EGLBoolean SetDamageRegionCalled;
|
||||
|
||||
/* EGL_KHR_partial_update
|
||||
* True if the buffer age is read by the client
|
||||
* between frame boundaries.
|
||||
*/
|
||||
EGLBoolean BufferAgeRead;
|
||||
|
||||
/* True if the surface is bound to an OpenGL ES texture */
|
||||
EGLBoolean BoundToTexture;
|
||||
|
||||
EGLBoolean ProtectedContent;
|
||||
|
||||
EGLBoolean PresentOpaque;
|
||||
|
||||
struct _egl_hdr_metadata HdrMetadata;
|
||||
|
||||
void *NativeSurface;
|
||||
};
|
||||
|
||||
extern EGLBoolean
|
||||
_eglInitSurface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
|
||||
_EGLConfig *config, const EGLint *attrib_list,
|
||||
void *native_surface);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
|
||||
EGLint *value);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSurfaceAttrib(_EGLDisplay *disp, _EGLSurface *surf, EGLint attribute,
|
||||
EGLint value);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglBindTexImage(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglReleaseTexImage(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSurfaceHasMutableRenderBuffer(_EGLSurface *surf);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSurfaceInSharedBufferMode(_EGLSurface *surf);
|
||||
|
||||
/**
|
||||
* Increment reference count for the surface.
|
||||
*/
|
||||
static inline _EGLSurface *
|
||||
_eglGetSurface(_EGLSurface *surf)
|
||||
{
|
||||
if (surf)
|
||||
_eglGetResource(&surf->Resource);
|
||||
return surf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement reference count for the surface.
|
||||
*/
|
||||
static inline EGLBoolean
|
||||
_eglPutSurface(_EGLSurface *surf)
|
||||
{
|
||||
return (surf) ? _eglPutResource(&surf->Resource) : EGL_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a surface to its display and return the handle of the link.
|
||||
* The handle can be passed to client directly.
|
||||
*/
|
||||
static inline EGLSurface
|
||||
_eglLinkSurface(_EGLSurface *surf)
|
||||
{
|
||||
_eglLinkResource(&surf->Resource, _EGL_RESOURCE_SURFACE);
|
||||
return (EGLSurface)surf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a linked surface from its display.
|
||||
* Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
|
||||
*/
|
||||
static inline void
|
||||
_eglUnlinkSurface(_EGLSurface *surf)
|
||||
{
|
||||
_eglUnlinkResource(&surf->Resource, _EGL_RESOURCE_SURFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a handle to find the linked surface.
|
||||
* Return NULL if the handle has no corresponding linked surface.
|
||||
*/
|
||||
static inline _EGLSurface *
|
||||
_eglLookupSurface(EGLSurface surface, _EGLDisplay *disp)
|
||||
{
|
||||
_EGLSurface *surf = (_EGLSurface *)surface;
|
||||
if (!disp || !_eglCheckResource((void *)surf, _EGL_RESOURCE_SURFACE, disp))
|
||||
surf = NULL;
|
||||
return surf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the handle of a linked surface, or EGL_NO_SURFACE.
|
||||
*/
|
||||
static inline EGLSurface
|
||||
_eglGetSurfaceHandle(_EGLSurface *surf)
|
||||
{
|
||||
_EGLResource *res = (_EGLResource *)surf;
|
||||
return (res && _eglIsResourceLinked(res)) ? (EGLSurface)surf
|
||||
: EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLSURFACE_INCLUDED */
|
||||
@@ -0,0 +1,151 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "eglcurrent.h"
|
||||
#include "egldriver.h"
|
||||
#include "egllog.h"
|
||||
#include "eglsync.h"
|
||||
|
||||
/**
|
||||
* Parse the list of sync attributes and return the proper error code.
|
||||
*/
|
||||
static EGLint
|
||||
_eglParseSyncAttribList(_EGLSync *sync, const EGLAttrib *attrib_list)
|
||||
{
|
||||
EGLint i;
|
||||
|
||||
if (!attrib_list)
|
||||
return EGL_SUCCESS;
|
||||
|
||||
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
|
||||
EGLAttrib attr = attrib_list[i++];
|
||||
EGLAttrib val = attrib_list[i];
|
||||
EGLint err = EGL_SUCCESS;
|
||||
|
||||
switch (attr) {
|
||||
case EGL_CL_EVENT_HANDLE_KHR:
|
||||
if (sync->Type == EGL_SYNC_CL_EVENT_KHR) {
|
||||
sync->CLEvent = val;
|
||||
} else {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
}
|
||||
break;
|
||||
case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
|
||||
if (sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID) {
|
||||
/* we take ownership of the native fd, so no dup(): */
|
||||
sync->SyncFd = val;
|
||||
} else {
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS) {
|
||||
_eglLog(_EGL_DEBUG, "bad sync attribute 0x%" PRIxPTR, attr);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_SUCCESS;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglInitSync(_EGLSync *sync, _EGLDisplay *disp, EGLenum type,
|
||||
const EGLAttrib *attrib_list)
|
||||
{
|
||||
EGLint err;
|
||||
|
||||
_eglInitResource(&sync->Resource, sizeof(*sync), disp);
|
||||
sync->Type = type;
|
||||
sync->SyncStatus = EGL_UNSIGNALED_KHR;
|
||||
sync->SyncFd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
||||
|
||||
err = _eglParseSyncAttribList(sync, attrib_list);
|
||||
|
||||
switch (type) {
|
||||
case EGL_SYNC_CL_EVENT_KHR:
|
||||
sync->SyncCondition = EGL_SYNC_CL_EVENT_COMPLETE_KHR;
|
||||
break;
|
||||
case EGL_SYNC_NATIVE_FENCE_ANDROID:
|
||||
if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID)
|
||||
sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
|
||||
else
|
||||
sync->SyncCondition = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
|
||||
break;
|
||||
default:
|
||||
sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS)
|
||||
return _eglError(err, "eglCreateSyncKHR");
|
||||
|
||||
if (type == EGL_SYNC_CL_EVENT_KHR && !sync->CLEvent)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean
|
||||
_eglGetSyncAttrib(_EGLDisplay *disp, _EGLSync *sync, EGLint attribute,
|
||||
EGLAttrib *value)
|
||||
{
|
||||
switch (attribute) {
|
||||
case EGL_SYNC_TYPE_KHR:
|
||||
*value = sync->Type;
|
||||
break;
|
||||
case EGL_SYNC_STATUS_KHR:
|
||||
/* update the sync status */
|
||||
if (sync->SyncStatus != EGL_SIGNALED_KHR &&
|
||||
(sync->Type == EGL_SYNC_FENCE_KHR ||
|
||||
sync->Type == EGL_SYNC_CL_EVENT_KHR ||
|
||||
sync->Type == EGL_SYNC_REUSABLE_KHR ||
|
||||
sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID))
|
||||
disp->Driver->ClientWaitSyncKHR(disp, sync, 0, 0);
|
||||
|
||||
*value = sync->SyncStatus;
|
||||
break;
|
||||
case EGL_SYNC_CONDITION_KHR:
|
||||
if (sync->Type != EGL_SYNC_FENCE_KHR &&
|
||||
sync->Type != EGL_SYNC_CL_EVENT_KHR &&
|
||||
sync->Type != EGL_SYNC_NATIVE_FENCE_ANDROID)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
|
||||
*value = sync->SyncCondition;
|
||||
break;
|
||||
|
||||
default:
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
|
||||
break;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLSYNC_INCLUDED
|
||||
#define EGLSYNC_INCLUDED
|
||||
|
||||
#include "egldisplay.h"
|
||||
#include "egltypedefs.h"
|
||||
|
||||
/**
|
||||
* "Base" class for device driver syncs.
|
||||
*/
|
||||
struct _egl_sync {
|
||||
/* A sync is a display resource */
|
||||
_EGLResource Resource;
|
||||
|
||||
EGLenum Type;
|
||||
EGLenum SyncStatus;
|
||||
EGLenum SyncCondition;
|
||||
EGLAttrib CLEvent;
|
||||
EGLint SyncFd;
|
||||
};
|
||||
|
||||
extern EGLBoolean
|
||||
_eglInitSync(_EGLSync *sync, _EGLDisplay *disp, EGLenum type,
|
||||
const EGLAttrib *attrib_list);
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetSyncAttrib(_EGLDisplay *disp, _EGLSync *sync, EGLint attribute,
|
||||
EGLAttrib *value);
|
||||
|
||||
/**
|
||||
* Increment reference count for the sync.
|
||||
*/
|
||||
static inline _EGLSync *
|
||||
_eglGetSync(_EGLSync *sync)
|
||||
{
|
||||
if (sync)
|
||||
_eglGetResource(&sync->Resource);
|
||||
return sync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement reference count for the sync.
|
||||
*/
|
||||
static inline EGLBoolean
|
||||
_eglPutSync(_EGLSync *sync)
|
||||
{
|
||||
return (sync) ? _eglPutResource(&sync->Resource) : EGL_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a sync to its display and return the handle of the link.
|
||||
* The handle can be passed to client directly.
|
||||
*/
|
||||
static inline EGLSync
|
||||
_eglLinkSync(_EGLSync *sync)
|
||||
{
|
||||
_eglLinkResource(&sync->Resource, _EGL_RESOURCE_SYNC);
|
||||
return (EGLSync)sync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a linked sync from its display.
|
||||
*/
|
||||
static inline void
|
||||
_eglUnlinkSync(_EGLSync *sync)
|
||||
{
|
||||
_eglUnlinkResource(&sync->Resource, _EGL_RESOURCE_SYNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a handle to find the linked sync.
|
||||
* Return NULL if the handle has no corresponding linked sync.
|
||||
*/
|
||||
static inline _EGLSync *
|
||||
_eglLookupSync(EGLSync handle, _EGLDisplay *disp)
|
||||
{
|
||||
_EGLSync *sync = (_EGLSync *)handle;
|
||||
if (!disp || !_eglCheckResource((void *)sync, _EGL_RESOURCE_SYNC, disp))
|
||||
sync = NULL;
|
||||
return sync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the handle of a linked sync, or EGL_NO_SYNC_KHR.
|
||||
*/
|
||||
static inline EGLSync
|
||||
_eglGetSyncHandle(_EGLSync *sync)
|
||||
{
|
||||
_EGLResource *res = (_EGLResource *)sync;
|
||||
return (res && _eglIsResourceLinked(res)) ? (EGLSync)sync : EGL_NO_SYNC_KHR;
|
||||
}
|
||||
|
||||
#endif /* EGLSYNC_INCLUDED */
|
||||
@@ -0,0 +1,76 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 VMware, Inc.
|
||||
* Copyright 2009-2010 Chia-I Wu <[email protected]>
|
||||
* Copyright 2010 LunarG, Inc.
|
||||
* 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, sub license, 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 (including the
|
||||
* next paragraph) 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 EGLTYPEDEFS_INCLUDED
|
||||
#define EGLTYPEDEFS_INCLUDED
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/eglext_angle.h>
|
||||
#include <EGL/eglmesaext.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _egl_array _EGLArray;
|
||||
|
||||
typedef struct _egl_config _EGLConfig;
|
||||
|
||||
typedef struct _egl_context _EGLContext;
|
||||
|
||||
typedef struct _egl_device _EGLDevice;
|
||||
|
||||
typedef struct _egl_display _EGLDisplay;
|
||||
|
||||
typedef struct _egl_driver _EGLDriver;
|
||||
|
||||
typedef struct _egl_extensions _EGLExtensions;
|
||||
|
||||
typedef struct _egl_image _EGLImage;
|
||||
|
||||
typedef struct _egl_image_attribs _EGLImageAttribs;
|
||||
|
||||
typedef struct _egl_mode _EGLMode;
|
||||
|
||||
typedef struct _egl_resource _EGLResource;
|
||||
|
||||
typedef struct _egl_screen _EGLScreen;
|
||||
|
||||
typedef struct _egl_surface _EGLSurface;
|
||||
|
||||
typedef struct _egl_sync _EGLSync;
|
||||
|
||||
typedef struct _egl_thread_info _EGLThreadInfo;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EGLTYPEDEFS_INCLUDED */
|
||||
@@ -0,0 +1,272 @@
|
||||
# Copyright © 2017-2019 Intel Corporation
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
inc_egl = include_directories('.', 'main')
|
||||
|
||||
c_args_for_egl = [asan_c_args]
|
||||
cpp_args_for_egl = []
|
||||
link_args_for_egl = []
|
||||
link_deps_for_egl = []
|
||||
link_for_egl = []
|
||||
if with_dri
|
||||
link_for_egl += libgallium_dri
|
||||
endif
|
||||
if with_platform_windows
|
||||
link_for_egl += libgallium_wgl
|
||||
endif
|
||||
deps_for_egl = []
|
||||
incs_for_egl = [inc_include, inc_src, inc_egl]
|
||||
|
||||
files_egl = files(
|
||||
'main/eglapi.c',
|
||||
'main/eglarray.c',
|
||||
'main/eglarray.h',
|
||||
'main/eglconfigdebug.c',
|
||||
'main/eglconfigdebug.h',
|
||||
'main/eglconfig.c',
|
||||
'main/eglconfig.h',
|
||||
'main/eglcontext.c',
|
||||
'main/eglcontext.h',
|
||||
'main/eglcurrent.c',
|
||||
'main/eglcurrent.h',
|
||||
'main/egldefines.h',
|
||||
'main/egldevice.c',
|
||||
'main/egldevice.h',
|
||||
'main/egldisplay.c',
|
||||
'main/egldisplay.h',
|
||||
'main/egldriver.h',
|
||||
'main/eglglobals.c',
|
||||
'main/eglglobals.h',
|
||||
'main/eglimage.c',
|
||||
'main/eglimage.h',
|
||||
'main/egllog.c',
|
||||
'main/egllog.h',
|
||||
'main/eglsurface.c',
|
||||
'main/eglsurface.h',
|
||||
'main/eglsync.c',
|
||||
'main/eglsync.h',
|
||||
'main/eglentrypoint.h',
|
||||
'main/egltypedefs.h',
|
||||
)
|
||||
|
||||
# Remove the argument parsing from gen_egl_dispatch.py when removing this
|
||||
# option
|
||||
gen_args = []
|
||||
if with_wayland_bind_display
|
||||
gen_args += [ '--bind-wl-display' ]
|
||||
endif
|
||||
|
||||
g_egldispatchstubs_c = custom_target(
|
||||
'g_egldispatchstubs.c',
|
||||
input : [
|
||||
'generate/gen_egl_dispatch.py',
|
||||
'generate/egl.xml', 'generate/egl_other.xml'
|
||||
],
|
||||
output : 'g_egldispatchstubs.c',
|
||||
command : [
|
||||
prog_python, '@INPUT0@', gen_args, 'source', '@INPUT1@', '@INPUT2@'
|
||||
],
|
||||
depend_files : [ 'generate/eglFunctionList.py', glapi_xml_py_deps],
|
||||
capture : true,
|
||||
)
|
||||
|
||||
g_egldispatchstubs_h = custom_target(
|
||||
'g_egldispatchstubs.h',
|
||||
input : [
|
||||
'generate/gen_egl_dispatch.py',
|
||||
'generate/egl.xml', 'generate/egl_other.xml'
|
||||
],
|
||||
output : 'g_egldispatchstubs.h',
|
||||
command : [
|
||||
prog_python, '@INPUT0@', gen_args, 'header', '@INPUT1@', '@INPUT2@'
|
||||
],
|
||||
depend_files : [ 'generate/eglFunctionList.py', glapi_xml_py_deps],
|
||||
capture : true,
|
||||
)
|
||||
|
||||
if with_dri
|
||||
files_egl += files(
|
||||
'drivers/dri2/egl_dri2.c',
|
||||
'drivers/dri2/egl_dri2.h',
|
||||
)
|
||||
files_egl += sha1_h
|
||||
files_egl += main_dispatch_h
|
||||
deps_for_egl += idep_xmlconfig
|
||||
link_for_egl += libloader
|
||||
incs_for_egl += inc_loader
|
||||
incs_for_egl += inc_gallium
|
||||
incs_for_egl += inc_gallium_aux
|
||||
incs_for_egl += inc_mesa
|
||||
incs_for_egl += inc_st_dri
|
||||
|
||||
files_egl += files(
|
||||
'drivers/dri2/platform_device.c',
|
||||
'drivers/dri2/platform_surfaceless.c',
|
||||
)
|
||||
|
||||
if with_platform_x11
|
||||
files_egl += files('drivers/dri2/platform_x11.c')
|
||||
incs_for_egl += inc_loader_x11
|
||||
link_for_egl += libloader_x11
|
||||
if with_dri_platform == 'drm' or with_dri_platform == 'pseudo-drm'
|
||||
files_egl += files('drivers/dri2/platform_x11_dri3.c')
|
||||
endif
|
||||
deps_for_egl += [dep_x11_xcb, dep_xcb_xrandr, dep_xcb_xfixes, dep_xcb_shm]
|
||||
endif
|
||||
if with_gbm and not with_platform_android
|
||||
files_egl += files('drivers/dri2/platform_drm.c')
|
||||
incs_for_egl += [include_directories('../gbm/backends/dri')]
|
||||
deps_for_egl += [dep_libdrm, dep_gbm]
|
||||
endif
|
||||
if with_platform_wayland
|
||||
deps_for_egl += [dep_wayland_client, dep_wayland_server, dep_wayland_egl_headers]
|
||||
link_for_egl += libloader_wayland_helper
|
||||
files_egl += files('drivers/dri2/platform_wayland.c')
|
||||
files_egl += wp_files['linux-dmabuf-unstable-v1']
|
||||
files_egl += wp_files['presentation-time']
|
||||
if with_wayland_bind_display
|
||||
files_egl += [wayland_drm_client_protocol_h]
|
||||
link_for_egl += [libwayland_drm]
|
||||
incs_for_egl += include_directories('wayland/wayland-drm')
|
||||
c_args_for_egl += [
|
||||
'-DHAVE_BIND_WL_DISPLAY'
|
||||
]
|
||||
endif
|
||||
endif
|
||||
if with_platform_android
|
||||
deps_for_egl += [dep_android, idep_u_gralloc]
|
||||
files_egl += files('drivers/dri2/platform_android.c')
|
||||
endif
|
||||
elif with_platform_haiku
|
||||
c_args_for_egl += [
|
||||
'-D_EGL_BUILT_IN_DRIVER_HAIKU',
|
||||
]
|
||||
files_egl += files('drivers/haiku/egl_haiku.cpp')
|
||||
|
||||
incs_for_egl += [inc_gallium, inc_gallium_aux, inc_gallium_drivers, inc_gallium_winsys, inc_gallium_winsys_sw]
|
||||
incs_for_egl += [inc_mesa]
|
||||
incs_for_egl += [include_directories('../gallium/frontends/hgl')]
|
||||
|
||||
link_for_egl += [libmesa, libgallium, libswhgl, libsthgl, libglapi]
|
||||
deps_for_egl += [cpp.find_library('be'), driver_swrast]
|
||||
elif with_platform_windows
|
||||
c_args_for_egl += [
|
||||
'-DEGLAPI=', '-DPUBLIC='
|
||||
]
|
||||
files_egl += files('drivers/wgl/egl_wgl.c')
|
||||
files_egl += main_dispatch_h
|
||||
incs_for_egl += [inc_wgl, inc_gallium, inc_gallium_aux, inc_mesa]
|
||||
link_for_egl += libgallium_wgl
|
||||
|
||||
else
|
||||
error('No EGL driver available.')
|
||||
endif
|
||||
|
||||
if cc.has_function('mincore')
|
||||
c_args_for_egl += '-DHAVE_MINCORE'
|
||||
endif
|
||||
|
||||
if not with_glvnd
|
||||
egl_lib_name = 'EGL' + get_option('egl-lib-suffix')
|
||||
egl_lib_version = '1.0.0'
|
||||
egl_lib_soversion = host_machine.system() == 'windows' ? '' : '1'
|
||||
else
|
||||
egl_lib_name = 'EGL_@0@'.format(glvnd_vendor_name)
|
||||
egl_lib_version = '0.0.0'
|
||||
egl_lib_soversion = '0'
|
||||
deps_for_egl += dep_glvnd
|
||||
files_egl += [g_egldispatchstubs_h, g_egldispatchstubs_c]
|
||||
files_egl += files('main/eglglvnd.c', 'main/egldispatchstubs.c')
|
||||
endif
|
||||
|
||||
if with_ld_version_script
|
||||
if with_glvnd
|
||||
link_args_for_egl += [
|
||||
'-Wl,--version-script', join_paths(meson.current_source_dir(), 'egl-glvnd.sym')
|
||||
]
|
||||
link_deps_for_egl += files('egl-glvnd.sym')
|
||||
else
|
||||
link_args_for_egl += [
|
||||
'-Wl,--version-script', join_paths(meson.current_source_dir(), 'egl.sym')
|
||||
]
|
||||
link_deps_for_egl += files('egl.sym')
|
||||
endif
|
||||
endif
|
||||
|
||||
egl_def = custom_target(
|
||||
'egl.def',
|
||||
input: 'main/egl.def.in',
|
||||
output : 'egl.def',
|
||||
command : gen_vs_module_defs_normal_command,
|
||||
)
|
||||
|
||||
libegl = shared_library(
|
||||
egl_lib_name,
|
||||
files_egl,
|
||||
c_args : [
|
||||
c_args_for_egl,
|
||||
'-D_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_@0@'.format(egl_native_platform.to_upper()),
|
||||
],
|
||||
cpp_args : [cpp_args_for_egl],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
include_directories : incs_for_egl,
|
||||
link_with : [link_for_egl],
|
||||
link_args : [ld_args_bsymbolic, ld_args_gc_sections, link_args_for_egl],
|
||||
link_depends : [link_deps_for_egl],
|
||||
dependencies : [deps_for_egl, dep_dl, dep_libdrm, dep_clock, dep_thread, idep_mesautil],
|
||||
install : true,
|
||||
version : egl_lib_version,
|
||||
soversion : egl_lib_soversion,
|
||||
name_prefix : host_machine.system() == 'windows' ? 'lib' : [], # always use lib, but avoid warnings on !windows
|
||||
vs_module_defs : egl_def
|
||||
)
|
||||
|
||||
if with_glvnd
|
||||
configure_file(
|
||||
configuration: {'library_path' : 'libEGL_@[email protected]'.format(glvnd_vendor_name)},
|
||||
input : 'main/50_mesa.json',
|
||||
output: '50_@[email protected]'.format(glvnd_vendor_name),
|
||||
install : true,
|
||||
install_tag : 'runtime',
|
||||
install_dir : join_paths(get_option('datadir'), 'glvnd', 'egl_vendor.d')
|
||||
)
|
||||
|
||||
devenv_glvnd_egl_json_file = configure_file(
|
||||
configuration: {'library_path' : libegl.full_path()},
|
||||
input : 'main/50_mesa.json',
|
||||
output: 'devenv_glvnd_egl.json',
|
||||
)
|
||||
devenv.set('__EGL_VENDOR_LIBRARY_FILENAMES', devenv_glvnd_egl_json_file.full_path())
|
||||
else
|
||||
pkg.generate(
|
||||
name : 'egl',
|
||||
description : 'Mesa EGL Library',
|
||||
version : meson.project_version(),
|
||||
libraries : libegl,
|
||||
libraries_private: gl_priv_libs,
|
||||
requires_private : gl_priv_reqs,
|
||||
extra_cflags : gl_pkgconfig_c_flags,
|
||||
)
|
||||
endif
|
||||
|
||||
if with_symbols_check
|
||||
if with_glvnd
|
||||
egl_symbols = files('egl-glvnd-symbols.txt')
|
||||
else
|
||||
egl_symbols = files('egl-symbols.txt')
|
||||
endif
|
||||
test('egl-symbols-check',
|
||||
symbols_check,
|
||||
args : [
|
||||
'--lib', libegl,
|
||||
'--symbols-file', egl_symbols,
|
||||
symbols_check_args,
|
||||
],
|
||||
suite : ['egl'],
|
||||
)
|
||||
test('egl-entrypoint-check',
|
||||
prog_python,
|
||||
args : files('egl-entrypoint-check.py', 'main/eglentrypoint.h'),
|
||||
suite : ['egl'],
|
||||
)
|
||||
endif
|
||||
@@ -0,0 +1,2 @@
|
||||
[*.{c,h}]
|
||||
indent_style = tab
|
||||
@@ -0,0 +1,18 @@
|
||||
# Copyright © 2017 Intel Corporation
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
inc_wayland_drm = include_directories('.')
|
||||
|
||||
_wl_drm = mod_wl.scan_xml('wayland-drm.xml', server : true, include_core_only : false)
|
||||
wayland_drm_protocol_c = _wl_drm[0]
|
||||
wayland_drm_client_protocol_h = _wl_drm[1]
|
||||
wayland_drm_server_protocol_h = _wl_drm[2]
|
||||
|
||||
libwayland_drm = static_library(
|
||||
'wayland_drm',
|
||||
['wayland-drm.c', wayland_drm_protocol_c, wayland_drm_server_protocol_h],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
dependencies : [dep_wayland_server],
|
||||
include_directories : inc_include,
|
||||
build_by_default : false,
|
||||
)
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* Copyright © 2011 Benjamin Franzke
|
||||
*
|
||||
* 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 (including the next
|
||||
* paragraph) 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.
|
||||
*
|
||||
* Authors:
|
||||
* Kristian Høgsberg <[email protected]>
|
||||
* Benjamin Franzke <[email protected]>
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "EGL/egl.h"
|
||||
#include "EGL/eglext.h"
|
||||
|
||||
#include "wayland-drm-server-protocol.h"
|
||||
#include "wayland-drm.h"
|
||||
#include <wayland-server.h>
|
||||
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
static void
|
||||
destroy_buffer(struct wl_resource *resource)
|
||||
{
|
||||
struct wl_drm_buffer *buffer = wl_resource_get_user_data(resource);
|
||||
struct wl_drm *drm = buffer->drm;
|
||||
|
||||
drm->callbacks.release_buffer(drm->user_data, buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_destroy(struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_create_buffer(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, uint32_t name, int32_t width, int32_t height,
|
||||
uint32_t stride, uint32_t format)
|
||||
{
|
||||
wl_resource_post_error(resource, WL_DRM_ERROR_INVALID_NAME,
|
||||
"global GEM names are no longer supported");
|
||||
}
|
||||
|
||||
static void
|
||||
drm_create_planar_buffer(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, uint32_t name, int32_t width,
|
||||
int32_t height, uint32_t format, int32_t offset0,
|
||||
int32_t stride0, int32_t offset1, int32_t stride1,
|
||||
int32_t offset2, int32_t stride2)
|
||||
{
|
||||
wl_resource_post_error(resource, WL_DRM_ERROR_INVALID_NAME,
|
||||
"global GEM names are no longer supported");
|
||||
}
|
||||
|
||||
static void
|
||||
drm_create_prime_buffer(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id, int fd, int32_t width, int32_t height,
|
||||
uint32_t format, int32_t offset0, int32_t stride0,
|
||||
int32_t offset1, int32_t stride1, int32_t offset2,
|
||||
int32_t stride2)
|
||||
{
|
||||
struct wl_drm *drm = wl_resource_get_user_data(resource);
|
||||
struct wl_drm_buffer *buffer;
|
||||
|
||||
buffer = calloc(1, sizeof *buffer);
|
||||
if (buffer == NULL) {
|
||||
wl_resource_post_no_memory(resource);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->drm = drm;
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
buffer->format = format;
|
||||
buffer->offset[0] = offset0;
|
||||
buffer->stride[0] = stride0;
|
||||
buffer->offset[1] = offset1;
|
||||
buffer->stride[1] = stride1;
|
||||
buffer->offset[2] = offset2;
|
||||
buffer->stride[2] = stride2;
|
||||
|
||||
switch (format) {
|
||||
case WL_DRM_FORMAT_ARGB2101010:
|
||||
case WL_DRM_FORMAT_ABGR2101010:
|
||||
case WL_DRM_FORMAT_ARGB8888:
|
||||
buffer->egl_components = EGL_TEXTURE_RGBA;
|
||||
break;
|
||||
case WL_DRM_FORMAT_XRGB2101010:
|
||||
case WL_DRM_FORMAT_XBGR2101010:
|
||||
case WL_DRM_FORMAT_XRGB8888:
|
||||
case WL_DRM_FORMAT_BGR888:
|
||||
case WL_DRM_FORMAT_RGB888:
|
||||
case WL_DRM_FORMAT_RGB565:
|
||||
buffer->egl_components = EGL_TEXTURE_RGB;
|
||||
break;
|
||||
case WL_DRM_FORMAT_YUV410:
|
||||
case WL_DRM_FORMAT_YUV411:
|
||||
case WL_DRM_FORMAT_YUV420:
|
||||
case WL_DRM_FORMAT_YUV422:
|
||||
case WL_DRM_FORMAT_YUV444:
|
||||
buffer->egl_components = EGL_TEXTURE_Y_U_V_WL;
|
||||
break;
|
||||
case WL_DRM_FORMAT_NV12:
|
||||
case WL_DRM_FORMAT_NV16:
|
||||
buffer->egl_components = EGL_TEXTURE_Y_UV_WL;
|
||||
break;
|
||||
case WL_DRM_FORMAT_YUYV:
|
||||
buffer->egl_components = EGL_TEXTURE_Y_XUXV_WL;
|
||||
break;
|
||||
}
|
||||
|
||||
drm->callbacks.reference_buffer(drm->user_data, fd, buffer);
|
||||
close(fd);
|
||||
if (buffer->driver_buffer == NULL) {
|
||||
wl_resource_post_error(resource, WL_DRM_ERROR_INVALID_NAME,
|
||||
"invalid name");
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id);
|
||||
if (!buffer->resource) {
|
||||
wl_resource_post_no_memory(resource);
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation(buffer->resource,
|
||||
(void (**)(void)) & drm->buffer_interface,
|
||||
buffer, destroy_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_authenticate(struct wl_client *client, struct wl_resource *resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_drm *drm = wl_resource_get_user_data(resource);
|
||||
|
||||
if (!drm->callbacks.authenticate ||
|
||||
drm->callbacks.authenticate(drm->user_data, id) < 0)
|
||||
wl_resource_post_error(resource, WL_DRM_ERROR_AUTHENTICATE_FAIL,
|
||||
"authenticate failed");
|
||||
else
|
||||
wl_resource_post_event(resource, WL_DRM_AUTHENTICATED);
|
||||
}
|
||||
|
||||
static const struct wl_drm_interface drm_interface = {
|
||||
drm_authenticate,
|
||||
drm_create_buffer,
|
||||
drm_create_planar_buffer,
|
||||
drm_create_prime_buffer,
|
||||
};
|
||||
|
||||
static void
|
||||
bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
||||
{
|
||||
struct wl_drm *drm = data;
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource =
|
||||
wl_resource_create(client, &wl_drm_interface, MIN(version, 2), id);
|
||||
if (!resource) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation(resource, &drm_interface, data, NULL);
|
||||
|
||||
wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name);
|
||||
|
||||
if (drm->callbacks.is_format_supported(drm->user_data,
|
||||
WL_DRM_FORMAT_ARGB2101010)) {
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT,
|
||||
WL_DRM_FORMAT_ARGB2101010);
|
||||
}
|
||||
|
||||
if (drm->callbacks.is_format_supported(drm->user_data,
|
||||
WL_DRM_FORMAT_XRGB2101010)) {
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT,
|
||||
WL_DRM_FORMAT_XRGB2101010);
|
||||
}
|
||||
|
||||
if (drm->callbacks.is_format_supported(drm->user_data,
|
||||
WL_DRM_FORMAT_ABGR2101010)) {
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT,
|
||||
WL_DRM_FORMAT_ABGR2101010);
|
||||
}
|
||||
|
||||
if (drm->callbacks.is_format_supported(drm->user_data,
|
||||
WL_DRM_FORMAT_XBGR2101010)) {
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT,
|
||||
WL_DRM_FORMAT_XBGR2101010);
|
||||
}
|
||||
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_ARGB8888);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_XRGB8888);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_BGR888);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_RGB888);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_RGB565);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV410);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV411);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV420);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV422);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUV444);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV12);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_NV16);
|
||||
wl_resource_post_event(resource, WL_DRM_FORMAT, WL_DRM_FORMAT_YUYV);
|
||||
|
||||
if (version >= 2) {
|
||||
wl_resource_post_event(resource, WL_DRM_CAPABILITIES,
|
||||
WL_DRM_CAPABILITY_PRIME);
|
||||
}
|
||||
}
|
||||
|
||||
struct wl_drm *
|
||||
wayland_drm_init(struct wl_display *display, char *device_name,
|
||||
const struct wayland_drm_callbacks *callbacks, void *user_data)
|
||||
{
|
||||
struct wl_drm *drm;
|
||||
|
||||
drm = malloc(sizeof *drm);
|
||||
if (!drm)
|
||||
return NULL;
|
||||
|
||||
drm->display = display;
|
||||
drm->device_name = strdup(device_name);
|
||||
drm->callbacks = *callbacks;
|
||||
drm->user_data = user_data;
|
||||
|
||||
drm->buffer_interface.destroy = buffer_destroy;
|
||||
|
||||
drm->wl_drm_global =
|
||||
wl_global_create(display, &wl_drm_interface, 2, drm, bind_drm);
|
||||
|
||||
return drm;
|
||||
}
|
||||
|
||||
void
|
||||
wayland_drm_uninit(struct wl_drm *drm)
|
||||
{
|
||||
free(drm->device_name);
|
||||
|
||||
wl_global_destroy(drm->wl_drm_global);
|
||||
|
||||
free(drm);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef WAYLAND_DRM_H
|
||||
#define WAYLAND_DRM_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
struct wl_display;
|
||||
struct wl_resource;
|
||||
struct wl_drm_buffer;
|
||||
|
||||
struct wayland_drm_callbacks {
|
||||
int (*authenticate)(void *user_data, uint32_t id);
|
||||
|
||||
void (*reference_buffer)(void *user_data, int fd,
|
||||
struct wl_drm_buffer *buffer);
|
||||
|
||||
void (*release_buffer)(void *user_data, struct wl_drm_buffer *buffer);
|
||||
|
||||
bool (*is_format_supported)(void *user_data, uint32_t format);
|
||||
};
|
||||
|
||||
struct wl_drm {
|
||||
struct wl_display *display;
|
||||
struct wl_global *wl_drm_global;
|
||||
|
||||
void *user_data;
|
||||
char *device_name;
|
||||
|
||||
struct wayland_drm_callbacks callbacks;
|
||||
|
||||
struct wl_buffer_interface buffer_interface;
|
||||
};
|
||||
|
||||
struct wl_drm_buffer {
|
||||
struct wl_resource *resource;
|
||||
struct wl_drm *drm;
|
||||
int32_t width, height;
|
||||
uint32_t format;
|
||||
uint32_t egl_components;
|
||||
int32_t offset[3];
|
||||
int32_t stride[3];
|
||||
void *driver_buffer;
|
||||
};
|
||||
|
||||
static inline struct wl_drm_buffer *
|
||||
wayland_drm_buffer_get(struct wl_drm *drm, struct wl_resource *resource)
|
||||
{
|
||||
if (resource == NULL)
|
||||
return NULL;
|
||||
|
||||
if (wl_resource_instance_of(resource, &wl_buffer_interface,
|
||||
&drm->buffer_interface))
|
||||
return wl_resource_get_user_data(resource);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wl_drm *
|
||||
wayland_drm_init(struct wl_display *display, char *device_name,
|
||||
const struct wayland_drm_callbacks *callbacks, void *user_data);
|
||||
|
||||
void
|
||||
wayland_drm_uninit(struct wl_drm *drm);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="drm">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2008-2011 Kristian Høgsberg
|
||||
Copyright © 2010-2011 Intel Corporation
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that\n the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<!-- drm support. This object is created by the server and published
|
||||
using the display's global event. -->
|
||||
<interface name="wl_drm" version="2">
|
||||
<enum name="error">
|
||||
<entry name="authenticate_fail" value="0"/>
|
||||
<entry name="invalid_format" value="1"/>
|
||||
<entry name="invalid_name" value="2"/>
|
||||
</enum>
|
||||
|
||||
<enum name="format">
|
||||
<!-- The drm format codes match the #defines in drm_fourcc.h.
|
||||
The formats actually supported by the compositor will be
|
||||
reported by the format event. New codes must not be added,
|
||||
unless directly taken from drm_fourcc.h. -->
|
||||
<entry name="c8" value="0x20203843"/>
|
||||
<entry name="rgb332" value="0x38424752"/>
|
||||
<entry name="bgr233" value="0x38524742"/>
|
||||
<entry name="xrgb4444" value="0x32315258"/>
|
||||
<entry name="xbgr4444" value="0x32314258"/>
|
||||
<entry name="rgbx4444" value="0x32315852"/>
|
||||
<entry name="bgrx4444" value="0x32315842"/>
|
||||
<entry name="argb4444" value="0x32315241"/>
|
||||
<entry name="abgr4444" value="0x32314241"/>
|
||||
<entry name="rgba4444" value="0x32314152"/>
|
||||
<entry name="bgra4444" value="0x32314142"/>
|
||||
<entry name="xrgb1555" value="0x35315258"/>
|
||||
<entry name="xbgr1555" value="0x35314258"/>
|
||||
<entry name="rgbx5551" value="0x35315852"/>
|
||||
<entry name="bgrx5551" value="0x35315842"/>
|
||||
<entry name="argb1555" value="0x35315241"/>
|
||||
<entry name="abgr1555" value="0x35314241"/>
|
||||
<entry name="rgba5551" value="0x35314152"/>
|
||||
<entry name="bgra5551" value="0x35314142"/>
|
||||
<entry name="rgb565" value="0x36314752"/>
|
||||
<entry name="bgr565" value="0x36314742"/>
|
||||
<entry name="rgb888" value="0x34324752"/>
|
||||
<entry name="bgr888" value="0x34324742"/>
|
||||
<entry name="xrgb8888" value="0x34325258"/>
|
||||
<entry name="xbgr8888" value="0x34324258"/>
|
||||
<entry name="rgbx8888" value="0x34325852"/>
|
||||
<entry name="bgrx8888" value="0x34325842"/>
|
||||
<entry name="argb8888" value="0x34325241"/>
|
||||
<entry name="abgr8888" value="0x34324241"/>
|
||||
<entry name="rgba8888" value="0x34324152"/>
|
||||
<entry name="bgra8888" value="0x34324142"/>
|
||||
<entry name="xrgb2101010" value="0x30335258"/>
|
||||
<entry name="xbgr2101010" value="0x30334258"/>
|
||||
<entry name="rgbx1010102" value="0x30335852"/>
|
||||
<entry name="bgrx1010102" value="0x30335842"/>
|
||||
<entry name="argb2101010" value="0x30335241"/>
|
||||
<entry name="abgr2101010" value="0x30334241"/>
|
||||
<entry name="rgba1010102" value="0x30334152"/>
|
||||
<entry name="bgra1010102" value="0x30334142"/>
|
||||
<entry name="yuyv" value="0x56595559"/>
|
||||
<entry name="yvyu" value="0x55595659"/>
|
||||
<entry name="uyvy" value="0x59565955"/>
|
||||
<entry name="vyuy" value="0x59555956"/>
|
||||
<entry name="ayuv" value="0x56555941"/>
|
||||
<entry name="xyuv8888" value="0x56555958"/>
|
||||
<entry name="nv12" value="0x3231564e"/>
|
||||
<entry name="nv21" value="0x3132564e"/>
|
||||
<entry name="nv16" value="0x3631564e"/>
|
||||
<entry name="nv61" value="0x3136564e"/>
|
||||
<entry name="yuv410" value="0x39565559"/>
|
||||
<entry name="yvu410" value="0x39555659"/>
|
||||
<entry name="yuv411" value="0x31315559"/>
|
||||
<entry name="yvu411" value="0x31315659"/>
|
||||
<entry name="yuv420" value="0x32315559"/>
|
||||
<entry name="yvu420" value="0x32315659"/>
|
||||
<entry name="yuv422" value="0x36315559"/>
|
||||
<entry name="yvu422" value="0x36315659"/>
|
||||
<entry name="yuv444" value="0x34325559"/>
|
||||
<entry name="yvu444" value="0x34325659"/>
|
||||
<entry name="abgr16f" value="0x48344241"/>
|
||||
<entry name="xbgr16f" value="0x48344258"/>
|
||||
</enum>
|
||||
|
||||
<!-- Call this request with the magic received from drmGetMagic().
|
||||
It will be passed on to the drmAuthMagic() or
|
||||
DRIAuthConnection() call. This authentication must be
|
||||
completed before create_buffer could be used. -->
|
||||
<request name="authenticate">
|
||||
<arg name="id" type="uint"/>
|
||||
</request>
|
||||
|
||||
<!-- Create a wayland buffer for the named DRM buffer. The DRM
|
||||
surface must have a name using the flink ioctl -->
|
||||
<request name="create_buffer">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="uint"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="stride" type="uint"/>
|
||||
<arg name="format" type="uint"/>
|
||||
</request>
|
||||
|
||||
<!-- Create a wayland buffer for the named DRM buffer. The DRM
|
||||
surface must have a name using the flink ioctl -->
|
||||
<request name="create_planar_buffer">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="uint"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="format" type="uint"/>
|
||||
<arg name="offset0" type="int"/>
|
||||
<arg name="stride0" type="int"/>
|
||||
<arg name="offset1" type="int"/>
|
||||
<arg name="stride1" type="int"/>
|
||||
<arg name="offset2" type="int"/>
|
||||
<arg name="stride2" type="int"/>
|
||||
</request>
|
||||
|
||||
<!-- Notification of the path of the drm device which is used by
|
||||
the server. The client should use this device for creating
|
||||
local buffers. Only buffers created from this device should
|
||||
be be passed to the server using this drm object's
|
||||
create_buffer request. -->
|
||||
<event name="device">
|
||||
<arg name="name" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="format">
|
||||
<arg name="format" type="uint"/>
|
||||
</event>
|
||||
|
||||
<!-- Raised if the authenticate request succeeded -->
|
||||
<event name="authenticated"/>
|
||||
|
||||
<enum name="capability" since="2">
|
||||
<description summary="wl_drm capability bitmask">
|
||||
Bitmask of capabilities.
|
||||
</description>
|
||||
<entry name="prime" value="1" summary="wl_drm prime available"/>
|
||||
</enum>
|
||||
|
||||
<event name="capabilities">
|
||||
<arg name="value" type="uint"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<!-- Create a wayland buffer for the prime fd. Use for regular and planar
|
||||
buffers. Pass 0 for offset and stride for unused planes. -->
|
||||
<request name="create_prime_buffer" since="2">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="fd"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="format" type="uint"/>
|
||||
<arg name="offset0" type="int"/>
|
||||
<arg name="stride0" type="int"/>
|
||||
<arg name="offset1" type="int"/>
|
||||
<arg name="stride1" type="int"/>
|
||||
<arg name="offset2" type="int"/>
|
||||
<arg name="stride2" type="int"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
Reference in new issue
Block a user