source: trunk/Packages/Graphics32/GR32_Bindings.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 6.7 KB
Line 
1unit GR32_Bindings;
2
3(* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1 or LGPL 2.1 with linking exception
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * Alternatively, the contents of this file may be used under the terms of the
17 * Free Pascal modified version of the GNU Lesser General Public License
18 * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
19 * of this license are applicable instead of those above.
20 * Please see the file LICENSE.txt for additional information concerning this
21 * license.
22 *
23 * The Original Code is Run-time Function Bindings for Graphics32
24 *
25 * The Initial Developer of the Original Code is
26 * Mattias Andersson
27 * mattias@centaurix.com
28 *
29 * Portions created by the Initial Developer are Copyright (C) 2005-2010
30 * the Initial Developer. All Rights Reserved.
31 *
32 * Contributor(s):
33 *
34 * ***** END LICENSE BLOCK ***** *)
35
36interface
37
38{$I GR32.inc}
39
40uses
41 Classes, GR32_System;
42
43type
44 TFunctionName = type string;
45 TFunctionID = type Integer;
46
47 PFunctionInfo = ^TFunctionInfo;
48 TFunctionInfo = record
49 FunctionID: Integer;
50 Proc: Pointer;
51 CPUFeatures: TCPUFeatures;
52 Flags: Integer;
53 end;
54
55 TFunctionPriority = function (Info: PFunctionInfo): Integer;
56
57 PFunctionBinding = ^TFunctionBinding;
58 TFunctionBinding = record
59 FunctionID: Integer;
60 BindVariable: PPointer;
61 end;
62
63 { TFunctionRegistry }
64 { This class fascilitates a registry that allows multiple function to be
65 registered together with information about their CPU requirements and
66 an additional 'flags' parameter. Functions that share the same FunctionID
67 can be assigned to a function variable through the rebind methods.
68 A priority callback function is used to assess the most optimal function. }
69 TFunctionRegistry = class(TPersistent)
70 private
71 FItems: TList;
72 FBindings: TList;
73 FName: string;
74 procedure SetName(const Value: string);
75 function GetItems(Index: Integer): PFunctionInfo;
76 procedure SetItems(Index: Integer; const Value: PFunctionInfo);
77 public
78 constructor Create; virtual;
79 destructor Destroy; override;
80 procedure Clear;
81
82 procedure Add(FunctionID: Integer; Proc: Pointer; CPUFeatures: TCPUFeatures = [];
83 Flags: Integer = 0);
84
85 // function rebinding support
86 procedure RegisterBinding(FunctionID: Integer; BindVariable: PPointer);
87 procedure RebindAll(PriorityCallback: TFunctionPriority = nil);
88 procedure Rebind(FunctionID: Integer; PriorityCallback: TFunctionPriority = nil);
89
90 function FindFunction(FunctionID: Integer; PriorityCallback: TFunctionPriority = nil): Pointer;
91 property Items[Index: Integer]: PFunctionInfo read GetItems write SetItems;
92 published
93 property Name: string read FName write SetName;
94 end;
95
96function NewRegistry(const Name: string = ''): TFunctionRegistry;
97
98function DefaultPriorityProc(Info: PFunctionInfo): Integer;
99
100var
101 DefaultPriority: TFunctionPriority = DefaultPriorityProc;
102
103const
104 INVALID_PRIORITY: Integer = MaxInt;
105
106implementation
107
108uses
109 Math;
110
111var
112 Registers: TList;
113
114function NewRegistry(const Name: string): TFunctionRegistry;
115begin
116 if Registers = nil then
117 Registers := TList.Create;
118 Result := TFunctionRegistry.Create;
119 {$IFDEF NEXTGEN}
120 Result.__ObjAddRef;
121 {$ENDIF}
122 Result.Name := Name;
123 Registers.Add(Result);
124end;
125
126function DefaultPriorityProc(Info: PFunctionInfo): Integer;
127begin
128 Result := IfThen(Info^.CPUFeatures <= GR32_System.CPUFeatures, 0, INVALID_PRIORITY);
129end;
130
131{ TFunctionRegistry }
132
133procedure TFunctionRegistry.Add(FunctionID: Integer; Proc: Pointer;
134 CPUFeatures: TCPUFeatures; Flags: Integer);
135var
136 Info: PFunctionInfo;
137begin
138 New(Info);
139 Info^.FunctionID := FunctionID;
140 Info^.Proc := Proc;
141 Info^.CPUFeatures := CPUFeatures;
142 Info^.Flags := Flags;
143 FItems.Add(Info);
144end;
145
146procedure TFunctionRegistry.Clear;
147var
148 I: Integer;
149begin
150 for I := 0 to FItems.Count - 1 do
151 Dispose(PFunctionInfo(FItems[I]));
152 FItems.Clear;
153 for I := 0 to FBindings.Count - 1 do
154 Dispose(PFunctionBinding(FBindings[I]));
155 FBindings.Clear;
156end;
157
158constructor TFunctionRegistry.Create;
159begin
160 FItems := TList.Create;
161 FBindings := TList.Create;
162end;
163
164destructor TFunctionRegistry.Destroy;
165begin
166 Clear;
167 FItems.Free;
168 FBindings.Free;
169 inherited;
170end;
171
172function TFunctionRegistry.FindFunction(FunctionID: Integer;
173 PriorityCallback: TFunctionPriority): Pointer;
174var
175 I, MinPriority, P: Integer;
176 Info: PFunctionInfo;
177begin
178 if not Assigned(PriorityCallback) then PriorityCallback := DefaultPriority;
179 Result := nil;
180 MinPriority := INVALID_PRIORITY;
181 for I := FItems.Count - 1 downto 0 do
182 begin
183 Info := FItems[I];
184 if (Info^.FunctionID = FunctionID) then
185 begin
186 P := PriorityCallback(Info);
187 if P < MinPriority then
188 begin
189 Result := Info^.Proc;
190 MinPriority := P;
191 end;
192 end;
193 end;
194end;
195
196function TFunctionRegistry.GetItems(Index: Integer): PFunctionInfo;
197begin
198 Result := FItems[Index];
199end;
200
201procedure TFunctionRegistry.Rebind(FunctionID: Integer;
202 PriorityCallback: TFunctionPriority);
203var
204 P: PFunctionBinding;
205 I: Integer;
206begin
207 for I := 0 to FBindings.Count - 1 do
208 begin
209 P := PFunctionBinding(FBindings[I]);
210 if P^.FunctionID = FunctionID then
211 P^.BindVariable^ := FindFunction(FunctionID, PriorityCallback);
212 end;
213end;
214
215procedure TFunctionRegistry.RebindAll(PriorityCallback: TFunctionPriority);
216var
217 I: Integer;
218 P: PFunctionBinding;
219begin
220 for I := 0 to FBindings.Count - 1 do
221 begin
222 P := PFunctionBinding(FBindings[I]);
223 P^.BindVariable^ := FindFunction(P^.FunctionID, PriorityCallback);
224 end;
225end;
226
227procedure TFunctionRegistry.RegisterBinding(FunctionID: Integer;
228 BindVariable: PPointer);
229var
230 Binding: PFunctionBinding;
231begin
232 New(Binding);
233 Binding^.FunctionID := FunctionID;
234 Binding^.BindVariable := BindVariable;
235 FBindings.Add(Binding);
236end;
237
238procedure TFunctionRegistry.SetItems(Index: Integer;
239 const Value: PFunctionInfo);
240begin
241 FItems[Index] := Value;
242end;
243
244procedure TFunctionRegistry.SetName(const Value: string);
245begin
246 FName := Value;
247end;
248
249procedure FreeRegisters;
250var
251 I: Integer;
252begin
253 if Assigned(Registers) then
254 begin
255 for I := Registers.Count - 1 downto 0 do
256 TFunctionRegistry(Registers[I]).Free;
257 Registers.Free;
258 Registers := nil;
259 end;
260end;
261
262initialization
263
264finalization
265 FreeRegisters;
266
267end.
Note: See TracBrowser for help on using the repository browser.