Add dmabuf import & render
parent
838570a4f9
commit
0dceb98f79
100
src/render.c
100
src/render.c
|
@ -44,6 +44,27 @@ struct renderer {
|
||||||
EGLSurface surface;
|
EGLSurface surface;
|
||||||
EGLContext context;
|
EGLContext context;
|
||||||
GLuint shader_program;
|
GLuint shader_program;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
GLint read_format;
|
||||||
|
GLint read_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dmabuf_plane {
|
||||||
|
int fd;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t pitch;
|
||||||
|
uint64_t modifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dmabuf_frame {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint32_t format;
|
||||||
|
|
||||||
|
uint32_t n_planes;
|
||||||
|
struct dmabuf_plane plane[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void* gl_load_single_extension(const char* name)
|
static inline void* gl_load_single_extension(const char* name)
|
||||||
|
@ -240,7 +261,7 @@ void renderer_destroy(struct renderer* self)
|
||||||
glDeleteProgram(self->shader_program);
|
glDeleteProgram(self->shader_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
int renderer_init(struct renderer* self, int width, int height)
|
int renderer_init(struct renderer* self, uint32_t width, uint32_t height)
|
||||||
{
|
{
|
||||||
if (!eglBindAPI(EGL_OPENGL_ES_API))
|
if (!eglBindAPI(EGL_OPENGL_ES_API))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -308,6 +329,11 @@ int renderer_init(struct renderer* self, int width, int height)
|
||||||
|
|
||||||
glUseProgram(self->shader_program);
|
glUseProgram(self->shader_program);
|
||||||
|
|
||||||
|
self->width = width;
|
||||||
|
self->height = height;
|
||||||
|
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &self->read_format);
|
||||||
|
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &self->read_type);
|
||||||
|
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
gl_clear();
|
gl_clear();
|
||||||
|
|
||||||
|
@ -321,3 +347,75 @@ surface_failure:
|
||||||
eglDestroyContext(self->display, self->context);
|
eglDestroyContext(self->display, self->context);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void append_attr(EGLint* dst, int* i, EGLint name, EGLint value)
|
||||||
|
{
|
||||||
|
dst[*i] = name;
|
||||||
|
i[0] += 1;
|
||||||
|
dst[*i] = value;
|
||||||
|
i[0] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dmabuf_attr_append_planes(EGLint* dst, int* i,
|
||||||
|
struct dmabuf_frame* frame)
|
||||||
|
{
|
||||||
|
#define APPEND_PLANE_ATTR(n) \
|
||||||
|
if (frame->n_planes <= n) \
|
||||||
|
return; \
|
||||||
|
\
|
||||||
|
append_attr(dst, i, EGL_DMA_BUF_PLANE##n##_FD_EXT, frame->plane[n].fd); \
|
||||||
|
append_attr(dst, i, EGL_DMA_BUF_PLANE##n##_OFFSET_EXT, frame->plane[n].offset); \
|
||||||
|
append_attr(dst, i, EGL_DMA_BUF_PLANE##n##_PITCH_EXT, frame->plane[n].pitch); \
|
||||||
|
append_attr(dst, i, EGL_DMA_BUF_PLANE##n##_MODIFIER_LO_EXT, frame->plane[n].modifier); \
|
||||||
|
append_attr(dst, i, EGL_DMA_BUF_PLANE##n##_MODIFIER_HI_EXT, frame->plane[n].modifier >> 32); \
|
||||||
|
|
||||||
|
APPEND_PLANE_ATTR(0);
|
||||||
|
APPEND_PLANE_ATTR(1);
|
||||||
|
APPEND_PLANE_ATTR(2);
|
||||||
|
APPEND_PLANE_ATTR(3);
|
||||||
|
#undef APPEND_PLANE_ATTR
|
||||||
|
}
|
||||||
|
|
||||||
|
int render_dmabuf_frame(struct renderer* self, struct dmabuf_frame* frame)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
EGLint attr[6 + 10 * 4 + 1];
|
||||||
|
|
||||||
|
if (frame->n_planes == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
append_attr(attr, &index, EGL_WIDTH, frame->width);
|
||||||
|
append_attr(attr, &index, EGL_HEIGHT, frame->height);
|
||||||
|
append_attr(attr, &index, EGL_LINUX_DRM_FOURCC_EXT, frame->format);
|
||||||
|
dmabuf_attr_append_planes(attr, &index, frame);
|
||||||
|
attr[index++] = EGL_NONE;
|
||||||
|
|
||||||
|
EGLImageKHR image =
|
||||||
|
eglCreateImageKHR(self->display, EGL_NO_CONTEXT,
|
||||||
|
EGL_LINUX_DMA_BUF_EXT, NULL, attr);
|
||||||
|
if (!image)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
GLuint tex;
|
||||||
|
glGenTextures(1, &tex);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
|
||||||
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
|
||||||
|
|
||||||
|
gl_render();
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glDeleteTextures(1, &tex);
|
||||||
|
eglDestroyImageKHR(self->display, image);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy a horizontal stripe from the GL frame into a pixel buffer */
|
||||||
|
void render_copy_pixels(struct renderer* self, void* dst, uint32_t y, uint32_t height)
|
||||||
|
{
|
||||||
|
assert(y + height <= self->height);
|
||||||
|
|
||||||
|
glReadPixels(0, y, self->width, height, self->read_format,
|
||||||
|
self->read_type, dst);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue