// @(#)root/gl:$Id$
// Author:  Timur Pocheptsov, Jun 2007

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <cassert>
#include <algorithm>
#include <set>

#include "TGLFormat.h"
#include "TGLWSIncludes.h"
#include "TGLWidget.h"

#include "TEnv.h"
#include "TError.h"
#include "TVirtualX.h"
#include "RConfigure.h"

//______________________________________________________________________________
//
// Encapsulation of format / contents of an OpenGL buffer.

ClassImp(TGLFormat);

std::vector<Int_t> TGLFormat::fgAvailableSamples;

//______________________________________________________________________________
TGLFormat::TGLFormat() :
   fDoubleBuffered(kTRUE),
   fStereo(kFALSE),
#ifdef WIN32
   fDepthSize(32),
#else
   // 16-bits needed for some virtual machines (VirtualBox) and Xming-mesa
   // (when running ssh from windows to linux).
   // All others seem to have 24-bit depth-buffers only and use this anyway.
   fDepthSize(16),
#endif
   fAccumSize(0),
   fStencilSize(8),
   fSamples(GetDefaultSamples())
{
   //Default ctor. Default surface is:
   //-double buffered
   //-RGBA
   //-with depth buffer
   //-no accumulation buffer
   //-with stencil
   //-multi-sampling depends on seeting of "OpenGL.Framebuffer.Multisample"
}

//______________________________________________________________________________
TGLFormat::TGLFormat(Rgl::EFormatOptions opt) :
   fDoubleBuffered(opt & Rgl::kDoubleBuffer),
   fStereo(kFALSE),
#ifdef WIN32
   fDepthSize(opt & Rgl::kDepth ? 32 : 0),
#else
   fDepthSize(opt & Rgl::kDepth ? 16 : 0),//FIXFIX
#endif
   fAccumSize(opt & Rgl::kAccum ? 8 : 0),     //I've never tested accumulation buffer size.
   fStencilSize(opt & Rgl::kStencil ? 8 : 0), //I've never tested stencil buffer size.
   fSamples(opt & Rgl::kMultiSample ? GetDefaultSamples() : 0)
{
   //Define surface using options.
}

//______________________________________________________________________________
TGLFormat::~TGLFormat()
{
   //Destructor.
}

//______________________________________________________________________________
Bool_t TGLFormat::operator == (const TGLFormat &rhs)const
{
   //Check if two formats are equal.
   return fDoubleBuffered == rhs.fDoubleBuffered && fDepthSize == rhs.fDepthSize &&
          fAccumSize == rhs.fAccumSize && fStencilSize == rhs.fStencilSize;
}

//______________________________________________________________________________
Bool_t TGLFormat::operator != (const TGLFormat &rhs)const
{
   //Check for non-equality.
   return !(*this == rhs);
}

//______________________________________________________________________________
Int_t TGLFormat::GetDepthSize()const
{
   //Get the size of depth buffer.
   return fDepthSize;
}

//______________________________________________________________________________
void TGLFormat::SetDepthSize(Int_t depth)
{
   //Set the size of color buffer.
   assert(depth);
   fDepthSize = depth;
}

//______________________________________________________________________________
Bool_t TGLFormat::HasDepth()const
{
   //Check, if this surface has depth buffer.
   return GetDepthSize() != 0;
}

//______________________________________________________________________________
Int_t TGLFormat::GetStencilSize()const
{
   //Get the size of stencil buffer.
   return fStencilSize;
}

//______________________________________________________________________________
void TGLFormat::SetStencilSize(Int_t stencil)
{
   //Set the size of stencil buffer.
   assert(stencil);
   fStencilSize = stencil;
}

//______________________________________________________________________________
Bool_t TGLFormat::HasStencil()const
{
   //Check, if this surface has stencil buffer.
   return GetStencilSize() != 0;
}

//______________________________________________________________________________
Int_t TGLFormat::GetAccumSize()const
{
   //Get the size of accum buffer.
   return fAccumSize;
}

//______________________________________________________________________________
void TGLFormat::SetAccumSize(Int_t accum)
{
   //Set the size of accum buffer.
   assert(accum);
   fAccumSize = accum;
}

//______________________________________________________________________________
Bool_t TGLFormat::HasAccumBuffer()const
{
   //Check, if this surface has accumulation buffer.
   return GetAccumSize() != 0;
}

//______________________________________________________________________________
Bool_t TGLFormat::IsDoubleBuffered()const
{
   //Check, if the surface is double buffered.
   return fDoubleBuffered;
}

//______________________________________________________________________________
void TGLFormat::SetDoubleBuffered(Bool_t db)
{
   //Set the surface as double/single buffered.
   fDoubleBuffered = db;
}

//______________________________________________________________________________
Bool_t TGLFormat::IsStereo()const
{
   //Check, if the surface is stereo buffered.
   return fStereo;
}

//______________________________________________________________________________
void TGLFormat::SetStereo(Bool_t db)
{
   //Set the surface as stereo/non-stereo buffered.
   fStereo = db;
}

//______________________________________________________________________________
Int_t TGLFormat::GetSamples()const
{
   //Get the number of samples for multi-sampling.
   return fSamples;
}

//______________________________________________________________________________
void TGLFormat::SetSamples(Int_t samples)
{
   //Set the number of samples for multi-sampling.
   fSamples = samples;
}

//______________________________________________________________________________
Bool_t TGLFormat::HasMultiSampling()const
{
   //Check, if multi-sampling is requred.
   return fSamples != 0;
}

//______________________________________________________________________________
Int_t TGLFormat::GetDefaultSamples()
{
   // Return default number of samples for multi-sampling.

   Int_t req = gEnv->GetValue("OpenGL.Framebuffer.Multisample", 0);

   // Avoid query of available multi-sample modes when not required.
   // Over ssh, SLC5 lies about supporting the GLX_SAMPLES_ARB
   // extension and then dies horribly when the query is made.
   if (req == 0) {
      return 0;
   }

   if (fgAvailableSamples.empty())
      InitAvailableSamples();

   std::vector<Int_t>::iterator i = fgAvailableSamples.begin();
   while (i != fgAvailableSamples.end() - 1 && *i < req)
      ++i;

   if (*i != req) {
      Info("TGLFormat::GetDefaultSamples", "Requested multi-sampling %d not available, using %d. Adjusting default.", req, *i);
      gEnv->SetValue("OpenGL.Framebuffer.Multisample", *i);
   }

   return *i;
}

//______________________________________________________________________________
void TGLFormat::InitAvailableSamples()
{
   std::set<Int_t> ns_set;
   ns_set.insert(0);

#ifdef WIN32

   // Missing implementation.
#elif defined(R__HAS_COCOA)
   ns_set.insert(8);
   ns_set.insert(16);
#else
   TGLWidget *widget = TGLWidget::CreateDummy();
   widget->MakeCurrent();

   if (GLXEW_ARB_multisample)
   {
      Display *dpy  = (Display*) gVirtualX->GetDisplay();
      XVisualInfo tmpl; tmpl.screen = gVirtualX->GetScreen();
      long mask = VisualScreenMask;
      int  numVisuals, use_gl, ms_ns;
      XVisualInfo *vis = XGetVisualInfo(dpy, mask, &tmpl, &numVisuals);
      for (int i = 0; i < numVisuals; i++)
      {
         if (glXGetConfig(dpy, &vis[i], GLX_USE_GL, &use_gl) == 0)
         {
            glXGetConfig(dpy, &vis[i], GLX_SAMPLES_ARB, &ms_ns);
            ns_set.insert(ms_ns);
         }
      }
      XFree(vis);
   }

   delete widget;
#endif

   fgAvailableSamples.reserve(ns_set.size());
   for (std::set<Int_t>::iterator i = ns_set.begin(); i != ns_set.end(); ++i)
   {
      fgAvailableSamples.push_back(*i);
   }
}
 TGLFormat.cxx:1
 TGLFormat.cxx:2
 TGLFormat.cxx:3
 TGLFormat.cxx:4
 TGLFormat.cxx:5
 TGLFormat.cxx:6
 TGLFormat.cxx:7
 TGLFormat.cxx:8
 TGLFormat.cxx:9
 TGLFormat.cxx:10
 TGLFormat.cxx:11
 TGLFormat.cxx:12
 TGLFormat.cxx:13
 TGLFormat.cxx:14
 TGLFormat.cxx:15
 TGLFormat.cxx:16
 TGLFormat.cxx:17
 TGLFormat.cxx:18
 TGLFormat.cxx:19
 TGLFormat.cxx:20
 TGLFormat.cxx:21
 TGLFormat.cxx:22
 TGLFormat.cxx:23
 TGLFormat.cxx:24
 TGLFormat.cxx:25
 TGLFormat.cxx:26
 TGLFormat.cxx:27
 TGLFormat.cxx:28
 TGLFormat.cxx:29
 TGLFormat.cxx:30
 TGLFormat.cxx:31
 TGLFormat.cxx:32
 TGLFormat.cxx:33
 TGLFormat.cxx:34
 TGLFormat.cxx:35
 TGLFormat.cxx:36
 TGLFormat.cxx:37
 TGLFormat.cxx:38
 TGLFormat.cxx:39
 TGLFormat.cxx:40
 TGLFormat.cxx:41
 TGLFormat.cxx:42
 TGLFormat.cxx:43
 TGLFormat.cxx:44
 TGLFormat.cxx:45
 TGLFormat.cxx:46
 TGLFormat.cxx:47
 TGLFormat.cxx:48
 TGLFormat.cxx:49
 TGLFormat.cxx:50
 TGLFormat.cxx:51
 TGLFormat.cxx:52
 TGLFormat.cxx:53
 TGLFormat.cxx:54
 TGLFormat.cxx:55
 TGLFormat.cxx:56
 TGLFormat.cxx:57
 TGLFormat.cxx:58
 TGLFormat.cxx:59
 TGLFormat.cxx:60
 TGLFormat.cxx:61
 TGLFormat.cxx:62
 TGLFormat.cxx:63
 TGLFormat.cxx:64
 TGLFormat.cxx:65
 TGLFormat.cxx:66
 TGLFormat.cxx:67
 TGLFormat.cxx:68
 TGLFormat.cxx:69
 TGLFormat.cxx:70
 TGLFormat.cxx:71
 TGLFormat.cxx:72
 TGLFormat.cxx:73
 TGLFormat.cxx:74
 TGLFormat.cxx:75
 TGLFormat.cxx:76
 TGLFormat.cxx:77
 TGLFormat.cxx:78
 TGLFormat.cxx:79
 TGLFormat.cxx:80
 TGLFormat.cxx:81
 TGLFormat.cxx:82
 TGLFormat.cxx:83
 TGLFormat.cxx:84
 TGLFormat.cxx:85
 TGLFormat.cxx:86
 TGLFormat.cxx:87
 TGLFormat.cxx:88
 TGLFormat.cxx:89
 TGLFormat.cxx:90
 TGLFormat.cxx:91
 TGLFormat.cxx:92
 TGLFormat.cxx:93
 TGLFormat.cxx:94
 TGLFormat.cxx:95
 TGLFormat.cxx:96
 TGLFormat.cxx:97
 TGLFormat.cxx:98
 TGLFormat.cxx:99
 TGLFormat.cxx:100
 TGLFormat.cxx:101
 TGLFormat.cxx:102
 TGLFormat.cxx:103
 TGLFormat.cxx:104
 TGLFormat.cxx:105
 TGLFormat.cxx:106
 TGLFormat.cxx:107
 TGLFormat.cxx:108
 TGLFormat.cxx:109
 TGLFormat.cxx:110
 TGLFormat.cxx:111
 TGLFormat.cxx:112
 TGLFormat.cxx:113
 TGLFormat.cxx:114
 TGLFormat.cxx:115
 TGLFormat.cxx:116
 TGLFormat.cxx:117
 TGLFormat.cxx:118
 TGLFormat.cxx:119
 TGLFormat.cxx:120
 TGLFormat.cxx:121
 TGLFormat.cxx:122
 TGLFormat.cxx:123
 TGLFormat.cxx:124
 TGLFormat.cxx:125
 TGLFormat.cxx:126
 TGLFormat.cxx:127
 TGLFormat.cxx:128
 TGLFormat.cxx:129
 TGLFormat.cxx:130
 TGLFormat.cxx:131
 TGLFormat.cxx:132
 TGLFormat.cxx:133
 TGLFormat.cxx:134
 TGLFormat.cxx:135
 TGLFormat.cxx:136
 TGLFormat.cxx:137
 TGLFormat.cxx:138
 TGLFormat.cxx:139
 TGLFormat.cxx:140
 TGLFormat.cxx:141
 TGLFormat.cxx:142
 TGLFormat.cxx:143
 TGLFormat.cxx:144
 TGLFormat.cxx:145
 TGLFormat.cxx:146
 TGLFormat.cxx:147
 TGLFormat.cxx:148
 TGLFormat.cxx:149
 TGLFormat.cxx:150
 TGLFormat.cxx:151
 TGLFormat.cxx:152
 TGLFormat.cxx:153
 TGLFormat.cxx:154
 TGLFormat.cxx:155
 TGLFormat.cxx:156
 TGLFormat.cxx:157
 TGLFormat.cxx:158
 TGLFormat.cxx:159
 TGLFormat.cxx:160
 TGLFormat.cxx:161
 TGLFormat.cxx:162
 TGLFormat.cxx:163
 TGLFormat.cxx:164
 TGLFormat.cxx:165
 TGLFormat.cxx:166
 TGLFormat.cxx:167
 TGLFormat.cxx:168
 TGLFormat.cxx:169
 TGLFormat.cxx:170
 TGLFormat.cxx:171
 TGLFormat.cxx:172
 TGLFormat.cxx:173
 TGLFormat.cxx:174
 TGLFormat.cxx:175
 TGLFormat.cxx:176
 TGLFormat.cxx:177
 TGLFormat.cxx:178
 TGLFormat.cxx:179
 TGLFormat.cxx:180
 TGLFormat.cxx:181
 TGLFormat.cxx:182
 TGLFormat.cxx:183
 TGLFormat.cxx:184
 TGLFormat.cxx:185
 TGLFormat.cxx:186
 TGLFormat.cxx:187
 TGLFormat.cxx:188
 TGLFormat.cxx:189
 TGLFormat.cxx:190
 TGLFormat.cxx:191
 TGLFormat.cxx:192
 TGLFormat.cxx:193
 TGLFormat.cxx:194
 TGLFormat.cxx:195
 TGLFormat.cxx:196
 TGLFormat.cxx:197
 TGLFormat.cxx:198
 TGLFormat.cxx:199
 TGLFormat.cxx:200
 TGLFormat.cxx:201
 TGLFormat.cxx:202
 TGLFormat.cxx:203
 TGLFormat.cxx:204
 TGLFormat.cxx:205
 TGLFormat.cxx:206
 TGLFormat.cxx:207
 TGLFormat.cxx:208
 TGLFormat.cxx:209
 TGLFormat.cxx:210
 TGLFormat.cxx:211
 TGLFormat.cxx:212
 TGLFormat.cxx:213
 TGLFormat.cxx:214
 TGLFormat.cxx:215
 TGLFormat.cxx:216
 TGLFormat.cxx:217
 TGLFormat.cxx:218
 TGLFormat.cxx:219
 TGLFormat.cxx:220
 TGLFormat.cxx:221
 TGLFormat.cxx:222
 TGLFormat.cxx:223
 TGLFormat.cxx:224
 TGLFormat.cxx:225
 TGLFormat.cxx:226
 TGLFormat.cxx:227
 TGLFormat.cxx:228
 TGLFormat.cxx:229
 TGLFormat.cxx:230
 TGLFormat.cxx:231
 TGLFormat.cxx:232
 TGLFormat.cxx:233
 TGLFormat.cxx:234
 TGLFormat.cxx:235
 TGLFormat.cxx:236
 TGLFormat.cxx:237
 TGLFormat.cxx:238
 TGLFormat.cxx:239
 TGLFormat.cxx:240
 TGLFormat.cxx:241
 TGLFormat.cxx:242
 TGLFormat.cxx:243
 TGLFormat.cxx:244
 TGLFormat.cxx:245
 TGLFormat.cxx:246
 TGLFormat.cxx:247
 TGLFormat.cxx:248
 TGLFormat.cxx:249
 TGLFormat.cxx:250
 TGLFormat.cxx:251
 TGLFormat.cxx:252
 TGLFormat.cxx:253
 TGLFormat.cxx:254
 TGLFormat.cxx:255
 TGLFormat.cxx:256
 TGLFormat.cxx:257
 TGLFormat.cxx:258
 TGLFormat.cxx:259
 TGLFormat.cxx:260
 TGLFormat.cxx:261
 TGLFormat.cxx:262
 TGLFormat.cxx:263
 TGLFormat.cxx:264
 TGLFormat.cxx:265
 TGLFormat.cxx:266
 TGLFormat.cxx:267
 TGLFormat.cxx:268
 TGLFormat.cxx:269
 TGLFormat.cxx:270
 TGLFormat.cxx:271
 TGLFormat.cxx:272
 TGLFormat.cxx:273
 TGLFormat.cxx:274
 TGLFormat.cxx:275
 TGLFormat.cxx:276
 TGLFormat.cxx:277
 TGLFormat.cxx:278
 TGLFormat.cxx:279
 TGLFormat.cxx:280
 TGLFormat.cxx:281