commit
30b8fb5572
@ -1,149 +0,0 @@
|
|||||||
#ifndef WLR_RENDER_H
|
|
||||||
#define WLR_RENDER_H
|
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
|
||||||
#include <EGL/eglext.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <wayland-server-protocol.h>
|
|
||||||
#include <wlr/types/wlr_box.h>
|
|
||||||
#include <wlr/types/wlr_output.h>
|
|
||||||
|
|
||||||
struct wlr_texture;
|
|
||||||
struct wlr_renderer;
|
|
||||||
|
|
||||||
void wlr_renderer_begin(struct wlr_renderer *r, struct wlr_output *output);
|
|
||||||
void wlr_renderer_end(struct wlr_renderer *r);
|
|
||||||
void wlr_renderer_clear(struct wlr_renderer *r, const float (*color)[4]);
|
|
||||||
/**
|
|
||||||
* Defines a scissor box. Only pixels that lie within the scissor box can be
|
|
||||||
* modified by drawing functions. Providing a NULL `box` disables the scissor
|
|
||||||
* box.
|
|
||||||
*/
|
|
||||||
void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box);
|
|
||||||
/**
|
|
||||||
* Requests a texture handle from this renderer.
|
|
||||||
*/
|
|
||||||
struct wlr_texture *wlr_render_texture_create(struct wlr_renderer *r);
|
|
||||||
/**
|
|
||||||
* Renders the requested texture using the provided matrix. A typical texture
|
|
||||||
* rendering goes like so:
|
|
||||||
*
|
|
||||||
* struct wlr_renderer *renderer;
|
|
||||||
* struct wlr_texture *texture;
|
|
||||||
* float projection[16];
|
|
||||||
* float matrix[16];
|
|
||||||
* wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
|
|
||||||
* wlr_render_with_matrix(renderer, texture, &matrix, 0.5f);
|
|
||||||
*
|
|
||||||
* This will render the texture at <123, 321> with an alpha channel of 0.5.
|
|
||||||
*/
|
|
||||||
bool wlr_render_with_matrix(struct wlr_renderer *r,
|
|
||||||
struct wlr_texture *texture, const float (*matrix)[16], float alpha);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a solid quad in the specified color.
|
|
||||||
*/
|
|
||||||
void wlr_render_colored_quad(struct wlr_renderer *r,
|
|
||||||
const float (*color)[4], const float (*matrix)[16]);
|
|
||||||
/**
|
|
||||||
* Renders a solid ellipse in the specified color.
|
|
||||||
*/
|
|
||||||
void wlr_render_colored_ellipse(struct wlr_renderer *r,
|
|
||||||
const float (*color)[4], const float (*matrix)[16]);
|
|
||||||
/**
|
|
||||||
* Returns a list of pixel formats supported by this renderer.
|
|
||||||
*/
|
|
||||||
const enum wl_shm_format *wlr_renderer_get_formats(
|
|
||||||
struct wlr_renderer *r, size_t *len);
|
|
||||||
/**
|
|
||||||
* Returns true if this wl_buffer is a DRM buffer.
|
|
||||||
*/
|
|
||||||
bool wlr_renderer_buffer_is_drm(struct wlr_renderer *renderer,
|
|
||||||
struct wl_resource *buffer);
|
|
||||||
/**
|
|
||||||
* Reads out of pixels of the currently bound surface into data. `stride` is in
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
|
|
||||||
uint32_t stride, uint32_t width, uint32_t height,
|
|
||||||
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, void *data);
|
|
||||||
/**
|
|
||||||
* Checks if a format is supported.
|
|
||||||
*/
|
|
||||||
bool wlr_renderer_format_supported(struct wlr_renderer *r,
|
|
||||||
enum wl_shm_format fmt);
|
|
||||||
/**
|
|
||||||
* Destroys this wlr_renderer. Textures must be destroyed separately.
|
|
||||||
*/
|
|
||||||
void wlr_renderer_destroy(struct wlr_renderer *renderer);
|
|
||||||
|
|
||||||
struct wlr_texture_impl;
|
|
||||||
|
|
||||||
struct wlr_texture {
|
|
||||||
struct wlr_texture_impl *impl;
|
|
||||||
|
|
||||||
bool valid;
|
|
||||||
uint32_t format;
|
|
||||||
int width, height;
|
|
||||||
struct wl_signal destroy_signal;
|
|
||||||
struct wl_resource *resource;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies pixels to this texture. The buffer is not accessed after this function
|
|
||||||
* returns.
|
|
||||||
*/
|
|
||||||
bool wlr_texture_upload_pixels(struct wlr_texture *tex,
|
|
||||||
enum wl_shm_format format, int stride, int width, int height,
|
|
||||||
const unsigned char *pixels);
|
|
||||||
/**
|
|
||||||
* Copies pixels to this texture. The buffer is not accessed after this function
|
|
||||||
* returns. Under some circumstances, this function may re-upload the entire
|
|
||||||
* buffer - therefore, the entire buffer must be valid.
|
|
||||||
*/
|
|
||||||
bool wlr_texture_update_pixels(struct wlr_texture *surf,
|
|
||||||
enum wl_shm_format format, int stride, int x, int y,
|
|
||||||
int width, int height, const unsigned char *pixels);
|
|
||||||
/**
|
|
||||||
* Copies pixels from a wl_shm_buffer into this texture. The buffer is not
|
|
||||||
* accessed after this function returns.
|
|
||||||
*/
|
|
||||||
bool wlr_texture_upload_shm(struct wlr_texture *tex, uint32_t format,
|
|
||||||
struct wl_shm_buffer *shm);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attaches the contents from the given wl_drm wl_buffer resource onto the
|
|
||||||
* texture. The wl_resource is not used after this call.
|
|
||||||
* Will fail (return false) if the given resource is no drm buffer.
|
|
||||||
*/
|
|
||||||
bool wlr_texture_upload_drm(struct wlr_texture *tex,
|
|
||||||
struct wl_resource *drm_buffer);
|
|
||||||
|
|
||||||
bool wlr_texture_upload_eglimage(struct wlr_texture *tex,
|
|
||||||
EGLImageKHR image, uint32_t width, uint32_t height);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies a rectangle of pixels from a wl_shm_buffer onto the texture. The
|
|
||||||
* buffer is not accessed after this function returns. Under some circumstances,
|
|
||||||
* this function may re-upload the entire buffer - therefore, the entire buffer
|
|
||||||
* must be valid.
|
|
||||||
*/
|
|
||||||
bool wlr_texture_update_shm(struct wlr_texture *surf, uint32_t format,
|
|
||||||
int x, int y, int width, int height, struct wl_shm_buffer *shm);
|
|
||||||
/**
|
|
||||||
* Prepares a matrix with the appropriate scale for the given texture and
|
|
||||||
* multiplies it with the projection, producing a matrix that the shader can
|
|
||||||
* muptlipy vertex coordinates with to get final screen coordinates.
|
|
||||||
*
|
|
||||||
* The projection matrix is assumed to be an orthographic projection of [0,
|
|
||||||
* width) and [0, height], and the x and y coordinates provided are used as
|
|
||||||
* such.
|
|
||||||
*/
|
|
||||||
void wlr_texture_get_matrix(struct wlr_texture *texture,
|
|
||||||
float (*matrix)[16], const float (*projection)[16], int x, int y);
|
|
||||||
/**
|
|
||||||
* Destroys this wlr_texture.
|
|
||||||
*/
|
|
||||||
void wlr_texture_destroy(struct wlr_texture *texture);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||||||
#ifndef WLR_RENDER_MATRIX_H
|
|
||||||
#define WLR_RENDER_MATRIX_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <wlr/types/wlr_box.h>
|
|
||||||
|
|
||||||
void wlr_matrix_identity(float (*output)[16]);
|
|
||||||
void wlr_matrix_translate(float (*output)[16], float x, float y, float z);
|
|
||||||
void wlr_matrix_scale(float (*output)[16], float x, float y, float z);
|
|
||||||
void wlr_matrix_rotate(float (*output)[16], float radians);
|
|
||||||
void wlr_matrix_mul(const float (*x)[16], const float (*y)[16], float (*product)[16]);
|
|
||||||
|
|
||||||
enum wl_output_transform;
|
|
||||||
void wlr_matrix_transform(float mat[static 16],
|
|
||||||
enum wl_output_transform transform);
|
|
||||||
void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height,
|
|
||||||
enum wl_output_transform transform);
|
|
||||||
void wlr_matrix_project_box(float (*mat)[16], struct wlr_box *box,
|
|
||||||
enum wl_output_transform transform, float rotation, float
|
|
||||||
(*projection)[16]);
|
|
||||||
|
|
||||||
#endif
|
|
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef WLR_RENDER_WLR_RENDERER_H
|
||||||
|
#define WLR_RENDER_WLR_RENDERER_H
|
||||||
|
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <wayland-server-protocol.h>
|
||||||
|
#include <wlr/render/wlr_texture.h>
|
||||||
|
#include <wlr/types/wlr_box.h>
|
||||||
|
|
||||||
|
struct wlr_output;
|
||||||
|
|
||||||
|
struct wlr_renderer;
|
||||||
|
|
||||||
|
void wlr_renderer_begin(struct wlr_renderer *r, int width, int height);
|
||||||
|
void wlr_renderer_end(struct wlr_renderer *r);
|
||||||
|
void wlr_renderer_clear(struct wlr_renderer *r, const float color[static 4]);
|
||||||
|
/**
|
||||||
|
* Defines a scissor box. Only pixels that lie within the scissor box can be
|
||||||
|
* modified by drawing functions. Providing a NULL `box` disables the scissor
|
||||||
|
* box.
|
||||||
|
*/
|
||||||
|
void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box);
|
||||||
|
/**
|
||||||
|
* Requests a texture handle from this renderer.
|
||||||
|
*/
|
||||||
|
struct wlr_texture *wlr_render_texture_create(struct wlr_renderer *r);
|
||||||
|
/**
|
||||||
|
* Renders the requested texture.
|
||||||
|
*/
|
||||||
|
bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture,
|
||||||
|
const float projection[static 9], int x, int y, float alpha);
|
||||||
|
/**
|
||||||
|
* Renders the requested texture using the provided matrix.
|
||||||
|
*/
|
||||||
|
bool wlr_render_texture_with_matrix(struct wlr_renderer *r,
|
||||||
|
struct wlr_texture *texture, const float matrix[static 9], float alpha);
|
||||||
|
/**
|
||||||
|
* Renders a solid quad in the specified color.
|
||||||
|
*/
|
||||||
|
void wlr_render_colored_quad(struct wlr_renderer *r,
|
||||||
|
const float color[static 4], const float matrix[static 9]);
|
||||||
|
/**
|
||||||
|
* Renders a solid ellipse in the specified color.
|
||||||
|
*/
|
||||||
|
void wlr_render_colored_ellipse(struct wlr_renderer *r,
|
||||||
|
const float color[static 4], const float matrix[static 9]);
|
||||||
|
/**
|
||||||
|
* Returns a list of pixel formats supported by this renderer.
|
||||||
|
*/
|
||||||
|
const enum wl_shm_format *wlr_renderer_get_formats(struct wlr_renderer *r,
|
||||||
|
size_t *len);
|
||||||
|
/**
|
||||||
|
* Returns true if this wl_buffer is a DRM buffer.
|
||||||
|
*/
|
||||||
|
bool wlr_renderer_buffer_is_drm(struct wlr_renderer *renderer,
|
||||||
|
struct wl_resource *buffer);
|
||||||
|
/**
|
||||||
|
* Reads out of pixels of the currently bound surface into data. `stride` is in
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
|
||||||
|
uint32_t stride, uint32_t width, uint32_t height,
|
||||||
|
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, void *data);
|
||||||
|
/**
|
||||||
|
* Checks if a format is supported.
|
||||||
|
*/
|
||||||
|
bool wlr_renderer_format_supported(struct wlr_renderer *r,
|
||||||
|
enum wl_shm_format fmt);
|
||||||
|
/**
|
||||||
|
* Destroys this wlr_renderer. Textures must be destroyed separately.
|
||||||
|
*/
|
||||||
|
void wlr_renderer_destroy(struct wlr_renderer *renderer);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef WLR_RENDER_WLR_TEXTURE_H
|
||||||
|
#define WLR_RENDER_WLR_TEXTURE_H
|
||||||
|
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <wayland-server-protocol.h>
|
||||||
|
|
||||||
|
struct wlr_texture_impl;
|
||||||
|
|
||||||
|
struct wlr_texture {
|
||||||
|
const struct wlr_texture_impl *impl;
|
||||||
|
|
||||||
|
bool valid;
|
||||||
|
uint32_t format;
|
||||||
|
int width, height;
|
||||||
|
bool inverted_y;
|
||||||
|
struct wl_signal destroy_signal;
|
||||||
|
struct wl_resource *resource;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies pixels to this texture. The buffer is not accessed after this function
|
||||||
|
* returns.
|
||||||
|
*/
|
||||||
|
bool wlr_texture_upload_pixels(struct wlr_texture *tex,
|
||||||
|
enum wl_shm_format format, int stride, int width, int height,
|
||||||
|
const unsigned char *pixels);
|
||||||
|
/**
|
||||||
|
* Copies pixels to this texture. The buffer is not accessed after this function
|
||||||
|
* returns. Under some circumstances, this function may re-upload the entire
|
||||||
|
* buffer - therefore, the entire buffer must be valid.
|
||||||
|
*/
|
||||||
|
bool wlr_texture_update_pixels(struct wlr_texture *surf,
|
||||||
|
enum wl_shm_format format, int stride, int x, int y,
|
||||||
|
int width, int height, const unsigned char *pixels);
|
||||||
|
/**
|
||||||
|
* Copies pixels from a wl_shm_buffer into this texture. The buffer is not
|
||||||
|
* accessed after this function returns.
|
||||||
|
*/
|
||||||
|
bool wlr_texture_upload_shm(struct wlr_texture *tex, uint32_t format,
|
||||||
|
struct wl_shm_buffer *shm);
|
||||||
|
/**
|
||||||
|
* Attaches the contents from the given wl_drm wl_buffer resource onto the
|
||||||
|
* texture. The wl_resource is not used after this call.
|
||||||
|
* Will fail (return false) if the given resource is no drm buffer.
|
||||||
|
*/
|
||||||
|
bool wlr_texture_upload_drm(struct wlr_texture *tex,
|
||||||
|
struct wl_resource *drm_buffer);
|
||||||
|
|
||||||
|
bool wlr_texture_upload_eglimage(struct wlr_texture *tex,
|
||||||
|
EGLImageKHR image, uint32_t width, uint32_t height);
|
||||||
|
|
||||||
|
bool wlr_texture_upload_dmabuf(struct wlr_texture *tex,
|
||||||
|
struct wl_resource *dmabuf_resource);
|
||||||
|
/**
|
||||||
|
* Copies a rectangle of pixels from a wl_shm_buffer onto the texture. The
|
||||||
|
* buffer is not accessed after this function returns. Under some circumstances,
|
||||||
|
* this function may re-upload the entire buffer - therefore, the entire buffer
|
||||||
|
* must be valid.
|
||||||
|
*/
|
||||||
|
bool wlr_texture_update_shm(struct wlr_texture *surf, uint32_t format,
|
||||||
|
int x, int y, int width, int height, struct wl_shm_buffer *shm);
|
||||||
|
/**
|
||||||
|
* Destroys this wlr_texture.
|
||||||
|
*/
|
||||||
|
void wlr_texture_destroy(struct wlr_texture *texture);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,84 @@
|
|||||||
|
#ifndef WLR_TYPES_WLR_LINUX_DMABUF_H
|
||||||
|
#define WLR_TYPES_WLR_LINUX_DMABUF_H
|
||||||
|
|
||||||
|
#define WLR_LINUX_DMABUF_MAX_PLANES 4
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <wayland-server-protocol.h>
|
||||||
|
|
||||||
|
/* So we don't have to pull in linux specific drm headers */
|
||||||
|
#ifndef DRM_FORMAT_MOD_INVALID
|
||||||
|
#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer_attribs {
|
||||||
|
/* set via params_add */
|
||||||
|
int n_planes;
|
||||||
|
uint32_t offset[WLR_LINUX_DMABUF_MAX_PLANES];
|
||||||
|
uint32_t stride[WLR_LINUX_DMABUF_MAX_PLANES];
|
||||||
|
uint64_t modifier[WLR_LINUX_DMABUF_MAX_PLANES];
|
||||||
|
int fd[WLR_LINUX_DMABUF_MAX_PLANES];
|
||||||
|
/* set via params_create */
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t flags; /* enum zlinux_buffer_params_flags */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer {
|
||||||
|
struct wlr_egl *egl;
|
||||||
|
struct wl_resource *buffer_resource;
|
||||||
|
struct wl_resource *params_resource;
|
||||||
|
struct wlr_dmabuf_buffer_attribs attributes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given resource was created via the linux-dmabuf
|
||||||
|
* buffer protocol, false otherwise
|
||||||
|
*/
|
||||||
|
bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the wlr_dmabuf_buffer if the given resource was created
|
||||||
|
* via the linux-dmabuf buffer protocol
|
||||||
|
*/
|
||||||
|
struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
|
||||||
|
struct wl_resource *buffer_resource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the wlr_dmabuf_buffer if the given resource was created
|
||||||
|
* via the linux-dmabuf params protocol
|
||||||
|
*/
|
||||||
|
struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
|
||||||
|
struct wl_resource *params_resource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given dmabuf has y-axis inverted, false otherwise
|
||||||
|
*/
|
||||||
|
bool wlr_dmabuf_buffer_has_inverted_y(struct wlr_dmabuf_buffer *dmabuf);
|
||||||
|
|
||||||
|
/* the protocol interface */
|
||||||
|
struct wlr_linux_dmabuf {
|
||||||
|
struct wl_global *wl_global;
|
||||||
|
struct wl_listener display_destroy;
|
||||||
|
struct wlr_egl *egl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create linux-dmabuf interface
|
||||||
|
*/
|
||||||
|
struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
|
||||||
|
struct wlr_egl *egl);
|
||||||
|
/**
|
||||||
|
* Destroy the linux-dmabuf interface
|
||||||
|
*/
|
||||||
|
void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the wlr_linux_dmabuf if the given resource was created
|
||||||
|
* via the linux_dmabuf protocol
|
||||||
|
*/
|
||||||
|
struct wlr_linux_dmabuf *wlr_linux_dmabuf_from_resource(
|
||||||
|
struct wl_resource *resource);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef WLR_TYPES_WLR_MATRIX_H
|
||||||
|
#define WLR_TYPES_WLR_MATRIX_H
|
||||||
|
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#include <wlr/types/wlr_box.h>
|
||||||
|
|
||||||
|
void wlr_matrix_identity(float mat[static 9]);
|
||||||
|
void wlr_matrix_multiply(float mat[static 9], const float a[static 9],
|
||||||
|
const float b[static 9]);
|
||||||
|
void wlr_matrix_transpose(float mat[static 9], const float a[static 9]);
|
||||||
|
void wlr_matrix_translate(float mat[static 9], float x, float y);
|
||||||
|
void wlr_matrix_scale(float mat[static 9], float x, float y);
|
||||||
|
void wlr_matrix_rotate(float mat[static 9], float rad);
|
||||||
|
void wlr_matrix_transform(float mat[static 9],
|
||||||
|
enum wl_output_transform transform);
|
||||||
|
void wlr_matrix_projection(float mat[static 9], int width, int height,
|
||||||
|
enum wl_output_transform transform);
|
||||||
|
void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box,
|
||||||
|
enum wl_output_transform transform, float rotation,
|
||||||
|
const float projection[static 9]);
|
||||||
|
|
||||||
|
#endif
|
@ -1,210 +0,0 @@
|
|||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <wayland-server-protocol.h>
|
|
||||||
#include <wlr/render/matrix.h>
|
|
||||||
#include <wlr/types/wlr_box.h>
|
|
||||||
#include <wlr/types/wlr_output.h>
|
|
||||||
|
|
||||||
/* Obtains the index for the given row/column */
|
|
||||||
static inline int mind(int row, int col) {
|
|
||||||
return (row - 1) * 4 + col - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_matrix_identity(float (*output)[16]) {
|
|
||||||
static const float identity[16] = {
|
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 1.0f, 0.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
|
||||||
0.0f, 0.0f, 0.0f, 1.0f
|
|
||||||
};
|
|
||||||
memcpy(*output, identity, sizeof(identity));
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_matrix_translate(float (*output)[16], float x, float y, float z) {
|
|
||||||
wlr_matrix_identity(output);
|
|
||||||
(*output)[mind(1, 4)] = x;
|
|
||||||
(*output)[mind(2, 4)] = y;
|
|
||||||
(*output)[mind(3, 4)] = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_matrix_scale(float (*output)[16], float x, float y, float z) {
|
|
||||||
wlr_matrix_identity(output);
|
|
||||||
(*output)[mind(1, 1)] = x;
|
|
||||||
(*output)[mind(2, 2)] = y;
|
|
||||||
(*output)[mind(3, 3)] = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_matrix_rotate(float (*output)[16], float radians) {
|
|
||||||
wlr_matrix_identity(output);
|
|
||||||
float _cos = cosf(radians);
|
|
||||||
float _sin = sinf(radians);
|
|
||||||
(*output)[mind(1, 1)] = _cos;
|
|
||||||
(*output)[mind(1, 2)] = _sin;
|
|
||||||
(*output)[mind(2, 1)] = -_sin;
|
|
||||||
(*output)[mind(2, 2)] = _cos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_matrix_mul(const float (*x)[16], const float (*y)[16], float (*product)[16]) {
|
|
||||||
float _product[16] = {
|
|
||||||
(*x)[mind(1, 1)] * (*y)[mind(1, 1)] + (*x)[mind(1, 2)] * (*y)[mind(2, 1)] +
|
|
||||||
(*x)[mind(1, 3)] * (*y)[mind(3, 1)] + (*x)[mind(1, 4)] * (*y)[mind(4, 1)],
|
|
||||||
(*x)[mind(1, 1)] * (*y)[mind(1, 2)] + (*x)[mind(1, 2)] * (*y)[mind(2, 2)] +
|
|
||||||
(*x)[mind(1, 3)] * (*y)[mind(3, 2)] + (*x)[mind(1, 4)] * (*y)[mind(4, 2)],
|
|
||||||
(*x)[mind(1, 1)] * (*y)[mind(1, 3)] + (*x)[mind(1, 2)] * (*y)[mind(2, 3)] +
|
|
||||||
(*x)[mind(1, 3)] * (*y)[mind(3, 3)] + (*x)[mind(1, 4)] * (*y)[mind(4, 3)],
|
|
||||||
(*x)[mind(1, 1)] * (*y)[mind(1, 4)] + (*x)[mind(1, 2)] * (*y)[mind(2, 4)] +
|
|
||||||
(*x)[mind(1, 4)] * (*y)[mind(3, 4)] + (*x)[mind(1, 4)] * (*y)[mind(4, 4)],
|
|
||||||
|
|
||||||
(*x)[mind(2, 1)] * (*y)[mind(1, 1)] + (*x)[mind(2, 2)] * (*y)[mind(2, 1)] +
|
|
||||||
(*x)[mind(2, 3)] * (*y)[mind(3, 1)] + (*x)[mind(2, 4)] * (*y)[mind(4, 1)],
|
|
||||||
(*x)[mind(2, 1)] * (*y)[mind(1, 2)] + (*x)[mind(2, 2)] * (*y)[mind(2, 2)] +
|
|
||||||
(*x)[mind(2, 3)] * (*y)[mind(3, 2)] + (*x)[mind(2, 4)] * (*y)[mind(4, 2)],
|
|
||||||
(*x)[mind(2, 1)] * (*y)[mind(1, 3)] + (*x)[mind(2, 2)] * (*y)[mind(2, 3)] +
|
|
||||||
(*x)[mind(2, 3)] * (*y)[mind(3, 3)] + (*x)[mind(2, 4)] * (*y)[mind(4, 3)],
|
|
||||||
(*x)[mind(2, 1)] * (*y)[mind(1, 4)] + (*x)[mind(2, 2)] * (*y)[mind(2, 4)] +
|
|
||||||
(*x)[mind(2, 4)] * (*y)[mind(3, 4)] + (*x)[mind(2, 4)] * (*y)[mind(4, 4)],
|
|
||||||
|
|
||||||
(*x)[mind(3, 1)] * (*y)[mind(1, 1)] + (*x)[mind(3, 2)] * (*y)[mind(2, 1)] +
|
|
||||||
(*x)[mind(3, 3)] * (*y)[mind(3, 1)] + (*x)[mind(3, 4)] * (*y)[mind(4, 1)],
|
|
||||||
(*x)[mind(3, 1)] * (*y)[mind(1, 2)] + (*x)[mind(3, 2)] * (*y)[mind(2, 2)] +
|
|
||||||
(*x)[mind(3, 3)] * (*y)[mind(3, 2)] + (*x)[mind(3, 4)] * (*y)[mind(4, 2)],
|
|
||||||
(*x)[mind(3, 1)] * (*y)[mind(1, 3)] + (*x)[mind(3, 2)] * (*y)[mind(2, 3)] +
|
|
||||||
(*x)[mind(3, 3)] * (*y)[mind(3, 3)] + (*x)[mind(3, 4)] * (*y)[mind(4, 3)],
|
|
||||||
(*x)[mind(3, 1)] * (*y)[mind(1, 4)] + (*x)[mind(3, 2)] * (*y)[mind(2, 4)] +
|
|
||||||
(*x)[mind(3, 4)] * (*y)[mind(3, 4)] + (*x)[mind(3, 4)] * (*y)[mind(4, 4)],
|
|
||||||
|
|
||||||
(*x)[mind(4, 1)] * (*y)[mind(1, 1)] + (*x)[mind(4, 2)] * (*y)[mind(2, 1)] +
|
|
||||||
(*x)[mind(4, 3)] * (*y)[mind(3, 1)] + (*x)[mind(4, 4)] * (*y)[mind(4, 1)],
|
|
||||||
(*x)[mind(4, 1)] * (*y)[mind(1, 2)] + (*x)[mind(4, 2)] * (*y)[mind(2, 2)] +
|
|
||||||
(*x)[mind(4, 3)] * (*y)[mind(3, 2)] + (*x)[mind(4, 4)] * (*y)[mind(4, 2)],
|
|
||||||
(*x)[mind(4, 1)] * (*y)[mind(1, 3)] + (*x)[mind(4, 2)] * (*y)[mind(2, 3)] +
|
|
||||||
(*x)[mind(4, 3)] * (*y)[mind(3, 3)] + (*x)[mind(4, 4)] * (*y)[mind(4, 3)],
|
|
||||||
(*x)[mind(4, 1)] * (*y)[mind(1, 4)] + (*x)[mind(4, 2)] * (*y)[mind(2, 4)] +
|
|
||||||
(*x)[mind(4, 4)] * (*y)[mind(3, 4)] + (*x)[mind(4, 4)] * (*y)[mind(4, 4)],
|
|
||||||
};
|
|
||||||
memcpy(*product, _product, sizeof(_product));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const float transforms[][4] = {
|
|
||||||
[WL_OUTPUT_TRANSFORM_NORMAL] = {
|
|
||||||
1.0f, 0.0f,
|
|
||||||
0.0f, 1.0f,
|
|
||||||
},
|
|
||||||
[WL_OUTPUT_TRANSFORM_90] = {
|
|
||||||
0.0f, -1.0f,
|
|
||||||
1.0f, 0.0f,
|
|
||||||
},
|
|
||||||
[WL_OUTPUT_TRANSFORM_180] = {
|
|
||||||
-1.0f, 0.0f,
|
|
||||||
0.0f, -1.0f,
|
|
||||||
},
|
|
||||||
[WL_OUTPUT_TRANSFORM_270] = {
|
|
||||||
0.0f, 1.0f,
|
|
||||||
-1.0f, 0.0f,
|
|
||||||
},
|
|
||||||
[WL_OUTPUT_TRANSFORM_FLIPPED] = {
|
|
||||||
-1.0f, 0.0f,
|
|
||||||
0.0f, 1.0f,
|
|
||||||
},
|
|
||||||
[WL_OUTPUT_TRANSFORM_FLIPPED_90] = {
|
|
||||||
0.0f, -1.0f,
|
|
||||||
-1.0f, 0.0f,
|
|
||||||
},
|
|
||||||
[WL_OUTPUT_TRANSFORM_FLIPPED_180] = {
|
|
||||||
1.0f, 0.0f,
|
|
||||||
0.0f, -1.0f,
|
|
||||||
},
|
|
||||||
[WL_OUTPUT_TRANSFORM_FLIPPED_270] = {
|
|
||||||
0.0f, 1.0f,
|
|
||||||
1.0f, 0.0f,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
void wlr_matrix_transform(float mat[static 16],
|
|
||||||
enum wl_output_transform transform) {
|
|
||||||
memset(mat, 0, sizeof(*mat) * 16);
|
|
||||||
|
|
||||||
const float *t = transforms[transform];
|
|
||||||
|
|
||||||
// Rotation + reflection
|
|
||||||
mat[0] = t[0];
|
|
||||||
mat[1] = t[1];
|
|
||||||
mat[4] = t[2];
|
|
||||||
mat[5] = t[3];
|
|
||||||
|
|
||||||
// Identity
|
|
||||||
mat[10] = 1.0f;
|
|
||||||
mat[15] = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equivilent to glOrtho(0, width, 0, height, 1, -1) with the transform applied
|
|
||||||
void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height,
|
|
||||||
enum wl_output_transform transform) {
|
|
||||||
memset(mat, 0, sizeof(*mat) * 16);
|
|
||||||
|
|
||||||
const float *t = transforms[transform];
|
|
||||||
float x = 2.0f / width;
|
|
||||||
float y = 2.0f / height;
|
|
||||||
|
|
||||||
// Rotation + reflection
|
|
||||||
mat[0] = x * t[0];
|
|
||||||
mat[1] = x * t[1];
|
|
||||||
mat[4] = y * -t[2];
|
|
||||||
mat[5] = y * -t[3];
|
|
||||||
|
|
||||||
// Translation
|
|
||||||
mat[3] = -copysign(1.0f, mat[0] + mat[1]);
|
|
||||||
mat[7] = -copysign(1.0f, mat[4] + mat[5]);
|
|
||||||
|
|
||||||
// Identity
|
|
||||||
mat[10] = 1.0f;
|
|
||||||
mat[15] = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_matrix_project_box(float (*mat)[16], struct wlr_box *box,
|
|
||||||
enum wl_output_transform transform, float rotation,
|
|
||||||
float (*projection)[16]) {
|
|
||||||
int x = box->x;
|
|
||||||
int y = box->y;
|
|
||||||
int width = box->width;
|
|
||||||
int height = box->height;
|
|
||||||
|
|
||||||
wlr_matrix_translate(mat, x, y, 0);
|
|
||||||
|
|
||||||
if (rotation != 0) {
|
|
||||||
float translate_center[16];
|
|
||||||
wlr_matrix_translate(&translate_center, width/2, height/2, 0);
|
|
||||||
|
|
||||||
float rotate[16];
|
|
||||||
wlr_matrix_rotate(&rotate, rotation);
|
|
||||||
|
|
||||||
float translate_origin[16];
|
|
||||||
wlr_matrix_translate(&translate_origin, -width/2, -height/2, 0);
|
|
||||||
|
|
||||||
wlr_matrix_mul(mat, &translate_center, mat);
|
|
||||||
wlr_matrix_mul(mat, &rotate, mat);
|
|
||||||
wlr_matrix_mul(mat, &translate_origin, mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
float scale[16];
|
|
||||||
wlr_matrix_scale(&scale, width, height, 1);
|
|
||||||
|
|
||||||
wlr_matrix_mul(mat, &scale, mat);
|
|
||||||
|
|
||||||
if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
|
|
||||||
float surface_translate_center[16];
|
|
||||||
wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0);
|
|
||||||
|
|
||||||
float surface_transform[16];
|
|
||||||
wlr_matrix_transform(surface_transform, transform);
|
|
||||||
|
|
||||||
float surface_translate_origin[16];
|
|
||||||
wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0);
|
|
||||||
|
|
||||||
wlr_matrix_mul(mat, &surface_translate_center, mat);
|
|
||||||
wlr_matrix_mul(mat, &surface_transform, mat);
|
|
||||||
wlr_matrix_mul(mat, &surface_translate_origin, mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_matrix_mul(projection, mat, mat);
|
|
||||||
}
|
|
@ -0,0 +1,463 @@
|
|||||||
|
#ifndef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#endif
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#include <wlr/render/egl.h>
|
||||||
|
#include <wlr/types/wlr_linux_dmabuf.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||||
|
|
||||||
|
static void wl_buffer_destroy(struct wl_client *client,
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_buffer_interface wl_buffer_impl = {
|
||||||
|
wl_buffer_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool wlr_dmabuf_buffer_has_inverted_y(struct wlr_dmabuf_buffer *dmabuf) {
|
||||||
|
return dmabuf->attributes.flags
|
||||||
|
& ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) {
|
||||||
|
if (!wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
|
||||||
|
&wl_buffer_impl)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer *buffer = wl_resource_get_user_data(buffer_resource);
|
||||||
|
if (buffer && buffer->buffer_resource && !buffer->params_resource &&
|
||||||
|
buffer->buffer_resource == buffer_resource) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
|
||||||
|
struct wl_resource *buffer_resource) {
|
||||||
|
assert(wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
|
||||||
|
&wl_buffer_impl));
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer *buffer = wl_resource_get_user_data(buffer_resource);
|
||||||
|
assert(buffer);
|
||||||
|
assert(buffer->buffer_resource);
|
||||||
|
assert(!buffer->params_resource);
|
||||||
|
assert(buffer->buffer_resource == buffer_resource);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linux_dmabuf_buffer_destroy(struct wlr_dmabuf_buffer *buffer) {
|
||||||
|
for (int i = 0; i < buffer->attributes.n_planes; i++) {
|
||||||
|
close(buffer->attributes.fd[i]);
|
||||||
|
buffer->attributes.fd[i] = -1;
|
||||||
|
}
|
||||||
|
buffer->attributes.n_planes = 0;
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void params_destroy(struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void params_add(struct wl_client *client,
|
||||||
|
struct wl_resource *params_resource, int32_t name_fd,
|
||||||
|
uint32_t plane_idx, uint32_t offset, uint32_t stride,
|
||||||
|
uint32_t modifier_hi, uint32_t modifier_lo) {
|
||||||
|
struct wlr_dmabuf_buffer *buffer = wlr_dmabuf_buffer_from_params_resource(
|
||||||
|
params_resource);
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
|
||||||
|
"params was already used to create a wl_buffer");
|
||||||
|
close(name_fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plane_idx >= WLR_LINUX_DMABUF_MAX_PLANES) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX,
|
||||||
|
"plane index %u > %u", plane_idx, WLR_LINUX_DMABUF_MAX_PLANES);
|
||||||
|
close(name_fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->attributes.fd[plane_idx] != -1) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET,
|
||||||
|
"a dmabuf with id %d has already been added for plane %u",
|
||||||
|
buffer->attributes.fd[plane_idx],
|
||||||
|
plane_idx);
|
||||||
|
close(name_fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->attributes.fd[plane_idx] = name_fd;
|
||||||
|
buffer->attributes.offset[plane_idx] = offset;
|
||||||
|
buffer->attributes.stride[plane_idx] = stride;
|
||||||
|
buffer->attributes.modifier[plane_idx] = ((uint64_t)modifier_hi << 32) |
|
||||||
|
modifier_lo;
|
||||||
|
buffer->attributes.n_planes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_buffer_destroy(struct wl_resource *buffer_resource)
|
||||||
|
{
|
||||||
|
struct wlr_dmabuf_buffer *buffer = wlr_dmabuf_buffer_from_buffer_resource(
|
||||||
|
buffer_resource);
|
||||||
|
|
||||||
|
linux_dmabuf_buffer_destroy(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void params_create_common(struct wl_client *client,
|
||||||
|
struct wl_resource *params_resource, uint32_t buffer_id, int32_t width,
|
||||||
|
int32_t height, uint32_t format, uint32_t flags) {
|
||||||
|
if (!wl_resource_get_user_data(params_resource)) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
|
||||||
|
"params was already used to create a wl_buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct wlr_dmabuf_buffer *buffer = wlr_dmabuf_buffer_from_params_resource(
|
||||||
|
params_resource);
|
||||||
|
|
||||||
|
/* Switch the linux_dmabuf_buffer object from params resource to
|
||||||
|
* eventually wl_buffer resource. */
|
||||||
|
wl_resource_set_user_data(buffer->params_resource, NULL);
|
||||||
|
buffer->params_resource = NULL;
|
||||||
|
|
||||||
|
if (!buffer->attributes.n_planes) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
|
||||||
|
"no dmabuf has been added to the params");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: support more planes */
|
||||||
|
if (buffer->attributes.n_planes != 1) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
|
||||||
|
"only single plane buffers supported not %d",
|
||||||
|
buffer->attributes.n_planes);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->attributes.fd[0] == -1) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
|
||||||
|
"no dmabuf has been added for plane");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->attributes.width = width;
|
||||||
|
buffer->attributes.height = height;
|
||||||
|
buffer->attributes.format = format;
|
||||||
|
buffer->attributes.flags = flags;
|
||||||
|
|
||||||
|
if (width < 1 || height < 1) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS,
|
||||||
|
"invalid width %d or height %d", width, height);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uint64_t)buffer->attributes.offset[0] + buffer->attributes.stride[0] > UINT32_MAX) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
|
||||||
|
"size overflow for plane");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uint64_t)buffer->attributes.offset[0] +
|
||||||
|
(uint64_t)buffer->attributes.stride[0] * height > UINT32_MAX) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
|
||||||
|
"size overflow for plane");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t size = lseek(buffer->attributes.fd[0], 0, SEEK_END);
|
||||||
|
if (size != -1) { /* Skip checks if kernel does no support seek on buffer */
|
||||||
|
if (buffer->attributes.offset[0] >= size) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
|
||||||
|
"invalid offset %i for plane",
|
||||||
|
buffer->attributes.offset[0]);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->attributes.offset[0] + buffer->attributes.stride[0] > size) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
|
||||||
|
"invalid stride %i for plane",
|
||||||
|
buffer->attributes.stride[0]);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->attributes.offset[0] + buffer->attributes.stride[0] * height > size) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
|
||||||
|
"invalid buffer stride or height for plane");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reject unknown flags */
|
||||||
|
if (buffer->attributes.flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT) {
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT,
|
||||||
|
"Unknown dmabuf flags %"PRIu32, buffer->attributes.flags);
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if dmabuf is usable */
|
||||||
|
if (!wlr_egl_check_import_dmabuf(buffer->egl, buffer)) {
|
||||||
|
goto err_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->buffer_resource = wl_resource_create(client, &wl_buffer_interface,
|
||||||
|
1, buffer_id);
|
||||||
|
if (!buffer->buffer_resource) {
|
||||||
|
wl_resource_post_no_memory(params_resource);
|
||||||
|
goto err_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_set_implementation(buffer->buffer_resource,
|
||||||
|
&wl_buffer_impl, buffer, handle_buffer_destroy);
|
||||||
|
|
||||||
|
/* send 'created' event when the request is not for an immediate
|
||||||
|
* import, that is buffer_id is zero */
|
||||||
|
if (buffer_id == 0) {
|
||||||
|
zwp_linux_buffer_params_v1_send_created(params_resource,
|
||||||
|
buffer->buffer_resource);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
err_failed:
|
||||||
|
if (buffer_id == 0) {
|
||||||
|
zwp_linux_buffer_params_v1_send_failed(params_resource);
|
||||||
|
} else {
|
||||||
|
/* since the behavior is left implementation defined by the
|
||||||
|
* protocol in case of create_immed failure due to an unknown cause,
|
||||||
|
* we choose to treat it as a fatal error and immediately kill the
|
||||||
|
* client instead of creating an invalid handle and waiting for it
|
||||||
|
* to be used.
|
||||||
|
*/
|
||||||
|
wl_resource_post_error(params_resource,
|
||||||
|
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER,
|
||||||
|
"importing the supplied dmabufs failed");
|
||||||
|
}
|
||||||
|
err_out:
|
||||||
|
linux_dmabuf_buffer_destroy(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void params_create(struct wl_client *client,
|
||||||
|
struct wl_resource *params_resource,
|
||||||
|
int32_t width, int32_t height,uint32_t format, uint32_t flags) {
|
||||||
|
params_create_common(client, params_resource, 0, width, height, format, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void params_create_immed(struct wl_client *client,
|
||||||
|
struct wl_resource *params_resource, uint32_t buffer_id,
|
||||||
|
int32_t width, int32_t height,uint32_t format, uint32_t flags) {
|
||||||
|
params_create_common(client, params_resource, buffer_id, width, height, format, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_linux_buffer_params_v1_interface linux_buffer_params_impl = {
|
||||||
|
params_destroy,
|
||||||
|
params_add,
|
||||||
|
params_create,
|
||||||
|
params_create_immed,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
|
||||||
|
struct wl_resource *params_resource) {
|
||||||
|
assert(wl_resource_instance_of(params_resource,
|
||||||
|
&zwp_linux_buffer_params_v1_interface,
|
||||||
|
&linux_buffer_params_impl));
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer *buffer = wl_resource_get_user_data(params_resource);
|
||||||
|
assert(buffer);
|
||||||
|
assert(buffer->params_resource);
|
||||||
|
assert(!buffer->buffer_resource);
|
||||||
|
assert(buffer->params_resource == params_resource);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_params_destroy(struct wl_resource *params_resource) {
|
||||||
|
/* Check for NULL since wlr_dmabuf_buffer_from_params_resource will choke */
|
||||||
|
if (!wl_resource_get_user_data(params_resource)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_dmabuf_buffer *buffer =
|
||||||
|
wlr_dmabuf_buffer_from_params_resource(params_resource);
|
||||||
|
linux_dmabuf_buffer_destroy(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linux_dmabuf_create_params(struct wl_client *client,
|
||||||
|
struct wl_resource *linux_dmabuf_resource,
|
||||||
|
uint32_t params_id) {
|
||||||
|
struct wlr_linux_dmabuf *linux_dmabuf = wlr_linux_dmabuf_from_resource(
|
||||||
|
linux_dmabuf_resource);
|
||||||
|
|
||||||
|
uint32_t version = wl_resource_get_version(linux_dmabuf_resource);
|
||||||
|
struct wlr_dmabuf_buffer *buffer = calloc(1, sizeof *buffer);
|
||||||
|
if (!buffer) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < WLR_LINUX_DMABUF_MAX_PLANES; i++) {
|
||||||
|
buffer->attributes.fd[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->egl = linux_dmabuf->egl;
|
||||||
|
buffer->params_resource = wl_resource_create(client,
|
||||||
|
&zwp_linux_buffer_params_v1_interface,
|
||||||
|
version, params_id);
|
||||||
|
if (!buffer->params_resource) {
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_set_implementation(buffer->params_resource,
|
||||||
|
&linux_buffer_params_impl,buffer, handle_params_destroy);
|
||||||
|
return;
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
free(buffer);
|
||||||
|
err:
|
||||||
|
wl_resource_post_no_memory(linux_dmabuf_resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linux_dmabuf_destroy(struct wl_client *client, struct wl_resource *resource) {
|
||||||
|
wl_resource_destroy(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct zwp_linux_dmabuf_v1_interface linux_dmabuf_impl = {
|
||||||
|
linux_dmabuf_destroy,
|
||||||
|
linux_dmabuf_create_params
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wlr_linux_dmabuf *wlr_linux_dmabuf_from_resource(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource, &zwp_linux_dmabuf_v1_interface,
|
||||||
|
&linux_dmabuf_impl));
|
||||||
|
|
||||||
|
struct wlr_linux_dmabuf *dmabuf = wl_resource_get_user_data(resource);
|
||||||
|
assert(dmabuf);
|
||||||
|
return dmabuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf *linux_dmabuf,
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
struct wlr_egl *egl = linux_dmabuf->egl;
|
||||||
|
/*
|
||||||
|
* Use EGL_EXT_image_dma_buf_import_modifiers to query and advertise
|
||||||
|
* format/modifier codes.
|
||||||
|
*/
|
||||||
|
uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID;
|
||||||
|
int *formats = NULL;
|
||||||
|
int num_formats = wlr_egl_get_dmabuf_formats(egl, &formats);
|
||||||
|
|
||||||
|
if (num_formats < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_formats; i++) {
|
||||||
|
int num_modifiers;
|
||||||
|
uint64_t *modifiers = NULL;
|
||||||
|
|
||||||
|
num_modifiers = wlr_egl_get_dmabuf_modifiers(egl, formats[i],
|
||||||
|
&modifiers);
|
||||||
|
if (num_modifiers < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* send DRM_FORMAT_MOD_INVALID token when no modifiers are supported
|
||||||
|
* for this format */
|
||||||
|
if (num_modifiers == 0) {
|
||||||
|
num_modifiers = 1;
|
||||||
|
modifiers = &modifier_invalid;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < num_modifiers; j++) {
|
||||||
|
uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF;
|
||||||
|
uint32_t modifier_hi = modifiers[j] >> 32;
|
||||||
|
zwp_linux_dmabuf_v1_send_modifier(resource, formats[i],
|
||||||
|
modifier_hi,
|
||||||
|
modifier_lo);
|
||||||
|
}
|
||||||
|
if (modifiers != &modifier_invalid) {
|
||||||
|
free(modifiers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(formats);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void linux_dmabuf_bind(struct wl_client *client,
|
||||||
|
void *data, uint32_t version, uint32_t id) {
|
||||||
|
struct wlr_linux_dmabuf *linux_dmabuf = data;
|
||||||
|
struct wl_resource *resource = wl_resource_create(client,
|
||||||
|
&zwp_linux_dmabuf_v1_interface,
|
||||||
|
version, id);
|
||||||
|
|
||||||
|
if (resource == NULL) {
|
||||||
|
wl_client_post_no_memory(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_resource_set_implementation(resource, &linux_dmabuf_impl,
|
||||||
|
linux_dmabuf, NULL);
|
||||||
|
if (version < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
linux_dmabuf_send_modifiers(linux_dmabuf, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf) {
|
||||||
|
if (!linux_dmabuf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wl_list_remove(&linux_dmabuf->display_destroy.link);
|
||||||
|
|
||||||
|
wl_global_destroy(linux_dmabuf->wl_global);
|
||||||
|
free(linux_dmabuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct wlr_linux_dmabuf *linux_dmabuf = wl_container_of(listener, linux_dmabuf, display_destroy);
|
||||||
|
wlr_linux_dmabuf_destroy(linux_dmabuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
|
||||||
|
struct wlr_egl *egl) {
|
||||||
|
struct wlr_linux_dmabuf *linux_dmabuf =
|
||||||
|
calloc(1, sizeof(struct wlr_linux_dmabuf));
|
||||||
|
if (linux_dmabuf == NULL) {
|
||||||
|
wlr_log(L_ERROR, "could not create simple dmabuf manager");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
linux_dmabuf->display_destroy.notify = handle_display_destroy;
|
||||||
|
wl_display_add_destroy_listener(display, &linux_dmabuf->display_destroy);
|
||||||
|
|
||||||
|
linux_dmabuf->wl_global =
|
||||||
|
wl_global_create(display, &zwp_linux_dmabuf_v1_interface,
|
||||||
|
3, linux_dmabuf, linux_dmabuf_bind);
|
||||||
|
|
||||||
|
linux_dmabuf->egl = egl;
|
||||||
|
if (!linux_dmabuf->wl_global) {
|
||||||
|
wlr_log(L_ERROR, "could not create linux dmabuf v1 wl global");
|
||||||
|
free(linux_dmabuf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return linux_dmabuf;
|
||||||
|
}
|
@ -0,0 +1,169 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <wayland-server-protocol.h>
|
||||||
|
#include <wlr/types/wlr_matrix.h>
|
||||||
|
#include <wlr/types/wlr_box.h>
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
|
||||||
|
void wlr_matrix_identity(float mat[static 9]) {
|
||||||
|
static const float identity[9] = {
|
||||||
|
1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
memcpy(mat, identity, sizeof(identity));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_matrix_multiply(float mat[static 9], const float a[static 9],
|
||||||
|
const float b[static 9]) {
|
||||||
|
float product[9];
|
||||||
|
|
||||||
|
product[0] = a[0]*b[0] + a[1]*b[3] + a[2]*b[6];
|
||||||
|
product[1] = a[0]*b[1] + a[1]*b[4] + a[2]*b[7];
|
||||||
|
product[2] = a[0]*b[2] + a[1]*b[5] + a[2]*b[8];
|
||||||
|
|
||||||
|
product[3] = a[3]*b[0] + a[4]*b[3] + a[5]*b[6];
|
||||||
|
product[4] = a[3]*b[1] + a[4]*b[4] + a[5]*b[7];
|
||||||
|
product[5] = a[3]*b[2] + a[4]*b[5] + a[5]*b[8];
|
||||||
|
|
||||||
|
product[6] = a[6]*b[0] + a[7]*b[3] + a[8]*b[6];
|
||||||
|
product[7] = a[6]*b[1] + a[7]*b[4] + a[8]*b[7];
|
||||||
|
product[8] = a[6]*b[2] + a[7]*b[5] + a[8]*b[8];
|
||||||
|
|
||||||
|
memcpy(mat, product, sizeof(product));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_matrix_transpose(float mat[static 9], const float a[static 9]) {
|
||||||
|
float transposition[9] = {
|
||||||
|
a[0], a[3], a[6],
|
||||||
|
a[1], a[4], a[7],
|
||||||
|
a[2], a[5], a[8],
|
||||||
|
};
|
||||||
|
memcpy(mat, transposition, sizeof(transposition));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_matrix_translate(float mat[static 9], float x, float y) {
|
||||||
|
float translate[9] = {
|
||||||
|
1.0f, 0.0f, x,
|
||||||
|
0.0f, 1.0f, y,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
wlr_matrix_multiply(mat, mat, translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_matrix_scale(float mat[static 9], float x, float y) {
|
||||||
|
float scale[9] = {
|
||||||
|
x, 0.0f, 0.0f,
|
||||||
|
0.0f, y, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
wlr_matrix_multiply(mat, mat, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_matrix_rotate(float mat[static 9], float rad) {
|
||||||
|
float rotate[9] = {
|
||||||
|
cos(rad), -sin(rad), 0.0f,
|
||||||
|
sin(rad), cos(rad), 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
wlr_matrix_multiply(mat, mat, rotate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const float transforms[][9] = {
|
||||||
|
[WL_OUTPUT_TRANSFORM_NORMAL] = {
|
||||||
|
1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
[WL_OUTPUT_TRANSFORM_90] = {
|
||||||
|
0.0f, -1.0f, 0.0f,
|
||||||
|
1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
[WL_OUTPUT_TRANSFORM_180] = {
|
||||||
|
-1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, -1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
[WL_OUTPUT_TRANSFORM_270] = {
|
||||||
|
0.0f, 1.0f, 0.0f,
|
||||||
|
-1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
[WL_OUTPUT_TRANSFORM_FLIPPED] = {
|
||||||
|
-1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
[WL_OUTPUT_TRANSFORM_FLIPPED_90] = {
|
||||||
|
0.0f, -1.0f, 0.0f,
|
||||||
|
-1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
[WL_OUTPUT_TRANSFORM_FLIPPED_180] = {
|
||||||
|
1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, -1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
[WL_OUTPUT_TRANSFORM_FLIPPED_270] = {
|
||||||
|
0.0f, 1.0f, 0.0f,
|
||||||
|
1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void wlr_matrix_transform(float mat[static 9],
|
||||||
|
enum wl_output_transform transform) {
|
||||||
|
wlr_matrix_multiply(mat, mat, transforms[transform]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equivilent to glOrtho(0, width, 0, height, 1, -1) with the transform applied
|
||||||
|
void wlr_matrix_projection(float mat[static 9], int width, int height,
|
||||||
|
enum wl_output_transform transform) {
|
||||||
|
memset(mat, 0, sizeof(*mat) * 9);
|
||||||
|
|
||||||
|
const float *t = transforms[transform];
|
||||||
|
float x = 2.0f / width;
|
||||||
|
float y = 2.0f / height;
|
||||||
|
|
||||||
|
// Rotation + reflection
|
||||||
|
mat[0] = x * t[0];
|
||||||
|
mat[1] = x * t[1];
|
||||||
|
mat[3] = y * -t[3];
|
||||||
|
mat[4] = y * -t[4];
|
||||||
|
|
||||||
|
// Translation
|
||||||
|
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
|
||||||
|
mat[5] = -copysign(1.0f, mat[3] + mat[4]);
|
||||||
|
|
||||||
|
// Identity
|
||||||
|
mat[8] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box,
|
||||||
|
enum wl_output_transform transform, float rotation,
|
||||||
|
const float projection[static 9]) {
|
||||||
|
int x = box->x;
|
||||||
|
int y = box->y;
|
||||||
|
int width = box->width;
|
||||||
|
int height = box->height;
|
||||||
|
|
||||||
|
wlr_matrix_identity(mat);
|
||||||
|
wlr_matrix_translate(mat, x, y);
|
||||||
|
|
||||||
|
if (rotation != 0) {
|
||||||
|
wlr_matrix_translate(mat, width/2, height/2);
|
||||||
|
wlr_matrix_rotate(mat, rotation);
|
||||||
|
wlr_matrix_translate(mat, -width/2, -height/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_matrix_scale(mat, width, height);
|
||||||
|
|
||||||
|
if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
|
||||||
|
wlr_matrix_translate(mat, 0.5, 0.5);
|
||||||
|
wlr_matrix_transform(mat, transform);
|
||||||
|
wlr_matrix_translate(mat, -0.5, -0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_matrix_multiply(mat, projection, mat);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue