Back to index

lightning-sunbird  0.9+nobinonly
nsDrawingSurfacePh.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 #include "nsDrawingSurfacePh.h"
00039 #include "nsCOMPtr.h"
00040 #include "nsIPref.h"
00041 #include "nsIServiceManager.h"
00042 #include "prmem.h"
00043 
00044 #include "nsPhGfxLog.h"
00045 #include <photon/PhRender.h>
00046 #include <Pt.h>
00047 #include <errno.h>
00048 
00049 static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
00050 
00051 nsPixelFormat nsDrawingSurfacePh::mPixFormat = {
00052        0, // mRedZeroMask;     //red color mask in zero position
00053        0, // mGreenZeroMask;   //green color mask in zero position
00054        0, // mBlueZeroMask;    //blue color mask in zero position
00055        0, // mAlphaZeroMask;   //alpha data mask in zero position
00056        0xff0000, // mRedMask;         //red color mask
00057        0x00ff00, // mGreenMask;       //green color mask
00058        0x0000ff, // mBlueMask;        //blue color mask
00059        0, // mAlphaMask;       //alpha data mask
00060        0, // mRedCount;        //number of red color bits
00061        0, // mGreenCount;      //number of green color bits
00062        0, // mBlueCount;       //number of blue color bits
00063        0, // mAlphaCount;      //number of alpha data bits
00064        16, // mRedShift;        //number to shift value into red position
00065        8, // mGreenShift;      //number to shift value into green position
00066        0, // mBlueShift;       //number to shift value into blue position
00067        0 // mAlphaShift;      //number to shift value into alpha position
00068        };
00069 
00070 NS_IMPL_ISUPPORTS2( nsDrawingSurfacePh, nsIDrawingSurface, nsIDrawingSurfacePh )
00071 
00072 nsDrawingSurfacePh :: nsDrawingSurfacePh( ) 
00073 {
00074        mDrawContext = nsnull;
00075        mGC = nsnull;
00076        mWidth = 0;
00077        mHeight = 0;
00078        mFlags = 0;
00079 
00080   mIsOffscreen = PR_FALSE;
00081        mLockDrawContext = nsnull;
00082        mLockWidth = 0;
00083        mLockHeight = 0;
00084        mLockFlags = 0;
00085        mLockX = 0;
00086        mLockY = 0;
00087        mLocked = PR_FALSE;
00088 }
00089 
00090 nsDrawingSurfacePh :: ~nsDrawingSurfacePh( ) 
00091 {
00092        if( mIsOffscreen ) {
00093               mDrawContext->gc = NULL;
00094               PhDCRelease( mDrawContext ); /* the mDrawContext->gc will be freed by the upper classes */
00095        }
00096        
00097        if( mLockDrawContext ) {
00098               PhDCRelease(mLockDrawContext);
00099        }
00100 
00101        if( mIsOffscreen ) {
00102               nsresult rv;
00103               nsCOMPtr<nsIPref> prefs = do_GetService(kPrefCID, &rv);
00104               if (NS_SUCCEEDED(rv)) {
00105                      prefs->UnregisterCallback("browser.display.internaluse.graphics_changed", prefChanged, (void *)this);
00106               }
00107 
00108               if( mGC ) PgDestroyGC( mGC );
00109        }
00110 }
00111 
00129 NS_IMETHODIMP nsDrawingSurfacePh :: Lock( PRInt32 aX, PRInt32 aY,
00130                                           PRUint32 aWidth, PRUint32 aHeight,
00131                                           void **aBits, PRInt32 *aStride,
00132                                           PRInt32 *aWidthBytes, PRUint32 aFlags ) {
00133 
00134        if( mLocked ) return NS_ERROR_FAILURE;
00135 
00136        PdOffscreenContext_t *odc = (PdOffscreenContext_t *) mDrawContext, *dc;
00137        int bpp, format = odc->format, offset;
00138 
00139        switch( format ) {
00140               case Pg_IMAGE_PALETTE_BYTE:
00141                      bpp = 1;
00142                      break;
00143               case Pg_IMAGE_DIRECT_8888:
00144                      bpp = 4;
00145               break;
00146               case Pg_IMAGE_DIRECT_888:
00147                      bpp = 3;
00148                      break;
00149               case Pg_IMAGE_DIRECT_565:
00150               case Pg_IMAGE_DIRECT_555:
00151                      bpp = 2;
00152                      break;
00153               default:
00154                   return NS_ERROR_FAILURE;
00155               }
00156 
00157 
00158        if( !( aFlags & NS_LOCK_SURFACE_READ_ONLY ) ) {
00159               PhArea_t dst_area, src_area;
00160 
00161               // create an offscreen context to save the locked rectangle into
00162               mLockDrawContext = ( PhDrawContext_t * )PdCreateOffscreenContext( format, aWidth, aHeight, Pg_OSC_MEM_PAGE_ALIGN );
00163               if( !mLockDrawContext ) return NS_ERROR_FAILURE;
00164            PgSetDrawBufferSizeCx( mLockDrawContext, 0xffff );
00165 
00166               dst_area.pos.x = dst_area.pos.y = 0;
00167               dst_area.size.w = aWidth;
00168               dst_area.size.h = aHeight;
00169               src_area.pos.x = aX;
00170               src_area.pos.y = aY;
00171               src_area.size.w = aWidth;
00172               src_area.size.h = aHeight;
00173 
00174               PhDCSetCurrent( mLockDrawContext );
00175               PgContextBlitAreaCx( mLockDrawContext, (PdOffscreenContext_t *)mDrawContext, &src_area, (PdOffscreenContext_t *) mLockDrawContext, &dst_area );
00176               PgFlushCx( mLockDrawContext );
00177               dc = (PdOffscreenContext_t *) mLockDrawContext; /* to be used to get the stride and bits */
00178               offset = 0;
00179               }
00180        else {
00181               mLockDrawContext = nsnull;
00182               dc = (PdOffscreenContext_t *) mDrawContext; /* to be used to get the stride and bits */
00183               offset = aX * bpp + aY * dc->pitch;
00184               }
00185 
00186        *aBits = PdGetOffscreenContextPtr( dc );
00187        if( *aBits == nsnull ) return NS_ERROR_FAILURE; /* on certain hardware this may fail */
00188 
00189        if( offset ) *aBits = ( (char*) *aBits ) + offset;
00190 
00191        *aWidthBytes = bpp * aWidth;
00192        *aStride = dc->pitch;
00193 
00194        mLocked = PR_TRUE;
00195        mLockX = aX;
00196        mLockY = aY;
00197        mLockWidth = aWidth;
00198        mLockHeight = aHeight;
00199        mLockFlags = aFlags;
00200 
00201        return NS_OK;
00202        }
00203 
00204 NS_IMETHODIMP nsDrawingSurfacePh :: Unlock( void ) {
00205        PhArea_t dst_area, src_area;
00206 
00207        if( !mLocked ) return NS_ERROR_FAILURE;
00208 
00209        // If the lock was not read only, put the bits back on the draw context
00210        if( !( mLockFlags & NS_LOCK_SURFACE_READ_ONLY ) ) {
00211               dst_area.pos.x = mLockX;
00212               dst_area.pos.y = mLockY;
00213               dst_area.size.w = mLockWidth;
00214               dst_area.size.h = mLockHeight;
00215               src_area.pos.x = src_area.pos.y = 0;
00216               src_area.size.w = mLockWidth;
00217               src_area.size.h = mLockHeight;
00218 
00219               PhDCSetCurrent( mDrawContext );
00220               PgContextBlitAreaCx( mDrawContext, (PdOffscreenContext_t *) mLockDrawContext, &src_area, (PdOffscreenContext_t *) mDrawContext, &dst_area );
00221               PgFlushCx( mDrawContext );
00222 
00223               // release the mLockDrawContext
00224               PhDCRelease( (PdDirectContext_t *) mLockDrawContext );
00225               mLockDrawContext = nsnull;
00226               }
00227 
00228        mLocked = PR_FALSE;
00229        return NS_OK;
00230        }
00231 
00232 NS_IMETHODIMP nsDrawingSurfacePh :: Init( PRUint32 aWidth, PRUint32 aHeight, PRUint32 aFlags ) {
00233        mWidth = aWidth;
00234        mHeight = aHeight;
00235        mFlags = aFlags;
00236        
00237        mIsOffscreen = PR_TRUE;
00238 
00239        /* an offscreen surface owns its own PhGC_t */
00240        mGC = PgCreateGC( 0 );
00241 
00242        mDrawContext = (PhDrawContext_t *)PdCreateOffscreenContext(0, mWidth, mHeight, Pg_OSC_MEM_PAGE_ALIGN);
00243        if( !mDrawContext ) return NS_ERROR_FAILURE;
00244 
00245        PgSetDrawBufferSizeCx( mDrawContext, 0xffff );
00246 
00247        nsresult rv;
00248        nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &rv));
00249        if (NS_SUCCEEDED(rv)) {
00250               prefs->RegisterCallback("browser.display.internaluse.graphics_changed", prefChanged, (void *)this);
00251               }
00252 
00253        return NS_OK;
00254        }
00255 
00256 int nsDrawingSurfacePh::prefChanged(const char *aPref, void *aClosure)
00257 {
00258        nsDrawingSurfacePh *surface = (nsDrawingSurfacePh*)aClosure;
00259        
00260        if( surface->mLockDrawContext ) {
00261               PhDCRelease(surface->mLockDrawContext);
00262               surface->mLockDrawContext = nsnull;
00263               }
00264 
00265        if(surface->mIsOffscreen) {
00266               PhDrawContext_t *newdc;
00267 
00268               newdc = (PhDrawContext_t *)PdCreateOffscreenContext(0, surface->mWidth, surface->mHeight, Pg_OSC_MEM_PAGE_ALIGN);
00269               if ( !newdc )
00270                      return NS_ERROR_FAILURE;
00271               surface->mDrawContext->gc = nsnull; /* because we do not want to destroy the one we have since other have it */
00272               PhDCRelease( surface->mDrawContext ); 
00273               surface->mDrawContext = newdc;
00274               PgSetDrawBufferSizeCx( surface->mDrawContext, 0xffff );
00275 
00276               PgDestroyGC(surface->mDrawContext->gc);
00277               surface->mDrawContext->gc = surface->mGC;
00278               /* use the gc provided */
00279        }
00280        return 0;
00281 }