Example #1
0
        internal DrmModeInfo(ref drmModeModeInfo info)
        {
            Mode = info;

            fixed(void *pName = info.name)
            Name = Marshal.PtrToStringAnsi(new IntPtr(pName));
        }
Example #2
0
        void Init(DrmCard card, DrmResources resources, DrmConnector connector, DrmModeInfo modeInfo)
        {
            FbDestroyDelegate = FbDestroyCallback;
            _card             = card;
            uint GetCrtc()
            {
                if (resources.Encoders.TryGetValue(connector.EncoderId, out var encoder))
                {
                    // Not sure why that should work
                    return(encoder.Encoder.crtc_id);
                }
                else
                {
                    foreach (var encId in connector.EncoderIds)
                    {
                        if (resources.Encoders.TryGetValue(encId, out encoder) &&
                            encoder.PossibleCrtcs.Count > 0)
                        {
                            return(encoder.PossibleCrtcs.First().crtc_id);
                        }
                    }

                    throw new InvalidOperationException("Unable to find CRTC matching the desired mode");
                }
            }

            _crtcId = GetCrtc();
            var device = gbm_create_device(card.Fd);

            _gbmTargetSurface = gbm_surface_create(device, modeInfo.Resolution.Width, modeInfo.Resolution.Height,
                                                   GbmColorFormats.GBM_FORMAT_XRGB8888, GbmBoFlags.GBM_BO_USE_SCANOUT | GbmBoFlags.GBM_BO_USE_RENDERING);
            if (_gbmTargetSurface == null)
            {
                throw new InvalidOperationException("Unable to create GBM surface");
            }



            _eglDisplay = new EglDisplay(new EglInterface(eglGetProcAddress), 0x31D7, device, null);
            _eglSurface = _eglDisplay.CreateWindowSurface(_gbmTargetSurface);


            EglContext CreateContext(EglContext share)
            {
                var offSurf = gbm_surface_create(device, 1, 1, GbmColorFormats.GBM_FORMAT_XRGB8888,
                                                 GbmBoFlags.GBM_BO_USE_RENDERING);

                if (offSurf == null)
                {
                    throw new InvalidOperationException("Unable to create 1x1 sized GBM surface");
                }
                return(_eglDisplay.CreateContext(share, _eglDisplay.CreateWindowSurface(offSurf)));
            }

            _immediateContext = CreateContext(null);
            _deferredContext  = CreateContext(_immediateContext);

            _immediateContext.MakeCurrent(_eglSurface);
            _eglDisplay.GlInterface.ClearColor(0, 0, 0, 0);
            _eglDisplay.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
            _eglSurface.SwapBuffers();
            var bo          = gbm_surface_lock_front_buffer(_gbmTargetSurface);
            var fbId        = GetFbIdForBo(bo);
            var connectorId = connector.Id;
            var mode        = modeInfo.Mode;


            var res = drmModeSetCrtc(_card.Fd, _crtcId, fbId, 0, 0, &connectorId, 1, &mode);

            if (res != 0)
            {
                throw new Win32Exception(res, "drmModeSetCrtc failed");
            }

            _mode      = mode;
            _currentBo = bo;

            // Go trough two cycles of buffer swapping (there are render artifacts otherwise)
            for (var c = 0; c < 2; c++)
            {
                using (CreateGlRenderTarget().BeginDraw())
                {
                    _eglDisplay.GlInterface.ClearColor(0, 0, 0, 0);
                    _eglDisplay.GlInterface.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_STENCIL_BUFFER_BIT);
                }
            }
        }