Reduce memory used by SDD calibration objects in OCDB (F. Prino)
[u/mrichter/AliRoot.git] / EVE / EveDet / AliEveTPCSector2DGL.cxx
1 // $Id$
2 // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3
4 /**************************************************************************
5  * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
6  * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
7  * full copyright notice.                                                 *
8  **************************************************************************/
9
10 #include "AliEveTPCSector2DGL.h"
11
12 #include <EveDet/AliEveTPCSector2D.h>
13
14 #include <TGLRnrCtx.h>
15 #include <TGLSelectRecord.h>
16 #include <TGLIncludes.h>
17
18 //______________________________________________________________________________
19 //
20 // GL renderer for AliEveTPCSector2D.
21
22 ClassImp(AliEveTPCSector2DGL)
23
24 // This can be optimized to non-pow-2 values once everybody has GL 1.4.
25
26 const Int_t AliEveTPCSector2DGL::fgkTextureWidth    = 256;
27 const Int_t AliEveTPCSector2DGL::fgkTextureHeight   = 128;
28 const Int_t AliEveTPCSector2DGL::fgkTextureByteSize = 4*256*128;
29
30 /******************************************************************************/
31
32 AliEveTPCSector2DGL::AliEveTPCSector2DGL() :
33   TGLObject(),
34
35   fSector     (0),
36   fSectorData (0),
37
38   fImage   (0),
39   fTexture (0),
40   fRTS     (0)
41 {
42   // Constructor.
43 }
44
45 AliEveTPCSector2DGL::~AliEveTPCSector2DGL()
46 {
47   // Destructor.
48   // !!!! Should unregister texture via ContextIdentity!
49
50   if (fImage)   delete fImage;
51   if (fTexture) glDeleteTextures(1, &fTexture);
52 }
53
54 /******************************************************************************/
55
56 Bool_t AliEveTPCSector2DGL::SetModel(TObject* obj, const Option_t* /*opt*/)
57 {
58   // Set model object.
59
60   if (SetModelCheckClass(obj, AliEveTPCSector2D::Class())) {
61     fSector = (AliEveTPCSector2D*) fExternalObj;
62     return kTRUE;
63   }
64   return kFALSE;
65 }
66
67 void AliEveTPCSector2DGL::SetBBox()
68 {
69   // Set bounding-box.
70
71   SetAxisAlignedBBox(((AliEveTPCSector2D*)fExternalObj)->AssertBBox());
72 }
73
74 /******************************************************************************/
75
76 void AliEveTPCSector2DGL::ProcessSelection(TGLRnrCtx       & /*rnrCtx*/,
77                                            TGLSelectRecord & rec)
78 {
79   // Process selection record.
80   // Determine row and pad, call PadSelected() in model object.
81
82   if (rec.GetN() != 3) return;
83   Int_t row = rec.GetItem(1);
84   Int_t pad = rec.GetItem(2);
85   if (row < 0 || row >= AliEveTPCSectorData::GetNAllRows())      return;
86   if (pad < 0 || pad >= AliEveTPCSectorData::GetNPadsInRow(row)) return;
87   fSector->PadSelected(row, pad);
88 }
89
90 /******************************************************************************/
91
92 void AliEveTPCSector2DGL::DirectDraw(TGLRnrCtx& rnrCtx) const
93 {
94   // Actual GL drawing.
95
96   // printf("AliEveTPCSector2DGL::DirectDraw \n");
97
98   fSectorData = fSector->GetSectorData();
99
100   if(fRTS < fSector->fRTS && fSectorData != 0) {
101     CreateTexture();
102     fRTS = fSector->fRTS;
103   }
104
105   glPushAttrib(GL_CURRENT_BIT      | GL_DEPTH_BUFFER_BIT |
106                GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT       | GL_POLYGON_BIT);
107
108   glDisable(GL_LIGHTING);
109   glDisable(GL_CULL_FACE);
110
111   // Display digits
112   if(fSectorData != 0) {
113
114     const AliEveTPCSectorData::SegmentInfo&  iSeg = AliEveTPCSectorData::GetInnSeg();
115     const AliEveTPCSectorData::SegmentInfo& o1Seg = AliEveTPCSectorData::GetOut1Seg();
116     const AliEveTPCSectorData::SegmentInfo& o2Seg = AliEveTPCSectorData::GetOut2Seg();
117
118     if(rnrCtx.SecSelection()) {
119
120       if(fSector->fRnrInn)  DisplayNamedQuads(iSeg, 0, 0);
121       if(fSector->fRnrOut1) DisplayNamedQuads(o1Seg, iSeg.GetNMaxPads(), 0);
122       if(fSector->fRnrOut2) DisplayNamedQuads(o2Seg, 0, o1Seg.GetNRows());
123
124     } else {
125
126       if(fSector->fUseTexture) {
127         //texture
128         glEnable(GL_BLEND);
129         glDepthMask(GL_FALSE);
130         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
131
132         glPolygonOffset(2,2);
133         glEnable(GL_POLYGON_OFFSET_FILL);
134
135         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
136         glBindTexture(GL_TEXTURE_2D, fTexture);
137         glEnable(GL_TEXTURE_2D);
138
139         if(fSector->fRnrInn)  DisplayTexture(iSeg, 0, 0);
140         if(fSector->fRnrOut1) DisplayTexture(o1Seg, iSeg.GetNMaxPads(), 0);
141         if(fSector->fRnrOut2) DisplayTexture(o2Seg, 0, o1Seg.GetNRows());
142
143         glDisable(GL_TEXTURE_2D);
144       } else {
145         if(fSector->fRnrInn)  DisplayQuads(iSeg, 0, 0);
146         if(fSector->fRnrOut1) DisplayQuads(o1Seg, iSeg.GetNMaxPads(), 0);
147         if(fSector->fRnrOut2) DisplayQuads(o2Seg, 0, o1Seg.GetNRows());
148       }
149       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
150       DisplayFrame();
151     }
152
153   }
154
155   glPopAttrib();
156 }
157
158 /******************************************************************************/
159 // Data import
160 /******************************************************************************/
161
162 void AliEveTPCSector2DGL::LoadPadrow(AliEveTPCSectorData::RowIterator& iter,
163                                      Int_t row, Int_t colOff) const
164 {
165   // Load data for one pad-row into the texture.
166
167   Int_t    padVal;
168   Int_t    time, val;
169
170   Int_t    minTime = fSector->fMinTime;
171   Int_t    maxTime = fSector->fMaxTime;
172   Bool_t   halfBorderTime = ((maxTime - minTime) % 2 == 0);
173
174   UChar_t* imgPos = GetRowCol(row, colOff);
175   while (iter.NextPad()) {
176     padVal = 0;
177
178     while (iter.Next()) {
179       time = iter.Time();
180       val  = iter.Signal();
181
182       if(time < minTime || time > maxTime)
183         continue;
184
185       if(fSector->fShowMax) {
186         if(val > padVal) {
187           padVal = val;
188         }
189       } else {
190         if(halfBorderTime && (time == minTime || time == maxTime))
191           padVal += val/2;
192         else
193           padVal += val;
194       }
195     }
196
197     if(fSector->fShowMax == kFALSE && fSector->fAverage) {
198       padVal = (Int_t)((Float_t)padVal / (maxTime - minTime));
199     }
200     padVal = TMath::Min(padVal, fSector->fMaxVal);
201     if(padVal > fSector->fThreshold)
202       fSector->ColorFromArray(padVal, imgPos);
203     imgPos += 4;
204   }
205 }
206
207 /******************************************************************************/
208
209 void AliEveTPCSector2DGL::CreateTexture() const
210 {
211   // Create texture that holds pad data.
212
213   if (fImage == 0 ) {
214     fImage = new UChar_t[fgkTextureByteSize];
215     glGenTextures(1, &fTexture);
216   }
217   memset(fImage, 0, fgkTextureByteSize);
218
219   Int_t rowOff[3], colOff[3];
220   Bool_t isOn[3];
221   rowOff[0] = 0;
222   rowOff[1] = rowOff[2] = -AliEveTPCSectorData::GetSeg(1).GetFirstRow();
223   colOff[0] = colOff[2] = 0;
224   colOff[1] = AliEveTPCSectorData::GetSeg(0).GetNMaxPads();
225   isOn[0] = fSector->fRnrInn;
226   isOn[1] = fSector->fRnrOut1;
227   isOn[2] = fSector->fRnrOut2;
228
229   fSector->SetupColorArray();
230
231   // Loop over 3 main segments
232   for (Int_t sId = 0; sId <= 2; ++sId)
233   {
234     if (isOn[sId] == kFALSE)
235       continue;
236     const AliEveTPCSectorData::SegmentInfo& sInfo = AliEveTPCSectorData::GetSeg(sId);
237     for (Int_t row = sInfo.GetFirstRow(); row <= sInfo.GetLastRow(); ++row)
238     {
239       AliEveTPCSectorData::RowIterator i = fSectorData->MakeRowIterator(row);
240       Int_t offset = (sInfo.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(row))/2;
241       LoadPadrow(i, row + rowOff[sId], offset + colOff[sId]);
242     }
243   }
244
245   glBindTexture  (GL_TEXTURE_2D, fTexture);
246   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT);
247   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT);
248   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
249   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
250   glTexEnvf      (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,   GL_REPLACE);
251   glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, fgkTextureWidth, fgkTextureHeight,
252                   0, GL_RGBA, GL_UNSIGNED_BYTE, fImage);
253
254 }
255
256 /******************************************************************************/
257 // Data display
258 /******************************************************************************/
259
260 void AliEveTPCSector2DGL::DisplayTexture(const AliEveTPCSectorData::SegmentInfo& seg,
261                                          Int_t startCol, Int_t startRow) const
262 {
263   // Display segment data via one textured rectangle.
264
265   Float_t w  = seg.GetNMaxPads()*seg.GetPadWidth()/2;
266   Float_t y1 = seg.GetRLow();
267   Float_t y2 = y1 + seg.GetNRows()*seg.GetPadHeight();
268
269   Float_t u1 = (Float_t) startCol / fgkTextureWidth;
270   Float_t v1 = (Float_t) startRow / fgkTextureHeight;
271   Float_t u2 = u1 + (Float_t) seg.GetNMaxPads() / fgkTextureWidth;
272   Float_t v2 = v1 + (Float_t) seg.GetNRows()    / fgkTextureHeight;
273
274   glBegin(GL_QUADS);
275   glTexCoord2f(u1, v1);  glVertex2f(-w, y1);
276   glTexCoord2f(u1, v2);  glVertex2f(-w, y2);
277   glTexCoord2f(u2, v2);  glVertex2f( w, y2);
278   glTexCoord2f(u2, v1);  glVertex2f( w, y1);
279   glEnd();
280 }
281
282 /******************************************************************************/
283
284 void AliEveTPCSector2DGL::DisplayQuads(const AliEveTPCSectorData::SegmentInfo& seg,
285                                        Int_t startCol, Int_t startRow) const
286 {
287   // Display segment data by rendering one quad per pad.
288
289   Float_t yD, yU;
290   Float_t xOff, x;
291   Float_t padW = seg.GetPadWidth();
292   Float_t padH = seg.GetPadHeight();
293
294   glBegin(GL_QUADS);
295   for (Int_t row = 0; row < seg.GetNRows(); row++)
296   {
297     yD = seg.GetRLow() + row*padH;
298     yU = yD + padH;
299     xOff = -seg.GetNMaxPads()*padW/2;
300     Int_t tpcRow = row + seg.GetFirstRow();
301     Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2;
302     Int_t   maxPad = seg.GetNMaxPads() - deltaPad;
303     UChar_t   *pix = GetRowCol(row + startRow, startCol + deltaPad);
304     for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4)
305     {
306       x = xOff + pad*padW;
307       if (pix[3] != 0)
308       {
309         TGLUtil::Color4ubv(pix);
310         glVertex2f(x+padW, yD);
311         glVertex2f(x,      yD);
312         glVertex2f(x,      yU);
313         glVertex2f(x+padW, yU);
314       }
315     }
316   }
317   glEnd();
318 }
319
320 void AliEveTPCSector2DGL::DisplayNamedQuads(const AliEveTPCSectorData::SegmentInfo& seg,
321                                             Int_t startCol, Int_t startRow) const
322 {
323   // Display segmen data as one quad per pad.
324   // Tag the rows and pads for selection.
325
326   Float_t yD, yU;
327   Float_t xOff, x;
328   Float_t padW = seg.GetPadWidth();
329   Float_t padH = seg.GetPadHeight();
330
331   glPushName(0);
332   for (Int_t row = 0; row < seg.GetNRows(); row++)
333   {
334     yD = seg.GetRLow() + row*padH;
335     yU = yD + padH;
336     xOff = -seg.GetNMaxPads()*padW/2;
337     Int_t tpcRow = row + seg.GetFirstRow();
338     glLoadName(tpcRow);
339     Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2;
340     Int_t   maxPad = seg.GetNMaxPads() - deltaPad;
341     UChar_t   *pix = GetRowCol(row + startRow, startCol + deltaPad);
342     glPushName(0);
343     for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4) 
344     {
345       x = xOff + pad*padW;
346       if (pix[3] != 0 || fSector->fPickEmpty)
347       {
348         glLoadName(pad - deltaPad);
349         glBegin(GL_QUADS);
350         glVertex2f(x+padW, yD);
351         glVertex2f(x,      yD);
352         glVertex2f(x,      yU);
353         glVertex2f(x+padW, yU);
354         glEnd();
355       }
356     }
357     glPopName();
358   }
359   glPopName();
360 }
361
362 /******************************************************************************/
363 // Frame drawing
364 /******************************************************************************/
365
366 void AliEveTPCSector2DGL::TraceStepsUp(const AliEveTPCSectorData::SegmentInfo& s)
367 {
368   // Trace border of segment upwards.
369
370   Float_t x = -(s.GetNMaxPads()*1.0/2 - s.GetNYSteps())*s.GetPadWidth();
371   Float_t y  = s.GetRLow();
372   glVertex2f(x, y);
373   for (Int_t i = 0; i < s.GetNYSteps(); ++i)
374   {
375     y = s.GetYStep(i);
376     glVertex2f(x, y);
377     x -= s.GetPadWidth();
378     glVertex2f(x, y);
379   }
380   y =  s.GetRLow() + s.GetNRows()*s.GetPadHeight();
381   glVertex2f(-s.GetNMaxPads()*s.GetPadWidth()/2, y);
382 }
383
384 void AliEveTPCSector2DGL::TraceStepsDown(const AliEveTPCSectorData::SegmentInfo& s)
385 {
386   // Trace border of segment downwards.
387
388   Float_t x = s.GetNMaxPads()*s.GetPadWidth()/2;
389   Float_t y = s.GetRLow() + s.GetNRows()*s.GetPadHeight();
390   glVertex2f(x, y);
391   for (Int_t i = s.GetNYSteps() - 1; i >= 0; --i)
392   {
393     y =  s.GetYStep(i);
394     glVertex2f(x, y);
395     x -= s.GetPadWidth();
396     glVertex2f(x, y);
397   }
398   y = s.GetRLow();
399   glVertex2f((0.5*s.GetNMaxPads() - s.GetNYSteps())*s.GetPadWidth(), y);
400 }
401
402 void AliEveTPCSector2DGL::DisplayFrame() const
403 {
404   // Display frame of the sector.
405   // Each segment's frame is drawn only if its data is drawn, too.
406
407   TGLUtil::Color(fSector->fFrameColor);
408
409   if(fSector->fRnrInn)
410   {
411     glBegin(GL_POLYGON);
412     TraceStepsUp  (AliEveTPCSectorData::GetInnSeg());
413     TraceStepsDown(AliEveTPCSectorData::GetInnSeg());
414     glEnd();
415   }
416   if(fSector->fRnrOut1)
417   {
418     glBegin(GL_POLYGON);
419     TraceStepsUp  (AliEveTPCSectorData::GetOut1Seg());
420     TraceStepsDown(AliEveTPCSectorData::GetOut1Seg());
421     glEnd();
422   }
423   if(fSector->fRnrOut2)
424   {
425     glBegin(GL_POLYGON);
426     TraceStepsUp  (AliEveTPCSectorData::GetOut2Seg());
427     TraceStepsDown(AliEveTPCSectorData::GetOut2Seg());
428     glEnd();
429   }
430 }