From: Ronald H. <ron...@us...> - 2005-09-11 10:21:08
|
Update of /cvsroot/apophysis/2.10/Source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27792/Source Modified Files: ControlPoint.pas Render32.pas Render64MT.pas RenderMM.pas RenderThread.pas Added Files: BucketFillerThread.pas RenderMM_MT.pas Log Message: Multithread rendering Index: ControlPoint.pas =================================================================== RCS file: /cvsroot/apophysis/2.10/Source/ControlPoint.pas,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** ControlPoint.pas 3 Sep 2005 11:23:37 -0000 1.8 --- ControlPoint.pas 11 Sep 2005 10:20:56 -0000 1.9 *************** *** 22,26 **** uses ! Classes, Windows, Cmap, Xform; const --- 22,26 ---- uses ! Classes, Windows, Cmap, Xform, XFormMan; const *************** *** 31,34 **** --- 31,35 ---- FILTER_CUTOFF = 1.8; BRIGHT_ADJUST = 2.3; + FUSE = 15; type *************** *** 132,135 **** --- 133,137 ---- function add_symmetry_to_control_point(var cp: TControlPoint; sym: integer): integer; function CalcUPRMagn(const cp: TControlPoint): double; + procedure FillVarDisturb; implementation *************** *** 140,145 **** var ! var_distrib: array[0..NRVISVAR + 18] of integer; ! mixed_var_distrib: array[0..NRVISVAR + 8] of integer; { TControlPoint } --- 142,147 ---- var ! var_distrib: array of integer; ! mixed_var_distrib: array of integer; { TControlPoint } *************** *** 243,246 **** --- 245,249 ---- px, py, pc: double; dx, dy, tx, ty: double; + nx, ny: double; r: double; s, v, a: double; *************** *** 253,257 **** PreparePropTable; ! for i := -100 to NrPoints - 1 do begin with xform[PropTable[Random(1024)]] do begin --- 256,260 ---- PreparePropTable; ! for i := -FUSE to NrPoints - 1 do begin with xform[PropTable[Random(1024)]] do begin *************** *** 482,499 **** xform[i].prepare; ! for i := -100 to NrPoints - 1 do begin ! try xform[PropTable[Random(1024)]].NextPointXY(px,py); - except - on EMathError do begin - exit; - end; - end; - // store points - if i >= 0 then begin CurrentPoint := @Points[i]; CurrentPoint.X := px; CurrentPoint.Y := py; end end; end; --- 485,502 ---- xform[i].prepare; ! try ! for i := 0 to FUSE do ! xform[PropTable[Random(1024)]].NextPointXY(px,py); ! ! for i := 0 to NrPoints - 1 do begin xform[PropTable[Random(1024)]].NextPointXY(px,py); CurrentPoint := @Points[i]; CurrentPoint.X := px; CurrentPoint.Y := py; end + except + on EMathError do begin + exit; + end; end; end; *************** *** 515,528 **** xform[i].prepare; ! for i := -100 to NrPoints - 1 do begin ! try xform[PropTable[Random(1024)]].NextPoint(px,py,pc); - except - on EMathError do begin - exit; - end; - end; - // store points - if i >= 0 then begin CurrentPoint := @Points[i]; CurrentPoint.X := px; --- 518,527 ---- xform[i].prepare; ! try ! for i := 0 to FUSE do ! xform[PropTable[Random(1024)]].NextPoint(px,py,pc); ! ! for i := 0 to NrPoints - 1 do begin xform[PropTable[Random(1024)]].NextPoint(px,py,pc); CurrentPoint := @Points[i]; CurrentPoint.X := px; *************** *** 530,533 **** --- 529,536 ---- CurrentPoint.C := pc; end + except + on EMathError do begin + exit; + end; end; end; *************** *** 596,615 **** xform[i].prepare; ! for i := -100 to NrPoints - 1 do begin ! try xform[PropTable[Random(1024)]].NextPoint2C(px, py, pc1, pc2); - except - on EMathError do begin - exit; - end; - end; - // store points - if i >= 0 then begin CurrentPoint := @Points[i]; ! CurrentPoint.X := px; ! CurrentPoint.Y := py; CurrentPoint.C1 := pc1; CurrentPoint.C2 := pc2; end end; end; --- 599,618 ---- xform[i].prepare; ! try ! for i := 0 to FUSE do ! xform[PropTable[Random(1024)]].NextPoint2C(px, py, pc1, pc2); ! ! for i := 0 to NrPoints - 1 do begin xform[PropTable[Random(1024)]].NextPoint2C(px, py, pc1, pc2); CurrentPoint := @Points[i]; ! CurrentPoint.X := px; ! CurrentPoint.Y := py; CurrentPoint.C1 := pc1; CurrentPoint.C2 := pc2; end + except + on EMathError do begin + exit; + end; end; end; *************** *** 636,652 **** xform[i].prepare; ! for i := -100 to NrPoints - 1 do begin ! try xform[PropTable[Random(1024)]].NextPointXY(px,py); ! if i >= 0 then begin ! CurrentPoint := @Points[i]; ! CurrentPoint.X := px; ! CurrentPoint.Y := py; ! end ! except ! on EMathError do begin ! Result := True; ! Exit; ! end; end; end; --- 639,656 ---- xform[i].prepare; ! try ! for i := 0 to FUSE do xform[PropTable[Random(1024)]].NextPointXY(px,py); ! ! for i := 0 to NrPoints - 1 do begin ! xform[PropTable[Random(1024)]].NextPointXY(px,py); ! CurrentPoint := @Points[i]; ! CurrentPoint.X := px; ! CurrentPoint.Y := py; ! end; ! except ! on EMathError do begin ! Result := True; ! Exit; end; end; *************** *** 859,864 **** VarPossible: boolean; begin VarPossible := false; ! for j := 0 to NRVISVAR - 1 do begin VarPossible := VarPossible or Variations[j]; end; --- 863,869 ---- VarPossible: boolean; begin + FillVarDisturb; VarPossible := false; ! for j := 0 to NRVAR - 1 do begin VarPossible := VarPossible or Variations[j]; end; *************** *** 914,919 **** nrXforms := random(Max - (Min - 1)) + Min; VarPossible := false; ! for j := 0 to NRVISVAR - 1 do begin VarPossible := VarPossible or Variations[j]; end; --- 919,925 ---- nrXforms := random(Max - (Min - 1)) + Min; + FillVarDisturb; VarPossible := false; ! for j := 0 to NRVAR - 1 do begin VarPossible := VarPossible or Variations[j]; end; *************** *** 1467,1470 **** --- 1473,1477 ---- function TControlPoint.Clone: TControlPoint; var + i: integer; sl: TStringList; begin *************** *** 1478,1481 **** --- 1485,1492 ---- Result.nick := nick; Result.url := url; + + for i := 0 to NXFORMS - 1 do + Result.xform[i].assign(xform[i]); + sl.Free; end; *************** *** 1483,1486 **** --- 1494,1498 ---- procedure TControlPoint.Copy(cp1: TControlPoint); var + i: integer; sl: TStringList; begin *************** *** 1494,1497 **** --- 1506,1513 ---- nick := cp1.nick; url := cp1.url; + + for i := 0 to NXFORMS - 1 do + xform[i].assign(cp1.xform[i]); + sl.Free; end; *************** *** 1717,1720 **** --- 1733,1751 ---- /////////////////////////////////////////////////////////////////////////////// + function TControlPoint.getppux: double; + begin + result := pixels_per_unit * power(2, zoom) + end; + + /////////////////////////////////////////////////////////////////////////////// + function TControlPoint.getppuy: double; + begin + result := pixels_per_unit * power(2, zoom) + end; + + /////////////////////////////////////////////////////////////////////////////// + var + vdfilled: boolean = False; + procedure FillVarDisturb; const *************** *** 1724,1727 **** --- 1755,1764 ---- i: integer; begin + if vdfilled then + Exit; + + setlength(var_distrib, NRVAR + 19); + setlength(mixed_var_distrib, NRVAR + 9); + for i := 0 to High(startvar_distrib) do var_distrib[i] := startvar_distrib[i]; *************** *** 1735,1755 **** for i := High(startmixed_var_distrib) + 1 to high(mixed_var_distrib) do mixed_var_distrib[i] := 8 + i - High(startmixed_var_distrib) - 1; - end; - - /////////////////////////////////////////////////////////////////////////////// - function TControlPoint.getppux: double; - begin - result := pixels_per_unit * power(2, zoom) - end; ! /////////////////////////////////////////////////////////////////////////////// ! function TControlPoint.getppuy: double; ! begin ! result := pixels_per_unit * power(2, zoom) end; /////////////////////////////////////////////////////////////////////////////// - initialization - FillVarDisturb end. --- 1772,1780 ---- for i := High(startmixed_var_distrib) + 1 to high(mixed_var_distrib) do mixed_var_distrib[i] := 8 + i - High(startmixed_var_distrib) - 1; ! vdfilled := true; end; /////////////////////////////////////////////////////////////////////////////// end. --- NEW FILE: BucketFillerThread.pas --- unit BucketFillerThread; interface uses Classes, Windows, Controlpoint,Render; type TBucketFillerThread = class(TThread) private fcp: TControlPoint; points: TPointsArray; public nrbatches: integer; batchcounter: Pinteger; BucketWidth: Int64; BucketHeight: Int64; bounds: array[0..3] of extended; size: array[0..1] of extended; RotationCenter: array[0..1] of extended; Buckets: PBucketArray; ColorMap: TColorMapArray; CriticalSection: TRTLCriticalSection; constructor Create(cp: TControlPoint); destructor Destroy; override; procedure Execute; override; procedure AddPointsToBuckets(const points: TPointsArray); overload; procedure AddPointsToBucketsAngle(const points: TPointsArray); overload; end; implementation { PixelRenderThread } /////////////////////////////////////////////////////////////////////////////// procedure TBucketFillerThread.AddPointsToBuckets(const points: TPointsArray); var i: integer; px, py: double; bws, bhs: double; bx, by: double; wx, wy: double; Bucket: PBucket; MapColor: PColorMapColor; begin bws := (BucketWidth - 0.5) * size[0]; bhs := (BucketHeight - 0.5) * size[1]; bx := bounds[0]; by := bounds[1]; wx := bounds[2] - bounds[0]; wy := bounds[3] - bounds[1]; for i := SUB_BATCH_SIZE - 1 downto 0 do begin px := points[i].x - bx; py := points[i].y - by; if ((px < 0) or (px > wx) or (py < 0) or (py > wy)) then continue; MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @TbucketArray(buckets^)[Round(bws * px) + Round(bhs * py) * BucketWidth]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); Inc(Bucket.Blue, MapColor.Blue); Inc(Bucket.Count); end; end; /////////////////////////////////////////////////////////////////////////////// procedure TBucketFillerThread.AddPointsToBucketsAngle(const points: TPointsArray); var i: integer; px, py: double; ca,sa: double; nx, ny: double; bws, bhs: double; bx, by: double; wx, wy: double; Bucket: PBucket; MapColor: PColorMapColor; begin bws := (BucketWidth - 0.5) * size[0]; bhs := (BucketHeight - 0.5) * size[1]; bx := bounds[0]; by := bounds[1]; wx := bounds[2] - bounds[0]; wy := bounds[3] - bounds[1]; ca := cos(FCP.FAngle); sa := sin(FCP.FAngle); for i := SUB_BATCH_SIZE - 1 downto 0 do begin px := points[i].x - RotationCenter[0]; py := points[i].y - RotationCenter[1]; nx := px * ca + py * sa; ny := -px * sa + py * ca; px := nx + FCP.Center[0] - bx; py := ny + FCP.Center[1] - by; if ((px < 0) or (px > wx) or (py < 0) or (py > wy)) then continue; MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @TbucketArray(buckets^)[Round(bws * px) + Round(bhs * py) * BucketWidth]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); Inc(Bucket.Blue, MapColor.Blue); Inc(Bucket.Count); end; end; /////////////////////////////////////////////////////////////////////////////// constructor TBucketFillerThread.Create(cp: TControlPoint); begin inherited Create(True); Self.FreeOnTerminate := True; Fcp := cp.Clone; SetLength(Points, SUB_BATCH_SIZE); end; /////////////////////////////////////////////////////////////////////////////// destructor TBucketFillerThread.Destroy; begin FCP.Free; inherited; end; /////////////////////////////////////////////////////////////////////////////// procedure TBucketFillerThread.Execute; var bc: integer; begin inherited; bc := 0; while (not Terminated) and (bc < Nrbatches) do begin fcp.iterateXYC(SUB_BATCH_SIZE, points); try EnterCriticalSection(CriticalSection); if FCP.FAngle = 0 then AddPointsToBuckets(Points) else AddPointsToBucketsAngle(Points); Inc(batchcounter^); bc := batchcounter^ finally LeaveCriticalSection(CriticalSection); end; end; end; /////////////////////////////////////////////////////////////////////////////// end. Index: Render64MT.pas =================================================================== RCS file: /cvsroot/apophysis/2.10/Source/Render64MT.pas,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Render64MT.pas 3 Sep 2005 11:25:44 -0000 1.1 --- Render64MT.pas 11 Sep 2005 10:20:56 -0000 1.2 *************** *** 23,52 **** uses Windows, Classes, Graphics, ! Render, Controlpoint, ImageMaker; ! ! type ! TPixelRenderThread = class(TThread) ! private ! fcp: TControlPoint; ! points: TPointsArray; ! public ! nrbatches: integer; ! batchcounter: Pinteger; ! ! BucketWidth: Int64; ! BucketHeight: Int64; ! bounds: array[0..3] of extended; ! size: array[0..1] of extended; ! Buckets: PBucketArray; ! ColorMap: TColorMapArray; ! CriticalSection: TRTLCriticalSection; ! ! constructor Create(cp: TControlPoint); ! ! procedure Execute; override; ! ! procedure AddPointsToBuckets(const points: TPointsArray); overload; ! procedure AddPointsToBucketsAngle(const points: TPointsArray); overload; ! end; type --- 23,27 ---- uses Windows, Classes, Graphics, ! Render, Controlpoint, ImageMaker, BucketFillerthread; type *************** *** 55,59 **** oversample: Int64; batchcounter: Integer; ! FNrBatches: Integer; BucketWidth: Int64; --- 30,34 ---- oversample: Int64; batchcounter: Integer; ! FNrBatches: Int64; BucketWidth: Int64; *************** *** 72,76 **** ppux, ppuy: extended; FNrOfTreads: integer; ! WorkingThreads: array of TPixelRenderThread; CriticalSection: TRTLCriticalSection; --- 47,51 ---- ppux, ppuy: extended; FNrOfTreads: integer; ! WorkingThreads: array of TBucketFillerThread; CriticalSection: TRTLCriticalSection; *************** *** 88,92 **** procedure SetNrOfTreads(const Value: integer); ! function NewThread: TPixelRenderThread; public constructor Create; override; --- 63,67 ---- procedure SetNrOfTreads(const Value: integer); ! function NewThread: TBucketFillerThread; public constructor Create; override; *************** *** 240,243 **** --- 215,219 ---- i: integer; nsamples: Int64; + bc : integer; begin nsamples := Round(sample_density * bucketSize / (oversample * oversample)); *************** *** 252,262 **** WorkingThreads[i] := NewThread; ! while (Not FStop) and (batchcounter < FNrBatches) do begin ! if batchcounter > 0 then ! Progress(batchcounter / FNrBatches) ! else ! Progress(0); ! sleep(200) end; --- 228,248 ---- WorkingThreads[i] := NewThread; ! for i := 0 to NrOfTreads - 1 do ! WorkingThreads[i].Resume; ! bc := 0; ! while (Not FStop) and (bc < FNrBatches) do begin ! sleep(200); ! try ! EnterCriticalSection(CriticalSection); ! if batchcounter > 0 then ! Progress(batchcounter / FNrBatches) ! else ! Progress(0); ! ! bc := batchcounter; ! finally ! LeaveCriticalSection(CriticalSection); ! end; end; *************** *** 326,335 **** /////////////////////////////////////////////////////////////////////////////// ! function TRenderer64MT.NewThread: TPixelRenderThread; begin ! Result := TPixelRenderThread.Create(fcp); ! // Result.OnTerminate := OnThreadTerminated; Result.BucketWidth := BucketWidth; Result.BucketHeight := BucketHeight; Result.size[0] := size[0]; Result.size[1] := size[1]; --- 312,321 ---- /////////////////////////////////////////////////////////////////////////////// ! function TRenderer64MT.NewThread: TBucketFillerThread; begin ! Result := TBucketFillerThread.Create(fcp); Result.BucketWidth := BucketWidth; Result.BucketHeight := BucketHeight; + Result.Buckets := @Buckets; Result.size[0] := size[0]; Result.size[1] := size[1]; *************** *** 338,469 **** Result.bounds[2] := Bounds[2]; Result.bounds[3] := Bounds[3]; Result.ColorMap := colorMap; - Result.Buckets := @Buckets; Result.CriticalSection := CriticalSection; Result.Nrbatches := FNrBatches; Result.batchcounter := @batchcounter; ! Result.Resume; ! end; ! ! { PixelRenderThread } ! ! /////////////////////////////////////////////////////////////////////////////// ! procedure TPixelRenderThread.AddPointsToBuckets(const points: TPointsArray); ! var ! i: integer; ! px, py: double; ! bws, bhs: double; ! bx, by: double; ! wx, wy: double; ! // R: double; ! // V1, v2, v3: integer; ! Bucket: PBucket; ! MapColor: PColorMapColor; ! begin ! bws := (BucketWidth - 0.5) * size[0]; ! bhs := (BucketHeight - 0.5) * size[1]; ! bx := bounds[0]; ! by := bounds[1]; ! wx := bounds[2] - bounds[0]; ! wy := bounds[3] - bounds[1]; ! ! for i := SUB_BATCH_SIZE - 1 downto 0 do begin ! px := points[i].x - bx; ! py := points[i].y - by; ! ! if ((px < 0) or (px > wx) or ! (py < 0) or (py > wy)) then ! continue; ! ! MapColor := @ColorMap[Round(points[i].c * 255)]; ! Bucket := @TbucketArray(buckets^)[Round(bws * px) + Round(bhs * py) * BucketWidth]; ! ! Inc(Bucket.Red, MapColor.Red); ! Inc(Bucket.Green, MapColor.Green); ! Inc(Bucket.Blue, MapColor.Blue); ! Inc(Bucket.Count); ! end; ! end; ! ! /////////////////////////////////////////////////////////////////////////////// ! procedure TPixelRenderThread.AddPointsToBucketsAngle(const points: TPointsArray); ! var ! i: integer; ! px, py: double; ! ca,sa: double; ! nx, ny: double; ! bws, bhs: double; ! bx, by: double; ! wx, wy: double; ! Bucket: PBucket; ! MapColor: PColorMapColor; ! begin ! ! bws := (BucketWidth - 0.5) * size[0]; ! bhs := (BucketHeight - 0.5) * size[1]; ! bx := bounds[0]; ! by := bounds[1]; ! wx := bounds[2] - bounds[0]; ! wy := bounds[3] - bounds[1]; ! ! ca := cos(FCP.FAngle); ! sa := sin(FCP.FAngle); ! ! for i := SUB_BATCH_SIZE - 1 downto 0 do begin ! px := points[i].x - FCP.Center[0]; ! py := points[i].y - FCP.Center[1]; ! ! nx := px * ca + py * sa; ! ny := -px * sa + py * ca; ! ! px := nx + FCP.Center[0] - bx; ! py := ny + FCP.Center[1] - by; ! ! if ((px < 0) or (px > wx) or ! (py < 0) or (py > wy)) then ! continue; ! ! MapColor := @ColorMap[Round(points[i].c * 255)]; ! Bucket := @TbucketArray(buckets^)[Round(bws * px) + Round(bhs * py) * BucketWidth]; ! ! Inc(Bucket.Red, MapColor.Red); ! Inc(Bucket.Green, MapColor.Green); ! Inc(Bucket.Blue, MapColor.Blue); ! Inc(Bucket.Count); ! end; ! end; ! ! /////////////////////////////////////////////////////////////////////////////// ! constructor TPixelRenderThread.Create(cp: TControlPoint); ! begin ! inherited Create(True); ! Self.FreeOnTerminate := True; ! ! fcp := cp; ! ! SetLength(Points, SUB_BATCH_SIZE); ! end; ! ! /////////////////////////////////////////////////////////////////////////////// ! procedure TPixelRenderThread.Execute; ! begin ! inherited; ! ! // while true do begin ! while (not Terminated) and (batchcounter^ < Nrbatches) do begin ! fcp.iterateXYC(SUB_BATCH_SIZE, points); ! try ! EnterCriticalSection(CriticalSection); ! ! if FCP.FAngle = 0 then ! AddPointsToBuckets(Points) ! else ! AddPointsToBucketsAngle(Points); ! ! Inc(batchcounter^); ! finally ! LeaveCriticalSection(CriticalSection); ! end; ! end; end; --- 324,334 ---- Result.bounds[2] := Bounds[2]; Result.bounds[3] := Bounds[3]; + Result.RotationCenter[0] := FCP.Center[0]; + Result.RotationCenter[1] := FCP.Center[1]; Result.ColorMap := colorMap; Result.CriticalSection := CriticalSection; Result.Nrbatches := FNrBatches; Result.batchcounter := @batchcounter; ! // Result.Resume; end; *************** *** 474,477 **** --- 339,343 ---- end; + /////////////////////////////////////////////////////////////////////////////// end. Index: RenderThread.pas =================================================================== RCS file: /cvsroot/apophysis/2.10/Source/RenderThread.pas,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RenderThread.pas 3 Sep 2005 11:22:04 -0000 1.4 --- RenderThread.pas 11 Sep 2005 10:20:56 -0000 1.5 *************** *** 23,27 **** uses Classes, windows, Messages, Graphics, ! controlPoint, Render, Render64, Render64MT, RenderMM; const --- 23,27 ---- uses Classes, windows, Messages, Graphics, ! controlPoint, Render, Render64, Render64MT, RenderMM, RenderMM_MT; const *************** *** 133,137 **** end; end else begin ! FRenderer := TRendererMM64.Create; FRenderer.MaxMem := MaxMem end; --- 133,142 ---- end; end else begin ! if NrThreads <= 1 then begin ! FRenderer := TRendererMM64.Create; ! end else begin ! FRenderer := TRendererMM64_MT.Create; ! TRendererMM64_MT(FRenderer).NrOfTreads := NrThreads; ! end; FRenderer.MaxMem := MaxMem end; --- NEW FILE: RenderMM_MT.pas --- { Flame screensaver Copyright (C) 2002 Ronald Hordijk Apophysis Copyright (C) 2001-2004 Mark Townsend This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. } unit RenderMM_MT; interface uses Windows, Graphics, Render, Controlpoint, ImageMaker, BucketFillerThread; type TRendererMM64_MT = class(TBaseRenderer) private oversample: Integer; image_Width: Int64; image_Height: Int64; BucketWidth: Integer; BucketHeight: Integer; BucketSize: Integer; gutter_width: Integer; sample_density: extended; Buckets: TBucketArray; ColorMap: TColorMapArray; bounds: array[0..3] of extended; size: array[0..1] of extended; FRotationCenter: array[0..1] of extended; ppux, ppuy: extended; nrSlices: int64; Slice: int64; FImageMaker: TImageMaker; FNrBatches: int64; batchcounter: Integer; FNrOfTreads: integer; WorkingThreads: array of TBucketFillerThread; CriticalSection: TRTLCriticalSection; procedure InitValues; procedure InitBuffers; procedure ClearBuffers; procedure ClearBuckets; procedure CreateColorMap; procedure CreateCamera; procedure AddPointsToBuckets(const points: TPointsArray); overload; procedure AddPointsToBucketsAngle(const points: TPointsArray); overload; procedure SetPixels; procedure SetPixelsMT; procedure SetNrOfTreads(const Value: integer); function NewThread: TBucketFillerThread; protected function GetSlice: integer; override; function GetNrSlices: integer; override; public constructor Create; override; destructor Destroy; override; function GetImage: TBitmap; override; procedure SaveImage(const FileName: String); override; procedure Render; override; property NrOfTreads: integer read FNrOfTreads write SetNrOfTreads; end; implementation uses Math, Sysutils; { TRendererMM64_MT } /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.ClearBuckets; var i: integer; begin for i := 0 to BucketSize - 1 do begin buckets[i].Red := 0; buckets[i].Green := 0; buckets[i].Blue := 0; buckets[i].Count := 0; end; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.ClearBuffers; begin ClearBuckets; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.CreateCamera; var scale: double; t0, t1: double; corner0, corner1: double; shift: Integer; begin scale := power(2, fcp.zoom); sample_density := fcp.sample_density * scale * scale; ppux := fcp.pixels_per_unit * scale; ppuy := fcp.pixels_per_unit * scale; // todo field stuff shift := 0; t0 := gutter_width / (oversample * ppux); t1 := gutter_width / (oversample * ppuy); corner0 := fcp.center[0] - image_width / ppux / 2.0; corner1 := fcp.center[1] - image_height / ppuy / 2.0; bounds[0] := corner0 - t0; bounds[1] := corner1 - t1 + shift; bounds[2] := corner0 + image_width / ppux + t0; bounds[3] := corner1 + image_height / ppuy + t1; //+ shift; if abs(bounds[2] - bounds[0]) > 0.01 then size[0] := 1.0 / (bounds[2] - bounds[0]) else size[0] := 1; if abs(bounds[3] - bounds[1]) > 0.01 then size[1] := 1.0 / (bounds[3] - bounds[1]) else size[1] := 1; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.CreateColorMap; var i: integer; begin for i := 0 to 255 do begin ColorMap[i].Red := (fcp.CMap[i][0] * fcp.white_level) div 256; ColorMap[i].Green := (fcp.CMap[i][1] * fcp.white_level) div 256; ColorMap[i].Blue := (fcp.CMap[i][2] * fcp.white_level) div 256; // cmap[i][3] := fcp.white_level; end; end; /////////////////////////////////////////////////////////////////////////////// destructor TRendererMM64_MT.Destroy; begin FImageMaker.Free; inherited; end; /////////////////////////////////////////////////////////////////////////////// function TRendererMM64_MT.GetImage: TBitmap; begin Result := FImageMaker.GetImage; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.InitBuffers; begin oversample := fcp.spatial_oversample; gutter_width := (FImageMaker.GetFilterSize - oversample) div 2; BucketHeight := oversample * image_height + 2 * gutter_width; Bucketwidth := oversample * image_width + 2 * gutter_width; BucketSize := BucketWidth * BucketHeight; if high(buckets) <> (BucketSize - 1) then begin SetLength(buckets, BucketSize); end; // share the buffer with imagemaker FImageMaker.SetBucketData(Buckets, BucketWidth); end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.InitValues; begin image_height := fcp.Height; image_Width := fcp.Width; CreateCamera; InitBuffers; CreateColorMap; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.AddPointsToBuckets(const points: TPointsArray); var i: integer; px, py: double; bws, bhs: double; bx, by: double; wx, wy: double; // R: double; // V1, v2, v3: integer; Bucket: PBucket; MapColor: PColorMapColor; begin bws := (BucketWidth - 0.5) * size[0]; bhs := (BucketHeight - 0.5) * size[1]; bx := bounds[0]; by := bounds[1]; wx := bounds[2] - bounds[0]; wy := bounds[3] - bounds[1]; for i := SUB_BATCH_SIZE - 1 downto 0 do begin if FStop then Exit; px := points[i].x - bx; py := points[i].y - by; if ((px < 0) or (px > wx) or (py < 0) or (py > wy)) then continue; MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); Inc(Bucket.Blue, MapColor.Blue); Inc(Bucket.Count); end; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.AddPointsToBucketsAngle(const points: TPointsArray); var i: integer; px, py: double; ca,sa: double; nx, ny: double; bws, bhs: double; bx, by: double; wx, wy: double; // R: double; // V1, v2, v3: integer; Bucket: PBucket; MapColor: PColorMapColor; begin bws := (BucketWidth - 0.5) * size[0]; bhs := (BucketHeight - 0.5) * size[1]; bx := bounds[0]; by := bounds[1]; wx := bounds[2] - bounds[0]; wy := bounds[3] - bounds[1]; ca := cos(FCP.FAngle); sa := sin(FCP.FAngle); for i := SUB_BATCH_SIZE - 1 downto 0 do begin if FStop then Exit; px := points[i].x - FRotationCenter[0]; py := points[i].y - FRotationCenter[1]; nx := px * ca + py * sa; ny := -px * sa + py * ca; px := nx + FRotationCenter[0] - bx; py := ny + FRotationCenter[1] - by; if ((px < 0) or (px > wx) or (py < 0) or (py > wy)) then continue; MapColor := @ColorMap[Round(points[i].c * 255)]; Bucket := @buckets[Round(bws * px) + Round(bhs * py) * BucketWidth]; Inc(Bucket.Red, MapColor.Red); Inc(Bucket.Green, MapColor.Green); Inc(Bucket.Blue, MapColor.Blue); Inc(Bucket.Count); end; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.SetPixels; var i: integer; nsamples: Int64; nrbatches: Integer; points: TPointsArray; begin SetLength(Points, SUB_BATCH_SIZE); nsamples := Round(sample_density * bucketSize / (oversample * oversample)); nrbatches := Round(nsamples / (fcp.nbatches * SUB_BATCH_SIZE)); Randomize; for i := 0 to nrbatches do begin if FStop then Exit; if (i and $F = 0) then if nrbatches > 0 then Progress(i / nrbatches) else Progress(0); // generate points case Compatibility of 0: fcp.iterate_Old(SUB_BATCH_SIZE, points); 1: fcp.iterateXYC(SUB_BATCH_SIZE, points); end; if FCP.FAngle = 0 then AddPointsToBuckets(points) else AddPointsToBucketsAngle(points); end; Progress(1); end; /////////////////////////////////////////////////////////////////////////////// constructor TRendererMM64_MT.Create; begin inherited Create; FImageMaker := TImageMaker.Create; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.Render; const Dividers: array[0..15] of integer = (1, 2, 3, 4, 5, 6, 7, 8, 10, 16, 20, 32, 64, 128, 256, 512); var ApproxMemory, MaxMemory: int64; i: integer; zoom_scale, center_base, center_y: double; begin FStop := False; FRotationCenter[0] := fcp.center[0]; FRotationCenter[1] := fcp.center[1]; image_height := fcp.Height; image_Width := fcp.Width; oversample := fcp.spatial_oversample; // entered memory - imagesize MaxMemory := FMaxMem * 1024 * 1024 - 4 * image_height * image_width; ApproxMemory := 32 * oversample * oversample * image_height * image_width; if (MaxMemory < 0) then Exit; nrSlices := 1 + ApproxMemory div MaxMemory; if nrSlices > Dividers[High(Dividers)] then begin for i := High(Dividers) downto 0 do begin if image_height <> (image_height div dividers[i]) * dividers[i] then begin nrSlices := dividers[i]; break; end; end; end else begin for i := 0 to High(Dividers) do begin if image_height <> (image_height div dividers[i]) * dividers[i] then continue; if nrslices <= dividers[i] then begin nrSlices := dividers[i]; break; end; end; end; FImageMaker.SetCP(FCP); FImageMaker.Init; fcp.sample_density := fcp.sample_density * nrslices; fcp.height := fcp.height div nrslices; center_y := fcp.center[1]; zoom_scale := power(2.0, fcp.zoom); center_base := center_y - ((nrslices - 1) * fcp.height) / (2 * fcp.pixels_per_unit * zoom_scale); InitValues; for i := 0 to NrSlices - 1 do begin if FStop then Exit; Slice := i; fcp.center[1] := center_base + fcp.height * slice / (fcp.pixels_per_unit * zoom_scale); CreateCamera; ClearBuffers; SetPixelsMT; if not FStop then begin FImageMaker.OnProgress := OnProgress; FImageMaker.CreateImage(Slice * fcp.height); end; end; fcp.sample_density := fcp.sample_density / nrslices; fcp.height := fcp.height * nrslices; end; /////////////////////////////////////////////////////////////////////////////// function TRendererMM64_MT.GetSlice: integer; begin Result := Slice; end; /////////////////////////////////////////////////////////////////////////////// function TRendererMM64_MT.GetNrSlices: integer; begin Result := NrSlices; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.SaveImage(const FileName: String); begin FImageMaker.SaveImage(FileName); end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.SetNrOfTreads(const Value: integer); begin FNrOfTreads := Value; end; /////////////////////////////////////////////////////////////////////////////// procedure TRendererMM64_MT.SetPixelsMT; var i: integer; nsamples: Int64; bc : integer; begin nsamples := Round(sample_density * bucketSize / (oversample * oversample)); FNrBatches := Round(nsamples / (fcp.nbatches * SUB_BATCH_SIZE)); batchcounter := 0; Randomize; InitializeCriticalSection(CriticalSection); SetLength(WorkingThreads, NrOfTreads); for i := 0 to NrOfTreads - 1 do WorkingThreads[i] := NewThread; for i := 0 to NrOfTreads - 1 do WorkingThreads[i].Resume; bc := 0; while (Not FStop) and (bc < FNrBatches) do begin sleep(200); try EnterCriticalSection(CriticalSection); if batchcounter > 0 then Progress(batchcounter / FNrBatches) else Progress(0); bc := batchcounter; finally LeaveCriticalSection(CriticalSection); end; end; DeleteCriticalSection(CriticalSection); Progress(1); end; /////////////////////////////////////////////////////////////////////////////// function TRendererMM64_MT.NewThread: TBucketFillerThread; begin Result := TBucketFillerThread.Create(fcp); Result.BucketWidth := BucketWidth; Result.BucketHeight := BucketHeight; Result.Buckets := @Buckets; Result.size[0] := size[0]; Result.size[1] := size[1]; Result.bounds[0] := Bounds[0]; Result.bounds[1] := Bounds[1]; Result.bounds[2] := Bounds[2]; Result.bounds[3] := Bounds[3]; Result.RotationCenter[0] := FRotationCenter[0]; Result.RotationCenter[1] := FRotationCenter[1]; Result.ColorMap := colorMap; Result.CriticalSection := CriticalSection; Result.Nrbatches := FNrBatches; Result.batchcounter := @batchcounter; end; /////////////////////////////////////////////////////////////////////////////// end. Index: RenderMM.pas =================================================================== RCS file: /cvsroot/apophysis/2.10/Source/RenderMM.pas,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RenderMM.pas 3 Sep 2005 11:22:04 -0000 1.4 --- RenderMM.pas 11 Sep 2005 10:20:56 -0000 1.5 *************** *** 29,34 **** private oversample: Integer; - filter_width: Integer; - filter: array of array of extended; image_Width: Int64; --- 29,32 ---- Index: Render32.pas =================================================================== RCS file: /cvsroot/apophysis/2.10/Source/Render32.pas,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Render32.pas 1 May 2005 08:01:31 -0000 1.2 --- Render32.pas 11 Sep 2005 10:20:56 -0000 1.3 *************** *** 47,50 **** --- 47,55 ---- TBucketArray = array of TBucket; + PLongintArray = ^TLongintArray; + TLongintArray = array[0..0] of Longint; + PByteArray = ^TByteArray; + TByteArray = array[0..0] of Byte; + type TRenderer32 = class(TBaseRenderer) |