Update copyright date; remove old CVS keyword
[ctsim.git] / src / threadraster.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          threadraster.cpp
5 **   Purpose:       Threaded rasterizer class
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  February 2001
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2009 Kevin Rosenberg
11 **
12 **  This program is free software; you can redistribute it and/or modify
13 **  it under the terms of the GNU General Public License (version 2) as
14 **  published by the Free Software Foundation.
15 **
16 **  This program is distributed in the hope that it will be useful,
17 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 **  GNU General Public License for more details.
20 **
21 **  You should have received a copy of the GNU General Public License
22 **  along with this program; if not, write to the Free Software
23 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 ******************************************************************************/
25
26
27 #if defined(HAVE_CONFIG_H)
28 #include "config.h"
29 #endif
30
31 #include "wx/wxprec.h"
32
33 #ifndef WX_PRECOMP
34 #include "wx/wx.h"
35 #endif
36
37 #include "ct.h"
38 #include "ctsim.h"
39 #include "docs.h"
40 #include "views.h"
41
42
43 #ifdef HAVE_WXTHREADS
44
45
46 #include "threadraster.h"
47 #include "backgroundmgr.h"
48 #include "backgroundsupr.h"
49
50
51 /////////////////////////////////////////////////////////////////////
52 //
53 // Class RasterizerSupervisorThread -- Thread for Background Supervisor
54 //
55 /////////////////////////////////////////////////////////////////////
56
57 RasterizerSupervisorThread::RasterizerSupervisorThread (PhantomFileView* pProjView, int iNX, int iNY,
58                                                         int iNSample, double dViewRatio, wxChar const* pszLabel)
59                                                         :   SupervisorThread(), m_pPhantomView(pProjView), m_iNX(iNX), m_iNY(iNY), m_iNSample(iNSample), m_dViewRatio(dViewRatio), m_strLabel(pszLabel)
60 {
61 }
62
63 wxThread::ExitCode
64 RasterizerSupervisorThread::Entry()
65 {
66   RasterizerSupervisor rasterSupervisor (this, m_pPhantomView, m_iNX, m_iNY, m_iNSample, m_dViewRatio, m_strLabel);
67
68   rasterSupervisor.start();
69
70   while (! rasterSupervisor.workersDone() && ! rasterSupervisor.fail() && ! rasterSupervisor.cancelled()) {
71     Sleep(100);
72   }
73
74   if (rasterSupervisor.fail())
75   {
76     wxString msg (_T("Error starting Rasterizer supervisor: "));
77     msg += rasterSupervisor.getFailMessage();
78     msg += _T("\n");
79     wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
80     eventLog.SetString( msg );
81     wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
82   }
83
84   if (! rasterSupervisor.cancelled())
85     rasterSupervisor.onDone();
86   rasterSupervisor.deleteWorkers();
87
88   return static_cast<wxThread::ExitCode>(0);
89 }
90
91 void
92 RasterizerSupervisorThread::OnExit()
93 {
94 }
95
96
97 /////////////////////////////////////////////////////////////////////
98 //
99 // Class RasterizerSupervisor -- A Background Supervisor
100 //
101 /////////////////////////////////////////////////////////////////////
102
103 RasterizerSupervisor::RasterizerSupervisor (SupervisorThread* pThread, PhantomFileView* pPhantomView, int iNX, int iNY,
104                                             int iNSample, double dViewRatio, wxChar const* pszLabel)
105   : BackgroundSupervisor (pThread, pPhantomView->GetFrame(), pPhantomView->GetDocument(), _T("Rasterizing"), iNX),
106                                             m_pPhantomView(pPhantomView), m_pPhantomDoc(pPhantomView->GetDocument()),
107                                             m_iNX(iNX), m_iNY(iNY), m_iNSample(iNSample), m_dViewRatio(dViewRatio), m_strLabel(pszLabel)
108 {
109   m_vecpChildImageFiles.reserve (getNumWorkers());
110   for (int iThread = 0; iThread < getNumWorkers(); iThread++) {
111     m_vecpChildImageFiles[iThread] = new ImageFile;
112   }
113 }
114
115 RasterizerSupervisor::~RasterizerSupervisor()
116 {
117   for (int i = 0; i < getNumWorkers(); i++)
118     delete m_vecpChildImageFiles[i];
119 }
120
121 BackgroundWorkerThread*
122 RasterizerSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
123 {
124   RasterizerWorker* pThread = new RasterizerWorker (this, iThread, iStartUnit, iNumUnits);
125   m_vecpChildImageFiles[iThread]->setArraySize (iNumUnits, m_iNY);
126   pThread->SetParameters (m_pPhantomView, m_vecpChildImageFiles[iThread], m_iNX, m_iNY, m_iNSample, m_dViewRatio);
127
128   return pThread;
129 }
130
131 void
132 RasterizerSupervisor::onDone()
133 {
134   wxCriticalSection doneSection;
135   wxCriticalSectionLocker critsect (doneSection);
136
137   ImageFile* pImageFile = getImageFile();
138   pImageFile->labelAdd (m_strLabel.mb_str(wxConvUTF8), getTimerEnd());
139
140   wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
141   wxString msg (m_strLabel);
142   msg += _T("\n");
143   eventLog.SetString( msg );
144   wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
145
146   wxCommandEvent newImageEvent (wxEVT_COMMAND_MENU_SELECTED, NEW_IMAGEFILE_EVENT);
147   newImageEvent.SetClientData (pImageFile);
148   wxPostEvent (theApp->getMainFrame(), newImageEvent);
149
150   setDone();
151 }
152
153
154 ImageFile*
155 RasterizerSupervisor::getImageFile()
156 {
157   ImageFile* pImageFile = new ImageFile (m_iNX, m_iNY);
158
159   size_t iColSize = sizeof(ImageFileValue) * m_iNY;
160
161   ImageFileArray globalArray = pImageFile->getArray();
162   int iGlobalCol = 0;
163   for (int iw = 0; iw < getNumWorkers(); iw++) {
164     ImageFileArray childArray = m_vecpChildImageFiles[iw]->getArray();
165     for (unsigned int iCol = 0; iCol < m_vecpChildImageFiles[iw]->nx(); iCol++) {
166       memcpy (globalArray[iGlobalCol++], childArray[iCol], iColSize);
167     }
168   }
169   return (pImageFile);
170 }
171
172
173 /////////////////////////////////////////////////////////////////////
174 //
175 // Class RasterizerWorker -- A worker thread
176 //
177 /////////////////////////////////////////////////////////////////////
178
179 void
180 RasterizerWorker::SetParameters (PhantomFileView* pPhantomView, ImageFile* pImageFile, int iNX, int iNY, int iNSample, double dViewRatio)
181 {
182   m_pImageFile = pImageFile;
183   m_iNX = iNX;
184   m_iNY = iNY;
185   m_pPhantomView = pPhantomView;
186   m_iNSample = iNSample;
187   m_dViewRatio = dViewRatio;
188 }
189
190 wxThread::ExitCode
191 RasterizerWorker::Entry ()
192 {
193   const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
194   wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
195   for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
196     if (TestDestroy()) {
197 #ifdef DEBUG
198       if (theApp->getVerboseLogging()) {
199         wxString msg;
200         msg.Printf(_T("Worker thread: Received destroy message at work unit #%d\n"), iUnit);
201         wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
202         event.SetString( msg );
203         wxPostEvent( theApp->getMainFrame(), event );
204       }
205 #endif
206       break;
207     }
208     rPhantom.convertToImagefile (*m_pImageFile, m_iNX, m_dViewRatio, m_iNSample, Trace::TRACE_NONE, iUnit + m_iStartUnit, 1, iUnit);
209     m_pSupervisor->onWorkerUnitTick();
210   }
211
212   m_pSupervisor->onWorkerDone (m_iThread);
213
214   while (! TestDestroy())
215     Sleep(100);
216
217   return static_cast<wxThread::ExitCode>(0);
218 }
219
220 void
221 RasterizerWorker::OnExit ()
222 {
223 }
224
225 #endif // HAVE_WXTHREADS