winex11: Make the BitBlt short-cuts more generic to apply to all possible ROPs.

This commit is contained in:
Alexandre Julliard 2008-02-21 20:15:41 +01:00
parent 997e5f1230
commit 23afe2e94c
1 changed files with 95 additions and 132 deletions

View File

@ -317,7 +317,7 @@ static const unsigned char BITBLT_Opcodes[256][MAX_OP_LEN] =
OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */ OP(PAT,DST,GXequiv) }, /* 0xa7 ~P^(D&(S|P)) */
{ OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */ { OP(PAT,SRC,GXor), OP(SRC,DST,GXand) }, /* 0xa8 D&(P|S) */
{ OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */ { OP(PAT,SRC,GXor), OP(SRC,DST,GXequiv) }, /* 0xa9 ~D^(P|S) */
{ OP(SRC,DST,GXnoop) }, /* 0xaa D */ { OP(PAT,DST,GXnoop) }, /* 0xaa D */
{ OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */ { OP(PAT,SRC,GXnor), OP(SRC,DST,GXor) }, /* 0xab D|~(P|S) */
{ OP(SRC,DST,GXxor), OP(PAT,DST,GXand), { OP(SRC,DST,GXxor), OP(PAT,DST,GXand),
OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */ OP(SRC,DST,GXxor) }, /* 0xac S^(P&(D^S)) */
@ -1320,143 +1320,106 @@ static BOOL BITBLT_InternalStretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT
width = visRectDst.right - visRectDst.left; width = visRectDst.right - visRectDst.left;
height = visRectDst.bottom - visRectDst.top; height = visRectDst.bottom - visRectDst.top;
if (!fStretch) switch(rop) /* A few optimisations */ opcode = BITBLT_Opcodes[(rop >> 16) & 0xff];
/* a few optimisations for single-op rops */
if (!fStretch && !opcode[1])
{ {
case BLACKNESS: /* 0x00 */ if (OP_SRCDST(*opcode) == OP_ARGS(PAT,DST))
wine_tsx11_lock();
if ((physDevDst->depth == 1) || !X11DRV_PALETTE_PaletteToXPixel)
XSetFunction( gdi_display, physDevDst->gc, GXclear );
else
{ {
XSetFunction( gdi_display, physDevDst->gc, GXcopy ); switch(rop) /* a few special cases */
XSetForeground( gdi_display, physDevDst->gc, X11DRV_PALETTE_PaletteToXPixel[0] ); {
XSetFillStyle( gdi_display, physDevDst->gc, FillSolid ); case BLACKNESS: /* 0x00 */
} case WHITENESS: /* 0xff */
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc, if ((physDevDst->depth != 1) && X11DRV_PALETTE_PaletteToXPixel)
physDevDst->dc_rect.left + visRectDst.left, {
physDevDst->dc_rect.top + visRectDst.top, wine_tsx11_lock();
width, height ); XSetFunction( gdi_display, physDevDst->gc, GXcopy );
wine_tsx11_unlock(); if (rop == BLACKNESS)
return TRUE; XSetForeground( gdi_display, physDevDst->gc, X11DRV_PALETTE_PaletteToXPixel[0] );
else
case DSTINVERT: /* 0x55 */ XSetForeground( gdi_display, physDevDst->gc,
wine_tsx11_lock(); WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
XSetFunction( gdi_display, physDevDst->gc, GXinvert ); XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
if( X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL) ) physDevDst->dc_rect.left + visRectDst.left,
XSetFunction( gdi_display, physDevDst->gc, GXinvert); physDevDst->dc_rect.top + visRectDst.top,
else width, height );
{ wine_tsx11_unlock();
/* Xor is much better when we do not have full colormap. */ return TRUE;
/* Using white^black ensures that we invert at least black */ }
/* and white. */ break;
unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^ case DSTINVERT: /* 0x55 */
BlackPixel( gdi_display, DefaultScreen(gdi_display) )); if (!(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_PRIVATE | X11DRV_PALETTE_VIRTUAL)))
XSetFunction( gdi_display, physDevDst->gc, GXxor ); {
XSetForeground( gdi_display, physDevDst->gc, xor_pix); /* Xor is much better when we do not have full colormap. */
XSetFillStyle( gdi_display, physDevDst->gc, FillSolid ); /* Using white^black ensures that we invert at least black */
} /* and white. */
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc, unsigned long xor_pix = (WhitePixel( gdi_display, DefaultScreen(gdi_display) ) ^
physDevDst->dc_rect.left + visRectDst.left, BlackPixel( gdi_display, DefaultScreen(gdi_display) ));
physDevDst->dc_rect.top + visRectDst.top, wine_tsx11_lock();
width, height ); XSetFunction( gdi_display, physDevDst->gc, GXxor );
wine_tsx11_unlock(); XSetForeground( gdi_display, physDevDst->gc, xor_pix);
return TRUE; XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
case PATINVERT: /* 0x5a */ physDevDst->dc_rect.left + visRectDst.left,
if (X11DRV_SetupGCForBrush( physDevDst )) physDevDst->dc_rect.top + visRectDst.top,
{ width, height );
wine_tsx11_lock(); wine_tsx11_unlock();
XSetFunction( gdi_display, physDevDst->gc, GXxor ); return TRUE;
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc, }
physDevDst->dc_rect.left + visRectDst.left, break;
physDevDst->dc_rect.top + visRectDst.top, }
width, height ); if (!usePat || X11DRV_SetupGCForBrush( physDevDst ))
wine_tsx11_unlock(); {
} wine_tsx11_lock();
return TRUE; XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
case 0xa50065: physDevDst->dc_rect.left + visRectDst.left,
if (X11DRV_SetupGCForBrush( physDevDst )) physDevDst->dc_rect.top + visRectDst.top,
{ width, height );
wine_tsx11_lock(); wine_tsx11_unlock();
XSetFunction( gdi_display, physDevDst->gc, GXequiv ); }
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
physDevDst->dc_rect.left + visRectDst.left,
physDevDst->dc_rect.top + visRectDst.top,
width, height );
wine_tsx11_unlock();
}
return TRUE;
case SRCCOPY: /* 0xcc */
case SRCINVERT:
if (physDevSrc->depth == physDevDst->depth)
{
wine_tsx11_lock();
XSetFunction( gdi_display, physDevDst->gc, rop == SRCCOPY ? GXcopy : GXxor );
XCopyArea( gdi_display, physDevSrc->drawable,
physDevDst->drawable, physDevDst->gc,
physDevSrc->dc_rect.left + visRectSrc.left,
physDevSrc->dc_rect.top + visRectSrc.top,
width, height,
physDevDst->dc_rect.left + visRectDst.left,
physDevDst->dc_rect.top + visRectDst.top );
physDevDst->exposures++;
wine_tsx11_unlock();
return TRUE; return TRUE;
} }
else if (OP_SRCDST(*opcode) == OP_ARGS(SRC,DST))
if (physDevSrc->depth == 1)
{ {
int fg, bg; if (physDevSrc->depth == physDevDst->depth)
get_colors(physDevDst, physDevSrc, &fg, &bg); {
wine_tsx11_lock(); wine_tsx11_lock();
XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
XCopyArea( gdi_display, physDevSrc->drawable,
physDevDst->drawable, physDevDst->gc,
physDevSrc->dc_rect.left + visRectSrc.left,
physDevSrc->dc_rect.top + visRectSrc.top,
width, height,
physDevDst->dc_rect.left + visRectDst.left,
physDevDst->dc_rect.top + visRectDst.top );
physDevDst->exposures++;
wine_tsx11_unlock();
return TRUE;
}
if (physDevSrc->depth == 1)
{
int fg, bg;
get_colors(physDevDst, physDevSrc, &fg, &bg);
wine_tsx11_lock();
XSetBackground( gdi_display, physDevDst->gc, fg ); XSetBackground( gdi_display, physDevDst->gc, fg );
XSetForeground( gdi_display, physDevDst->gc, bg ); XSetForeground( gdi_display, physDevDst->gc, bg );
XSetFunction( gdi_display, physDevDst->gc, rop == SRCCOPY ? GXcopy : GXxor ); XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
XCopyPlane( gdi_display, physDevSrc->drawable, XCopyPlane( gdi_display, physDevSrc->drawable,
physDevDst->drawable, physDevDst->gc, physDevDst->drawable, physDevDst->gc,
physDevSrc->dc_rect.left + visRectSrc.left, physDevSrc->dc_rect.left + visRectSrc.left,
physDevSrc->dc_rect.top + visRectSrc.top, physDevSrc->dc_rect.top + visRectSrc.top,
width, height, width, height,
physDevDst->dc_rect.left + visRectDst.left, physDevDst->dc_rect.left + visRectDst.left,
physDevDst->dc_rect.top + visRectDst.top, 1 ); physDevDst->dc_rect.top + visRectDst.top, 1 );
physDevDst->exposures++; physDevDst->exposures++;
wine_tsx11_unlock(); wine_tsx11_unlock();
return TRUE; return TRUE;
}
} }
break;
case PATCOPY: /* 0xf0 */
if (!X11DRV_SetupGCForBrush( physDevDst )) return TRUE;
wine_tsx11_lock();
XSetFunction( gdi_display, physDevDst->gc, GXcopy );
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
physDevDst->dc_rect.left + visRectDst.left,
physDevDst->dc_rect.top + visRectDst.top,
width, height );
wine_tsx11_unlock();
return TRUE;
case WHITENESS: /* 0xff */
wine_tsx11_lock();
if ((physDevDst->depth == 1) || !X11DRV_PALETTE_PaletteToXPixel)
XSetFunction( gdi_display, physDevDst->gc, GXset );
else
{
XSetFunction( gdi_display, physDevDst->gc, GXcopy );
XSetForeground( gdi_display, physDevDst->gc,
WhitePixel( gdi_display, DefaultScreen(gdi_display) ));
XSetFillStyle( gdi_display, physDevDst->gc, FillSolid );
}
XFillRectangle( gdi_display, physDevDst->drawable, physDevDst->gc,
physDevDst->dc_rect.left + visRectDst.left,
physDevDst->dc_rect.top + visRectDst.top,
width, height );
wine_tsx11_unlock();
return TRUE;
} }
wine_tsx11_lock(); wine_tsx11_lock();
@ -1489,7 +1452,7 @@ static BOOL BITBLT_InternalStretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT
destUsed = FALSE; destUsed = FALSE;
wine_tsx11_lock(); wine_tsx11_lock();
for (opcode = BITBLT_Opcodes[(rop >> 16) & 0xff]; *opcode; opcode++) for ( ; *opcode; opcode++)
{ {
if (OP_DST(*opcode) == DST) destUsed = TRUE; if (OP_DST(*opcode) == DST) destUsed = TRUE;
XSetFunction( gdi_display, tmpGC, OP_ROP(*opcode) ); XSetFunction( gdi_display, tmpGC, OP_ROP(*opcode) );