Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
46e2d795
Commit
46e2d795
authored
Sep 17, 2007
by
Stefan Dösinger
Committed by
Alexandre Julliard
Sep 18, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wined3d: Move the software blitting to the base surface class.
parent
09b7d3bb
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
963 additions
and
961 deletions
+963
-961
surface.c
dlls/wined3d/surface.c
+2
-2
surface_base.c
dlls/wined3d/surface_base.c
+957
-0
surface_gdi.c
dlls/wined3d/surface_gdi.c
+2
-957
wined3d_private.h
dlls/wined3d/wined3d_private.h
+2
-2
No files found.
dlls/wined3d/surface.c
View file @
46e2d795
...
...
@@ -3300,7 +3300,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *Dest
* For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
* other Blts are rather rare
*/
return
IWine
GDI
SurfaceImpl_Blt
(
iface
,
DestRect
,
SrcSurface
,
SrcRect
,
Flags
,
DDBltFx
,
Filter
);
return
IWine
D3DBase
SurfaceImpl_Blt
(
iface
,
DestRect
,
SrcSurface
,
SrcRect
,
Flags
,
DDBltFx
,
Filter
);
}
HRESULT
WINAPI
IWineD3DSurfaceImpl_BltFast
(
IWineD3DSurface
*
iface
,
DWORD
dstx
,
DWORD
dsty
,
IWineD3DSurface
*
Source
,
RECT
*
rsrc
,
DWORD
trans
)
{
...
...
@@ -3354,7 +3354,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, D
}
return
IWine
GDI
SurfaceImpl_BltFast
(
iface
,
dstx
,
dsty
,
Source
,
rsrc
,
trans
);
return
IWine
D3DBase
SurfaceImpl_BltFast
(
iface
,
dstx
,
dsty
,
Source
,
rsrc
,
trans
);
}
static
HRESULT
WINAPI
IWineD3DSurfaceImpl_PrivateSetup
(
IWineD3DSurface
*
iface
)
{
...
...
dlls/wined3d/surface_base.c
View file @
46e2d795
...
...
@@ -30,6 +30,8 @@
#include "wine/port.h"
#include "wined3d_private.h"
#include <assert.h>
WINE_DEFAULT_DEBUG_CHANNEL
(
d3d_surface
);
/* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */
...
...
@@ -611,3 +613,958 @@ HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) {
return
WINED3D_OK
;
}
/*****************************************************************************
* _Blt_ColorFill
*
* Helper function that fills a memory area with a specific color
*
* Params:
* buf: memory address to start filling at
* width, height: Dimensions of the area to fill
* bpp: Bit depth of the surface
* lPitch: pitch of the surface
* color: Color to fill with
*
*****************************************************************************/
static
HRESULT
_Blt_ColorFill
(
BYTE
*
buf
,
int
width
,
int
height
,
int
bpp
,
LONG
lPitch
,
DWORD
color
)
{
int
x
,
y
;
LPBYTE
first
;
/* Do first row */
#define COLORFILL_ROW(type) \
{ \
type *d = (type *) buf; \
for (x = 0; x < width; x++) \
d[x] = (type) color; \
break; \
}
switch
(
bpp
)
{
case
1
:
COLORFILL_ROW
(
BYTE
)
case
2
:
COLORFILL_ROW
(
WORD
)
case
3
:
{
BYTE
*
d
=
(
BYTE
*
)
buf
;
for
(
x
=
0
;
x
<
width
;
x
++
,
d
+=
3
)
{
d
[
0
]
=
(
color
)
&
0xFF
;
d
[
1
]
=
(
color
>>
8
)
&
0xFF
;
d
[
2
]
=
(
color
>>
16
)
&
0xFF
;
}
break
;
}
case
4
:
COLORFILL_ROW
(
DWORD
)
default:
FIXME
(
"Color fill not implemented for bpp %d!
\n
"
,
bpp
*
8
);
return
WINED3DERR_NOTAVAILABLE
;
}
#undef COLORFILL_ROW
/* Now copy first row */
first
=
buf
;
for
(
y
=
1
;
y
<
height
;
y
++
)
{
buf
+=
lPitch
;
memcpy
(
buf
,
first
,
width
*
bpp
);
}
return
WINED3D_OK
;
}
/*****************************************************************************
* IWineD3DSurface::Blt, SW emulation version
*
* Performs blits to a surface, eigher from a source of source-less blts
* This is the main functionality of DirectDraw
*
* Params:
* DestRect: Destination rectangle to write to
* SrcSurface: Source surface, can be NULL
* SrcRect: Source rectangle
*****************************************************************************/
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_Blt
(
IWineD3DSurface
*
iface
,
RECT
*
DestRect
,
IWineD3DSurface
*
SrcSurface
,
RECT
*
SrcRect
,
DWORD
Flags
,
WINEDDBLTFX
*
DDBltFx
,
WINED3DTEXTUREFILTERTYPE
Filter
)
{
IWineD3DSurfaceImpl
*
This
=
(
IWineD3DSurfaceImpl
*
)
iface
;
IWineD3DSurfaceImpl
*
Src
=
(
IWineD3DSurfaceImpl
*
)
SrcSurface
;
RECT
xdst
,
xsrc
;
HRESULT
ret
=
WINED3D_OK
;
WINED3DLOCKED_RECT
dlock
,
slock
;
WINED3DFORMAT
dfmt
=
WINED3DFMT_UNKNOWN
,
sfmt
=
WINED3DFMT_UNKNOWN
;
int
bpp
,
srcheight
,
srcwidth
,
dstheight
,
dstwidth
,
width
;
int
x
,
y
;
const
StaticPixelFormatDesc
*
sEntry
,
*
dEntry
;
LPBYTE
dbuf
,
sbuf
;
TRACE
(
"(%p)->(%p,%p,%p,%x,%p)
\n
"
,
This
,
DestRect
,
Src
,
SrcRect
,
Flags
,
DDBltFx
);
if
(
TRACE_ON
(
d3d_surface
))
{
if
(
DestRect
)
TRACE
(
"
\t
destrect :%dx%d-%dx%d
\n
"
,
DestRect
->
left
,
DestRect
->
top
,
DestRect
->
right
,
DestRect
->
bottom
);
if
(
SrcRect
)
TRACE
(
"
\t
srcrect :%dx%d-%dx%d
\n
"
,
SrcRect
->
left
,
SrcRect
->
top
,
SrcRect
->
right
,
SrcRect
->
bottom
);
#if 0
TRACE("\tflags: ");
DDRAW_dump_DDBLT(Flags);
if (Flags & WINEDDBLT_DDFX)
{
TRACE("\tblitfx: ");
DDRAW_dump_DDBLTFX(DDBltFx->dwDDFX);
}
#endif
}
if
(
(
This
->
Flags
&
SFLAG_LOCKED
)
||
((
Src
!=
NULL
)
&&
(
Src
->
Flags
&
SFLAG_LOCKED
)))
{
WARN
(
" Surface is busy, returning DDERR_SURFACEBUSY
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
if
(
Filter
!=
WINED3DTEXF_NONE
&&
Filter
!=
WINED3DTEXF_POINT
)
{
/* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
FIXME
(
"Filters not supported in software blit
\n
"
);
}
if
(
Src
==
This
)
{
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
NULL
,
0
);
dfmt
=
This
->
resource
.
format
;
slock
=
dlock
;
sfmt
=
dfmt
;
sEntry
=
getFormatDescEntry
(
sfmt
,
NULL
,
NULL
);
dEntry
=
sEntry
;
}
else
{
if
(
Src
)
{
IWineD3DSurface_LockRect
(
SrcSurface
,
&
slock
,
NULL
,
WINED3DLOCK_READONLY
);
sfmt
=
Src
->
resource
.
format
;
}
sEntry
=
getFormatDescEntry
(
sfmt
,
NULL
,
NULL
);
dfmt
=
This
->
resource
.
format
;
dEntry
=
getFormatDescEntry
(
dfmt
,
NULL
,
NULL
);
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
NULL
,
0
);
}
if
(
!
DDBltFx
||
!
(
DDBltFx
->
dwDDFX
))
Flags
&=
~
WINEDDBLT_DDFX
;
if
(
sEntry
->
isFourcc
&&
dEntry
->
isFourcc
)
{
if
(
sfmt
!=
dfmt
)
{
FIXME
(
"FOURCC->FOURCC copy only supported for the same type of surface
\n
"
);
ret
=
WINED3DERR_WRONGTEXTUREFORMAT
;
goto
release
;
}
memcpy
(
dlock
.
pBits
,
slock
.
pBits
,
This
->
resource
.
size
);
goto
release
;
}
if
(
sEntry
->
isFourcc
&&
!
dEntry
->
isFourcc
)
{
FIXME
(
"DXTC decompression not supported right now
\n
"
);
goto
release
;
}
if
(
DestRect
)
{
memcpy
(
&
xdst
,
DestRect
,
sizeof
(
xdst
));
}
else
{
xdst
.
top
=
0
;
xdst
.
bottom
=
This
->
currentDesc
.
Height
;
xdst
.
left
=
0
;
xdst
.
right
=
This
->
currentDesc
.
Width
;
}
if
(
SrcRect
)
{
memcpy
(
&
xsrc
,
SrcRect
,
sizeof
(
xsrc
));
}
else
{
if
(
Src
)
{
xsrc
.
top
=
0
;
xsrc
.
bottom
=
Src
->
currentDesc
.
Height
;
xsrc
.
left
=
0
;
xsrc
.
right
=
Src
->
currentDesc
.
Width
;
}
else
{
memset
(
&
xsrc
,
0
,
sizeof
(
xsrc
));
}
}
/* First check for the validity of source / destination rectangles. This was
* verified using a test application + by MSDN.
*/
if
((
Src
!=
NULL
)
&&
((
xsrc
.
bottom
>
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
bottom
<
0
)
||
(
xsrc
.
top
>
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
top
<
0
)
||
(
xsrc
.
left
>
Src
->
currentDesc
.
Width
)
||
(
xsrc
.
left
<
0
)
||
(
xsrc
.
right
>
Src
->
currentDesc
.
Width
)
||
(
xsrc
.
right
<
0
)
||
(
xsrc
.
right
<
xsrc
.
left
)
||
(
xsrc
.
bottom
<
xsrc
.
top
)))
{
WARN
(
"Application gave us bad source rectangle for Blt.
\n
"
);
ret
=
WINEDDERR_INVALIDRECT
;
goto
release
;
}
/* For the Destination rect, it can be out of bounds on the condition that a clipper
* is set for the given surface.
*/
if
((
/*This->clipper == NULL*/
TRUE
)
&&
((
xdst
.
bottom
>
This
->
currentDesc
.
Height
)
||
(
xdst
.
bottom
<
0
)
||
(
xdst
.
top
>
This
->
currentDesc
.
Height
)
||
(
xdst
.
top
<
0
)
||
(
xdst
.
left
>
This
->
currentDesc
.
Width
)
||
(
xdst
.
left
<
0
)
||
(
xdst
.
right
>
This
->
currentDesc
.
Width
)
||
(
xdst
.
right
<
0
)
||
(
xdst
.
right
<
xdst
.
left
)
||
(
xdst
.
bottom
<
xdst
.
top
)))
{
WARN
(
"Application gave us bad destination rectangle for Blt without a clipper set.
\n
"
);
ret
=
WINEDDERR_INVALIDRECT
;
goto
release
;
}
/* Now handle negative values in the rectangles. Warning: only supported for now
in the 'simple' cases (ie not in any stretching / rotation cases).
First, the case where nothing is to be done.
*/
if
(((
xdst
.
bottom
<=
0
)
||
(
xdst
.
right
<=
0
)
||
(
xdst
.
top
>=
(
int
)
This
->
currentDesc
.
Height
)
||
(
xdst
.
left
>=
(
int
)
This
->
currentDesc
.
Width
))
||
((
Src
!=
NULL
)
&&
((
xsrc
.
bottom
<=
0
)
||
(
xsrc
.
right
<=
0
)
||
(
xsrc
.
top
>=
(
int
)
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
left
>=
(
int
)
Src
->
currentDesc
.
Width
))
))
{
TRACE
(
"Nothing to be done !
\n
"
);
goto
release
;
}
/* The easy case : the source-less blits.... */
if
(
Src
==
NULL
)
{
RECT
full_rect
;
RECT
temp_rect
;
/* No idea if intersect rect can be the same as one of the source rect */
full_rect
.
left
=
0
;
full_rect
.
top
=
0
;
full_rect
.
right
=
This
->
currentDesc
.
Width
;
full_rect
.
bottom
=
This
->
currentDesc
.
Height
;
IntersectRect
(
&
temp_rect
,
&
full_rect
,
&
xdst
);
xdst
=
temp_rect
;
}
else
{
/* Only handle clipping on the destination rectangle */
int
clip_horiz
=
(
xdst
.
left
<
0
)
||
(
xdst
.
right
>
(
int
)
This
->
currentDesc
.
Width
);
int
clip_vert
=
(
xdst
.
top
<
0
)
||
(
xdst
.
bottom
>
(
int
)
This
->
currentDesc
.
Height
);
if
(
clip_vert
||
clip_horiz
)
{
/* Now check if this is a special case or not... */
if
((((
xdst
.
bottom
-
xdst
.
top
)
!=
(
xsrc
.
bottom
-
xsrc
.
top
))
&&
clip_vert
)
||
(((
xdst
.
right
-
xdst
.
left
)
!=
(
xsrc
.
right
-
xsrc
.
left
))
&&
clip_horiz
)
||
(
Flags
&
WINEDDBLT_DDFX
))
{
WARN
(
"Out of screen rectangle in special case. Not handled right now.
\n
"
);
goto
release
;
}
if
(
clip_horiz
)
{
if
(
xdst
.
left
<
0
)
{
xsrc
.
left
-=
xdst
.
left
;
xdst
.
left
=
0
;
}
if
(
xdst
.
right
>
This
->
currentDesc
.
Width
)
{
xsrc
.
right
-=
(
xdst
.
right
-
(
int
)
This
->
currentDesc
.
Width
);
xdst
.
right
=
(
int
)
This
->
currentDesc
.
Width
;
}
}
if
(
clip_vert
)
{
if
(
xdst
.
top
<
0
)
{
xsrc
.
top
-=
xdst
.
top
;
xdst
.
top
=
0
;
}
if
(
xdst
.
bottom
>
This
->
currentDesc
.
Height
)
{
xsrc
.
bottom
-=
(
xdst
.
bottom
-
(
int
)
This
->
currentDesc
.
Height
);
xdst
.
bottom
=
(
int
)
This
->
currentDesc
.
Height
;
}
}
/* And check if after clipping something is still to be done... */
if
((
xdst
.
bottom
<=
0
)
||
(
xdst
.
right
<=
0
)
||
(
xdst
.
top
>=
(
int
)
This
->
currentDesc
.
Height
)
||
(
xdst
.
left
>=
(
int
)
This
->
currentDesc
.
Width
)
||
(
xsrc
.
bottom
<=
0
)
||
(
xsrc
.
right
<=
0
)
||
(
xsrc
.
top
>=
(
int
)
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
left
>=
(
int
)
Src
->
currentDesc
.
Width
))
{
TRACE
(
"Nothing to be done after clipping !
\n
"
);
goto
release
;
}
}
}
bpp
=
This
->
bytesPerPixel
;
srcheight
=
xsrc
.
bottom
-
xsrc
.
top
;
srcwidth
=
xsrc
.
right
-
xsrc
.
left
;
dstheight
=
xdst
.
bottom
-
xdst
.
top
;
dstwidth
=
xdst
.
right
-
xdst
.
left
;
width
=
(
xdst
.
right
-
xdst
.
left
)
*
bpp
;
assert
(
width
<=
dlock
.
Pitch
);
dbuf
=
(
BYTE
*
)
dlock
.
pBits
+
(
xdst
.
top
*
dlock
.
Pitch
)
+
(
xdst
.
left
*
bpp
);
if
(
Flags
&
WINEDDBLT_WAIT
)
{
Flags
&=
~
WINEDDBLT_WAIT
;
}
if
(
Flags
&
WINEDDBLT_ASYNC
)
{
static
BOOL
displayed
=
FALSE
;
if
(
!
displayed
)
FIXME
(
"Can't handle WINEDDBLT_ASYNC flag right now.
\n
"
);
displayed
=
TRUE
;
Flags
&=
~
WINEDDBLT_ASYNC
;
}
if
(
Flags
&
WINEDDBLT_DONOTWAIT
)
{
/* WINEDDBLT_DONOTWAIT appeared in DX7 */
static
BOOL
displayed
=
FALSE
;
if
(
!
displayed
)
FIXME
(
"Can't handle WINEDDBLT_DONOTWAIT flag right now.
\n
"
);
displayed
=
TRUE
;
Flags
&=
~
WINEDDBLT_DONOTWAIT
;
}
/* First, all the 'source-less' blits */
if
(
Flags
&
WINEDDBLT_COLORFILL
)
{
ret
=
_Blt_ColorFill
(
dbuf
,
dstwidth
,
dstheight
,
bpp
,
dlock
.
Pitch
,
DDBltFx
->
u5
.
dwFillColor
);
Flags
&=
~
WINEDDBLT_COLORFILL
;
}
if
(
Flags
&
WINEDDBLT_DEPTHFILL
)
{
FIXME
(
"DDBLT_DEPTHFILL needs to be implemented!
\n
"
);
}
if
(
Flags
&
WINEDDBLT_ROP
)
{
/* Catch some degenerate cases here */
switch
(
DDBltFx
->
dwROP
)
{
case
BLACKNESS
:
ret
=
_Blt_ColorFill
(
dbuf
,
dstwidth
,
dstheight
,
bpp
,
dlock
.
Pitch
,
0
);
break
;
case
0xAA0029
:
/* No-op */
break
;
case
WHITENESS
:
ret
=
_Blt_ColorFill
(
dbuf
,
dstwidth
,
dstheight
,
bpp
,
dlock
.
Pitch
,
~
0
);
break
;
case
SRCCOPY
:
/* well, we do that below ? */
break
;
default:
FIXME
(
"Unsupported raster op: %08x Pattern: %p
\n
"
,
DDBltFx
->
dwROP
,
DDBltFx
->
u5
.
lpDDSPattern
);
goto
error
;
}
Flags
&=
~
WINEDDBLT_ROP
;
}
if
(
Flags
&
WINEDDBLT_DDROPS
)
{
FIXME
(
"
\t
Ddraw Raster Ops: %08x Pattern: %p
\n
"
,
DDBltFx
->
dwDDROP
,
DDBltFx
->
u5
.
lpDDSPattern
);
}
/* Now the 'with source' blits */
if
(
Src
)
{
LPBYTE
sbase
;
int
sx
,
xinc
,
sy
,
yinc
;
if
(
!
dstwidth
||
!
dstheight
)
/* hmm... stupid program ? */
goto
release
;
sbase
=
(
BYTE
*
)
slock
.
pBits
+
(
xsrc
.
top
*
slock
.
Pitch
)
+
xsrc
.
left
*
bpp
;
xinc
=
(
srcwidth
<<
16
)
/
dstwidth
;
yinc
=
(
srcheight
<<
16
)
/
dstheight
;
if
(
!
Flags
)
{
/* No effects, we can cheat here */
if
(
dstwidth
==
srcwidth
)
{
if
(
dstheight
==
srcheight
)
{
/* No stretching in either direction. This needs to be as
* fast as possible */
sbuf
=
sbase
;
/* check for overlapping surfaces */
if
(
SrcSurface
!=
iface
||
xdst
.
top
<
xsrc
.
top
||
xdst
.
right
<=
xsrc
.
left
||
xsrc
.
right
<=
xdst
.
left
)
{
/* no overlap, or dst above src, so copy from top downwards */
for
(
y
=
0
;
y
<
dstheight
;
y
++
)
{
memcpy
(
dbuf
,
sbuf
,
width
);
sbuf
+=
slock
.
Pitch
;
dbuf
+=
dlock
.
Pitch
;
}
}
else
if
(
xdst
.
top
>
xsrc
.
top
)
/* copy from bottom upwards */
{
sbuf
+=
(
slock
.
Pitch
*
dstheight
);
dbuf
+=
(
dlock
.
Pitch
*
dstheight
);
for
(
y
=
0
;
y
<
dstheight
;
y
++
)
{
sbuf
-=
slock
.
Pitch
;
dbuf
-=
dlock
.
Pitch
;
memcpy
(
dbuf
,
sbuf
,
width
);
}
}
else
/* src and dst overlapping on the same line, use memmove */
{
for
(
y
=
0
;
y
<
dstheight
;
y
++
)
{
memmove
(
dbuf
,
sbuf
,
width
);
sbuf
+=
slock
.
Pitch
;
dbuf
+=
dlock
.
Pitch
;
}
}
}
else
{
/* Stretching in Y direction only */
for
(
y
=
sy
=
0
;
y
<
dstheight
;
y
++
,
sy
+=
yinc
)
{
sbuf
=
sbase
+
(
sy
>>
16
)
*
slock
.
Pitch
;
memcpy
(
dbuf
,
sbuf
,
width
);
dbuf
+=
dlock
.
Pitch
;
}
}
}
else
{
/* Stretching in X direction */
int
last_sy
=
-
1
;
for
(
y
=
sy
=
0
;
y
<
dstheight
;
y
++
,
sy
+=
yinc
)
{
sbuf
=
sbase
+
(
sy
>>
16
)
*
slock
.
Pitch
;
if
((
sy
>>
16
)
==
(
last_sy
>>
16
))
{
/* this sourcerow is the same as last sourcerow -
* copy already stretched row
*/
memcpy
(
dbuf
,
dbuf
-
dlock
.
Pitch
,
width
);
}
else
{
#define STRETCH_ROW(type) { \
type *s = (type *) sbuf, *d = (type *) dbuf; \
for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
d[x] = s[sx >> 16]; \
break; }
switch
(
bpp
)
{
case
1
:
STRETCH_ROW
(
BYTE
)
case
2
:
STRETCH_ROW
(
WORD
)
case
4
:
STRETCH_ROW
(
DWORD
)
case
3
:
{
LPBYTE
s
,
d
=
dbuf
;
for
(
x
=
sx
=
0
;
x
<
dstwidth
;
x
++
,
sx
+=
xinc
)
{
DWORD
pixel
;
s
=
sbuf
+
3
*
(
sx
>>
16
);
pixel
=
s
[
0
]
|
(
s
[
1
]
<<
8
)
|
(
s
[
2
]
<<
16
);
d
[
0
]
=
(
pixel
)
&
0xff
;
d
[
1
]
=
(
pixel
>>
8
)
&
0xff
;
d
[
2
]
=
(
pixel
>>
16
)
&
0xff
;
d
+=
3
;
}
break
;
}
default:
FIXME
(
"Stretched blit not implemented for bpp %d!
\n
"
,
bpp
*
8
);
ret
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
}
#undef STRETCH_ROW
}
dbuf
+=
dlock
.
Pitch
;
last_sy
=
sy
;
}
}
}
else
{
LONG
dstyinc
=
dlock
.
Pitch
,
dstxinc
=
bpp
;
DWORD
keylow
=
0xFFFFFFFF
,
keyhigh
=
0
,
keymask
=
0xFFFFFFFF
;
DWORD
destkeylow
=
0x0
,
destkeyhigh
=
0xFFFFFFFF
,
destkeymask
=
0xFFFFFFFF
;
if
(
Flags
&
(
WINEDDBLT_KEYSRC
|
WINEDDBLT_KEYDEST
|
WINEDDBLT_KEYSRCOVERRIDE
|
WINEDDBLT_KEYDESTOVERRIDE
))
{
/* The color keying flags are checked for correctness in ddraw */
if
(
Flags
&
WINEDDBLT_KEYSRC
)
{
keylow
=
Src
->
SrcBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
Src
->
SrcBltCKey
.
dwColorSpaceHighValue
;
}
else
if
(
Flags
&
WINEDDBLT_KEYSRCOVERRIDE
)
{
keylow
=
DDBltFx
->
ddckSrcColorkey
.
dwColorSpaceLowValue
;
keyhigh
=
DDBltFx
->
ddckSrcColorkey
.
dwColorSpaceHighValue
;
}
if
(
Flags
&
WINEDDBLT_KEYDEST
)
{
/* Destination color keys are taken from the source surface ! */
destkeylow
=
Src
->
DestBltCKey
.
dwColorSpaceLowValue
;
destkeyhigh
=
Src
->
DestBltCKey
.
dwColorSpaceHighValue
;
}
else
if
(
Flags
&
WINEDDBLT_KEYDESTOVERRIDE
)
{
destkeylow
=
DDBltFx
->
ddckDestColorkey
.
dwColorSpaceLowValue
;
destkeyhigh
=
DDBltFx
->
ddckDestColorkey
.
dwColorSpaceHighValue
;
}
if
(
bpp
==
1
)
{
keymask
=
0xff
;
}
else
{
keymask
=
sEntry
->
redMask
|
sEntry
->
greenMask
|
sEntry
->
blueMask
;
}
Flags
&=
~
(
WINEDDBLT_KEYSRC
|
WINEDDBLT_KEYDEST
|
WINEDDBLT_KEYSRCOVERRIDE
|
WINEDDBLT_KEYDESTOVERRIDE
);
}
if
(
Flags
&
WINEDDBLT_DDFX
)
{
LPBYTE
dTopLeft
,
dTopRight
,
dBottomLeft
,
dBottomRight
,
tmp
;
LONG
tmpxy
;
dTopLeft
=
dbuf
;
dTopRight
=
dbuf
+
((
dstwidth
-
1
)
*
bpp
);
dBottomLeft
=
dTopLeft
+
((
dstheight
-
1
)
*
dlock
.
Pitch
);
dBottomRight
=
dBottomLeft
+
((
dstwidth
-
1
)
*
bpp
);
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ARITHSTRETCHY
)
{
/* I don't think we need to do anything about this flag */
WARN
(
"Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY
\n
"
);
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_MIRRORLEFTRIGHT
)
{
tmp
=
dTopRight
;
dTopRight
=
dTopLeft
;
dTopLeft
=
tmp
;
tmp
=
dBottomRight
;
dBottomRight
=
dBottomLeft
;
dBottomLeft
=
tmp
;
dstxinc
=
dstxinc
*-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_MIRRORUPDOWN
)
{
tmp
=
dTopLeft
;
dTopLeft
=
dBottomLeft
;
dBottomLeft
=
tmp
;
tmp
=
dTopRight
;
dTopRight
=
dBottomRight
;
dBottomRight
=
tmp
;
dstyinc
=
dstyinc
*-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_NOTEARING
)
{
/* I don't think we need to do anything about this flag */
WARN
(
"Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING
\n
"
);
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ROTATE180
)
{
tmp
=
dBottomRight
;
dBottomRight
=
dTopLeft
;
dTopLeft
=
tmp
;
tmp
=
dBottomLeft
;
dBottomLeft
=
dTopRight
;
dTopRight
=
tmp
;
dstxinc
=
dstxinc
*
-
1
;
dstyinc
=
dstyinc
*
-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ROTATE270
)
{
tmp
=
dTopLeft
;
dTopLeft
=
dBottomLeft
;
dBottomLeft
=
dBottomRight
;
dBottomRight
=
dTopRight
;
dTopRight
=
tmp
;
tmpxy
=
dstxinc
;
dstxinc
=
dstyinc
;
dstyinc
=
tmpxy
;
dstxinc
=
dstxinc
*
-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ROTATE90
)
{
tmp
=
dTopLeft
;
dTopLeft
=
dTopRight
;
dTopRight
=
dBottomRight
;
dBottomRight
=
dBottomLeft
;
dBottomLeft
=
tmp
;
tmpxy
=
dstxinc
;
dstxinc
=
dstyinc
;
dstyinc
=
tmpxy
;
dstyinc
=
dstyinc
*
-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ZBUFFERBASEDEST
)
{
/* I don't think we need to do anything about this flag */
WARN
(
"Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST
\n
"
);
}
dbuf
=
dTopLeft
;
Flags
&=
~
(
WINEDDBLT_DDFX
);
}
#define COPY_COLORKEY_FX(type) { \
type *s, *d = (type *) dbuf, *dx, tmp; \
for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
s = (type*)(sbase + (sy >> 16) * slock.Pitch); \
dx = d; \
for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
tmp = s[sx >> 16]; \
if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
dx[0] = tmp; \
} \
dx = (type*)(((LPBYTE)dx)+dstxinc); \
} \
d = (type*)(((LPBYTE)d)+dstyinc); \
} \
break; }
switch
(
bpp
)
{
case
1
:
COPY_COLORKEY_FX
(
BYTE
)
case
2
:
COPY_COLORKEY_FX
(
WORD
)
case
4
:
COPY_COLORKEY_FX
(
DWORD
)
case
3
:
{
LPBYTE
s
,
d
=
dbuf
,
dx
;
for
(
y
=
sy
=
0
;
y
<
dstheight
;
y
++
,
sy
+=
yinc
)
{
sbuf
=
sbase
+
(
sy
>>
16
)
*
slock
.
Pitch
;
dx
=
d
;
for
(
x
=
sx
=
0
;
x
<
dstwidth
;
x
++
,
sx
+=
xinc
)
{
DWORD
pixel
,
dpixel
=
0
;
s
=
sbuf
+
3
*
(
sx
>>
16
);
pixel
=
s
[
0
]
|
(
s
[
1
]
<<
8
)
|
(
s
[
2
]
<<
16
);
dpixel
=
dx
[
0
]
|
(
dx
[
1
]
<<
8
)
|
(
dx
[
2
]
<<
16
);
if
(((
pixel
&
keymask
)
<
keylow
||
(
pixel
&
keymask
)
>
keyhigh
)
&&
((
dpixel
&
keymask
)
>=
destkeylow
||
(
dpixel
&
keymask
)
<=
keyhigh
))
{
dx
[
0
]
=
(
pixel
)
&
0xff
;
dx
[
1
]
=
(
pixel
>>
8
)
&
0xff
;
dx
[
2
]
=
(
pixel
>>
16
)
&
0xff
;
}
dx
+=
dstxinc
;
}
d
+=
dstyinc
;
}
break
;
}
default:
FIXME
(
"%s color-keyed blit not implemented for bpp %d!
\n
"
,
(
Flags
&
WINEDDBLT_KEYSRC
)
?
"Source"
:
"Destination"
,
bpp
*
8
);
ret
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
#undef COPY_COLORKEY_FX
}
}
}
error:
if
(
Flags
&&
FIXME_ON
(
d3d_surface
))
{
FIXME
(
"
\t
Unsupported flags: %08x
\n
"
,
Flags
);
}
release:
IWineD3DSurface_UnlockRect
(
iface
);
if
(
SrcSurface
&&
SrcSurface
!=
iface
)
IWineD3DSurface_UnlockRect
(
SrcSurface
);
return
ret
;
}
/*****************************************************************************
* IWineD3DSurface::BltFast, SW emulation version
*
* This is the software implementation of BltFast, as used by GDI surfaces
* and as a fallback for OpenGL surfaces. This code is taken from the old
* DirectDraw code, and was originally written by TransGaming.
*
* Params:
* dstx:
* dsty:
* Source: Source surface to copy from
* rsrc: Source rectangle
* trans: Some Flags
*
* Returns:
* WINED3D_OK on success
*
*****************************************************************************/
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_BltFast
(
IWineD3DSurface
*
iface
,
DWORD
dstx
,
DWORD
dsty
,
IWineD3DSurface
*
Source
,
RECT
*
rsrc
,
DWORD
trans
)
{
IWineD3DSurfaceImpl
*
This
=
(
IWineD3DSurfaceImpl
*
)
iface
;
IWineD3DSurfaceImpl
*
Src
=
(
IWineD3DSurfaceImpl
*
)
Source
;
int
bpp
,
w
,
h
,
x
,
y
;
WINED3DLOCKED_RECT
dlock
,
slock
;
HRESULT
ret
=
WINED3D_OK
;
RECT
rsrc2
;
RECT
lock_src
,
lock_dst
,
lock_union
;
BYTE
*
sbuf
,
*
dbuf
;
const
StaticPixelFormatDesc
*
sEntry
,
*
dEntry
;
if
(
TRACE_ON
(
d3d_surface
))
{
TRACE
(
"(%p)->(%d,%d,%p,%p,%08x)
\n
"
,
This
,
dstx
,
dsty
,
Src
,
rsrc
,
trans
);
if
(
rsrc
)
{
TRACE
(
"
\t
srcrect: %dx%d-%dx%d
\n
"
,
rsrc
->
left
,
rsrc
->
top
,
rsrc
->
right
,
rsrc
->
bottom
);
}
else
{
TRACE
(
" srcrect: NULL
\n
"
);
}
}
if
((
This
->
Flags
&
SFLAG_LOCKED
)
||
((
Src
!=
NULL
)
&&
(
Src
->
Flags
&
SFLAG_LOCKED
)))
{
WARN
(
" Surface is busy, returning DDERR_SURFACEBUSY
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
if
(
!
rsrc
)
{
WARN
(
"rsrc is NULL!
\n
"
);
rsrc
=
&
rsrc2
;
rsrc
->
left
=
0
;
rsrc
->
top
=
0
;
rsrc
->
right
=
Src
->
currentDesc
.
Width
;
rsrc
->
bottom
=
Src
->
currentDesc
.
Height
;
}
/* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
if
((
rsrc
->
bottom
>
Src
->
currentDesc
.
Height
)
||
(
rsrc
->
bottom
<
0
)
||
(
rsrc
->
top
>
Src
->
currentDesc
.
Height
)
||
(
rsrc
->
top
<
0
)
||
(
rsrc
->
left
>
Src
->
currentDesc
.
Width
)
||
(
rsrc
->
left
<
0
)
||
(
rsrc
->
right
>
Src
->
currentDesc
.
Width
)
||
(
rsrc
->
right
<
0
)
||
(
rsrc
->
right
<
rsrc
->
left
)
||
(
rsrc
->
bottom
<
rsrc
->
top
))
{
WARN
(
"Application gave us bad source rectangle for BltFast.
\n
"
);
return
WINEDDERR_INVALIDRECT
;
}
h
=
rsrc
->
bottom
-
rsrc
->
top
;
if
(
h
>
This
->
currentDesc
.
Height
-
dsty
)
h
=
This
->
currentDesc
.
Height
-
dsty
;
if
(
h
>
Src
->
currentDesc
.
Height
-
rsrc
->
top
)
h
=
Src
->
currentDesc
.
Height
-
rsrc
->
top
;
if
(
h
<=
0
)
return
WINEDDERR_INVALIDRECT
;
w
=
rsrc
->
right
-
rsrc
->
left
;
if
(
w
>
This
->
currentDesc
.
Width
-
dstx
)
w
=
This
->
currentDesc
.
Width
-
dstx
;
if
(
w
>
Src
->
currentDesc
.
Width
-
rsrc
->
left
)
w
=
Src
->
currentDesc
.
Width
-
rsrc
->
left
;
if
(
w
<=
0
)
return
WINEDDERR_INVALIDRECT
;
/* Now compute the locking rectangle... */
lock_src
.
left
=
rsrc
->
left
;
lock_src
.
top
=
rsrc
->
top
;
lock_src
.
right
=
lock_src
.
left
+
w
;
lock_src
.
bottom
=
lock_src
.
top
+
h
;
lock_dst
.
left
=
dstx
;
lock_dst
.
top
=
dsty
;
lock_dst
.
right
=
dstx
+
w
;
lock_dst
.
bottom
=
dsty
+
h
;
bpp
=
This
->
bytesPerPixel
;
/* We need to lock the surfaces, or we won't get refreshes when done. */
if
(
Src
==
This
)
{
int
pitch
;
UnionRect
(
&
lock_union
,
&
lock_src
,
&
lock_dst
);
/* Lock the union of the two rectangles */
ret
=
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
&
lock_union
,
0
);
if
(
ret
!=
WINED3D_OK
)
goto
error
;
pitch
=
dlock
.
Pitch
;
slock
.
Pitch
=
dlock
.
Pitch
;
/* Since slock was originally copied from this surface's description, we can just reuse it */
assert
(
This
->
resource
.
allocatedMemory
!=
NULL
);
sbuf
=
(
BYTE
*
)
This
->
resource
.
allocatedMemory
+
lock_src
.
top
*
pitch
+
lock_src
.
left
*
bpp
;
dbuf
=
(
BYTE
*
)
This
->
resource
.
allocatedMemory
+
lock_dst
.
top
*
pitch
+
lock_dst
.
left
*
bpp
;
sEntry
=
getFormatDescEntry
(
Src
->
resource
.
format
,
NULL
,
NULL
);
dEntry
=
sEntry
;
}
else
{
ret
=
IWineD3DSurface_LockRect
(
Source
,
&
slock
,
&
lock_src
,
WINED3DLOCK_READONLY
);
if
(
ret
!=
WINED3D_OK
)
goto
error
;
ret
=
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
&
lock_dst
,
0
);
if
(
ret
!=
WINED3D_OK
)
goto
error
;
sbuf
=
slock
.
pBits
;
dbuf
=
dlock
.
pBits
;
TRACE
(
"Dst is at %p, Src is at %p
\n
"
,
dbuf
,
sbuf
);
sEntry
=
getFormatDescEntry
(
Src
->
resource
.
format
,
NULL
,
NULL
);
dEntry
=
getFormatDescEntry
(
This
->
resource
.
format
,
NULL
,
NULL
);
}
/* Handle first the FOURCC surfaces... */
if
(
sEntry
->
isFourcc
&&
dEntry
->
isFourcc
)
{
TRACE
(
"Fourcc -> Fourcc copy
\n
"
);
if
(
trans
)
FIXME
(
"trans arg not supported when a FOURCC surface is involved
\n
"
);
if
(
dstx
||
dsty
)
FIXME
(
"offset for destination surface is not supported
\n
"
);
if
(
Src
->
resource
.
format
!=
This
->
resource
.
format
)
{
FIXME
(
"FOURCC->FOURCC copy only supported for the same type of surface
\n
"
);
ret
=
WINED3DERR_WRONGTEXTUREFORMAT
;
goto
error
;
}
/* FIXME: Watch out that the size is correct for FOURCC surfaces */
memcpy
(
dbuf
,
sbuf
,
This
->
resource
.
size
);
goto
error
;
}
if
(
sEntry
->
isFourcc
&&
!
dEntry
->
isFourcc
)
{
/* TODO: Use the libtxc_dxtn.so shared library to do
* software decompression
*/
ERR
(
"DXTC decompression not supported by now
\n
"
);
goto
error
;
}
if
(
trans
&
(
WINEDDBLTFAST_SRCCOLORKEY
|
WINEDDBLTFAST_DESTCOLORKEY
))
{
DWORD
keylow
,
keyhigh
;
TRACE
(
"Color keyed copy
\n
"
);
if
(
trans
&
WINEDDBLTFAST_SRCCOLORKEY
)
{
keylow
=
Src
->
SrcBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
Src
->
SrcBltCKey
.
dwColorSpaceHighValue
;
}
else
{
/* I'm not sure if this is correct */
FIXME
(
"WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.
\n
"
);
keylow
=
This
->
DestBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
This
->
DestBltCKey
.
dwColorSpaceHighValue
;
}
#define COPYBOX_COLORKEY(type) { \
type *d, *s, tmp; \
s = (type *) sbuf; \
d = (type *) dbuf; \
for (y = 0; y < h; y++) { \
for (x = 0; x < w; x++) { \
tmp = s[x]; \
if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
} \
s = (type *)((BYTE *)s + slock.Pitch); \
d = (type *)((BYTE *)d + dlock.Pitch); \
} \
break; \
}
switch
(
bpp
)
{
case
1
:
COPYBOX_COLORKEY
(
BYTE
)
case
2
:
COPYBOX_COLORKEY
(
WORD
)
case
4
:
COPYBOX_COLORKEY
(
DWORD
)
case
3
:
{
BYTE
*
d
,
*
s
;
DWORD
tmp
;
s
=
(
BYTE
*
)
sbuf
;
d
=
(
BYTE
*
)
dbuf
;
for
(
y
=
0
;
y
<
h
;
y
++
)
{
for
(
x
=
0
;
x
<
w
*
3
;
x
+=
3
)
{
tmp
=
(
DWORD
)
s
[
x
]
+
((
DWORD
)
s
[
x
+
1
]
<<
8
)
+
((
DWORD
)
s
[
x
+
2
]
<<
16
);
if
(
tmp
<
keylow
||
tmp
>
keyhigh
)
{
d
[
x
+
0
]
=
s
[
x
+
0
];
d
[
x
+
1
]
=
s
[
x
+
1
];
d
[
x
+
2
]
=
s
[
x
+
2
];
}
}
s
+=
slock
.
Pitch
;
d
+=
dlock
.
Pitch
;
}
break
;
}
default:
FIXME
(
"Source color key blitting not supported for bpp %d
\n
"
,
bpp
*
8
);
ret
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
}
#undef COPYBOX_COLORKEY
TRACE
(
"Copy Done
\n
"
);
}
else
{
int
width
=
w
*
bpp
;
TRACE
(
"NO color key copy
\n
"
);
for
(
y
=
0
;
y
<
h
;
y
++
)
{
/* This is pretty easy, a line for line memcpy */
memcpy
(
dbuf
,
sbuf
,
width
);
sbuf
+=
slock
.
Pitch
;
dbuf
+=
dlock
.
Pitch
;
}
TRACE
(
"Copy done
\n
"
);
}
error:
if
(
Src
==
This
)
{
IWineD3DSurface_UnlockRect
(
iface
);
}
else
{
IWineD3DSurface_UnlockRect
(
iface
);
IWineD3DSurface_UnlockRect
(
Source
);
}
return
ret
;
}
dlls/wined3d/surface_gdi.c
View file @
46e2d795
...
...
@@ -446,961 +446,6 @@ IWineGDISurfaceImpl_Flip(IWineD3DSurface *iface,
}
/*****************************************************************************
* _Blt_ColorFill
*
* Helper function that fills a memory area with a specific color
*
* Params:
* buf: memory address to start filling at
* width, height: Dimensions of the area to fill
* bpp: Bit depth of the surface
* lPitch: pitch of the surface
* color: Color to fill with
*
*****************************************************************************/
static
HRESULT
_Blt_ColorFill
(
BYTE
*
buf
,
int
width
,
int
height
,
int
bpp
,
LONG
lPitch
,
DWORD
color
)
{
int
x
,
y
;
LPBYTE
first
;
/* Do first row */
#define COLORFILL_ROW(type) \
{ \
type *d = (type *) buf; \
for (x = 0; x < width; x++) \
d[x] = (type) color; \
break; \
}
switch
(
bpp
)
{
case
1
:
COLORFILL_ROW
(
BYTE
)
case
2
:
COLORFILL_ROW
(
WORD
)
case
3
:
{
BYTE
*
d
=
(
BYTE
*
)
buf
;
for
(
x
=
0
;
x
<
width
;
x
++
,
d
+=
3
)
{
d
[
0
]
=
(
color
)
&
0xFF
;
d
[
1
]
=
(
color
>>
8
)
&
0xFF
;
d
[
2
]
=
(
color
>>
16
)
&
0xFF
;
}
break
;
}
case
4
:
COLORFILL_ROW
(
DWORD
)
default:
FIXME
(
"Color fill not implemented for bpp %d!
\n
"
,
bpp
*
8
);
return
WINED3DERR_NOTAVAILABLE
;
}
#undef COLORFILL_ROW
/* Now copy first row */
first
=
buf
;
for
(
y
=
1
;
y
<
height
;
y
++
)
{
buf
+=
lPitch
;
memcpy
(
buf
,
first
,
width
*
bpp
);
}
return
WINED3D_OK
;
}
/*****************************************************************************
* IWineD3DSurface::Blt, GDI version
*
* Performs blits to a surface, eigher from a source of source-less blts
* This is the main functionality of DirectDraw
*
* Params:
* DestRect: Destination rectangle to write to
* SrcSurface: Source surface, can be NULL
* SrcRect: Source rectangle
*****************************************************************************/
HRESULT
WINAPI
IWineGDISurfaceImpl_Blt
(
IWineD3DSurface
*
iface
,
RECT
*
DestRect
,
IWineD3DSurface
*
SrcSurface
,
RECT
*
SrcRect
,
DWORD
Flags
,
WINEDDBLTFX
*
DDBltFx
,
WINED3DTEXTUREFILTERTYPE
Filter
)
{
IWineD3DSurfaceImpl
*
This
=
(
IWineD3DSurfaceImpl
*
)
iface
;
IWineD3DSurfaceImpl
*
Src
=
(
IWineD3DSurfaceImpl
*
)
SrcSurface
;
RECT
xdst
,
xsrc
;
HRESULT
ret
=
WINED3D_OK
;
WINED3DLOCKED_RECT
dlock
,
slock
;
WINED3DFORMAT
dfmt
=
WINED3DFMT_UNKNOWN
,
sfmt
=
WINED3DFMT_UNKNOWN
;
int
bpp
,
srcheight
,
srcwidth
,
dstheight
,
dstwidth
,
width
;
int
x
,
y
;
const
StaticPixelFormatDesc
*
sEntry
,
*
dEntry
;
LPBYTE
dbuf
,
sbuf
;
TRACE
(
"(%p)->(%p,%p,%p,%x,%p)
\n
"
,
This
,
DestRect
,
Src
,
SrcRect
,
Flags
,
DDBltFx
);
if
(
TRACE_ON
(
d3d_surface
))
{
if
(
DestRect
)
TRACE
(
"
\t
destrect :%dx%d-%dx%d
\n
"
,
DestRect
->
left
,
DestRect
->
top
,
DestRect
->
right
,
DestRect
->
bottom
);
if
(
SrcRect
)
TRACE
(
"
\t
srcrect :%dx%d-%dx%d
\n
"
,
SrcRect
->
left
,
SrcRect
->
top
,
SrcRect
->
right
,
SrcRect
->
bottom
);
#if 0
TRACE("\tflags: ");
DDRAW_dump_DDBLT(Flags);
if (Flags & WINEDDBLT_DDFX)
{
TRACE("\tblitfx: ");
DDRAW_dump_DDBLTFX(DDBltFx->dwDDFX);
}
#endif
}
if
(
(
This
->
Flags
&
SFLAG_LOCKED
)
||
((
Src
!=
NULL
)
&&
(
Src
->
Flags
&
SFLAG_LOCKED
)))
{
WARN
(
" Surface is busy, returning DDERR_SURFACEBUSY
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
if
(
Filter
!=
WINED3DTEXF_NONE
&&
Filter
!=
WINED3DTEXF_POINT
)
{
/* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
FIXME
(
"Filters not supported in software blit
\n
"
);
}
if
(
Src
==
This
)
{
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
NULL
,
0
);
dfmt
=
This
->
resource
.
format
;
slock
=
dlock
;
sfmt
=
dfmt
;
sEntry
=
getFormatDescEntry
(
sfmt
,
NULL
,
NULL
);
dEntry
=
sEntry
;
}
else
{
if
(
Src
)
{
IWineD3DSurface_LockRect
(
SrcSurface
,
&
slock
,
NULL
,
WINED3DLOCK_READONLY
);
sfmt
=
Src
->
resource
.
format
;
}
sEntry
=
getFormatDescEntry
(
sfmt
,
NULL
,
NULL
);
dfmt
=
This
->
resource
.
format
;
dEntry
=
getFormatDescEntry
(
dfmt
,
NULL
,
NULL
);
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
NULL
,
0
);
}
if
(
!
DDBltFx
||
!
(
DDBltFx
->
dwDDFX
))
Flags
&=
~
WINEDDBLT_DDFX
;
if
(
sEntry
->
isFourcc
&&
dEntry
->
isFourcc
)
{
if
(
sfmt
!=
dfmt
)
{
FIXME
(
"FOURCC->FOURCC copy only supported for the same type of surface
\n
"
);
ret
=
WINED3DERR_WRONGTEXTUREFORMAT
;
goto
release
;
}
memcpy
(
dlock
.
pBits
,
slock
.
pBits
,
This
->
resource
.
size
);
goto
release
;
}
if
(
sEntry
->
isFourcc
&&
!
dEntry
->
isFourcc
)
{
FIXME
(
"DXTC decompression not supported right now
\n
"
);
goto
release
;
}
if
(
DestRect
)
{
memcpy
(
&
xdst
,
DestRect
,
sizeof
(
xdst
));
}
else
{
xdst
.
top
=
0
;
xdst
.
bottom
=
This
->
currentDesc
.
Height
;
xdst
.
left
=
0
;
xdst
.
right
=
This
->
currentDesc
.
Width
;
}
if
(
SrcRect
)
{
memcpy
(
&
xsrc
,
SrcRect
,
sizeof
(
xsrc
));
}
else
{
if
(
Src
)
{
xsrc
.
top
=
0
;
xsrc
.
bottom
=
Src
->
currentDesc
.
Height
;
xsrc
.
left
=
0
;
xsrc
.
right
=
Src
->
currentDesc
.
Width
;
}
else
{
memset
(
&
xsrc
,
0
,
sizeof
(
xsrc
));
}
}
/* First check for the validity of source / destination rectangles. This was
verified using a test application + by MSDN.
*/
if
((
Src
!=
NULL
)
&&
((
xsrc
.
bottom
>
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
bottom
<
0
)
||
(
xsrc
.
top
>
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
top
<
0
)
||
(
xsrc
.
left
>
Src
->
currentDesc
.
Width
)
||
(
xsrc
.
left
<
0
)
||
(
xsrc
.
right
>
Src
->
currentDesc
.
Width
)
||
(
xsrc
.
right
<
0
)
||
(
xsrc
.
right
<
xsrc
.
left
)
||
(
xsrc
.
bottom
<
xsrc
.
top
)))
{
WARN
(
"Application gave us bad source rectangle for Blt.
\n
"
);
ret
=
WINEDDERR_INVALIDRECT
;
goto
release
;
}
/* For the Destination rect, it can be out of bounds on the condition that a clipper
is set for the given surface.
*/
if
((
/*This->clipper == NULL*/
TRUE
)
&&
((
xdst
.
bottom
>
This
->
currentDesc
.
Height
)
||
(
xdst
.
bottom
<
0
)
||
(
xdst
.
top
>
This
->
currentDesc
.
Height
)
||
(
xdst
.
top
<
0
)
||
(
xdst
.
left
>
This
->
currentDesc
.
Width
)
||
(
xdst
.
left
<
0
)
||
(
xdst
.
right
>
This
->
currentDesc
.
Width
)
||
(
xdst
.
right
<
0
)
||
(
xdst
.
right
<
xdst
.
left
)
||
(
xdst
.
bottom
<
xdst
.
top
)))
{
WARN
(
"Application gave us bad destination rectangle for Blt without a clipper set.
\n
"
);
ret
=
WINEDDERR_INVALIDRECT
;
goto
release
;
}
/* Now handle negative values in the rectangles. Warning: only supported for now
in the 'simple' cases (ie not in any stretching / rotation cases).
First, the case where nothing is to be done.
*/
if
(((
xdst
.
bottom
<=
0
)
||
(
xdst
.
right
<=
0
)
||
(
xdst
.
top
>=
(
int
)
This
->
currentDesc
.
Height
)
||
(
xdst
.
left
>=
(
int
)
This
->
currentDesc
.
Width
))
||
((
Src
!=
NULL
)
&&
((
xsrc
.
bottom
<=
0
)
||
(
xsrc
.
right
<=
0
)
||
(
xsrc
.
top
>=
(
int
)
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
left
>=
(
int
)
Src
->
currentDesc
.
Width
))
))
{
TRACE
(
"Nothing to be done !
\n
"
);
goto
release
;
}
/* The easy case : the source-less blits.... */
if
(
Src
==
NULL
)
{
RECT
full_rect
;
RECT
temp_rect
;
/* No idea if intersect rect can be the same as one of the source rect */
full_rect
.
left
=
0
;
full_rect
.
top
=
0
;
full_rect
.
right
=
This
->
currentDesc
.
Width
;
full_rect
.
bottom
=
This
->
currentDesc
.
Height
;
IntersectRect
(
&
temp_rect
,
&
full_rect
,
&
xdst
);
xdst
=
temp_rect
;
}
else
{
/* Only handle clipping on the destination rectangle */
int
clip_horiz
=
(
xdst
.
left
<
0
)
||
(
xdst
.
right
>
(
int
)
This
->
currentDesc
.
Width
);
int
clip_vert
=
(
xdst
.
top
<
0
)
||
(
xdst
.
bottom
>
(
int
)
This
->
currentDesc
.
Height
);
if
(
clip_vert
||
clip_horiz
)
{
/* Now check if this is a special case or not... */
if
((((
xdst
.
bottom
-
xdst
.
top
)
!=
(
xsrc
.
bottom
-
xsrc
.
top
))
&&
clip_vert
)
||
(((
xdst
.
right
-
xdst
.
left
)
!=
(
xsrc
.
right
-
xsrc
.
left
))
&&
clip_horiz
)
||
(
Flags
&
WINEDDBLT_DDFX
))
{
WARN
(
"Out of screen rectangle in special case. Not handled right now.
\n
"
);
goto
release
;
}
if
(
clip_horiz
)
{
if
(
xdst
.
left
<
0
)
{
xsrc
.
left
-=
xdst
.
left
;
xdst
.
left
=
0
;
}
if
(
xdst
.
right
>
This
->
currentDesc
.
Width
)
{
xsrc
.
right
-=
(
xdst
.
right
-
(
int
)
This
->
currentDesc
.
Width
);
xdst
.
right
=
(
int
)
This
->
currentDesc
.
Width
;
}
}
if
(
clip_vert
)
{
if
(
xdst
.
top
<
0
)
{
xsrc
.
top
-=
xdst
.
top
;
xdst
.
top
=
0
;
}
if
(
xdst
.
bottom
>
This
->
currentDesc
.
Height
)
{
xsrc
.
bottom
-=
(
xdst
.
bottom
-
(
int
)
This
->
currentDesc
.
Height
);
xdst
.
bottom
=
(
int
)
This
->
currentDesc
.
Height
;
}
}
/* And check if after clipping something is still to be done... */
if
((
xdst
.
bottom
<=
0
)
||
(
xdst
.
right
<=
0
)
||
(
xdst
.
top
>=
(
int
)
This
->
currentDesc
.
Height
)
||
(
xdst
.
left
>=
(
int
)
This
->
currentDesc
.
Width
)
||
(
xsrc
.
bottom
<=
0
)
||
(
xsrc
.
right
<=
0
)
||
(
xsrc
.
top
>=
(
int
)
Src
->
currentDesc
.
Height
)
||
(
xsrc
.
left
>=
(
int
)
Src
->
currentDesc
.
Width
))
{
TRACE
(
"Nothing to be done after clipping !
\n
"
);
goto
release
;
}
}
}
bpp
=
This
->
bytesPerPixel
;
srcheight
=
xsrc
.
bottom
-
xsrc
.
top
;
srcwidth
=
xsrc
.
right
-
xsrc
.
left
;
dstheight
=
xdst
.
bottom
-
xdst
.
top
;
dstwidth
=
xdst
.
right
-
xdst
.
left
;
width
=
(
xdst
.
right
-
xdst
.
left
)
*
bpp
;
assert
(
width
<=
dlock
.
Pitch
);
dbuf
=
(
BYTE
*
)
dlock
.
pBits
+
(
xdst
.
top
*
dlock
.
Pitch
)
+
(
xdst
.
left
*
bpp
);
if
(
Flags
&
WINEDDBLT_WAIT
)
{
Flags
&=
~
WINEDDBLT_WAIT
;
}
if
(
Flags
&
WINEDDBLT_ASYNC
)
{
static
BOOL
displayed
=
FALSE
;
if
(
!
displayed
)
FIXME
(
"Can't handle WINEDDBLT_ASYNC flag right now.
\n
"
);
displayed
=
TRUE
;
Flags
&=
~
WINEDDBLT_ASYNC
;
}
if
(
Flags
&
WINEDDBLT_DONOTWAIT
)
{
/* WINEDDBLT_DONOTWAIT appeared in DX7 */
static
BOOL
displayed
=
FALSE
;
if
(
!
displayed
)
FIXME
(
"Can't handle WINEDDBLT_DONOTWAIT flag right now.
\n
"
);
displayed
=
TRUE
;
Flags
&=
~
WINEDDBLT_DONOTWAIT
;
}
/* First, all the 'source-less' blits */
if
(
Flags
&
WINEDDBLT_COLORFILL
)
{
ret
=
_Blt_ColorFill
(
dbuf
,
dstwidth
,
dstheight
,
bpp
,
dlock
.
Pitch
,
DDBltFx
->
u5
.
dwFillColor
);
Flags
&=
~
WINEDDBLT_COLORFILL
;
}
if
(
Flags
&
WINEDDBLT_DEPTHFILL
)
{
FIXME
(
"DDBLT_DEPTHFILL needs to be implemented!
\n
"
);
}
if
(
Flags
&
WINEDDBLT_ROP
)
{
/* Catch some degenerate cases here */
switch
(
DDBltFx
->
dwROP
)
{
case
BLACKNESS
:
ret
=
_Blt_ColorFill
(
dbuf
,
dstwidth
,
dstheight
,
bpp
,
dlock
.
Pitch
,
0
);
break
;
case
0xAA0029
:
/* No-op */
break
;
case
WHITENESS
:
ret
=
_Blt_ColorFill
(
dbuf
,
dstwidth
,
dstheight
,
bpp
,
dlock
.
Pitch
,
~
0
);
break
;
case
SRCCOPY
:
/* well, we do that below ? */
break
;
default:
FIXME
(
"Unsupported raster op: %08x Pattern: %p
\n
"
,
DDBltFx
->
dwROP
,
DDBltFx
->
u5
.
lpDDSPattern
);
goto
error
;
}
Flags
&=
~
WINEDDBLT_ROP
;
}
if
(
Flags
&
WINEDDBLT_DDROPS
)
{
FIXME
(
"
\t
Ddraw Raster Ops: %08x Pattern: %p
\n
"
,
DDBltFx
->
dwDDROP
,
DDBltFx
->
u5
.
lpDDSPattern
);
}
/* Now the 'with source' blits */
if
(
Src
)
{
LPBYTE
sbase
;
int
sx
,
xinc
,
sy
,
yinc
;
if
(
!
dstwidth
||
!
dstheight
)
/* hmm... stupid program ? */
goto
release
;
sbase
=
(
BYTE
*
)
slock
.
pBits
+
(
xsrc
.
top
*
slock
.
Pitch
)
+
xsrc
.
left
*
bpp
;
xinc
=
(
srcwidth
<<
16
)
/
dstwidth
;
yinc
=
(
srcheight
<<
16
)
/
dstheight
;
if
(
!
Flags
)
{
/* No effects, we can cheat here */
if
(
dstwidth
==
srcwidth
)
{
if
(
dstheight
==
srcheight
)
{
/* No stretching in either direction. This needs to be as
* fast as possible */
sbuf
=
sbase
;
/* check for overlapping surfaces */
if
(
SrcSurface
!=
iface
||
xdst
.
top
<
xsrc
.
top
||
xdst
.
right
<=
xsrc
.
left
||
xsrc
.
right
<=
xdst
.
left
)
{
/* no overlap, or dst above src, so copy from top downwards */
for
(
y
=
0
;
y
<
dstheight
;
y
++
)
{
memcpy
(
dbuf
,
sbuf
,
width
);
sbuf
+=
slock
.
Pitch
;
dbuf
+=
dlock
.
Pitch
;
}
}
else
if
(
xdst
.
top
>
xsrc
.
top
)
/* copy from bottom upwards */
{
sbuf
+=
(
slock
.
Pitch
*
dstheight
);
dbuf
+=
(
dlock
.
Pitch
*
dstheight
);
for
(
y
=
0
;
y
<
dstheight
;
y
++
)
{
sbuf
-=
slock
.
Pitch
;
dbuf
-=
dlock
.
Pitch
;
memcpy
(
dbuf
,
sbuf
,
width
);
}
}
else
/* src and dst overlapping on the same line, use memmove */
{
for
(
y
=
0
;
y
<
dstheight
;
y
++
)
{
memmove
(
dbuf
,
sbuf
,
width
);
sbuf
+=
slock
.
Pitch
;
dbuf
+=
dlock
.
Pitch
;
}
}
}
else
{
/* Stretching in Y direction only */
for
(
y
=
sy
=
0
;
y
<
dstheight
;
y
++
,
sy
+=
yinc
)
{
sbuf
=
sbase
+
(
sy
>>
16
)
*
slock
.
Pitch
;
memcpy
(
dbuf
,
sbuf
,
width
);
dbuf
+=
dlock
.
Pitch
;
}
}
}
else
{
/* Stretching in X direction */
int
last_sy
=
-
1
;
for
(
y
=
sy
=
0
;
y
<
dstheight
;
y
++
,
sy
+=
yinc
)
{
sbuf
=
sbase
+
(
sy
>>
16
)
*
slock
.
Pitch
;
if
((
sy
>>
16
)
==
(
last_sy
>>
16
))
{
/* this sourcerow is the same as last sourcerow -
* copy already stretched row
*/
memcpy
(
dbuf
,
dbuf
-
dlock
.
Pitch
,
width
);
}
else
{
#define STRETCH_ROW(type) { \
type *s = (type *) sbuf, *d = (type *) dbuf; \
for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
d[x] = s[sx >> 16]; \
break; }
switch
(
bpp
)
{
case
1
:
STRETCH_ROW
(
BYTE
)
case
2
:
STRETCH_ROW
(
WORD
)
case
4
:
STRETCH_ROW
(
DWORD
)
case
3
:
{
LPBYTE
s
,
d
=
dbuf
;
for
(
x
=
sx
=
0
;
x
<
dstwidth
;
x
++
,
sx
+=
xinc
)
{
DWORD
pixel
;
s
=
sbuf
+
3
*
(
sx
>>
16
);
pixel
=
s
[
0
]
|
(
s
[
1
]
<<
8
)
|
(
s
[
2
]
<<
16
);
d
[
0
]
=
(
pixel
)
&
0xff
;
d
[
1
]
=
(
pixel
>>
8
)
&
0xff
;
d
[
2
]
=
(
pixel
>>
16
)
&
0xff
;
d
+=
3
;
}
break
;
}
default:
FIXME
(
"Stretched blit not implemented for bpp %d!
\n
"
,
bpp
*
8
);
ret
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
}
#undef STRETCH_ROW
}
dbuf
+=
dlock
.
Pitch
;
last_sy
=
sy
;
}
}
}
else
{
LONG
dstyinc
=
dlock
.
Pitch
,
dstxinc
=
bpp
;
DWORD
keylow
=
0xFFFFFFFF
,
keyhigh
=
0
,
keymask
=
0xFFFFFFFF
;
DWORD
destkeylow
=
0x0
,
destkeyhigh
=
0xFFFFFFFF
,
destkeymask
=
0xFFFFFFFF
;
if
(
Flags
&
(
WINEDDBLT_KEYSRC
|
WINEDDBLT_KEYDEST
|
WINEDDBLT_KEYSRCOVERRIDE
|
WINEDDBLT_KEYDESTOVERRIDE
))
{
/* The color keying flags are checked for correctness in ddraw */
if
(
Flags
&
WINEDDBLT_KEYSRC
)
{
keylow
=
Src
->
SrcBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
Src
->
SrcBltCKey
.
dwColorSpaceHighValue
;
}
else
if
(
Flags
&
WINEDDBLT_KEYSRCOVERRIDE
)
{
keylow
=
DDBltFx
->
ddckSrcColorkey
.
dwColorSpaceLowValue
;
keyhigh
=
DDBltFx
->
ddckSrcColorkey
.
dwColorSpaceHighValue
;
}
if
(
Flags
&
WINEDDBLT_KEYDEST
)
{
/* Destination color keys are taken from the source surface ! */
destkeylow
=
Src
->
DestBltCKey
.
dwColorSpaceLowValue
;
destkeyhigh
=
Src
->
DestBltCKey
.
dwColorSpaceHighValue
;
}
else
if
(
Flags
&
WINEDDBLT_KEYDESTOVERRIDE
)
{
destkeylow
=
DDBltFx
->
ddckDestColorkey
.
dwColorSpaceLowValue
;
destkeyhigh
=
DDBltFx
->
ddckDestColorkey
.
dwColorSpaceHighValue
;
}
if
(
bpp
==
1
)
{
keymask
=
0xff
;
}
else
{
keymask
=
sEntry
->
redMask
|
sEntry
->
greenMask
|
sEntry
->
blueMask
;
}
Flags
&=
~
(
WINEDDBLT_KEYSRC
|
WINEDDBLT_KEYDEST
|
WINEDDBLT_KEYSRCOVERRIDE
|
WINEDDBLT_KEYDESTOVERRIDE
);
}
if
(
Flags
&
WINEDDBLT_DDFX
)
{
LPBYTE
dTopLeft
,
dTopRight
,
dBottomLeft
,
dBottomRight
,
tmp
;
LONG
tmpxy
;
dTopLeft
=
dbuf
;
dTopRight
=
dbuf
+
((
dstwidth
-
1
)
*
bpp
);
dBottomLeft
=
dTopLeft
+
((
dstheight
-
1
)
*
dlock
.
Pitch
);
dBottomRight
=
dBottomLeft
+
((
dstwidth
-
1
)
*
bpp
);
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ARITHSTRETCHY
)
{
/* I don't think we need to do anything about this flag */
WARN
(
"Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY
\n
"
);
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_MIRRORLEFTRIGHT
)
{
tmp
=
dTopRight
;
dTopRight
=
dTopLeft
;
dTopLeft
=
tmp
;
tmp
=
dBottomRight
;
dBottomRight
=
dBottomLeft
;
dBottomLeft
=
tmp
;
dstxinc
=
dstxinc
*-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_MIRRORUPDOWN
)
{
tmp
=
dTopLeft
;
dTopLeft
=
dBottomLeft
;
dBottomLeft
=
tmp
;
tmp
=
dTopRight
;
dTopRight
=
dBottomRight
;
dBottomRight
=
tmp
;
dstyinc
=
dstyinc
*-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_NOTEARING
)
{
/* I don't think we need to do anything about this flag */
WARN
(
"Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING
\n
"
);
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ROTATE180
)
{
tmp
=
dBottomRight
;
dBottomRight
=
dTopLeft
;
dTopLeft
=
tmp
;
tmp
=
dBottomLeft
;
dBottomLeft
=
dTopRight
;
dTopRight
=
tmp
;
dstxinc
=
dstxinc
*
-
1
;
dstyinc
=
dstyinc
*
-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ROTATE270
)
{
tmp
=
dTopLeft
;
dTopLeft
=
dBottomLeft
;
dBottomLeft
=
dBottomRight
;
dBottomRight
=
dTopRight
;
dTopRight
=
tmp
;
tmpxy
=
dstxinc
;
dstxinc
=
dstyinc
;
dstyinc
=
tmpxy
;
dstxinc
=
dstxinc
*
-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ROTATE90
)
{
tmp
=
dTopLeft
;
dTopLeft
=
dTopRight
;
dTopRight
=
dBottomRight
;
dBottomRight
=
dBottomLeft
;
dBottomLeft
=
tmp
;
tmpxy
=
dstxinc
;
dstxinc
=
dstyinc
;
dstyinc
=
tmpxy
;
dstyinc
=
dstyinc
*
-
1
;
}
if
(
DDBltFx
->
dwDDFX
&
WINEDDBLTFX_ZBUFFERBASEDEST
)
{
/* I don't think we need to do anything about this flag */
WARN
(
"Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST
\n
"
);
}
dbuf
=
dTopLeft
;
Flags
&=
~
(
WINEDDBLT_DDFX
);
}
#define COPY_COLORKEY_FX(type) { \
type *s, *d = (type *) dbuf, *dx, tmp; \
for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
s = (type*)(sbase + (sy >> 16) * slock.Pitch); \
dx = d; \
for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
tmp = s[sx >> 16]; \
if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
dx[0] = tmp; \
} \
dx = (type*)(((LPBYTE)dx)+dstxinc); \
} \
d = (type*)(((LPBYTE)d)+dstyinc); \
} \
break; }
switch
(
bpp
)
{
case
1
:
COPY_COLORKEY_FX
(
BYTE
)
case
2
:
COPY_COLORKEY_FX
(
WORD
)
case
4
:
COPY_COLORKEY_FX
(
DWORD
)
case
3
:
{
LPBYTE
s
,
d
=
dbuf
,
dx
;
for
(
y
=
sy
=
0
;
y
<
dstheight
;
y
++
,
sy
+=
yinc
)
{
sbuf
=
sbase
+
(
sy
>>
16
)
*
slock
.
Pitch
;
dx
=
d
;
for
(
x
=
sx
=
0
;
x
<
dstwidth
;
x
++
,
sx
+=
xinc
)
{
DWORD
pixel
,
dpixel
=
0
;
s
=
sbuf
+
3
*
(
sx
>>
16
);
pixel
=
s
[
0
]
|
(
s
[
1
]
<<
8
)
|
(
s
[
2
]
<<
16
);
dpixel
=
dx
[
0
]
|
(
dx
[
1
]
<<
8
)
|
(
dx
[
2
]
<<
16
);
if
(((
pixel
&
keymask
)
<
keylow
||
(
pixel
&
keymask
)
>
keyhigh
)
&&
((
dpixel
&
keymask
)
>=
destkeylow
||
(
dpixel
&
keymask
)
<=
keyhigh
))
{
dx
[
0
]
=
(
pixel
)
&
0xff
;
dx
[
1
]
=
(
pixel
>>
8
)
&
0xff
;
dx
[
2
]
=
(
pixel
>>
16
)
&
0xff
;
}
dx
+=
dstxinc
;
}
d
+=
dstyinc
;
}
break
;
}
default:
FIXME
(
"%s color-keyed blit not implemented for bpp %d!
\n
"
,
(
Flags
&
WINEDDBLT_KEYSRC
)
?
"Source"
:
"Destination"
,
bpp
*
8
);
ret
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
#undef COPY_COLORKEY_FX
}
}
}
error:
if
(
Flags
&&
FIXME_ON
(
d3d_surface
))
{
FIXME
(
"
\t
Unsupported flags: %08x
\n
"
,
Flags
);
}
release:
IWineD3DSurface_UnlockRect
(
iface
);
if
(
SrcSurface
&&
SrcSurface
!=
iface
)
IWineD3DSurface_UnlockRect
(
SrcSurface
);
return
ret
;
}
/*****************************************************************************
* IWineD3DSurface::BltFast, GDI version
*
* This is the software implementation of BltFast, as used by GDI surfaces
* and as a fallback for OpenGL surfaces. This code is taken from the old
* DirectDraw code, and was originally written by TransGaming.
*
* Params:
* dstx:
* dsty:
* Source: Source surface to copy from
* rsrc: Source rectangle
* trans: Some Flags
*
* Returns:
* WINED3D_OK on success
*
*****************************************************************************/
HRESULT
WINAPI
IWineGDISurfaceImpl_BltFast
(
IWineD3DSurface
*
iface
,
DWORD
dstx
,
DWORD
dsty
,
IWineD3DSurface
*
Source
,
RECT
*
rsrc
,
DWORD
trans
)
{
IWineD3DSurfaceImpl
*
This
=
(
IWineD3DSurfaceImpl
*
)
iface
;
IWineD3DSurfaceImpl
*
Src
=
(
IWineD3DSurfaceImpl
*
)
Source
;
int
bpp
,
w
,
h
,
x
,
y
;
WINED3DLOCKED_RECT
dlock
,
slock
;
HRESULT
ret
=
WINED3D_OK
;
RECT
rsrc2
;
RECT
lock_src
,
lock_dst
,
lock_union
;
BYTE
*
sbuf
,
*
dbuf
;
const
StaticPixelFormatDesc
*
sEntry
,
*
dEntry
;
if
(
TRACE_ON
(
d3d_surface
))
{
TRACE
(
"(%p)->(%d,%d,%p,%p,%08x)
\n
"
,
This
,
dstx
,
dsty
,
Src
,
rsrc
,
trans
);
if
(
rsrc
)
{
TRACE
(
"
\t
srcrect: %dx%d-%dx%d
\n
"
,
rsrc
->
left
,
rsrc
->
top
,
rsrc
->
right
,
rsrc
->
bottom
);
}
else
{
TRACE
(
" srcrect: NULL
\n
"
);
}
}
if
((
This
->
Flags
&
SFLAG_LOCKED
)
||
((
Src
!=
NULL
)
&&
(
Src
->
Flags
&
SFLAG_LOCKED
)))
{
WARN
(
" Surface is busy, returning DDERR_SURFACEBUSY
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
if
(
!
rsrc
)
{
WARN
(
"rsrc is NULL!
\n
"
);
rsrc
=
&
rsrc2
;
rsrc
->
left
=
0
;
rsrc
->
top
=
0
;
rsrc
->
right
=
Src
->
currentDesc
.
Width
;
rsrc
->
bottom
=
Src
->
currentDesc
.
Height
;
}
/* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
if
((
rsrc
->
bottom
>
Src
->
currentDesc
.
Height
)
||
(
rsrc
->
bottom
<
0
)
||
(
rsrc
->
top
>
Src
->
currentDesc
.
Height
)
||
(
rsrc
->
top
<
0
)
||
(
rsrc
->
left
>
Src
->
currentDesc
.
Width
)
||
(
rsrc
->
left
<
0
)
||
(
rsrc
->
right
>
Src
->
currentDesc
.
Width
)
||
(
rsrc
->
right
<
0
)
||
(
rsrc
->
right
<
rsrc
->
left
)
||
(
rsrc
->
bottom
<
rsrc
->
top
))
{
WARN
(
"Application gave us bad source rectangle for BltFast.
\n
"
);
return
WINEDDERR_INVALIDRECT
;
}
h
=
rsrc
->
bottom
-
rsrc
->
top
;
if
(
h
>
This
->
currentDesc
.
Height
-
dsty
)
h
=
This
->
currentDesc
.
Height
-
dsty
;
if
(
h
>
Src
->
currentDesc
.
Height
-
rsrc
->
top
)
h
=
Src
->
currentDesc
.
Height
-
rsrc
->
top
;
if
(
h
<=
0
)
return
WINEDDERR_INVALIDRECT
;
w
=
rsrc
->
right
-
rsrc
->
left
;
if
(
w
>
This
->
currentDesc
.
Width
-
dstx
)
w
=
This
->
currentDesc
.
Width
-
dstx
;
if
(
w
>
Src
->
currentDesc
.
Width
-
rsrc
->
left
)
w
=
Src
->
currentDesc
.
Width
-
rsrc
->
left
;
if
(
w
<=
0
)
return
WINEDDERR_INVALIDRECT
;
/* Now compute the locking rectangle... */
lock_src
.
left
=
rsrc
->
left
;
lock_src
.
top
=
rsrc
->
top
;
lock_src
.
right
=
lock_src
.
left
+
w
;
lock_src
.
bottom
=
lock_src
.
top
+
h
;
lock_dst
.
left
=
dstx
;
lock_dst
.
top
=
dsty
;
lock_dst
.
right
=
dstx
+
w
;
lock_dst
.
bottom
=
dsty
+
h
;
bpp
=
This
->
bytesPerPixel
;
/* We need to lock the surfaces, or we won't get refreshes when done. */
if
(
Src
==
This
)
{
int
pitch
;
UnionRect
(
&
lock_union
,
&
lock_src
,
&
lock_dst
);
/* Lock the union of the two rectangles */
ret
=
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
&
lock_union
,
0
);
if
(
ret
!=
WINED3D_OK
)
goto
error
;
pitch
=
dlock
.
Pitch
;
slock
.
Pitch
=
dlock
.
Pitch
;
/* Since slock was originally copied from this surface's description, we can just reuse it */
assert
(
This
->
resource
.
allocatedMemory
!=
NULL
);
sbuf
=
(
BYTE
*
)
This
->
resource
.
allocatedMemory
+
lock_src
.
top
*
pitch
+
lock_src
.
left
*
bpp
;
dbuf
=
(
BYTE
*
)
This
->
resource
.
allocatedMemory
+
lock_dst
.
top
*
pitch
+
lock_dst
.
left
*
bpp
;
sEntry
=
getFormatDescEntry
(
Src
->
resource
.
format
,
NULL
,
NULL
);
dEntry
=
sEntry
;
}
else
{
ret
=
IWineD3DSurface_LockRect
(
Source
,
&
slock
,
&
lock_src
,
WINED3DLOCK_READONLY
);
if
(
ret
!=
WINED3D_OK
)
goto
error
;
ret
=
IWineD3DSurface_LockRect
(
iface
,
&
dlock
,
&
lock_dst
,
0
);
if
(
ret
!=
WINED3D_OK
)
goto
error
;
sbuf
=
slock
.
pBits
;
dbuf
=
dlock
.
pBits
;
TRACE
(
"Dst is at %p, Src is at %p
\n
"
,
dbuf
,
sbuf
);
sEntry
=
getFormatDescEntry
(
Src
->
resource
.
format
,
NULL
,
NULL
);
dEntry
=
getFormatDescEntry
(
This
->
resource
.
format
,
NULL
,
NULL
);
}
/* Handle first the FOURCC surfaces... */
if
(
sEntry
->
isFourcc
&&
dEntry
->
isFourcc
)
{
TRACE
(
"Fourcc -> Fourcc copy
\n
"
);
if
(
trans
)
FIXME
(
"trans arg not supported when a FOURCC surface is involved
\n
"
);
if
(
dstx
||
dsty
)
FIXME
(
"offset for destination surface is not supported
\n
"
);
if
(
Src
->
resource
.
format
!=
This
->
resource
.
format
)
{
FIXME
(
"FOURCC->FOURCC copy only supported for the same type of surface
\n
"
);
ret
=
WINED3DERR_WRONGTEXTUREFORMAT
;
goto
error
;
}
/* FIXME: Watch out that the size is correct for FOURCC surfaces */
memcpy
(
dbuf
,
sbuf
,
This
->
resource
.
size
);
goto
error
;
}
if
(
sEntry
->
isFourcc
&&
!
dEntry
->
isFourcc
)
{
/* TODO: Use the libtxc_dxtn.so shared library to do
* software decompression
*/
ERR
(
"DXTC decompression not supported by now
\n
"
);
goto
error
;
}
if
(
trans
&
(
WINEDDBLTFAST_SRCCOLORKEY
|
WINEDDBLTFAST_DESTCOLORKEY
))
{
DWORD
keylow
,
keyhigh
;
TRACE
(
"Color keyed copy
\n
"
);
if
(
trans
&
WINEDDBLTFAST_SRCCOLORKEY
)
{
keylow
=
Src
->
SrcBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
Src
->
SrcBltCKey
.
dwColorSpaceHighValue
;
}
else
{
/* I'm not sure if this is correct */
FIXME
(
"WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.
\n
"
);
keylow
=
This
->
DestBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
This
->
DestBltCKey
.
dwColorSpaceHighValue
;
}
#define COPYBOX_COLORKEY(type) { \
type *d, *s, tmp; \
s = (type *) sbuf; \
d = (type *) dbuf; \
for (y = 0; y < h; y++) { \
for (x = 0; x < w; x++) { \
tmp = s[x]; \
if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
} \
s = (type *)((BYTE *)s + slock.Pitch); \
d = (type *)((BYTE *)d + dlock.Pitch); \
} \
break; \
}
switch
(
bpp
)
{
case
1
:
COPYBOX_COLORKEY
(
BYTE
)
case
2
:
COPYBOX_COLORKEY
(
WORD
)
case
4
:
COPYBOX_COLORKEY
(
DWORD
)
case
3
:
{
BYTE
*
d
,
*
s
;
DWORD
tmp
;
s
=
(
BYTE
*
)
sbuf
;
d
=
(
BYTE
*
)
dbuf
;
for
(
y
=
0
;
y
<
h
;
y
++
)
{
for
(
x
=
0
;
x
<
w
*
3
;
x
+=
3
)
{
tmp
=
(
DWORD
)
s
[
x
]
+
((
DWORD
)
s
[
x
+
1
]
<<
8
)
+
((
DWORD
)
s
[
x
+
2
]
<<
16
);
if
(
tmp
<
keylow
||
tmp
>
keyhigh
)
{
d
[
x
+
0
]
=
s
[
x
+
0
];
d
[
x
+
1
]
=
s
[
x
+
1
];
d
[
x
+
2
]
=
s
[
x
+
2
];
}
}
s
+=
slock
.
Pitch
;
d
+=
dlock
.
Pitch
;
}
break
;
}
default:
FIXME
(
"Source color key blitting not supported for bpp %d
\n
"
,
bpp
*
8
);
ret
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
}
#undef COPYBOX_COLORKEY
TRACE
(
"Copy Done
\n
"
);
}
else
{
int
width
=
w
*
bpp
;
TRACE
(
"NO color key copy
\n
"
);
for
(
y
=
0
;
y
<
h
;
y
++
)
{
/* This is pretty easy, a line for line memcpy */
memcpy
(
dbuf
,
sbuf
,
width
);
sbuf
+=
slock
.
Pitch
;
dbuf
+=
dlock
.
Pitch
;
}
TRACE
(
"Copy done
\n
"
);
}
error:
if
(
Src
==
This
)
{
IWineD3DSurface_UnlockRect
(
iface
);
}
else
{
IWineD3DSurface_UnlockRect
(
iface
);
IWineD3DSurface_UnlockRect
(
Source
);
}
return
ret
;
}
/*****************************************************************************
* IWineD3DSurface::LoadTexture, GDI version
*
* This is mutually unsupported by GDI surfaces
...
...
@@ -1756,12 +801,12 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl =
IWineGDISurfaceImpl_GetDC
,
IWineGDISurfaceImpl_ReleaseDC
,
IWineGDISurfaceImpl_Flip
,
IWine
GDI
SurfaceImpl_Blt
,
IWine
D3DBase
SurfaceImpl_Blt
,
IWineD3DBaseSurfaceImpl_GetBltStatus
,
IWineD3DBaseSurfaceImpl_GetFlipStatus
,
IWineD3DBaseSurfaceImpl_IsLost
,
IWineD3DBaseSurfaceImpl_Restore
,
IWine
GDI
SurfaceImpl_BltFast
,
IWine
D3DBase
SurfaceImpl_BltFast
,
IWineD3DBaseSurfaceImpl_GetPalette
,
IWineD3DBaseSurfaceImpl_SetPalette
,
IWineD3DBaseSurfaceImpl_RealizePalette
,
...
...
dlls/wined3d/wined3d_private.h
View file @
46e2d795
...
...
@@ -1170,11 +1170,11 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_GetClipper
(
IWineD3DSurface
*
iface
,
IWineD3DClipper
**
clipper
);
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_SetFormat
(
IWineD3DSurface
*
iface
,
WINED3DFORMAT
format
);
HRESULT
IWineD3DBaseSurfaceImpl_CreateDIBSection
(
IWineD3DSurface
*
iface
);
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_Blt
(
IWineD3DSurface
*
iface
,
RECT
*
DestRect
,
IWineD3DSurface
*
SrcSurface
,
RECT
*
SrcRect
,
DWORD
Flags
,
WINEDDBLTFX
*
DDBltFx
,
WINED3DTEXTUREFILTERTYPE
Filter
);
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_BltFast
(
IWineD3DSurface
*
iface
,
DWORD
dstx
,
DWORD
dsty
,
IWineD3DSurface
*
Source
,
RECT
*
rsrc
,
DWORD
trans
);
const
void
*
WINAPI
IWineD3DSurfaceImpl_GetData
(
IWineD3DSurface
*
iface
);
HRESULT
WINAPI
IWineGDISurfaceImpl_Blt
(
IWineD3DSurface
*
iface
,
RECT
*
DestRect
,
IWineD3DSurface
*
SrcSurface
,
RECT
*
SrcRect
,
DWORD
Flags
,
WINEDDBLTFX
*
DDBltFx
,
WINED3DTEXTUREFILTERTYPE
Filter
);
HRESULT
WINAPI
IWineGDISurfaceImpl_BltFast
(
IWineD3DSurface
*
iface
,
DWORD
dstx
,
DWORD
dsty
,
IWineD3DSurface
*
Source
,
RECT
*
rsrc
,
DWORD
trans
);
/* Surface flags: */
#define SFLAG_OVERSIZE 0x00000001
/* Surface is bigger than gl size, blts only */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment