// File: /workspace/github_c_makefile_star2_O3/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 $0xb8, %rsp
movl %r8d, %ebp
movq %rcx, %rbx
movq %rdx, 0x58(%rsp)
movq %rsi, %r12
movq %rdi, %r13
movslq %r8d, %r14
imulq $0x58, %r14, %rdi
callq 0x2140
movq %rax, 0x18(%rsp)
testl %r14d, %r14d
jle 0x342d
movl %ebp, %eax
movq 0x18(%rsp), %r14
addq $0x50, %r14
shlq $0x3, %rax
leaq (%rax,%rax,2), %rax
movq %rax, 0x50(%rsp)
xorl %r15d, %r15d
movq %r13, 0x48(%rsp)
movq %r12, 0x40(%rsp)
movq $0x3235, 0x60(%rsp)     # imm = 0x3235
movl (%rbx,%r15), %esi
movq %rsi, 0x68(%rsp)
movl $0x3038, %ebp           # imm = 0x3038
movq %rbp, 0x70(%rsp)
leaq 0x2370(%rip), %rdi      # 0x55ac
xorl %eax, %eax
callq 0x2050
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x90(%rsp)
movaps %xmm0, 0xa0(%rsp)
movq $0x31fc, 0x80(%rsp) # imm = 0x31FC
movq $0x332b, 0x90(%rsp) # imm = 0x332B
movq $0x321e, 0xa0(%rsp) # imm = 0x321E
movq %rbp, 0xb0(%rsp)
movl $0x3057, 0x20(%rsp)     # imm = 0x3057
movl 0x4(%rbx,%r15), %eax
movl %eax, 0x24(%rsp)
movl $0x3056, 0x28(%rsp)     # imm = 0x3056
movl 0x8(%rbx,%r15), %eax
movl %eax, 0x2c(%rsp)
movl $0x3038, 0x30(%rsp)     # imm = 0x3038
movl $0x0, 0xc(%rsp)
movq %r13, %rdi
leaq 0x60(%rsp), %rsi
leaq 0x10(%rsp), %rdx
movl $0x1, %ecx
leaq 0xc(%rsp), %r8
callq *0x4f6f(%rip)           # 0x8248
movl %eax, %ebp
testl %eax, %eax
je 0x32fd
cmpl $0x0, 0xc(%rsp)
je 0x32fd
movq 0x10(%rsp), %rsi
movq %r13, %rdi
movl $0x322f, %edx           # imm = 0x322F
xorl %ecx, %ecx
callq *0x4f8d(%rip)           # 0x8288
jmp 0x3336
movl (%rbx,%r15), %esi
leaq 0x22bd(%rip), %rdi      # 0x55c5
xorl %eax, %eax
callq 0x4184
movq 0x10(%rsp), %rsi
movq %r13, %rdi
movl $0x322f, %edx           # imm = 0x322F
xorl %ecx, %ecx
callq *0x4f64(%rip)           # 0x8288
testl %ebp, %ebp
jne 0x3336
leaq 0x22c5(%rip), %rdi      # 0x55f4
xorl %eax, %eax
callq 0x4184
movq %r13, %rdi
leaq 0x80(%rsp), %rsi
callq *0x4f39(%rip)           # 0x8280
movq %rax, %rbp
testq %rax, %rax
jne 0x3369
leaq 0x1e1d(%rip), %rdi      # 0x5173
callq 0x30c8
leaq 0x22c0(%rip), %rdi      # 0x5622
xorl %eax, %eax
callq 0x4184
movq 0x10(%rsp), %rdx
movq %r13, %rdi
movq %rbp, %rsi
callq *0x4ede(%rip)           # 0x8258
testl %eax, %eax
jne 0x338c
leaq 0x22b7(%rip), %rdi      # 0x563c
xorl %eax, %eax
callq 0x4184
movq %r13, %rdi
movq %r12, %rsi
movq %rbp, %rdx
leaq 0x20(%rsp), %rcx
callq *0x4ec0(%rip)           # 0x8260
movq %rax, %r13
testq %rax, %rax
jne 0x33b6
leaq 0x22ba(%rip), %rdi      # 0x5669
xorl %eax, %eax
callq 0x4184
movq %rbx, %r12
movq 0x10(%rbx,%r15), %rbx
movq %rbx, -0x50(%r14)
movq 0x4(%r12,%r15), %rax
movq %rax, -0x48(%r14)
movq (%rbx), %rdi
callq 0x2300
movq %rax, -0x40(%r14)
movq 0x8(%rbx), %rdi
movq %r12, %rbx
callq 0x2300
movq %rax, -0x38(%r14)
movq 0x48(%rsp), %rcx
movq %rcx, -0x20(%r14)
movq %r13, -0x30(%r14)
movq 0x58(%rsp), %rax
movq %rax, -0x28(%r14)
movq 0x40(%rsp), %r12
movq %r12, -0x18(%r14)
movq %rbp, -0x10(%r14)
movq 0x10(%rsp), %rax
movq %rax, -0x8(%r14)
movb $0x0, (%r14)
addq $0x58, %r14
addq $0x18, %r15
cmpq %r15, 0x50(%rsp)
movq %rcx, %r13
jne 0x3219
movq 0x18(%rsp), %rax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq