/// <summary> /// Bind a macro index to a position for the MME /// </summary> /// <param name="index">The macro index</param> /// <param name="data">The position of the macro</param> public void BindMacro(int index, int position) { _macros[index] = new CachedMacro(position); }
private void Call3dMethod(NvGpuVmm Vmm, GpuMethodCall MethCall) { if (MethCall.Method < 0x80) { switch ((NvGpuFifoMeth)MethCall.Method) { case NvGpuFifoMeth.SetMacroUploadAddress: { CurrMacroPosition = MethCall.Argument; break; } case NvGpuFifoMeth.SendMacroCodeData: { Mme[CurrMacroPosition++] = MethCall.Argument; break; } case NvGpuFifoMeth.SetMacroBindingIndex: { CurrMacroBindIndex = MethCall.Argument; break; } case NvGpuFifoMeth.BindMacro: { int Position = MethCall.Argument; Macros[CurrMacroBindIndex] = new CachedMacro(this, Gpu.Engine3d, Position); break; } default: CallP2mfMethod(Vmm, MethCall); break; } } else if (MethCall.Method < 0xe00) { Gpu.Engine3d.CallMethod(Vmm, MethCall); } else { int MacroIndex = (MethCall.Method >> 1) & MacroIndexMask; if ((MethCall.Method & 1) != 0) { Macros[MacroIndex].PushArgument(MethCall.Argument); } else { Macros[MacroIndex].StartExecution(MethCall.Argument); } if (MethCall.IsLastCall) { Macros[MacroIndex].Execute(Vmm, Mme); } } }
private void Call3dMethod(NvGpuVmm vmm, GpuMethodCall methCall) { if (methCall.Method < 0x80) { switch ((NvGpuFifoMeth)methCall.Method) { case NvGpuFifoMeth.SetMacroUploadAddress: { _currMacroPosition = methCall.Argument; break; } case NvGpuFifoMeth.SendMacroCodeData: { _mme[_currMacroPosition++] = methCall.Argument; break; } case NvGpuFifoMeth.SetMacroBindingIndex: { _currMacroBindIndex = methCall.Argument; break; } case NvGpuFifoMeth.BindMacro: { int position = methCall.Argument; _macros[_currMacroBindIndex++] = new CachedMacro(this, _gpu.Engine3d, position); break; } default: CallP2mfMethod(vmm, methCall); break; } } else if (methCall.Method < 0xe00) { _gpu.Engine3d.CallMethod(vmm, methCall); } else { int macroIndex = (methCall.Method >> 1) & MacroIndexMask; if ((methCall.Method & 1) != 0) { _macros[macroIndex].PushArgument(methCall.Argument); } else { _macros[macroIndex].StartExecution(methCall.Argument); } if (methCall.IsLastCall) { _macros[macroIndex].Execute(vmm, _mme); } } }
/// <summary> /// Calls a GPU method. /// </summary> /// <param name="meth">GPU method call parameters</param> public void CallMethod(MethodParams meth) { if ((NvGpuFifoMeth)meth.Method == NvGpuFifoMeth.BindChannel) { _subChannels[meth.SubChannel].Class = (ClassId)meth.Argument; } else if (meth.Method < 0x60) { switch ((NvGpuFifoMeth)meth.Method) { case NvGpuFifoMeth.WaitForIdle: { _context.Methods.PerformDeferredDraws(); _context.Renderer.Pipeline.Barrier(); break; } case NvGpuFifoMeth.SetMacroUploadAddress: { _currMacroPosition = meth.Argument; break; } case NvGpuFifoMeth.SendMacroCodeData: { _mme[_currMacroPosition++] = meth.Argument; break; } case NvGpuFifoMeth.SetMacroBindingIndex: { _currMacroBindIndex = meth.Argument; break; } case NvGpuFifoMeth.BindMacro: { int position = meth.Argument; _macros[_currMacroBindIndex++] = new CachedMacro(position); break; } } } else if (meth.Method < 0xe00) { _subChannels[meth.SubChannel].State.CallMethod(meth); } else { int macroIndex = (meth.Method >> 1) & MacroIndexMask; if ((meth.Method & 1) != 0) { _macros[macroIndex].PushArgument(meth.Argument); } else { _macros[macroIndex].StartExecution(meth.Argument); } if (meth.IsLastCall) { _macros[macroIndex].Execute(_mme, _subChannels[meth.SubChannel].State); _context.Methods.PerformDeferredDraws(); } } }
/// <summary> /// This method invokes the macros. It's very tolerant about calls /// it can't make, meaning that it absorbs the exceptions /// </summary> /// <param name="obj"></param> /// <param name="expression"></param> /// <returns></returns> private object InvokeMacro( object obj, string expression ) { int subexStartIndex = 0; int subexEndIndex = 0; object subexObject = obj; try { do { subexEndIndex = expression.IndexOfAny(new char[]{'.','(','['}, subexStartIndex); if ( subexEndIndex == -1 ) subexEndIndex=expression.Length; string subex = expression.Substring(subexStartIndex,subexEndIndex-subexStartIndex); int subexWithArgsEndIndex = expression.IndexOfAny(new char[]{'(','['}, subexStartIndex); string subexWithArgs; if ( subexWithArgsEndIndex != -1 ) subexWithArgs = expression.Substring(subexStartIndex); else subexWithArgs = subex; // build the cacheKey used for caching the macros: typename.macroname // obj can be null, so we should check for that // we use obj instead of subexObject to short-cut the loop string cacheKey = ( obj != null ? obj.GetType().FullName + "." : "" ) + subexWithArgs; CachedMacro subCached; if (!macros.TryGetValue(cacheKey, out subCached) || subCached == null) { lock(macrosLock) { subexStartIndex = subexEndIndex+1; MemberInfo memberToInvoke; MemberInfo[] members = subexObject.GetType().FindMembers( MemberTypes.Field|MemberTypes.Method|MemberTypes.Property, BindingFlags.IgnoreCase|BindingFlags.Instance|BindingFlags.Public, new MemberFilter(this.IsMemberEligibleForMacroCall), subex.Trim() ); string[] arglist=null; if ( members.Length == 0 ) { throw new MissingMemberException(subexObject.GetType().FullName,subex.Trim()); } if ( subexEndIndex<expression.Length && (expression[subexEndIndex] == '[' || expression[subexEndIndex] == '(') ) { arglist = SplitArgs(expression,subexEndIndex, ref subexStartIndex); } //SDH: We REALLY need to refactor this whole Clemens thing - it's getting hairy. memberToInvoke = null; if ( members.Length > 1 ) { foreach(MemberInfo potentialMember in members) { MethodInfo potentialMethod = potentialMember as MethodInfo; if(potentialMethod != null) { ParameterInfo[] parameters = potentialMethod.GetParameters(); if(parameters != null && parameters.Length > 0) { if(parameters.Length == arglist.Length) { memberToInvoke = potentialMember; break; } } } } } if(memberToInvoke == null)//Previous behavior, use the first one. { memberToInvoke = members[0]; } if ( memberToInvoke.MemberType == MemberTypes.Property && (subexEndIndex==expression.Length || expression[subexEndIndex] == '.' || expression[subexEndIndex] == '[' )) { PropertyInfo propInfo = memberToInvoke as PropertyInfo; if ( subexEndIndex<expression.Length && expression[subexEndIndex] == '[' ) { System.Reflection.ParameterInfo[] paramInfo = propInfo.GetIndexParameters(); if ( arglist.Length > paramInfo.Length ) { throw new InvalidOperationException(String.Format("Parameter list length mismatch {0}",memberToInvoke.Name)); } object[] oarglist = new object[paramInfo.Length]; for( int n=0;n<arglist.Length;n++) { oarglist[n] = Convert.ChangeType(arglist[n],paramInfo[n].ParameterType); } CachedMacro macro = new CachedMacro(propInfo,oarglist); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = propInfo.GetValue(subexObject,oarglist); } else { CachedMacro macro = new CachedMacro(propInfo,null); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = propInfo.GetValue(subexObject,null); } } else if ( memberToInvoke.MemberType == MemberTypes.Field && (subexEndIndex==expression.Length || expression[subexEndIndex] == '.')) { FieldInfo fieldInfo = memberToInvoke as FieldInfo; CachedMacro macro = new CachedMacro(fieldInfo); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = fieldInfo.GetValue(subexObject); } else if ( memberToInvoke.MemberType == MemberTypes.Method && subexEndIndex<expression.Length && expression[subexEndIndex] == '(' ) { MethodInfo methInfo = memberToInvoke as MethodInfo; System.Reflection.ParameterInfo[] paramInfo = methInfo.GetParameters(); if ( arglist.Length > paramInfo.Length && !(paramInfo.Length>0 && paramInfo[paramInfo.Length-1].ParameterType == typeof(string[]))) { throw new InvalidOperationException(String.Format("Parameter list length mismatch {0}",memberToInvoke.Name)); } object[] oarglist = new object[paramInfo.Length]; for( int n=0;n<arglist.Length;n++) { if ( n == paramInfo.Length-1 && arglist.Length>paramInfo.Length) { string[] paramsArg = new string[arglist.Length-paramInfo.Length+1]; for( int m=n;m<arglist.Length;m++) { paramsArg[m-n] = Convert.ChangeType(arglist[n],typeof(string)) as string; } oarglist[n] = paramsArg; break; } else { oarglist[n] = Convert.ChangeType(arglist[n],paramInfo[n].ParameterType); } } CachedMacro macro = new CachedMacro(methInfo,oarglist); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = methInfo.Invoke(subexObject,oarglist); } } } else { subexStartIndex = subexEndIndex+1; subexObject = subCached.Invoke(subexObject); if (subexObject is Control) { return subexObject; } } } while(subexEndIndex<expression.Length && subexStartIndex < expression.Length); return subexObject==null?new LiteralControl(""):subexObject; } catch( Exception exc ) { ErrorTrace.Trace(System.Diagnostics.TraceLevel.Error,exc); throw; } }
/// <summary> /// This method invokes the macros. It's very tolerant about calls /// it can't make, meaning that it absorbs the exceptions /// </summary> /// <param name="obj"></param> /// <param name="expression"></param> /// <returns></returns> private object InvokeMacro(object obj, string expression) { int subexStartIndex = 0; int subexEndIndex = 0; object subexObject = obj; try { do { subexEndIndex = expression.IndexOfAny(new char[] { '.', '(', '[' }, subexStartIndex); if (subexEndIndex == -1) { subexEndIndex = expression.Length; } string subex = expression.Substring(subexStartIndex, subexEndIndex - subexStartIndex); int subexWithArgsEndIndex = expression.IndexOfAny(new char[] { '(', '[' }, subexStartIndex); string subexWithArgs; if (subexWithArgsEndIndex != -1) { subexWithArgs = expression.Substring(subexStartIndex); } else { subexWithArgs = subex; } // build the cacheKey used for caching the macros: typename.macroname // obj can be null, so we should check for that // we use obj instead of subexObject to short-cut the loop string cacheKey = (obj != null ? obj.GetType().FullName + "." : "") + subexWithArgs; CachedMacro subCached; if (!macros.TryGetValue(cacheKey, out subCached) || subCached == null) { lock (macrosLock) { subexStartIndex = subexEndIndex + 1; MemberInfo memberToInvoke; MemberInfo[] members = subexObject.GetType().FindMembers( MemberTypes.Field | MemberTypes.Method | MemberTypes.Property, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public, new MemberFilter(this.IsMemberEligibleForMacroCall), subex.Trim()); string[] arglist = null; if (members.Length == 0) { throw new MissingMemberException(subexObject.GetType().FullName, subex.Trim()); } if (subexEndIndex < expression.Length && (expression[subexEndIndex] == '[' || expression[subexEndIndex] == '(')) { arglist = SplitArgs(expression, subexEndIndex, ref subexStartIndex); } //SDH: We REALLY need to refactor this whole Clemens thing - it's getting hairy. memberToInvoke = null; if (members.Length > 1) { foreach (MemberInfo potentialMember in members) { MethodInfo potentialMethod = potentialMember as MethodInfo; if (potentialMethod != null) { ParameterInfo[] parameters = potentialMethod.GetParameters(); if (parameters != null && parameters.Length > 0) { if (parameters.Length == arglist.Length) { memberToInvoke = potentialMember; break; } } } } } if (memberToInvoke == null) //Previous behavior, use the first one. { memberToInvoke = members[0]; } if (memberToInvoke.MemberType == MemberTypes.Property && (subexEndIndex == expression.Length || expression[subexEndIndex] == '.' || expression[subexEndIndex] == '[')) { PropertyInfo propInfo = memberToInvoke as PropertyInfo; if (subexEndIndex < expression.Length && expression[subexEndIndex] == '[') { System.Reflection.ParameterInfo[] paramInfo = propInfo.GetIndexParameters(); if (arglist.Length > paramInfo.Length) { throw new InvalidOperationException(String.Format("Parameter list length mismatch {0}", memberToInvoke.Name)); } object[] oarglist = new object[paramInfo.Length]; for (int n = 0; n < arglist.Length; n++) { oarglist[n] = Convert.ChangeType(arglist[n], paramInfo[n].ParameterType); } CachedMacro macro = new CachedMacro(propInfo, oarglist); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = propInfo.GetValue(subexObject,oarglist); } else { CachedMacro macro = new CachedMacro(propInfo, null); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = propInfo.GetValue(subexObject,null); } } else if (memberToInvoke.MemberType == MemberTypes.Field && (subexEndIndex == expression.Length || expression[subexEndIndex] == '.')) { FieldInfo fieldInfo = memberToInvoke as FieldInfo; CachedMacro macro = new CachedMacro(fieldInfo); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = fieldInfo.GetValue(subexObject); } else if (memberToInvoke.MemberType == MemberTypes.Method && subexEndIndex < expression.Length && expression[subexEndIndex] == '(') { MethodInfo methInfo = memberToInvoke as MethodInfo; System.Reflection.ParameterInfo[] paramInfo = methInfo.GetParameters(); if (arglist.Length > paramInfo.Length && !(paramInfo.Length > 0 && paramInfo[paramInfo.Length - 1].ParameterType == typeof(string[]))) { throw new InvalidOperationException(String.Format("Parameter list length mismatch {0}", memberToInvoke.Name)); } object[] oarglist = new object[paramInfo.Length]; for (int n = 0; n < arglist.Length; n++) { if (n == paramInfo.Length - 1 && arglist.Length > paramInfo.Length) { string[] paramsArg = new string[arglist.Length - paramInfo.Length + 1]; for (int m = n; m < arglist.Length; m++) { paramsArg[m - n] = Convert.ChangeType(arglist[n], typeof(string)) as string; } oarglist[n] = paramsArg; break; } else { oarglist[n] = Convert.ChangeType(arglist[n], paramInfo[n].ParameterType); } } CachedMacro macro = new CachedMacro(methInfo, oarglist); macros[cacheKey] = macro; subexObject = macro.Invoke(subexObject); //subexObject = methInfo.Invoke(subexObject,oarglist); } } } else { subexStartIndex = subexEndIndex + 1; subexObject = subCached.Invoke(subexObject); if (subexObject is Control) { return(subexObject); } } }while(subexEndIndex < expression.Length && subexStartIndex < expression.Length); return(subexObject == null?new LiteralControl(""):subexObject); } catch (Exception exc) { ErrorTrace.Trace(System.Diagnostics.TraceLevel.Error, exc); throw; } }