#include #include #include #include #include #define EGL_EGLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #include #include #include #include static void draw_image(EGLImageKHR image, float r, float g, float b) { GLuint fb, color_rb; glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER_EXT, fb); glGenRenderbuffers(1, &color_rb); glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_rb); glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, color_rb); glClearColor(r, g, b, 0); glClear(GL_COLOR_BUFFER_BIT); glFlush(); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, 0); glDeleteRenderbuffers(1, &color_rb); glDeleteFramebuffers(1, &fb); } int main(int argc, char *argv[]) { WFDDevice dev = WFD_INVALID_HANDLE; WFDPort port = WFD_INVALID_HANDLE; WFDPipeline pipeline = WFD_INVALID_HANDLE; WFDSource source[2] = { WFD_INVALID_HANDLE, WFD_INVALID_HANDLE }; WFDEvent event = WFD_INVALID_HANDLE; WFDint num = 0; WFDint *devices; WFDint *ports; WFDint *pipelines; WFDPortMode *modes; WFDint source_rect[4] = { 0, 0, 0, 0 }; int drm_fd; int width,height; EGLDisplay edpy; EGLContext ectx; EGLImageKHR image[2]; EGLint major,minor; EGLint image_attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; EGLSyncKHR esync; num = wfdEnumerateDevices(NULL, 0, NULL); printf("num: %d\n", num); devices = calloc(num, sizeof *devices); if (devices == NULL) return 1; num = wfdEnumerateDevices(devices, num, NULL); printf("num: %d\n", num); dev = wfdCreateDevice(WFD_DEFAULT_DEVICE_ID, NULL); printf("dev: %d\n", dev); num = wfdEnumeratePorts(dev, NULL, 0, NULL); printf("ports: %d\n", num); ports = calloc(num, sizeof *ports); if (ports == NULL) return 1; num = wfdEnumeratePorts(dev, ports, num, NULL); if (num < 1) { printf("no ports found.\n"); return 2; } port = wfdCreatePort(dev, ports[0], NULL); printf("port: %d\n", port); num = wfdGetPortModes(dev, port, NULL, 0); modes = calloc(num, sizeof *modes); if (modes == NULL) return 1; num = wfdGetPortModes(dev, port, modes, num); printf("modes: %d\n", num); width = wfdGetPortModeAttribi(dev, port, modes[0], WFD_PORT_MODE_WIDTH); height = wfdGetPortModeAttribi(dev, port, modes[0], WFD_PORT_MODE_HEIGHT); printf("width: %d, height: %d\n", width, height); wfdSetPortMode(dev, port, modes[0]); wfdSetPortAttribi(dev, port, WFD_PORT_POWER_MODE, WFD_POWER_MODE_ON); num = wfdEnumeratePipelines(dev, NULL, 0, NULL); printf("pipelines: %d\n", num); pipelines = calloc(num, sizeof *pipelines); if (pipelines == NULL) return 1; num = wfdEnumeratePipelines(dev, pipelines, num, NULL); if (num < 1) { printf("no pipelines found.\n"); return 3; } num = wfdGetPortAttribi(dev, port, WFD_PORT_PIPELINE_ID_COUNT); if (num == 0) { printf("no bindable pipelines found.\n"); return 4; } printf("%d bindable pipelines found.\n", num); WFDint *bindable_pipelines = calloc(num, sizeof(WFDint)); if (bindable_pipelines == NULL) return 1; wfdGetPortAttribiv(dev, port, WFD_PORT_BINDABLE_PIPELINE_IDS, num, bindable_pipelines); pipeline = wfdCreatePipeline(dev, bindable_pipelines[0], NULL); printf("pipeline: %d\n", pipeline); drm_fd = wfdGetDeviceAttribi(dev, WFD_DEVICE_ID); printf("drm fd: %d\n", drm_fd); edpy = eglGetDRMDisplayMESA(drm_fd); assert(edpy != EGL_NO_DISPLAY); eglInitialize(edpy, &major, &minor); eglBindAPI(EGL_OPENGL_API); ectx = eglCreateContext(edpy, NULL, EGL_NO_CONTEXT, NULL); eglMakeCurrent(edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx); image_attribs[1] = width; image_attribs[3] = height; image[0] = eglCreateDRMImageMESA(edpy, image_attribs); image[1] = eglCreateDRMImageMESA(edpy, image_attribs); draw_image(image[0], 0.0, 1.0, 0.0); draw_image(image[1], 1.0, 0.0, 0.0); source_rect[2] = width; source_rect[3] = height; wfdSetPipelineAttribiv(dev, pipeline, WFD_PIPELINE_SOURCE_RECTANGLE, 4, source_rect); wfdSetPipelineAttribiv(dev, pipeline, WFD_PIPELINE_DESTINATION_RECTANGLE, 4, source_rect); source[0] = wfdCreateSourceFromImage(dev, pipeline, image[0], NULL); source[1] = wfdCreateSourceFromImage(dev, pipeline, image[1], NULL); printf("source[0]: %d\n", source[0]); printf("source[1]: %d\n", source[1]); event = wfdCreateEvent(dev, NULL); wfdBindSourceToPipeline(dev, pipeline, source[0], WFD_TRANSITION_AT_VSYNC, NULL); wfdBindPipelineToPort(dev, port, pipeline); wfdDeviceCommit(dev, WFD_COMMIT_ENTIRE_DEVICE, WFD_INVALID_HANDLE); sleep(1); wfdBindSourceToPipeline(dev, pipeline, source[1], WFD_TRANSITION_AT_VSYNC, NULL); wfdDeviceCommit(dev, WFD_COMMIT_PIPELINE, pipeline); WFDEventType type = wfdDeviceEventWait(dev, event, WFD_FOREVER); switch (type) { case WFD_EVENT_PIPELINE_BIND_SOURCE_COMPLETE: printf("got bind source event. pipeline: %d\n", wfdGetEventAttribi(dev, event, WFD_EVENT_PIPELINE_BIND_PIPELINE_ID)); break; default: printf("wrong device\n"); return 5; break; } sleep(1); esync = eglCreateSyncKHR(edpy, EGL_SYNC_REUSABLE_KHR, NULL); wfdDeviceEventAsync(dev, event, edpy, esync); wfdBindSourceToPipeline(dev, pipeline, source[0], WFD_TRANSITION_AT_VSYNC, NULL); /* commit entire device should work as well :) */ wfdDeviceCommit(dev, WFD_COMMIT_ENTIRE_DEVICE, WFD_INVALID_HANDLE); EGLint status = eglClientWaitSyncKHR(edpy, esync, 0, EGL_FOREVER_KHR); switch (status) { case EGL_CONDITION_SATISFIED_KHR: printf("condition satisfied\n"); WFDEventType type = wfdDeviceEventWait(dev, event, WFD_FOREVER); break; default: printf("ClientWaitSync badly returned: %d\n", status); return 5; } sleep(1); wfdDestroyEvent(dev, event); wfdDestroySource(dev, source[0]); wfdDestroySource(dev, source[1]); wfdDestroyEvent(dev, event); wfdDestroyPipeline(dev, pipeline); wfdDestroyPort(dev, port); wfdDestroyDevice(dev); free(modes); free(pipelines); free(ports); free(devices); return 0; }