blob: f493ff135ebc772355289e13170b6e8e9105fd54 [file] [log] [blame]
/*
* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __BS_DRM_H__
#define __BS_DRM_H__
#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <drm_fourcc.h>
#include <gbm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#define bs_rank_skip UINT32_MAX
#define BS_ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0]))
// debug.c
__attribute__((format(printf, 5, 6))) void bs_debug_print(const char *prefix, const char *func,
const char *file, int line,
const char *format, ...);
#define bs_debug_error(...) \
do { \
bs_debug_print("ERROR", __func__, __FILE__, __LINE__, __VA_ARGS__); \
} while (0)
int64_t bs_debug_gettime_ns();
// pipe.c
typedef bool (*bs_make_pipe_piece)(void *context, void *out);
bool bs_pipe_make(void *context, bs_make_pipe_piece *pieces, size_t piece_count, void *out_pipe,
size_t pipe_size);
// open.c
// A return value of true causes enumeration to end immediately. fd is always
// closed after the callback.
typedef bool (*bs_open_enumerate_func)(void *user, int fd);
// A return value of true causes the filter to return the given fd.
typedef bool (*bs_open_filter_func)(int fd);
// The fd with the lowest (magnitude) rank is returned. A fd with rank UINT32_MAX is skipped. A fd
// with rank 0 ends the enumeration early and is returned. On a tie, the fd returned will be
// arbitrarily chosen from the set of lowest rank fds.
typedef uint32_t (*bs_open_rank_func)(int fd);
void bs_open_enumerate(const char *format, unsigned start, unsigned end,
bs_open_enumerate_func body, void *user);
int bs_open_filtered(const char *format, unsigned start, unsigned end, bs_open_filter_func filter);
int bs_open_ranked(const char *format, unsigned start, unsigned end, bs_open_rank_func rank);
// drm_connectors.c
#define bs_drm_connectors_any UINT32_MAX
// Interleaved arrays in the layout { DRM_MODE_CONNECTOR_*, rank, DRM_MODE_CONNECTOR_*, rank, ... },
// terminated by { ... 0, 0 }. bs_drm_connectors_any can be used in place of DRM_MODE_CONNECTOR_* to
// match any connector. bs_rank_skip can be used in place of a rank to indicate that that connector
// should be skipped.
// Use internal connectors and fallback to any connector
extern const uint32_t bs_drm_connectors_main_rank[];
// Use only internal connectors
extern const uint32_t bs_drm_connectors_internal_rank[];
// Use only external connectors
extern const uint32_t bs_drm_connectors_external_rank[];
uint32_t bs_drm_connectors_rank(const uint32_t *ranks, uint32_t connector_type);
// drm_pipe.c
struct bs_drm_pipe {
int fd; // Always owned by the user of this library
uint32_t connector_id;
uint32_t encoder_id;
uint32_t crtc_id;
};
struct bs_drm_pipe_plumber;
// A class that makes pipes with certain constraints.
struct bs_drm_pipe_plumber *bs_drm_pipe_plumber_new();
void bs_drm_pipe_plumber_destroy(struct bs_drm_pipe_plumber **);
// Takes ranks in the rank array format from drm_connectors.c. Lifetime of connector_ranks must
// exceed the plumber
void bs_drm_pipe_plumber_connector_ranks(struct bs_drm_pipe_plumber *,
const uint32_t *connector_ranks);
// crtc_mask is in the same format as drmModeEncoder.possible_crtcs
void bs_drm_pipe_plumber_crtc_mask(struct bs_drm_pipe_plumber *, uint32_t crtc_mask);
// Sets which card fd the plumber should use. The fd remains owned by the caller. If left unset,
// bs_drm_pipe_plumber_make will try all available cards.
void bs_drm_pipe_plumber_fd(struct bs_drm_pipe_plumber *, int card_fd);
// Sets a pointer to store the chosen connector in after a succesful call to
// bs_drm_pipe_plumber_make. It's optional, but calling drmModeGetConnector yourself can be slow.
void bs_drm_pipe_plumber_connector_ptr(struct bs_drm_pipe_plumber *, drmModeConnector **ptr);
// Makes the pipe based on the constraints of the plumber. Returns false if no pipe worked.
bool bs_drm_pipe_plumber_make(struct bs_drm_pipe_plumber *, struct bs_drm_pipe *pipe);
// Makes any pipe that will work for the given card fd. Returns false if no pipe worked.
bool bs_drm_pipe_make(int fd, struct bs_drm_pipe *pipe);
// drm_fb.c
uint32_t bs_drm_fb_create_gbm(struct gbm_bo *bo);
// drm_open.c
// Opens an arbitrary display's card.
int bs_drm_open_for_display();
// Opens the main display's card. This falls back to bs_drm_open_for_display().
int bs_drm_open_main_display();
int bs_drm_open_vgem();
// dumb_mmap.c
void *bs_dumb_mmap(int fd, uint32_t handle, size_t size);
// dma_buf.c
void *bs_dma_buf_mmap(struct gbm_bo *bo);
void *bs_dma_buf_mmap_plane(struct gbm_bo *bo, size_t plane);
int bs_dma_buf_unmmap(struct gbm_bo *bo, void *addr);
int bs_dma_buf_unmmap_plane(struct gbm_bo *bo, size_t plane, void *addr);
// egl.c
struct bs_egl;
struct bs_egl_fb;
struct bs_egl *bs_egl_new();
void bs_egl_destroy(struct bs_egl **egl);
bool bs_egl_setup(struct bs_egl *self);
bool bs_egl_make_current(struct bs_egl *self);
EGLImageKHR bs_egl_image_create(struct bs_egl *self, int prime_fd, int width, int height,
uint32_t format, int pitch, int offset);
EGLImageKHR bs_egl_image_create_with_modifier(struct bs_egl *self, int prime_fd, int width,
int height, uint32_t format, int pitch, int offset,
uint64_t format_modifier);
EGLImageKHR bs_egl_image_create_gbm(struct bs_egl *self, struct gbm_bo *bo);
void bs_egl_image_destroy(struct bs_egl *self, EGLImageKHR *image);
bool bs_egl_image_flush_external(struct bs_egl *self, EGLImageKHR image);
struct bs_egl_fb *bs_egl_fb_new(struct bs_egl *self, EGLImageKHR image);
bool bs_egl_target_texture2D(struct bs_egl *self, EGLImageKHR image);
void bs_egl_fb_destroy(struct bs_egl_fb **fb);
GLuint bs_egl_fb_name(struct bs_egl_fb *self);
// gl.c
// The entry after the last valid binding should have name == NULL. The binding array is terminated
// by a NULL name.
struct bs_gl_program_create_binding {
// These parameters are passed to glBindAttribLocation
GLuint index;
const GLchar *name;
};
GLuint bs_gl_shader_create(GLenum type, const GLchar *src);
// bindings can be NULL.
GLuint bs_gl_program_create_vert_frag_bind(const GLchar *vert_src, const GLchar *frag_src,
struct bs_gl_program_create_binding *bindings);
// app.c
struct bs_app;
struct bs_app *bs_app_new();
void bs_app_destroy(struct bs_app **app);
int bs_app_fd(struct bs_app *self);
size_t bs_app_fb_count(struct bs_app *self);
void bs_app_set_fb_count(struct bs_app *self, size_t fb_count);
struct gbm_bo *bs_app_fb_bo(struct bs_app *self, size_t index);
uint32_t bs_app_fb_id(struct bs_app *self, size_t index);
bool bs_app_setup(struct bs_app *self);
int bs_app_display_fb(struct bs_app *self, size_t index);
#endif