LCOV - code coverage report
Current view: top level - canvas/source/opengl - ogl_spritedevicehelper.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 0 380 0.0 %
Date: 2014-04-11 Functions: 0 50 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "ogl_spritedevicehelper.hxx"
      11             : #include "ogl_spritecanvas.hxx"
      12             : #include "ogl_canvasbitmap.hxx"
      13             : #include "ogl_canvastools.hxx"
      14             : #include "ogl_canvascustomsprite.hxx"
      15             : #include "ogl_texturecache.hxx"
      16             : 
      17             : #include <canvas/verbosetrace.hxx>
      18             : #include <basegfx/tools/canvastools.hxx>
      19             : #include <basegfx/tools/unopolypolygon.hxx>
      20             : 
      21             : #include <osl/mutex.hxx>
      22             : #include <rtl/instance.hxx>
      23             : #include <com/sun/star/uno/Reference.hxx>
      24             : #include <com/sun/star/lang/NoSupportException.hpp>
      25             : #include <com/sun/star/rendering/XColorSpace.hpp>
      26             : #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
      27             : 
      28             : #include <vcl/sysdata.hxx>
      29             : #include <vcl/syschild.hxx>
      30             : #include <vcl/canvastools.hxx>
      31             : #include <toolkit/helper/vclunohelper.hxx>
      32             : 
      33             : #define GL_GLEXT_PROTOTYPES
      34             : #include <GL/gl.h>
      35             : #include <GL/glu.h>
      36             : #include <GL/glext.h>
      37             : 
      38             : namespace unx
      39             : {
      40             :  #include <X11/keysym.h>
      41             :  #include <X11/X.h>
      42             :  #include <GL/glx.h>
      43             :  #include <GL/glxext.h>
      44             : }
      45             : 
      46             : 
      47             : using namespace ::com::sun::star;
      48             : 
      49             : static bool lcl_bErrorTriggered=false;
      50           0 : static int lcl_XErrorHandler( unx::Display*, unx::XErrorEvent* )
      51             : {
      52           0 :     lcl_bErrorTriggered = true;
      53           0 :     return 0;
      54             : }
      55             : 
      56             : /** Dummy vertex processing. Simply uses default pipeline for vertex
      57             :    transformation, and forwards texture coodinates to fragment shader
      58             :  */
      59             : static const char dummyVertexShader[] =
      60             : {
      61             :     "varying vec2 v_textureCoords2d;                                            "
      62             :     "void main(void)                                                            "
      63             :     "{                                                                          "
      64             :     "    gl_Position = ftransform();                                            "
      65             :     "    v_textureCoords2d = gl_MultiTexCoord0.st;                              "
      66             :     "}                                                                          "
      67             : };
      68             : 
      69             : /** Two-color linear gradient
      70             :  */
      71             : static const char linearTwoColorGradientFragmentShader[] =
      72             : {
      73             :     "#version 120                                                            \n"
      74             :     "uniform vec4   v_startColor4d;                                            "
      75             :     "uniform vec4   v_endColor4d;                                              "
      76             :     "uniform mat3x2 m_transform;                                               "
      77             :     "varying vec2   v_textureCoords2d;                                         "
      78             :     "void main(void)                                                           "
      79             :     "{                                                                         "
      80             :     "    gl_FragColor = mix(v_startColor4d,                                    "
      81             :     "                       v_endColor4d,                                      "
      82             :     "                       clamp(                                             "
      83             :     "                          (m_transform * vec3(v_textureCoords2d,1)).s,    "
      84             :     "                          0.0, 1.0));                                     "
      85             :     "}                                                                         "
      86             : };
      87             : 
      88             : /** N-color linear gradient
      89             :  */
      90             : static const char linearMultiColorGradientFragmentShader[] =
      91             : {
      92             :     "#version 120                                                            \n"
      93             :     "uniform int       i_nColors;                                              "
      94             :     "uniform sampler1D t_colorArray4d;                                         "
      95             :     "uniform sampler1D t_stopArray1d;                                          "
      96             :     "uniform mat3x2    m_transform;                                            "
      97             :     "varying vec2      v_textureCoords2d;                                      "
      98             :     "                                                                          "
      99             :     "int findBucket(float t)                                                   "
     100             :     "{                                                                         "
     101             :     "    int nMinBucket=0;                                                     "
     102             :     "    while( nMinBucket < i_nColors &&                                      "
     103             :     "           texture1D(t_stopArray1d, nMinBucket).s < t )                   "
     104             :     "        ++nMinBucket;                                                     "
     105             :     "    return max(nMinBucket-1,0);                                           "
     106             :     "}                                                                         "
     107             :     "                                                                          "
     108             :     "void main(void)                                                           "
     109             :     "{                                                                         "
     110             :     "    const float fAlpha =                                                  "
     111             :     "        clamp( (m_transform * vec3(v_textureCoords2d,1)).s,               "
     112             :     "               0.0, 1.0 );                                                "
     113             :     "                                                                          "
     114             :     "    const int nMinBucket=findBucket( fAlpha );                            "
     115             :     "                                                                          "
     116             :     "    const float fLerp =                                                   "
     117             :     "        (fAlpha-texture1D(t_stopArray1d, nMinBucket).s) /                 "
     118             :     "        (texture1D(t_stopArray1d, nMinBucket+1).s -                       "
     119             :     "         texture1D(t_stopArray1d, nMinBucket).s);                         "
     120             :     "                                                                          "
     121             :     "    gl_FragColor = mix(texture1D(t_colorArray4d, nMinBucket),             "
     122             :     "                       texture1D(t_colorArray4d, nMinBucket+1),           "
     123             :     "                       fLerp);                                            "
     124             :     "}                                                                         "
     125             : };
     126             : 
     127             : /** Two-color radial gradient
     128             :  */
     129             : static const char radialTwoColorGradientFragmentShader[] =
     130             : {
     131             :     "#version 120                                                             \n"
     132             :     "uniform vec4   v_startColor4d;                                             "
     133             :     "uniform vec4   v_endColor4d;                                               "
     134             :     "uniform mat3x2 m_transform;                                                "
     135             :     "varying vec2   v_textureCoords2d;                                          "
     136             :     "const vec2     v_center2d = vec2(0,0);                                     "
     137             :     "void main(void)                                                            "
     138             :     "{                                                                          "
     139             :     "    gl_FragColor = mix(v_startColor4d,                                     "
     140             :     "                       v_endColor4d,                                       "
     141             :     "                       1.0 - distance(                                     "
     142             :     "                          vec2(                                            "
     143             :     "                             m_transform * vec3(v_textureCoords2d,1)),     "
     144             :     "                          v_center2d));                                    "
     145             :     "}                                                                          "
     146             : };
     147             : 
     148             : /** Multi-color radial gradient
     149             :  */
     150             : static const char radialMultiColorGradientFragmentShader[] =
     151             : {
     152             :     "#version 120                                                             \n"
     153             :     "uniform int       i_nColors;                                              "
     154             :     "uniform sampler1D t_colorArray4d;                                         "
     155             :     "uniform sampler1D t_stopArray1d;                                          "
     156             :     "uniform mat3x2    m_transform;                                            "
     157             :     "varying vec2      v_textureCoords2d;                                      "
     158             :     "const vec2        v_center2d = vec2(0,0);                                 "
     159             :     "                                                                          "
     160             :     "int findBucket(float t)                                                   "
     161             :     "{                                                                         "
     162             :     "    int nMinBucket=0;                                                     "
     163             :     "    while( nMinBucket < i_nColors &&                                      "
     164             :     "           texture1D(t_stopArray1d, nMinBucket).s < t )                   "
     165             :     "        ++nMinBucket;                                                     "
     166             :     "    return max(nMinBucket-1,0);                                           "
     167             :     "}                                                                         "
     168             :     "                                                                          "
     169             :     "void main(void)                                                           "
     170             :     "{                                                                         "
     171             :     "    const float fAlpha =                                                  "
     172             :     "        clamp( 1.0 - distance(                                            "
     173             :     "               vec2( m_transform * vec3(v_textureCoords2d,1)),            "
     174             :     "                     v_center2d),                                         "
     175             :     "               0.0, 1.0 );                                                "
     176             :     "                                                                          "
     177             :     "    const int nMinBucket=findBucket( fAlpha );                            "
     178             :     "                                                                          "
     179             :     "    const float fLerp =                                                   "
     180             :     "        (fAlpha-texture1D(t_stopArray1d, nMinBucket).s) /                 "
     181             :     "        (texture1D(t_stopArray1d, nMinBucket+1).s -                       "
     182             :     "         texture1D(t_stopArray1d, nMinBucket).s);                         "
     183             :     "                                                                          "
     184             :     "    gl_FragColor = mix(texture1D(t_colorArray4d, nMinBucket),             "
     185             :     "                       texture1D(t_colorArray4d, nMinBucket+1),           "
     186             :     "                       fLerp);                                            "
     187             :     "}                                                                         "
     188             : };
     189             : 
     190             : /** Two-color rectangular gradient
     191             :  */
     192             : static const char rectangularTwoColorGradientFragmentShader[] =
     193             : {
     194             :     "#version 120                                                             \n"
     195             :     "uniform vec4   v_startColor4d;                                             "
     196             :     "uniform vec4   v_endColor4d;                                               "
     197             :     "uniform mat3x2 m_transform;                                                "
     198             :     "varying vec2   v_textureCoords2d;                                          "
     199             :     "void main(void)                                                            "
     200             :     "{                                                                          "
     201             :     "    const vec2 v = abs( vec2(m_transform * vec3(v_textureCoords2d,1)) );   "
     202             :     "    const float t = max(v.x, v.y);                                         "
     203             :     "    gl_FragColor = mix(v_startColor4d,                                     "
     204             :     "                       v_endColor4d,                                       "
     205             :     "                       1.0-t);                                             "
     206             :     "}                                                                          "
     207             : };
     208             : 
     209             : /** Multi-color rectangular gradient
     210             :  */
     211             : static const char rectangularMultiColorGradientFragmentShader[] =
     212             : {
     213             :     "#version 120                                                             \n"
     214             :     "uniform int       i_nColors;                                              "
     215             :     "uniform sampler1D t_colorArray4d;                                         "
     216             :     "uniform sampler1D t_stopArray1d;                                          "
     217             :     "uniform mat3x2    m_transform;                                            "
     218             :     "varying vec2      v_textureCoords2d;                                      "
     219             :     "                                                                          "
     220             :     "int findBucket(float t)                                                   "
     221             :     "{                                                                         "
     222             :     "    int nMinBucket=0;                                                     "
     223             :     "    while( nMinBucket < i_nColors &&                                      "
     224             :     "           texture1D(t_stopArray1d, nMinBucket).s < t )                   "
     225             :     "        ++nMinBucket;                                                     "
     226             :     "    return max(nMinBucket-1,0);                                           "
     227             :     "}                                                                         "
     228             :     "                                                                          "
     229             :     "void main(void)                                                           "
     230             :     "{                                                                         "
     231             :     "    const vec2  v = abs( vec2(m_transform * vec3(v_textureCoords2d,1)) ); "
     232             :     "    const float fAlpha = 1 - max(v.x, v.y);                               "
     233             :     "                                                                          "
     234             :     "    const int nMinBucket=findBucket( fAlpha );                            "
     235             :     "                                                                          "
     236             :     "    const float fLerp =                                                   "
     237             :     "        (fAlpha-texture1D(t_stopArray1d, nMinBucket).s) /                 "
     238             :     "        (texture1D(t_stopArray1d, nMinBucket+1).s -                       "
     239             :     "         texture1D(t_stopArray1d, nMinBucket).s);                         "
     240             :     "                                                                          "
     241             :     "    gl_FragColor = mix(texture1D(t_colorArray4d, nMinBucket),             "
     242             :     "                       texture1D(t_colorArray4d, nMinBucket+1),           "
     243             :     "                       fLerp);                                            "
     244             :     "}                                                                         "
     245             : };
     246             : 
     247           0 : static void initContext()
     248             : {
     249             :     // need the backside for mirror effects
     250           0 :     glDisable(GL_CULL_FACE);
     251             : 
     252             :     // no perspective, we're 2D
     253           0 :     glMatrixMode(GL_PROJECTION);
     254           0 :     glLoadIdentity();
     255             : 
     256             :     // misc preferences
     257           0 :     glEnable(GL_POINT_SMOOTH);
     258           0 :     glEnable(GL_LINE_SMOOTH);
     259           0 :     glEnable(GL_POLYGON_SMOOTH);
     260           0 :     glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
     261           0 :     glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
     262           0 :     glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
     263           0 :     glShadeModel(GL_FLAT);
     264           0 : }
     265             : 
     266           0 : static void initTransformation(const ::Size& rSize, bool bMirror=false)
     267             : {
     268             :     // use whole window
     269             :     glViewport( 0,0,
     270           0 :                 (GLsizei)rSize.Width(),
     271           0 :                 (GLsizei)rSize.Height() );
     272             : 
     273             :     // model coordinate system is already in device pixel
     274           0 :     glMatrixMode(GL_MODELVIEW);
     275           0 :     glLoadIdentity();
     276           0 :     glTranslated(-1.0, (bMirror ? -1.0 : 1.0), 0.0);
     277           0 :     glScaled( 2.0  / rSize.Width(),
     278           0 :               (bMirror ? 2.0 : -2.0) / rSize.Height(),
     279           0 :               1.0 );
     280             : 
     281             :     // clear to black
     282           0 :     glClearColor(0,0,0,0);
     283           0 :     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     284           0 : }
     285             : 
     286           0 : static boost::shared_ptr<SystemChildWindow> createChildWindow( unx::XVisualInfo*& viWin,
     287             :                                                                unx::XVisualInfo*& viPB,
     288             :                                                                void*&             fbConfig,
     289             :                                                                Window&            rWindow,
     290             :                                                                unx::Display*      pDisplay,
     291             :                                                                int                nScreen )
     292             : {
     293             :     // select appropriate visual
     294             :     static int winAttrList3[] =
     295             :         {
     296             :             GLX_RGBA,//only TrueColor or DirectColor
     297             :             //single buffered
     298             :             GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
     299             :             GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
     300             :             GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
     301             :             GLX_DEPTH_SIZE,0,//no depth buffer
     302             :             None
     303             :         };
     304             :     static int pBufAttrList3[] =
     305             :         {
     306             :             GLX_DOUBLEBUFFER,False,// never doublebuffer pbuffer
     307             :             GLX_RED_SIZE,4,//use the maximum red bits, with a minimum of 4 bits
     308             :             GLX_GREEN_SIZE,4,//use the maximum green bits, with a minimum of 4 bits
     309             :             GLX_BLUE_SIZE,4,//use the maximum blue bits, with a minimum of 4 bits
     310             :             GLX_ALPHA_SIZE,4,
     311             :             GLX_DEPTH_SIZE,0,//no depth buffer
     312             :             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
     313             :             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
     314             :             None
     315             :         };
     316             :     static int winAttrList2[] =
     317             :         {
     318             :             GLX_RGBA,//only TrueColor or DirectColor
     319             :             /// single buffered
     320             :             GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
     321             :             GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
     322             :             GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
     323             :             GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
     324             :             None
     325             :         };
     326             :     static int pBufAttrList2[] =
     327             :         {
     328             :             GLX_DOUBLEBUFFER,False,// never doublebuffer pbuffer
     329             :             GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
     330             :             GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
     331             :             GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
     332             :             GLX_ALPHA_SIZE,4,
     333             :             GLX_DEPTH_SIZE,1,/// use the maximum depth bits, making sure there is a depth buffer
     334             :             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
     335             :             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
     336             :             None
     337             :         };
     338             :     static int winAttrList1[] =
     339             :         {
     340             :             GLX_RGBA,//only TrueColor or DirectColor
     341             :             GLX_DOUBLEBUFFER,/// only double buffer
     342             :             GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
     343             :             GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
     344             :             GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
     345             :             GLX_DEPTH_SIZE,0,/// no depth buffer
     346             :             None
     347             :         };
     348             :     static int pBufAttrList1[] =
     349             :         {
     350             :             GLX_DOUBLEBUFFER,False,// never doublebuffer pbuffer
     351             :             GLX_RED_SIZE,4,/// use the maximum red bits, with a minimum of 4 bits
     352             :             GLX_GREEN_SIZE,4,/// use the maximum green bits, with a minimum of 4 bits
     353             :             GLX_BLUE_SIZE,4,/// use the maximum blue bits, with a minimum of 4 bits
     354             :             GLX_ALPHA_SIZE,4,
     355             :             GLX_DEPTH_SIZE,0,/// no depth buffer
     356             :             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
     357             :             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
     358             :             None
     359             :         };
     360             :     static int winAttrList0[] =
     361             :         {
     362             :             GLX_RGBA,//only TrueColor or DirectColor
     363             :             GLX_DOUBLEBUFFER,// only double buffer
     364             :             GLX_RED_SIZE,4,// use the maximum red bits, with a minimum of 4 bits
     365             :             GLX_GREEN_SIZE,4,// use the maximum green bits, with a minimum of 4 bits
     366             :             GLX_BLUE_SIZE,4,// use the maximum blue bits, with a minimum of 4 bits
     367             :             GLX_DEPTH_SIZE,1,// use the maximum depth bits, making sure there is a depth buffer
     368             :             None
     369             :         };
     370             :     static int pBufAttrList0[] =
     371             :         {
     372             :             GLX_DOUBLEBUFFER,False,// never doublebuffer pbuffer
     373             :             GLX_RED_SIZE,4,// use the maximum red bits, with a minimum of 4 bits
     374             :             GLX_GREEN_SIZE,4,// use the maximum green bits, with a minimum of 4 bits
     375             :             GLX_BLUE_SIZE,4,// use the maximum blue bits, with a minimum of 4 bits
     376             :             GLX_ALPHA_SIZE,4,
     377             :             GLX_DEPTH_SIZE,1,// use the maximum depth bits, making sure there is a depth buffer
     378             :             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
     379             :             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
     380             :             None
     381             :         };
     382             :     static int* winAttrTable[] =
     383             :         {
     384             :             winAttrList0,
     385             :             winAttrList1,
     386             :             winAttrList2,
     387             :             winAttrList3,
     388             :             NULL
     389             :         };
     390             :     static int* pBufAttrTable[] =
     391             :         {
     392             :             pBufAttrList0,
     393             :             pBufAttrList1,
     394             :             pBufAttrList2,
     395             :             pBufAttrList3,
     396             :             NULL
     397             :         };
     398           0 :     int** pWinAttributeTable = winAttrTable;
     399           0 :     int** pBufAttributeTable = pBufAttrTable;
     400             : 
     401           0 :     boost::shared_ptr<SystemChildWindow> pResult;
     402           0 :     unx::GLXFBConfig* fbConfigs=NULL;
     403             :     int nConfigs, nVal;
     404           0 :     while( *pWinAttributeTable && *pBufAttributeTable )
     405             :     {
     406             :         // try to find a window visual for the current set of
     407             :         // attributes
     408             :         viWin = unx::glXChooseVisual( pDisplay,
     409             :                                       nScreen,
     410           0 :                                       *pWinAttributeTable );
     411           0 :         if( viWin )
     412             :         {
     413             :             // try to find a framebuffer config for the current set of
     414             :             // attributes
     415             :             fbConfigs = glXChooseFBConfig( pDisplay,
     416             :                                            nScreen,
     417             :                                            *pBufAttributeTable,
     418           0 :                                            &nConfigs );
     419             :             // don't use glXGetFBConfigs, that does not list alpha-configs
     420             :             // fbConfigs = unx::glXGetFBConfigs(pDisplay, nScreen, &nConfigs);
     421           0 :             for(int i=0; i<nConfigs; i++)
     422             :             {
     423           0 :                 viPB = glXGetVisualFromFBConfig(pDisplay, fbConfigs[i]);
     424           0 :                 if( viPB && viPB->visualid != viWin->visualid )
     425             :                 {
     426             :                     glXGetFBConfigAttrib(pDisplay,
     427           0 :                                          fbConfigs[i],
     428             :                                          GLX_DRAWABLE_TYPE,
     429           0 :                                          &nVal);
     430             : 
     431           0 :                     if( (GLX_PBUFFER_BIT|GLX_WINDOW_BIT|GLX_PIXMAP_BIT)
     432           0 :                         == (nVal & (GLX_PBUFFER_BIT|GLX_WINDOW_BIT|GLX_PIXMAP_BIT)) )
     433             :                     {
     434             :                         SystemWindowData winData;
     435           0 :                         winData.nSize = sizeof(winData);
     436             :                         SAL_INFO("canvas.ogl", "using VisualID " << viWin->visualid << " for OpenGL canvas");
     437           0 :                         winData.pVisual = (void*)(viWin->visual);
     438           0 :                         pResult.reset( new SystemChildWindow(&rWindow, 0, &winData, false) );
     439             : 
     440           0 :                         if( pResult->GetSystemData() )
     441             :                         {
     442           0 :                             fbConfig = &fbConfigs[i];
     443           0 :                             return pResult;
     444             :                         }
     445             : 
     446           0 :                         pResult.reset();
     447             :                     }
     448             : 
     449           0 :                     XFree(viPB);
     450             :                 }
     451             :             }
     452             : 
     453           0 :             XFree(viWin);
     454             :         }
     455             : 
     456           0 :         ++pWinAttributeTable;
     457           0 :         ++pBufAttributeTable;
     458             :     }
     459             : 
     460           0 :     return pResult;
     461             : }
     462             : 
     463             : 
     464             : namespace oglcanvas
     465             : {
     466             :     /** Compile shader program
     467             : 
     468             :         Code courtesy rodo
     469             :      */
     470           0 :     void SpriteDeviceHelper::compileShader(unsigned int& o_rShaderHandle,
     471             :                                            unsigned int  eShaderType,
     472             :                                            const char*   pShaderSourceCode)
     473             :     {
     474             :         GLint nCompileStatus;
     475             :         char log[1024];
     476             : 
     477           0 :         o_rShaderHandle = glCreateShader( eShaderType );
     478           0 :         glShaderSource( o_rShaderHandle, 1, &pShaderSourceCode, NULL );
     479           0 :         glCompileShader( o_rShaderHandle );
     480           0 :         glGetShaderInfoLog( o_rShaderHandle, sizeof(log), NULL, log );
     481             :         SAL_INFO("canvas.ogl", "shader compile log: " << log);
     482             : 
     483           0 :         glGetShaderiv( o_rShaderHandle, GL_COMPILE_STATUS, &nCompileStatus );
     484           0 :         if( !nCompileStatus )
     485             :         {
     486           0 :             glDeleteShader(o_rShaderHandle);
     487           0 :             o_rShaderHandle=0;
     488             :         }
     489           0 :     }
     490             : 
     491             :     /** Link vertex & fragment shaders
     492             : 
     493             :         Code courtesy rodo
     494             :      */
     495           0 :     void SpriteDeviceHelper::linkShaders(unsigned int& o_rProgramHandle,
     496             :                                          unsigned int  nVertexProgramId,
     497             :                                          unsigned int  nFragmentProgramId)
     498             :     {
     499           0 :         if( !nVertexProgramId || !nFragmentProgramId )
     500           0 :             return;
     501             : 
     502           0 :         o_rProgramHandle = glCreateProgram();
     503           0 :         glAttachShader( o_rProgramHandle, nVertexProgramId );
     504           0 :         glAttachShader( o_rProgramHandle, nFragmentProgramId );
     505             : 
     506             :         char log[1024];
     507             :         GLint nProgramLinked;
     508             : 
     509           0 :         glLinkProgram( o_rProgramHandle );
     510           0 :         glGetProgramInfoLog( o_rProgramHandle, sizeof(log), NULL, log );
     511             :         SAL_INFO("canvas.ogl", "shader program link log: " << log);
     512           0 :         glGetProgramiv( o_rProgramHandle, GL_LINK_STATUS, &nProgramLinked );
     513             : 
     514           0 :         if( !nProgramLinked )
     515             :         {
     516           0 :             glDeleteProgram(o_rProgramHandle);
     517           0 :             o_rProgramHandle=0;
     518             :         }
     519             :     }
     520             : 
     521           0 :     SpriteDeviceHelper::SpriteDeviceHelper() :
     522             :         mpDevice(NULL),
     523             :         mpSpriteCanvas(NULL),
     524             :         maActiveSprites(),
     525             :         maLastUpdate(),
     526             :         mpChildWindow(),
     527             :         mpDisplay(NULL),
     528             :         mpGLContext(NULL),
     529             :         mpGLPBufContext(NULL),
     530             :         mpFBConfig(NULL),
     531           0 :         mpTextureCache(new TextureCache()),
     532             :         mnDummyVertexProgram(0),
     533             :         mnLinearTwoColorGradientFragmentProgram(0),
     534             :         mnLinearMultiColorGradientFragmentProgram(0),
     535             :         mnRadialTwoColorGradientFragmentProgram(0),
     536             :         mnRadialMultiColorGradientFragmentProgram(0),
     537             :         mnRectangularTwoColorGradientFragmentProgram(0),
     538             :         mnRectangularMultiColorGradientFragmentProgram(0),
     539             :         mnLinearTwoColorGradientProgram(0),
     540             :         mnLinearMultiColorGradientProgram(0),
     541             :         mnRadialTwoColorGradientProgram(0),
     542             :         mnRadialMultiColorGradientProgram(0),
     543             :         mnRectangularTwoColorGradientProgram(0),
     544           0 :         mnRectangularMultiColorGradientProgram(0)
     545           0 :     {}
     546             : 
     547           0 :     void SpriteDeviceHelper::init( Window&               rWindow,
     548             :                                    SpriteCanvas&         rSpriteCanvas,
     549             :                                    const awt::Rectangle& rViewArea )
     550             :     {
     551           0 :         mpSpriteCanvas = &rSpriteCanvas;
     552             : 
     553             :         rSpriteCanvas.setWindow(
     554             :             uno::Reference<awt::XWindow2>(
     555             :                 VCLUnoHelper::GetInterface(&rWindow),
     556           0 :                 uno::UNO_QUERY_THROW) );
     557             : 
     558             :         // init OpenGL
     559           0 :         const SystemEnvData* sysData(rWindow.GetSystemData());
     560           0 :         unx::Display* pDisplay=reinterpret_cast<unx::Display*>(sysData->pDisplay);
     561           0 :         mpDisplay=pDisplay;
     562           0 :         if( !unx::glXQueryExtension(pDisplay, NULL, NULL) )
     563           0 :             return;
     564             : 
     565           0 :         unx::Window xWindow = sysData->aWindow;
     566             :         unx::XWindowAttributes xAttr;
     567           0 :         unx::XGetWindowAttributes( pDisplay, xWindow, &xAttr );
     568           0 :         int nScreen = XScreenNumberOfScreen( xAttr.screen );
     569             : 
     570           0 :         unx::Window childXWindow=0;
     571           0 :         unx::XVisualInfo* viWin=NULL;
     572           0 :         unx::XVisualInfo* viPB=NULL;
     573           0 :         mpChildWindow=createChildWindow(viWin,viPB,mpFBConfig,
     574           0 :                                         rWindow,pDisplay,nScreen);
     575             : 
     576             :         // tweak SysChild window to act as an input-transparent
     577             :         // overlay
     578           0 :         if( mpChildWindow )
     579             :         {
     580           0 :             childXWindow=mpChildWindow->GetSystemData()->aWindow;
     581           0 :             mpChildWindow->SetMouseTransparent(true);
     582           0 :             mpChildWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
     583           0 :             mpChildWindow->EnableEraseBackground(false);
     584           0 :             mpChildWindow->SetControlForeground();
     585           0 :             mpChildWindow->SetControlBackground();
     586           0 :             mpChildWindow->EnablePaint(false);
     587             : 
     588             :             unx::GLXContext pContext1 =
     589             :                 glXCreateContext(pDisplay,
     590             :                                  viWin,
     591             :                                  0,
     592           0 :                                  GL_TRUE);
     593           0 :             mpGLContext = pContext1;
     594             : 
     595             :             unx::GLXContext pContext2 =
     596             :                 glXCreateContext( pDisplay,
     597             :                                   viPB,
     598             :                                   pContext1,
     599           0 :                                   GL_TRUE );
     600           0 :             mpGLPBufContext = pContext2;
     601             : 
     602           0 :             XFree(viWin);
     603           0 :             XFree(viPB);
     604             : 
     605           0 :             if( !glXMakeCurrent( pDisplay,
     606             :                                  childXWindow,
     607           0 :                                  pContext1) )
     608             :             {
     609           0 :                 glXDestroyContext(pDisplay, pContext1);
     610           0 :                 glXDestroyContext(pDisplay, pContext2);
     611           0 :                 throw lang::NoSupportException("Could not select OpenGL context!", NULL);
     612             :             }
     613             : 
     614           0 :             const GLubyte* extensions=glGetString( GL_EXTENSIONS );
     615           0 :             if( gluCheckExtension((const GLubyte*)"GLX_SGI_swap_control", extensions) )
     616             :             {
     617             :                 // try to enable vsync
     618             :                 typedef GLint (*glXSwapIntervalProc)(GLint);
     619             :                 glXSwapIntervalProc glXSwapInterval =
     620           0 :                     (glXSwapIntervalProc) unx::glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI");
     621           0 :                 if( glXSwapInterval )
     622             :                 {
     623             :                     int (*oldHandler)(unx::Display*, unx::XErrorEvent*);
     624             : 
     625             :                     // synchronize on global mutex - no other ogl
     626             :                     // canvas instance permitted to enter here
     627             :                     {
     628           0 :                         ::osl::MutexGuard aGuard( *::osl::Mutex::getGlobalMutex() );
     629             : 
     630             :                         // replace error handler temporarily
     631           0 :                         oldHandler = unx::XSetErrorHandler( lcl_XErrorHandler );
     632             : 
     633           0 :                         lcl_bErrorTriggered = false;
     634             : 
     635             :                         // Note: if this fails, so be it. Buggy
     636             :                         // drivers will then not have vsync.
     637           0 :                         glXSwapInterval(1);
     638             : 
     639             :                         // sync so that we possibly get an XError
     640           0 :                         unx::glXWaitGL();
     641           0 :                         XSync(pDisplay, false);
     642             : 
     643           0 :                         unx::XSetErrorHandler( oldHandler );
     644             :                     }
     645             :                 }
     646             :             }
     647             : 
     648             :             // init window context
     649           0 :             initContext();
     650             : 
     651             :             // compile & link shaders - code courtesy rodo
     652             :             compileShader(mnDummyVertexProgram,
     653             :                           GL_VERTEX_SHADER,
     654           0 :                           dummyVertexShader);
     655             :             compileShader(mnLinearTwoColorGradientFragmentProgram,
     656             :                           GL_FRAGMENT_SHADER,
     657           0 :                           linearTwoColorGradientFragmentShader);
     658             :             compileShader(mnLinearMultiColorGradientFragmentProgram,
     659             :                           GL_FRAGMENT_SHADER,
     660           0 :                           linearMultiColorGradientFragmentShader);
     661             :             compileShader(mnRadialTwoColorGradientFragmentProgram,
     662             :                           GL_FRAGMENT_SHADER,
     663           0 :                           radialTwoColorGradientFragmentShader);
     664             :             compileShader(mnRadialMultiColorGradientFragmentProgram,
     665             :                           GL_FRAGMENT_SHADER,
     666           0 :                           radialMultiColorGradientFragmentShader);
     667             :             compileShader(mnRectangularTwoColorGradientFragmentProgram,
     668             :                           GL_FRAGMENT_SHADER,
     669           0 :                           rectangularTwoColorGradientFragmentShader);
     670             :             compileShader(mnRectangularMultiColorGradientFragmentProgram,
     671             :                           GL_FRAGMENT_SHADER,
     672           0 :                           rectangularMultiColorGradientFragmentShader);
     673             :             linkShaders(mnLinearTwoColorGradientProgram,
     674             :                         mnDummyVertexProgram,
     675           0 :                         mnLinearTwoColorGradientFragmentProgram);
     676             :             linkShaders(mnLinearMultiColorGradientProgram,
     677             :                         mnDummyVertexProgram,
     678           0 :                         mnLinearMultiColorGradientFragmentProgram);
     679             :             linkShaders(mnRadialTwoColorGradientProgram,
     680             :                         mnDummyVertexProgram,
     681           0 :                         mnRadialTwoColorGradientFragmentProgram);
     682             :             linkShaders(mnRadialMultiColorGradientProgram,
     683             :                         mnDummyVertexProgram,
     684           0 :                         mnRadialMultiColorGradientFragmentProgram);
     685             :             linkShaders(mnRectangularTwoColorGradientProgram,
     686             :                         mnDummyVertexProgram,
     687           0 :                         mnRectangularTwoColorGradientFragmentProgram);
     688             :             linkShaders(mnRectangularMultiColorGradientProgram,
     689             :                         mnDummyVertexProgram,
     690           0 :                         mnRectangularMultiColorGradientFragmentProgram);
     691             : 
     692           0 :             glXMakeCurrent(pDisplay, None, NULL);
     693             :         }
     694             : 
     695           0 :         if( !mpGLContext || glGetError() != GL_NO_ERROR )
     696             :             throw lang::NoSupportException(
     697           0 :                 "Could not create OpenGL context, or an error occurred doing so!", NULL);
     698             : 
     699           0 :         notifySizeUpdate(rViewArea);
     700           0 :         mpChildWindow->Show();
     701             :         // TODO(E3): check for GL_ARB_imaging extension
     702             :     }
     703             : 
     704           0 :     void SpriteDeviceHelper::disposing()
     705             :     {
     706             :         // release all references
     707           0 :         mpSpriteCanvas = NULL;
     708           0 :         mpDevice = NULL;
     709           0 :         mpTextureCache.reset();
     710             : 
     711           0 :         if( mpGLContext )
     712             :         {
     713           0 :             glDeleteProgram( mnRectangularTwoColorGradientProgram );
     714           0 :             glDeleteProgram( mnRectangularMultiColorGradientProgram );
     715           0 :             glDeleteProgram( mnRadialTwoColorGradientProgram );
     716           0 :             glDeleteProgram( mnRadialMultiColorGradientProgram );
     717           0 :             glDeleteProgram( mnLinearTwoColorGradientProgram );
     718           0 :             glDeleteProgram( mnLinearMultiColorGradientProgram );
     719           0 :             glDeleteShader( mnRectangularTwoColorGradientFragmentProgram );
     720           0 :             glDeleteShader( mnRectangularMultiColorGradientFragmentProgram );
     721           0 :             glDeleteShader( mnRadialTwoColorGradientFragmentProgram );
     722           0 :             glDeleteShader( mnRadialMultiColorGradientFragmentProgram );
     723           0 :             glDeleteShader( mnLinearTwoColorGradientFragmentProgram );
     724           0 :             glDeleteShader( mnLinearMultiColorGradientFragmentProgram );
     725           0 :             glDeleteShader( mnDummyVertexProgram );
     726             : 
     727             :             glXDestroyContext(reinterpret_cast<unx::Display*>(mpDisplay),
     728           0 :                               reinterpret_cast<unx::GLXContext>(mpGLContext));
     729             :         }
     730             : 
     731           0 :         mpDisplay = NULL;
     732           0 :         mpGLContext = NULL;
     733           0 :         mpChildWindow.reset();
     734           0 :     }
     735             : 
     736           0 :     geometry::RealSize2D SpriteDeviceHelper::getPhysicalResolution()
     737             :     {
     738           0 :         if( !mpChildWindow )
     739           0 :             return ::canvas::tools::createInfiniteSize2D(); // we're disposed
     740             : 
     741             :         // Map a one-by-one millimeter box to pixel
     742           0 :         const MapMode aOldMapMode( mpChildWindow->GetMapMode() );
     743           0 :         mpChildWindow->SetMapMode( MapMode(MAP_MM) );
     744           0 :         const Size aPixelSize( mpChildWindow->LogicToPixel(Size(1,1)) );
     745           0 :         mpChildWindow->SetMapMode( aOldMapMode );
     746             : 
     747           0 :         return ::vcl::unotools::size2DFromSize( aPixelSize );
     748             :     }
     749             : 
     750           0 :     geometry::RealSize2D SpriteDeviceHelper::getPhysicalSize()
     751             :     {
     752           0 :         if( !mpChildWindow )
     753           0 :             return ::canvas::tools::createInfiniteSize2D(); // we're disposed
     754             : 
     755             :         // Map the pixel dimensions of the output window to millimeter
     756           0 :         const MapMode aOldMapMode( mpChildWindow->GetMapMode() );
     757           0 :         mpChildWindow->SetMapMode( MapMode(MAP_MM) );
     758           0 :         const Size aLogSize( mpChildWindow->PixelToLogic(mpChildWindow->GetOutputSizePixel()) );
     759           0 :         mpChildWindow->SetMapMode( aOldMapMode );
     760             : 
     761           0 :         return ::vcl::unotools::size2DFromSize( aLogSize );
     762             :     }
     763             : 
     764           0 :     uno::Reference< rendering::XLinePolyPolygon2D > SpriteDeviceHelper::createCompatibleLinePolyPolygon(
     765             :         const uno::Reference< rendering::XGraphicDevice >&              /*rDevice*/,
     766             :         const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >&  points )
     767             :     {
     768             :         // disposed?
     769           0 :         if( !mpSpriteCanvas )
     770           0 :             return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
     771             : 
     772             :         return uno::Reference< rendering::XLinePolyPolygon2D >(
     773             :             new ::basegfx::unotools::UnoPolyPolygon(
     774           0 :                 ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points )));
     775             :     }
     776             : 
     777           0 :     uno::Reference< rendering::XBezierPolyPolygon2D > SpriteDeviceHelper::createCompatibleBezierPolyPolygon(
     778             :         const uno::Reference< rendering::XGraphicDevice >&                      /*rDevice*/,
     779             :         const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >&  points )
     780             :     {
     781             :         // disposed?
     782           0 :         if( !mpSpriteCanvas )
     783           0 :             return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
     784             : 
     785             :         return uno::Reference< rendering::XBezierPolyPolygon2D >(
     786             :             new ::basegfx::unotools::UnoPolyPolygon(
     787           0 :                 ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
     788             :     }
     789             : 
     790           0 :     uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleBitmap(
     791             :         const uno::Reference< rendering::XGraphicDevice >&  /*rDevice*/,
     792             :         const geometry::IntegerSize2D&                      size )
     793             :     {
     794             :         // disposed?
     795           0 :         if( !mpSpriteCanvas )
     796           0 :             return uno::Reference< rendering::XBitmap >(); // we're disposed
     797             : 
     798             :         return uno::Reference< rendering::XBitmap >(
     799             :             new CanvasBitmap( size,
     800             :                               mpSpriteCanvas,
     801             :                               *this,
     802           0 :                               false ) );
     803             :     }
     804             : 
     805           0 :     uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileBitmap(
     806             :         const uno::Reference< rendering::XGraphicDevice >&  /*rDevice*/,
     807             :         const geometry::IntegerSize2D&                      /*size*/ )
     808             :     {
     809           0 :         return uno::Reference< rendering::XVolatileBitmap >();
     810             :     }
     811             : 
     812           0 :     uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleAlphaBitmap(
     813             :         const uno::Reference< rendering::XGraphicDevice >&  /*rDevice*/,
     814             :         const geometry::IntegerSize2D&                      size )
     815             :     {
     816             :         // disposed?
     817           0 :         if( !mpSpriteCanvas )
     818           0 :             return uno::Reference< rendering::XBitmap >(); // we're disposed
     819             : 
     820             :         return uno::Reference< rendering::XBitmap >(
     821             :             new CanvasBitmap( size,
     822             :                               mpSpriteCanvas,
     823             :                               *this,
     824           0 :                               true ) );
     825             :     }
     826             : 
     827           0 :     uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileAlphaBitmap(
     828             :         const uno::Reference< rendering::XGraphicDevice >&  /*rDevice*/,
     829             :         const geometry::IntegerSize2D&                      /*size*/ )
     830             :     {
     831           0 :         return uno::Reference< rendering::XVolatileBitmap >();
     832             :     }
     833             : 
     834           0 :     sal_Bool SpriteDeviceHelper::hasFullScreenMode()
     835             :     {
     836             :         // TODO(F3): offer fullscreen mode the XCanvas way
     837           0 :         return false;
     838             :     }
     839             : 
     840           0 :     sal_Bool SpriteDeviceHelper::enterFullScreenMode( sal_Bool /*bEnter*/ )
     841             :     {
     842             :         // TODO(F3): offer fullscreen mode the XCanvas way
     843           0 :         return false;
     844             :     }
     845             : 
     846           0 :     ::sal_Int32 SpriteDeviceHelper::createBuffers( ::sal_Int32 /*nBuffers*/ )
     847             :     {
     848             :         // TODO(F3): implement XBufferStrategy interface. For now, we
     849             :         // _always_ will have exactly one backbuffer
     850           0 :         return 1;
     851             :     }
     852             : 
     853           0 :     void SpriteDeviceHelper::destroyBuffers()
     854             :     {
     855             :         // TODO(F3): implement XBufferStrategy interface. For now, we
     856             :         // _always_ will have exactly one backbuffer
     857           0 :     }
     858             : 
     859             :     namespace
     860             :     {
     861             :         /** Functor providing a StrictWeakOrdering for XSprites (over
     862             :             priority)
     863             :          */
     864             :         struct SpriteComparator
     865             :         {
     866           0 :             bool operator()( const ::rtl::Reference<CanvasCustomSprite>& rLHS,
     867             :                              const ::rtl::Reference<CanvasCustomSprite>& rRHS ) const
     868             :             {
     869           0 :                 const double nPrioL( rLHS->getPriority() );
     870           0 :                 const double nPrioR( rRHS->getPriority() );
     871             : 
     872             :                 // if prios are equal, tie-break on ptr value
     873           0 :                 return nPrioL == nPrioR ? rLHS.get() < rRHS.get() : nPrioL < nPrioR;
     874             :             }
     875             :         };
     876             :     }
     877             : 
     878           0 :     sal_Bool SpriteDeviceHelper::showBuffer( bool bIsVisible, sal_Bool /*bUpdateAll*/ )
     879             :     {
     880             :         // hidden or disposed?
     881           0 :         if( !bIsVisible || !mpChildWindow || !mpSpriteCanvas )
     882           0 :             return false;
     883             : 
     884           0 :         if( !activateWindowContext() )
     885           0 :             return false;
     886             : 
     887           0 :         const ::Size& rOutputSize=mpChildWindow->GetSizePixel();
     888           0 :         initTransformation(rOutputSize);
     889             : 
     890             :         // render the actual spritecanvas content
     891           0 :         mpSpriteCanvas->renderRecordedActions();
     892             : 
     893             :         // render all sprites (in order of priority) on top of that
     894           0 :         std::vector< ::rtl::Reference<CanvasCustomSprite> > aSprites;
     895             :         std::copy(maActiveSprites.begin(),
     896             :                   maActiveSprites.end(),
     897             :                   std::back_insert_iterator<
     898           0 :                        std::vector< ::rtl::Reference< CanvasCustomSprite > > >(aSprites));
     899             :         std::sort(aSprites.begin(),
     900             :                   aSprites.end(),
     901           0 :                   SpriteComparator());
     902             :         std::for_each(aSprites.begin(),
     903             :                       aSprites.end(),
     904           0 :                       boost::mem_fn(&CanvasCustomSprite::renderSprite));
     905             : 
     906             : 
     907             :         // frame counter, other info
     908           0 :         glMatrixMode(GL_MODELVIEW);
     909           0 :         glLoadIdentity();
     910           0 :         glTranslated(-1.0, 1.0, 0.0);
     911           0 :         glScaled( 2.0  / rOutputSize.Width(),
     912           0 :                   -2.0 / rOutputSize.Height(),
     913           0 :                   1.0 );
     914             : 
     915           0 :         const double denominator( maLastUpdate.getElapsedTime() );
     916           0 :         maLastUpdate.reset();
     917             : 
     918           0 :         const double fps(denominator == 0.0 ? 100.0 : 1.0/denominator);
     919           0 :         std::vector<double> aVec; aVec.push_back(fps);
     920           0 :         aVec.push_back(maActiveSprites.size());
     921           0 :         aVec.push_back(mpTextureCache->getCacheSize());
     922           0 :         aVec.push_back(mpTextureCache->getCacheMissCount());
     923           0 :         aVec.push_back(mpTextureCache->getCacheHitCount());
     924           0 :         renderOSD( aVec, 20 );
     925             : 
     926             :         // switch buffer, sync etc.
     927           0 :         const unx::Window aXWindow=mpChildWindow->GetSystemData()->aWindow;
     928             :         unx::glXSwapBuffers(reinterpret_cast<unx::Display*>(mpDisplay),
     929           0 :                             aXWindow);
     930           0 :         mpChildWindow->Show();
     931           0 :         unx::glXWaitGL();
     932           0 :         XSync( reinterpret_cast<unx::Display*>(mpDisplay), false );
     933             : 
     934             :         // flush texture cache, such that it does not build up
     935             :         // indefinitely.
     936             :         // TODO: have max cache size/LRU time in config, prune only on
     937             :         // demand
     938           0 :         mpTextureCache->prune();
     939             : 
     940           0 :         return true;
     941             :     }
     942             : 
     943           0 :     sal_Bool SpriteDeviceHelper::switchBuffer( bool bIsVisible, sal_Bool bUpdateAll )
     944             :     {
     945             :         // no difference for VCL canvas
     946           0 :         return showBuffer( bIsVisible, bUpdateAll );
     947             :     }
     948             : 
     949           0 :     uno::Any SpriteDeviceHelper::isAccelerated() const
     950             :     {
     951           0 :         return ::com::sun::star::uno::makeAny(false);
     952             :     }
     953             : 
     954           0 :     uno::Any SpriteDeviceHelper::getDeviceHandle() const
     955             :     {
     956           0 :         return uno::makeAny( reinterpret_cast< sal_Int64 >(mpChildWindow.get()) );
     957             :     }
     958             : 
     959           0 :     uno::Any SpriteDeviceHelper::getSurfaceHandle() const
     960             :     {
     961           0 :         return uno::Any();
     962             :     }
     963             : 
     964           0 :     uno::Reference<rendering::XColorSpace> SpriteDeviceHelper::getColorSpace() const
     965             :     {
     966             :         // always the same
     967             :         return uno::Reference<rendering::XColorSpace>(
     968             :             ::canvas::tools::getStdColorSpace(),
     969           0 :             uno::UNO_QUERY);
     970             :     }
     971             : 
     972           0 :     void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
     973             :     {
     974           0 :         if( mpChildWindow )
     975           0 :             mpChildWindow->setPosSizePixel(
     976           0 :                 0,0,rBounds.Width,rBounds.Height);
     977           0 :     }
     978             : 
     979           0 :     void SpriteDeviceHelper::dumpScreenContent() const
     980             :     {
     981             :         SAL_INFO("canvas.ogl", BOOST_CURRENT_FUNCTION );
     982           0 :     }
     983             : 
     984           0 :     void SpriteDeviceHelper::show( const ::rtl::Reference< CanvasCustomSprite >& xSprite )
     985             :     {
     986           0 :         maActiveSprites.insert(xSprite);
     987           0 :     }
     988             : 
     989           0 :     void SpriteDeviceHelper::hide( const ::rtl::Reference< CanvasCustomSprite >& xSprite )
     990             :     {
     991           0 :         maActiveSprites.erase(xSprite);
     992           0 :     }
     993             : 
     994           0 :     static void setupUniforms( unsigned int                                 nProgramId,
     995             :                                const ::basegfx::B2DHomMatrix&               rTexTransform )
     996             :     {
     997             :         const GLint nTransformLocation = glGetUniformLocation(nProgramId,
     998           0 :                                                              "m_transform" );
     999             :         // OGL is column-major
    1000             :         float aTexTransform[] =
    1001             :             {
    1002           0 :                 float(rTexTransform.get(0,0)), float(rTexTransform.get(1,0)),
    1003           0 :                 float(rTexTransform.get(0,1)), float(rTexTransform.get(1,1)),
    1004           0 :                 float(rTexTransform.get(0,2)), float(rTexTransform.get(1,2))
    1005           0 :             };
    1006           0 :         glUniformMatrix3x2fv(nTransformLocation,1,false,aTexTransform);
    1007           0 :     }
    1008             : 
    1009           0 :     static void setupUniforms( unsigned int                   nProgramId,
    1010             :                                const rendering::ARGBColor*    pColors,
    1011             :                                const uno::Sequence< double >& rStops,
    1012             :                                const ::basegfx::B2DHomMatrix& rTexTransform )
    1013             :     {
    1014           0 :         glUseProgram(nProgramId);
    1015             : 
    1016             :         GLuint nColorsTexture;
    1017           0 :         glActiveTexture(GL_TEXTURE0);
    1018           0 :         glGenTextures(1, &nColorsTexture);
    1019           0 :         glBindTexture(GL_TEXTURE_1D, nColorsTexture);
    1020             : 
    1021           0 :         const sal_Int32 nColors=rStops.getLength();
    1022           0 :         glTexImage1D( GL_TEXTURE_1D, 0, GL_RGBA, nColors, 0, GL_RGBA, GL_DOUBLE, pColors );
    1023           0 :         glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    1024           0 :         glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    1025             : 
    1026             :         GLuint nStopsTexture;
    1027           0 :         glActiveTexture(GL_TEXTURE1);
    1028           0 :         glGenTextures(1, &nStopsTexture);
    1029           0 :         glBindTexture(GL_TEXTURE_1D, nStopsTexture);
    1030             : 
    1031           0 :         glTexImage1D( GL_TEXTURE_1D, 0, GL_ALPHA, nColors, 0, GL_ALPHA, GL_DOUBLE, rStops.getConstArray() );
    1032           0 :         glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    1033           0 :         glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    1034             : 
    1035             :         const GLint nColorArrayLocation = glGetUniformLocation(nProgramId,
    1036           0 :                                                                "t_colorArray4d" );
    1037           0 :         glUniform1i( nColorArrayLocation, 0 ); // unit 0
    1038             : 
    1039             :         const GLint nStopArrayLocation = glGetUniformLocation(nProgramId,
    1040           0 :                                                               "t_stopArray1d" );
    1041           0 :         glUniform1i( nStopArrayLocation, 1 ); // unit 1
    1042             : 
    1043             :         const GLint nNumColorLocation = glGetUniformLocation(nProgramId,
    1044           0 :                                                              "i_nColors" );
    1045           0 :         glUniform1i( nNumColorLocation, nColors-1 );
    1046             : 
    1047           0 :         setupUniforms(nProgramId,rTexTransform);
    1048           0 :     }
    1049             : 
    1050           0 :     static void setupUniforms( unsigned int                   nProgramId,
    1051             :                                const rendering::ARGBColor&    rStartColor,
    1052             :                                const rendering::ARGBColor&    rEndColor,
    1053             :                                const ::basegfx::B2DHomMatrix& rTexTransform )
    1054             :     {
    1055           0 :         glUseProgram(nProgramId);
    1056             : 
    1057             :         const GLint nStartColorLocation = glGetUniformLocation(nProgramId,
    1058           0 :                                                                "v_startColor4d" );
    1059             :         glUniform4f(nStartColorLocation,
    1060             :                     rStartColor.Red,
    1061             :                     rStartColor.Green,
    1062             :                     rStartColor.Blue,
    1063           0 :                     rStartColor.Alpha);
    1064             : 
    1065             :         const GLint nEndColorLocation = glGetUniformLocation(nProgramId,
    1066           0 :                                                              "v_endColor4d" );
    1067             :         glUniform4f(nEndColorLocation,
    1068             :                     rEndColor.Red,
    1069             :                     rEndColor.Green,
    1070             :                     rEndColor.Blue,
    1071           0 :                     rEndColor.Alpha);
    1072             : 
    1073           0 :         setupUniforms(nProgramId,rTexTransform);
    1074           0 :     }
    1075             : 
    1076           0 :     void SpriteDeviceHelper::useLinearGradientShader( const rendering::ARGBColor*    pColors,
    1077             :                                                       const uno::Sequence< double >& rStops,
    1078             :                                                       const ::basegfx::B2DHomMatrix& rTexTransform )
    1079             :     {
    1080           0 :         if( rStops.getLength() > 2 )
    1081           0 :             setupUniforms(mnLinearMultiColorGradientProgram, pColors, rStops, rTexTransform);
    1082             :         else
    1083           0 :             setupUniforms(mnLinearTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
    1084           0 :     }
    1085             : 
    1086           0 :     void SpriteDeviceHelper::useRadialGradientShader( const rendering::ARGBColor*    pColors,
    1087             :                                                       const uno::Sequence< double >& rStops,
    1088             :                                                       const ::basegfx::B2DHomMatrix& rTexTransform )
    1089             :     {
    1090           0 :         if( rStops.getLength() > 2 )
    1091           0 :             setupUniforms(mnRadialMultiColorGradientProgram, pColors, rStops, rTexTransform);
    1092             :         else
    1093           0 :             setupUniforms(mnRadialTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
    1094           0 :     }
    1095             : 
    1096           0 :     void SpriteDeviceHelper::useRectangularGradientShader( const rendering::ARGBColor*    pColors,
    1097             :                                                            const uno::Sequence< double >& rStops,
    1098             :                                                            const ::basegfx::B2DHomMatrix& rTexTransform )
    1099             :     {
    1100           0 :         if( rStops.getLength() > 2 )
    1101           0 :             setupUniforms(mnRectangularMultiColorGradientProgram, pColors, rStops, rTexTransform);
    1102             :         else
    1103           0 :             setupUniforms(mnRectangularTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
    1104           0 :     }
    1105             : 
    1106           0 :     bool SpriteDeviceHelper::activatePBufferContext(const ::basegfx::B2IVector& rSize,
    1107             :                                                     unsigned int                PBuffer) const
    1108             :     {
    1109           0 :         if( !glXMakeCurrent( reinterpret_cast<unx::Display*>(mpDisplay),
    1110             :                              PBuffer,
    1111           0 :                              reinterpret_cast<unx::GLXContext>(mpGLPBufContext)) )
    1112             :         {
    1113             :             SAL_INFO("canvas.ogl", "SpriteDeviceHelper::activatePBufferContext(): cannot activate GL context");
    1114           0 :             return false;
    1115             :         }
    1116             : 
    1117           0 :         initContext();
    1118             :         initTransformation(
    1119             :             ::Size(
    1120             :                 rSize.getX(),
    1121             :                 rSize.getY()),
    1122           0 :             true);
    1123             : 
    1124           0 :         return true;
    1125             :     }
    1126             : 
    1127           0 :     bool SpriteDeviceHelper::activateWindowContext() const
    1128             :     {
    1129           0 :         const unx::Window aXWindow=mpChildWindow->GetSystemData()->aWindow;
    1130           0 :         if( !glXMakeCurrent( reinterpret_cast<unx::Display*>(mpDisplay),
    1131             :                              aXWindow,
    1132           0 :                              reinterpret_cast<unx::GLXContext>(mpGLContext)) )
    1133             :         {
    1134             :             SAL_INFO("canvas.ogl", "SpriteDeviceHelper::activateWindowContext(): cannot activate GL context");
    1135           0 :             return false;
    1136             :         }
    1137             : 
    1138           0 :         return true;
    1139             :     }
    1140             : 
    1141           0 :     bool SpriteDeviceHelper::updatePBufferTexture( const ::basegfx::B2IVector& rSize,
    1142             :                                                    unsigned int                nTextId ) const
    1143             :     {
    1144           0 :         glBindTexture( GL_TEXTURE_2D, nTextId );
    1145           0 :         glEnable(GL_TEXTURE_2D);
    1146             :         glCopyTexSubImage2D( GL_TEXTURE_2D,
    1147             :                              0, 0, 0, 0, 0,
    1148           0 :                              rSize.getX(),
    1149           0 :                              rSize.getY() );
    1150           0 :         glBindTexture(GL_TEXTURE_2D, 0);
    1151             : 
    1152           0 :         return true;
    1153             :     }
    1154             : 
    1155             :     namespace
    1156             :     {
    1157             :         class BufferContextImpl : public IBufferContext
    1158             :         {
    1159             :             ::basegfx::B2IVector       maSize;
    1160             :             const SpriteDeviceHelper&  mrDeviceHelper;
    1161             :             unx::GLXPbuffer            mpPBuffer;
    1162             : #if 0
    1163             :             unx::Display*              mpDisplay;
    1164             : #endif
    1165             :             unsigned int               mnTexture;
    1166             : 
    1167           0 :             virtual bool startBufferRendering() SAL_OVERRIDE
    1168             :             {
    1169           0 :                 return mrDeviceHelper.activatePBufferContext(maSize,mpPBuffer);
    1170             :             }
    1171             : 
    1172           0 :             virtual bool endBufferRendering() SAL_OVERRIDE
    1173             :             {
    1174           0 :                 mrDeviceHelper.updatePBufferTexture(maSize,mnTexture);
    1175           0 :                 if( !mrDeviceHelper.activateWindowContext() )
    1176           0 :                     return false;
    1177             : 
    1178           0 :                 glBindTexture( GL_TEXTURE_2D, mnTexture );
    1179             : 
    1180           0 :                 return true;
    1181             :             }
    1182             : 
    1183             :         public:
    1184           0 :             BufferContextImpl(const SpriteDeviceHelper&   rDeviceHelper,
    1185             :                               unx::GLXPbuffer             pBuffer,
    1186             :                               unx::Display*
    1187             : #if 0
    1188             :                                                           pDisplay
    1189             : #endif
    1190             :                               ,
    1191             :                               const ::basegfx::B2IVector& rSize) :
    1192             :                 maSize(rSize),
    1193             :                 mrDeviceHelper(rDeviceHelper),
    1194             :                 mpPBuffer(pBuffer),
    1195             : #if 0
    1196             :                 mpDisplay(pDisplay),
    1197             : #endif
    1198           0 :                 mnTexture(0)
    1199             :             {
    1200           0 :                 glGenTextures( 1, &mnTexture );
    1201             : #if 1
    1202           0 :                 glBindTexture( GL_TEXTURE_2D, mnTexture );
    1203           0 :                 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    1204           0 :                 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    1205             :                 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
    1206           0 :                               maSize.getX(), maSize.getY(),
    1207           0 :                               0, GL_RGBA, GL_UNSIGNED_BYTE, new int[maSize.getX()*maSize.getY()] );
    1208             : #endif
    1209           0 :             }
    1210             : 
    1211           0 :             virtual ~BufferContextImpl()
    1212           0 :             {
    1213             : #if 0
    1214             :                 glBindTexture(GL_TEXTURE_2D, 0);
    1215             :                 glDeleteTextures( 1, &mnTexture );
    1216             :                 glXDestroyPbuffer( mpDisplay, mpPBuffer );
    1217             : #endif
    1218           0 :             }
    1219             :         };
    1220             :     }
    1221             : 
    1222           0 :     IBufferContextSharedPtr SpriteDeviceHelper::createBufferContext(const ::basegfx::B2IVector& rSize) const
    1223             :     {
    1224             :         int pBufAttribs[] =
    1225             :             {
    1226           0 :                 GLX_PBUFFER_WIDTH,   rSize.getX(),
    1227           0 :                 GLX_PBUFFER_HEIGHT,  rSize.getY(),
    1228             :                 GLX_LARGEST_PBUFFER, False,
    1229             :                 None
    1230           0 :             };
    1231             : 
    1232             :         unx::GLXPbuffer pBuffer;
    1233             :         pBuffer = unx::glXCreatePbuffer( reinterpret_cast<unx::Display*>(mpDisplay),
    1234             :                                          *reinterpret_cast<unx::GLXFBConfig*>(mpFBConfig),
    1235           0 :                                          pBufAttribs );
    1236             : 
    1237           0 :         IBufferContextSharedPtr pRet;
    1238           0 :         if( pBuffer )
    1239             :             pRet.reset(new BufferContextImpl(
    1240             :                            *this,
    1241             :                            pBuffer,
    1242             :                            reinterpret_cast<unx::Display*>(mpDisplay),
    1243           0 :                            rSize));
    1244             : 
    1245           0 :         return pRet;
    1246             :     }
    1247             : 
    1248           0 :     TextureCache& SpriteDeviceHelper::getTextureCache() const
    1249             :     {
    1250           0 :         return *mpTextureCache;
    1251             :     }
    1252           0 : }
    1253             : 
    1254             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10