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); }
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); }