diff options
Diffstat (limited to 'src')
73 files changed, 2532 insertions, 1400 deletions
diff --git a/src/3rdparty/README b/src/3rdparty/README index 2be1036..ef05674 100644 --- a/src/3rdparty/README +++ b/src/3rdparty/README @@ -20,3 +20,8 @@ have been removed: Some patches are applied from time to time. Recent patches can be found in the patches subdirectory. + + +The pvr2d.h & wsegl.h in the powervr directory are required for building +the PowerVR plugin on Qt for Embedded Linux. These headers are for SGX +based SoCs, but may also work on MBX SoCs. diff --git a/src/3rdparty/powervr/pvr2d.h b/src/3rdparty/powervr/pvr2d.h new file mode 100644 index 0000000..07f28c7 --- /dev/null +++ b/src/3rdparty/powervr/pvr2d.h @@ -0,0 +1,502 @@ +/*!**************************************************************************** +@File pvr2d.h +@Title PVR2D external header file +@Author Imagination Technologies +@Copyright Copyright (c) by Imagination Technologies Limited. + This specification is protected by copyright laws and contains + material proprietary to Imagination Technologies Limited. + You may use and distribute this specification free of charge for implementing + the functionality therein, without altering or removing any trademark, copyright, + or other notice from the specification. +@Platform Generic +@Description PVR2D definitions for PVR2D clients +******************************************************************************/ + + +/****************************************************************************** +Modifications :- +$Log: pvr2d.h $ +******************************************************************************/ + +#ifndef _PVR2D_H_ +#define _PVR2D_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* PVR2D Platform-specific definitions */ +#define PVR2D_EXPORT +#define PVR2D_IMPORT + + +#define PVR2D_REV_MAJOR 2 +#define PVR2D_REV_MINOR 1 + +typedef enum +{ + PVR2D_FALSE = 0, + PVR2D_TRUE +} PVR2D_BOOL; + + +/* error codes */ +typedef enum +{ + PVR2D_OK = 0, + PVR2DERROR_INVALID_PARAMETER = -1, + PVR2DERROR_DEVICE_UNAVAILABLE = -2, + PVR2DERROR_INVALID_CONTEXT = -3, + PVR2DERROR_MEMORY_UNAVAILABLE = -4, + PVR2DERROR_DEVICE_NOT_PRESENT = -5, + PVR2DERROR_IOCTL_ERROR = -6, + PVR2DERROR_GENERIC_ERROR = -7, + PVR2DERROR_BLT_NOTCOMPLETE = -8, + PVR2DERROR_HW_FEATURE_NOT_SUPPORTED = -9, + PVR2DERROR_NOT_YET_IMPLEMENTED = -10, + PVR2DERROR_MAPPING_FAILED = -11 +}PVR2DERROR; + + +/* pixel formats */ +typedef enum +{ + PVR2D_1BPP = 0, + PVR2D_RGB565, + PVR2D_ARGB4444, + PVR2D_RGB888, + PVR2D_ARGB8888, + PVR2D_ARGB1555, + PVR2D_ALPHA8, + PVR2D_ALPHA4, + PVR2D_PAL2, + PVR2D_PAL4, + PVR2D_PAL8, + PVR2D_VGAEMU + +}PVR2DFORMAT; + + +/* wrap surface type */ +typedef enum +{ + PVR2D_WRAPFLAG_NONCONTIGUOUS = 0, + PVR2D_WRAPFLAG_CONTIGUOUS = 1, + +}PVR2DWRAPFLAGS; + +/* flags for control information of additional blits */ +typedef enum +{ + PVR2D_BLIT_DISABLE_ALL = 0x0000, /* disable all additional controls */ + PVR2D_BLIT_CK_ENABLE = 0x0001, /* enable colour key */ + PVR2D_BLIT_GLOBAL_ALPHA_ENABLE = 0x0002, /* enable standard global alpha */ + PVR2D_BLIT_PERPIXEL_ALPHABLEND_ENABLE = 0x0004, /* enable per-pixel alpha bleding */ + PVR2D_BLIT_PAT_SURFACE_ENABLE = 0x0008, /* enable pattern surf (disable fill) */ + PVR2D_BLIT_FULLY_SPECIFIED_ALPHA_ENABLE = 0x0010, /* enable fully specified alpha */ + PVR2D_BLIT_ROT_90 = 0x0020, /* apply 90 degree rotation to the blt */ + PVR2D_BLIT_ROT_180 = 0x0040, /* apply 180 degree rotation to the blt */ + PVR2D_BLIT_ROT_270 = 0x0080, /* apply 270 degree rotation to the blt */ + PVR2D_BLIT_COPYORDER_TL2BR = 0x0100, /* copy order overrides */ + PVR2D_BLIT_COPYORDER_BR2TL = 0x0200, + PVR2D_BLIT_COPYORDER_TR2BL = 0x0400, + PVR2D_BLIT_COPYORDER_BL2TR = 0x0800, + PVR2D_BLIT_COLKEY_SOURCE = 0x1000, /* Key colour is on the source surface */ + PVR2D_BLIT_COLKEY_DEST = 0x2000 /* Key colour is on the destination surface */ + +} PVR2DBLITFLAGS; + +/* standard alpha-blending functions, AlphaBlendingFunc field of PVR2DBLTINFO */ +typedef enum +{ + PVR2D_ALPHA_OP_SRC_DSTINV = 1, /* source alpha : Cdst = Csrc*Asrc + Cdst*(1-Asrc) */ + PVR2D_ALPHA_OP_SRCP_DSTINV = 2 /* premultiplied source alpha : Cdst = Csrc + Cdst*(1-Asrc) */ +} PVR2D_ALPHABLENDFUNC; + +/* blend ops for fully specified alpha */ +typedef enum +{ + PVR2D_BLEND_OP_ZERO = 0, + PVR2D_BLEND_OP_ONE = 1, + PVR2D_BLEND_OP_SRC = 2, + PVR2D_BLEND_OP_DST = 3, + PVR2D_BLEND_OP_GLOBAL = 4, + PVR2D_BLEND_OP_SRC_PLUS_GLOBAL = 5, + PVR2D_BLEND_OP_DST_PLUS_GLOBAL = 6 +}PVR2D_BLEND_OP; + + +typedef void* PVR2D_HANDLE; + + +/* Fully specified alpha blend : pAlpha field of PVR2DBLTINFO structure */ +/* a fully specified Alpha Blend operation is defined as */ +/* DST (ALPHA) = (ALPHA_1 * SRC (ALPHA)) + (ALPHA_3 * DST (ALPHA)) */ +/* DST (RGB) = (ALPHA_2 * SRC (RGB)) + (ALPHA_4 * DST (RGB)) */ +/* if the pre-multiplication stage is enabled then the equations become the following: */ +/* PRE_MUL = ((SRC(A)) * (Global Alpha Value)) */ +/* DST (ALPHA) = (ALPHA_1 * SRC (ALPHA)) + (PRE_MUL * DST (ALPHA)) */ +/* DST (RGB) = (ALPHA_2 * SRC (RGB)) + (PRE_MUL * DST (RGB)) */ +/* if the transparent source alpha stage is enabled then a source alpha of zero forces the */ +/* source to be transparent for that pixel regardless of the blend equation being used. */ +typedef struct _PVR2D_ALPHABLT +{ + PVR2D_BLEND_OP eAlpha1; + PVR2D_BOOL bAlpha1Invert; + PVR2D_BLEND_OP eAlpha2; + PVR2D_BOOL bAlpha2Invert; + PVR2D_BLEND_OP eAlpha3; + PVR2D_BOOL bAlpha3Invert; + PVR2D_BLEND_OP eAlpha4; + PVR2D_BOOL bAlpha4Invert; + PVR2D_BOOL bPremulAlpha; /* enable pre-multiplication stage */ + PVR2D_BOOL bTransAlpha; /* enable transparent source alpha stage */ + PVR2D_BOOL bUpdateAlphaLookup; /* enable and update the 1555-Lookup alpha table */ + unsigned char uAlphaLookup0; /* 8 bit alpha when A=0 in a 1555-Lookup surface */ + unsigned char uAlphaLookup1; /* 8 bit alpha when A=1 in a 1555-Lookup surface */ + unsigned char uGlobalRGB; /* Global Alpha Value for RGB, 0=transparent 255=opaque */ + unsigned char uGlobalA; /* Global Alpha Value for Alpha */ + +} PVR2D_ALPHABLT, *PPVR2D_ALPHABLT; + + +/* surface memory info structure */ +typedef struct _PVR2DMEMINFO +{ + void *pBase; + unsigned long ui32MemSize; + unsigned long ui32DevAddr; + unsigned long ulFlags; + void *hPrivateData; + void *hPrivateMapData; + +}PVR2DMEMINFO, *PPVR2DMEMINFO; + + +#define PVR2D_MAX_DEVICE_NAME 20 + +typedef struct _PVR2DDEVICEINFO +{ + unsigned long ulDevID; + char szDeviceName[PVR2D_MAX_DEVICE_NAME]; +}PVR2DDEVICEINFO; + + +typedef struct _PVR2DISPLAYINFO +{ + unsigned long ulMaxFlipChains; + unsigned long ulMaxBuffersInChain; + PVR2DFORMAT eFormat; + unsigned long ulWidth; + unsigned long ulHeight; + long lStride; + unsigned long ulMinFlipInterval; + unsigned long ulMaxFlipInterval; + +}PVR2DDISPLAYINFO; + + +typedef struct _PVR2DBLTINFO +{ + unsigned long CopyCode; /* rop code */ + unsigned long Colour; /* fill colour */ + unsigned long ColourKey; /* colour key */ + unsigned char GlobalAlphaValue; /* global alpha blending */ + unsigned char AlphaBlendingFunc; /* per-pixel alpha-blending function */ + + PVR2DBLITFLAGS BlitFlags; /* additional blit control information */ + + PVR2DMEMINFO *pDstMemInfo; /* destination memory */ + unsigned long DstOffset; /* byte offset from start of allocation to destination surface pixel 0,0 */ + long DstStride; /* signed stride, the number of bytes from pixel 0,0 to 0,1 */ + long DstX, DstY; /* pixel offset from start of dest surface to start of blt rectangle */ + long DSizeX,DSizeY; /* blt size */ + PVR2DFORMAT DstFormat; /* dest format */ + unsigned long DstSurfWidth; /* size of dest surface in pixels */ + unsigned long DstSurfHeight; /* size of dest surface in pixels */ + + PVR2DMEMINFO *pSrcMemInfo; /* source mem, (source fields are also used for patterns) */ + unsigned long SrcOffset; /* byte offset from start of allocation to src/pat surface pixel 0,0 */ + long SrcStride; /* signed stride, the number of bytes from pixel 0,0 to 0,1 */ + long SrcX, SrcY; /* pixel offset from start of surface to start of source rectangle */ + /* for patterns this is the start offset within the pattern */ + long SizeX,SizeY; /* source rectangle size or pattern size in pixels */ + PVR2DFORMAT SrcFormat; /* source/pattern format */ + PVR2DMEMINFO *pPalMemInfo; /* source/pattern palette memory containing argb8888 colour table */ + unsigned long PalOffset; /* byte offset from start of allocation to start of palette */ + unsigned long SrcSurfWidth; /* size of source surface in pixels */ + unsigned long SrcSurfHeight; /* size of source surface in pixels */ + + PVR2DMEMINFO *pMaskMemInfo; /* mask memory, 1bpp format implied */ + unsigned long MaskOffset; /* byte offset from start of allocation to mask surface pixel 0,0 */ + long MaskStride; /* signed stride, the number of bytes from pixel 0,0 to 0,1 */ + long MaskX, MaskY; /* mask rect top left (mask size = blt size) */ + unsigned long MaskSurfWidth; /* size of mask surface in pixels */ + unsigned long MaskSurfHeight; /* size of mask surface in pixels */ + + PPVR2D_ALPHABLT pAlpha; /* fully specified alpha blend */ + +}PVR2DBLTINFO, *PPVR2DBLTINFO; + +typedef struct _PVR2DRECT +{ + long left, top; + long right, bottom; +} PVR2DRECT; + +typedef struct +{ + PVR2DMEMINFO *pSurfMemInfo; /* surface memory */ + unsigned long SurfOffset; /* byte offset from start of allocation to destination surface pixel 0,0 */ + long Stride; /* signed stride */ + PVR2DFORMAT Format; + unsigned long SurfWidth; /* surface size in pixels */ + unsigned long SurfHeight; + +} PVR2D_SURFACE, *PPVR2D_SURFACE; + +typedef struct +{ + unsigned long *pUseCode; /* USSE code */ + unsigned long UseCodeSize; /* usse code size in bytes */ + +} PVR2D_USECODE, *PPVR2D_USECODE; + +typedef struct +{ + PVR2D_SURFACE sDst; /* destination surface */ + PVR2D_SURFACE sSrc; /* source surface */ + PVR2DRECT rcDest; /* destination rectangle */ + PVR2DRECT rcSource; /* source rectangle */ + PVR2D_HANDLE hUseCode; /* custom USE code (NULL implies source copy) */ + unsigned long UseParams[2]; /* per-blt params for use code */ + +} PVR2D_3DBLT, *PPVR2D_3DBLT; + + +#define MAKE_COPY_BLIT(src,soff,dest,doff,sx,sy,dx,dy,sz) + +typedef void* PVR2DCONTEXTHANDLE; +typedef void* PVR2DFLIPCHAINHANDLE; + + +// CopyCode field of PVR2DBLTINFO structure: +// the CopyCode field of the PVR2DBLTINFO structure should contain a rop3 or rop4 code. +// a rop3 is an 8 bit code that describes a blt with three inputs : source dest and pattern +// rop4 is a 16 bit code that describes a blt with four inputs : source dest pattern and mask +// common rop3 codes are defined below +// a colour fill blt is processed in the pattern channel as a constant colour with a rop code of 0xF0 +// PVR2D_BLIT_PAT_SURFACE_ENABLE defines whether the pattern channel is a surface or a fill colour. +// a rop4 is defined by two rop3 codes, and the 1 bit-per-pixel mask surface defines which is used. +// a common rop4 is 0xAAF0 which is the mask copy blt used for text glyphs. +// CopyCode is taken to be a rop4 when pMaskMemInfo is non zero, otherwise it is assumed to be a rop3 +// use the PVR2DMASKROP4 macro below to construct a rop4 from two rop3's +// rop3a is the rop used when mask pixel = 1, and rop3b when mask = 0 +#define PVR2DROP4(rop3b, rop3a) ((rop3b<<8)|rop3a) + +/* common rop codes */ +#define PVR2DROPclear 0x00 /* 0 (whiteness) */ +#define PVR2DROPset 0xFF /* 1 (blackness) */ +#define PVR2DROPnoop 0xAA /* dst (used for masked blts) */ + +/* source and dest rop codes */ +#define PVR2DROPand 0x88 /* src AND dst */ +#define PVR2DROPandReverse 0x44 /* src AND NOT dst */ +#define PVR2DROPcopy 0xCC /* src (used for source copy and alpha blts) */ +#define PVR2DROPandInverted 0x22 /* NOT src AND dst */ +#define PVR2DROPxor 0x66 /* src XOR dst */ +#define PVR2DROPor 0xEE /* src OR dst */ +#define PVR2DROPnor 0x11 /* NOT src AND NOT dst */ +#define PVR2DROPequiv 0x99 /* NOT src XOR dst */ +#define PVR2DROPinvert 0x55 /* NOT dst */ +#define PVR2DROPorReverse 0xDD /* src OR NOT dst */ +#define PVR2DROPcopyInverted 0x33 /* NOT src */ +#define PVR2DROPorInverted 0xBB /* NOT src OR dst */ +#define PVR2DROPnand 0x77 /* NOT src OR NOT dst */ + +/* pattern rop codes */ +#define PVR2DPATROPand 0xA0 /* pat AND dst */ +#define PVR2DPATROPandReverse 0x50 /* pat AND NOT dst */ +#define PVR2DPATROPcopy 0xF0 /* pat (used for solid color fills and pattern blts) */ +#define PVR2DPATROPandInverted 0x0A /* NOT pat AND dst */ +#define PVR2DPATROPxor 0x5A /* pat XOR dst */ +#define PVR2DPATROPor 0xFA /* pat OR dst */ +#define PVR2DPATROPnor 0x05 /* NOT pat AND NOT dst */ +#define PVR2DPATROPequiv 0xA5 /* NOT pat XOR dst */ +#define PVR2DPATROPinvert 0x55 /* NOT dst */ +#define PVR2DPATROPorReverse 0xF5 /* pat OR NOT dst */ +#define PVR2DPATROPcopyInverted 0x0F /* NOT pat */ +#define PVR2DPATROPorInverted 0xAF /* NOT pat OR dst */ +#define PVR2DPATROPnand 0x5F /* NOT pat OR NOT dst */ + +/* common rop4 codes */ +#define PVR2DROP4MaskedCopy PVR2DROP4(PVR2DROPnoop,PVR2DROPcopy) /* masked source copy blt (used for rounded window corners etc) */ +#define PVR2DROP4MaskedFill PVR2DROP4(PVR2DROPnoop,PVR2DPATROPcopy) /* masked colour fill blt (used for text) */ + +/* Legacy support */ +#define PVR2DROP3_PATMASK PVR2DPATROPcopy +#define PVR2DROP3_SRCMASK PVR2DROPcopy + +/* pixmap memory alignment */ +#define PVR2D_ALIGNMENT_4 4 /* DWORD alignment */ +#define PVR2D_ALIGNMENT_ANY 0 /* no alignment */ +#define PVR2D_ALIGNMENT_PALETTE 16 /* 16 byte alignment is required for palettes */ + +/* Heap number for PVR2DGetFrameBuffer */ +#define PVR2D_FB_PRIMARY_SURFACE 0 + +#define PVR2D_PRESENT_PROPERTY_SRCSTRIDE (1 << 0) +#define PVR2D_PRESENT_PROPERTY_DSTSIZE (1 << 1) +#define PVR2D_PRESENT_PROPERTY_DSTPOS (1 << 2) +#define PVR2D_PRESENT_PROPERTY_CLIPRECTS (1 << 3) +#define PVR2D_PRESENT_PROPERTY_INTERVAL (1 << 4) + + +#define PVR2D_CREATE_FLIPCHAIN_SHARED (1 << 0) +#define PVR2D_CREATE_FLIPCHAIN_QUERY (1 << 1) + +/* Functions that the library exports */ + +PVR2D_IMPORT +int PVR2DEnumerateDevices(PVR2DDEVICEINFO *pDevInfo); + +PVR2D_IMPORT +PVR2DERROR PVR2DCreateDeviceContext(unsigned long ulDevID, + PVR2DCONTEXTHANDLE* phContext, + unsigned long ulFlags); + +PVR2D_IMPORT +PVR2DERROR PVR2DDestroyDeviceContext(PVR2DCONTEXTHANDLE hContext); + +PVR2D_IMPORT +PVR2DERROR PVR2DGetDeviceInfo(PVR2DCONTEXTHANDLE hContext, + PVR2DDISPLAYINFO *pDisplayInfo); + +PVR2D_IMPORT +PVR2DERROR PVR2DGetScreenMode(PVR2DCONTEXTHANDLE hContext, + PVR2DFORMAT *pFormat, + long *plWidth, + long *plHeight, + long *plStride, + int *piRefreshRate); + +PVR2D_IMPORT +PVR2DERROR PVR2DGetFrameBuffer(PVR2DCONTEXTHANDLE hContext, + int nHeap, + PVR2DMEMINFO **ppsMemInfo); + +PVR2D_IMPORT +PVR2DERROR PVR2DMemAlloc(PVR2DCONTEXTHANDLE hContext, + unsigned long ulBytes, + unsigned long ulAlign, + unsigned long ulFlags, + PVR2DMEMINFO **ppsMemInfo); + +PVR2D_IMPORT +PVR2DERROR PVR2DMemWrap(PVR2DCONTEXTHANDLE hContext, + void *pMem, + unsigned long ulFlags, + unsigned long ulBytes, + unsigned long alPageAddress[], + PVR2DMEMINFO **ppsMemInfo); + +PVR2D_IMPORT +PVR2DERROR PVR2DMemMap(PVR2DCONTEXTHANDLE hContext, + unsigned long ulFlags, + void *hPrivateMapData, + PVR2DMEMINFO **ppsDstMem); + +PVR2D_IMPORT +PVR2DERROR PVR2DMemFree(PVR2DCONTEXTHANDLE hContext, + PVR2DMEMINFO *psMemInfo); + +PVR2D_IMPORT +PVR2DERROR PVR2DBlt(PVR2DCONTEXTHANDLE hContext, + PVR2DBLTINFO *pBltInfo); + +PVR2D_IMPORT +PVR2DERROR PVR2DBltClipped(PVR2DCONTEXTHANDLE hContext, + PVR2DBLTINFO *pBltInfo, + unsigned long ulNumClipRects, + PVR2DRECT *pClipRects); + +PVR2D_IMPORT +PVR2DERROR PVR2DQueryBlitsComplete(PVR2DCONTEXTHANDLE hContext, + PVR2DMEMINFO *pMemInfo, + unsigned int uiWaitForComplete); + +PVR2D_IMPORT +PVR2DERROR PVR2DSetPresentBltProperties(PVR2DCONTEXTHANDLE hContext, + unsigned long ulPropertyMask, + long lSrcStride, + unsigned long ulDstWidth, + unsigned long ulDstHeight, + long lDstXPos, + long lDstYPos, + unsigned long ulNumClipRects, + PVR2DRECT *pClipRects, + unsigned long ulSwapInterval); + +PVR2D_IMPORT +PVR2DERROR PVR2DPresentBlt(PVR2DCONTEXTHANDLE hContext, + PVR2DMEMINFO *pMemInfo, + long lRenderID); + +PVR2D_IMPORT +PVR2DERROR PVR2DCreateFlipChain(PVR2DCONTEXTHANDLE hContext, + unsigned long ulFlags, + unsigned long ulNumBuffers, + unsigned long ulWidth, + unsigned long ulHeight, + PVR2DFORMAT eFormat, + long *plStride, + unsigned long *pulFlipChainID, + PVR2DFLIPCHAINHANDLE *phFlipChain); + +PVR2D_IMPORT +PVR2DERROR PVR2DDestroyFlipChain(PVR2DCONTEXTHANDLE hContext, + PVR2DFLIPCHAINHANDLE hFlipChain); + +PVR2D_IMPORT +PVR2DERROR PVR2DGetFlipChainBuffers(PVR2DCONTEXTHANDLE hContext, + PVR2DFLIPCHAINHANDLE hFlipChain, + unsigned long *pulNumBuffers, + PVR2DMEMINFO *psMemInfo[]); + +PVR2D_IMPORT +PVR2DERROR PVR2DSetPresentFlipProperties(PVR2DCONTEXTHANDLE hContext, + PVR2DFLIPCHAINHANDLE hFlipChain, + unsigned long ulPropertyMask, + long lDstXPos, + long lDstYPos, + unsigned long ulNumClipRects, + PVR2DRECT *pClipRects, + unsigned long ulSwapInterval); + +PVR2D_IMPORT +PVR2DERROR PVR2DPresentFlip(PVR2DCONTEXTHANDLE hContext, + PVR2DFLIPCHAINHANDLE hFlipChain, + PVR2DMEMINFO *psMemInfo, + long lRenderID); + +PVR2D_IMPORT +PVR2DERROR PVR2DGetAPIRev(long *lRevMajor, long *lRevMinor); + +PVR2D_IMPORT +PVR2DERROR PVR2DLoadUseCode (const PVR2DCONTEXTHANDLE hContext, const unsigned char *pUseCode, + const unsigned long UseCodeSize, PVR2D_HANDLE *pUseCodeHandle); +PVR2D_IMPORT +PVR2DERROR PVR2DFreeUseCode (const PVR2DCONTEXTHANDLE hContext, const PVR2D_HANDLE hUseCodeHandle); + +PVR2D_IMPORT +PVR2DERROR PVR2DBlt3D (const PVR2DCONTEXTHANDLE hContext, const PPVR2D_3DBLT pBlt3D); + +#ifdef __cplusplus +} +#endif + +#endif /* _PVR2D_H_ */ + +/****************************************************************************** + End of file (pvr2d.h) +******************************************************************************/ diff --git a/src/3rdparty/powervr/wsegl.h b/src/3rdparty/powervr/wsegl.h new file mode 100644 index 0000000..0490607 --- /dev/null +++ b/src/3rdparty/powervr/wsegl.h @@ -0,0 +1,240 @@ +/****************************************************************************** + Name : wsegl.h + Copyright : Copyright (c) Imagination Technologies Limited. + This specification is protected by copyright laws and contains + material proprietary to Imagination Technologies Limited. + You may use and distribute this specification free of charge for implementing + the functionality therein, without altering or removing any trademark, copyright, + or other notice from the specification. + Platform : ANSI +*****************************************************************************/ + + +#if !defined(__WSEGL_H__) +#define __WSEGL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +// WSEGL Platform-specific definitions +*/ +#define WSEGL_EXPORT +#define WSEGL_IMPORT + +/* +// WSEGL API Version Number +*/ + +#define WSEGL_VERSION 1 +#define WSEGL_DEFAULT_DISPLAY 0 +#define WSEGL_DEFAULT_NATIVE_ENGINE 0 + +#define WSEGL_FALSE 0 +#define WSEGL_TRUE 1 +#define WSEGL_NULL 0 + +#define WSEGL_UNREFERENCED_PARAMETER(param) (param) = (param) + +/* +// WSEGL handles +*/ +typedef void *WSEGLDisplayHandle; +typedef void *WSEGLDrawableHandle; + +/* +// Display capability type +*/ +typedef enum WSEGLCapsType_TAG +{ + WSEGL_NO_CAPS = 0, + WSEGL_CAP_MIN_SWAP_INTERVAL = 1, /* System default value = 1 */ + WSEGL_CAP_MAX_SWAP_INTERVAL = 2, /* System default value = 1 */ + WSEGL_CAP_WINDOWS_USE_HW_SYNC = 3, /* System default value = 0 (FALSE) */ + WSEGL_CAP_PIXMAPS_USE_HW_SYNC = 4, /* System default value = 0 (FALSE) */ + +} WSEGLCapsType; + +/* +// Display capability +*/ +typedef struct WSEGLCaps_TAG +{ + WSEGLCapsType eCapsType; + unsigned long ui32CapsValue; + +} WSEGLCaps; + +/* +// Drawable type +*/ +#define WSEGL_NO_DRAWABLE 0x0 +#define WSEGL_DRAWABLE_WINDOW 0x1 +#define WSEGL_DRAWABLE_PIXMAP 0x2 + + +/* +// Pixel format of display/drawable +*/ +typedef enum WSEGLPixelFormat_TAG +{ + WSEGL_PIXELFORMAT_565 = 0, + WSEGL_PIXELFORMAT_4444 = 1, + WSEGL_PIXELFORMAT_8888 = 2, + WSEGL_PIXELFORMAT_1555 = 3 + +} WSEGLPixelFormat; + +/* +// Transparent of display/drawable +*/ +typedef enum WSEGLTransparentType_TAG +{ + WSEGL_OPAQUE = 0, + WSEGL_COLOR_KEY = 1, + +} WSEGLTransparentType; + +/* +// Display/drawable configuration +*/ +typedef struct WSEGLConfig_TAG +{ + /* + // Type of drawables this configuration applies to - + // OR'd values of drawable types. + */ + unsigned long ui32DrawableType; + + /* Pixel format */ + WSEGLPixelFormat ePixelFormat; + + /* Native Renderable - set to WSEGL_TRUE if native renderable */ + unsigned long ulNativeRenderable; + + /* FrameBuffer Level Parameter */ + unsigned long ulFrameBufferLevel; + + /* Native Visual ID */ + unsigned long ulNativeVisualID; + + /* Native Visual */ + void *hNativeVisual; + + /* Transparent Type */ + WSEGLTransparentType eTransparentType; + + /* Transparent Color - only used if transparent type is COLOR_KEY */ + unsigned long ulTransparentColor; /* packed as 0x00RRGGBB */ + + +} WSEGLConfig; + +/* +// WSEGL errors +*/ +typedef enum WSEGLError_TAG +{ + WSEGL_SUCCESS = 0, + WSEGL_CANNOT_INITIALISE = 1, + WSEGL_BAD_NATIVE_DISPLAY = 2, + WSEGL_BAD_NATIVE_WINDOW = 3, + WSEGL_BAD_NATIVE_PIXMAP = 4, + WSEGL_BAD_NATIVE_ENGINE = 5, + WSEGL_BAD_DRAWABLE = 6, + WSEGL_BAD_CONFIG = 7, + WSEGL_OUT_OF_MEMORY = 8 + +} WSEGLError; + +/* +// Drawable orientation (in degrees anti-clockwise) +*/ +typedef enum WSEGLRotationAngle_TAG +{ + WSEGL_ROTATE_0 = 0, + WSEGL_ROTATE_90 = 1, + WSEGL_ROTATE_180 = 2, + WSEGL_ROTATE_270 = 3 + +} WSEGLRotationAngle; + +/* +// Drawable information required by OpenGL-ES driver +*/ +typedef struct WSEGLDrawableParams_TAG +{ + /* Width in pixels of the drawable */ + unsigned long ui32Width; + + /* Height in pixels of the drawable */ + unsigned long ui32Height; + + /* Stride in pixels of the drawable */ + unsigned long ui32Stride; + + /* Pixel format of the drawable */ + WSEGLPixelFormat ePixelFormat; + + /* User space cpu virtual address of the drawable */ + void *pvLinearAddress; + + /* HW address of the drawable */ + unsigned long ui32HWAddress; + + /* Private data for the drawable */ + void *hPrivateData; + +} WSEGLDrawableParams; + + +/* +// Table of function pointers that is returned by WSEGL_GetFunctionTablePointer() +// +// The first entry in the table is the version number of the wsegl.h header file that +// the module has been written against, and should therefore be set to WSEGL_VERSION +*/ +typedef struct WSEGL_FunctionTable_TAG +{ + unsigned long ui32WSEGLVersion; + + WSEGLError (*pfnWSEGL_IsDisplayValid)(NativeDisplayType); + + WSEGLError (*pfnWSEGL_InitialiseDisplay)(NativeDisplayType, WSEGLDisplayHandle *, const WSEGLCaps **, WSEGLConfig **); + + WSEGLError (*pfnWSEGL_CloseDisplay)(WSEGLDisplayHandle); + + WSEGLError (*pfnWSEGL_CreateWindowDrawable)(WSEGLDisplayHandle, WSEGLConfig *, WSEGLDrawableHandle *, NativeWindowType, WSEGLRotationAngle *); + + WSEGLError (*pfnWSEGL_CreatePixmapDrawable)(WSEGLDisplayHandle, WSEGLConfig *, WSEGLDrawableHandle *, NativePixmapType, WSEGLRotationAngle *); + + WSEGLError (*pfnWSEGL_DeleteDrawable)(WSEGLDrawableHandle); + + WSEGLError (*pfnWSEGL_SwapDrawable)(WSEGLDrawableHandle, unsigned long); + + WSEGLError (*pfnWSEGL_SwapControlInterval)(WSEGLDrawableHandle, unsigned long); + + WSEGLError (*pfnWSEGL_WaitNative)(WSEGLDrawableHandle, unsigned long); + + WSEGLError (*pfnWSEGL_CopyFromDrawable)(WSEGLDrawableHandle, NativePixmapType); + + WSEGLError (*pfnWSEGL_CopyFromPBuffer)(void *, unsigned long, unsigned long, unsigned long, WSEGLPixelFormat, NativePixmapType); + + WSEGLError (*pfnWSEGL_GetDrawableParameters)(WSEGLDrawableHandle, WSEGLDrawableParams *, WSEGLDrawableParams *); + + +} WSEGL_FunctionTable; + + +WSEGL_IMPORT const WSEGL_FunctionTable *WSEGL_GetFunctionTablePointer(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __WSEGL_H__ */ + +/****************************************************************************** + End of file (wsegl.h) +******************************************************************************/ diff --git a/src/corelib/concurrent/qfutureinterface.h b/src/corelib/concurrent/qfutureinterface.h index 85d03c9..345bebe 100644 --- a/src/corelib/concurrent/qfutureinterface.h +++ b/src/corelib/concurrent/qfutureinterface.h @@ -165,6 +165,8 @@ public: QFutureInterface &operator=(const QFutureInterface &other) { + if (referenceCountIsOne()) + resultStore().clear(); QFutureInterfaceBase::operator=(other); return *this; } diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index ada08c7..29e356e 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -485,100 +485,27 @@ QT_END_NAMESPACE #if defined(Q_CC_GNU) && defined(Q_OS_LINUX) && !defined(QT_LINUXBASE) && !defined(QT_BOOTSTRAPPED) -# include <sys/syscall.h> -# include <unistd.h> - -static const char boilerplate[] = - "This is the QtCore library version " QT_VERSION_STR "\n" - "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).\n" - "Contact: Qt Software Information (qt-info@nokia.com)\n" - "\n" - "Build key: " QT_BUILD_KEY; - -extern "C" { -void qt_core_init_boilerplate() __attribute__((noreturn)); -} +# include <stdio.h> +# include <stdlib.h> -# if defined(QT_ARCH_I386) -#define sysinit() (void)0 -#define syswrite(msg, len) \ - ({ int res; \ - asm volatile ("movl %%ebx, %%edi\n" \ - "movl $1, %%ebx\n" \ - "int $0x80\n" \ - "movl %%edi, %%ebx\n" \ - : "=a" (res) : "0" (SYS_write), "c" (msg), "d" (len) : "edi"); res; }) -#define sysexit(c) \ - asm ("xor %%ebx, %%ebx\n" \ - "int $0x80\n" \ - : : "a" (SYS_exit)); _exit(c) - -# elif defined(QT_ARCH_X86_64) -#define sysinit() (void)0 -#define syswrite(msg, len) \ - ({ int res; \ - asm volatile ("syscall\n" \ - : "=a" (res) : "0" (SYS_write), "D" (1), "S" (msg), "d" (len) : "rcx"); res; }) -#define sysexit(c) \ - asm ("syscall\n" \ - : : "a" (SYS_exit), "D" (0)); _exit(c) - -# elif defined(QT_ARCH_IA64) -#define sysinit() \ - asm volatile ("{.mlx\n" \ - " nop.m 0\n" \ - " movl r2 = @pcrel(boilerplate);;" \ - "}\n" \ - "{.mii\n" \ - " mov r10 = @ltoffx(boilerplate)\n" \ - " mov r1 = ip\n" \ - " adds r2 = -16, r2\n;;\n" \ - "}\n" \ - " add r1 = r2, r1;;\n" \ - " sub r1 = r1, r10;;\n" \ - : : : "r2", "r10") -#define syswrite(msg, len) \ - ({ const char *_msg = msg; \ - asm ("mov out0=%1\n" \ - "mov out1=%2\n" \ - "mov out2=%3\n" \ - ";;\n" \ - "mov r15=%0\n" \ - "break 0x100000;;\n" \ - : : "I" (SYS_write), "I" (1), "r" (_msg), "r" (len)); }) -#define sysexit(c) \ - asm ("mov out0=%1\n" \ - ";;\n" \ - "mov r15=%0\n" \ - "break 0x100000;;\n" \ - : : "I" (SYS_exit), "O" (0)); write(1, 0, 0); _exit(c) -# else -#define sysinit() (void)0 -#define syswrite(msg, len) (msg); (len) -#define sysexit(c) __builtin_exit(c) -# endif - -#define sysputs(msg) syswrite(msg, -1 + sizeof(msg)) -#define sysendl() syswrite("\n", 1) -#define print_qt_configure(_which) \ - ({const char *which = _which; \ - which += 12; \ - int len = 0; \ - while (which[len]) ++len; \ - syswrite(which, len); }) +extern const char qt_core_interpreter[] __attribute__((section(".interp"))) + = "/lib/ld-linux.so.2"; +extern "C" void qt_core_init_boilerplate() { - sysinit(); - sysputs(boilerplate); - sysputs("\nInstallation prefix: "); - print_qt_configure(qt_configure_prefix_path_str); - sysputs("\nLibrary path: "); - print_qt_configure(qt_configure_libraries_path_str); - sysputs("\nInclude path: "); - print_qt_configure(qt_configure_headers_path_str); - sysendl(); - sysexit(0); + printf("This is the QtCore library version " QT_VERSION_STR "\n" + "Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).\n" + "Contact: Qt Software Information (qt-info@nokia.com)\n" + "\n" + "Build key: " QT_BUILD_KEY "\n" + "Installation prefix: %s\n" + "Library path: %s\n" + "Include path: %s\n", + qt_configure_prefix_path_str + 12, + qt_configure_libraries_path_str + 12, + qt_configure_headers_path_str + 12); + exit(0); } #endif diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index a57c00e..2df13f0 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -346,8 +346,15 @@ bool QFSFileEnginePrivate::uncListSharesOnServer(const QString &server, QStringL static bool isUncRoot(const QString &server) { QString localPath = QDir::toNativeSeparators(server); - QStringList parts = localPath.split(QLatin1Char('\\'), QString::SkipEmptyParts); - return localPath.startsWith(QLatin1String("\\\\")) && parts.count() <= 1; + if (!localPath.startsWith(QLatin1String("\\\\"))) + return false; + + int idx = localPath.indexOf(QLatin1Char('\\'), 2); + if (idx == -1 || idx + 1 == localPath.length()) + return true; + + localPath = localPath.right(localPath.length() - idx - 1).trimmed(); + return localPath.isEmpty(); } static bool isUncPath(const QString &path) diff --git a/src/corelib/tools/qlistdata.cpp b/src/corelib/tools/qlistdata.cpp index d7c39a7..d40b6b6 100644 --- a/src/corelib/tools/qlistdata.cpp +++ b/src/corelib/tools/qlistdata.cpp @@ -764,6 +764,10 @@ void **QListData::erase(void **xi) This function requires the value type to have an implementation of \c operator==(). + Note that QList uses 0-based indexes, just like C++ arrays. Negative + indexes are not supported with the exception of the value mentioned + above. + \sa lastIndexOf(), contains() */ @@ -780,6 +784,10 @@ void **QListData::erase(void **xi) This function requires the value type to have an implementation of \c operator==(). + Note that QList uses 0-based indexes, just like C++ arrays. Negative + indexes are not supported with the exception of the value mentioned + above. + \sa indexOf() */ diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 8c701f5..2c27381 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1102,7 +1102,7 @@ void QDBusConnectionPrivate::socketWrite(int fd) } for (int i = 0; i < pendingWatches.size(); ++i) - if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_READABLE)) + if (!q_dbus_watch_handle(pendingWatches[i], DBUS_WATCH_WRITABLE)) qDebug("OUT OF MEM"); } diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 7056575..b911ee0 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -99,9 +99,8 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook order to select one or many files or a directory. The easiest way to create a QFileDialog is to use the static - functions. On Windows, these static functions will call the native - Windows file dialog, and on Mac OS X these static function will call - the native Mac OS X file dialog. + functions. On Windows, Mac OS X, KDE and GNOME, these static functions will + call the native file dialog when possible. \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 0 @@ -219,7 +218,7 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook are resolved. \value DontConfirmOverwrite Don't ask for confirmation if an existing file is selected. By default confirmation is requested. - \value DontUseNativeDialog Don't use the native file dialog. By default on Mac OS X and Windows, + \value DontUseNativeDialog Don't use the native file dialog. By default on Mac OS X, the native file dialog is used unless you use a subclass of QFileDialog that contains the Q_OBJECT macro. \value ReadOnly Indicates that the model is readonly. @@ -1541,52 +1540,51 @@ extern QString qt_win_get_existing_directory(const QFileDialogArgs &args); #endif /*! - This is a convenience static function that returns an existing file - selected by the user. If the user presses Cancel, it returns a null - string. + This is a convenience static function that returns an existing file + selected by the user. If the user presses Cancel, it returns a null string. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 8 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 8 - The function creates a modal file dialog with the given \a parent widget. - If the parent is not 0, the dialog will be shown centered over the - parent widget. + The function creates a modal file dialog with the given \a parent widget. + If \a parent is not 0, the dialog will be shown centered over the parent + widget. - The file dialog's working directory will be set to \a dir. If \a - dir includes a file name, the file will be selected. Only files - that match the given \a filter are shown. The filter selected is - set to \a selectedFilter. The parameters \a dir, \a - selectedFilter, and \a filter may be empty strings. If you want - multiple filters, separate them with ';;', for example: + The file dialog's working directory will be set to \a dir. If \a dir + includes a file name, the file will be selected. Only files that match the + given \a filter are shown. The filter selected is set to \a selectedFilter. + The parameters \a dir, \a selectedFilter, and \a filter may be empty + strings. If you want multiple filters, separate them with ';;', for + example: - \code + \code "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" - \endcode + \endcode - The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. - The dialog's caption is set to \a caption. If \a caption is not - specified then a default caption will be used. + The dialog's caption is set to \a caption. If \a caption is not specified + then a default caption will be used. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks, - the file dialog will treat symlinks as regular directories. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If + \a options includes DontResolveSymlinks, the file dialog will treat + symlinks as regular directories. - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory() + \sa getOpenFileNames(), getSaveFileName(), getExistingDirectory() */ QString QFileDialog::getOpenFileName(QWidget *parent, const QString &caption, @@ -1629,54 +1627,53 @@ QString QFileDialog::getOpenFileName(QWidget *parent, } /*! - This is a convenience static function that will return one or more - existing files selected by the user. + This is a convenience static function that will return one or more existing + files selected by the user. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 9 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 9 - This function creates a modal file dialog with the given \a parent - widget. If the parent is not 0, the dialog will be shown centered - over the parent widget. + This function creates a modal file dialog with the given \a parent widget. + If \a parent is not 0, the dialog will be shown centered over the parent + widget. - The file dialog's working directory will be set to \a dir. If \a - dir includes a file name, the file will be selected. The filter - is set to \a filter so that only those files which match the filter - are shown. The filter selected is set to \a selectedFilter. The parameters - \a dir, \a selectedFilter and \a filter may be empty strings. If you - need multiple filters, separate them with ';;', for instance: + The file dialog's working directory will be set to \a dir. If \a dir + includes a file name, the file will be selected. The filter is set to + \a filter so that only those files which match the filter are shown. The + filter selected is set to \a selectedFilter. The parameters \a dir, + \a selectedFilter and \a filter may be empty strings. If you need multiple + filters, separate them with ';;', for instance: - \code + \code "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" - \endcode + \endcode - The dialog's caption is set to \a caption. If \a caption is not - specified then a default caption will be used. + The dialog's caption is set to \a caption. If \a caption is not specified + then a default caption will be used. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. On Mac OS X, the \a dir argument - is ignored, the native dialog always displays the last visited directory. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. - Note that if you want to iterate over the list of files, you should - iterate over a copy. For example: + \note If you want to iterate over the list of files, you should iterate + over a copy. For example: \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 10 - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileName(), getSaveFileName(), getExistingDirectory() + \sa getOpenFileName(), getSaveFileName(), getExistingDirectory() */ QStringList QFileDialog::getOpenFileNames(QWidget *parent, const QString &caption, @@ -1720,54 +1717,54 @@ QStringList QFileDialog::getOpenFileNames(QWidget *parent, } /*! - This is a convenience static function that will return a file name - selected by the user. The file does not have to exist. + This is a convenience static function that will return a file name selected + by the user. The file does not have to exist. - It creates a modal file dialog with the given \a parent widget. If the - parent is not 0, the dialog will be shown centered over the parent - widget. + It creates a modal file dialog with the given \a parent widget. If + \a parent is not 0, the dialog will be shown centered over the parent + widget. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 11 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 11 - The file dialog's working directory will be set to \a dir. If \a - dir includes a file name, the file will be selected. Only files that - match the \a filter are shown. The filter selected is set to - \a selectedFilter. The parameters \a dir, \a selectedFilter, and - \a filter may be empty strings. Multiple filters are separated with ';;'. - For instance: + The file dialog's working directory will be set to \a dir. If \a dir + includes a file name, the file will be selected. Only files that match the + \a filter are shown. The filter selected is set to \a selectedFilter. The + parameters \a dir, \a selectedFilter, and \a filter may be empty strings. + Multiple filters are separated with ';;'. For instance: - \code + \code "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" - \endcode + \endcode - The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. - The default filter can be chosen by setting \a selectedFilter to the desired value. + The default filter can be chosen by setting \a selectedFilter to the + desired value. - The dialog's caption is set to \a caption. If \a caption is not - specified then a default caption will be used. + The dialog's caption is set to \a caption. If \a caption is not specified, + a default caption will be used. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. - On Mac OS X, the filter argument is ignored. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. On Mac OS X, with its native file + dialog, the filter argument is ignored. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks, - the file dialog will treat symlinks as regular directories. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If + \a options includes DontResolveSymlinks the file dialog will treat symlinks + as regular directories. - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory() + \sa getOpenFileName(), getOpenFileNames(), getExistingDirectory() */ QString QFileDialog::getSaveFileName(QWidget *parent, const QString &caption, @@ -1813,46 +1810,43 @@ QString QFileDialog::getSaveFileName(QWidget *parent, } /*! - This is a convenience static function that will return an existing - directory selected by the user. + This is a convenience static function that will return an existing + directory selected by the user. - \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 12 + \snippet doc/src/snippets/code/src_gui_dialogs_qfiledialog.cpp 12 - This function creates a modal file dialog with the given \a parent - widget. If the parent is not 0, the dialog will be shown centered over - the parent widget. + This function creates a modal file dialog with the given \a parent widget. + If \a parent is not 0, the dialog will be shown centered over the parent + widget. - The dialog's working directory is set to \a dir, and the caption is - set to \a caption. Either of these may be an empty string in which case - the current directory and a default caption will be used - respectively. + The dialog's working directory is set to \a dir, and the caption is set to + \a caption. Either of these may be an empty string in which case the + current directory and a default caption will be used respectively. - The \a options argument holds various - options about how to run the dialog, see the QFileDialog::Option enum for - more information on the flags you can pass. Note that \l{QFileDialog::}{ShowDirsOnly} - must be set to ensure a native file dialog. + The \a options argument holds various options about how to run the dialog, + see the QFileDialog::Option enum for more information on the flags you can + pass. To ensure a native file dialog, \l{QFileDialog::}{ShowDirsOnly} must + be set. - Under Windows and Mac OS X, this static function will use the native - file dialog and not a QFileDialog. On Mac OS X, the \a dir argument - is ignored, the native dialog always displays the last visited directory. - On Windows CE, if the device has no native file dialog, a QFileDialog - will be used. + On Windows and Mac OS X, this static function will use the native file + dialog and not a QFileDialog. On Windows CE, if the device has no native + file dialog, a QFileDialog will be used. - Under Unix/X11, the normal behavior of the file dialog is to resolve - and follow symlinks. For example, if \c{/usr/tmp} is a symlink to - \c{/var/tmp}, the file dialog will change to \c{/var/tmp} after - entering \c{/usr/tmp}. If \a options includes DontResolveSymlinks, - the file dialog will treat symlinks as regular directories. + On Unix/X11, the normal behavior of the file dialog is to resolve and + follow symlinks. For example, if \c{/usr/tmp} is a symlink to \c{/var/tmp}, + the file dialog will change to \c{/var/tmp} after entering \c{/usr/tmp}. If + \a options includes DontResolveSymlinks, the file dialog will treat + symlinks as regular directories. - Note that on Windows the dialog will spin a blocking modal event loop - that will not dispatch any QTimers, and if parent is not 0 then it will - position the dialog just under the parent's title bar. + On Windows the dialog will spin a blocking modal event loop that will not + dispatch any QTimers, and if \a parent is not 0 then it will position the + dialog just below the parent's title bar. - \warning Do not delete \a parent during the execution of the dialog. - If you want to do this, you should create the dialog - yourself using one of the QFileDialog constructors. + \warning Do not delete \a parent during the execution of the dialog. If you + want to do this, you should create the dialog yourself using one of the + QFileDialog constructors. - \sa getOpenFileName(), getOpenFileNames(), getSaveFileName() + \sa getOpenFileName(), getOpenFileNames(), getSaveFileName() */ QString QFileDialog::getExistingDirectory(QWidget *parent, const QString &caption, @@ -2801,7 +2795,7 @@ void QFileDialogPrivate::_q_enterDirectory(const QModelIndex &index) { Q_Q(QFileDialog); // My Computer or a directory - QModelIndex sourceIndex = mapToSource(index); + QModelIndex sourceIndex = index.model() == proxyModel ? mapToSource(index) : index; QString path = sourceIndex.data(QFileSystemModel::FilePathRole).toString(); if (path.isEmpty() || model->isDir(sourceIndex)) { q->setDirectory(path); diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm index 42be3be..50917a1 100644 --- a/src/gui/dialogs/qfontdialog_mac.mm +++ b/src/gui/dialogs/qfontdialog_mac.mm @@ -87,7 +87,6 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin NSButton *mOkButton; NSButton *mCancelButton; QFontDialogPrivate *mPriv; - NSFont *mCocoaFont; QFont *mQtFont; BOOL mPanelHackedWithButtons; CGFloat mDialogExtraWidth; @@ -119,6 +118,29 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin - (void)cleanUpAfterMyself; @end +static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) +{ + QFont newFont; + if (cocoaFont) { + int pSize = qRound([cocoaFont pointSize]); + QString family(QCFString::toQString(reinterpret_cast<CFStringRef>([cocoaFont familyName]))); + QString typeface(QCFString::toQString(reinterpret_cast<CFStringRef>([cocoaFont fontName]))); +// qDebug() << "original family" << family << "typeface" << typeface << "psize" << pSize; + int hyphenPos = typeface.indexOf(QLatin1Char('-')); + if (hyphenPos != -1) { + typeface.remove(0, hyphenPos + 1); + } else { + typeface = QLatin1String("Normal"); + } +// qDebug() << " massaged family" << family << "typeface" << typeface << "psize" << pSize; + newFont = QFontDatabase().font(family, typeface, pSize); + newFont.setUnderline(resolveFont.underline()); + newFont.setStrikeOut(resolveFont.strikeOut()); + + } + return newFont; +} + @implementation QCocoaFontPanelDelegate - (id)initWithFontPanel:(NSFontPanel *)panel stolenContentView:(NSView *)stolenContentView @@ -134,7 +156,6 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin mOkButton = okButton; mCancelButton = cancelButton; mPriv = priv; - mCocoaFont = 0; mPanelHackedWithButtons = (okButton != 0); mDialogExtraWidth = extraWidth; mDialogExtraHeight = extraHeight; @@ -155,42 +176,14 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin - (void)dealloc { - if (mCocoaFont) - [mCocoaFont release]; delete mQtFont; [super dealloc]; } - (void)changeFont:(id)sender { - Q_UNUSED(sender); - - QFont newFont; - - if (mCocoaFont) - [mCocoaFont autorelease]; NSFont *dummyFont = [NSFont userFontOfSize:12.0]; - mCocoaFont = [sender convertFont:dummyFont]; - if (mCocoaFont) { - [mCocoaFont retain]; - - int pSize = qRound([mCocoaFont pointSize]); - QString family(QCFString::toQString(reinterpret_cast<CFStringRef>([mCocoaFont familyName]))); - QString typeface(QCFString::toQString(reinterpret_cast<CFStringRef>([mCocoaFont fontName]))); -// qDebug() << "original family" << family << "typeface" << typeface << "psize" << pSize; - int hyphenPos = typeface.indexOf(QLatin1Char('-')); - if (hyphenPos != -1) { - typeface.remove(0, hyphenPos + 1); - } else { - typeface = QLatin1String("Normal"); - } -// qDebug() << " massaged family" << family << "typeface" << typeface << "psize" << pSize; - newFont = QFontDatabase().font(family, typeface, pSize); - newFont.setUnderline(mQtFont->underline()); - newFont.setStrikeOut(mQtFont->strikeOut()); - } - - [self setQtFont:newFont]; + [self setQtFont:qfontForCocoaFont([sender convertFont:dummyFont], *mQtFont)]; if (mPriv) mPriv->updateSampleFont(*mQtFont); } @@ -317,6 +310,9 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin - (void)onOkClicked { Q_ASSERT(mPanelHackedWithButtons); + NSFontManager *fontManager = [NSFontManager sharedFontManager]; + [self setQtFont:qfontForCocoaFont([fontManager convertFont:[fontManager selectedFont]], + *mQtFont)]; [[mStolenContentView window] close]; [self finishOffWithCode:NSOKButton]; } @@ -374,16 +370,7 @@ const int StyleMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWin mModalSession = 0; } - // temporary hack to work around bug in deleteLater() in Qt/Mac Cocoa -#if 1 - bool deleteDialog = mPriv->fontDialog()->testAttribute(Qt::WA_DeleteOnClose); - mPriv->fontDialog()->setAttribute(Qt::WA_DeleteOnClose, false); -#endif mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected); -#if 1 - if (deleteDialog) - delete mPriv->fontDialog(); -#endif } else { [NSApp stopModalWithCode:code]; } diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index 9702fd1..15a99af 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -280,6 +280,9 @@ void QMessageBoxPrivate::updateSize() int hardLimit = screenSize.width() - (q->frameGeometry().width() - q->geometry().width()); #else int hardLimit = qMin(screenSize.width() - 480, 1000); // can never get bigger than this + // on small screens allows the messagebox be the same size as the screen + if (screenSize.width() <= 1024) + hardLimit = screenSize.width(); #endif #ifdef Q_WS_MAC int softLimit = qMin(screenSize.width()/2, 420); diff --git a/src/gui/embedded/qscreentransformed_qws.cpp b/src/gui/embedded/qscreentransformed_qws.cpp index 46ac1d1..e22ea1f 100644 --- a/src/gui/embedded/qscreentransformed_qws.cpp +++ b/src/gui/embedded/qscreentransformed_qws.cpp @@ -400,7 +400,19 @@ void QTransformedScreen::blit(const QImage &image, const QPoint &topLeft, #endif #if defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15) || defined(QT_QWS_DEPTH_12) case 16: +#if defined QT_QWS_ROTATE_BGR + if (pixelType() == BGRPixel && image.depth() == 16) { + SET_BLIT_FUNC(qbgr565, quint16, trans, func); + break; + } //fall-through here!!! +#endif case 15: +#if defined QT_QWS_ROTATE_BGR + if (pixelType() == BGRPixel && image.format() == QImage::Format_RGB555) { + SET_BLIT_FUNC(qbgr555, qrgb555, trans, func); + break; + } //fall-through here!!! +#endif case 12: if (image.depth() == 16) SET_BLIT_FUNC(quint16, quint16, trans, func); diff --git a/src/gui/embedded/qscreenvfb_qws.cpp b/src/gui/embedded/qscreenvfb_qws.cpp index abbe73b..accfe1f 100644 --- a/src/gui/embedded/qscreenvfb_qws.cpp +++ b/src/gui/embedded/qscreenvfb_qws.cpp @@ -310,6 +310,9 @@ bool QVFbScreen::connect(const QString &displaySpec) connected = this; + if (qgetenv("QT_QVFB_BGR").toInt()) + pixeltype = BGRPixel; + return true; } diff --git a/src/gui/embedded/qwindowsystem_qws.cpp b/src/gui/embedded/qwindowsystem_qws.cpp index dffebf2..fdcd193 100644 --- a/src/gui/embedded/qwindowsystem_qws.cpp +++ b/src/gui/embedded/qwindowsystem_qws.cpp @@ -4044,7 +4044,7 @@ void QWSServer::setDesktopBackground(const QImage &img) */ void QWSServer::setDesktopBackground(const QColor &c) { - setDesktopBackground(QBrush(c)); + setBackground(QBrush(c)); } #endif //QT3_SUPPORT diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 4f1f0f0..c9973d0 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -189,6 +189,11 @@ bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost) cacheKeys.insert(key, cacheKey); return true; } + qint64 oldCacheKey = cacheKeys.value(key, -1); + //If for the same key we add already a pixmap we should delete it + if (oldCacheKey != -1) + QCache<qint64, QDetachedPixmap>::remove(oldCacheKey); + bool success = QCache<qint64, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost); if (success) { cacheKeys.insert(key, cacheKey); diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 6c2d109..d1f3791 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -88,6 +88,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() autoScroll(true), autoScrollMargin(16), autoScrollCount(0), + shouldScrollToCurrentOnShow(false), alternatingColors(false), textElideMode(Qt::ElideRight), verticalScrollMode(QAbstractItemView::ScrollPerItem), @@ -1380,8 +1381,9 @@ bool QAbstractItemView::event(QEvent *event) d->executePostedLayout(); //make sure we set the layout properly break; case QEvent::Show: - { - d->executePostedLayout(); //make sure we set the layout properly + d->executePostedLayout(); //make sure we set the layout properly + if (d->shouldScrollToCurrentOnShow) { + d->shouldScrollToCurrentOnShow = false; const QModelIndex current = currentIndex(); if (current.isValid() && (d->state == QAbstractItemView::EditingState || d->autoScroll)) scrollTo(current); @@ -3164,14 +3166,18 @@ void QAbstractItemView::currentChanged(const QModelIndex ¤t, const QModelI d->updateDirtyRegion(); } } - if (isVisible() && current.isValid() && !d->autoScrollTimer.isActive()) { - if (d->autoScroll) - scrollTo(current); - d->setDirtyRegion(visualRect(current)); - d->updateDirtyRegion(); - edit(current, CurrentChanged, 0); - if (current.row() == (d->model->rowCount(d->root) - 1)) - d->_q_fetchMore(); + if (current.isValid() && !d->autoScrollTimer.isActive()) { + if (isVisible()) { + if (d->autoScroll) + scrollTo(current); + d->setDirtyRegion(visualRect(current)); + d->updateDirtyRegion(); + edit(current, CurrentChanged, 0); + if (current.row() == (d->model->rowCount(d->root) - 1)) + d->_q_fetchMore(); + } else { + d->shouldScrollToCurrentOnShow = d->autoScroll; + } } } diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 37fe4a2..16bd1ab 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -359,6 +359,7 @@ public: QBasicTimer autoScrollTimer; int autoScrollMargin; int autoScrollCount; + bool shouldScrollToCurrentOnShow; //used to know if we should scroll to current on show event bool alternatingColors; diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index 1a3ae2d..8baefdf 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -1313,11 +1313,11 @@ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &par int left = sel.at(i).left(); int right = sel.at(i).right(); if (top <= row && bottom >= row) { - Qt::ItemFlags leftFlags = d->model->index(row, left, parent).flags(); - Qt::ItemFlags rightFlags = d->model->index(row, right, parent).flags(); - if ((leftFlags & Qt::ItemIsSelectable) && (leftFlags & Qt::ItemIsEnabled) - && (rightFlags & Qt::ItemIsSelectable) && (rightFlags & Qt::ItemIsEnabled)) - return true; + for (int j = left; j <= right; j++) { + const Qt::ItemFlags flags = d->model->index(row, j, parent).flags(); + if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) + return true; + } } } @@ -1342,11 +1342,11 @@ bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelInde int top = sel.at(i).top(); int bottom = sel.at(i).bottom(); if (left <= column && right >= column) { - Qt::ItemFlags topFlags = d->model->index(top, column, parent).flags(); - Qt::ItemFlags bottomFlags = d->model->index(bottom, column, parent).flags(); - if ((topFlags & Qt::ItemIsSelectable) && (topFlags & Qt::ItemIsEnabled) - && (bottomFlags & Qt::ItemIsSelectable) && (bottomFlags & Qt::ItemIsEnabled)) - return true; + for (int j = top; j <= bottom; j++) { + const Qt::ItemFlags flags = d->model->index(j, column, parent).flags(); + if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) + return true; + } } } diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 07f0a38..48f53a0 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -1997,14 +1997,15 @@ bool QListViewPrivate::doItemsLayout(int delta) int first = batchStartRow(); int last = qMin(first + delta - 1, max); - if (max < 0 || last < first) - return true; // nothing to do - if (first == 0) { layoutChildren(); // make sure the viewport has the right size prepareItemsLayout(); } + if (max < 0 || last < first) { + return true; // nothing to do + } + QListViewLayoutInfo info; info.bounds = layoutBounds; info.grid = gridSize(); diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 91431c4..43feda8 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -144,6 +144,7 @@ public: const QModelIndex &proxy_index) const { Q_ASSERT(proxy_index.isValid()); + Q_ASSERT(proxy_index.model() == q_func()); const void *p = proxy_index.internalPointer(); Q_ASSERT(p); QMap<QModelIndex, Mapping *>::const_iterator it = @@ -311,6 +312,10 @@ QModelIndex QSortFilterProxyModelPrivate::proxy_to_source(const QModelIndex &pro { if (!proxy_index.isValid()) return QModelIndex(); // for now; we may want to be able to set a root index later + if (proxy_index.model() != q_func()) { + qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapToSource"; + return QModelIndex(); + } IndexMap::const_iterator it = index_to_iterator(proxy_index); Mapping *m = it.value(); if ((proxy_index.row() >= m->source_rows.size()) || (proxy_index.column() >= m->source_columns.size())) @@ -324,6 +329,10 @@ QModelIndex QSortFilterProxyModelPrivate::source_to_proxy(const QModelIndex &sou { if (!source_index.isValid()) return QModelIndex(); // for now; we may want to be able to set a root index later + if (source_index.model() != model) { + qWarning() << "QSortFilterProxyModel: index from wrong model passed to mapFromSource"; + return QModelIndex(); + } QModelIndex source_parent = source_index.parent(); IndexMap::const_iterator it = create_mapping(source_parent); Mapping *m = it.value(); diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 5f8c572..69302ec 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -194,8 +194,8 @@ static bool appNoGrab = false; // mouse/keyboard grabbing #ifndef QT_MAC_USE_COCOA static EventHandlerRef app_proc_handler = 0; static EventHandlerUPP app_proc_handlerUPP = 0; -static AEEventHandlerUPP app_proc_ae_handlerUPP = NULL; #endif +static AEEventHandlerUPP app_proc_ae_handlerUPP = NULL; static EventHandlerRef tablet_proximity_handler = 0; static EventHandlerUPP tablet_proximity_UPP = 0; bool QApplicationPrivate::native_modal_dialog_active; @@ -951,7 +951,6 @@ void qt_mac_event_release(QWidget *w) } } -#ifndef QT_MAC_USE_COCOA struct QMacAppleEventTypeSpec { AEEventClass mac_class; AEEventID mac_id; @@ -959,6 +958,7 @@ struct QMacAppleEventTypeSpec { { kCoreEventClass, kAEQuitApplication }, { kCoreEventClass, kAEOpenDocuments } }; +#ifndef QT_MAC_USE_COCOA /* watched events */ static EventTypeSpec app_events[] = { { kEventClassQt, kEventQtRequestWindowChange }, @@ -1156,13 +1156,13 @@ void qt_init(QApplicationPrivate *priv, int) qt_init_app_proc_handler(); } +#endif if (!app_proc_ae_handlerUPP) { app_proc_ae_handlerUPP = AEEventHandlerUPP(QApplicationPrivate::globalAppleEventProcessor); for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) AEInstallEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, app_proc_ae_handlerUPP, SRefCon(qApp), true); } -#endif if (QApplicationPrivate::app_style) { QEvent ev(QEvent::Style); @@ -1210,6 +1210,17 @@ void qt_init(QApplicationPrivate *priv, int) } +void qt_release_apple_event_handler() +{ + if(app_proc_ae_handlerUPP) { + for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) + AERemoveEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, + app_proc_ae_handlerUPP, true); + DisposeAEEventHandlerUPP(app_proc_ae_handlerUPP); + app_proc_ae_handlerUPP = 0; + } +} + /***************************************************************************** qt_cleanup() - cleans up when the application is finished *****************************************************************************/ @@ -1223,15 +1234,8 @@ void qt_cleanup() DisposeEventHandlerUPP(app_proc_handlerUPP); app_proc_handlerUPP = 0; } - if(app_proc_ae_handlerUPP) { - for(uint i = 0; i < sizeof(app_apple_events) / sizeof(QMacAppleEventTypeSpec); ++i) - AERemoveEventHandler(app_apple_events[i].mac_class, app_apple_events[i].mac_id, - app_proc_ae_handlerUPP, true); - DisposeAEEventHandlerUPP(app_proc_ae_handlerUPP); - app_proc_ae_handlerUPP = NULL; - } #endif - + qt_release_apple_event_handler(); qt_release_tablet_proximity_handler(); if (tablet_proximity_UPP) DisposeEventHandlerUPP(tablet_proximity_UPP); @@ -2367,6 +2371,12 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event #endif } +// In Carbon this is your one stop for apple events. +// In Cocoa, it ISN'T. This is the catch-all Apple Event handler that exists +// for the time between instantiating the NSApplication, but before the +// NSApplication has installed it's OWN Apple Event handler. When Cocoa has +// that set up, we remove this. So, if you are debugging problems, you likely +// want to check out QCocoaApplicationDelegate instead. OSStatus QApplicationPrivate::globalAppleEventProcessor(const AppleEvent *ae, AppleEvent *, long handlerRefcon) { QApplication *app = (QApplication *)handlerRefcon; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index fae0335..bc32c14 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -2432,10 +2432,12 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam widget = (QETWidget*)qApp->focusWidget(); HWND focus = ::GetFocus(); //if there is a current widget and the new widget belongs to the same toplevel window + //or if the current widget was embedded into non-qt window (i.e. we won't get WM_ACTIVATEAPP) //then we clear the focus on the widget //in case the new widget belongs to a different widget hierarchy, clearing the focus //will be handled because the active window will change - if (widget && ::IsChild(widget->window()->internalWinId(), focus)) { + const bool embedded = widget && ((QETWidget*)widget->window())->topData()->embedded; + if (widget && (embedded || ::IsChild(widget->window()->internalWinId(), focus))) { widget->clearFocus(); result = true; } else { diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index f1fb001..15149a5 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -3169,43 +3169,48 @@ int QApplication::x11ProcessEvent(XEvent* event) #ifdef ALIEN_DEBUG //qDebug() << "QApplication::x11ProcessEvent:" << event->type; #endif + Time time = 0, userTime = 0; switch (event->type) { case ButtonPress: pressed_window = event->xbutton.window; - X11->userTime = event->xbutton.time; + userTime = event->xbutton.time; // fallthrough intended case ButtonRelease: - X11->time = event->xbutton.time; + time = event->xbutton.time; break; case MotionNotify: - X11->time = event->xmotion.time; + time = event->xmotion.time; break; case XKeyPress: - X11->userTime = event->xkey.time; + userTime = event->xkey.time; // fallthrough intended case XKeyRelease: - X11->time = event->xkey.time; + time = event->xkey.time; break; case PropertyNotify: - X11->time = event->xproperty.time; + time = event->xproperty.time; break; case EnterNotify: case LeaveNotify: - X11->time = event->xcrossing.time; + time = event->xcrossing.time; break; case SelectionClear: - X11->time = event->xselectionclear.time; + time = event->xselectionclear.time; break; default: - break; - } #ifndef QT_NO_XFIXES - if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) { - XFixesSelectionNotifyEvent *req = - reinterpret_cast<XFixesSelectionNotifyEvent *>(event); - X11->time = req->selection_timestamp; - } + if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) { + XFixesSelectionNotifyEvent *req = + reinterpret_cast<XFixesSelectionNotifyEvent *>(event); + time = req->selection_timestamp; + } #endif + break; + } + if (time > X11->time) + X11->time = time; + if (userTime > X11->userTime) + X11->userTime = userTime; QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window); diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index 6571068..9a24645 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -183,27 +183,32 @@ static void cleanupCocoaApplicationDelegate() { Q_UNUSED(sender); // The reflection delegate gets precedence - NSApplicationTerminateReply reply = NSTerminateCancel; if (reflectionDelegate && [reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)]) { return [reflectionDelegate applicationShouldTerminate:sender]; } if (qtPrivate->canQuit()) { - reply = NSTerminateNow; if (!startedQuit) { startedQuit = true; qAppInstance()->quit(); startedQuit = false; } } - return reply; + + // Prevent Cocoa from terminating the application, since this simply + // exits the program whithout allowing QApplication::exec() to return. + // The call to QApplication::quit() above will instead quit the + // application from the Qt side. + return NSTerminateCancel; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { Q_UNUSED(aNotification); inLaunch = false; + extern void qt_release_apple_event_handler(); //qapplication_mac.mm + qt_release_apple_event_handler(); } - (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index fae4821..ff36ca1 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -807,10 +807,10 @@ extern "C" { QWheelEvent qwe(qlocal, qglobal, deltaY, buttons, keyMods, Qt::Vertical); qt_sendSpontaneousEvent(qwidget, &qwe); wheelOK = qwe.isAccepted(); - if (wheelOK && QApplicationPrivate::focus_widget + if (!wheelOK && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != qwidget) { QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(qglobal), qglobal, - deltaZ, buttons, keyMods, Qt::Vertical); + deltaY, buttons, keyMods, Qt::Vertical); qt_sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2); wheelOK = qwe2.isAccepted(); } diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 03b2fce..fa325f4 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -194,7 +194,6 @@ static void cleanupCocoaWindowDelegate() { NSWindow *window = [notification object]; QWidget *qwidget = m_windowHash->value(window); - // Just here to handle the is zoomed method. QWidgetData *widgetData = qt_qwidget_data(qwidget); if (!(qwidget->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) && [window isZoomed]) { widgetData->window_state = widgetData->window_state | Qt::WindowMaximized; @@ -202,7 +201,6 @@ static void cleanupCocoaWindowDelegate() & ~Qt::WindowMaximized)); qt_sendSpontaneousEvent(qwidget, &e); } - [self checkForMove:[window frame] forWidget:qwidget]; NSRect rect = [[window contentView] frame]; const QSize newSize(rect.size.width, rect.size.height); const QSize &oldSize = widgetData->crect.size(); @@ -212,12 +210,18 @@ static void cleanupCocoaWindowDelegate() } } -- (void)checkForMove:(const NSRect &)newRect forWidget:(QWidget *)qwidget +- (void)windowDidMove:(NSNotification *)notification { - // newRect's origin is bottom left. + // The code underneath needs to translate the window location + // from bottom left (which is the origin used by Cocoa) to + // upper left (which is the origin used by Qt): + NSWindow *window = [notification object]; + NSRect newRect = [window frame]; + QWidget *qwidget = m_windowHash->value(window); QPoint qtPoint = flipPoint(NSMakePoint(newRect.origin.x, newRect.origin.y + newRect.size.height)).toPoint(); const QRect &oldRect = qwidget->frameGeometry(); + if (qtPoint.x() != oldRect.x() || qtPoint.y() != oldRect.y()) { QWidgetData *widgetData = qt_qwidget_data(qwidget); QRect oldCRect = widgetData->crect; @@ -233,11 +237,6 @@ static void cleanupCocoaWindowDelegate() } } -- (void)windowDidMove:(NSNotification *)notification -{ - [self windowDidResize:notification]; -} - -(BOOL)windowShouldClose:(id)windowThatWantsToClose { QWidget *qwidget = m_windowHash->value(windowThatWantsToClose); diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index aa46249..1d5a70d 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -1239,7 +1239,7 @@ bool QLayout::activate() Must be implemented in subclasses to remove the layout item at \a index from the layout, and return the item. If there is no such item, the function must do nothing and return 0. Items are numbered - consecutively from 0. If an item is deleted, other items will be + consecutively from 0. If an item is removed, other items will be renumbered. The following code fragment shows a safe way to remove all items diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index f5deb96..23a5b08 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -187,6 +187,7 @@ QWidgetPrivate::QWidgetPrivate(int version) : ,inDirtyList(0) ,isScrolled(0) ,isMoved(0) + ,usesDoubleBufferedGLContext(0) #ifdef Q_WS_WIN ,noPaintOnScreen(0) #endif @@ -2149,6 +2150,10 @@ QWidget *QWidget::find(WId id) If a widget is non-native (alien) and winId() is invoked on it, that widget will be provided a native handle. + On Mac OS X, the type returned depends on which framework Qt was linked + against. If Qt is using Carbon, the {WId} is actually an HIViewRef. If Qt + is using Cocoa, {WId} is a pointer to an NSView. + \note We recommend that you do not store this value as it is likely to change at run-time. @@ -4726,10 +4731,13 @@ void QWidget::render(QPaintDevice *target, const QPoint &targetOffset, if (redirected) { target = redirected; offset -= redirectionOffset; - if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp). - const QRegion redirectedSystemClip = redirected->paintEngine()->systemClip(); - if (!redirectedSystemClip.isEmpty()) - paintRegion &= redirectedSystemClip.translated(-offset); + } + + if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp). + if (QPaintEngine *targetEngine = target->paintEngine()) { + const QRegion targetSystemClip = targetEngine->systemClip(); + if (!targetSystemClip.isEmpty()) + paintRegion &= targetSystemClip.translated(-offset); } } @@ -4833,8 +4841,13 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, const QRegion oldSystemClip = enginePriv->systemClip; const QRegion oldSystemViewport = enginePriv->systemViewport; - // This ensures that transformed system clips are inside the current system clip. - enginePriv->setSystemViewport(oldSystemClip); + // This ensures that all painting triggered by render() is clipped to the current engine clip. + if (painter->hasClipping()) { + const QRegion painterClip = painter->deviceTransform().map(painter->clipRegion()); + enginePriv->setSystemViewport(oldSystemClip.isEmpty() ? painterClip : oldSystemClip & painterClip); + } else { + enginePriv->setSystemViewport(oldSystemClip); + } render(target, targetOffset, toBePainted, renderFlags); diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index a00f969..5abaaf8 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -4039,7 +4039,11 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) QMacCocoaAutoReleasePool pool; bool realWindow = isRealWindow(); - if (realWindow && !(w == 0 && h == 0) && !q->testAttribute(Qt::WA_DontShowOnScreen)) { + if (realWindow && !q->testAttribute(Qt::WA_DontShowOnScreen) +#ifndef QT_MAC_USE_COCOA + && !(w == 0 && h == 0) +#endif + ){ applyMaxAndMinSizeConstraints(w, h); topData()->isSetGeometry = 1; topData()->isMove = isMove; @@ -4054,7 +4058,24 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) fStrut.top() + fStrut.bottom() + h)); NSRect cocoaFrameRect = NSMakeRect(frameRect.x(), flipYCoordinate(frameRect.bottom() + 1), frameRect.width(), frameRect.height()); - [window setFrame:cocoaFrameRect display:NO]; + + QPoint currTopLeft = data.crect.topLeft(); + if (currTopLeft.x() == x && currTopLeft.y() == y + && cocoaFrameRect.size.width != 0 + && cocoaFrameRect.size.height != 0) { + [window setFrame:cocoaFrameRect display:NO]; + } else { + // The window is moved and resized (or resized to zero). + // Since Cocoa usually only sends us a resize callback after + // setting a window frame, we issue an explicit move as + // well. To stop Cocoa from optimize away the move (since the move + // would have the same origin as the setFrame call) we shift the + // window back and forth inbetween. + cocoaFrameRect.origin.y += 1; + [window setFrame:cocoaFrameRect display:NO]; + cocoaFrameRect.origin.y -= 1; + [window setFrameOrigin:cocoaFrameRect.origin]; + } #endif topData()->isSetGeometry = 0; } else { diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 19f4b98..e02d329 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -550,6 +550,7 @@ public: uint inDirtyList : 1; uint isScrolled : 1; uint isMoved : 1; + uint usesDoubleBufferedGLContext : 1; #ifdef Q_WS_WIN uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index fbac811a..8fb7a12 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -1510,6 +1510,9 @@ void QWidgetPrivate::invalidateBuffer(const QRect &rect) void QWidgetPrivate::repaint_sys(const QRegion &rgn) { + if (data.in_destructor) + return; + Q_Q(QWidget); if (q->testAttribute(Qt::WA_StaticContents)) { if (!extra) @@ -1517,13 +1520,20 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn) extra->staticContentsSize = data.crect.size(); } + QPaintEngine *engine = q->paintEngine(); + // QGLWidget does not support partial updates if: + // 1) The context is double buffered + // 2) The context is single buffered and auto-fill background is enabled. + const bool noPartialUpdateSupport = (engine && engine->type() == QPaintEngine::OpenGL) + && (usesDoubleBufferedGLContext || q->autoFillBackground()); + QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn); + #ifdef Q_WS_MAC // No difference between update() and repaint() on the Mac. - update_sys(rgn); + update_sys(toBePainted); return; #endif - QRegion toBePainted(rgn); toBePainted &= clipRect(); clipToEffectiveMask(toBePainted); if (toBePainted.isEmpty()) diff --git a/src/gui/painting/qcolormap_win.cpp b/src/gui/painting/qcolormap_win.cpp index d61b933..7d36582 100644 --- a/src/gui/painting/qcolormap_win.cpp +++ b/src/gui/painting/qcolormap_win.cpp @@ -138,7 +138,11 @@ void QColormap::cleanup() } QColormap QColormap::instance(int) -{ return QColormap(); } +{ + Q_ASSERT_X(screenMap, "QColormap", + "A QApplication object needs to be constructed before QColormap is used."); + return QColormap(); +} QColormap::QColormap() : d(screenMap) diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp index 4058143..471f544 100644 --- a/src/gui/painting/qmemrotate.cpp +++ b/src/gui/painting/qmemrotate.cpp @@ -528,6 +528,26 @@ void qt_memrotate270(const srctype *src, int w, int h, int sstride, \ qt_memrotate270_template(src, w, h, sstride, dest, dstride); \ } +#define QT_IMPL_SIMPLE_MEMROTATE(srctype, desttype) \ +void qt_memrotate90(const srctype *src, int w, int h, int sstride, \ + desttype *dest, int dstride) \ +{ \ + qt_memrotate90_tiled_unpacked<desttype,srctype>(src, w, h, sstride, dest, dstride); \ +} \ +void qt_memrotate180(const srctype *src, int w, int h, int sstride, \ + desttype *dest, int dstride) \ +{ \ + qt_memrotate180_template(src, w, h, sstride, dest, dstride); \ +} \ +void qt_memrotate270(const srctype *src, int w, int h, int sstride, \ + desttype *dest, int dstride) \ +{ \ + qt_memrotate270_tiled_unpacked<desttype,srctype>(src, w, h, sstride, dest, dstride); \ +} + + + + QT_IMPL_MEMROTATE(quint32, quint32) QT_IMPL_MEMROTATE(quint32, quint16) QT_IMPL_MEMROTATE(quint16, quint32) @@ -539,6 +559,14 @@ QT_IMPL_MEMROTATE(quint32, quint8) QT_IMPL_MEMROTATE(quint16, quint8) QT_IMPL_MEMROTATE(qrgb444, quint8) QT_IMPL_MEMROTATE(quint8, quint8) + +#if defined(QT_QWS_ROTATE_BGR) +QT_IMPL_SIMPLE_MEMROTATE(quint16, qbgr565) +QT_IMPL_SIMPLE_MEMROTATE(quint32, qbgr565) +QT_IMPL_SIMPLE_MEMROTATE(qrgb555, qbgr555) +QT_IMPL_SIMPLE_MEMROTATE(quint32, qbgr555) +#endif + #ifdef QT_QWS_DEPTH_GENERIC QT_IMPL_MEMROTATE(quint32, qrgb_generic16) QT_IMPL_MEMROTATE(quint16, qrgb_generic16) diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h index c1eb93e..87cfb1a 100644 --- a/src/gui/painting/qmemrotate_p.h +++ b/src/gui/painting/qmemrotate_p.h @@ -92,6 +92,14 @@ QT_DECL_MEMROTATE(quint32, quint8); QT_DECL_MEMROTATE(quint16, quint8); QT_DECL_MEMROTATE(qrgb444, quint8); QT_DECL_MEMROTATE(quint8, quint8); + +#ifdef QT_QWS_ROTATE_BGR +QT_DECL_MEMROTATE(quint16, qbgr565); +QT_DECL_MEMROTATE(quint32, qbgr565); +QT_DECL_MEMROTATE(qrgb555, qbgr555); +QT_DECL_MEMROTATE(quint32, qbgr555); +#endif + #ifdef QT_QWS_DEPTH_GENERIC QT_DECL_MEMROTATE(quint32, qrgb_generic16); QT_DECL_MEMROTATE(quint16, qrgb_generic16); diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index ad09060..7de1ec4 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -949,8 +949,8 @@ void QPaintEngine::setSystemClip(const QRegion ®ion) Q_D(QPaintEngine); d->systemClip = region; // Be backward compatible and only call d->systemStateChanged() - // if we currently have a system transform set. - if (d->hasSystemTransform) { + // if we currently have a system transform/viewport set. + if (d->hasSystemTransform || d->hasSystemViewport) { d->transformSystemClip(); d->systemStateChanged(); } diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp index 0644a02..5889388 100644 --- a/src/gui/painting/qpaintengine_mac.cpp +++ b/src/gui/painting/qpaintengine_mac.cpp @@ -996,15 +996,14 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co } else if (differentSize) { #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - CGImageRef img = (CGImageRef)pm.macCGHandle(); + QCFType<CGImageRef> img = pm.toMacCGImageRef(); image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); - CGImageRelease(img); } else #endif { const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height()); const QMacPixmapData *pmData = static_cast<const QMacPixmapData*>(pm.data); - quint32 *pantherData = pmData->pixels + (sy * pm.width() + sx); + quint32 *pantherData = pmData->pixels + sy * (pmData->bytesPerRow / 4) + sx; QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, pantherData, sw*sh*pmData->bytesPerRow, 0); image = CGImageCreate(sw, sh, 8, 32, pmData->bytesPerRow, macGenericColorSpace(), diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index eeba7ec..0b5e175 100644 --- a/src/gui/painting/qpaintengine_p.h +++ b/src/gui/painting/qpaintengine_p.h @@ -83,10 +83,12 @@ public: if (systemClip.isEmpty()) return; - if (systemTransform.type() <= QTransform::TxTranslate) - systemClip.translate(qRound(systemTransform.dx()), qRound(systemTransform.dy())); - else - systemClip = systemTransform.map(systemClip); + if (hasSystemTransform) { + if (systemTransform.type() <= QTransform::TxTranslate) + systemClip.translate(qRound(systemTransform.dx()), qRound(systemTransform.dy())); + else + systemClip = systemTransform.map(systemClip); + } // Make sure we're inside the viewport. if (hasSystemViewport) { @@ -101,7 +103,7 @@ public: inline void setSystemTransform(const QTransform &xform) { systemTransform = xform; - if ((hasSystemTransform = !xform.isIdentity())) + if ((hasSystemTransform = !xform.isIdentity()) || hasSystemViewport) transformSystemClip(); systemStateChanged(); } diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 19b2574..ba8f2a3 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1024,7 +1024,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, int alpha, const QRect &sr) { - if (!clip.isValid()) + if (alpha == 0 || !clip.isValid()) return; Q_ASSERT(img.depth() >= 8); @@ -2666,7 +2666,13 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe QRectF rr = r; rr.translate(s->matrix.dx(), s->matrix.dy()); - fillRect_normalized(toRect_normalized(rr), &d->image_filler, d); + + const int x1 = qRound(rr.x()); + const int y1 = qRound(rr.y()); + const int x2 = qRound(rr.right()); + const int y2 = qRound(rr.bottom()); + + fillRect_normalized(QRect(x1, y1, x2-x1, y2-y1), &d->image_filler, d); } } @@ -5155,7 +5161,11 @@ void QSpanData::adjustSpanMethods() void QSpanData::setupMatrix(const QTransform &matrix, int bilin) { - QTransform inv = matrix.inverted(); + QTransform delta; + // make sure we round off correctly in qdrawhelper.cpp + delta.translate(1.0 / 65536, 1.0 / 65536); + + QTransform inv = (delta * matrix).inverted(); m11 = inv.m11(); m12 = inv.m12(); m13 = inv.m13(); diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index 39ce59f..4b2fbca 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -2352,7 +2352,9 @@ void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti) GlyphSet glyphSet = set->id; const QColor &pen = d->cpen.color(); ::Picture src = X11->getSolidFill(d->scrn, pen); - XRenderPictFormat *maskFormat = XRenderFindStandardFormat(X11->display, ft->xglyph_format); + XRenderPictFormat *maskFormat = 0; + if (ft->xglyph_format != PictStandardA1) + maskFormat = XRenderFindStandardFormat(X11->display, ft->xglyph_format); enum { t_min = SHRT_MIN, t_max = SHRT_MAX }; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 65d87fa..afc4211 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2398,7 +2398,6 @@ QRegion QPainter::clipRegion() const // ### Falcon: Use QPainterPath for (int i=0; i<d->state->clipInfo.size(); ++i) { const QPainterClipInfo &info = d->state->clipInfo.at(i); - QRegion other; switch (info.clipType) { case QPainterClipInfo::RegionClip: { @@ -2451,15 +2450,20 @@ QRegion QPainter::clipRegion() const lastWasNothing = false; continue; } - if (info.operation == Qt::IntersectClip) - region &= QRegion(info.rect) * matrix; - else if (info.operation == Qt::UniteClip) + if (info.operation == Qt::IntersectClip) { + // Use rect intersection if possible. + if (matrix.type() <= QTransform::TxScale) + region &= matrix.mapRect(info.rect); + else + region &= matrix.map(QRegion(info.rect)); + } else if (info.operation == Qt::UniteClip) { region |= QRegion(info.rect) * matrix; - else if (info.operation == Qt::NoClip) { + } else if (info.operation == Qt::NoClip) { lastWasNothing = true; region = QRegion(); - } else + } else { region = QRegion(info.rect) * matrix; + } break; } @@ -2470,15 +2474,20 @@ QRegion QPainter::clipRegion() const lastWasNothing = false; continue; } - if (info.operation == Qt::IntersectClip) - region &= QRegion(info.rectf.toRect()) * matrix; - else if (info.operation == Qt::UniteClip) + if (info.operation == Qt::IntersectClip) { + // Use rect intersection if possible. + if (matrix.type() <= QTransform::TxScale) + region &= matrix.mapRect(info.rectf.toRect()); + else + region &= matrix.map(QRegion(info.rectf.toRect())); + } else if (info.operation == Qt::UniteClip) { region |= QRegion(info.rectf.toRect()) * matrix; - else if (info.operation == Qt::NoClip) { + } else if (info.operation == Qt::NoClip) { lastWasNothing = true; region = QRegion(); - } else + } else { region = QRegion(info.rectf.toRect()) * matrix; + } break; } } @@ -5133,6 +5142,11 @@ void QPainter::drawConvexPolygon(const QPointF *points, int pointCount) d->engine->drawPolygon(points, pointCount, QPaintEngine::ConvexMode); } +static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransform &m) +{ + return m.inverted().map(QPointF(m.map(p).toPoint())); +} + /*! \fn void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source) @@ -5201,11 +5215,12 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))) { save(); - // If there is no scaling or transformation involved we have to make sure we use the + // If there is no rotation involved we have to make sure we use the // antialiased and not the aliased coordinate system by rounding the coordinates. - if (d->state->matrix.type() <= QTransform::TxTranslate) { - x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx(); - y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy(); + if (d->state->matrix.type() <= QTransform::TxScale) { + const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); + x = p.x(); + y = p.y(); } translate(x, y); setBackgroundMode(Qt::TransparentMode); @@ -5315,16 +5330,21 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) || ((sw != w || sh != h) && !d->engine->hasFeature(QPaintEngine::PixmapTransform))) { save(); - // If there is no scaling or transformation involved we have to make sure we use the + // If there is no rotation involved we have to make sure we use the // antialiased and not the aliased coordinate system by rounding the coordinates. + if (d->state->matrix.type() <= QTransform::TxScale) { + const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); + x = p.x(); + y = p.y(); + } + if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) { - x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx(); - y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy(); sx = qRound(sx); sy = qRound(sy); sw = qRound(sw); sh = qRound(sh); } + translate(x, y); scale(w / sw, h / sh); setBackgroundMode(Qt::TransparentMode); @@ -5474,11 +5494,12 @@ void QPainter::drawImage(const QPointF &p, const QImage &image) || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))) { save(); - // If there is no scaling or transformation involved we have to make sure we use the + // If there is no rotation involved we have to make sure we use the // antialiased and not the aliased coordinate system by rounding the coordinates. - if (d->state->matrix.type() <= QTransform::TxTranslate) { - x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx(); - y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy(); + if (d->state->matrix.type() <= QTransform::TxScale) { + const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); + x = p.x(); + y = p.y(); } translate(x, y); setBackgroundMode(Qt::TransparentMode); @@ -5577,11 +5598,15 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR || (d->state->opacity != 1.0 && !d->engine->hasFeature(QPaintEngine::ConstantOpacity))) { save(); - // If there is no scaling or transformation involved we have to make sure we use the + // If there is no rotation involved we have to make sure we use the // antialiased and not the aliased coordinate system by rounding the coordinates. + if (d->state->matrix.type() <= QTransform::TxScale) { + const QPointF p = roundInDeviceCoordinates(QPointF(x, y), d->state->matrix); + x = p.x(); + y = p.y(); + } + if (d->state->matrix.type() <= QTransform::TxTranslate && sw == w && sh == h) { - x = qRound(x + d->state->matrix.dx()) - d->state->matrix.dx(); - y = qRound(y + d->state->matrix.dy()) - d->state->matrix.dy(); sx = qRound(sx); sy = qRound(sy); sw = qRound(sw); @@ -6324,17 +6349,18 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo setBrush(QBrush(d->state->pen.color(), pixmap)); setPen(Qt::NoPen); - // If there is no scaling or transformation involved we have to make sure we use the + // If there is no rotation involved we have to make sure we use the // antialiased and not the aliased coordinate system by rounding the coordinates. - if (d->state->matrix.type() <= QTransform::TxTranslate) { - qreal x = qRound(r.x() + d->state->matrix.dx()) - d->state->matrix.dx(); - qreal y = qRound(r.y() + d->state->matrix.dy()) - d->state->matrix.dy(); - qreal w = qRound(r.width()); - qreal h = qRound(r.height()); - sx = qRound(sx); - sy = qRound(sy); + if (d->state->matrix.type() <= QTransform::TxScale) { + const QPointF p = roundInDeviceCoordinates(r.topLeft(), d->state->matrix); + + if (d->state->matrix.type() <= QTransform::TxTranslate) { + sx = qRound(sx); + sy = qRound(sy); + } + setBrushOrigin(QPointF(r.x()-sx, r.y()-sy)); - drawRect(QRectF(x, y, w, h)); + drawRect(QRectF(p, r.size())); } else { setBrushOrigin(QPointF(r.x()-sx, r.y()-sy)); drawRect(r); diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index af27fd5..2383272 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1317,12 +1317,16 @@ QRegion QTransform::map(const QRegion &r) const TransformationType t = type(); if (t == TxNone) return r; + if (t == TxTranslate) { QRegion copy(r); copy.translate(qRound(affine._dx), qRound(affine._dy)); return copy; } + if (t == TxScale && r.numRects() == 1) + return QRegion(mapRect(r.boundingRect())); + QPainterPath p = map(qt_regionToPath(r)); return p.toFillPolygon(QTransform()).toPolygon(); } diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index 819965b..3cae08a 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -1779,46 +1779,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, case CE_TabBarTab: if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { drawControl(CE_TabBarTabShape, tab, p, widget); - - QStyleOptionTabV3 tabV3(*tab); - QRect labelRect = tabV3.rect; - QSize &left= tabV3.leftButtonSize; - QSize &right = tabV3.rightButtonSize; - const int spacing = 6 + 2; - - // left widget - if (!left.isEmpty()) { - if (tabV3.shape == QTabBar::RoundedEast || tabV3.shape == QTabBar::TriangularEast ) - labelRect.setTop(labelRect.top() + spacing + left.height()); - else if (tabV3.shape == QTabBar::RoundedWest|| tabV3.shape == QTabBar::TriangularWest) - labelRect.setBottom(labelRect.bottom() - spacing - left.height()); - else - labelRect.setLeft(labelRect.left() + spacing + left.width()); - } - - // right widget - if (!right.isEmpty()) { - if (tabV3.shape == QTabBar::RoundedEast || tabV3.shape == QTabBar::TriangularEast ) - labelRect.setBottom(labelRect.bottom() - spacing - right.height()); - else if (tabV3.shape == QTabBar::RoundedWest|| tabV3.shape == QTabBar::TriangularWest) - labelRect.setTop(labelRect.top() + spacing + right.height()); - else - labelRect.setRight(labelRect.right() - spacing - right.width()); - } - - tabV3.rect = visualRect(opt->direction, opt->rect, labelRect); - drawControl(CE_TabBarTabLabel, &tabV3, p, widget); - if (tabV3.state & State_HasFocus) { - const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth); - int x1, x2; - x1 = tab->rect.left(); - x2 = tab->rect.right() - 1; - QStyleOptionFocusRect fropt; - fropt.QStyleOption::operator=(*tab); - fropt.rect.setRect(x1 + 1 + OFFSET, tab->rect.y() + OFFSET, - x2 - x1 - 2*OFFSET, tab->rect.height() - 2*OFFSET); - drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); - } + drawControl(CE_TabBarTabLabel, tab, p, widget); } break; case CE_TabBarTabShape: @@ -2020,8 +1981,12 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, (tabV2.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled); - int offset = 6; + int offset = 4; int left = opt->rect.left(); + if (tabV2.leftButtonSize.isEmpty()) + offset += 2; + else + left += tabV2.leftButtonSize.width() + (6 + 2) + 2; QRect iconRect = QRect(left + offset, tr.center().y() - tabIcon.height() / 2, tabIconSize.width(), tabIconSize.height()); if (!verticalTabs) @@ -2032,6 +1997,20 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text, QPalette::WindowText); if (verticalTabs) p->restore(); + + if (tabV2.state & State_HasFocus) { + const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth); + + int x1, x2; + x1 = tabV2.rect.left(); + x2 = tabV2.rect.right() - 1; + + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*tab); + fropt.rect.setRect(x1 + 1 + OFFSET, tabV2.rect.y() + OFFSET, + x2 - x1 - 2*OFFSET, tabV2.rect.height() - 2*OFFSET); + drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); + } } break; #endif // QT_NO_TABBAR @@ -2879,6 +2858,12 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, tr.setRight(tr.right() - horizontalShift); } + // left widget + if (!tabV2.leftButtonSize.isEmpty()) { + tr.setLeft(tr.left() + 6 + 2 + + (verticalTabs ? tabV2.leftButtonSize.height() : tabV2.leftButtonSize.width())); + } + // icon if (!tabV2.icon.isNull()) { QSize iconSize = tabV2.iconSize; @@ -2900,6 +2885,12 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, tr.setLeft(tr.left() + tabIconSize.width() + offset + 2); } + // right widget + if (!tabV2.rightButtonSize.isEmpty()) { + tr.setRight(tr.right() - 6 - 2 - + (verticalTabs ? tabV2.rightButtonSize.height() : tabV2.rightButtonSize.width())); + } + if (!verticalTabs) tr = visualRect(opt->direction, opt->rect, tr); r = tr; diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 398e11d..c973b41 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -2146,8 +2146,11 @@ void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QPoint /*! \reimp */ void QMacStyle::polish(QPalette &pal) { - if (qt_mac_backgroundPattern == 0) + if (!qt_mac_backgroundPattern) { + if (!qApp) + return; qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern()); + } QColor pc(Qt::black); pc = qcolorForTheme(kThemeBrushDialogBackgroundActive); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 49ac57a..058660e 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -5842,7 +5842,7 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c bool QStyleSheetStyle::event(QEvent *e) { - return baseStyle()->event(e) || ParentStyle::event(e); + return (baseStyle()->event(e) && e->isAccepted()) || ParentStyle::event(e); } void QStyleSheetStyle::updateStyleSheetFont(QWidget* w) const diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 0e4b378..d691f93 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -904,7 +904,10 @@ int QFont::pointSize() const */ void QFont::setPointSize(int pointSize) { - Q_ASSERT_X (pointSize > 0, "QFont::setPointSize", "point size must be greater than 0"); + if (pointSize <= 0) { + qWarning("QFont::setPointSize: Point size <= 0 (%d), must be greater than 0", pointSize); + return; + } detach(); @@ -923,7 +926,10 @@ void QFont::setPointSize(int pointSize) */ void QFont::setPointSizeF(qreal pointSize) { - Q_ASSERT_X(pointSize > 0.0, "QFont::setPointSizeF", "point size must be greater than 0"); + if (pointSize <= 0) { + qWarning("QFont::setPointSizeF: Point size <= 0 (%d), must be greater than 0", pointSize); + return; + } detach(); diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index 0571d75..8eaeeb1 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -232,6 +232,12 @@ public: ImageWidth = 0x5010, ImageHeight = 0x5011, + // internal + /* + SuppressText = 0x5012, + SuppressBackground = 0x513 + */ + // selection properties FullWidthSelection = 0x06000, diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 434d1ca..fa624ef 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE #define ObjectSelectionBrush (QTextFormat::ForegroundBrush + 1) +#define SuppressText 0x5012 +#define SuppressBackground 0x513 static inline QFixed leadingSpaceWidth(QTextEngine *eng, const QScriptLine &line) { @@ -1143,6 +1145,7 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang } QPainterPath excludedRegion; + QPainterPath textDoneRegion; for (int i = 0; i < selections.size(); ++i) { FormatRange selection = selections.at(i); const QBrush bg = selection.format.background(); @@ -1202,23 +1205,55 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang } + + bool hasText = (selection.format.foreground().style() != Qt::NoBrush); + bool hasBackground= (selection.format.background().style() != Qt::NoBrush); + + if (hasBackground) { + selection.format.setProperty(ObjectSelectionBrush, selection.format.property(QTextFormat::BackgroundBrush)); + // don't just clear the property, set an empty brush that overrides a potential + // background brush specified in the text + selection.format.setProperty(QTextFormat::BackgroundBrush, QBrush()); + selection.format.clearProperty(QTextFormat::OutlinePen); + } + + selection.format.setProperty(SuppressText, !hasText); + + if (hasText && !hasBackground && !(textDoneRegion & region).isEmpty()) + continue; + p->save(); p->setClipPath(region, Qt::IntersectClip); - selection.format.setProperty(ObjectSelectionBrush, selection.format.property(QTextFormat::BackgroundBrush)); - // don't just clear the property, set an empty brush that overrides a potential - // background brush specified in the text - selection.format.setProperty(QTextFormat::BackgroundBrush, QBrush()); - selection.format.clearProperty(QTextFormat::OutlinePen); - for (int line = firstLine; line < lastLine; ++line) { QTextLine l(line, d); l.draw(p, position, &selection); } p->restore(); - if (selection.format.foreground().style() != Qt::NoBrush) // i.e. we have drawn text - excludedRegion += region; + if (hasText) { + textDoneRegion += region; + } else { + if (hasBackground) + textDoneRegion -= region; + } + + excludedRegion += region; + } + + QPainterPath needsTextButNoBackground = excludedRegion - textDoneRegion; + if (!needsTextButNoBackground.isEmpty()){ + p->save(); + p->setClipPath(needsTextButNoBackground, Qt::IntersectClip); + FormatRange selection; + selection.start = 0; + selection.length = INT_MAX; + selection.format.setProperty(SuppressBackground, true); + for (int line = firstLine; line < lastLine; ++line) { + QTextLine l(line, d); + l.draw(p, position, &selection); + } + p->restore(); } if (!excludedRegion.isEmpty()) { @@ -1912,14 +1947,17 @@ static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si, static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r) { QBrush c = chf.foreground(); - if (c.style() == Qt::NoBrush) + if (c.style() == Qt::NoBrush) { p->setPen(defaultPen); + } QBrush bg = chf.background(); - if (bg.style() != Qt::NoBrush) + if (bg.style() != Qt::NoBrush && !chf.property(SuppressBackground).toBool()) p->fillRect(r, bg); - if (c.style() != Qt::NoBrush) + if (c.style() != Qt::NoBrush) { p->setPen(QPen(c, 0)); + } + } /*! @@ -1933,7 +1971,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR const QScriptLine &line = eng->lines[i]; QPen pen = p->pen(); - bool noText = (selection && selection->format.foreground().style() == Qt::NoBrush); + bool noText = (selection && selection->format.property(SuppressText).toBool()); if (!line.length) { if (selection diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 11e1e46..bcbeef1 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -477,7 +477,8 @@ void QNetworkAccessManager::setCache(QAbstractNetworkCache *cache) if (d->networkCache != cache) { delete d->networkCache; d->networkCache = cache; - d->networkCache->setParent(this); + if (d->networkCache) + d->networkCache->setParent(this); } } diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index c8d6097..e921318 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -1013,14 +1013,14 @@ QList<QNetworkCookie> QNetworkCookie::parseCookies(const QByteArray &cookieStrin cookie.setExpirationDate(dt); } else if (field.first == "domain") { QByteArray rawDomain = field.second; - QString maybeLeadingDot; if (rawDomain.startsWith('.')) { - maybeLeadingDot = QLatin1Char('.'); rawDomain = rawDomain.mid(1); } - QString normalizedDomain = QUrl::fromAce(QUrl::toAce(QString::fromUtf8(rawDomain))); - cookie.setDomain(maybeLeadingDot + normalizedDomain); + // always add the dot, there are some servers that forget the + // leading dot. This is actually forbidden according to RFC 2109, + // but all browsers accept it anyway so we do that as well + cookie.setDomain(QLatin1Char('.') + normalizedDomain); } else if (field.first == "max-age") { bool ok = false; int secs = field.second.toInt(&ok); @@ -1221,7 +1221,6 @@ bool QNetworkCookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieLis cookie.expirationDate() < now; // validate the cookie & set the defaults if unset - // (RFC 2965: "The request-URI MUST path-match the Path attribute of the cookie.") if (cookie.path().isEmpty()) cookie.setPath(defaultPath); else if (!isParentPath(pathAndFileName, cookie.path())) @@ -1235,6 +1234,13 @@ bool QNetworkCookieJar::setCookiesFromUrl(const QList<QNetworkCookie> &cookieLis || isParentDomain(defaultDomain, domain))) { continue; // not accepted } + + // reject if domain is like ".com" + // (i.e., reject if domain does not contain embedded dots, see RFC 2109 section 4.3.2) + // this is just a rudimentary check and does not cover all cases + if (domain.lastIndexOf(QLatin1Char('.')) == 0) + continue; // not accepted + } QList<QNetworkCookie>::Iterator it = d->allCookies.begin(), diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index b4a0e5c..04bc611 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1327,13 +1327,21 @@ QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include // This is an old legacy fix for PowerPC based Macs, which // we shouldn't remove while (p < end) { - *p = 0xFF000000 | (*p>>8); + *p = 0xff000000 | (*p>>8); ++p; } } } else { // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB - img = img.rgbSwapped(); + for (int y = 0; y < h; y++) { + uint *q = (uint*)img.scanLine(y); + for (int x=0; x < w; ++x) { + const uint pixel = *q; + *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); + q++; + } + } + } return img.mirrored(); } @@ -2398,6 +2406,10 @@ bool QGLContext::create(const QGLContext* shareContext) return false; reset(); d->valid = chooseContext(shareContext); + if (d->valid && d->paintDevice->devType() == QInternal::Widget) { + QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice)); + wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer(); + } if (d->sharing) // ok, we managed to share qgl_share_reg()->addShare(this, shareContext); return d->valid; diff --git a/src/plugins/gfxdrivers/directfb/directfb.pro b/src/plugins/gfxdrivers/directfb/directfb.pro index 1ee9030..5c60b2f 100644 --- a/src/plugins/gfxdrivers/directfb/directfb.pro +++ b/src/plugins/gfxdrivers/directfb/directfb.pro @@ -6,6 +6,7 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers # These defines might be necessary if your DirectFB driver doesn't # support all of the DirectFB API. # +#DEFINES += QT_DIRECTFB_IMAGECACHE #DEFINES += QT_NO_DIRECTFB_WM #DEFINES += QT_NO_DIRECTFB_LAYER #DEFINES += QT_NO_DIRECTFB_PALETTE @@ -14,31 +15,30 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers #DEFINES += QT_NO_DIRECTFB_KEYBOARD #DEFINES += QT_DIRECTFB_TIMING #DEFINES += QT_NO_DIRECTFB_OPAQUE_DETECTION -#DEFINES += QT_DIRECTFB_WARN_ON_RASTERFALLBACKS -#DEFINES += QT_DIRECTFB_DISABLE_RASTERFALLBACKS +#DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS +#DEFINES += \"QT_DIRECTFB_WARN_ON_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\" +#DEFINES += \"QT_DIRECTFB_DISABLE_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\" target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers INSTALLS += target -HEADERS = \ - qdirectfbscreen.h \ - qdirectfbsurface.h \ - qdirectfbpaintengine.h \ - qdirectfbpaintdevice.h \ - qdirectfbpixmap.h \ - qdirectfbkeyboard.h \ - qdirectfbmouse.h +HEADERS = qdirectfbscreen.h \ + qdirectfbwindowsurface.h \ + qdirectfbpaintengine.h \ + qdirectfbpaintdevice.h \ + qdirectfbpixmap.h \ + qdirectfbkeyboard.h \ + qdirectfbmouse.h -SOURCES = \ - qdirectfbscreen.cpp \ - qdirectfbscreenplugin.cpp \ - qdirectfbsurface.cpp \ - qdirectfbpaintengine.cpp \ - qdirectfbpaintdevice.cpp \ - qdirectfbpixmap.cpp \ - qdirectfbkeyboard.cpp \ - qdirectfbmouse.cpp +SOURCES = qdirectfbscreen.cpp \ + qdirectfbscreenplugin.cpp \ + qdirectfbwindowsurface.cpp \ + qdirectfbpaintengine.cpp \ + qdirectfbpaintdevice.cpp \ + qdirectfbpixmap.cpp \ + qdirectfbkeyboard.cpp \ + qdirectfbmouse.cpp QMAKE_CXXFLAGS += $$QT_CFLAGS_DIRECTFB LIBS += $$QT_LIBS_DIRECTFB - +DEFINES += $$QT_DEFINES_DIRECTFB diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp index f4d9b46..b999dd2 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp @@ -56,9 +56,7 @@ public: QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h); ~QDirectFBMouseHandlerPrivate(); - void suspend(); - void resume(); - + void setEnabled(bool on); private: QDirectFBMouseHandler *handler; IDirectFBEventBuffer *eventBuffer; @@ -130,7 +128,7 @@ QDirectFBMouseHandlerPrivate::QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData())); - resume(); + setEnabled(true); } QDirectFBMouseHandlerPrivate::~QDirectFBMouseHandlerPrivate() @@ -139,15 +137,32 @@ QDirectFBMouseHandlerPrivate::~QDirectFBMouseHandlerPrivate() eventBuffer->Release(eventBuffer); } -void QDirectFBMouseHandlerPrivate::suspend() +void QDirectFBMouseHandlerPrivate::setEnabled(bool on) { - mouseNotifier->setEnabled(false); -} + if (mouseNotifier->isEnabled() != on) { +#ifndef QT_NO_DIRECTFB_LAYER + DFBResult result; + result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::QDirectFBScreenCursor: " + "Unable to set cooperative level", result); + } + result = layer->EnableCursor(layer, on ? 1 : 0); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::QDirectFBScreenCursor: " + "Unable to enable cursor", result); + } -void QDirectFBMouseHandlerPrivate::resume() -{ - eventBuffer->Reset(eventBuffer); - mouseNotifier->setEnabled(true); + result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::show: " + "Unable to set cooperative level", result); + } + + layer->SetCooperativeLevel(layer, DLSCL_SHARED); +#endif + mouseNotifier->setEnabled(on); + } } void QDirectFBMouseHandlerPrivate::readMouseData() @@ -260,12 +275,12 @@ QDirectFBMouseHandler::~QDirectFBMouseHandler() void QDirectFBMouseHandler::suspend() { - d->suspend(); + d->setEnabled(false); } void QDirectFBMouseHandler::resume() { - d->resume(); + d->setEnabled(true); } #include "qdirectfbmouse.moc" diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.h b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.h index e81a4ba..d2eccfc 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.h @@ -61,7 +61,6 @@ public: void suspend(); void resume(); - protected: QDirectFBMouseHandlerPrivate *d; }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp index 924090c..72e0ce5 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp @@ -56,15 +56,20 @@ IDirectFBSurface *QDirectFBPaintDevice::directFBSurface() const } -void QDirectFBPaintDevice::lockDirectFB() +void QDirectFBPaintDevice::lockDirectFB(uint flags) { - if (lockedImage) - return; // Already locked - - if (uchar *mem = QDirectFBScreen::lockSurface(dfbSurface, DSLF_WRITE, &bpl)) { - const QSize s = size(); - lockedImage = new QImage(mem, s.width(), s.height(), bpl, - QDirectFBScreen::getImageFormat(dfbSurface)); + if (!(lock & flags)) { + if (lock) + unlockDirectFB(); + if ((mem = QDirectFBScreen::lockSurface(dfbSurface, flags, &bpl))) { + const QSize s = size(); + lockedImage = new QImage(mem, s.width(), s.height(), bpl, + QDirectFBScreen::getImageFormat(dfbSurface)); + lock = flags; + Q_ASSERT(mem); + } else { + lock = 0; + } } } @@ -77,15 +82,19 @@ void QDirectFBPaintDevice::unlockDirectFB() dfbSurface->Unlock(dfbSurface); delete lockedImage; lockedImage = 0; + mem = 0; + lock = 0; } -void* QDirectFBPaintDevice::memory() const +void *QDirectFBPaintDevice::memory() const { - QDirectFBPaintDevice* that = const_cast<QDirectFBPaintDevice*>(this); - that->lockDirectFB(); - Q_ASSERT(that->lockedImage); - return that->lockedImage->bits(); + if (lock != (DSLF_READ|DSLF_WRITE)) { + QDirectFBPaintDevice *that = const_cast<QDirectFBPaintDevice*>(this); + that->lockDirectFB(DSLF_READ|DSLF_WRITE); + Q_ASSERT(that->lockedImage); + } + return mem; } @@ -101,7 +110,7 @@ int QDirectFBPaintDevice::bytesPerLine() const // Can only get the stride when we lock the surface Q_ASSERT(!lockedImage); QDirectFBPaintDevice* that = const_cast<QDirectFBPaintDevice*>(this); - that->lockDirectFB(); + that->lockDirectFB(DSLF_READ); Q_ASSERT(bpl != -1); } return bpl; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h index a11064b..13f0a8f 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h @@ -58,7 +58,7 @@ public: IDirectFBSurface *directFBSurface() const; - void lockDirectFB(); + void lockDirectFB(uint flags); void unlockDirectFB(); inline bool forceRasterPrimitives() const { return forceRaster; } @@ -69,6 +69,7 @@ public: int bytesPerLine() const; QSize size() const; int metric(QPaintDevice::PaintDeviceMetric metric) const; + uint lockFlags() const { return lock; } protected: // Shouldn't create QDirectFBPaintDevice by itself but only sub-class it: QDirectFBPaintDevice(QDirectFBScreen *scr = QDirectFBScreen::instance()) @@ -76,7 +77,10 @@ protected: dfbSurface(0), lockedImage(0), screen(scr), - forceRaster(false) {} + forceRaster(false), + lock(0), + mem(0) + {} inline int dotsPerMeterX() const { @@ -92,6 +96,8 @@ protected: QDirectFBScreen *screen; int bpl; bool forceRaster; + uint lock; + uchar *mem; private: Q_DISABLE_COPY(QDirectFBPaintDevice) }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index ba5d71a..6d8f617 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -43,7 +43,7 @@ #ifndef QT_NO_DIRECTFB -#include "qdirectfbsurface.h" +#include "qdirectfbwindowsurface.h" #include "qdirectfbscreen.h" #include "qdirectfbpixmap.h" #include <directfb.h> @@ -54,12 +54,33 @@ #include <private/qpixmapdata_p.h> #include <private/qpixmap_raster_p.h> +#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS +#define VOID_ARG() static_cast<bool>(false) +enum PaintOperation { + DRAW_RECTS = 0x0001, + DRAW_LINES = 0x0002, + DRAW_IMAGE = 0x0004, + DRAW_PIXMAP = 0x0008, + DRAW_TILED_PIXMAP = 0x0010, + STROKE_PATH = 0x0020, + DRAW_PATH = 0x0040, + DRAW_POINTS = 0x0080, + DRAW_ELLIPSE = 0x0100, + DRAW_POLYGON = 0x0200, + DRAW_TEXT = 0x0400, + FILL_PATH = 0x0800, + FILL_RECT = 0x1000, + DRAW_COLORSPANS = 0x2000, + ALL = 0xffff +}; +#endif + #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS template <typename T> inline const T *ptr(const T &t) { return &t; } template <> inline const bool* ptr<bool>(const bool &) { return 0; } template <typename device, typename T1, typename T2, typename T3> static void rasterFallbackWarn(const char *msg, const char *func, const device *dev, - bool matrixScale, bool matrixRotShear, bool simplePen, + QDirectFBPaintEnginePrivate::Scale scale, bool matrixRotShear, bool simplePen, bool dfbHandledClip, bool forceRasterPrimitives, const char *nameOne, const T1 &one, const char *nameTwo, const T2 &two, @@ -74,7 +95,7 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * dbg << dev << "of type" << dev->devType(); } - dbg << "matrixScale" << matrixScale + dbg << "scale" << scale << "matrixRotShear" << matrixRotShear << "simplePen" << simplePen << "dfbHandledClip" << dfbHandledClip @@ -98,24 +119,31 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * #endif #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS -#define RASTERFALLBACK(one, two, three) rasterFallbackWarn("Disabled raster engine operation", \ - __FUNCTION__, state()->painter->device(), \ - d_func()->matrixScale, d_func()->matrixRotShear, \ - d_func()->simplePen, d_func()->dfbCanHandleClip(), \ - d_func()->forceRasterPrimitives, \ - #one, one, #two, two, #three, three); \ - return; +#define RASTERFALLBACK(op, one, two, three) \ + if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ + rasterFallbackWarn("Disabled raster engine operation", \ + __FUNCTION__, state()->painter->device(), \ + d_func()->scale, d_func()->matrixRotShear, \ + d_func()->simplePen, d_func()->dfbCanHandleClip(), \ + d_func()->forceRasterPrimitives, \ + #one, one, #two, two, #three, three); \ + if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \ + return; #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS -#define RASTERFALLBACK(one, two, three) return; +#define RASTERFALLBACK(op, one, two, three) \ + if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \ + return; #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS -#define RASTERFALLBACK(one, two, three) rasterFallbackWarn("Falling back to raster engine for", \ - __FUNCTION__, state()->painter->device(), \ - d_func()->matrixScale, d_func()->matrixRotShear, \ - d_func()->simplePen, d_func()->dfbCanHandleClip(), \ - d_func()->forceRasterPrimitives, \ - #one, one, #two, two, #three, three); +#define RASTERFALLBACK(op, one, two, three) \ + if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ + rasterFallbackWarn("Falling back to raster engine for", \ + __FUNCTION__, state()->painter->device(), \ + d_func()->scale, d_func()->matrixRotShear, \ + d_func()->simplePen, d_func()->dfbCanHandleClip(), \ + d_func()->forceRasterPrimitives, \ + #one, one, #two, two, #three, three); #else -#define RASTERFALLBACK(one, two, three) +#define RASTERFALLBACK(op, one, two, three) #endif static inline uint ALPHA_MUL(uint x, uint a) @@ -128,113 +156,57 @@ static inline uint ALPHA_MUL(uint x, uint a) class SurfaceCache { public: - SurfaceCache(); - ~SurfaceCache(); - - inline IDirectFBSurface *getSurface(const uint *buffer, int size); - inline void clear(); - -private: - IDirectFBSurface *surface; - uint *buffer; - int bufsize; -}; + SurfaceCache() : surface(0), buffer(0), bufsize(0) {} + ~SurfaceCache() { clear(); } -SurfaceCache::SurfaceCache() - : surface(0), buffer(0), bufsize(0) -{ -} -class CachedImage -{ -public: - CachedImage(const QImage &image); - ~CachedImage(); + IDirectFBSurface *getSurface(const uint *buf, int size) + { + if (buffer == buf && bufsize == size) + return surface; - IDirectFBSurface *surface() { return s; } + clear(); -private: - IDirectFBSurface *s; -}; + const DFBSurfaceDescription description = QDirectFBScreen::getSurfaceDescription(buf, size); + surface = QDirectFBScreen::instance()->createDFBSurface(description, QDirectFBScreen::TrackSurface); + if (!surface) + qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface"); -CachedImage::CachedImage(const QImage &image) - : s(0) -{ - IDirectFBSurface *tmpSurface = 0; - DFBSurfaceDescription description; - description = QDirectFBScreen::getSurfaceDescription(image); - QDirectFBScreen* screen = QDirectFBScreen::instance(); + buffer = const_cast<uint*>(buf); + bufsize = size; - tmpSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); - if (!tmpSurface) { - qWarning("CachedImage CreateSurface failed!"); - return; + return surface; } -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(tmpSurface, image); -#endif - - description.flags = DFBSurfaceDescriptionFlags(description.flags & ~DSDESC_PREALLOCATED); - - s = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); - if (!s) - qWarning("QDirectFBPaintEngine failed caching image"); - -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(s, image); -#endif - - if (s) { - s->SetBlittingFlags(s, DSBLIT_NOFX); - s->Blit(s, tmpSurface, 0, 0, 0); - s->ReleaseSource(s); + void clear() + { + if (surface && QDirectFBScreen::instance()) + QDirectFBScreen::instance()->releaseDFBSurface(surface); + surface = 0; + buffer = 0; + bufsize = 0; } - if (tmpSurface) - screen->releaseDFBSurface(tmpSurface); -} - -CachedImage::~CachedImage() -{ - if (s && QDirectFBScreen::instance()) - QDirectFBScreen::instance()->releaseDFBSurface(s); -} - -static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB - -IDirectFBSurface* SurfaceCache::getSurface(const uint *buf, int size) -{ - if (buffer == buf && bufsize == size) - return surface; - - clear(); - - DFBSurfaceDescription description; - description = QDirectFBScreen::getSurfaceDescription(buf, size); - - surface = QDirectFBScreen::instance()->createDFBSurface(&description, QDirectFBScreen::TrackSurface); - if (!surface) - qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface"); - - buffer = const_cast<uint*>(buf); - bufsize = size; - - return surface; -} +private: + IDirectFBSurface *surface; + uint *buffer; + int bufsize; +}; -void SurfaceCache::clear() -{ - if (surface) - QDirectFBScreen::instance()->releaseDFBSurface(surface); - surface = 0; - buffer = 0; - bufsize = 0; -} -SurfaceCache::~SurfaceCache() +#ifdef QT_DIRECTFB_IMAGECACHE +#include <private/qimage_p.h> +struct CachedImage { - clear(); -} + IDirectFBSurface *surface; + ~CachedImage() + { + if (surface && QDirectFBScreen::instance()) { + QDirectFBScreen::instance()->releaseDFBSurface(surface); + } + } +}; +static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB +#endif class QDirectFBPaintEnginePrivate : public QRasterPaintEnginePrivate { @@ -242,18 +214,6 @@ public: QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p); ~QDirectFBPaintEnginePrivate(); - IDirectFBSurface *surface; - - QPen pen; - - bool antialiased; - bool forceRasterPrimitives; - - bool simplePen; - - bool matrixRotShear; - bool matrixScale; - void setTransform(const QTransform &m); void setPen(const QPen &pen); void setCompositionMode(QPainter::CompositionMode mode); @@ -270,33 +230,48 @@ public: inline bool dfbCanHandleClip() const; inline bool isSimpleBrush(const QBrush &brush) const; - void drawLines(const QLine *lines, int count) const; - void drawLines(const QLineF *lines, int count) const; - - void fillRegion(const QRegion &r) const; - void fillRects(const QRect *rects, int count) const; - void drawRects(const QRect *rects, int count) const; - void fillRects(const QRectF *rects, int count) const; - void drawRects(const QRectF *rects, int count) const; + void drawLines(const QLine *lines, int count); + void drawLines(const QLineF *lines, int count); + void fillRegion(const QRegion &r); + void fillRects(const QRect *rects, int count); + void drawRects(const QRect *rects, int count); + void fillRects(const QRectF *rects, int count); + void drawRects(const QRectF *rects, int count); - void drawPixmap(const QRectF &dest, - const QPixmap &pixmap, const QRectF &src); void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap); - void drawImage(const QRectF &dest, const QImage &image, const QRectF &src); + void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src); inline void updateClip(); - inline void setClipDirty(); void systemStateChanged(); void begin(QPaintDevice *device); void end(); + static IDirectFBSurface *getSurface(const QImage &img, bool *release); + +#ifdef QT_DIRECTFB_IMAGECACHE + static inline int cacheCost(const QImage &img) { return img.width() * img.height() * img.depth() / 8; } +#endif + void prepareForBlit(bool alpha); +private: + IDirectFBSurface *surface; + + QPen pen; + + bool antialiased; + bool forceRasterPrimitives; + + bool simplePen; + + bool matrixRotShear; + enum Scale { NoScale, Scaled, NegativeScale } scale; + SurfaceCache *surfaceCache; QTransform transform; int lastLockedHeight; -private: + IDirectFB *fb; DFBSurfaceDescription fbDescription; int fbWidth; @@ -309,468 +284,14 @@ private: bool dirtyClip; bool dfbHandledClip; + bool ignoreSystemClip; QDirectFBPaintDevice *dfbDevice; + void *lockedMemory; QDirectFBPaintEngine *q; + friend class QDirectFBPaintEngine; }; -QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) - : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false), - matrixRotShear(false), matrixScale(false), lastLockedHeight(-1), - fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0), - blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true), - dfbHandledClip(false), dfbDevice(0), q(p) -{ - fb = QDirectFBScreen::instance()->dfb(); - surfaceCache = new SurfaceCache; - static int cacheLimit = qgetenv("QT_DIRECTFB_IMAGECACHE").toInt(); - if (cacheLimit > 0) - imageCache.setMaxCost(cacheLimit * 1024); -} - -QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate() -{ - delete surfaceCache; -} - -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const -{ - // TODO: Check to see if DirectFB can handle the clip for the given rect - return dfbHandledClip; -} - -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const -{ - // TODO: Check to see if DirectFB can handle the clip for the given rect - return dfbHandledClip; -} - -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const -{ - return dfbHandledClip; -} - -bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const -{ - return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); -} - -void QDirectFBPaintEnginePrivate::setClipDirty() -{ - dirtyClip = true; -} - -void QDirectFBPaintEnginePrivate::lock() -{ - // We will potentially get a new pointer to the buffer after a - // lock so we need to call the base implementation of prepare so - // it updates its rasterBuffer to point to the new buffer address. - lastLockedHeight = dfbDevice->height(); - - Q_ASSERT(dfbDevice); - prepare(dfbDevice); -} - -void QDirectFBPaintEnginePrivate::unlock() -{ - Q_ASSERT(dfbDevice); - dfbDevice->unlockDirectFB(); -} - -void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m) -{ - transform = m; - matrixRotShear = (transform.m12() != 0 || transform.m21() != 0); - matrixScale = (transform.m11() != 1 || transform.m22() != 1); -} - -void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) -{ - lastLockedHeight = -1; - if (device->devType() == QInternal::CustomRaster) - dfbDevice = static_cast<QDirectFBPaintDevice*>(device); - else if (device->devType() == QInternal::Pixmap) { - QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData* dfbPixmapData = static_cast<QDirectFBPixmapData*>(data); - dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData); - } - - if (dfbDevice) - surface = dfbDevice->directFBSurface(); - - if (!surface) { - qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", - device->devType()); - } - forceRasterPrimitives = dfbDevice->forceRasterPrimitives(); - - surface->GetSize(surface, &fbWidth, &fbHeight); - - setTransform(QTransform()); - antialiased = false; - opacity = 255; - setCompositionMode(q->state()->compositionMode()); - dirtyClip = true; - setPen(q->state()->pen); - setDFBColor(pen.color()); -} - -void QDirectFBPaintEnginePrivate::end() -{ - dfbDevice = 0; - surface->ReleaseSource(surface); - surface->SetClip(surface, NULL); - surface = 0; -} - -void QDirectFBPaintEnginePrivate::setPen(const QPen &p) -{ - pen = p; - simplePen = (pen.style() == Qt::NoPen) || - (pen.style() == Qt::SolidLine - && !antialiased - && (pen.brush().style() == Qt::SolidPattern) - && (pen.widthF() <= 1 && !matrixScale)); -} - -void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) -{ - blitFlagsFromCompositionMode = DSBLIT_NOFX; - drawFlagsFromCompositionMode = DSDRAW_NOFX; - - bool blend = true; - switch (mode) { - case QPainter::CompositionMode_SourceOver: - porterDuffRule = DSPD_SRC_OVER; - break; - case QPainter::CompositionMode_DestinationOver: - porterDuffRule = DSPD_DST_OVER; - break; - case QPainter::CompositionMode_Clear: - porterDuffRule = DSPD_CLEAR; - blend = false; - break; - case QPainter::CompositionMode_Source: - porterDuffRule = DSPD_SRC; - blend = false; - break; - case QPainter::CompositionMode_Destination: - porterDuffRule = DSPD_NONE; // ### need to double check this - blend = false; - return; - case QPainter::CompositionMode_SourceIn: - porterDuffRule = DSPD_SRC_IN; - break; - case QPainter::CompositionMode_DestinationIn: - porterDuffRule = DSPD_DST_IN; - break; - case QPainter::CompositionMode_SourceOut: - porterDuffRule = DSPD_SRC_OUT; - break; - case QPainter::CompositionMode_DestinationOut: - porterDuffRule = DSPD_DST_OUT; - break; - case QPainter::CompositionMode_Xor: - porterDuffRule = DSPD_XOR; - blitFlagsFromCompositionMode |= DSBLIT_XOR; - drawFlagsFromCompositionMode |= DSDRAW_XOR; - break; -// case QPainter::CompositionMode_Plus: // ??? -// porterDuffRule = DSPD_ADD; -// break; - default: - qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): " - "mode %d not implemented", mode); - return; - } - // intentially not comparing with current porterDuffRule. surface might have changed. - if (blend) { - blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL; - drawFlagsFromCompositionMode |= DSDRAW_BLEND; - } - if (opacity != 255) { - setOpacity(opacity); - } -} - -void QDirectFBPaintEnginePrivate::setOpacity(quint8 op) -{ - opacity = op; - if (opacity == 255) { - blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA; - } else { - blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA; - } -} - -void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) -{ - const bool old = antialiased; - antialiased = bool(hints & QPainter::Antialiasing); - if (old != antialiased) { - setPen(q->state()->pen); - } -} - -void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) -{ - quint32 blittingFlags = blitFlagsFromCompositionMode; - if (alpha) { - surface->SetPorterDuff(surface, - (blittingFlags & DSBLIT_BLEND_COLORALPHA) - ? DSPD_NONE - : porterDuffRule); - } else { - blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL; - surface->SetPorterDuff(surface, DSPD_NONE); - } - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags)); -} - -void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) -{ - Q_ASSERT(surface); - const quint8 alpha = (opacity == 255 ? - color.alpha() : ALPHA_MUL(color.alpha(), opacity)); - surface->SetColor(surface, - color.red(), color.green(), color.blue(), alpha); - quint32 drawingFlags = drawFlagsFromCompositionMode; - if (alpha == 255) { - drawingFlags &= ~DSDRAW_BLEND; - } - surface->SetPorterDuff(surface, DSPD_NONE); - // PorterDuff messes up alpha values for primitives - surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags)); -} - -void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) const -{ - for (int i = 0; i < n; ++i) { - const QLine l = transform.map(lines[i]); - surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); - } -} - -void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) const -{ - for (int i = 0; i < n; ++i) { - const QLine l = transform.map(lines[i]).toLine(); - surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); - } -} - -void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®ion) const -{ - const QVector<QRect> rects = region.rects(); - const int n = rects.size(); - fillRects(rects.constData(), n); -} - -void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n) const -{ - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]); - surface->FillRectangle(surface, r.x(), r.y(), - r.width(), r.height()); - } -} - -void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n) const -{ - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]).toRect(); - surface->FillRectangle(surface, r.x(), r.y(), - r.width(), r.height()); - } -} - -void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n) const -{ - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]); - surface->DrawRectangle(surface, r.x(), r.y(), - r.width() + 1, r.height() + 1); - } -} - -void QDirectFBPaintEnginePrivate::drawRects(const QRectF *rects, int n) const -{ - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]).toRect(); - surface->DrawRectangle(surface, r.x(), r.y(), - r.width() + 1, r.height() + 1); - } -} - -void QDirectFBPaintEnginePrivate::drawPixmap(const QRectF &dest, - const QPixmap &pixmap, - const QRectF &src) -{ - prepareForBlit(pixmap.hasAlphaChannel()); - QPixmapData *data = pixmap.pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); - IDirectFBSurface *s = dfbData->directFBSurface(); - const QRect sr = src.toRect(); - const QRect dr = transform.mapRect(dest).toRect(); - const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; - DFBResult result; - - if (dr.size() == sr.size()) { - result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); - } else { - const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; - result = surface->StretchBlit(surface, s, &sRect, &dRect); - } - if (result != DFB_OK) - DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); -} - -void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, - const QPixmap &pixmap) -{ - prepareForBlit(pixmap.hasAlphaChannel()); - QPixmapData *data = pixmap.pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); - IDirectFBSurface *s = dfbData->directFBSurface(); - const QRect dr = transform.mapRect(dest).toRect(); - DFBResult result = DFB_OK; - - if (!matrixScale && dr == QRect(0, 0, fbWidth, fbHeight)) { - result = surface->TileBlit(surface, s, 0, 0, 0); - } else if (!matrixScale) { - const int dx = pixmap.width(); - const int dy = pixmap.height(); - const DFBRectangle rect = { 0, 0, dx, dy }; - QVarLengthArray<DFBRectangle> rects; - QVarLengthArray<DFBPoint> points; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - rects.append(rect); - const DFBPoint point = { x, y }; - points.append(point); - } - } - result = surface->BatchBlit(surface, s, rects.constData(), - points.constData(), points.size()); - } else { - const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height())); - const int dx = sr.width(); - const int dy = sr.height(); - const DFBRectangle sRect = { 0, 0, dx, dy }; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - const DFBRectangle dRect = { x, y, dx, dy }; - result = surface->StretchBlit(surface, s, &sRect, &dRect); - if (result != DFB_OK) { - y = dr.bottom() + 1; - break; - } - } - } - } - - if (result != DFB_OK) - DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); -} - -void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, - const QImage &image, - const QRectF &src) -{ - Q_ASSERT(QDirectFBScreen::getSurfacePixelFormat(image.format()) != DSPF_UNKNOWN); - CachedImage *img = imageCache[image.cacheKey()]; - IDirectFBSurface *imgSurface = 0; - bool doRelease = false; - - if (img) { - imgSurface = img->surface(); - } else { - const int cost = image.width() * image.height() * image.depth() / 8; - if (cost <= imageCache.maxCost()) { - img = new CachedImage(image); - imgSurface = img->surface(); - if (imgSurface) { - imageCache.insert(image.cacheKey(), img, cost); - } else { - delete img; - img = 0; - } - } - - if (!imgSurface) { - DFBSurfaceDescription description; - - description = QDirectFBScreen::getSurfaceDescription(image); - imgSurface = QDirectFBScreen::instance()->createDFBSurface(&description, - QDirectFBScreen::DontTrackSurface); - if (!imgSurface) { - qWarning("QDirectFBPaintEnginePrivate::drawImage"); - return; - } - -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(surface, image); -#endif - doRelease = (imgSurface != 0); - } - } - - const QRect sr = src.toRect(); - const QRect dr = transform.mapRect(dest).toRect(); - const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; - - prepareForBlit(image.hasAlphaChannel()); - if (dr.size() == sr.size()) { - surface->Blit(surface, imgSurface, &sRect, dr.x(), dr.y()); - } else { - const DFBRectangle dRect = { dr.x(), dr.y(), - dr.width(), dr.height() }; - surface->StretchBlit(surface, imgSurface, &sRect, &dRect); - } - if (doRelease) { - surface->ReleaseSource(surface); - imgSurface->Release(imgSurface); - } -} - -void QDirectFBPaintEnginePrivate::updateClip() -{ - if (!dirtyClip) - return; - - if (!clip() || !clip()->enabled) { - surface->SetClip(surface, NULL); - dfbHandledClip = true; - } - else if (clip()->hasRectClip) { - const DFBRegion r = { - clip()->clipRect.x(), - clip()->clipRect.y(), - clip()->clipRect.x() + clip()->clipRect.width(), - clip()->clipRect.y() + clip()->clipRect.height() - }; - surface->SetClip(surface, &r); - - dfbHandledClip = true; - } - else - dfbHandledClip = false; - - dirtyClip = false; -} - -void QDirectFBPaintEnginePrivate::systemStateChanged() -{ - setClipDirty(); - QRasterPaintEnginePrivate::systemStateChanged(); -} - QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device) : QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device) { @@ -799,12 +320,10 @@ bool QDirectFBPaintEngine::end() return QRasterPaintEngine::end(); } - - void QDirectFBPaintEngine::clipEnabledChanged() { Q_D(QDirectFBPaintEngine); - d->setClipDirty(); + d->dirtyClip = true; QRasterPaintEngine::clipEnabledChanged(); } @@ -840,9 +359,9 @@ void QDirectFBPaintEngine::renderHintsChanged() void QDirectFBPaintEngine::transformChanged() { Q_D(QDirectFBPaintEngine); - const bool old = d->matrixScale; + const QDirectFBPaintEnginePrivate::Scale old = d->scale; d->setTransform(state()->transform()); - if (d->matrixScale != old) { + if (d->scale != old) { d->setPen(state()->pen); } QRasterPaintEngine::transformChanged(); @@ -852,7 +371,7 @@ void QDirectFBPaintEngine::setState(QPainterState *s) { Q_D(QDirectFBPaintEngine); QRasterPaintEngine::setState(s); - d->setClipDirty(); + d->dirtyClip = true; d->setPen(state()->pen); d->setOpacity(quint8(state()->opacity * 255)); d->setCompositionMode(state()->compositionMode()); @@ -862,7 +381,7 @@ void QDirectFBPaintEngine::setState(QPainterState *s) void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) { Q_D(QDirectFBPaintEngine); - d->setClipDirty(); + d->dirtyClip = true; const QPoint bottom = d->transform.map(QPoint(0, path.controlPointRect().y2)); if (bottom.y() >= d->lastLockedHeight) d->lock(); @@ -872,8 +391,8 @@ void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) { Q_D(QDirectFBPaintEngine); - d->setClipDirty(); - if (!d->clip()->hasRectClip && d->clip()->enabled) { + d->dirtyClip = true; + if (d->clip() && !d->clip()->hasRectClip && d->clip()->enabled) { const QPoint bottom = d->transform.map(QPoint(0, rect.bottom())); if (bottom.y() >= d->lastLockedHeight) d->lock(); @@ -890,7 +409,7 @@ void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount) if (!d->dfbCanHandleClip() || d->matrixRotShear || !d->simplePen || d->forceRasterPrimitives || !d->isSimpleBrush(brush)) { - RASTERFALLBACK(rectCount, static_cast<bool>(false), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawRects(rects, rectCount); return; @@ -916,6 +435,7 @@ void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount) if (!d->dfbCanHandleClip() || d->matrixRotShear || !d->simplePen || d->forceRasterPrimitives || !d->isSimpleBrush(brush)) { + RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawRects(rects, rectCount); return; @@ -938,7 +458,7 @@ void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount) Q_D(QDirectFBPaintEngine); d->updateClip(); if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) { - RASTERFALLBACK(lineCount, static_cast<bool>(false), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawLines(lines, lineCount); return; @@ -956,7 +476,7 @@ void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount) Q_D(QDirectFBPaintEngine); d->updateClip(); if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) { - RASTERFALLBACK(lineCount, static_cast<bool>(false), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawLines(lines, lineCount); return; @@ -974,23 +494,53 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, Qt::ImageConversionFlags flags) { Q_D(QDirectFBPaintEngine); - Q_UNUSED(flags); // XXX + Q_UNUSED(flags); + + /* This is hard to read. The way it works is like this: + + - If you do not have support for preallocated surfaces and do not use an + image cache we always fall back to raster engine. + + - If it's rotated/sheared/mirrored (negative scale) or we can't + clip it we fall back to raster engine. + + - If we don't cache the image, but we do have support for + preallocated surfaces we fall back to the raster engine if the + image is in a format DirectFB can't handle. + + - If we do cache the image but don't have support for preallocated + images and the cost of caching the image (bytes used) is higher + than the max image cache size we fall back to raster engine. + */ -#ifndef QT_NO_DIRECTFB_PREALLOCATED d->updateClip(); - if (!d->dfbCanHandleClip(r) || d->matrixRotShear - || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN) +#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE + if (d->matrixRotShear + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale + || !d->dfbCanHandleClip(r) +#ifndef QT_DIRECTFB_IMAGECACHE + || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN +#elif defined QT_NO_DIRECTFB_PREALLOCATED + || QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost() +#endif + ) #endif { - RASTERFALLBACK(r, image.size(), sr); + RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr); d->lock(); QRasterPaintEngine::drawImage(r, image, sr, flags); return; } - -#ifndef QT_NO_DIRECTFB_PREALLOCATED +#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE d->unlock(); - d->drawImage(r, image, sr); + bool release; + IDirectFBSurface *imgSurface = d->getSurface(image, &release); + d->prepareForBlit(QDirectFBScreen::hasAlpha(imgSurface)); + d->blit(r, imgSurface, sr); + if (release) { + imgSurface->ReleaseSource(imgSurface); + imgSurface->Release(imgSurface); + } #endif } @@ -1006,17 +556,23 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, d->updateClip(); if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { - // not using RASTERFALLBACK since this is the way we do bitmaps? + RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); d->lock(); QRasterPaintEngine::drawPixmap(r, pixmap, sr); - } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear) { - RASTERFALLBACK(r, pixmap.size(), sr); - const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { + RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); + const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ); d->lock(); QRasterPaintEngine::drawImage(r, *img, sr); } else { d->unlock(); - d->drawPixmap(r, pixmap, sr); + d->prepareForBlit(pixmap.hasAlphaChannel()); + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); + IDirectFBSurface *s = dfbData->directFBSurface(); + d->blit(r, s, sr); } } @@ -1032,11 +588,13 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, Q_D(QDirectFBPaintEngine); d->updateClip(); if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { + RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); d->lock(); QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp); - } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) { - RASTERFALLBACK(r, pixmap.size(), sp); - const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull() + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { + RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); + const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ); d->lock(); QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType); data->fromImage(*img, Qt::AutoColor); @@ -1051,6 +609,7 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen) { + RASTERFALLBACK(STROKE_PATH, path, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::stroke(path, pen); @@ -1058,7 +617,7 @@ void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen) void QDirectFBPaintEngine::drawPath(const QPainterPath &path) { - RASTERFALLBACK(path.boundingRect(), static_cast<bool>(false), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_PATH, path, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::drawPath(path); @@ -1066,7 +625,7 @@ void QDirectFBPaintEngine::drawPath(const QPainterPath &path) void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount) { - RASTERFALLBACK(pointCount, static_cast<bool>(false), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::drawPoints(points, pointCount); @@ -1074,7 +633,7 @@ void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount) void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount) { - RASTERFALLBACK(pointCount, static_cast<bool>(false), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::drawPoints(points, pointCount); @@ -1082,7 +641,7 @@ void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount) void QDirectFBPaintEngine::drawEllipse(const QRectF &rect) { - RASTERFALLBACK(rect, static_cast<bool>(false), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_ELLIPSE, rect, VOID_ARG(), VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::drawEllipse(rect); @@ -1091,7 +650,7 @@ void QDirectFBPaintEngine::drawEllipse(const QRectF &rect) void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) { - RASTERFALLBACK(pointCount, mode, static_cast<bool>(false)); + RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::drawPolygon(points, pointCount, mode); @@ -1100,7 +659,7 @@ void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount, void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) { - RASTERFALLBACK(pointCount, mode, static_cast<bool>(false)); + RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::drawPolygon(points, pointCount, mode); @@ -1109,7 +668,7 @@ void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount, void QDirectFBPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) { - RASTERFALLBACK(p, textItem.text(), static_cast<bool>(false)); + RASTERFALLBACK(DRAW_TEXT, p, textItem.text(), VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::drawTextItem(p, textItem); @@ -1117,7 +676,7 @@ void QDirectFBPaintEngine::drawTextItem(const QPointF &p, void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush) { - RASTERFALLBACK(path, brush, static_cast<bool>(false)); + RASTERFALLBACK(FILL_PATH, path, brush, VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); QRasterPaintEngine::fill(path, brush); @@ -1151,7 +710,7 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) break; } } - RASTERFALLBACK(rect, brush, static_cast<bool>(false)); + RASTERFALLBACK(FILL_RECT, rect, brush, VOID_ARG()); d->lock(); QRasterPaintEngine::fillRect(rect, brush); } @@ -1161,7 +720,7 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color) Q_D(QDirectFBPaintEngine); d->updateClip(); if (!d->dfbCanHandleClip() || d->matrixRotShear || d->forceRasterPrimitives) { - RASTERFALLBACK(rect, color, static_cast<bool>(false)); + RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG()); d->lock(); QRasterPaintEngine::fillRect(rect, color); } else { @@ -1178,7 +737,7 @@ void QDirectFBPaintEngine::drawColorSpans(const QSpan *spans, int count, { Q_D(QDirectFBPaintEngine); if (d->forceRasterPrimitives) { - RASTERFALLBACK(count, color, static_cast<bool>(false)); + RASTERFALLBACK(DRAW_COLORSPANS, count, color, VOID_ARG()); d->lock(); QRasterPaintEngine::drawColorSpans(spans, count, color); } else { @@ -1223,4 +782,457 @@ void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize, d->surface->Blit(d->surface, src, &rect, x, y); } +#ifdef QT_DIRECTFB_IMAGECACHE +static void cachedImageCleanupHook(qint64 key) +{ + delete imageCache.take(key); +} +void QDirectFBPaintEngine::initImageCache(int size) +{ + Q_ASSERT(size >= 0); + imageCache.setMaxCost(size); + typedef void (*_qt_image_cleanup_hook_64)(qint64); + extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; + qt_image_cleanup_hook_64 = ::cachedImageCleanupHook; +} + +#endif // QT_DIRECTFB_IMAGECACHE + +// ---- QDirectFBPaintEnginePrivate ---- + + +QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) + : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false), + matrixRotShear(false), scale(NoScale), lastLockedHeight(-1), + fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0), + blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true), + dfbHandledClip(false), dfbDevice(0), lockedMemory(0), q(p) +{ + fb = QDirectFBScreen::instance()->dfb(); + ignoreSystemClip = QDirectFBScreen::instance()->directFBFlags() & QDirectFBScreen::IgnoreSystemClip; + surfaceCache = new SurfaceCache; +} + +QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate() +{ + delete surfaceCache; +} + +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const +{ + // TODO: Check to see if DirectFB can handle the clip for the given rect + return dfbHandledClip; +} + +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const +{ + // TODO: Check to see if DirectFB can handle the clip for the given rect + return dfbHandledClip; +} + +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const +{ + return dfbHandledClip; +} + +bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const +{ + return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); +} + +void QDirectFBPaintEnginePrivate::lock() +{ + // We will potentially get a new pointer to the buffer after a + // lock so we need to call the base implementation of prepare so + // it updates its rasterBuffer to point to the new buffer address. + Q_ASSERT(dfbDevice); + if (dfbDevice->lockFlags() != (DSLF_WRITE|DSLF_READ) + || dfbDevice->height() != lastLockedHeight + || dfbDevice->memory() != lockedMemory) { + prepare(dfbDevice); + lastLockedHeight = dfbDevice->height(); + lockedMemory = dfbDevice->memory(); + } +} + +void QDirectFBPaintEnginePrivate::unlock() +{ + Q_ASSERT(dfbDevice); + dfbDevice->unlockDirectFB(); + lockedMemory = 0; +} + +void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m) +{ + transform = m; + matrixRotShear = (transform.m12() != 0 || transform.m21() != 0); + if (qMin(transform.m11(), transform.m22()) < 0) { + scale = NegativeScale; + } else if (transform.m11() != 1 || transform.m22() != 1) { + scale = Scaled; + } else { + scale = NoScale; + } +} + +void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) +{ + lastLockedHeight = -1; + if (device->devType() == QInternal::CustomRaster) + dfbDevice = static_cast<QDirectFBPaintDevice*>(device); + else if (device->devType() == QInternal::Pixmap) { + QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData* dfbPixmapData = static_cast<QDirectFBPixmapData*>(data); + dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData); + } + + if (dfbDevice) + surface = dfbDevice->directFBSurface(); + + if (!surface) { + qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", + device->devType()); + } + lockedMemory = 0; + forceRasterPrimitives = dfbDevice->forceRasterPrimitives(); + + surface->GetSize(surface, &fbWidth, &fbHeight); + + setTransform(QTransform()); + antialiased = false; + opacity = 255; + setCompositionMode(q->state()->compositionMode()); + dirtyClip = true; + setPen(q->state()->pen); + setDFBColor(pen.color()); +} + +void QDirectFBPaintEnginePrivate::end() +{ + lockedMemory = 0; + dfbDevice = 0; + surface->ReleaseSource(surface); + surface->SetClip(surface, NULL); + surface = 0; +} + +void QDirectFBPaintEnginePrivate::setPen(const QPen &p) +{ + pen = p; + simplePen = (pen.style() == Qt::NoPen) || + (pen.style() == Qt::SolidLine + && !antialiased + && (pen.brush().style() == Qt::SolidPattern) + && (pen.widthF() <= 1 && scale != NoScale)); +} + +void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) +{ + blitFlagsFromCompositionMode = DSBLIT_NOFX; + drawFlagsFromCompositionMode = DSDRAW_NOFX; + + bool blend = true; + switch (mode) { + case QPainter::CompositionMode_SourceOver: + porterDuffRule = DSPD_SRC_OVER; + break; + case QPainter::CompositionMode_DestinationOver: + porterDuffRule = DSPD_DST_OVER; + break; + case QPainter::CompositionMode_Clear: + porterDuffRule = DSPD_CLEAR; + blend = false; + break; + case QPainter::CompositionMode_Source: + porterDuffRule = DSPD_SRC; + blend = false; + break; + case QPainter::CompositionMode_Destination: + porterDuffRule = DSPD_NONE; // ### need to double check this + blend = false; + return; + case QPainter::CompositionMode_SourceIn: + porterDuffRule = DSPD_SRC_IN; + break; + case QPainter::CompositionMode_DestinationIn: + porterDuffRule = DSPD_DST_IN; + break; + case QPainter::CompositionMode_SourceOut: + porterDuffRule = DSPD_SRC_OUT; + break; + case QPainter::CompositionMode_DestinationOut: + porterDuffRule = DSPD_DST_OUT; + break; + case QPainter::CompositionMode_Xor: + porterDuffRule = DSPD_XOR; + blitFlagsFromCompositionMode |= DSBLIT_XOR; + drawFlagsFromCompositionMode |= DSDRAW_XOR; + break; +// case QPainter::CompositionMode_Plus: // ??? +// porterDuffRule = DSPD_ADD; +// break; + default: + qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): " + "mode %d not implemented", mode); + return; + } + // intentially not comparing with current porterDuffRule. surface might have changed. + if (blend) { + blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL; + drawFlagsFromCompositionMode |= DSDRAW_BLEND; + } + if (opacity != 255) { + setOpacity(opacity); + } +} + +void QDirectFBPaintEnginePrivate::setOpacity(quint8 op) +{ + opacity = op; + if (opacity == 255) { + blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA; + } else { + blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA; + } +} + +void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) +{ + const bool old = antialiased; + antialiased = bool(hints & QPainter::Antialiasing); + if (old != antialiased) { + setPen(q->state()->pen); + } +} + +void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) +{ + quint32 blittingFlags = blitFlagsFromCompositionMode; + if (alpha) { + surface->SetPorterDuff(surface, + (blittingFlags & DSBLIT_BLEND_COLORALPHA) + ? DSPD_NONE + : porterDuffRule); + } else { + blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL; + surface->SetPorterDuff(surface, DSPD_NONE); + } + surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); + surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags)); +} + +void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) +{ + Q_ASSERT(surface); + const quint8 alpha = (opacity == 255 ? + color.alpha() : ALPHA_MUL(color.alpha(), opacity)); + surface->SetColor(surface, + color.red(), color.green(), color.blue(), alpha); + quint32 drawingFlags = drawFlagsFromCompositionMode; + if (alpha == 255) { + drawingFlags &= ~DSDRAW_BLEND; + } + surface->SetPorterDuff(surface, DSPD_NONE); + // PorterDuff messes up alpha values for primitives + surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags)); +} + +void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) +{ + for (int i = 0; i < n; ++i) { + const QLine l = transform.map(lines[i]); + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + } +} + +void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) +{ + for (int i = 0; i < n; ++i) { + const QLine l = transform.map(lines[i]).toLine(); + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + } +} + +void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®ion) +{ + Q_ASSERT(isSimpleBrush(q->state()->brush)); + setDFBColor(q->state()->brush.color()); + const QVector<QRect> rects = region.rects(); + const int n = rects.size(); + fillRects(rects.constData(), n); +} + +void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n) +{ + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]); + surface->FillRectangle(surface, r.x(), r.y(), + r.width(), r.height()); + } +} + +void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n) +{ + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]).toRect(); + surface->FillRectangle(surface, r.x(), r.y(), + r.width(), r.height()); + } +} + +void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n) +{ + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]); + surface->DrawRectangle(surface, r.x(), r.y(), + r.width() + 1, r.height() + 1); + } +} + +void QDirectFBPaintEnginePrivate::drawRects(const QRectF *rects, int n) +{ + for (int i = 0; i < n; ++i) { + const QRect r = transform.mapRect(rects[i]).toRect(); + surface->DrawRectangle(surface, r.x(), r.y(), + r.width() + 1, r.height() + 1); + } +} + +IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release) +{ +#ifndef QT_DIRECTFB_IMAGECACHE + *release = true; + return QDirectFBScreen::instance()->createDFBSurface(img, QDirectFBScreen::DontTrackSurface); +#else + const qint64 key = img.cacheKey(); + *release = false; + if (imageCache.contains(key)) { + return imageCache[key]->surface; + } + + const int cost = cacheCost(img); + const bool cache = cost <= imageCache.maxCost(); + QDirectFBScreen *screen = QDirectFBScreen::instance(); + const QImage::Format format = (img.format() == screen->alphaPixmapFormat() || QDirectFBPixmapData::hasAlphaChannel(img) + ? screen->alphaPixmapFormat() : screen->pixelFormat()); + + IDirectFBSurface *surface = screen->copyToDFBSurface(img, format, + cache + ? QDirectFBScreen::TrackSurface + : QDirectFBScreen::DontTrackSurface); + if (cache) { + CachedImage *cachedImage = new CachedImage; + const_cast<QImage&>(img).data_ptr()->is_cached = true; + cachedImage->surface = surface; + imageCache.insert(key, cachedImage, cost); + } else { + *release = true; + } + return surface; +#endif +} + + +void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, const QRectF &src) +{ + const QRect sr = src.toRect(); + const QRect dr = transform.mapRect(dest).toRect(); + const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; + DFBResult result; + + if (dr.size() == sr.size()) { + result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); + } else { + const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; + result = surface->StretchBlit(surface, s, &sRect, &dRect); + } + if (result != DFB_OK) + DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); +} + +void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, + const QPixmap &pixmap) +{ + prepareForBlit(pixmap.hasAlphaChannel()); + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); + IDirectFBSurface *s = dfbData->directFBSurface(); + const QRect dr = transform.mapRect(dest).toRect(); + DFBResult result = DFB_OK; + + if (scale == NoScale && dr == QRect(0, 0, fbWidth, fbHeight)) { + result = surface->TileBlit(surface, s, 0, 0, 0); + } else if (scale == NoScale) { + const int dx = pixmap.width(); + const int dy = pixmap.height(); + const DFBRectangle rect = { 0, 0, dx, dy }; + QVarLengthArray<DFBRectangle> rects; + QVarLengthArray<DFBPoint> points; + + for (int y = dr.y(); y <= dr.bottom(); y += dy) { + for (int x = dr.x(); x <= dr.right(); x += dx) { + rects.append(rect); + const DFBPoint point = { x, y }; + points.append(point); + } + } + result = surface->BatchBlit(surface, s, rects.constData(), + points.constData(), points.size()); + } else { + const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height())); + const int dx = sr.width(); + const int dy = sr.height(); + const DFBRectangle sRect = { 0, 0, dx, dy }; + + for (int y = dr.y(); y <= dr.bottom(); y += dy) { + for (int x = dr.x(); x <= dr.right(); x += dx) { + const DFBRectangle dRect = { x, y, dx, dy }; + result = surface->StretchBlit(surface, s, &sRect, &dRect); + if (result != DFB_OK) { + y = dr.bottom() + 1; + break; + } + } + } + } + + if (result != DFB_OK) + DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); +} + +void QDirectFBPaintEnginePrivate::updateClip() +{ + if (!dirtyClip) + return; + + const QClipData *clipData = clip(); + if (!clipData || !clipData->enabled) { + surface->SetClip(surface, NULL); + dfbHandledClip = true; + } else if (clipData->hasRectClip) { + const DFBRegion r = { + clipData->clipRect.x(), + clipData->clipRect.y(), + clipData->clipRect.x() + clipData->clipRect.width(), + clipData->clipRect.y() + clipData->clipRect.height() + }; + surface->SetClip(surface, &r); + dfbHandledClip = true; + } else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) { + dfbHandledClip = true; + } else { + dfbHandledClip = false; + } + + dirtyClip = false; +} + +void QDirectFBPaintEnginePrivate::systemStateChanged() +{ + dirtyClip = true; + QRasterPaintEnginePrivate::systemStateChanged(); +} + #endif // QT_NO_DIRECTFB diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h index e79ec61..d33255b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h @@ -106,6 +106,7 @@ public: virtual void clip(const QVectorPath &path, Qt::ClipOperation op); virtual void clip(const QRect &rect, Qt::ClipOperation op); + static void initImageCache(int size); }; QT_END_HEADER diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index ea9bb3a..7297a99 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -157,6 +157,16 @@ static bool checkForAlphaPixels(const QImage &img) return false; } +bool QDirectFBPixmapData::hasAlphaChannel(const QImage &img) +{ +#ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION + return ::checkForAlphaPixels(img); +#else + return img.hasAlphaChannel(); +#endif +} + + void QDirectFBPixmapData::fromImage(const QImage &i, Qt::ImageConversionFlags flags) { @@ -166,7 +176,7 @@ void QDirectFBPixmapData::fromImage(const QImage &i, const QImage img = (i.depth() == 1 ? i.convertToFormat(screen->alphaPixmapFormat()) : i); if (img.hasAlphaChannel() #ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION - && (flags & Qt::NoOpaqueDetection || ::checkForAlphaPixels(img)) + && (flags & Qt::NoOpaqueDetection || QDirectFBPixmapData::hasAlphaChannel(img)) #endif ) { alpha = true; @@ -357,7 +367,7 @@ QImage QDirectFBPixmapData::toImage() const return img->copy(); } -QPaintEngine* QDirectFBPixmapData::paintEngine() const +QPaintEngine *QDirectFBPixmapData::paintEngine() const { if (!engine) { // QDirectFBPixmapData is also a QCustomRasterPaintDevice, so pass @@ -368,10 +378,15 @@ QPaintEngine* QDirectFBPixmapData::paintEngine() const return engine; } +QImage *QDirectFBPixmapData::buffer() +{ + lockDirectFB(DSLF_READ|DSLF_WRITE); + return lockedImage; +} -QImage* QDirectFBPixmapData::buffer() +QImage * QDirectFBPixmapData::buffer(uint lockFlags) { - lockDirectFB(); + lockDirectFB(lockFlags); return lockedImage; } @@ -381,3 +396,4 @@ void QDirectFBPixmapData::invalidate() alpha = false; format = QImage::Format_Invalid; } + diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h index 6cfafcd..7cd60d6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h @@ -69,11 +69,13 @@ public: Qt::TransformationMode mode) const; QImage toImage() const; QPaintEngine* paintEngine() const; - QImage *buffer(); + virtual QImage *buffer(); + QImage *buffer(uint lockFlags); // Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);} inline QImage::Format pixelFormat() const { return format; } + static bool hasAlphaChannel(const QImage &img); private: void invalidate(); QDirectFBPaintEngine *engine; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 3e54e7f..25e24fd 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include "qdirectfbscreen.h" -#include "qdirectfbsurface.h" +#include "qdirectfbwindowsurface.h" #include "qdirectfbpixmap.h" #include "qdirectfbmouse.h" #include "qdirectfbkeyboard.h" @@ -80,11 +80,11 @@ public: #ifndef QT_NO_DIRECTFB_KEYBOARD QDirectFBKeyboardHandler *keyboard; #endif - bool videoonly; + QDirectFBScreen::DirectFBFlags directFBFlags; QImage::Format alphaPixmapFormat; }; -QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen) +QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *screen) : QWSGraphicsSystem(screen), dfb(0), dfbSurface(0), flipFlags(DSFLIP_NONE) #ifndef QT_NO_DIRECTFB_LAYER , dfbLayer(0) @@ -96,7 +96,7 @@ QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen) #ifndef QT_NO_DIRECTFB_KEYBOARD , keyboard(0) #endif - , videoonly(false) + , directFBFlags(QDirectFBScreen::NoFlags) , alphaPixmapFormat(QImage::Format_Invalid) { #ifndef QT_NO_QWS_SIGNALHANDLER @@ -113,9 +113,9 @@ QDirectFBScreenPrivate::~QDirectFBScreenPrivate() delete keyboard; #endif - foreach (IDirectFBSurface* surf, allocatedSurfaces) - surf->Release(surf); - allocatedSurfaces.clear(); + for (QSet<IDirectFBSurface*>::const_iterator it = allocatedSurfaces.begin(); it != allocatedSurfaces.end(); ++it) { + (*it)->Release(*it); + } if (dfbSurface) dfbSurface->Release(dfbSurface); @@ -137,7 +137,7 @@ QDirectFBScreenPrivate::~QDirectFBScreenPrivate() // creates a preallocated surface with the same format as the image if // possible. -IDirectFBSurface* QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCreationOptions options) +IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCreationOptions options) { if (img.isNull()) // assert? return 0; @@ -155,8 +155,7 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCr return surface; } - DFBSurfaceDescription desc = QDirectFBScreen::getSurfaceDescription(img); - IDirectFBSurface *surface = createDFBSurface(&desc, options); + IDirectFBSurface *surface = createDFBSurface(QDirectFBScreen::getSurfaceDescription(img), options); #ifdef QT_NO_DIRECTFB_PREALLOCATED if (surface) { int bpl; @@ -211,53 +210,55 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, return 0; desc.width = size.width(); desc.height = size.height(); - return createDFBSurface(&desc, options); + return createDFBSurface(desc, options); } -IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription *desc, SurfaceCreationOptions options) +IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options) { - DFBResult result; - IDirectFBSurface* newSurface = 0; + DFBResult result = DFB_OK; + IDirectFBSurface *newSurface = 0; if (!d_ptr->dfb) { qWarning("QDirectFBScreen::createDFBSurface() - not connected"); return 0; } - if (d_ptr->videoonly && !(desc->flags & DSDESC_PREALLOCATED)) { + if (d_ptr->directFBFlags & VideoOnly && !(desc.flags & DSDESC_PREALLOCATED)) { // Add the video only capability. This means the surface will be created in video ram - DFBSurfaceDescription voDesc = *desc; - if (!(voDesc.flags & DSDESC_CAPS)) { - voDesc.caps = DSCAPS_VIDEOONLY; - voDesc.flags = DFBSurfaceDescriptionFlags(voDesc.flags | DSDESC_CAPS); + if (!(desc.flags & DSDESC_CAPS)) { + desc.caps = DSCAPS_VIDEOONLY; + desc.flags = DFBSurfaceDescriptionFlags(desc.flags | DSDESC_CAPS); } else { - voDesc.caps = DFBSurfaceCapabilities(voDesc.caps | DSCAPS_VIDEOONLY); + desc.caps = DFBSurfaceCapabilities(desc.caps | DSCAPS_VIDEOONLY); } - result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &voDesc, &newSurface); + result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface); if (result != DFB_OK #ifdef QT_NO_DEBUG - && (desc->flags & DSDESC_CAPS) && (desc->caps & DSCAPS_PRIMARY) + && (desc.flags & DSDESC_CAPS) && (desc.caps & DSCAPS_PRIMARY) #endif ) { qWarning("QDirectFBScreen::createDFBSurface() Failed to create surface in video memory!\n" " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s", - desc->flags, desc->caps, desc->width, desc->height, - desc->pixelformat, DFB_PIXELFORMAT_INDEX(desc->pixelformat), - desc->preallocated[0].data, desc->preallocated[0].pitch, + desc.flags, desc.caps, desc.width, desc.height, + desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat), + desc.preallocated[0].data, desc.preallocated[0].pitch, DirectFBErrorString(result)); } + desc.caps = DFBSurfaceCapabilities(desc.caps & ~DSCAPS_VIDEOONLY); } + if (d_ptr->directFBFlags & SystemOnly) + desc.caps = DFBSurfaceCapabilities(desc.caps | DSCAPS_SYSTEMONLY); if (!newSurface) - result = d_ptr->dfb->CreateSurface(d_ptr->dfb, desc, &newSurface); + result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface); if (result != DFB_OK) { qWarning("QDirectFBScreen::createDFBSurface() Failed!\n" " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s", - desc->flags, desc->caps, desc->width, desc->height, - desc->pixelformat, DFB_PIXELFORMAT_INDEX(desc->pixelformat), - desc->preallocated[0].data, desc->preallocated[0].pitch, + desc.flags, desc.caps, desc.width, desc.height, + desc.pixelformat, DFB_PIXELFORMAT_INDEX(desc.pixelformat), + desc.preallocated[0].data, desc.preallocated[0].pitch, DirectFBErrorString(result)); return 0; } @@ -345,23 +346,23 @@ void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface *surface) //qDebug("Released surface at %p. New count = %d", surface, d_ptr->allocatedSurfaces.count()); } -bool QDirectFBScreen::preferVideoOnly() const +QDirectFBScreen::DirectFBFlags QDirectFBScreen::directFBFlags() const { - return d_ptr->videoonly; + return d_ptr->directFBFlags; } -IDirectFB* QDirectFBScreen::dfb() +IDirectFB *QDirectFBScreen::dfb() { return d_ptr->dfb; } -IDirectFBSurface* QDirectFBScreen::dfbSurface() +IDirectFBSurface *QDirectFBScreen::dfbSurface() { return d_ptr->dfbSurface; } #ifndef QT_NO_DIRECTFB_LAYER -IDirectFBDisplayLayer* QDirectFBScreen::dfbDisplayLayer() +IDirectFBDisplayLayer *QDirectFBScreen::dfbDisplayLayer() { return d_ptr->dfbLayer; } @@ -539,16 +540,12 @@ class Q_GUI_EXPORT QDirectFBScreenCursor : public QScreenCursor { public: QDirectFBScreenCursor(); - ~QDirectFBScreenCursor(); - - void set(const QImage &image, int hotx, int hoty); - void move(int x, int y); - void show(); - void hide(); - + virtual void set(const QImage &image, int hotx, int hoty); + virtual void move(int x, int y); + virtual void show(); + virtual void hide(); private: IDirectFBDisplayLayer *layer; - bool implicitHide; }; QDirectFBScreenCursor::QDirectFBScreenCursor() @@ -558,116 +555,101 @@ QDirectFBScreenCursor::QDirectFBScreenCursor() qFatal("QDirectFBScreenCursor: DirectFB not initialized"); layer = QDirectFBScreen::instance()->dfbDisplayLayer(); + Q_ASSERT(layer); - if (layer) - layer->SetCooperativeLevel(layer, DLSCL_SHARED); // XXX: hw: remove? - else - qFatal("QDirectFBScreenCursor: Unable to get primary display layer!"); - - enable = true; + enable = false; hwaccel = true; - implicitHide = false; supportsAlpha = true; - - set(QImage(), 0, 0); -} - -QDirectFBScreenCursor::~QDirectFBScreenCursor() -{ } -void QDirectFBScreenCursor::show() +void QDirectFBScreenCursor::move(int x, int y) { - DFBResult result; - result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::show: " - "Unable to set cooperative level", result); - } - result = layer->EnableCursor(layer, 1); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::show: " - "Unable to enable cursor", result); - } - result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::show: " - "Unable to reset cooperative level", result); - } - implicitHide = false; + layer->WarpCursor(layer, x, y); } void QDirectFBScreenCursor::hide() { - DFBResult result; - result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::hide: " - "Unable to set cooperative level", result); - } - result = layer->EnableCursor(layer, 0); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::hide: " - "Unable to disable cursor", result); - } - result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::hide: " - "Unable to reset cooperative level", result); + if (enable) { + enable = false; + DFBResult result; + result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::hide: " + "Unable to set cooperative level", result); + } + result = layer->SetCursorOpacity(layer, 0); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::hide: " + "Unable to set cursor opacity", result); + } + result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::hide: " + "Unable to set cooperative level", result); + } } - implicitHide = true; } -void QDirectFBScreenCursor::move(int x, int y) +void QDirectFBScreenCursor::show() { - layer->WarpCursor(layer, x, y); + if (!enable) { + enable = true; + DFBResult result; + result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::show: " + "Unable to set cooperative level", result); + } + result = layer->SetCursorOpacity(layer, 255); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::show: " + "Unable to set cursor shape", result); + } + result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreenCursor::show: " + "Unable to set cooperative level", result); + } + } } void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty) { - if (image.isNull() && isVisible()) { - hide(); - implicitHide = true; - } else if (!image.isNull() && implicitHide) { - show(); - } - cursor = image.convertToFormat(QDirectFBScreen::instance()->alphaPixmapFormat()); + QDirectFBScreen *screen = QDirectFBScreen::instance(); + if (!screen) + return; - if (!image.isNull()) { - Q_ASSERT(cursor.numColors() == 0); + if (image.isNull()) { + cursor = QImage(); + hide(); + } else { + cursor = image.convertToFormat(screen->alphaPixmapFormat()); size = cursor.size(); hotspot = QPoint(hotx, hoty); - - DFBSurfaceDescription description; - description = QDirectFBScreen::getSurfaceDescription(cursor); - - IDirectFBSurface *surface; - surface = QDirectFBScreen::instance()->createDFBSurface(&description, - QDirectFBScreen::TrackSurface); + IDirectFBSurface *surface = screen->createDFBSurface(cursor, QDirectFBScreen::DontTrackSurface); if (!surface) { qWarning("QDirectFBScreenCursor::set: Unable to create surface"); return; } DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::set: " + DirectFBError("QDirectFBScreenCursor::show: " "Unable to set cooperative level", result); } result = layer->SetCursorShape(layer, surface, hotx, hoty); if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::set: Unable to set cursor shape", - result); + DirectFBError("QDirectFBScreenCursor::show: " + "Unable to set cursor shape", result); } - + surface->Release(surface); result = layer->SetCooperativeLevel(layer, DLSCL_SHARED); if (result != DFB_OK) { - DirectFBError("QDirectFBScreenCursor::set: " - "Unable to reset cooperative level", result); + DirectFBError("QDirectFBScreenCursor::show: " + "Unable to set cooperative level", result); } - - if (surface) - QDirectFBScreen::instance()->releaseDFBSurface(surface); + show(); } + } #endif // QT_NO_DIRECTFB_LAYER @@ -750,7 +732,7 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) } } -QPixmapData* QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType type) const +QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType type) const { if (type == QPixmapData::BitmapType) return QWSGraphicsSystem::createPixmapData(type); @@ -758,6 +740,84 @@ QPixmapData* QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType typ return new QDirectFBPixmapData(type); } +#ifdef QT_NO_DEBUG +struct FlagDescription; +static const FlagDescription *accelerationDescriptions = 0; +static const FlagDescription *blitDescriptions = 0; +static const FlagDescription *drawDescriptions = 0; +#else +struct FlagDescription { + const char *name; + uint flag; +}; + +static const FlagDescription accelerationDescriptions[] = { + { " DFXL_NONE ", DFXL_NONE }, + { " DFXL_FILLRECTANGLE", DFXL_FILLRECTANGLE }, + { " DFXL_DRAWRECTANGLE", DFXL_DRAWRECTANGLE }, + { " DFXL_DRAWLINE", DFXL_DRAWLINE }, + { " DFXL_FILLTRIANGLE", DFXL_FILLTRIANGLE }, + { " DFXL_BLIT", DFXL_BLIT }, + { " DFXL_STRETCHBLIT", DFXL_STRETCHBLIT }, + { " DFXL_TEXTRIANGLES", DFXL_TEXTRIANGLES }, + { " DFXL_DRAWSTRING", DFXL_DRAWSTRING }, + { 0, 0 } +}; + +static const FlagDescription blitDescriptions[] = { + { " DSBLIT_NOFX", DSBLIT_NOFX }, + { " DSBLIT_BLEND_ALPHACHANNEL", DSBLIT_BLEND_ALPHACHANNEL }, + { " DSBLIT_BLEND_COLORALPHA", DSBLIT_BLEND_COLORALPHA }, + { " DSBLIT_COLORIZE", DSBLIT_COLORIZE }, + { " DSBLIT_SRC_COLORKEY", DSBLIT_SRC_COLORKEY }, + { " DSBLIT_DST_COLORKEY", DSBLIT_DST_COLORKEY }, + { " DSBLIT_SRC_PREMULTIPLY", DSBLIT_SRC_PREMULTIPLY }, + { " DSBLIT_DST_PREMULTIPLY", DSBLIT_DST_PREMULTIPLY }, + { " DSBLIT_DEMULTIPLY", DSBLIT_DEMULTIPLY }, + { " DSBLIT_DEINTERLACE", DSBLIT_DEINTERLACE }, + { " DSBLIT_SRC_PREMULTCOLOR", DSBLIT_SRC_PREMULTCOLOR }, + { " DSBLIT_XOR", DSBLIT_XOR }, + { " DSBLIT_INDEX_TRANSLATION", DSBLIT_INDEX_TRANSLATION }, + { 0, 0 } +}; + +static const FlagDescription drawDescriptions[] = { + { " DSDRAW_NOFX", DSDRAW_NOFX }, + { " DSDRAW_BLEND", DSDRAW_BLEND }, + { " DSDRAW_DST_COLORKEY", DSDRAW_DST_COLORKEY }, + { " DSDRAW_SRC_PREMULTIPLY", DSDRAW_SRC_PREMULTIPLY }, + { " DSDRAW_DST_PREMULTIPLY", DSDRAW_DST_PREMULTIPLY }, + { " DSDRAW_DEMULTIPLY", DSDRAW_DEMULTIPLY }, + { " DSDRAW_XOR", DSDRAW_XOR }, + { 0, 0 } +}; +#endif + + + +static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags) +{ +#ifdef QT_NO_DEBUG + Q_UNUSED(mask); + Q_UNUSED(flags); + return QByteArray(""); +#else + if (!mask) + return flags[0].name; + + QStringList list; + for (int i=1; flags[i].name; ++i) { + if (mask & flags[i].flag) { + list.append(QString::fromLatin1(flags[i].name)); + } + } + Q_ASSERT(!list.isEmpty()); + return (QLatin1Char(' ') + list.join(QLatin1String("|"))).toLatin1(); +#endif +} + + + static void printDirectFBInfo(IDirectFB *fb) { DFBResult result; @@ -770,10 +830,13 @@ static void printDirectFBInfo(IDirectFB *fb) } qDebug("Device: %s (%s), Driver: %s v%i.%i (%s)\n" - " acceleration: 0x%x, blit: 0x%x, draw: 0x%0x video: %i\n", + "acceleration: 0x%x%s\nblit: 0x%x%s\ndraw: 0x%0x%s\nvideo: %iKB\n", dev.name, dev.vendor, dev.driver.name, dev.driver.major, dev.driver.minor, dev.driver.vendor, dev.acceleration_mask, - dev.blitting_flags, dev.drawing_flags, dev.video_memory); + ::flagDescriptions(dev.acceleration_mask, accelerationDescriptions).constData(), + dev.blitting_flags, ::flagDescriptions(dev.blitting_flags, blitDescriptions).constData(), + dev.drawing_flags, ::flagDescriptions(dev.drawing_flags, drawDescriptions).constData(), + (dev.video_memory >> 10)); } static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value) @@ -823,8 +886,29 @@ bool QDirectFBScreen::connect(const QString &displaySpec) if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive)) printDirectFBInfo(d_ptr->dfb); - if (displayArgs.contains(QLatin1String("videoonly"))) - d_ptr->videoonly = true; + if (displayArgs.contains(QLatin1String("videoonly"), Qt::CaseInsensitive)) + d_ptr->directFBFlags |= VideoOnly; + + if (displayArgs.contains(QLatin1String("systemonly"), Qt::CaseInsensitive)) { + if (d_ptr->directFBFlags & VideoOnly) { + qWarning("QDirectFBScreen: error. videoonly and systemonly are mutually exclusive"); + } else { + d_ptr->directFBFlags |= SystemOnly; + } + } + + if (displayArgs.contains(QLatin1String("boundingrectflip"), Qt::CaseInsensitive)) { + d_ptr->directFBFlags |= BoundingRectFlip; + } + +#ifdef QT_DIRECTFB_IMAGECACHE + int imageCacheSize = 4 * 1024 * 1024; // 4 MB + ::setIntOption(displayArgs, QLatin1String("imagecachesize"), &imageCacheSize); + QDirectFBPaintEngine::initImageCache(imageCacheSize); +#endif + + if (displayArgs.contains(QLatin1String("ignoresystemclip"), Qt::CaseInsensitive)) + d_ptr->directFBFlags |= IgnoreSystemClip; #ifndef QT_NO_DIRECTFB_WM if (displayArgs.contains(QLatin1String("fullscreen"))) @@ -837,9 +921,23 @@ bool QDirectFBScreen::connect(const QString &displaySpec) description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_WIDTH); if (::setIntOption(displayArgs, QLatin1String("height"), &description.height)) description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_HEIGHT); + uint caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE; - if (displayArgs.contains(QLatin1String("static_alloc"))) - caps |= DSCAPS_STATIC_ALLOC; + struct { + const char *name; + const DFBSurfaceCapabilities cap; + } const capabilities[] = { + { "static_alloc", DSCAPS_STATIC_ALLOC }, + { "triplebuffer", DSCAPS_TRIPLE }, + { "interlaced", DSCAPS_INTERLACED }, + { "separated", DSCAPS_SEPARATED }, +// { "depthbuffer", DSCAPS_DEPTH }, // only makes sense with TextureTriangles which are not supported + { 0, DSCAPS_NONE } + }; + for (int i=0; capabilities[i].name; ++i) { + if (displayArgs.contains(QString::fromLatin1(capabilities[i].name), Qt::CaseInsensitive)) + caps |= capabilities[i].cap; + } if (displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive)) { caps |= DSCAPS_PREMULTIPLIED; @@ -847,7 +945,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec) description.caps = DFBSurfaceCapabilities(caps); // We don't track the primary surface as it's released in disconnect - d_ptr->dfbSurface = createDFBSurface(&description, DontTrackSurface); + d_ptr->dfbSurface = createDFBSurface(description, DontTrackSurface); if (!d_ptr->dfbSurface) { DirectFBError("QDirectFBScreen: error creating primary surface", result); @@ -938,7 +1036,7 @@ void QDirectFBScreen::disconnect() d_ptr->dfbSurface->Release(d_ptr->dfbSurface); d_ptr->dfbSurface = 0; - foreach (IDirectFBSurface* surf, d_ptr->allocatedSurfaces) + foreach (IDirectFBSurface *surf, d_ptr->allocatedSurfaces) surf->Release(surf); d_ptr->allocatedSurfaces.clear(); @@ -1007,23 +1105,23 @@ void QDirectFBScreen::blank(bool on) (on ? DSPM_ON : DSPM_SUSPEND)); } -QWSWindowSurface* QDirectFBScreen::createSurface(QWidget *widget) const +QWSWindowSurface *QDirectFBScreen::createSurface(QWidget *widget) const { #ifdef QT_NO_DIRECTFB_WM if (QApplication::type() == QApplication::GuiServer) { - return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); + return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); } else { return QScreen::createSurface(widget); } #else - return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); + return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); #endif } -QWSWindowSurface* QDirectFBScreen::createSurface(const QString &key) const +QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const { if (key == QLatin1String("directfb")) { - return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); + return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); } return QScreen::createSurface(key); } @@ -1056,7 +1154,7 @@ void QDirectFBScreen::compose(const QRegion ®ion) const QPoint offset = win->requestedRegion().boundingRect().topLeft(); if (surface->key() == QLatin1String("directfb")) { - QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface); + QDirectFBWindowSurface *s = static_cast<QDirectFBWindowSurface*>(surface); blit(s->directFBSurface(), offset, r); } else { blit(surface->image(), offset, r); @@ -1105,7 +1203,7 @@ void QDirectFBScreen::compose(const QRegion ®ion) const QPoint offset = win->requestedRegion().boundingRect().topLeft(); if (surface->key() == QLatin1String("directfb")) { - QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface); + QDirectFBWindowSurface *s = static_cast<QDirectFBWindowSurface*>(surface); blit(s->directFBSurface(), offset, r); } else { blit(surface->image(), offset, r); @@ -1245,12 +1343,12 @@ bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *d return true; } -uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl) +uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, uint flags, int *bpl) { void *mem; - const DFBResult result = surface->Lock(surface, flags, static_cast<void**>(&mem), bpl); + const DFBResult result = surface->Lock(surface, static_cast<DFBSurfaceLockFlags>(flags), static_cast<void**>(&mem), bpl); if (result != DFB_OK) { - DirectFBError("QDirectFBPixmapData::lockSurface()", result); + DirectFBError("QDirectFBScreen::lockSurface()", result); } return reinterpret_cast<uchar*>(mem); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 8dd38dc..84199a2 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -59,6 +59,18 @@ public: QDirectFBScreen(int display_id); ~QDirectFBScreen(); + enum DirectFBFlag { + NoFlags = 0x00, + VideoOnly = 0x01, + SystemOnly = 0x02, + IgnoreSystemClip = 0x04, + BoundingRectFlip = 0x08 + }; + + Q_DECLARE_FLAGS(DirectFBFlags, DirectFBFlag); + + DirectFBFlags directFBFlags() const; + bool connect(const QString &displaySpec); void disconnect(); bool initDevice(); @@ -72,19 +84,19 @@ public: void setMode(int width, int height, int depth); void blank(bool on); - QWSWindowSurface* createSurface(QWidget *widget) const; - QWSWindowSurface* createSurface(const QString &key) const; + QWSWindowSurface *createSurface(QWidget *widget) const; + QWSWindowSurface *createSurface(const QString &key) const; - static inline QDirectFBScreen* instance() { + static inline QDirectFBScreen *instance() { QScreen *inst = QScreen::instance(); Q_ASSERT(!inst || inst->classId() == QScreen::DirectFBClass); return static_cast<QDirectFBScreen*>(inst); } - IDirectFB* dfb(); - IDirectFBSurface* dfbSurface(); + IDirectFB *dfb(); + IDirectFBSurface *dfbSurface(); #ifndef QT_NO_DIRECTFB_LAYER - IDirectFBDisplayLayer* dfbDisplayLayer(); + IDirectFBDisplayLayer *dfbDisplayLayer(); #endif // Track surface creation/release so we can release all on exit @@ -93,8 +105,6 @@ public: TrackSurface = 1 }; Q_DECLARE_FLAGS(SurfaceCreationOptions, SurfaceCreationOption); - IDirectFBSurface *createDFBSurface(const DFBSurfaceDescription *desc, - SurfaceCreationOptions options); IDirectFBSurface *createDFBSurface(const QImage &image, SurfaceCreationOptions options); IDirectFBSurface *createDFBSurface(const QSize &size, @@ -106,9 +116,7 @@ public: IDirectFBSurface *copyToDFBSurface(const QImage &image, QImage::Format format, SurfaceCreationOptions options); - void releaseDFBSurface(IDirectFBSurface* surface); - - bool preferVideoOnly() const; + void releaseDFBSurface(IDirectFBSurface *surface); static int depth(DFBSurfacePixelFormat format); @@ -120,6 +128,7 @@ public: static bool initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, QImage::Format format); static inline bool isPremultiplied(QImage::Format format); static inline bool hasAlpha(DFBSurfacePixelFormat format); + static inline bool hasAlpha(IDirectFBSurface *surface); QImage::Format alphaPixmapFormat() const; #ifndef QT_NO_DIRECTFB_PALETTE @@ -127,17 +136,21 @@ public: const QImage &image); #endif - static uchar *lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl = 0); + static uchar *lockSurface(IDirectFBSurface *surface, uint flags, int *bpl = 0); private: + IDirectFBSurface *createDFBSurface(DFBSurfaceDescription desc, + SurfaceCreationOptions options); void compose(const QRegion &r); void blit(IDirectFBSurface *src, const QPoint &topLeft, const QRegion ®ion); QDirectFBScreenPrivate *d_ptr; + friend class SurfaceCache; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDirectFBScreen::SurfaceCreationOptions); +Q_DECLARE_OPERATORS_FOR_FLAGS(QDirectFBScreen::DirectFBFlags); inline bool QDirectFBScreen::isPremultiplied(QImage::Format format) { @@ -175,6 +188,14 @@ inline bool QDirectFBScreen::hasAlpha(DFBSurfacePixelFormat format) } } +inline bool QDirectFBScreen::hasAlpha(IDirectFBSurface *surface) +{ + Q_ASSERT(surface); + DFBSurfacePixelFormat format; + surface->GetPixelFormat(surface, &format); + return QDirectFBScreen::hasAlpha(format); +} + QT_END_HEADER #endif // QDIRECTFBSCREEN_H diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 8ed308c..f1e3c84 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qdirectfbsurface.h" +#include "qdirectfbwindowsurface.h" #include "qdirectfbscreen.h" #include "qdirectfbpaintengine.h" @@ -50,13 +50,14 @@ //#define QT_DIRECTFB_DEBUG_SURFACES 1 -QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen* scr) +QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) : QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif , engine(0) , flipFlags(flip) + , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip) { setSurfaceFlags(Opaque | Buffered); #ifdef QT_DIRECTFB_TIMING @@ -65,13 +66,14 @@ QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen* sc #endif } -QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget) +QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget) : QWSWindowSurface(widget), QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif , engine(0) , flipFlags(flip) + , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip) { onscreen = widget->testAttribute(Qt::WA_PaintOnScreen); if (onscreen) @@ -84,17 +86,17 @@ QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *sc #endif } -QDirectFBSurface::~QDirectFBSurface() +QDirectFBWindowSurface::~QDirectFBWindowSurface() { } -bool QDirectFBSurface::isValid() const +bool QDirectFBWindowSurface::isValid() const { return true; } #ifndef QT_NO_DIRECTFB_WM -void QDirectFBSurface::createWindow() +void QDirectFBWindowSurface::createWindow() { #ifdef QT_NO_DIRECTFB_LAYER #warning QT_NO_DIRECTFB_LAYER requires QT_NO_DIRECTFB_WM @@ -110,7 +112,7 @@ void QDirectFBSurface::createWindow() |DWDESC_PIXELFORMAT); description.surface_caps = DSCAPS_NONE; - if (screen->preferVideoOnly()) + if (screen->directFBFlags() & QDirectFBScreen::VideoOnly) description.surface_caps = DFBSurfaceCapabilities(description.surface_caps|DSCAPS_VIDEOONLY); const QImage::Format format = screen->pixelFormat(); description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); @@ -130,7 +132,7 @@ void QDirectFBSurface::createWindow() } #endif // QT_NO_DIRECTFB_WM -void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) +void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) { if (rect.isNull()) { #ifndef QT_NO_DIRECTFB_WM @@ -184,7 +186,7 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) description.height = rect.height(); QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, screen->pixelFormat()); - dfbSurface = screen->createDFBSurface(&description, false); + dfbSurface = screen->createDFBSurface(description, false); forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); } else { Q_ASSERT(dfbSurface); @@ -209,13 +211,13 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) } if (result != DFB_OK) - DirectFBErrorFatal("QDirectFBSurface::setGeometry()", result); + DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result); } QWSWindowSurface::setGeometry(rect, mask); } -QByteArray QDirectFBSurface::permanentState() const +QByteArray QDirectFBWindowSurface::permanentState() const { QByteArray array; #ifdef QT_NO_DIRECTFB_WM @@ -234,7 +236,7 @@ QByteArray QDirectFBSurface::permanentState() const return array; } -void QDirectFBSurface::setPermanentState(const QByteArray &state) +void QDirectFBWindowSurface::setPermanentState(const QByteArray &state) { SurfaceFlags flags; const char *ptr = state.constData(); @@ -248,7 +250,7 @@ void QDirectFBSurface::setPermanentState(const QByteArray &state) #endif } -bool QDirectFBSurface::scroll(const QRegion ®ion, int dx, int dy) +bool QDirectFBWindowSurface::scroll(const QRegion ®ion, int dx, int dy) { if (!dfbSurface || !(flipFlags & DSFLIP_BLIT)) return false; @@ -276,7 +278,7 @@ bool QDirectFBSurface::scroll(const QRegion ®ion, int dx, int dy) return true; } -bool QDirectFBSurface::move(const QPoint &offset) +bool QDirectFBWindowSurface::move(const QPoint &offset) { QWSWindowSurface::move(offset); @@ -291,7 +293,7 @@ bool QDirectFBSurface::move(const QPoint &offset) #endif } -QRegion QDirectFBSurface::move(const QPoint &offset, const QRegion &newClip) +QRegion QDirectFBWindowSurface::move(const QPoint &offset, const QRegion &newClip) { #ifdef QT_NO_DIRECTFB_WM return QWSWindowSurface::move(offset, newClip); @@ -304,10 +306,10 @@ QRegion QDirectFBSurface::move(const QPoint &offset, const QRegion &newClip) #endif } -QPaintEngine* QDirectFBSurface::paintEngine() const +QPaintEngine* QDirectFBWindowSurface::paintEngine() const { if (!engine) { - QDirectFBSurface *that = const_cast<QDirectFBSurface*>(this); + QDirectFBWindowSurface *that = const_cast<QDirectFBWindowSurface*>(this); that->engine = new QDirectFBPaintEngine(that); return that->engine; } @@ -337,7 +339,7 @@ inline bool isWidgetOpaque(const QWidget *w) return false; } -void QDirectFBSurface::flush(QWidget *widget, const QRegion ®ion, +void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(widget); @@ -369,20 +371,15 @@ void QDirectFBSurface::flush(QWidget *widget, const QRegion ®ion, if (!(flipFlags & DSFLIP_BLIT)) { dfbSurface->Flip(dfbSurface, 0, flipFlags); } else { - if (region.numRects() > 1) { + if (!boundingRectFlip && region.numRects() > 1) { const QVector<QRect> rects = region.rects(); - DFBSurfaceFlipFlags tmpFlags = flipFlags; - if (flipFlags & DSFLIP_WAIT) - tmpFlags = DFBSurfaceFlipFlags(flipFlags & ~DSFLIP_WAIT); + const DFBSurfaceFlipFlags nonWaitFlags = DFBSurfaceFlipFlags(flipFlags & ~DSFLIP_WAIT); for (int i=0; i<rects.size(); ++i) { const QRect &r = rects.at(i); const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), r.x() + r.width() + offset.x(), r.y() + r.height() + offset.y() }; - dfbSurface->Flip(dfbSurface, &dfbReg, - i + 1 < rects.size() - ? tmpFlags - : flipFlags); + dfbSurface->Flip(dfbSurface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags); } } else { const QRect r = region.boundingRect(); @@ -405,15 +402,15 @@ void QDirectFBSurface::flush(QWidget *widget, const QRegion ®ion, } -void QDirectFBSurface::beginPaint(const QRegion &) +void QDirectFBWindowSurface::beginPaint(const QRegion &) { } -void QDirectFBSurface::endPaint(const QRegion &) +void QDirectFBWindowSurface::endPaint(const QRegion &) { #ifdef QT_DIRECTFB_DEBUG_SURFACES if (bufferImages.count()) { - qDebug("QDirectFBSurface::endPaint() this=%p", this); + qDebug("QDirectFBWindowSurface::endPaint() this=%p", this); foreach(QImage* bufferImg, bufferImages) qDebug(" Deleting buffer image %p", bufferImg); @@ -426,7 +423,7 @@ void QDirectFBSurface::endPaint(const QRegion &) } -QImage* QDirectFBSurface::buffer(const QWidget *widget) +QImage *QDirectFBWindowSurface::buffer(const QWidget *widget) { if (!lockedImage) return 0; @@ -444,7 +441,7 @@ QImage* QDirectFBSurface::buffer(const QWidget *widget) bufferImages.append(img); #ifdef QT_DIRECTFB_DEBUG_SURFACES - qDebug("QDirectFBSurface::buffer() Created & returned %p", img); + qDebug("QDirectFBWindowSurface::buffer() Created & returned %p", img); #endif return img; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index ab4145d..75998c4 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -58,12 +58,12 @@ QT_BEGIN_HEADER QT_MODULE(Gui) -class QDirectFBSurface: public QWSWindowSurface, public QDirectFBPaintDevice +class QDirectFBWindowSurface : public QWSWindowSurface, public QDirectFBPaintDevice { public: - QDirectFBSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr); - QDirectFBSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr, QWidget *widget); - ~QDirectFBSurface(); + QDirectFBWindowSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr); + QDirectFBWindowSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr, QWidget *widget); + ~QDirectFBWindowSurface(); bool isValid() const; @@ -79,15 +79,15 @@ public: QRegion move(const QPoint &offset, const QRegion &newClip); QImage image() const { return QImage(); } - QPaintDevice* paintDevice() { return this; } - QPaintEngine* paintEngine() const; + QPaintDevice *paintDevice() { return this; } + QPaintEngine *paintEngine() const; void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); void beginPaint(const QRegion &); void endPaint(const QRegion &); - QImage* buffer(const QWidget *widget); + QImage *buffer(const QWidget *widget); private: #ifndef QT_NO_DIRECTFB_WM @@ -100,6 +100,7 @@ private: QList<QImage*> bufferImages; DFBSurfaceFlipFlags flipFlags; + bool boundingRectFlip; #ifdef QT_DIRECTFB_TIMING int frames; QTime timer; diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro b/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro index b62894d..9331d0a 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro @@ -22,3 +22,5 @@ LIBS += -lpvr2d DESTDIR = $$QMAKE_LIBDIR_QT target.path = $$[QT_INSTALL_LIBS] INSTALLS += target + +include(../powervr.pri)
\ No newline at end of file diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c index 5c37253..4771d14 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable.c @@ -72,7 +72,7 @@ static int pvrQwsInitFbScreen(int screen) /* Bail out if already initialized, or the number is incorrect */ if (screen < 0 || screen >= PVRQWS_MAX_SCREENS) return 0; - if (pvrQwsDisplay.screens[screen].mapped) + if (pvrQwsDisplay.screens[screen].initialized) return 1; /* Open the framebuffer and fetch its properties */ @@ -125,26 +125,33 @@ static int pvrQwsInitFbScreen(int screen) start = fix.smem_start; length = var.xres_virtual * var.yres_virtual * bytesPerPixel; - /* Map the framebuffer region into memory */ - mapped = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (!mapped || mapped == (void *)(-1)) { - perror("mmap"); - close(fd); - return 0; - } - - /* Allocate a PVR2D memory region for the framebuffer */ - memInfo = 0; - if (pvrQwsDisplay.context) { - pageAddresses[0] = start & 0xFFFFF000; - pageAddresses[1] = 0; - if (PVR2DMemWrap - (pvrQwsDisplay.context, mapped, PVR2D_WRAPFLAG_CONTIGUOUS, - length, pageAddresses, &memInfo) != PVR2D_OK) { - munmap(mapped, length); + if (screen == 0) { + /* We use PVR2DGetFrameBuffer to map the first screen. + On some chipsets it is more reliable than using PVR2DMemWrap */ + mapped = 0; + memInfo = 0; + } else { + /* Other screens: map the framebuffer region into memory */ + mapped = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (!mapped || mapped == (void *)(-1)) { + perror("mmap"); close(fd); return 0; } + + /* Allocate a PVR2D memory region for the framebuffer */ + memInfo = 0; + if (pvrQwsDisplay.context) { + pageAddresses[0] = start & 0xFFFFF000; + pageAddresses[1] = 0; + if (PVR2DMemWrap + (pvrQwsDisplay.context, mapped, PVR2D_WRAPFLAG_CONTIGUOUS, + length, pageAddresses, &memInfo) != PVR2D_OK) { + munmap(mapped, length); + close(fd); + return 0; + } + } } /* We don't need the file descriptor any more */ @@ -158,11 +165,17 @@ static int pvrQwsInitFbScreen(int screen) pvrQwsDisplay.screens[screen].screenStride = stride; pvrQwsDisplay.screens[screen].pixelFormat = format; pvrQwsDisplay.screens[screen].bytesPerPixel = bytesPerPixel; - pvrQwsDisplay.screens[screen].frameBuffer = memInfo; pvrQwsDisplay.screens[screen].screenDrawable = 0; - pvrQwsDisplay.screens[screen].mapped = mapped; + if (mapped) { + /* Don't set these fields if mapped is 0, because PVR2DGetFrameBuffer + may have already been called and set them */ + pvrQwsDisplay.screens[screen].frameBuffer = memInfo; + pvrQwsDisplay.screens[screen].mapped = mapped; + } pvrQwsDisplay.screens[screen].mappedLength = length; pvrQwsDisplay.screens[screen].screenStart = start; + pvrQwsDisplay.screens[screen].needsUnmap = (mapped != 0); + pvrQwsDisplay.screens[screen].initialized = 1; return 1; } @@ -209,7 +222,7 @@ static int pvrQwsAddDrawable(void) /* Create the PVR2DMEMINFO blocks for the active framebuffers */ for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) { - if (pvrQwsDisplay.screens[screen].mapped) { + if (screen != 0 && pvrQwsDisplay.screens[screen].mapped) { pageAddresses[0] = pvrQwsDisplay.screens[screen].screenStart & 0xFFFFF000; pageAddresses[1] = 0; @@ -224,6 +237,17 @@ static int pvrQwsAddDrawable(void) return 0; } pvrQwsDisplay.screens[screen].frameBuffer = memInfo; + } else if (screen == 0) { + if (PVR2DGetFrameBuffer + (pvrQwsDisplay.context, + PVR2D_FB_PRIMARY_SURFACE, &memInfo) != PVR2D_OK) { + fprintf(stderr, "QWSWSEGL: could not get the primary framebuffer surface\n"); + PVR2DDestroyDeviceContext(pvrQwsDisplay.context); + pvrQwsDisplay.context = 0; + return 0; + } + pvrQwsDisplay.screens[screen].frameBuffer = memInfo; + pvrQwsDisplay.screens[screen].mapped = memInfo->pBase; } } @@ -330,7 +354,7 @@ void pvrQwsDisplayClose(void) pvrQwsDestroyDrawableForced(info->screenDrawable); if (info->frameBuffer) PVR2DMemFree(pvrQwsDisplay.context, info->frameBuffer); - if (info->mapped) + if (info->mapped && info->needsUnmap) munmap(info->mapped, info->mappedLength); } diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h index d6c42a6..4f3ea90 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/pvrqwsdrawable_p.h @@ -76,6 +76,8 @@ typedef struct { void *mapped; int mappedLength; unsigned long screenStart; + int needsUnmap; + int initialized; } PvrQwsScreenInfo; diff --git a/src/plugins/gfxdrivers/powervr/README b/src/plugins/gfxdrivers/powervr/README index ec02efb..4dce87f 100644 --- a/src/plugins/gfxdrivers/powervr/README +++ b/src/plugins/gfxdrivers/powervr/README @@ -29,12 +29,13 @@ strictly Unix-style markers. *************************************************************************** * IMPORTANT: To build the QScreen plugin and the WSEGL library it depends * -* on, the pvr2d.h, wsegl.h headers for your platform are required. These * -* can be obtained either through your platform provider or directly from * -* Imagination Technologies. * +* on, the pvr2d.h, wsegl.h headers for your platform are required. You * +* can find a copy of these headers in src/3rdparty/powervr for SGX based * +* platforms like the TI OMAP3xxx. They may also work on MBX platforms too * +* depending on how old your libEGL is. You can tell Qt where to find * +* these headers by setting QMAKE_INCDIR_POWERVR in the mkspec. * *************************************************************************** - When you start a Qt/Embedded application, you should modify the QWS_DISPLAY environment variable to use the "powervr" driver instead of "LinuxFb". For example, if your original QWS_DISPLAY variable was: diff --git a/src/plugins/gfxdrivers/powervr/powervr.pri b/src/plugins/gfxdrivers/powervr/powervr.pri new file mode 100644 index 0000000..9df8c0e --- /dev/null +++ b/src/plugins/gfxdrivers/powervr/powervr.pri @@ -0,0 +1,2 @@ + +INCLUDEPATH += $$QMAKE_INCDIR_POWERVR diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro index 691cd2d..675be85 100644 --- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro +++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro @@ -9,9 +9,10 @@ DEFINES += QT_QWS_CLIENTBLIT INCLUDEPATH += ../QWSWSEGL + HEADERS = \ - pvreglscreen.h \ - pvreglwindowsurface.h + pvreglscreen.h \ + pvreglwindowsurface.h SOURCES = \ pvreglscreenplugin.cpp \ @@ -22,3 +23,5 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers INSTALLS += target + +include(../powervr.pri)
\ No newline at end of file diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index 0705722..9eeb41d 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -1270,27 +1270,27 @@ QSqlRecord QIBaseResult::record() const v = d->sqlda->sqlvar[i]; QSqlField f(QString::fromLatin1(v.aliasname, v.aliasname_length).simplified(), qIBaseTypeName2(v.sqltype, v.sqlscale < 0)); - QSqlQuery q(new QIBaseResult(d->db)); - q.setForwardOnly(true); - q.exec(QLatin1String("select b.RDB$FIELD_PRECISION, b.RDB$FIELD_SCALE, b.RDB$FIELD_LENGTH, a.RDB$NULL_FLAG " - "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " - "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " - "AND a.RDB$RELATION_NAME = '") + QString::fromAscii(v.relname, v.relname_length).toUpper() + QLatin1String("' " - "AND a.RDB$FIELD_NAME = '") + QString::fromAscii(v.sqlname, v.sqlname_length).toUpper() + QLatin1String("' ")); - if(q.first()) { - if(v.sqlscale < 0) { - f.setLength(q.value(0).toInt()); - f.setPrecision(qAbs(q.value(1).toInt())); - } else { - f.setLength(q.value(2).toInt()); - f.setPrecision(0); + f.setLength(v.sqllen); + f.setPrecision(qAbs(v.sqlscale)); + f.setRequiredStatus((v.sqltype & 1) == 0 ? QSqlField::Required : QSqlField::Optional); + if(v.sqlscale < 0) { + QSqlQuery q(new QIBaseResult(d->db)); + q.setForwardOnly(true); + q.exec(QLatin1String("select b.RDB$FIELD_PRECISION, b.RDB$FIELD_SCALE, b.RDB$FIELD_LENGTH, a.RDB$NULL_FLAG " + "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " + "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " + "AND a.RDB$RELATION_NAME = '") + QString::fromAscii(v.relname, v.relname_length).toUpper() + QLatin1String("' " + "AND a.RDB$FIELD_NAME = '") + QString::fromAscii(v.sqlname, v.sqlname_length).toUpper() + QLatin1String("' ")); + if(q.first()) { + if(v.sqlscale < 0) { + f.setLength(q.value(0).toInt()); + f.setPrecision(qAbs(q.value(1).toInt())); + } else { + f.setLength(q.value(2).toInt()); + f.setPrecision(0); + } + f.setRequiredStatus(q.value(3).toBool() ? QSqlField::Required : QSqlField::Optional); } - f.setRequiredStatus(q.value(3).toBool() ? QSqlField::Required : QSqlField::Optional); - } - else { - f.setLength(0); - f.setPrecision(0); - f.setRequiredStatus(QSqlField::Unknown); } f.setSqlType(v.sqltype); rec.append(f); diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index a84e840..1f54db7 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -224,7 +224,7 @@ static QTextCodec* codec(MYSQL* mysql) static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, const QMYSQLDriverPrivate* p) { - const char *cerr = mysql_error(p->mysql); + const char *cerr = p->mysql ? mysql_error(p->mysql) : 0; return QSqlError(QLatin1String("QMYSQL: ") + err, p->tc ? toUnicode(p->tc, cerr) : QString::fromLatin1(cerr), type, mysql_errno(p->mysql)); diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 2a83fe6..9932463 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -70,18 +70,15 @@ QT_BEGIN_NAMESPACE #endif // newer platform SDKs use SQLLEN instead of SQLINTEGER -#if defined(SQLLEN) || defined(Q_OS_WIN64) -# define QSQLLEN SQLLEN -#else +#if defined(WIN32) && (_MSC_VER < 1300) # define QSQLLEN SQLINTEGER -#endif - -#if defined(SQLULEN) || defined(Q_OS_WIN64) -# define QSQLULEN SQLULEN -#else # define QSQLULEN SQLUINTEGER +#else +# define QSQLLEN SQLLEN +# define QSQLULEN SQLULEN #endif + static const int COLNAMESIZE = 256; //Map Qt parameter types to ODBC types static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT }; diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index 3d702dd..47566ad 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -1650,19 +1650,19 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i) if (i->hasElementNormalOff()) m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Normal, QIcon::Off);\n"; if (i->hasElementNormalOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Normal, QIcon::On);\n"; + m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOn()->text(), m_dindent) << "), QSize(), QIcon::Normal, QIcon::On);\n"; if (i->hasElementDisabledOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::Off);\n"; + m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOff()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::Off);\n"; if (i->hasElementDisabledOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::On);\n"; + m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementDisabledOn()->text(), m_dindent) << "), QSize(), QIcon::Disabled, QIcon::On);\n"; if (i->hasElementActiveOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::Off);\n"; + m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOff()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::Off);\n"; if (i->hasElementActiveOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::On);\n"; + m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementActiveOn()->text(), m_dindent) << "), QSize(), QIcon::Active, QIcon::On);\n"; if (i->hasElementSelectedOff()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::Off);\n"; + m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOff()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::Off);\n"; if (i->hasElementSelectedOn()) - m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementNormalOff()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::On);\n"; + m_output << m_indent << iconName << ".addFile(QString::fromUtf8(" << fixString(i->elementSelectedOn()->text(), m_dindent) << "), QSize(), QIcon::Selected, QIcon::On);\n"; } else { // pre-4.4 legacy m_output << m_indent << "const QIcon " << iconName << " = " << pixCall(QLatin1String("QIcon"), i->text())<< ";\n"; } |