// File: /workspace/github_c_makefile_star2_O2/lukexi[P]eglstreams-mini/src/egl.c
// Function: SetupEGLDisplays
egl_display* SetupEGLDisplays(
    EGLDisplay eglDpy,
    EGLConfig eglConfig,
    EGLContext eglContext,
    kms_plane* Planes, int NumPlanes)
{

    EGLBoolean ret;

    egl_display* Displays = malloc(sizeof(egl_display) * NumPlanes);
    for (int PlaneIndex = 0; PlaneIndex < NumPlanes; PlaneIndex++) {
        kms_plane* Plane = &Planes[PlaneIndex];

        EGLAttrib layerAttribs[] = {
            EGL_DRM_PLANE_EXT,
            Plane->PlaneID,
            EGL_NONE,
        };
        printf("Setting up plane ID: %i\n", Plane->PlaneID);

        EGLAttrib streamAttribs[] = {
            EGL_STREAM_FIFO_LENGTH_KHR, 0,
            EGL_CONSUMER_AUTO_ACQUIRE_EXT, EGL_FALSE,
            EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0,
            EGL_NONE,
        };

        EGLint surfaceAttribs[] = {
            EGL_WIDTH,  Plane->Width,
            EGL_HEIGHT, Plane->Height,
            EGL_NONE
        };

        /* Find the EGLOutputLayer that corresponds to the DRM KMS plane. */
        EGLOutputLayerEXT eglLayer;
        EGLint n = 0;
        ret = pEglGetOutputLayersEXT(eglDpy, layerAttribs, &eglLayer, 1, &n);

        if (!ret || !n) {
            Fatal("Unable to get EGLOutputLayer for plane 0x%08x\n", Plane->PlaneID);
        }

        /* Set the OutputLayer's swap interval */
        pEglOutputLayerAttribEXT(eglDpy, eglLayer,
            EGL_SWAP_INTERVAL_EXT, 0);
        if (!ret) {
            Fatal("Unable to set EGLOutputLayer's swap interval\n");
        }

        /* Create an EGLStream. */
        EGLStreamKHR eglStream = pEglCreateStreamAttribNV(eglDpy, streamAttribs);

        if (eglStream == EGL_NO_STREAM_KHR) {
            EGLCheck("eglCreateStreamAttribNV");
            Fatal("Unable to create stream.\n");
        }

        /* Set the EGLOutputLayer as the consumer of the EGLStream. */

        ret = pEglStreamConsumerOutputEXT(eglDpy, eglStream, eglLayer);

        if (!ret) {
            Fatal("Unable to create EGLOutput stream consumer.\n");
        }

        /*
         * EGL_KHR_stream defines that normally stream consumers need to
         * explicitly retrieve frames from the stream.  That may be useful
         * when we attempt to better integrate
         * EGL_EXT_stream_consumer_egloutput with DRM atomic KMS requests.
         * But, EGL_EXT_stream_consumer_egloutput defines that by default:
         *
         *   On success, <layer> is bound to <stream>, <stream> is placed
         *   in the EGL_STREAM_STATE_CONNECTING_KHR state, and EGL_TRUE is
         *   returned.  Initially, no changes occur to the image displayed
         *   on <layer>. When the <stream> enters state
         *   EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR, <layer> will begin
         *   displaying frames, without further action required on the
         *   application's part, as they become available, taking into
         *   account any timestamps, swap intervals, or other limitations
         *   imposed by the stream or producer attributes.
         *
         * So, eglSwapBuffers() (to produce new frames) is sufficient for
         * the frames to be displayed.  That behavior can be altered with
         * the EGL_EXT_stream_acquire_mode extension.
         */

        /*
         * Create an EGLSurface as the producer of the EGLStream.  Once
         * the stream's producer and consumer are defined, the stream is
         * ready to use.  eglSwapBuffers() calls for the EGLSurface will
         * deliver to the stream's consumer, i.e., the DRM KMS plane
         * corresponding to the EGLOutputLayer.
         */

        EGLSurface eglSurface = pEglCreateStreamProducerSurfaceKHR(eglDpy, eglConfig,
                                                        eglStream, surfaceAttribs);
        if (eglSurface == EGL_NO_SURFACE) {
            Fatal("Unable to create EGLSurface stream producer.\n");
        }

        /*
         * Make current to the EGLSurface, so that OpenGL rendering is
         * directed to it.
         */
        Displays[PlaneIndex].EDID            = Plane->EDID;
        Displays[PlaneIndex].Width           = Plane->Width;
        Displays[PlaneIndex].Height          = Plane->Height;
        Displays[PlaneIndex].MonitorName     = strdup(Plane->EDID->MonitorName);
        Displays[PlaneIndex].SerialNumber    = strdup(Plane->EDID->SerialNumber);
        Displays[PlaneIndex].DisplayDevice   = eglDpy;
        Displays[PlaneIndex].Surface         = eglSurface;
        Displays[PlaneIndex].Context         = eglContext;
        Displays[PlaneIndex].Config          = eglConfig;
        Displays[PlaneIndex].Stream          = eglStream;
        Displays[PlaneIndex].Layer           = eglLayer;
        Displays[PlaneIndex].PageFlipPending = false;
    }


    return Displays;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rcx, %r15
movq %rdx, 0x40(%rsp)
movq %rsi, %r12
movq %rdi, 0x18(%rsp)
movslq %r8d, %r14
imulq $0x58, %r14, %rdi
callq 0x2140
movq %rax, %rbx
xorl %eax, %eax
testl %r14d, %r14d
cmovlel %eax, %r14d
imulq $0x58, %r14, %rax
movq %rax, 0x48(%rsp)
movq %r15, %r14
xorl %r15d, %r15d
movq %r12, 0x10(%rsp)
cmpq %r15, 0x48(%rsp)
je 0x33a1
movq $0x3235, 0x50(%rsp)     # imm = 0x3235
movl (%r14), %esi
movq %rsi, 0x58(%rsp)
movl $0x3038, %r12d          # imm = 0x3038
movq %r12, 0x60(%rsp)
leaq 0x23d7(%rip), %rdi      # 0x55ac
xorl %eax, %eax
callq 0x2050
xorps %xmm0, %xmm0
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x90(%rsp)
movq $0x31fc, 0x70(%rsp)     # imm = 0x31FC
movq $0x332b, 0x80(%rsp) # imm = 0x332B
movq $0x321e, 0x90(%rsp) # imm = 0x321E
movq %r12, 0xa0(%rsp)
movl $0x3057, 0x20(%rsp)     # imm = 0x3057
movl 0x4(%r14), %eax
movl %eax, 0x24(%rsp)
movl $0x3056, 0x28(%rsp)     # imm = 0x3056
movl 0x8(%r14), %eax
movl %eax, 0x2c(%rsp)
movl $0x3038, 0x30(%rsp)     # imm = 0x3038
andl $0x0, 0x4(%rsp)
movq 0x18(%rsp), %r13
movq %r13, %rdi
leaq 0x50(%rsp), %rsi
leaq 0x8(%rsp), %rdx
pushq $0x1
popq %rcx
leaq 0x4(%rsp), %r8
callq *0x4fde(%rip)           # 0x8248
movl %eax, %ebp
testl %eax, %eax
je 0x3277
cmpl $0x0, 0x4(%rsp)
jne 0x3288
movl (%r14), %esi
leaq 0x2344(%rip), %rdi      # 0x55c5
xorl %eax, %eax
callq 0x40d8
movq 0x8(%rsp), %rsi
movq %r13, %rdi
movl $0x322f, %edx           # imm = 0x322F
xorl %ecx, %ecx
callq *0x4feb(%rip)           # 0x8288
testl %ebp, %ebp
jne 0x32af
leaq 0x234c(%rip), %rdi      # 0x55f4
xorl %eax, %eax
callq 0x40d8
movq %r13, %rdi
leaq 0x70(%rsp), %rsi
callq *0x4fc3(%rip)           # 0x8280
movq %rax, %rbp
testq %rax, %rax
jne 0x32df
leaq 0x1ea7(%rip), %rdi      # 0x5173
callq 0x306c
leaq 0x234a(%rip), %rdi      # 0x5622
xorl %eax, %eax
callq 0x40d8
movq 0x8(%rsp), %rdx
movq %r13, %rdi
movq %rbp, %rsi
callq *0x4f68(%rip)           # 0x8258
testl %eax, %eax
jne 0x3302
leaq 0x2341(%rip), %rdi      # 0x563c
xorl %eax, %eax
callq 0x40d8
movq %r13, %rdi
movq 0x10(%rsp), %rsi
movq %rbp, %rdx
leaq 0x20(%rsp), %rcx
callq *0x4f48(%rip)           # 0x8260
movq %rax, %r13
testq %rax, %rax
jne 0x332e
leaq 0x2342(%rip), %rdi      # 0x5669
xorl %eax, %eax
callq 0x40d8
movq 0x10(%r14), %r12
movq %r12, (%rbx,%r15)
movq 0x4(%r14), %rax
movq %rax, 0x8(%rbx,%r15)
movq (%r12), %rdi
callq 0x2300
movq %rax, 0x10(%rbx,%r15)
movq 0x8(%r12), %rdi
callq 0x2300
movq %rax, 0x18(%rbx,%r15)
movq 0x18(%rsp), %rax
movq %rax, 0x30(%rbx,%r15)
movq %r13, 0x20(%rbx,%r15)
movq 0x40(%rsp), %rax
movq %rax, 0x28(%rbx,%r15)
movq 0x10(%rsp), %r12
movq %r12, 0x38(%rbx,%r15)
movq %rbp, 0x40(%rbx,%r15)
movq 0x8(%rsp), %rax
movq %rax, 0x48(%rbx,%r15)
movb $0x0, 0x50(%rbx,%r15)
addq $0x58, %r15
addq $0x18, %r14
jmp 0x31a7
movq %rbx, %rax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq