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