summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-12-17 14:21:44 +1000
committerDave Airlie <airlied@redhat.com>2013-12-17 14:21:44 +1000
commit94fe497ff9b6663ba4e3dc7bab75e7b695964e14 (patch)
treee75795e9498aadff8a4fb4f5cfe08d137d554b9e
parent07e205059e245b9b0d7774f36125db2a339b48cd (diff)
start passing more info
-rw-r--r--Makefile2
-rw-r--r--client.c44
-rw-r--r--common.h7
-rw-r--r--fdpass.c122
-rw-r--r--fdpass.h35
-rw-r--r--server_egl.c110
6 files changed, 240 insertions, 80 deletions
diff --git a/Makefile b/Makefile
index 35c77c7..8f3d7cf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
CFLAGS=-g -Wall `pkg-config --cflags libdrm`
LIBS=-lEGL -lGL -lgbm -lGLEW -ldrm -lX11
-OBJ = server_egl.o main.o client.o
+OBJ = server_egl.o main.o client.o fdpass.o
all: egl_pass
diff --git a/client.c b/client.c
index c6f8529..4294624 100644
--- a/client.c
+++ b/client.c
@@ -1,3 +1,6 @@
+#define EGL_EGLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -7,10 +10,11 @@
#include <errno.h>
#include <error.h>
#include <X11/Xlib.h>
+#include "fdpass.h"
#include "common.h"
#include <EGL/egl.h>
-
+#include <EGL/eglext.h>
struct x11_window {
Window win;
EGLSurface egl_surface;
@@ -36,6 +40,7 @@ struct client {
struct display *d;
struct window *w;
int sock_fd;
+ EGLImageKHR image;
};
static void x11_window_create(struct window *w)
@@ -181,6 +186,7 @@ static void display_destroy(struct display *d)
struct client *client_create(int sock_fd)
{
struct client *client;
+ ssize_t size;
client = calloc(1, sizeof(struct client));
if (!client)
error(1, errno, "cannot allocate memory");
@@ -188,6 +194,42 @@ struct client *client_create(int sock_fd)
client->d = display_create();
client->w = window_create(client->d);
client->sock_fd = sock_fd;
+
+ sleep(1);
+ for (;;) {
+ EGLint attrs[13];
+ struct bufinfo buf;
+ int myfd;
+ size = sock_fd_read(client->sock_fd, &buf, sizeof(buf), &myfd);
+ if (size <= 0)
+ break;
+
+ printf("read %d: %d %d %dx%d\n", (int)size, buf.id, buf.stride, buf.width, buf.height);
+
+ attrs[0] = EGL_DMA_BUF_PLANE0_FD_EXT;
+ attrs[1] = myfd;
+ attrs[2] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
+ attrs[3] = buf.stride;
+ attrs[4] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
+ attrs[5] = 0;
+ attrs[6] = EGL_WIDTH;
+ attrs[7] = buf.width;
+ attrs[8] = EGL_HEIGHT;
+ attrs[9] = buf.height;
+ attrs[10] = EGL_LINUX_DRM_FOURCC_EXT;
+ attrs[11] = buf.format;
+ attrs[12] = EGL_NONE;
+ client->image = eglCreateImageKHR(client->d->x11.egl_display,
+ EGL_NO_CONTEXT,
+ EGL_LINUX_DMA_BUF_EXT,
+ (EGLClientBuffer)NULL,
+ attrs);
+
+ if (!client->image)
+ error(1, errno, "failed to import image dma-buf");
+
+
+ }
return client;
}
diff --git a/common.h b/common.h
index b9a1781..bae2975 100644
--- a/common.h
+++ b/common.h
@@ -3,6 +3,13 @@
struct server;
+struct bufinfo {
+ int id;
+ int width, height;
+ int stride;
+ int format;
+};
+
struct server *server_create(int sock_fd);
void server_destroy(struct server *server);
diff --git a/fdpass.c b/fdpass.c
new file mode 100644
index 0000000..6e2e0c7
--- /dev/null
+++ b/fdpass.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "fdpass.h"
+
+ssize_t
+sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
+{
+ ssize_t size;
+
+ if (fd) {
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ struct cmsghdr cmsghdr;
+ char control[CMSG_SPACE(sizeof (int))];
+ } cmsgu;
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = buf;
+ iov.iov_len = bufsize;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = cmsgu.control;
+ msg.msg_controllen = sizeof(cmsgu.control);
+ size = recvmsg (sock, &msg, 0);
+ if (size < 0) {
+ perror ("recvmsg");
+ exit(1);
+ }
+ if ((msg.msg_flags & MSG_TRUNC) ||
+ (msg.msg_flags & MSG_CTRUNC)) {
+ fprintf (stderr, "control message truncated");
+ exit(1);
+ }
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
+ if (cmsg->cmsg_level != SOL_SOCKET) {
+ fprintf (stderr, "invalid cmsg_level %d\n",
+ cmsg->cmsg_level);
+ exit(1);
+ }
+ if (cmsg->cmsg_type != SCM_RIGHTS) {
+ fprintf (stderr, "invalid cmsg_type %d\n",
+ cmsg->cmsg_type);
+ exit(1);
+ }
+
+ *fd = *((int *) CMSG_DATA(cmsg));
+ printf ("received fd %d\n", *fd);
+ } else
+ *fd = -1;
+ } else {
+ size = read (sock, buf, bufsize);
+ if (size < 0) {
+ perror("read");
+ exit(1);
+ }
+ }
+ return size;
+}
+
+ssize_t
+sock_fd_write(int sock, void *buf, ssize_t buflen, int fd)
+{
+ ssize_t size;
+ struct msghdr msg;
+ struct iovec iov;
+ union {
+ struct cmsghdr cmsghdr;
+ char control[CMSG_SPACE(sizeof (int))];
+ } cmsgu;
+ struct cmsghdr *cmsg;
+
+ iov.iov_base = buf;
+ iov.iov_len = buflen;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (fd != -1) {
+ msg.msg_control = cmsgu.control;
+ msg.msg_controllen = sizeof(cmsgu.control);
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof (int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ printf ("passing fd %d\n", fd);
+ *((int *) CMSG_DATA(cmsg)) = fd;
+ } else {
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ printf ("not passing fd\n");
+ }
+
+ size = sendmsg(sock, &msg, 0);
+
+ if (size < 0)
+ perror ("sendmsg");
+ return size;
+}
diff --git a/fdpass.h b/fdpass.h
new file mode 100644
index 0000000..236849a
--- /dev/null
+++ b/fdpass.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _FDPASS_H_
+#define _FDPASS_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+ssize_t
+sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd);
+
+ssize_t
+sock_fd_write(int sock, void *buf, ssize_t buflen, int fd);
+
+#endif
diff --git a/server_egl.c b/server_egl.c
index fb00b8d..fa0fd1d 100644
--- a/server_egl.c
+++ b/server_egl.c
@@ -1,3 +1,7 @@
+
+/* requires
+ EGL_KHR_surfaceless_context
+*/
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES
#define _GNU_SOURCE
@@ -17,7 +21,9 @@
#include <error.h>
#include <gbm.h>
#include <xf86drm.h>
+#include "fdpass.h"
#include "common.h"
+#include <drm/drm_fourcc.h>
PFNGLGENTEXTURESEXTPROC my_glGenTextures;
PFNGLGENFRAMEBUFFERSPROC my_glGenFramebuffers;
GLuint tex_ids[4];
@@ -30,27 +36,17 @@ struct rnode_display {
EGLContext egl_ctx;
};
-struct rnode_window {
- struct gbm_surface *gbm_surface;
- EGLSurface egl_surface;
-};
-
-struct window {
- struct display *display;
- int width, height;
- struct rnode_window rnode;
-};
-
struct display {
struct rnode_display rnode;
};
struct server {
struct display *d;
- struct window *w;
GLuint tex_id;
GLuint fb_id;
EGLImageKHR image;
+ int stride;
+ int width, height;
int sock_fd;
};
@@ -152,8 +148,9 @@ static void rnode_init(struct display *d)
if (!d->rnode.egl_ctx)
error(1, errno, "cannot create EGL context");
+
eglMakeCurrent(d->rnode.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
+ d->rnode.egl_ctx);
}
static void rnode_destroy(struct display *d)
@@ -182,80 +179,26 @@ static void display_destroy(struct display *display)
free(display);
}
-static void rnode_window_create(struct window *w)
-{
- struct display *d = w->display;
- EGLBoolean b;
-
- w->rnode.gbm_surface = gbm_surface_create(d->rnode.gbm_dev,
- w->width, w->height,
- GBM_FORMAT_XRGB8888,
- GBM_BO_USE_RENDERING);
- if (!w->rnode.gbm_surface)
- error(1, errno, "cannot create gbm surface");
-
- w->rnode.egl_surface = eglCreateWindowSurface(d->rnode.egl_display,
- d->rnode.egl_conf,
- (EGLNativeWindowType)w->rnode.gbm_surface, NULL);
- if (!w->rnode.egl_surface)
- error(1, errno, "Cannot create EGL surface");
-
- b = eglMakeCurrent(d->rnode.egl_display,
- w->rnode.egl_surface,
- w->rnode.egl_surface,
- d->rnode.egl_ctx);
- if (!b)
- error(1, errno, "Cannot activate EGL context");
-}
-
-static void rnode_window_destroy(struct window *w)
-{
- struct display *d = w->display;
-
- eglMakeCurrent(d->rnode.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglDestroySurface(d->rnode.egl_display, w->rnode.egl_surface);
- gbm_surface_destroy(w->rnode.gbm_surface);
-}
-
-static struct window *window_create(struct display *display)
-{
- struct window *window = calloc(1, sizeof(*window));
- if (!window)
- error(1, errno, "cannot allocate window");
-
- window->display = display;
- window->width = 100;
- window->height = 100;
-
- rnode_window_create(window);
- return window;
-}
-
-static void window_destroy(struct window *window)
-{
- rnode_window_destroy(window);
- free(window);
-}
-
static void init_fns(void)
{
my_glGenTextures = (void *)eglGetProcAddress("glGenTextures");
my_glGenFramebuffers = (void *)eglGetProcAddress("glGenFramebuffers");
}
-static void server_init_texture(struct server *server)
+static int server_init_texture(struct server *server)
{
EGLBoolean b;
EGLint name, handle, stride;
int r;
int fd;
+ server->width = 640;
+ server->height = 480;
/* create some textures */
(*my_glGenTextures)(1, &server->tex_id);
glBindTexture(GL_TEXTURE_2D, server->tex_id);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 480, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, server->width, server->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
(*my_glGenFramebuffers)(1, &server->fb_id);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, server->fb_id);
@@ -272,17 +215,17 @@ static void server_init_texture(struct server *server)
b = eglExportDRMImageMESA(server->d->rnode.egl_display,
server->image,
&name, &handle,
- &stride);
+ &server->stride);
if (!b)
error(1, errno, "failed to export image\n");
- fprintf(stderr,"image exported %d %d %d\n", name, handle, stride);
+ fprintf(stderr,"image exported %d %d %d\n", name, handle, server->stride);
r = drmPrimeHandleToFD(server->d->rnode.fd, handle, 0, &fd);
if (r < 0)
error(1, errno, "cannot get prime-fd for handle");
-
+ return fd;
}
static void server_fini_texture(struct server *server)
@@ -294,17 +237,29 @@ static void server_fini_texture(struct server *server)
struct server *server_create(int sock_fd)
{
struct server *server;
-
+ int fd;
server = calloc(1, sizeof(struct server));
if (!server)
error(1, errno, "cannot allocate memory");
server->d = display_create();
- server->w = window_create(server->d);
server->sock_fd = sock_fd;
init_fns();
- server_init_texture(server);
+ fd = server_init_texture(server);
+ {
+ ssize_t size;
+ int i;
+ struct bufinfo buf;
+
+ buf.id = server->tex_id;
+ buf.stride = server->stride;
+ buf.width = server->width;
+ buf.height = server->height;
+ buf.format = DRM_FORMAT_XRGB8888;
+ size = sock_fd_write(server->sock_fd, &buf, sizeof(buf), fd);
+ }
+ sleep(10);
return server;
}
@@ -312,7 +267,6 @@ struct server *server_create(int sock_fd)
void server_destroy(struct server *server)
{
server_fini_texture(server);
- window_destroy(server->w);
display_destroy(server->d);
close(server->sock_fd);
free(server);