From cf8a80d0d6e8fca0a5f6a78e9b534e97cea7a963 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 25 Apr 2023 00:54:35 +0800 Subject: [PATCH] init --- failed-egl-server.c | 196 ++++++++++++++++++++++++++++++++++++++++++++ server.c | 127 ++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+) create mode 100644 failed-egl-server.c create mode 100644 server.c diff --git a/failed-egl-server.c b/failed-egl-server.c new file mode 100644 index 0000000..107700f --- /dev/null +++ b/failed-egl-server.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +// #define APIENTRY +// #define APIENTRYP APIENTRY * +// #define GLAPI extern +// // FIXME integrate into glad +// typedef void(APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)( +// GLenum target, GLeglImageOES image); +// GLAPI PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glad_glEGLImageTargetTexture2DOES; +// typedef void(APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)( +// GLenum target, GLeglImageOES image); +// GLAPI PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC +// glad_glEGLImageTargetRenderbufferStorageOES; + +// // FIXME glad +// static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; +// extern void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); + +int main(int argc, const char **argv) +{ + if (argc < 2) { + printf("not enough arguments\n"); + return 1; + } + + const char *card = argv[1]; + const int drmfd = open(card, O_RDONLY); + if (drmfd < 0) { + fprintf(stderr, "card %s open failed: %s\n", card, strerror(errno)); + return 1; + } + int err; + int source_plane = 0; + int source_crtc = 0; + err = drmSetClientCap(drmfd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + if (err < 0) { + perror("Failed to set universal planes capability: primary planes will not be usable"); + } + drmModePlane *plane = NULL; + drmModePlaneRes *plane_res = NULL; + drmModeFB2 *fb = NULL; + if (source_plane > 0) { + plane = drmModeGetPlane(drmfd, source_plane); + if (!plane) { + fprintf(stderr, "Failed to get plane %d: %s\n", source_plane, strerror(errno)); + goto cleanup; + } + if (plane->fb_id == 0) { + fprintf(stderr, "Place %d does not have an attached framebuffer\n", source_plane); + } + } + else { + plane_res = drmModeGetPlaneResources(drmfd); + if (!plane_res) { + perror("Failed to get plane resources"); + goto cleanup; + } + int i; + for (i = 0; i < plane_res->count_planes; i++) { + plane = drmModeGetPlane(drmfd, plane_res->planes[i]); + if (!plane) { + fprintf(stderr, "Failed to get plane %u: %s\n", plane_res->planes[i], strerror(errno)); + continue; + } + printf("Plane %u CRTC %u FB %u\n", plane->plane_id, plane->crtc_id, plane->fb_id); + if ((source_crtc > 0 && plane->crtc_id != source_crtc) || plane->fb_id == 0) { + // Either not connected to the target source CRTC + // or not active. + drmModeFreePlane(plane); + plane = NULL; + continue; + } + break; + } + if (i == plane_res->count_planes) { + if (source_crtc > 0) { + fprintf(stderr, "No usable planes found on CRTC %d\n", source_crtc); + } else { + fprintf(stderr, "No usable planes found\n"); + } + goto cleanup; + } + printf("Using plane %u to locate framebuffers\n", plane->plane_id); + } + uint32_t plane_id = plane->plane_id; + + fb = drmModeGetFB2(drmfd, plane->fb_id); + if (!fb) { + fprintf(stderr, "Failed to get framebuffer %u: %s\n", plane->fb_id, strerror(errno)); + goto cleanup; + } + //printf("Template framebuffer is %u: %ux%u %ubpp %ub depth %u pitch\n", fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth, fb->pitch); + printf("Template framebuffer is %u: %ux%u fourcc:%u mod:%u flags:%u\n", fb->fb_id, fb->width, fb->height, fb->pixel_format, fb->modifier, fb->flags); + printf("handles %u %u %u %u\n", fb->handles[0], fb->handles[1], fb->handles[2], fb->handles[3]); + printf("offsets %u %u %u %u\n", fb->offsets[0], fb->offsets[1], fb->offsets[2], fb->offsets[3]); + printf("pitches %u %u %u %u\n", fb->pitches[0], fb->pitches[1], fb->pitches[2], fb->pitches[3]); + printf("format %s, modifier %s:%s\n", drmGetFormatName(fb->pixel_format), drmGetFormatModifierVendor(fb->modifier), drmGetFormatModifierName(fb->modifier)); + + if (!fb->handles[0]) { + fprintf(stderr, "No handle set on framebuffer: maybe you need some additional capabilities?\n"); + goto cleanup; + } + + int fd = -1; + err = drmPrimeHandleToFD(drmfd, fb->handles[0], O_RDONLY, &fd); + if (err < 0 || fd < 0) { + perror("Failed to get PRIME fd from framebuffer handle"); + } + + // //size_t buflen = fb->width * fb->height * fb->bpp / 8; + // size_t buflen = fb->width * fb->height * 32 / 8; + // char *buf = malloc(buflen); + // char *mapped = mmap(NULL, buflen, PROT_READ, MAP_SHARED, fd, 0); + // if (mapped == MAP_FAILED) { + // perror("mmap"); + // goto cleanup; + // } + // memcpy(buf, mapped, buflen); + + //unlink("/tmp/1.raw"); + //write(open("/tmp/1.raw", O_WRONLY | O_CREAT, 00644), buf, buflen); + + // EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + // eglInitialize(display, NULL, NULL); + // EGLContext context = eglCreateContext(display, NULL, EGL_NO_CONTEXT, NULL); + // eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context); + EGLAttrib attrs[] = { + EGL_WIDTH, fb->width, + EGL_HEIGHT, fb->height, + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, + EGL_DMA_BUF_PLANE0_FD_EXT, fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, 1, + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, 1 >> 32, + EGL_NONE, + }; + EGLImage image = eglCreateImage(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs); + if (glGetError() != GL_NO_ERROR) { + fprintf(stderr, "eglCreateImage\n"); + } + + // Create an OpenGL texture and bind it to the EGL image + GLuint texture; + glGenTextures(1, &texture); + if (glGetError() != GL_NO_ERROR) { + fprintf(stderr, "glGenTextures\n"); + } + + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture); + if (glGetError() != GL_NO_ERROR) { + fprintf(stderr, "glBindTexture\n"); + } + + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = + (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image); + if (glGetError() != GL_NO_ERROR) { + fprintf(stderr, "glEGLImageTargetTexture2DOES\n"); + } + + // Read the pixel data from the texture + GLubyte *buf = malloc(fb->width * fb->height * 4); + glReadPixels(0, 0, fb->width, fb->height, GL_RGB, GL_UNSIGNED_BYTE, buf); + if (glGetError() != GL_NO_ERROR) { + fprintf(stderr, "glReadPixels\n"); + } + + // write(open("/tmp/1.raw", O_WRONLY | O_CREAT, 00644), buf, fb->width * fb->height * 4); + + rfbScreenInfoPtr server=rfbGetScreen(0,NULL,fb->width,fb->height,8,3,32/8); + if(!server) + return 1; + server->frameBuffer=buf; + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); + + cleanup: + close(drmfd); + return 1; + +} diff --git a/server.c b/server.c new file mode 100644 index 0000000..0819c85 --- /dev/null +++ b/server.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, const char **argv) +{ + if (argc < 2) { + printf("not enough arguments\n"); + return 1; + } + + const char *card = argv[1]; + const int drmfd = open(card, O_RDONLY); + if (drmfd < 0) { + fprintf(stderr, "card %s open failed: %s\n", card, strerror(errno)); + return 1; + } + int err; + int source_plane = 0; + int source_crtc = 0; + err = drmSetClientCap(drmfd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + if (err < 0) { + perror("Failed to set universal planes capability: primary planes will not be usable"); + } + drmModePlane *plane = NULL; + drmModePlaneRes *plane_res = NULL; + drmModeFB2 *fb = NULL; + if (source_plane > 0) { + plane = drmModeGetPlane(drmfd, source_plane); + if (!plane) { + fprintf(stderr, "Failed to get plane %d: %s\n", source_plane, strerror(errno)); + goto cleanup; + } + if (plane->fb_id == 0) { + fprintf(stderr, "Place %d does not have an attached framebuffer\n", source_plane); + } + } + else { + plane_res = drmModeGetPlaneResources(drmfd); + if (!plane_res) { + perror("Failed to get plane resources"); + goto cleanup; + } + int i; + for (i = 0; i < plane_res->count_planes; i++) { + plane = drmModeGetPlane(drmfd, plane_res->planes[i]); + if (!plane) { + fprintf(stderr, "Failed to get plane %u: %s\n", plane_res->planes[i], strerror(errno)); + continue; + } + printf("Plane %u CRTC %u FB %u\n", plane->plane_id, plane->crtc_id, plane->fb_id); + if ((source_crtc > 0 && plane->crtc_id != source_crtc) || plane->fb_id == 0) { + // Either not connected to the target source CRTC + // or not active. + drmModeFreePlane(plane); + plane = NULL; + continue; + } + break; + } + if (i == plane_res->count_planes) { + if (source_crtc > 0) { + fprintf(stderr, "No usable planes found on CRTC %d\n", source_crtc); + } else { + fprintf(stderr, "No usable planes found\n"); + } + goto cleanup; + } + printf("Using plane %u to locate framebuffers\n", plane->plane_id); + } + uint32_t plane_id = plane->plane_id; + + fb = drmModeGetFB2(drmfd, plane->fb_id); + if (!fb) { + fprintf(stderr, "Failed to get framebuffer %u: %s\n", plane->fb_id, strerror(errno)); + goto cleanup; + } + //printf("Template framebuffer is %u: %ux%u %ubpp %ub depth %u pitch\n", fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth, fb->pitch); + printf("Template framebuffer is %u: %ux%u fourcc:%u mod:%u flags:%u\n", fb->fb_id, fb->width, fb->height, fb->pixel_format, fb->modifier, fb->flags); + printf("handles %u %u %u %u\n", fb->handles[0], fb->handles[1], fb->handles[2], fb->handles[3]); + printf("offsets %u %u %u %u\n", fb->offsets[0], fb->offsets[1], fb->offsets[2], fb->offsets[3]); + printf("pitches %u %u %u %u\n", fb->pitches[0], fb->pitches[1], fb->pitches[2], fb->pitches[3]); + printf("format %s, modifier %s:%s\n", drmGetFormatName(fb->pixel_format), drmGetFormatModifierVendor(fb->modifier), drmGetFormatModifierName(fb->modifier)); + + if (!fb->handles[0]) { + fprintf(stderr, "No handle set on framebuffer: maybe you need some additional capabilities?\n"); + goto cleanup; + } + + int fd = -1; + err = drmPrimeHandleToFD(drmfd, fb->handles[0], O_RDONLY, &fd); + if (err < 0 || fd < 0) { + perror("Failed to get PRIME fd from framebuffer handle"); + } + + //size_t buflen = fb->width * fb->height * fb->bpp / 8; + size_t buflen = fb->width * fb->height * 32 / 8; + char *buf = malloc(buflen); + char *mapped = mmap(NULL, buflen, PROT_READ, MAP_SHARED, fd, 0); + if (mapped == MAP_FAILED) { + perror("mmap"); + goto cleanup; + } + memcpy(buf, mapped, buflen); + + //unlink("/tmp/1.raw"); + //write(open("/tmp/1.raw", O_WRONLY | O_CREAT, 00644), buf, buflen); + + rfbScreenInfoPtr server=rfbGetScreen(0,NULL,fb->width,fb->height,8,3,32/8); + if(!server) + return 1; + server->frameBuffer=buf+8; + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); + + cleanup: + close(drmfd); + return 1; + +} \ No newline at end of file