コード例 #1
0
 void AppendRetroShaderChain(FilterProgram program, string name, Filters.RetroShaderChain retroChain, Dictionary <string, object> properties)
 {
     for (int i = 0; i < retroChain.Passes.Length; i++)
     {
         var    pass  = retroChain.Passes[i];
         var    rsp   = new Filters.RetroShaderPass(retroChain, i);
         string fname = $"{name}[{i}]";
         program.AddFilter(rsp, fname);
         rsp.Parameters = properties;
     }
 }
コード例 #2
0
 void AppendRetroShaderChain(FilterProgram program, string name, BizHawk.Client.EmuHawk.Filters.RetroShaderChain retroChain, Dictionary <string, object> properties)
 {
     for (int i = 0; i < retroChain.Passes.Length; i++)
     {
         var    pass  = retroChain.Passes[i];
         var    rsp   = new BizHawk.Client.EmuHawk.Filters.RetroShaderPass(retroChain, i);
         string fname = string.Format("{0}[{1}]", name, i);
         program.AddFilter(rsp, fname);
         rsp.Parameters = properties;
     }
 }
コード例 #3
0
        FilterProgram BuildDefaultChain(Size chain_insize, Size chain_outsize, bool includeOSD)
        {
            //select user special FX shader chain
            Dictionary <string, object> selectedChainProperties = new Dictionary <string, object>();

            BizHawk.Client.EmuHawk.Filters.RetroShaderChain selectedChain = null;

            if (Global.Config.TargetDisplayFilter == 3 && ShaderChain_user != null && ShaderChain_user.Available)
            {
                selectedChain = ShaderChain_user;
            }

            BizHawk.Client.EmuHawk.Filters.FinalPresentation fPresent = new BizHawk.Client.EmuHawk.Filters.FinalPresentation(chain_outsize);
            BizHawk.Client.EmuHawk.Filters.SourceImage       fInput   = new BizHawk.Client.EmuHawk.Filters.SourceImage(chain_insize);
            BizHawk.Client.EmuHawk.Filters.OSD fOSD = new BizHawk.Client.EmuHawk.Filters.OSD();
            fOSD.RenderCallback = () =>
            {
                if (!includeOSD)
                {
                    return;
                }
                var size = fOSD.FindInput().SurfaceFormat.Size;
                Renderer.Begin(size.Width, size.Height);
                Renderer.SetBlendState(GL.BlendNormal);
                Renderer.End();
            };

            var chain = new FilterProgram();

            //add the first filter, encompassing output from the emulator core
            chain.AddFilter(fInput, "input");

            //choose final filter
            BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.None;
            if (Global.Config.DispFinalFilter == 1)
            {
                finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.Bilinear;
            }
            if (Global.Config.DispFinalFilter == 2)
            {
                finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.Bicubic;
            }

            finalFilter = BizHawk.Client.EmuHawk.Filters.FinalPresentation.eFilterOption.None;

            fPresent.FilterOption = finalFilter;

            //add final presentation
            chain.AddFilter(fPresent, "presentation");

            return(chain);
        }
コード例 #4
0
		private void AppendLuaLayer(FilterProgram chain, string name)
		{
			var luaNativeSurface = LuaSurfaceSets[name].GetCurrent();
			if (luaNativeSurface == null)
			{
				return;
			}

			Texture2d luaNativeTexture = LuaSurfaceFrugalizers[name].Get(luaNativeSurface);
			var fLuaLayer = new Filters.LuaLayer();
			fLuaLayer.SetTexture(luaNativeTexture);
			chain.AddFilter(fLuaLayer, name);
		}
コード例 #5
0
ファイル: DisplayManager.cs プロジェクト: lenalia/BizHawk
        FilterProgram UpdateSourceInternal(JobInfo job)
        {
            if (job.chain_outsize.Width == 0 || job.chain_outsize.Height == 0)
            {
                //this has to be a NOP, because lots of stuff will malfunction on a 0-sized viewport
                return(null);
            }

            //no drawing actually happens. it's important not to begin drawing on a control
            if (!job.simulate && !job.offscreen)
            {
                GLManager.Activate(CR_GraphicsControl);
            }

            IVideoProvider videoProvider = job.videoProvider;
            bool           simulate      = job.simulate;
            Size           chain_outsize = job.chain_outsize;

            //simulate = true;

            int vw = videoProvider.BufferWidth;
            int vh = videoProvider.BufferHeight;

            if (Global.Config.DispFixAspectRatio)
            {
                if (Global.Config.DispManagerAR == Config.EDispManagerAR.System)
                {
                    vw = videoProvider.VirtualWidth;
                    vh = videoProvider.VirtualHeight;
                }
                if (Global.Config.DispManagerAR == Config.EDispManagerAR.Custom)
                {
                    vw = Global.Config.DispCustomUserARWidth;
                    vh = Global.Config.DispCustomUserARHeight;
                }
                if (Global.Config.DispManagerAR == Config.EDispManagerAR.CustomRatio)
                {
                    FixRatio(Global.Config.DispCustomUserARX, Global.Config.DispCustomUserARY, videoProvider.BufferWidth, videoProvider.BufferHeight, out vw, out vh);
                }
            }

            var padding = CalculateCompleteContentPadding(true, false);

            vw += padding.Horizontal;
            vh += padding.Vertical;

            int[] videoBuffer = videoProvider.GetVideoBuffer();

            int  bufferWidth   = videoProvider.BufferWidth;
            int  bufferHeight  = videoProvider.BufferHeight;
            bool isGlTextureId = videoBuffer.Length == 1;

            BitmapBuffer bb           = null;
            Texture2d    videoTexture = null;

            if (!simulate)
            {
                if (isGlTextureId)
                {
                    //FYI: this is a million years from happening on n64, since it's all geriatric non-FBO code
                    //is it workable for saturn?
                    videoTexture = GL.WrapGLTexture2d(new IntPtr(videoBuffer[0]), bufferWidth, bufferHeight);
                }
                else
                {
                    //wrap the videoprovider data in a BitmapBuffer (no point to refactoring that many IVideoProviders)
                    bb = new BitmapBuffer(bufferWidth, bufferHeight, videoBuffer);
                    bb.DiscardAlpha();

                    //now, acquire the data sent from the videoProvider into a texture
                    videoTexture = VideoTextureFrugalizer.Get(bb);

                    //lets not use this. lets define BizwareGL to make clamp by default (TBD: check opengl)
                    //GL.SetTextureWrapMode(videoTexture, true);
                }
            }

            //record the size of what we received, since lua and stuff is gonna want to draw onto it
            currEmuWidth  = bufferWidth;
            currEmuHeight = bufferHeight;

            //build the default filter chain and set it up with services filters will need
            Size chain_insize = new Size(bufferWidth, bufferHeight);

            var filterProgram = BuildDefaultChain(chain_insize, chain_outsize, job.includeOSD);

            filterProgram.GuiRenderer = Renderer;
            filterProgram.GL          = GL;

            //setup the source image filter
            EmuHawk.Filters.SourceImage fInput = filterProgram["input"] as EmuHawk.Filters.SourceImage;
            fInput.Texture = videoTexture;

            //setup the final presentation filter
            EmuHawk.Filters.FinalPresentation fPresent = filterProgram["presentation"] as EmuHawk.Filters.FinalPresentation;
            fPresent.VirtualTextureSize = new Size(vw, vh);
            fPresent.TextureSize        = new Size(bufferWidth, bufferHeight);
            fPresent.BackgroundColor    = videoProvider.BackgroundColor;
            fPresent.GuiRenderer        = Renderer;
            fPresent.Flip = isGlTextureId;
            fPresent.Config_FixAspectRatio  = Global.Config.DispFixAspectRatio;
            fPresent.Config_FixScaleInteger = Global.Config.DispFixScaleInteger;
            fPresent.Padding      = ClientExtraPadding;
            fPresent.AutoPrescale = Global.Config.DispAutoPrescale;

            fPresent.GL = GL;

            filterProgram.Compile("default", chain_insize, chain_outsize, !job.offscreen);

            if (simulate)
            {
            }
            else
            {
                CurrentFilterProgram = filterProgram;
                UpdateSourceDrawingWork(job);
            }

            //cleanup:
            if (bb != null)
            {
                bb.Dispose();
            }

            return(filterProgram);
        }
コード例 #6
0
ファイル: DisplayManager.cs プロジェクト: lenalia/BizHawk
        FilterProgram BuildDefaultChain(Size chain_insize, Size chain_outsize, bool includeOSD)
        {
            //select user special FX shader chain
            Dictionary <string, object> selectedChainProperties = new Dictionary <string, object>();

            EmuHawk.Filters.RetroShaderChain selectedChain = null;
            if (Global.Config.TargetDisplayFilter == 3 && ShaderChain_user != null && ShaderChain_user.Available)
            {
                selectedChain = ShaderChain_user;
            }

            EmuHawk.Filters.FinalPresentation fPresent = new EmuHawk.Filters.FinalPresentation(chain_outsize);
            EmuHawk.Filters.SourceImage       fInput   = new EmuHawk.Filters.SourceImage(chain_insize);
            EmuHawk.Filters.OSD fOSD = new EmuHawk.Filters.OSD();
            fOSD.RenderCallback = () =>
            {
                if (!includeOSD)
                {
                    return;
                }
                var size = fOSD.FindInput().SurfaceFormat.Size;
                Renderer.Begin(size.Width, size.Height);
                Renderer.SetBlendState(GL.BlendNormal);
                Renderer.End();
            };

            var chain = new FilterProgram();

            //add the first filter, encompassing output from the emulator core
            chain.AddFilter(fInput, "input");

            //if a non-zero padding is required, add a filter to allow for that
            //note, we have two sources of padding right now.. one can come from the videoprovider and one from the user.
            //we're combining these now and just using black, for sake of being lean, despite the discussion below:
            //keep in mind, the videoprovider design in principle might call for another color.
            //we havent really been using this very hard, but users will probably want black there (they could fill it to another color if needed tho)
            var padding = CalculateCompleteContentPadding(true, true);

            if (padding.Vertical != 0 || padding.Horizontal != 0)
            {
                //TODO - add another filter just for this, its cumbersome to use final presentation... I think. but maybe theres enough similarities to justify it.
                Size size = chain_insize;
                size.Width  += padding.Horizontal;
                size.Height += padding.Vertical;
                EmuHawk.Filters.FinalPresentation fPadding = new EmuHawk.Filters.FinalPresentation(size);
                chain.AddFilter(fPadding, "padding");
                fPadding.GuiRenderer    = Renderer;
                fPadding.GL             = GL;
                fPadding.Config_PadOnly = true;
                fPadding.Padding        = padding;
            }

            if (Global.Config.DispPrescale != 1)
            {
                EmuHawk.Filters.PrescaleFilter fPrescale = new EmuHawk.Filters.PrescaleFilter()
                {
                    Scale = Global.Config.DispPrescale
                };
                chain.AddFilter(fPrescale, "user_prescale");
            }

            //AutoPrescale makes no sense for a None final filter
            if (Global.Config.DispAutoPrescale && Global.Config.DispFinalFilter != (int)EmuHawk.Filters.FinalPresentation.eFilterOption.None)
            {
                var apf = new EmuHawk.Filters.AutoPrescaleFilter();
                chain.AddFilter(apf, "auto_prescale");
            }

            //choose final filter
            EmuHawk.Filters.FinalPresentation.eFilterOption finalFilter = EmuHawk.Filters.FinalPresentation.eFilterOption.None;
            fPresent.FilterOption = finalFilter;

            //add final presentation
            chain.AddFilter(fPresent, "presentation");

            return(chain);
        }
コード例 #7
0
        FilterProgram BuildDefaultChain(Size chainInSize, Size chainOutSize, bool includeOSD)
        {
            // select user special FX shader chain
            var selectedChainProperties = new Dictionary <string, object>();

            Filters.RetroShaderChain selectedChain = null;
            if (Global.Config.TargetDisplayFilter == 1 && ShaderChain_hq2x != null && ShaderChain_hq2x.Available)
            {
                selectedChain = ShaderChain_hq2x;
            }

            if (Global.Config.TargetDisplayFilter == 2 && ShaderChain_scanlines != null && ShaderChain_scanlines.Available)
            {
                selectedChain = ShaderChain_scanlines;
                selectedChainProperties["uIntensity"] = 1.0f - Global.Config.TargetScanlineFilterIntensity / 256.0f;
            }

            if (Global.Config.TargetDisplayFilter == 3 && ShaderChain_user != null && ShaderChain_user.Available)
            {
                selectedChain = ShaderChain_user;
            }

            var fPresent = new Filters.FinalPresentation(chainOutSize);
            var fInput   = new Filters.SourceImage(chainInSize);
            var fOSD     = new Filters.OSD();

            fOSD.RenderCallback = () =>
            {
                if (!includeOSD)
                {
                    return;
                }

                var size = fOSD.FindInput().SurfaceFormat.Size;
                Renderer.Begin(size.Width, size.Height);
                var myBlitter = new MyBlitter(this)
                {
                    ClipBounds = new Rectangle(0, 0, size.Width, size.Height)
                };
                Renderer.SetBlendState(GL.BlendNormal);
                GlobalWin.OSD.Begin(myBlitter);
                GlobalWin.OSD.DrawScreenInfo(myBlitter);
                GlobalWin.OSD.DrawMessages(myBlitter);
                Renderer.End();
            };

            var chain = new FilterProgram();

            //add the first filter, encompassing output from the emulator core
            chain.AddFilter(fInput, "input");

            // if a non-zero padding is required, add a filter to allow for that
            // note, we have two sources of padding right now.. one can come from the VideoProvider and one from the user.
            // we're combining these now and just using black, for sake of being lean, despite the discussion below:
            // keep in mind, the VideoProvider design in principle might call for another color.
            // we haven't really been using this very hard, but users will probably want black there (they could fill it to another color if needed tho)
            var padding = CalculateCompleteContentPadding(true, true);

            if (padding.Vertical != 0 || padding.Horizontal != 0)
            {
                // TODO - add another filter just for this, its cumbersome to use final presentation... I think. but maybe there's enough similarities to justify it.
                Size size = chainInSize;
                size.Width  += padding.Horizontal;
                size.Height += padding.Vertical;
                Filters.FinalPresentation fPadding = new Filters.FinalPresentation(size);
                chain.AddFilter(fPadding, "padding");
                fPadding.GuiRenderer    = Renderer;
                fPadding.GL             = GL;
                fPadding.Config_PadOnly = true;
                fPadding.Padding        = padding;
            }

            //add lua layer 'emu'
            AppendLuaLayer(chain, "emu");

            if (Global.Config.DispPrescale != 1)
            {
                var fPrescale = new Filters.PrescaleFilter()
                {
                    Scale = Global.Config.DispPrescale
                };
                chain.AddFilter(fPrescale, "user_prescale");
            }

            // add user-selected retro shader
            if (selectedChain != null)
            {
                AppendRetroShaderChain(chain, "retroShader", selectedChain, selectedChainProperties);
            }

            // AutoPrescale makes no sense for a None final filter
            if (Global.Config.DispAutoPrescale && Global.Config.DispFinalFilter != (int)Filters.FinalPresentation.eFilterOption.None)
            {
                var apf = new Filters.AutoPrescaleFilter();
                chain.AddFilter(apf, "auto_prescale");
            }

            //choose final filter
            var finalFilter = Filters.FinalPresentation.eFilterOption.None;

            if (Global.Config.DispFinalFilter == 1)
            {
                finalFilter = Filters.FinalPresentation.eFilterOption.Bilinear;
            }

            if (Global.Config.DispFinalFilter == 2)
            {
                finalFilter = Filters.FinalPresentation.eFilterOption.Bicubic;
            }

            //if bicubic is selected and unavailable, don't use it. use bilinear instead I guess
            if (finalFilter == Filters.FinalPresentation.eFilterOption.Bicubic)
            {
                if (ShaderChain_bicubic == null || !ShaderChain_bicubic.Available)
                {
                    finalFilter = Filters.FinalPresentation.eFilterOption.Bilinear;
                }
            }

            fPresent.FilterOption = finalFilter;

            // now if bicubic is chosen, insert it
            if (finalFilter == Filters.FinalPresentation.eFilterOption.Bicubic)
            {
                AppendRetroShaderChain(chain, "bicubic", ShaderChain_bicubic, null);
            }

            // add final presentation
            chain.AddFilter(fPresent, "presentation");

            //add lua layer 'native'
            AppendLuaLayer(chain, "native");

            // and OSD goes on top of that
            // TODO - things break if this isn't present (the final presentation filter gets messed up when used with prescaling)
            // so, always include it (we'll handle this flag in the callback to do no rendering)
            //if (includeOSD)
            chain.AddFilter(fOSD, "osd");

            return(chain);
        }
コード例 #8
0
        FilterProgram UpdateSourceInternal(JobInfo job)
        {
            _glManager.Activate(CR_GraphicsControl);

            IVideoProvider videoProvider = job.videoProvider;
            bool           simulate      = job.simulate;
            Size           chain_outsize = job.chain_outsize;

            int vw = videoProvider.BufferWidth;
            int vh = videoProvider.BufferHeight;

            if (Global.Config.DispFixAspectRatio)
            {
                if (Global.Config.DispManagerAR == Config.EDispManagerAR.System)
                {
                    vw = videoProvider.VirtualWidth;
                    vh = videoProvider.VirtualHeight;
                }
                if (Global.Config.DispManagerAR == Config.EDispManagerAR.Custom)
                {
                    vw = Global.Config.DispCustomUserARWidth;
                    vh = Global.Config.DispCustomUserARHeight;
                }
            }

            int[] videoBuffer = videoProvider.GetVideoBuffer();

            int  bufferWidth   = videoProvider.BufferWidth;
            int  bufferHeight  = videoProvider.BufferHeight;
            bool isGlTextureId = videoBuffer.Length == 1;

            //TODO - need to do some work here for GDI+ to repair gl texture ID importing
            BitmapBuffer bb           = null;
            Texture2d    videoTexture = null;

            if (!simulate)
            {
                if (isGlTextureId)
                {
                    videoTexture = GL.WrapGLTexture2d(new IntPtr(videoBuffer[0]), bufferWidth, bufferHeight);
                }
                else
                {
                    //wrap the videoprovider data in a BitmapBuffer (no point to refactoring that many IVideoProviders)
                    bb = new BitmapBuffer(bufferWidth, bufferHeight, videoBuffer);

                    //now, acquire the data sent from the videoProvider into a texture
                    videoTexture = VideoTextureFrugalizer.Get(bb);
                    GL.SetTextureWrapMode(videoTexture, true);
                }

                //TEST (to be removed once we have an actual example of bring in a texture ID from opengl emu core):
                //if (!isGlTextureId)
                //{
                //  videoBuffer = new int[1] { videoTexture.Id.ToInt32() };
                //  goto TESTEROO;
                //}
            }

            //record the size of what we received, since lua and stuff is gonna want to draw onto it
            currEmuWidth  = bufferWidth;
            currEmuHeight = bufferHeight;

            //build the default filter chain and set it up with services filters will need
            Size chain_insize = new Size(bufferWidth, bufferHeight);

            var filterProgram = BuildDefaultChain(chain_insize, chain_outsize, job.includeOSD);

            filterProgram.GuiRenderer = Renderer;
            filterProgram.GL          = GL;

            //setup the source image filter
            BizHawk.Client.EmuHawk.Filters.SourceImage fInput = filterProgram["input"] as BizHawk.Client.EmuHawk.Filters.SourceImage;
            fInput.Texture = videoTexture;

            //setup the final presentation filter
            BizHawk.Client.EmuHawk.Filters.FinalPresentation fPresent = filterProgram["presentation"] as BizHawk.Client.EmuHawk.Filters.FinalPresentation;
            fPresent.VirtualTextureSize = new Size(vw, vh);
            fPresent.TextureSize        = new Size(bufferWidth, bufferHeight);
            fPresent.BackgroundColor    = videoProvider.BackgroundColor;
            fPresent.GuiRenderer        = Renderer;
            fPresent.GL = GL;

            filterProgram.Compile("default", chain_insize, chain_outsize, !job.offscreen);

            if (simulate)
            {
            }
            else
            {
                CurrentFilterProgram = filterProgram;
                UpdateSourceDrawingWork(job);
            }

            //cleanup:
            if (bb != null)
            {
                bb.Dispose();
            }

            return(filterProgram);
        }
コード例 #9
0
        FilterProgram BuildDefaultChain(Size chain_insize, Size chain_outsize, bool includeOSD)
        {
            //select user special FX shader chain
            Dictionary <string, object> selectedChainProperties = new Dictionary <string, object>();

            Filters.RetroShaderChain selectedChain = null;
            if (Global.Config.TargetDisplayFilter == 1 && ShaderChain_hq2x != null && ShaderChain_hq2x.Available)
            {
                selectedChain = ShaderChain_hq2x;
            }
            if (Global.Config.TargetDisplayFilter == 2 && ShaderChain_scanlines != null && ShaderChain_scanlines.Available)
            {
                //shader.Pipeline["uIntensity"].Set(1.0f - Global.Config.TargetScanlineFilterIntensity / 256.0f);
                selectedChain = ShaderChain_scanlines;
                selectedChainProperties["uIntensity"] = 1.0f - Global.Config.TargetScanlineFilterIntensity / 256.0f;
            }
            if (Global.Config.TargetDisplayFilter == 3 && ShaderChain_user != null && ShaderChain_user.Available)
            {
                selectedChain = ShaderChain_user;
            }

            Filters.FinalPresentation fPresent = new Filters.FinalPresentation(chain_outsize);
            Filters.SourceImage       fInput   = new Filters.SourceImage(chain_insize);
            Filters.OSD fOSD = new Filters.OSD();
            fOSD.RenderCallback = () =>
            {
                if (!includeOSD)
                {
                    return;
                }
                var size = fOSD.FindInput().SurfaceFormat.Size;
                Renderer.Begin(size.Width, size.Height);
                MyBlitter myBlitter = new MyBlitter(this);
                myBlitter.ClipBounds = new Rectangle(0, 0, size.Width, size.Height);
                Renderer.SetBlendState(GL.BlendNormal);
                GlobalWin.OSD.Begin(myBlitter);
                GlobalWin.OSD.DrawScreenInfo(myBlitter);
                GlobalWin.OSD.DrawMessages(myBlitter);
                Renderer.End();
            };

            var chain = new FilterProgram();

            //add the first filter, encompassing output from the emulator core
            chain.AddFilter(fInput, "input");

            //add lua layer 'emu'
            AppendLuaLayer(chain, "emu");

            //add user-selected retro shader
            if (selectedChain != null)
            {
                AppendRetroShaderChain(chain, "retroShader", selectedChain, selectedChainProperties);
            }

            //choose final filter
            Filters.FinalPresentation.eFilterOption finalFilter = Filters.FinalPresentation.eFilterOption.None;
            if (Global.Config.DispFinalFilter == 1)
            {
                finalFilter = Filters.FinalPresentation.eFilterOption.Bilinear;
            }
            if (Global.Config.DispFinalFilter == 2)
            {
                finalFilter = Filters.FinalPresentation.eFilterOption.Bicubic;
            }
            //if bicubic is selected and unavailable, dont use it
            if (!ShaderChain_bicubic.Available && fPresent.FilterOption == Filters.FinalPresentation.eFilterOption.Bicubic)
            {
                finalFilter = Filters.FinalPresentation.eFilterOption.None;
            }
            fPresent.FilterOption = finalFilter;

            //now if bicubic is chosen, insert it
            if (finalFilter == Filters.FinalPresentation.eFilterOption.Bicubic)
            {
                AppendRetroShaderChain(chain, "bicubic", ShaderChain_bicubic, null);
            }

            //add final presentation
            chain.AddFilter(fPresent, "presentation");

            //add lua layer 'native'
            AppendLuaLayer(chain, "native");

            //and OSD goes on top of that
            //TODO - things break if this isnt present (the final presentation filter gets messed up)
            //so, always include it (we'll handle this flag in the callback to do no rendering)
            //if (includeOSD)
            chain.AddFilter(fOSD, "osd");

            return(chain);
        }
コード例 #10
0
 //initialization stuff
 public void BeginInitialization(FilterProgram program)
 {
     IOSurfaceInfos.Clear(); FilterProgram = program;
 }
コード例 #11
0
ファイル: Utils.cs プロジェクト: WolfpawGroup/RTC3
 public override void Run()
 {
     YieldOutput(FilterProgram.GetRenderTarget().Texture2d);
 }
コード例 #12
0
        private FilterProgram UpdateSourceInternal(JobInfo job)
        {
            //no drawing actually happens. it's important not to begin drawing on a control
            if (!job.Simulate && !job.Offscreen)
            {
                GLManager.Activate(CR_GraphicsControl);

                if (job.ChainOutsize.Width == 0 || job.ChainOutsize.Height == 0)
                {
                    // this has to be a NOP, because lots of stuff will malfunction on a 0-sized viewport
                    if (_currentFilterProgram != null)
                    {
                        UpdateSourceDrawingWork(job);                         //but we still need to do this, because of vsync
                    }

                    return(null);
                }
            }

            IVideoProvider videoProvider = job.VideoProvider;
            bool           simulate      = job.Simulate;
            Size           chainOutsize  = job.ChainOutsize;

            //simulate = true;

            int[] videoBuffer            = videoProvider.GetVideoBuffer();
            int   bufferWidth            = videoProvider.BufferWidth;
            int   bufferHeight           = videoProvider.BufferHeight;
            int   presenterTextureWidth  = bufferWidth;
            int   presenterTextureHeight = bufferHeight;
            bool  isGlTextureId          = videoBuffer.Length == 1;

            int vw = videoProvider.VirtualWidth;
            int vh = videoProvider.VirtualHeight;

            //TODO: it is bad that this is happening outside the filter chain
            //the filter chain has the ability to add padding...
            //for now, we have to have some hacks. this could be improved by refactoring the filter setup hacks to be in one place only though
            //could the PADDING be done as filters too? that would be nice.
            var fCoreScreenControl = CreateCoreScreenControl();

            if (fCoreScreenControl != null)
            {
                var sz = fCoreScreenControl.PresizeInput("default", new Size(bufferWidth, bufferHeight));
                presenterTextureWidth  = vw = sz.Width;
                presenterTextureHeight = vh = sz.Height;
            }

            if (Global.Config.DispFixAspectRatio)
            {
                if (Global.Config.DispManagerAR == EDispManagerAR.System)
                {
                    //Already set
                }
                if (Global.Config.DispManagerAR == EDispManagerAR.Custom)
                {
                    //not clear what any of these other options mean for "screen controlled" systems
                    vw = Global.Config.DispCustomUserARWidth;
                    vh = Global.Config.DispCustomUserARHeight;
                }
                if (Global.Config.DispManagerAR == EDispManagerAR.CustomRatio)
                {
                    //not clear what any of these other options mean for "screen controlled" systems
                    FixRatio(Global.Config.DispCustomUserArx, Global.Config.DispCustomUserAry, videoProvider.BufferWidth, videoProvider.BufferHeight, out vw, out vh);
                }
            }

            var padding = CalculateCompleteContentPadding(true, false);

            vw += padding.Horizontal;
            vh += padding.Vertical;

            BitmapBuffer bb           = null;
            Texture2d    videoTexture = null;

            if (!simulate)
            {
                if (isGlTextureId)
                {
                    //FYI: this is a million years from happening on n64, since it's all geriatric non-FBO code
                    //is it workable for saturn?
                    videoTexture = GL.WrapGLTexture2d(new IntPtr(videoBuffer[0]), bufferWidth, bufferHeight);
                }
                else
                {
                    //wrap the VideoProvider data in a BitmapBuffer (no point to refactoring that many IVideoProviders)
                    bb = new BitmapBuffer(bufferWidth, bufferHeight, videoBuffer);
                    bb.DiscardAlpha();

                    //now, acquire the data sent from the videoProvider into a texture
                    videoTexture = VideoTextureFrugalizer.Get(bb);

                    // lets not use this. lets define BizwareGL to make clamp by default (TBD: check opengl)
                    //GL.SetTextureWrapMode(videoTexture, true);
                }
            }

            // record the size of what we received, since lua and stuff is gonna want to draw onto it
            currEmuWidth  = bufferWidth;
            currEmuHeight = bufferHeight;

            //build the default filter chain and set it up with services filters will need
            Size chainInsize = new Size(bufferWidth, bufferHeight);

            var filterProgram = BuildDefaultChain(chainInsize, chainOutsize, job.IncludeOSD, job.IncludeUserFilters);

            filterProgram.GuiRenderer = Renderer;
            filterProgram.GL          = GL;

            //setup the source image filter
            Filters.SourceImage fInput = filterProgram["input"] as Filters.SourceImage;
            fInput.Texture = videoTexture;

            //setup the final presentation filter
            Filters.FinalPresentation fPresent = filterProgram["presentation"] as Filters.FinalPresentation;
            fPresent.VirtualTextureSize = new Size(vw, vh);
            fPresent.TextureSize        = new Size(presenterTextureWidth, presenterTextureHeight);
            fPresent.BackgroundColor    = videoProvider.BackgroundColor;
            fPresent.GuiRenderer        = Renderer;
            fPresent.Flip = isGlTextureId;
            fPresent.Config_FixAspectRatio  = Global.Config.DispFixAspectRatio;
            fPresent.Config_FixScaleInteger = Global.Config.DispFixScaleInteger;
            fPresent.Padding      = ClientExtraPadding;
            fPresent.AutoPrescale = Global.Config.DispAutoPrescale;

            fPresent.GL = GL;

            //POOPY. why are we delivering the GL context this way? such bad
            Filters.ScreenControlNDS fNDS = filterProgram["CoreScreenControl"] as Filters.ScreenControlNDS;
            if (fNDS != null)
            {
                fNDS.GuiRenderer = Renderer;
                fNDS.GL          = GL;
            }

            filterProgram.Compile("default", chainInsize, chainOutsize, !job.Offscreen);

            if (simulate)
            {
            }
            else
            {
                _currentFilterProgram = filterProgram;
                UpdateSourceDrawingWork(job);
            }

            // cleanup:
            bb?.Dispose();

            return(filterProgram);
        }