Back to index

lightning-sunbird  0.9+nobinonly
nsDrawingSurfaceWin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifdef NGLAYOUT_DDRAW
00039 #define INITGUID
00040 #endif
00041 
00042 #include "nsDrawingSurfaceWin.h"
00043 #include "prmem.h"
00044 #include "nsCRT.h"
00045 
00046 //#define GFX_DEBUG
00047 
00048 #ifdef GFX_DEBUG
00049   #define BREAK_TO_DEBUGGER           DebugBreak()
00050 #else   
00051   #define BREAK_TO_DEBUGGER
00052 #endif  
00053 
00054 #ifdef GFX_DEBUG
00055   #define VERIFY(exp)                 ((exp) ? 0: (GetLastError(), BREAK_TO_DEBUGGER))
00056 #else   // !_DEBUG
00057   #define VERIFY(exp)                 (exp)
00058 #endif  // !_DEBUG
00059 
00060 static NS_DEFINE_IID(kIDrawingSurfaceIID, NS_IDRAWING_SURFACE_IID);
00061 static NS_DEFINE_IID(kIDrawingSurfaceWinIID, NS_IDRAWING_SURFACE_WIN_IID);
00062 
00063 #ifdef NGLAYOUT_DDRAW
00064 IDirectDraw *nsDrawingSurfaceWin::mDDraw = NULL;
00065 IDirectDraw2 *nsDrawingSurfaceWin::mDDraw2 = NULL;
00066 nsresult nsDrawingSurfaceWin::mDDrawResult = NS_OK;
00067 #endif
00068 
00069 nsDrawingSurfaceWin :: nsDrawingSurfaceWin()
00070 {
00071   mDC = NULL;
00072   mOrigBitmap = nsnull;
00073   mSelectedBitmap = nsnull;
00074   mKillDC = PR_FALSE;
00075   mBitmapInfo = nsnull;
00076   mDIBits = nsnull;
00077   mLockedBitmap = nsnull;
00078   mWidth = mHeight = 0;
00079   mLockOffset = mLockHeight = 0;
00080   mLockFlags = 0;
00081 
00082 #ifdef NGLAYOUT_DDRAW
00083 
00084   CreateDDraw();
00085 
00086   mSurface = NULL;
00087   mSurfLockCnt = 0;
00088 
00089 #endif
00090 }
00091 
00092 nsDrawingSurfaceWin :: ~nsDrawingSurfaceWin()
00093 {
00094   if ((nsnull != mDC) && (nsnull != mOrigBitmap))
00095   {
00096     HBITMAP tbits = (HBITMAP)::SelectObject(mDC, mOrigBitmap);
00097 
00098     if (nsnull != tbits)
00099       VERIFY(::DeleteObject(tbits));
00100 
00101     mOrigBitmap = nsnull;
00102   }
00103 
00104   if (nsnull != mBitmapInfo)
00105   {
00106     PR_Free(mBitmapInfo);
00107     mBitmapInfo = nsnull;
00108   }
00109 
00110   if ((nsnull != mDIBits) && (nsnull == mSelectedBitmap))
00111     PR_Free(mDIBits);
00112 
00113   mDIBits = nsnull;
00114   mSelectedBitmap = nsnull;
00115 
00116 #ifdef NGLAYOUT_DDRAW
00117   if (NULL != mSurface)
00118   {
00119     if (NULL != mDC)
00120     {
00121       mSurface->ReleaseDC(mDC);
00122       mDC = NULL;
00123     }
00124 
00125     NS_RELEASE(mSurface);
00126     mSurface = NULL;
00127   }
00128   else
00129 #endif
00130   {
00131     if (NULL != mDC)
00132     {
00133       if (PR_TRUE == mKillDC)
00134         ::DeleteDC(mDC);
00135 
00136       mDC = NULL;
00137     }
00138   }
00139 }
00140 
00141 NS_IMETHODIMP nsDrawingSurfaceWin :: QueryInterface(REFNSIID aIID, void** aInstancePtr)
00142 {
00143   if (nsnull == aInstancePtr)
00144     return NS_ERROR_NULL_POINTER;
00145 
00146   if (aIID.Equals(kIDrawingSurfaceIID))
00147   {
00148     nsIDrawingSurface* tmp = this;
00149     *aInstancePtr = (void*) tmp;
00150     NS_ADDREF_THIS();
00151     return NS_OK;
00152   }
00153 
00154   if (aIID.Equals(kIDrawingSurfaceWinIID))
00155   {
00156     nsIDrawingSurfaceWin* tmp = this;
00157     *aInstancePtr = (void*) tmp;
00158     NS_ADDREF_THIS();
00159     return NS_OK;
00160   }
00161 
00162   static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
00163 
00164   if (aIID.Equals(kISupportsIID))
00165   {
00166     nsIDrawingSurface* tmp = this;
00167     nsISupports* tmp2 = tmp;
00168     *aInstancePtr = (void*) tmp2;
00169     NS_ADDREF_THIS();
00170     return NS_OK;
00171   }
00172 
00173   return NS_NOINTERFACE;
00174 }
00175 
00176 NS_IMPL_ADDREF(nsDrawingSurfaceWin)
00177 NS_IMPL_RELEASE(nsDrawingSurfaceWin)
00178 
00179 NS_IMETHODIMP nsDrawingSurfaceWin :: Lock(PRInt32 aX, PRInt32 aY,
00180                                           PRUint32 aWidth, PRUint32 aHeight,
00181                                           void **aBits, PRInt32 *aStride,
00182                                           PRInt32 *aWidthBytes, PRUint32 aFlags)
00183 {
00184 #ifdef NGLAYOUT_DDRAW
00185   if (mSurfLockCnt == 0)
00186   {
00187     RECT  srect;
00188     DWORD lockflags = 0;
00189 
00190     srect.left = aX;
00191     srect.top = aY;
00192     srect.right = aX + aWidth;
00193     srect.bottom = aY + aHeight;
00194 
00195     if (aFlags & NS_LOCK_SURFACE_READ_ONLY)
00196       lockflags |= DDLOCK_READONLY;
00197 
00198     if (aFlags & NS_LOCK_SURFACE_WRITE_ONLY)
00199       lockflags |= DDLOCK_WRITEONLY;
00200 
00201     if (PR_TRUE == LockSurface(mSurface, &mSurfDesc, &mBitmap, &srect, lockflags, &mPixFormat))
00202       mSurfLockCnt++;
00203   }
00204   else
00205   {
00206     NS_ASSERTION(0, "nested lock attempt");
00207     return NS_ERROR_FAILURE;
00208   }
00209 
00210   if (mSurfLockCnt == 0)
00211 #endif
00212   {
00213     if (nsnull == mLockedBitmap)
00214     {
00215       if (nsnull == mSelectedBitmap)
00216       {
00217         HBITMAP tbits = ::CreateCompatibleBitmap(mDC, 2, 2);
00218         if ( tbits != nsnull )
00219         {
00220           mLockedBitmap = (HBITMAP)::SelectObject(mDC, tbits);
00221 
00222           // if the SelectObject fails, or there was no bitmap returned from this DC
00223           if ( mLockedBitmap != nsnull ) 
00224           {
00225             ::GetObject(mLockedBitmap, sizeof(BITMAP), &mBitmap);
00226             // Always use at least 24-bit bitmaps regardless of the device context.
00227             // See bug 228399 for more information.
00228             if (mBitmap.bmBitsPixel < 24)
00229               mBitmap.bmBitsPixel = 24;
00230             // Note the width of the DIB-bits rows. DIB rows are DWORD-aligned,
00231             // the original bitmap's rows may not have been DWORD-aligned.
00232             mBitmap.bmWidthBytes = RASWIDTH(mBitmap.bmWidth, mBitmap.bmBitsPixel);
00233 
00234             if (aY < 0 || aY + aHeight > mBitmap.bmHeight) {
00235               ::DeleteObject(tbits);
00236               return NS_ERROR_FAILURE;
00237             }
00238             
00239             // GetDIBits always seems to interpret the scanlines as bottom-to-top.
00240             mLockHeight = (PRInt32)aHeight;
00241             mLockOffset = mBitmap.bmHeight - (aY + aHeight);
00242 
00243             mBitmapInfo = CreateBitmapInfo(mBitmap.bmWidth, mBitmap.bmHeight, mBitmap.bmBitsPixel, (void **)&mDIBits);
00244 
00245             if ( mBitmapInfo != nsnull ) {
00246               if (!(aFlags & NS_LOCK_SURFACE_WRITE_ONLY))
00247                 ::GetDIBits(mDC, mLockedBitmap, mLockOffset, mLockHeight, mDIBits, mBitmapInfo, DIB_RGB_COLORS);
00248 
00249               mBitmap.bmBits = mDIBits;
00250             } else {
00251               ::DeleteObject(tbits);
00252               return NS_ERROR_FAILURE;
00253             }
00254           } 
00255           else 
00256           {      
00257             ::DeleteObject(tbits);
00258             return NS_ERROR_FAILURE;
00259           }
00260         }
00261         else
00262         {
00263           return NS_ERROR_FAILURE;
00264         }
00265       }
00266       else
00267       {
00268         if (!(aFlags & NS_LOCK_SURFACE_WRITE_ONLY))
00269           ::GdiFlush();
00270         mLockedBitmap = mSelectedBitmap;
00271         mBitmap.bmBits = mDIBits + mBitmap.bmWidthBytes * aY;
00272       }
00273     }
00274     else
00275     {
00276       NS_ASSERTION(0, "nested lock attempt");
00277       return NS_ERROR_FAILURE;
00278     }
00279   }
00280 
00281   *aBits = (PRUint8 *)mBitmap.bmBits + (aX * (mBitmap.bmBitsPixel >> 3));
00282   *aStride = mBitmap.bmWidthBytes;
00283   *aWidthBytes = aWidth * (mBitmap.bmBitsPixel >> 3);
00284   mLockFlags = aFlags;
00285 
00286   return NS_OK;
00287 }
00288 
00289 NS_IMETHODIMP nsDrawingSurfaceWin :: Unlock(void)
00290 {
00291 #ifdef NGLAYOUT_DDRAW
00292   NS_ASSERTION(!(mDC != nsnull), "attempt to unlock with dc");
00293 
00294   if (nsnull == mDC)
00295   {
00296     mSurfLockCnt--;
00297 
00298     NS_ASSERTION(!(mSurfLockCnt != 0), "nested surface locks");
00299 
00300     if (mSurfLockCnt == 0)
00301       mSurface->Unlock(mSurfDesc.lpSurface);
00302   }
00303   else
00304 #endif
00305   {
00306     if (nsnull != mLockedBitmap)
00307     {
00308       if (nsnull == mSelectedBitmap)
00309       {
00310         HBITMAP tbits;
00311 
00312         if (!(mLockFlags & NS_LOCK_SURFACE_READ_ONLY))
00313           ::SetDIBits(mDC, mLockedBitmap, mLockOffset, mLockHeight, mDIBits, mBitmapInfo, DIB_RGB_COLORS);
00314 
00315         tbits = (HBITMAP)::SelectObject(mDC, mLockedBitmap);
00316         ::DeleteObject(tbits);
00317 
00318         if (nsnull != mBitmapInfo)
00319         {
00320           PR_Free(mBitmapInfo);
00321           mBitmapInfo = nsnull;
00322         }
00323 
00324         if (nsnull != mDIBits)
00325         {
00326           PR_Free(mDIBits);
00327           mDIBits = nsnull;
00328         }
00329       }
00330 
00331       mLockedBitmap = nsnull;
00332     }
00333   }
00334 
00335   return NS_OK;
00336 }
00337 
00338 NS_IMETHODIMP nsDrawingSurfaceWin :: GetDimensions(PRUint32 *aWidth, PRUint32 *aHeight)
00339 {
00340   *aWidth = mWidth;
00341   *aHeight = mHeight;
00342 
00343   return NS_OK;
00344 }
00345 
00346 NS_IMETHODIMP nsDrawingSurfaceWin :: IsOffscreen(PRBool *aOffScreen)
00347 {
00348   *aOffScreen = mKillDC;
00349 
00350   return NS_OK;
00351 }
00352 
00353 NS_IMETHODIMP nsDrawingSurfaceWin :: IsPixelAddressable(PRBool *aAddressable)
00354 {
00355 #ifdef NGLAYOUT_DDRAW
00356   if (nsnull != mSurface)
00357     *aAddressable = PR_TRUE;
00358   else
00359 #endif
00360   if (nsnull != mSelectedBitmap)
00361     *aAddressable = PR_TRUE;
00362   else
00363     *aAddressable = PR_FALSE;
00364 
00365   return NS_OK;
00366 }
00367 
00368 NS_IMETHODIMP nsDrawingSurfaceWin :: GetPixelFormat(nsPixelFormat *aFormat)
00369 {
00370   *aFormat = mPixFormat;
00371 
00372   return NS_OK;
00373 }
00374 
00375 NS_IMETHODIMP nsDrawingSurfaceWin :: Init(HDC aDC)
00376 {
00377   mDC = aDC;
00378 
00379   mTechnology = ::GetDeviceCaps(mDC, TECHNOLOGY);
00380 
00381   return NS_OK;
00382 }
00383 
00384 NS_IMETHODIMP nsDrawingSurfaceWin :: Init(HDC aDC, PRUint32 aWidth,
00385                                           PRUint32 aHeight, PRUint32 aFlags)
00386 {
00387   NS_ASSERTION(!(aDC == nsnull), "null DC");
00388 
00389 #if defined(MOZ_SVG) && defined(SVG_FORCE_PIXEL_ACCESS_SURFACES)
00390   // force pixel access on all surfaces. Improves gdi+ performance
00391   aFlags |= NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS;
00392 #endif
00393   
00394 #ifdef NGLAYOUT_DDRAW
00395   if (aFlags & NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS)
00396   {
00397     LPDIRECTDRAWSURFACE ddsurf = nsnull;
00398 
00399     if ((NULL != mDDraw2) && (aWidth > 0) && (aHeight > 0))
00400     {
00401       DDSURFACEDESC ddsd;
00402 
00403       ddsd.dwSize = sizeof(ddsd);
00404       ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
00405       ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
00406                             ((aFlags & NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS) ?
00407                             DDSCAPS_SYSTEMMEMORY : 0);
00408       ddsd.dwWidth = aWidth;
00409       ddsd.dwHeight = aHeight;
00410 
00411       mDDraw2->CreateSurface(&ddsd, &ddsurf, NULL);
00412     }
00413 
00414     if (NULL != ddsurf)
00415       mSurface = ddsurf;
00416     else
00417     {
00418       mDC = ::CreateCompatibleDC(aDC);
00419       mKillDC = PR_TRUE;
00420     }
00421   }
00422   else
00423 #endif
00424   {
00425     mDC = ::CreateCompatibleDC(aDC);
00426     mTechnology = ::GetDeviceCaps(mDC, TECHNOLOGY);
00427     mKillDC = PR_TRUE;
00428   }
00429 
00430 #ifdef NGLAYOUT_DDRAW
00431   if (nsnull == mSurface)
00432 #endif
00433   {
00434     HBITMAP tbits = nsnull;
00435 
00436     if (aWidth > 0 && aHeight > 0)
00437     {
00438       if ((aFlags & NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS) == 0)
00439         tbits = ::CreateCompatibleBitmap(aDC, aWidth, aHeight);
00440 
00441       // Create a DIB if we need Pixel Access, or if DDB creation failed
00442       if (nsnull == tbits)
00443       {
00444         void        *bits;
00445         BITMAPINFO  *binfo;
00446         int         depth;
00447 
00448         depth = ::GetDeviceCaps(aDC, BITSPIXEL);
00449         // Always use at least 24-bit bitmaps regardless of the device context.
00450         // See bug 228399 for more information.
00451         if (depth < 24)
00452           depth = 24;
00453 
00454         binfo = CreateBitmapInfo(aWidth, aHeight, depth);
00455 
00456         if (nsnull == binfo)
00457           return NS_ERROR_FAILURE;
00458 
00459         mSelectedBitmap = tbits = ::CreateDIBSection(aDC, binfo, DIB_RGB_COLORS, &bits, NULL, 0);
00460 
00461         if (NULL == mSelectedBitmap)
00462           return NS_ERROR_FAILURE;
00463 
00464         mBitmapInfo = binfo;
00465         mDIBits = (PRUint8 *)bits;
00466         mBitmap.bmWidthBytes = RASWIDTH(aWidth, depth);
00467         mBitmap.bmBitsPixel = depth;
00468       }
00469     }
00470     else
00471     {
00472       //we do this to make sure that the memory DC knows what the
00473       //bitmap format of the original DC was. this way, later
00474       //operations to create bitmaps from the memory DC will create
00475       //bitmaps with the correct properties.
00476 
00477       tbits = ::CreateCompatibleBitmap(aDC, 2, 2);
00478     }
00479 
00480     mOrigBitmap = (HBITMAP)::SelectObject(mDC, tbits);
00481   }
00482 
00483   mWidth = aWidth;
00484   mHeight = aHeight;
00485 
00486   return NS_OK;
00487 }
00488 
00489 NS_IMETHODIMP nsDrawingSurfaceWin :: GetDC(HDC *aDC)
00490 {
00491 #ifdef NGLAYOUT_DDRAW
00492   if (nsnull != mSurface)
00493   {
00494     if (0 == mSurfLockCnt)
00495       mSurface->GetDC(&mDC);
00496 
00497     mSurfLockCnt++;
00498   }
00499 #endif
00500 
00501   *aDC = mDC;
00502 
00503   return NS_OK;
00504 }
00505 
00506 
00507 NS_IMETHODIMP 
00508 nsDrawingSurfaceWin::GetTECHNOLOGY(PRInt32  *aTechnology)
00509 { 
00510   
00511   *aTechnology = mTechnology;
00512   return NS_OK;
00513 }
00514 
00515 
00516 
00517 NS_IMETHODIMP nsDrawingSurfaceWin :: ReleaseDC(void)
00518 {
00519 #ifdef NGLAYOUT_DDRAW
00520   if (nsnull != mSurface)
00521   {
00522     --mSurfLockCnt;
00523 
00524     if ((nsnull != mDC) && (mSurfLockCnt == 0))
00525     {
00526       mSurface->ReleaseDC(mDC);
00527       mDC = nsnull;
00528     }
00529   }
00530 #endif
00531 
00532   return NS_OK;
00533 }
00534 
00535 NS_IMETHODIMP nsDrawingSurfaceWin :: IsReleaseDCDestructive(PRBool *aDestructive)
00536 {
00537 #ifdef NGLAYOUT_DDRAW
00538   if (nsnull != mSurface)
00539     *aDestructive = PR_TRUE;
00540   else
00541 #endif
00542     *aDestructive = PR_FALSE;
00543 
00544   return NS_OK;
00545 }
00546 
00547 BITMAPINFO * nsDrawingSurfaceWin :: CreateBitmapInfo(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth,
00548                                                      void **aBits)
00549 {
00550   NS_ASSERTION(aDepth == 24 || aDepth == 32, "Unsupported bitmap depth");
00551 
00552   PRInt32 palsize, imagesize, spanbytes, allocsize;
00553   PRUint8 *colortable;
00554   DWORD   bicomp, masks[3];
00555   BITMAPINFO  *rv = nsnull;
00556 
00557   switch (aDepth)
00558   {
00559     case 24:
00560       palsize = 0;
00561       allocsize = 0;
00562       bicomp = BI_RGB;
00563 
00564       mPixFormat.mRedZeroMask = 0xff;
00565       mPixFormat.mGreenZeroMask = 0xff;
00566       mPixFormat.mBlueZeroMask = 0xff;
00567       mPixFormat.mAlphaZeroMask = 0;
00568       mPixFormat.mRedMask = 0xff0000;
00569       mPixFormat.mGreenMask = 0xff00;
00570       mPixFormat.mBlueMask = 0xff;
00571       mPixFormat.mAlphaMask = 0;
00572       mPixFormat.mRedCount = 8;
00573       mPixFormat.mGreenCount = 8;
00574       mPixFormat.mBlueCount = 8;
00575       mPixFormat.mAlphaCount = 0;
00576       mPixFormat.mRedShift = 16;
00577       mPixFormat.mGreenShift = 8;
00578       mPixFormat.mBlueShift = 0;
00579       mPixFormat.mAlphaShift = 0;
00580       
00581       break;
00582 
00583     case 32:
00584       palsize = 0;
00585       allocsize = 3;
00586       bicomp = BI_BITFIELDS;
00587       masks[0] = 0xff0000;
00588       masks[1] = 0x00ff00;
00589       masks[2] = 0x0000ff;
00590      
00591       mPixFormat.mRedZeroMask = 0xff;
00592       mPixFormat.mGreenZeroMask = 0xff;
00593       mPixFormat.mBlueZeroMask = 0xff;
00594       mPixFormat.mAlphaZeroMask = 0xff;
00595       mPixFormat.mRedMask = masks[0];
00596       mPixFormat.mGreenMask = masks[1];
00597       mPixFormat.mBlueMask = masks[2];
00598       mPixFormat.mAlphaMask = 0xff000000;
00599       mPixFormat.mRedCount = 8;
00600       mPixFormat.mGreenCount = 8;
00601       mPixFormat.mBlueCount = 8;
00602       mPixFormat.mAlphaCount = 8;
00603       mPixFormat.mRedShift = 16;
00604       mPixFormat.mGreenShift = 8;
00605       mPixFormat.mBlueShift = 0;
00606       mPixFormat.mAlphaShift = 24;
00607 
00608       break;
00609 
00610     default:
00611       palsize = -1;
00612       break;
00613   }
00614 
00615   if (palsize >= 0)
00616   {
00617     spanbytes = RASWIDTH(aWidth, aDepth);
00618     imagesize = spanbytes * aHeight;
00619 
00620     rv = (BITMAPINFO *)PR_Malloc(sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * allocsize));
00621 
00622     if (nsnull != rv)
00623     {
00624       rv->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00625       rv->bmiHeader.biWidth = aWidth;
00626       rv->bmiHeader.biHeight = -aHeight;
00627       rv->bmiHeader.biPlanes = 1;
00628       rv->bmiHeader.biBitCount = (unsigned short)aDepth;
00629       rv->bmiHeader.biCompression = bicomp;
00630       rv->bmiHeader.biSizeImage = imagesize;
00631       rv->bmiHeader.biXPelsPerMeter = 0;
00632       rv->bmiHeader.biYPelsPerMeter = 0;
00633       rv->bmiHeader.biClrUsed = palsize;
00634       rv->bmiHeader.biClrImportant = palsize;
00635 
00636       // set the color table in the info header
00637       colortable = (PRUint8 *)rv + sizeof(BITMAPINFOHEADER);
00638 
00639       if ((aDepth == 16) || (aDepth == 32))
00640         memcpy(colortable, masks, sizeof(DWORD) * allocsize);
00641       else
00642         memset(colortable, 0, sizeof(RGBQUAD) * palsize);
00643 
00644       if (nsnull != aBits) {
00645         *aBits = PR_Malloc(imagesize);
00646         if ( nsnull == *aBits ) {
00647           PR_Free(rv);
00648           rv = nsnull;
00649         }
00650       }
00651     }
00652   }
00653 
00654   return rv;
00655 }
00656 
00657 #ifdef NGLAYOUT_DDRAW
00658 
00659 PRBool nsDrawingSurfaceWin :: LockSurface(IDirectDrawSurface *aSurface, DDSURFACEDESC *aDesc,
00660                                           BITMAP *aBitmap, RECT *aRect, DWORD aLockFlags, nsPixelFormat *aPixFormat)
00661 {
00662   if (nsnull != aSurface)
00663   {
00664     aDesc->dwSize = sizeof(DDSURFACEDESC);
00665 
00666     if (DD_OK == aSurface->Lock(aRect, aDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | aLockFlags, NULL))
00667     {
00668       if ((aDesc->ddpfPixelFormat.dwFlags &
00669           (DDPF_ALPHA | DDPF_PALETTEINDEXED1 |
00670           DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXED4 |
00671           DDPF_PALETTEINDEXEDTO8 | DDPF_YUV | DDPF_ZBUFFER)) ||
00672           (aDesc->ddpfPixelFormat.dwRGBBitCount < 8))
00673       {
00674         //this is a surface that we can't, or don't want to handle.
00675 
00676         aSurface->Unlock(aDesc->lpSurface);
00677         return PR_FALSE;
00678       }
00679       
00680       aBitmap->bmType = 0;
00681       aBitmap->bmWidth = aDesc->dwWidth;
00682       aBitmap->bmHeight = aDesc->dwHeight;
00683       aBitmap->bmWidthBytes = aDesc->lPitch;
00684       aBitmap->bmPlanes = 1;
00685       aBitmap->bmBitsPixel = (PRUint16)aDesc->ddpfPixelFormat.dwRGBBitCount;
00686       aBitmap->bmBits = aDesc->lpSurface;
00687 
00688       if ((nsnull != aPixFormat) && (aBitmap->bmBitsPixel > 8))
00689       {
00690         DWORD btemp, shiftcnt;
00691 
00692         btemp = aDesc->ddpfPixelFormat.dwRBitMask;
00693 
00694         aPixFormat->mRedMask = btemp;
00695 
00696         shiftcnt = 32;
00697 
00698         if (!(btemp & 0xffff))
00699         {
00700           aPixFormat->mRedShift = 16;
00701           btemp >>= 16;
00702           shiftcnt = 16;
00703         }
00704         else if (!(btemp & 0xff))
00705         {
00706           aPixFormat->mRedShift = 8;
00707           btemp >>= 8;
00708           shiftcnt = 24;
00709         }
00710         else
00711         {
00712           aPixFormat->mRedShift = 0;
00713           shiftcnt = 32;
00714         }
00715 
00716         while (!(btemp & 1) && shiftcnt--)
00717         {
00718           btemp >>= 1;
00719           aPixFormat->mRedShift++;
00720         }
00721 
00722         aPixFormat->mRedZeroMask = btemp;
00723         aPixFormat->mRedCount = 0;
00724 
00725         while ((btemp & 1) && shiftcnt--)
00726         {
00727           btemp >>= 1;
00728           aPixFormat->mRedCount++;
00729         }
00730 
00731         btemp = aDesc->ddpfPixelFormat.dwGBitMask;
00732 
00733         aPixFormat->mGreenMask = btemp;
00734 
00735         shiftcnt = 32;
00736 
00737         if (!(btemp & 0xffff))
00738         {
00739           aPixFormat->mGreenShift = 16;
00740           btemp >>= 16;
00741           shiftcnt = 16;
00742         }
00743         else if (!(btemp & 0xff))
00744         {
00745           aPixFormat->mGreenShift = 8;
00746           btemp >>= 8;
00747           shiftcnt = 24;
00748         }
00749         else
00750         {
00751           aPixFormat->mGreenShift = 0;
00752           shiftcnt = 32;
00753         }
00754 
00755         while (!(btemp & 1) && shiftcnt--)
00756         {
00757           btemp >>= 1;
00758           aPixFormat->mGreenShift++;
00759         }
00760 
00761         aPixFormat->mGreenZeroMask = btemp;
00762         aPixFormat->mGreenCount = 0;
00763 
00764         while ((btemp & 1) && shiftcnt--)
00765         {
00766           btemp >>= 1;
00767           aPixFormat->mGreenCount++;
00768         }
00769 
00770         btemp = aDesc->ddpfPixelFormat.dwBBitMask;
00771 
00772         aPixFormat->mBlueMask = btemp;
00773 
00774         shiftcnt = 32;
00775 
00776         if (!(btemp & 0xffff))
00777         {
00778           aPixFormat->mBlueShift = 16;
00779           btemp >>= 16;
00780           shiftcnt = 16;
00781         }
00782         else if (!(btemp & 0xff))
00783         {
00784           aPixFormat->mBlueShift = 8;
00785           btemp >>= 8;
00786           shiftcnt = 24;
00787         }
00788         else
00789         {
00790           aPixFormat->mBlueShift = 0;
00791           shiftcnt = 32;
00792         }
00793 
00794         while (!(btemp & 1) && shiftcnt--)
00795         {
00796           btemp >>= 1;
00797           aPixFormat->mBlueShift++;
00798         }
00799 
00800         aPixFormat->mBlueZeroMask = btemp;
00801         aPixFormat->mBlueCount = 0;
00802 
00803         while ((btemp & 1) && shiftcnt--)
00804         {
00805           btemp >>= 1;
00806           aPixFormat->mBlueCount++;
00807         }
00808 
00809         aPixFormat->mAlphaCount = (PRUint8)aDesc->ddpfPixelFormat.dwAlphaBitDepth;
00810 
00811         if (aPixFormat->mAlphaCount > 0)
00812         {
00813           btemp = aDesc->ddpfPixelFormat.dwRGBAlphaBitMask;
00814 
00815           aPixFormat->mAlphaMask = btemp;
00816 
00817           shiftcnt = 32;
00818 
00819           if (!(btemp & 0xffff))
00820           {
00821             aPixFormat->mAlphaShift = 16;
00822             btemp >>= 16;
00823             shiftcnt = 16;
00824           }
00825           else if (!(btemp & 0xff))
00826           {
00827             aPixFormat->mAlphaShift = 8;
00828             btemp >>= 8;
00829             shiftcnt = 24;
00830           }
00831           else
00832           {
00833             aPixFormat->mAlphaShift = 0;
00834             shiftcnt = 32;
00835           }
00836 
00837           while (!(btemp & 1) && shiftcnt--)
00838           {
00839             btemp >>= 1;
00840             aPixFormat->mAlphaShift++;
00841           }
00842 
00843           aPixFormat->mAlphaZeroMask = btemp;
00844         }
00845         else
00846         {
00847           aPixFormat->mAlphaMask = 0;
00848           aPixFormat->mAlphaShift = 0;
00849           aPixFormat->mAlphaZeroMask = 0;
00850         }
00851       }
00852 
00853       return PR_TRUE;
00854     }
00855     else
00856       return PR_FALSE;
00857   }
00858   else
00859     return PR_FALSE;
00860 }
00861 
00862 nsresult nsDrawingSurfaceWin :: CreateDDraw()
00863 {
00864   if ((mDDraw2 == NULL) && (mDDrawResult == NS_OK))
00865   {
00866     CoInitialize(NULL);
00867 
00868     mDDrawResult = DirectDrawCreate(NULL, &mDDraw, NULL);
00869 
00870     if (mDDrawResult == NS_OK)
00871       mDDrawResult = mDDraw->QueryInterface(IID_IDirectDraw2, (LPVOID *)&mDDraw2);
00872 
00873     if (mDDrawResult == NS_OK)
00874     {
00875       mDDraw2->SetCooperativeLevel(NULL, DDSCL_NORMAL);
00876 
00877 #ifdef NS_DEBUG
00878       printf("using DirectDraw (%08X)\n", mDDraw2);
00879 
00880       DDSCAPS ddscaps;
00881       DWORD   totalmem, freemem;
00882     
00883       ddscaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
00884       nsresult res = mDDraw2->GetAvailableVidMem(&ddscaps, &totalmem, &freemem);
00885 
00886       if (NS_SUCCEEDED(res))
00887       {
00888         printf("total video memory: %d\n", totalmem);
00889         printf("free video memory: %d\n", freemem);
00890       }
00891       else
00892       {
00893         printf("GetAvailableVidMem() returned %08x: %s\n", res,
00894                (res == DDERR_NODIRECTDRAWHW) ?
00895                "no hardware ddraw driver available" : "unknown error code");
00896       }
00897 #endif
00898     }
00899   }
00900 
00901   return mDDrawResult;
00902 }
00903 
00904 nsresult nsDrawingSurfaceWin :: GetDDraw(IDirectDraw2 **aDDraw)
00905 {
00906   CreateDDraw();
00907 
00908   if (NULL != mDDraw2)
00909   {
00910     NS_ADDREF(mDDraw2);
00911     *aDDraw = mDDraw2;
00912   }
00913   else
00914     *aDDraw = NULL;
00915 
00916   return NS_OK;
00917 }
00918 
00919 #endif