unixsurf.cpp
Upload User: zhongxx05
Upload Date: 2007-06-06
Package Size: 33641k
Code Size: 30k
Category:

Symbian

Development Platform:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include <errno.h>
  36. #include "hxcom.h"
  37. #include "hxtypes.h"
  38. #include "hxwintyp.h"
  39. #include "hxvsurf.h"
  40. #include "hxslist.h"
  41. #include "hxheap.h"
  42. #include "hxtick.h"
  43. #include "colormap.h"
  44. #include "hxthread.h"
  45. #include "ihxpckts.h"
  46. #include "unixsurf.h"
  47. #include "unixroot.h"
  48. #include "unixsite.h"
  49. #include "basesite.h"
  50. #include "shmhelp.h"
  51. #if defined(_LINUX) && defined(_OVERLAY)
  52. #include "hxprefs.h"
  53. CUnixSurf* CUnixSurf::zm_pXvOwner     = NULL;
  54. #endif
  55. CUnixSurf::CUnixSurf( IUnknown* pContext, CHXBaseSite* pSite )
  56.     : CBaseSurface( pContext, pSite )
  57. #if defined(_LINUX) && defined(_OVERLAY)
  58.     , m_bWallPaperMode(FALSE)
  59.     , m_nPortID(-1)
  60.     , m_nContrast(-9999)
  61.     , m_nBrightness(-9999)
  62.     , m_bPaintClipList(TRUE)
  63.     , m_ulColorKey(0x01020304)
  64.     , m_bStretchToFill(FALSE)
  65.     , m_pXvImage(NULL)
  66.     , m_atomColorKey(None)
  67.     , m_atomClipKey(None)
  68.     , m_atomBrightness(None)
  69.     , m_atomContrast(None)
  70.     , m_ulLastOverlayUpdateTime(0)
  71. #endif
  72.     , m_pcVideoBuf(NULL)
  73.     , m_ulFourCCID(0)
  74.     , m_nVideoPitch(0)
  75.     , m_bUseShm(FALSE)
  76.     , m_display(NULL)
  77.     , m_GC(0)
  78.     , m_nScreenNumber(0)
  79.     , m_shmInfo(NULL)
  80.     , m_nShmId(NULL)
  81.     , m_nCurrentBuffer(0)
  82.     , m_nCompletionEventID(-1)
  83.     , m_nMultiBufferCount(2)
  84. {
  85.     int i=0;
  86.     
  87. #if defined(_LINUX) && defined(_OVERLAY)
  88.     HX_ASSERT( m_pContext );
  89.     IHXPreferences* pPreferences = NULL;   
  90.     if( m_pContext && HXR_OK == m_pContext->QueryInterface( IID_IHXPreferences, (void **) &pPreferences))
  91.     { 
  92.         IHXBuffer *pBuffer = NULL;
  93.         //This makes the overlay appear on the root window....
  94.         //Just for inhouse testing right now...
  95.         pPreferences->ReadPref("OverlayMode", pBuffer);
  96.         if(pBuffer)
  97.         {
  98.             m_bUseOverlays = (::atoi((const char*)pBuffer->GetBuffer()) == 1);
  99.             HX_RELEASE(pBuffer);
  100.         }
  101.         else
  102.         {
  103.             if (pPreferences->ReadPref("UseOverlay", pBuffer) == HXR_OK)
  104.             {
  105.                 m_bUseOverlays = ::atoi((char*) pBuffer->GetBuffer()) == 1;
  106.             }
  107.             HX_RELEASE(pBuffer);
  108.         }
  109.         //This makes the overlay appear on the root window....
  110.         //Just for inhouse testing right now...
  111.         pPreferences->ReadPref("WallPaperMode", pBuffer);
  112.         if (pBuffer)
  113.         {
  114.             m_bWallPaperMode = (::atoi((const char*)pBuffer->GetBuffer()) == 1);
  115.             HX_RELEASE(pBuffer);
  116.         }
  117.         //This is used only when WallPaperMode=1 and stretches the
  118.         //presentation to fill the whole root window NOT preserving
  119.         //aspect ratio.
  120.         pPreferences->ReadPref("StretchToFill", pBuffer);
  121.         if (pBuffer)
  122.         {
  123.             m_bStretchToFill = (::atoi((const char*)pBuffer->GetBuffer()) == 1);
  124.             HX_RELEASE(pBuffer);
  125.         }
  126.         //This is used on ATI cards for debugging. It tells the driver
  127.         //to paint the window with the color key before each blt, or not.
  128.         pPreferences->ReadPref("PaintClipList", pBuffer);
  129.         if (pBuffer)
  130.         {
  131.             m_bPaintClipList = (::atoi((const char*)pBuffer->GetBuffer()) == 1);
  132.             HX_RELEASE(pBuffer);
  133.         }
  134.         //This is the color key to use. If not set each card's driver will
  135.         //choose one.
  136.         pPreferences->ReadPref("ColorKey", pBuffer);
  137.         if (pBuffer)
  138.         {
  139.             char *pszTmp   = NULL;
  140.             const char *pszColor = (const char*)pBuffer->GetBuffer();
  141.             long lTmp = ::strtol(pszColor, &pszTmp, 0);
  142.             HX_RELEASE(pBuffer);
  143.             if( lTmp>=0 && pszTmp!=pszColor && errno!=ERANGE )
  144.             {
  145.                 m_ulColorKey = lTmp;
  146.             }
  147.         }
  148.         //For use in testing on Matrox G400 cards that support this
  149.         //atom.
  150.         pPreferences->ReadPref("Contrast", pBuffer);
  151.         if (pBuffer)
  152.         {
  153.             char *pszTmp   = NULL;
  154.             const char *pszContrast = (const char*)pBuffer->GetBuffer();
  155.             long lTmp = ::strtol(pszContrast, &pszTmp, 0);
  156.             HX_RELEASE(pBuffer);
  157.             if( pszTmp!=pszContrast && errno!=ERANGE )
  158.             {
  159.                 m_nContrast = lTmp;
  160.             }
  161.         }
  162.         //For use in testing on Matrox G400 cards that support this
  163.         //atom.
  164.         pPreferences->ReadPref("Brightness", pBuffer);
  165.         if (pBuffer)
  166.         {
  167.             char *pszTmp   = NULL;
  168.             const char *pszBrightness = (const char*)pBuffer->GetBuffer();
  169.             long lTmp = ::strtol(pszBrightness, &pszTmp, 0);
  170.             HX_RELEASE(pBuffer);
  171.             if( pszTmp!=pszBrightness && errno!=ERANGE )
  172.             {
  173.                 m_nBrightness = lTmp;
  174.             }
  175.         }
  176.         //Find out how much multi buffering to do
  177.         m_nMultiBufferCount = 2; //default to 2.
  178.         pPreferences->ReadPref("MultiBufferingCount", pBuffer);
  179.         if (pBuffer)
  180.         {
  181.             char *pszTmp   = NULL;
  182.             const char *pszBufferCount = (const char*)pBuffer->GetBuffer();
  183.             long lTmp = ::strtol(pszBufferCount, &pszTmp, 0);
  184.             HX_RELEASE(pBuffer);
  185.             if( pszTmp!=pszBufferCount && errno!=ERANGE )
  186.             {
  187.                 m_nMultiBufferCount = lTmp;
  188.             }
  189.         }
  190.         if( m_nMultiBufferCount < 1 )
  191.             m_nMultiBufferCount = 1;
  192.       
  193.         HX_RELEASE( pPreferences );
  194.     }
  195.     if( m_bUseOverlays )
  196.     {
  197.         //Alloc our multi buffer lists.
  198.         m_pXvImage   = new XvImage* [m_nMultiBufferCount];
  199.         m_pcVideoBuf = new UCHAR* [m_nMultiBufferCount];
  200.         m_shmInfo    = new XShmSegmentInfo[m_nMultiBufferCount];
  201.         m_nShmId     = new int[m_nMultiBufferCount];
  202.         for( i=0 ; i<m_nMultiBufferCount ; i++ )
  203.         {
  204.             m_pXvImage[i] = NULL;
  205.             m_pcVideoBuf[i] = NULL;
  206.             m_nShmId[i] = -1;
  207.         }
  208.     }
  209.    
  210. #endif //_LINUX && _OVERLAY
  211.    
  212. }
  213. CUnixSurf::~CUnixSurf()
  214. {
  215.     int i = 0;
  216.     
  217.     if( m_GC)
  218.     {
  219.         XFreeGC(m_display, m_GC);
  220.         m_GC=0;
  221.     }
  222.     
  223. #if defined(_LINUX) && defined(_OVERLAY)
  224.    
  225.     if( m_pXvImage )
  226.     {
  227.         for( i=0; i<m_nMultiBufferCount; i++ )
  228.         {
  229.             XFree( m_pXvImage[i] );
  230.         }
  231.         HX_VECTOR_DELETE(m_pXvImage);
  232.     }
  233.    
  234.     if( m_nPortID!=-1 )
  235.     {
  236.         XvUngrabPort( m_display, m_nPortID, CurrentTime );
  237.         m_nPortID=-1;
  238.         if( zm_pXvOwner==this )
  239.         {
  240.             zm_pXvOwner = NULL;
  241.         }
  242.     }
  243.     if( m_pcVideoBuf != NULL )
  244.     {
  245.         for( i=0 ; i<m_nMultiBufferCount ; i++ )
  246.         {
  247.             if( m_nShmId[i] != -1 && m_bUseShm )
  248.             {
  249.                 ShmHelp::DetachSharedRegion( &m_pcVideoBuf[i], &m_shmInfo[i] );
  250.                 m_nShmId[i] = -1;
  251.             }
  252.             else
  253.             {
  254.                 HX_VECTOR_DELETE(m_pcVideoBuf[i]);
  255.             }
  256.         }
  257.         HX_VECTOR_DELETE(m_pcVideoBuf);
  258.         HX_VECTOR_DELETE(m_shmInfo);
  259.     }
  260.     memset( &m_surfaceSize, 0, sizeof(m_surfaceSize) );
  261.    
  262. #endif //_LINUX && _OVERLAY
  263.    
  264. }
  265. void CUnixSurf::_ReleaseSurface(CBaseRootSurface* pSurface)
  266. {
  267.     //Release our grab on the port and assorted memory.....
  268.     _ReleaseSurface();
  269. }
  270. void CUnixSurf::_DrawBlack(void* pWindow)
  271. {
  272.     //XXXgfw fill whole window with black? Just our rect?
  273. }
  274. HX_RESULT CUnixSurf::_BltToPrimary(HXxRect& rDestRect, HXxRect& rSrcRect)
  275. {
  276. #ifdef _DEBUG   
  277.     fprintf( stderr, "CUnixSurf::_BltToPrimary is called...n" );
  278. #endif   
  279.     return HXR_FAIL;
  280. }
  281. void CUnixSurf::_CreateBuffer()
  282. {
  283.     int i = 0;
  284. #if defined(_LINUX) && defined(_OVERLAY)
  285.     //Clean up the old stuff....
  286.     if( m_pcVideoBuf != NULL )
  287.     {
  288.         for( i=0 ; i<m_nMultiBufferCount ; i++ )
  289.         {
  290.             if( m_pcVideoBuf[i] != NULL )
  291.             {
  292.                 if( m_nShmId[i] != -1 && m_bUseShm )
  293.                 {
  294.                     ShmHelp::DetachSharedRegion( &m_pcVideoBuf[i], &m_shmInfo[i] );
  295.                     m_nShmId[i] = -1;
  296.                 }
  297.                 else
  298.                 {
  299.                     HX_VECTOR_DELETE(m_pcVideoBuf[i]);
  300.                 }
  301.                 m_pcVideoBuf[i] = NULL;
  302.             }
  303.         }
  304.     }
  305.     
  306.     if( m_pXvImage )
  307.     {
  308.         for( i=0; i<m_nMultiBufferCount; i++ )
  309.         {
  310.             if( m_pXvImage[i] != NULL )
  311.             {
  312.                 XFree( m_pXvImage[i] );
  313.                 m_pXvImage[i] = NULL;
  314.             }
  315.         }
  316.     }
  317.     m_nVideoPitch = 0;
  318.     HX_ASSERT( m_display );
  319.     //Clear BitmapInfo struct....
  320.     HXBitmapInfo bmi;
  321.     memset( &bmi, 0, sizeof(HXBitmapInfo) );
  322.     int nResult = MakeBitmap( &bmi,
  323.                               sizeof(bmi),
  324.                               m_nSurfaceCID,
  325.                               m_surfaceSize.cx,
  326.                               m_surfaceSize.cy,
  327.                               NULL,
  328.                               0);
  329.     if( nResult )
  330.     {
  331.         ShmHelp::Init(m_display);
  332.         m_bUseShm = ShmHelp::ShmAvailable();
  333.         for( i=0 ; i<m_nMultiBufferCount ; i++ )
  334.         {
  335.             if( m_bUseShm )
  336.             {
  337.                 HX_RESULT retVal = ShmHelp::CreateSharedRegion( bmi.bmiHeader.biSizeImage,
  338.                                                                 &m_pcVideoBuf[i],
  339.                                                                 &m_nShmId[i],
  340.                                                                 &m_shmInfo[i]
  341.                                                                 );
  342.                 if( retVal != HXR_OK )
  343.                 {
  344.                     HX_ASSERT("Can't alloc shared memory segment." == NULL );
  345.                     m_nShmId[i]     = -1;
  346.                     m_pcVideoBuf[i] = NULL;
  347.                 }
  348.             }
  349.           
  350.             //did the shm alloc work?
  351.             if( m_pcVideoBuf[i] == NULL )
  352.             {
  353.                 m_bUseShm        = FALSE;
  354.                 m_nShmId[i]      = -1;
  355.                 m_pcVideoBuf[i]  = new UCHAR[bmi.bmiHeader.biSizeImage];
  356.             }
  357.             HX_ASSERT( m_pcVideoBuf );
  358.         }
  359.         m_nVideoPitch = GetBitmapPitch(&bmi);
  360.     }
  361.    
  362.     HX_ASSERT( m_nVideoPitch != 0 );
  363.     //Now create the XvImage to blt to.....
  364.     HX_ASSERT( m_nPortID != -1 );
  365.     for( i=0 ; i<m_nMultiBufferCount ; i++ )
  366.     {
  367.         HX_ASSERT( m_pXvImage[i] == NULL );
  368.         if( m_bUseShm )
  369.         {
  370.             m_pXvImage[i]  = XvShmCreateImage( m_display,
  371.                                                m_nPortID,
  372.                                                m_ulFourCCID,
  373.                                                (char*)m_pcVideoBuf[i],
  374.                                                m_surfaceSize.cx,
  375.                                                m_surfaceSize.cy,
  376.                                                &m_shmInfo[i]
  377.                                                );
  378.         }
  379.         else
  380.         {
  381.             m_pXvImage[i] = XvCreateImage( m_display,
  382.                                            m_nPortID,
  383.                                            m_ulFourCCID,
  384.                                            (char*)m_pcVideoBuf[i],
  385.                                            m_surfaceSize.cx,
  386.                                            m_surfaceSize.cy
  387.                                            );
  388.         }
  389.           
  390.         if( m_pXvImage[i] == NULL )
  391.         {
  392.             HX_ASSERT("Could not create overlay surface"==NULL );
  393.             //XXgfw, well, what to do here????
  394.         }
  395.     }
  396.     if( m_bUseShm )
  397.     {
  398.         //Find the shm completion event ID.
  399.         m_nCompletionEventID = XShmGetEventBase(m_display) + ShmCompletion;
  400.     }
  401.    
  402. #endif
  403. }
  404. BOOL CUnixSurf::_OverlayAvailable(int nFourCCWanted, int* pnPortID )
  405. {
  406.     BOOL bRetVal = FALSE;
  407.     
  408. #if defined(_LINUX) && defined(_OVERLAY)
  409.     if( !m_bUseOverlays )
  410.     {
  411.         return bRetVal;
  412.     }
  413.    
  414.     unsigned int nNumAdaptors = 0;
  415.     int nImageCount  = 0;
  416.     int nPortID      = -1;
  417.     int i = 0;
  418.     int j = 0;
  419.     int k = 0;
  420.     unsigned int ver = 0;
  421.     unsigned int rel = 0;
  422.     unsigned int req = 0;
  423.     unsigned int ev  = 0;
  424.     unsigned int err = 0;
  425.     int nRetCode = 0;
  426.     XvImageFormatValues *pImageFormats = NULL;
  427.     XvAdaptorInfo       *pAdaptorInfo  = NULL;
  428.     //First, we need to map our cid to a FourCC.
  429.     ULONG32 ulFourCC = 0;
  430.     switch(nFourCCWanted)
  431.     {
  432.        case -1:
  433.            //nothing requested
  434.            break;
  435.        case CID_I420:
  436.            ulFourCC = MAKEFOURCC('I','4','2','0');
  437.            break;
  438.        case CID_YV12:
  439.            ulFourCC = MAKEFOURCC('Y','V','1','2');
  440.            break;
  441.        case CID_YVU9:
  442.            ulFourCC = MAKEFOURCC('Y','V','U','9');
  443.            break;
  444.        case CID_YUY2:
  445.            ulFourCC = MAKEFOURCC('Y','U','Y','2');
  446.            break;
  447.        case CID_UYVY:
  448.            ulFourCC = MAKEFOURCC('U','Y','V','Y');
  449.            break;
  450.        default:
  451.            HX_ASSERT( "Unkown CID" == NULL );
  452.     }
  453.    
  454.     if( m_pSite )
  455.     {
  456.         HX_ASSERT( m_pSite->GetWindow() );
  457.         m_display = (Display*)((m_pSite->GetWindow())->display);
  458.     }
  459.     HX_ASSERT( m_display );
  460.     //XXXgfw this code assumes that there is *only* one overlay available
  461.     //on a machine. We need to change this as more become available....
  462.     if( zm_pXvOwner != NULL )
  463.     {
  464.         //Someone owns the *one* overlay
  465.         goto doneChecking;
  466.     }
  467.    
  468.     nRetCode = XvQueryExtension(m_display, &ver, &rel, &req, &ev, &err);
  469.     if( nRetCode != Success )
  470.     {
  471.         //Our X-Server doesn't support XVideo at all.
  472.         bRetVal = FALSE;
  473.         goto doneChecking;
  474.     }
  475.    
  476.     nRetCode = XvQueryAdaptors( m_display,
  477.                                 DefaultRootWindow(m_display),
  478.                                 &nNumAdaptors,
  479.                                 &pAdaptorInfo );
  480.     if( nRetCode == Success && nNumAdaptors ) // pjg/gfw geForceII returns 0 adaptors with garbage return pointer
  481.     {
  482.         for(i=0 ; i<nNumAdaptors ; i++)
  483.         {
  484.             if(pAdaptorInfo[i].type & XvImageMask)
  485.             {
  486.                 if( ulFourCC==0 )
  487.                 {
  488.                     //User just wants to know if we have overlays at all.
  489.                     bRetVal = TRUE;
  490.                     goto doneChecking;
  491.                 }
  492.             
  493.                 pImageFormats = XvListImageFormats(m_display, pAdaptorInfo[i].base_id, &nImageCount);  
  494.                 for( j=0 ; j<nImageCount ; j++)
  495.                 {
  496.                     if(pImageFormats[j].id == ulFourCC)
  497.                     {
  498.                         for( k=0 ; k<pAdaptorInfo[i].num_ports; k++)
  499.                         {
  500.                             if(Success == XvGrabPort(m_display, pAdaptorInfo[i].base_id+k, 
  501.                                                      CurrentTime))
  502.                             {
  503.                                 //XXXgfw later, when we see graphics cards under linux
  504.                                 //that have more than one overlay available we will need
  505.                                 //to update this code......
  506.                         
  507.                                 //Hey! We found one!
  508.                                 nPortID = pAdaptorInfo[i].base_id+k;
  509.                                 XvUngrabPort(m_display,
  510.                                              pAdaptorInfo[i].base_id+k,
  511.                                              CurrentTime );
  512.                                 break;
  513.                             }
  514.                         }
  515.                     }
  516.                     if(nPortID != -1)
  517.                         break;
  518.                 }
  519.                 XFree(pImageFormats);
  520.             }
  521.             if(nPortID != -1)
  522.                 break;
  523.         }
  524.         XvFreeAdaptorInfo(pAdaptorInfo);
  525.       
  526.         if( nPortID != -1 )
  527.         {
  528.             bRetVal = TRUE;
  529.             if( NULL != pnPortID )
  530.                 *pnPortID = nPortID;
  531.             m_ulFourCCID = ulFourCC;
  532.         }
  533.       
  534. //        fprintf( stderr, "Found a port that supports %d(%p), it is %dn",
  535. //                 nFourCCWanted, (void*)ulFourCC,nPortID );
  536.     }
  537.   doneChecking:
  538. #endif   
  539.    
  540.     return bRetVal;
  541. }
  542. HX_RESULT CUnixSurf::_GetCaps(UINT32 *pfSurfaceCaps)
  543. {
  544.     *pfSurfaceCaps = 0;
  545.     if( _OverlayAvailable() )
  546.     {
  547.         *pfSurfaceCaps |= HX_OVERLAY;
  548.     }
  549.    
  550.     return HXR_OK;
  551. }
  552. HX_RESULT CUnixSurf::_CreateOverlay(BOOL bOverlay, int cid, int x, int y)
  553. {
  554.     HX_RESULT retVal = HXR_FAIL;
  555.     int       nSuc   = Success;
  556. //     fprintf( stderr, "CUnixSurf::_CreateOverlay(%p): bOverlay:%d cid:%d x,y: %d %dn",
  557. //              this, bOverlay, cid, x, y);
  558.     if( x & 15 )
  559.     {
  560.         x = (x&~15)+16;
  561.     }
  562. #if defined(_LINUX) && defined(_OVERLAY) 
  563.     if( bOverlay )
  564.     {
  565.         int  nPortID    = 0;
  566.         BOOL bAvailable = FALSE;
  567.         bAvailable = _OverlayAvailable( cid, &nPortID );
  568.         if( bAvailable )
  569.         {
  570.             HX_ASSERT(m_display);
  571.             //Grab the port.
  572.             nSuc = XvGrabPort( m_display, nPortID, CurrentTime );
  573.             if( nSuc == Success )
  574.             {
  575.                 //Take ownership of the overlay. A connection to the XServer
  576.                 //can grab the overlay port as much as it wants so we can't
  577.                 //rely on that to make sure that we only have one surface 
  578.                 //using the overlay.
  579.                 m_nPortID   = nPortID;
  580.                 zm_pXvOwner = this;
  581.             
  582.                 //So far so good. Now we need to grab all of our atoms to control
  583.                 //the overlay
  584.                 m_atomColorKey = XInternAtom(m_display, "XV_COLOR_KEY", True);
  585.                 if( m_atomColorKey == None )
  586.                 {
  587.                     //There isn't a naming convention for any of these atoms. we
  588.                     //have to disover at run time what they are.
  589.                     m_atomColorKey  = XInternAtom(m_display, "XV_COLORKEY", True);
  590.                 }
  591.                 m_atomClipKey    = XInternAtom(m_display, "XV_PAINT_CLIPLIST", True);
  592.                 m_atomBrightness = XInternAtom(m_display, "XV_BRIGHTNESS", True);
  593.                 m_atomContrast   = XInternAtom(m_display, "XV_CONTRAST", True);
  594.                 //Now set some of the atoms we read from the prefs
  595.                 if( None != m_atomClipKey)
  596.                 {
  597.                     XvSetPortAttribute(m_display, m_nPortID, m_atomClipKey, m_bPaintClipList);
  598.                 }            
  599.                 if( None!=m_atomBrightness && m_nBrightness!=-9999 )
  600.                 {
  601.                     XvSetPortAttribute(m_display, m_nPortID, m_atomBrightness, m_nBrightness);
  602.                 }
  603.                 if( None!=m_atomContrast && m_nContrast!=-9999 )
  604.                 {
  605.                     XvSetPortAttribute( m_display, m_nPortID, m_atomContrast, m_nContrast);
  606.                 }
  607.                 //Now we need to create the overlay surface???
  608.                 m_surfaceSize.cx = x;
  609.                 m_surfaceSize.cy = y;
  610.                 m_nSurfaceCID    = cid;
  611.                 m_nBltMode       = HX_OVERLAY_BLT;
  612.                 _CreateBuffer();
  613.                 //Return good.
  614.                 retVal = HXR_OK;
  615.             }
  616.         }
  617.     } //if(bOverlay)...
  618. #endif   
  619.     return retVal;
  620. }
  621. HX_RESULT CUnixSurf::_LockInternalSurface( UCHAR**  ppSurfPtr,
  622.                                            LONG32*  pnSurfPitch,
  623.                                            HXxSize& notused )
  624. {
  625.     HX_RESULT retVal = HXR_OK;
  626.     //Flip internal buffers....
  627.     m_nCurrentBuffer++;
  628.     if( m_nCurrentBuffer >= m_nMultiBufferCount )
  629.     {
  630.         m_nCurrentBuffer=0;
  631.     }
  632.     HX_ASSERT( m_pcVideoBuf[m_nCurrentBuffer] );
  633.     HX_ASSERT( m_nVideoPitch != 0 );
  634.    
  635.     *ppSurfPtr   = (UCHAR*)m_pcVideoBuf[m_nCurrentBuffer];
  636.     *pnSurfPitch = m_nVideoPitch;
  637.     return retVal;
  638. }
  639. HX_RESULT CUnixSurf::_UnlockInternalSurface(UCHAR* pSurfPtr)
  640. {
  641.     return HXR_OK;
  642. }
  643. void CUnixSurf::_SetupDCObjects(HXxDC hxxDC, void** phOldBrush, void** phOldPen)
  644. {
  645. #ifdef _DEBUG   
  646.     fprintf( stderr, "CUnixSurf::_SetupDCObjects needs to be written.n" );
  647. #endif   
  648. }
  649. void CUnixSurf::_FillRectangle(HXxDC hxxDC,
  650.                                UINT32 left, UINT32 top,
  651.                                UINT32 right, UINT32 bottom)
  652. {
  653.     if( !hxxDC )
  654.         return;
  655.     for( int x=left; x<=right-1; x++ )
  656.     {
  657.         for( int y=top; y<=bottom-1; y++ )
  658.         {
  659. #if defined _LINUX &&  defined _OVERLAY
  660.             XPutPixel( (XImage*)hxxDC, x, y, m_ulColorKey );
  661. #endif
  662.         }
  663.     }
  664. }
  665. void CUnixSurf::_RestoreDCObjects(HXxDC hxxDC, void* hOldBrush, void* hOldPen)
  666. {
  667. #ifdef _DEBUG   
  668.     fprintf( stderr, "CUnixSurf::_RestoreDCObjects needs to be written.n" );
  669. #endif   
  670. }
  671. void CUnixSurf::_GetCompositionSurfaceHXxDC(HXxDC *hdc)
  672. {
  673.     //This needs to return a drawable that points to the composition surface...
  674.     CUnixRootSurf* pSurface = (CUnixRootSurf*)m_pSite->GetRootSurface();
  675.     XImage *pImage = pSurface->_GetCompositionSurfaceDrawable();
  676.     *hdc = (HXxDC)pImage;
  677. }
  678. void CUnixSurf::_ReleaseCompositionSurfaceHXxDC(HXxDC hdc)
  679. {
  680.     //Nothing to do on unix...
  681. }
  682. INT32 CUnixSurf::_InsureColorMatch(INT32 InColor)
  683. {
  684.     return InColor;
  685. }
  686. void CUnixSurf::_SetColorKey(INT32 nColorSpaceLowValue,INT32 nColorSpaceHighValue)
  687. {
  688. #if defined(_LINUX) && defined(_OVERLAY)   
  689.     static BOOL bDoneItAlready = FALSE;
  690.    
  691.     if( m_atomColorKey != None && !bDoneItAlready)
  692.     {
  693.         if( m_ulColorKey == 0x01020304 )
  694.         {
  695.             m_ulColorKey = nColorSpaceHighValue;
  696.             //The user did not set a color key preference...
  697.             XvSetPortAttribute( m_display, m_nPortID, m_atomColorKey, nColorSpaceHighValue );
  698.         }
  699.         else
  700.         {
  701.             XvSetPortAttribute( m_display, m_nPortID, m_atomColorKey, m_ulColorKey );
  702.         }
  703.         bDoneItAlready = TRUE;
  704.     }
  705. #endif   
  706. }
  707. static BOOL CheckIt(Display* dis, XEvent* event, XPointer arg)
  708. {
  709.     BOOL ret = (event->type==(int)arg);
  710.     return ret;
  711. }
  712. void CUnixSurf::_UpdateOverlay(HXxRect* dest, HXxRect* src, INT32 inFlags)
  713. {
  714.     HXxWindow*        pWin         = m_pSite->GetWindow();
  715.     CBaseRootSurface* pRootSurface = m_pSite->GetRootSurface();
  716.     int               nRet         = 0;
  717.     Window            winSurface   = 0;
  718.     HXxRect           rectDest     = {0,0,0,0};
  719.     memcpy( &rectDest, dest, sizeof( HXxRect ) ); /* Flawfinder: ignore */
  720.     HX_ASSERT( m_nMultiBufferCount );
  721. #if defined(_LINUX) && defined(_OVERLAY)
  722.     m_ulLastOverlayUpdateTime = HX_GET_TICKCOUNT();
  723.    
  724.     //Draw on the root window if the user wants it. This feature isn't tested
  725.     //and has known problems for certain window managers that create their own
  726.     //window over the root. Looks really cool when it works though. :) Turn
  727.     //this on set the color key to the background color of all your xterms.
  728.     //Very nice.
  729.     if( !m_bWallPaperMode )
  730.     {
  731.         winSurface = (Window)pWin->window;
  732.     }
  733.     else
  734.     {
  735.         winSurface = DefaultRootWindow(m_display);
  736.     }
  737.    
  738.     HX_ASSERT( pWin );
  739. #ifdef _DEBUG   
  740. //     static ULONG32 ulLast  =0;
  741. //     static ULONG32 ulCount =0;
  742. //     static ULONG32 ulCountTot =0;
  743. //     static double  fpsTot=0;
  744. //     ULONG32        ulCurr  = HX_GET_TICKCOUNT();
  745. //     if( ulCurr-ulLast>1000 )
  746. //     {
  747. //        float fps = (float)ulCount/((float)(ulCurr-ulLast)/1000.0);
  748. //        fpsTot += fps;
  749. //        ulCountTot++;
  750.       
  751. //        fprintf( stderr, "%lu elapsed microseconds. %lu frames.  %f FPS (Ave: %f)n",
  752. //                 ulCurr-ulLast, ulCount, fps, fpsTot/(double)ulCountTot );
  753. //        ulCount = 0;
  754. //        ulLast  = ulCurr;
  755. //     }
  756. //     ulCount++;
  757. #endif   
  758.     //if we are on the root window, calculate new dest rect.
  759.     //Copy the one passed in.
  760.     if( m_bWallPaperMode )
  761.     {
  762.         Screen* pScreen = XDefaultScreenOfDisplay(m_display);
  763.         UINT16 uHorzRes = WidthOfScreen(pScreen);
  764.         UINT16 uVertRes = HeightOfScreen(pScreen);
  765.         //if the user wants to stretchtofill then make the dest rect the
  766.         //whole screen, otherwise preserve aspec ration.
  767.         if( m_bStretchToFill )
  768.         {
  769.             //Make it the whole screen.
  770.             rectDest.left   = 0;
  771.             rectDest.top    = 0;
  772.             rectDest.right  = uHorzRes;
  773.             rectDest.bottom = uVertRes;
  774.         }
  775.         else
  776.         {
  777.             //maintain aspect ration.
  778.             //Scale it.
  779.             float fXScale   = (float)uHorzRes/(float)(dest->right-dest->left);
  780.             float fYScale   = (float)uVertRes/(float)(dest->bottom-dest->top);
  781.             float fScale    = (fXScale<fYScale) ? fXScale : fYScale;
  782.             int nWidth      = (int)(fScale*(dest->right-dest->left)+.5);
  783.             int nHeight     = (int)(fScale*(dest->bottom-dest->top)+.5);
  784.             rectDest.left   = 0;
  785.             rectDest.top    = 0;
  786.          
  787.             if( nWidth<uHorzRes )
  788.                 rectDest.left = (uHorzRes-nWidth)/2;
  789.             if( nHeight<uVertRes )
  790.                 rectDest.top  = (uVertRes-nHeight)/2;
  791.             rectDest.right  = rectDest.left+nWidth;
  792.             rectDest.bottom = rectDest.top+nHeight;
  793.         }
  794.     }
  795.     if( m_bUseShm )
  796.     {
  797.         nRet = XvShmPutImage( m_display,
  798.                               m_nPortID,
  799.                               winSurface,
  800.                               ((CUnixRootSurf*)pRootSurface)->GetGC(),
  801.                               m_pXvImage[m_nCurrentBuffer],
  802.                               src->left, 
  803.                               src->top,
  804.                               src->right - src->left, 
  805.                               src->bottom - src->top,
  806.                               rectDest.left, 
  807.                               rectDest.top,
  808.                               rectDest.right - rectDest.left,      
  809.                               rectDest.bottom - rectDest.top,
  810.                               True
  811.                               );
  812.     }
  813.     else
  814.     {
  815.         nRet = XvPutImage( m_display,
  816.                            m_nPortID, 
  817.                            winSurface,
  818.                            ((CUnixRootSurf*)pRootSurface)->GetGC(),
  819.                            m_pXvImage[m_nCurrentBuffer],
  820.                            src->left, 
  821.                            src->top,
  822.                            src->right - src->left, 
  823.                            src->bottom - src->top,
  824.                            rectDest.left, 
  825.                            rectDest.top,
  826.                            rectDest.right - rectDest.left,      
  827.                            rectDest.bottom - rectDest.top
  828.                            );
  829.     }
  830.     if( m_bUseShm && m_nMultiBufferCount==1 )
  831.     {
  832.         //If we aren't at least double buffering and we are using
  833.         //shared memory, make sure we wait for the completion of the
  834.         //copy of the shared memory segment to the server. Tear not
  835.         //want not.
  836.         HX_ASSERT( m_nCompletionEventID > 0 );
  837.         XEvent event;
  838.         XIfEvent( m_display, &event, CheckIt, (XPointer)m_nCompletionEventID );
  839.     }
  840.    
  841. #endif   
  842. }
  843. BOOL CUnixSurf::_IsSurfaceVisible()
  844. {
  845.     return TRUE;
  846. }
  847. void CUnixSurf::_ReleaseSurface()
  848. {
  849.     int i=0;
  850.     
  851. #if defined(_LINUX) && defined(_OVERLAY)   
  852.     //Release all of our overlay resources.....
  853.     if( m_nPortID!=-1 )
  854.     {
  855.         XvUngrabPort( m_display, m_nPortID, CurrentTime );
  856.         m_nPortID=-1;
  857.         if( zm_pXvOwner==this )
  858.         {
  859.             zm_pXvOwner = NULL;
  860.         }
  861.     }
  862.     if( m_pcVideoBuf != NULL )
  863.     {
  864.         for( i=0 ; i<m_nMultiBufferCount ; i++ )
  865.         {
  866.             if( m_nShmId[i] != -1 && m_bUseShm )
  867.             {
  868.                 ShmHelp::DetachSharedRegion( &m_pcVideoBuf[i], &m_shmInfo[i] );
  869.                 m_nShmId[i] = -1;
  870.             }
  871.             else
  872.             {
  873.                 HX_VECTOR_DELETE(m_pcVideoBuf[i]);
  874.             }
  875.             m_pcVideoBuf[i] = NULL;
  876.         }
  877.     }
  878.     
  879.     if( m_pXvImage )
  880.     {
  881.         for( i=0; i<m_nMultiBufferCount; i++ )
  882.         {
  883.             XFree( m_pXvImage[i] );
  884.             m_pXvImage[i] = NULL;
  885.         }
  886.     }
  887.     memset( &m_surfaceSize, 0, sizeof(m_surfaceSize) );
  888.     m_nSurfaceCID = 1234; //what else?
  889. #endif   
  890. }
  891. HXxDC CUnixSurf::_GetDC(HXxWindow*)
  892. {
  893.     return (HXxDC)m_GC;
  894. }
  895. void CUnixSurf::_ReleaseDC(HXxWindow*, HXxDC)
  896. {
  897. #ifdef _DEBUG   
  898.     fprintf( stderr, "CUnixSurf::_ReleaseDC needs to be written.n" ); 
  899. #endif   
  900. }
  901. void CUnixSurf::_GetWindowDeviceCords(HXxRect* rect )
  902. {
  903.     memset( rect, 0, sizeof( HXxRect) );
  904. }