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
29c95df7
Commit
29c95df7
authored
Apr 29, 2011
by
Henri Verbeet
Committed by
Alexandre Julliard
Apr 29, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wined3d: Merge the IWineD3DSurface::BltFast() implementations.
parent
0b523df9
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
450 additions
and
421 deletions
+450
-421
surface.c
dlls/wined3d/surface.c
+448
-421
wined3d_private.h
dlls/wined3d/wined3d_private.h
+2
-0
No files found.
dlls/wined3d/surface.c
View file @
29c95df7
...
...
@@ -35,6 +35,12 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
d3d_surface
);
WINE_DECLARE_DEBUG_CHANNEL
(
d3d
);
static
HRESULT
surface_cpu_bltfast
(
IWineD3DSurfaceImpl
*
dst_surface
,
DWORD
dst_x
,
DWORD
dst_y
,
IWineD3DSurfaceImpl
*
src_surface
,
const
RECT
*
src_rect
,
DWORD
trans
);
static
HRESULT
IWineD3DSurfaceImpl_BltOverride
(
IWineD3DSurfaceImpl
*
dst_surface
,
const
RECT
*
dst_rect
,
IWineD3DSurfaceImpl
*
src_surface
,
const
RECT
*
src_rect
,
DWORD
flags
,
const
WINEDDBLTFX
*
fx
,
WINED3DTEXTUREFILTERTYPE
filter
);
static
void
surface_cleanup
(
IWineD3DSurfaceImpl
*
This
)
{
TRACE
(
"(%p) : Cleaning up.
\n
"
,
This
);
...
...
@@ -1062,6 +1068,61 @@ static HRESULT surface_flip(IWineD3DSurfaceImpl *surface, IWineD3DSurfaceImpl *o
return
WINED3D_OK
;
}
/* Do not call while under the GL lock. */
static
HRESULT
surface_bltfast
(
IWineD3DSurfaceImpl
*
dst_surface
,
DWORD
dst_x
,
DWORD
dst_y
,
IWineD3DSurfaceImpl
*
src_surface
,
const
RECT
*
src_rect_in
,
DWORD
trans
)
{
IWineD3DDeviceImpl
*
device
=
dst_surface
->
resource
.
device
;
TRACE
(
"dst_surface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.
\n
"
,
dst_surface
,
dst_x
,
dst_y
,
src_surface
,
wine_dbgstr_rect
(
src_rect_in
),
trans
);
if
((
dst_surface
->
flags
&
SFLAG_LOCKED
)
||
(
src_surface
->
flags
&
SFLAG_LOCKED
))
{
WARN
(
"Surface is busy, returning WINEDDERR_SURFACEBUSY.
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
if
(
device
->
inScene
&&
(
dst_surface
==
device
->
depth_stencil
||
src_surface
==
device
->
depth_stencil
))
{
WARN
(
"Attempt to access the depth / stencil surface while in a scene.
\n
"
);
return
WINED3DERR_INVALIDCALL
;
}
/* Special cases for RenderTargets */
if
((
dst_surface
->
resource
.
usage
&
WINED3DUSAGE_RENDERTARGET
)
||
(
src_surface
->
resource
.
usage
&
WINED3DUSAGE_RENDERTARGET
))
{
RECT
src_rect
,
dst_rect
;
DWORD
flags
=
0
;
surface_get_rect
(
src_surface
,
src_rect_in
,
&
src_rect
);
dst_rect
.
left
=
dst_x
;
dst_rect
.
top
=
dst_y
;
dst_rect
.
right
=
dst_x
+
src_rect
.
right
-
src_rect
.
left
;
dst_rect
.
bottom
=
dst_y
+
src_rect
.
bottom
-
src_rect
.
top
;
/* Convert BltFast flags into Blt ones because BltOverride is called
* from Blt as well. */
if
(
trans
&
WINEDDBLTFAST_SRCCOLORKEY
)
flags
|=
WINEDDBLT_KEYSRC
;
if
(
trans
&
WINEDDBLTFAST_DESTCOLORKEY
)
flags
|=
WINEDDBLT_KEYDEST
;
if
(
trans
&
WINEDDBLTFAST_WAIT
)
flags
|=
WINEDDBLT_WAIT
;
if
(
trans
&
WINEDDBLTFAST_DONOTWAIT
)
flags
|=
WINEDDBLT_DONOTWAIT
;
if
(
SUCCEEDED
(
IWineD3DSurfaceImpl_BltOverride
(
dst_surface
,
&
dst_rect
,
src_surface
,
&
src_rect
,
flags
,
NULL
,
WINED3DTEXF_POINT
)))
return
WINED3D_OK
;
}
return
surface_cpu_bltfast
(
dst_surface
,
dst_x
,
dst_y
,
src_surface
,
src_rect_in
,
trans
);
}
static
HRESULT
surface_set_mem
(
IWineD3DSurfaceImpl
*
surface
,
void
*
mem
)
{
TRACE
(
"surface %p, mem %p.
\n
"
,
surface
,
mem
);
...
...
@@ -1233,6 +1294,7 @@ static const struct wined3d_surface_ops surface_ops =
surface_unmap
,
surface_getdc
,
surface_flip
,
surface_bltfast
,
surface_set_mem
,
};
...
...
@@ -1416,6 +1478,15 @@ static HRESULT gdi_surface_flip(IWineD3DSurfaceImpl *surface, IWineD3DSurfaceImp
return
WINED3D_OK
;
}
static
HRESULT
gdi_surface_bltfast
(
IWineD3DSurfaceImpl
*
dst_surface
,
DWORD
dst_x
,
DWORD
dst_y
,
IWineD3DSurfaceImpl
*
src_surface
,
const
RECT
*
src_rect
,
DWORD
trans
)
{
TRACE
(
"dst_surface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.
\n
"
,
dst_surface
,
dst_x
,
dst_y
,
src_surface
,
wine_dbgstr_rect
(
src_rect
),
trans
);
return
surface_cpu_bltfast
(
dst_surface
,
dst_x
,
dst_y
,
src_surface
,
src_rect
,
trans
);
}
static
HRESULT
gdi_surface_set_mem
(
IWineD3DSurfaceImpl
*
surface
,
void
*
mem
)
{
TRACE
(
"surface %p, mem %p.
\n
"
,
surface
,
mem
);
...
...
@@ -1474,6 +1545,7 @@ static const struct wined3d_surface_ops gdi_surface_ops =
gdi_surface_unmap
,
gdi_surface_getdc
,
gdi_surface_flip
,
gdi_surface_bltfast
,
gdi_surface_set_mem
,
};
...
...
@@ -3715,410 +3787,149 @@ release:
return
ret
;
}
/* Do not call while under the GL lock. */
static
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_BltFast
(
IWineD3DSurface
*
iface
,
DWORD
dst
x
,
DWORD
dsty
,
IWineD3DSurface
*
src_surface
,
const
RECT
*
rsrc
,
DWORD
trans
)
DWORD
dst
_x
,
DWORD
dst_y
,
IWineD3DSurface
*
src_surface
,
const
RECT
*
src_rect
,
DWORD
trans
)
{
IWineD3DSurfaceImpl
*
dst_surface
=
(
IWineD3DSurfaceImpl
*
)
iface
;
IWineD3DSurfaceImpl
*
src
=
(
IWineD3DSurfaceImpl
*
)
src_surface
;
const
struct
wined3d_format
*
src_format
,
*
dst_format
;
RECT
lock_src
,
lock_dst
,
lock_union
;
WINED3DLOCKED_RECT
dlock
,
slock
;
HRESULT
ret
=
WINED3D_OK
;
int
bpp
,
w
,
h
,
x
,
y
;
const
BYTE
*
sbuf
;
BYTE
*
dbuf
;
RECT
rsrc2
;
TRACE
(
"iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s,
flag
s %#x.
\n
"
,
iface
,
dst
x
,
dsty
,
src_surface
,
wine_dbgstr_rect
(
rsrc
),
trans
);
TRACE
(
"iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s,
tran
s %#x.
\n
"
,
iface
,
dst
_x
,
dst_y
,
src_surface
,
wine_dbgstr_rect
(
src_rect
),
trans
);
if
((
dst_surface
->
flags
&
SFLAG_LOCKED
)
||
(
src
->
flags
&
SFLAG_LOCKED
))
{
WARN
(
" Surface is busy, returning DDERR_SURFACEBUSY
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
return
dst_surface
->
surface_ops
->
surface_bltfast
(
dst_surface
,
dst_x
,
dst_y
,
(
IWineD3DSurfaceImpl
*
)
src_surface
,
src_rect
,
trans
);
}
if
(
!
rsrc
)
{
WARN
(
"rsrc is NULL!
\n
"
);
rsrc2
.
left
=
0
;
rsrc2
.
top
=
0
;
rsrc2
.
right
=
src
->
resource
.
width
;
rsrc2
.
bottom
=
src
->
resource
.
height
;
rsrc
=
&
rsrc2
;
}
static
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_Unmap
(
IWineD3DSurface
*
iface
)
{
IWineD3DSurfaceImpl
*
surface
=
(
IWineD3DSurfaceImpl
*
)
iface
;
/* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate. */
if
((
rsrc
->
bottom
>
src
->
resource
.
height
)
||
(
rsrc
->
bottom
<
0
)
||
(
rsrc
->
top
>
src
->
resource
.
height
)
||
(
rsrc
->
top
<
0
)
||
(
rsrc
->
left
>
src
->
resource
.
width
)
||
(
rsrc
->
left
<
0
)
||
(
rsrc
->
right
>
src
->
resource
.
width
)
||
(
rsrc
->
right
<
0
)
||
(
rsrc
->
right
<
rsrc
->
left
)
||
(
rsrc
->
bottom
<
rsrc
->
top
))
TRACE
(
"iface %p.
\n
"
,
iface
);
if
(
!
(
surface
->
flags
&
SFLAG_LOCKED
))
{
WARN
(
"
Application gave us bad source rectangle for BltFast
.
\n
"
);
return
WINEDDERR_
INVALIDRECT
;
WARN
(
"
Trying to unmap unmapped surface
.
\n
"
);
return
WINEDDERR_
NOTLOCKED
;
}
surface
->
flags
&=
~
SFLAG_LOCKED
;
h
=
rsrc
->
bottom
-
rsrc
->
top
;
if
(
h
>
dst_surface
->
resource
.
height
-
dsty
)
h
=
dst_surface
->
resource
.
height
-
dsty
;
if
(
h
>
src
->
resource
.
height
-
rsrc
->
top
)
h
=
src
->
resource
.
height
-
rsrc
->
top
;
if
(
h
<=
0
)
return
WINEDDERR_INVALIDRECT
;
w
=
rsrc
->
right
-
rsrc
->
left
;
if
(
w
>
dst_surface
->
resource
.
width
-
dstx
)
w
=
dst_surface
->
resource
.
width
-
dstx
;
if
(
w
>
src
->
resource
.
width
-
rsrc
->
left
)
w
=
src
->
resource
.
width
-
rsrc
->
left
;
if
(
w
<=
0
)
return
WINEDDERR_INVALIDRECT
;
surface
->
surface_ops
->
surface_unmap
(
surface
);
/* 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
;
return
WINED3D_OK
;
}
lock_dst
.
left
=
dstx
;
lock_dst
.
top
=
dsty
;
lock_dst
.
right
=
dstx
+
w
;
lock_dst
.
bottom
=
dsty
+
h
;
static
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_Map
(
IWineD3DSurface
*
iface
,
WINED3DLOCKED_RECT
*
locked_rect
,
const
RECT
*
rect
,
DWORD
flags
)
{
IWineD3DSurfaceImpl
*
surface
=
(
IWineD3DSurfaceImpl
*
)
iface
;
bpp
=
dst_surface
->
resource
.
format
->
byte_count
;
TRACE
(
"iface %p, locked_rect %p, rect %s, flags %#x.
\n
"
,
iface
,
locked_rect
,
wine_dbgstr_rect
(
rect
),
flags
);
/* We need to lock the surfaces, or we won't get refreshes when done. */
if
(
src
==
dst_surface
)
if
(
surface
->
flags
&
SFLAG_LOCKED
)
{
int
pitch
;
WARN
(
"Surface is already mapped.
\n
"
);
return
WINED3DERR_INVALIDCALL
;
}
surface
->
flags
|=
SFLAG_LOCKED
;
UnionRect
(
&
lock_union
,
&
lock_src
,
&
lock_dst
);
if
(
!
(
surface
->
flags
&
SFLAG_LOCKABLE
))
WARN
(
"Trying to lock unlockable surface.
\n
"
);
/* Lock the union of the two rectangles */
ret
=
IWineD3DSurface_Map
(
iface
,
&
dlock
,
&
lock_union
,
0
);
if
(
FAILED
(
ret
))
goto
error
;
surface
->
surface_ops
->
surface_map
(
surface
,
rect
,
flags
);
pitch
=
dlock
.
Pitch
;
slock
.
Pitch
=
dlock
.
Pitch
;
locked_rect
->
Pitch
=
IWineD3DSurface_GetPitch
(
iface
);
/* Since slock was originally copied from this surface's description, we can just reuse it. */
sbuf
=
dst_surface
->
resource
.
allocatedMemory
+
lock_src
.
top
*
pitch
+
lock_src
.
left
*
bpp
;
dbuf
=
dst_surface
->
resource
.
allocatedMemory
+
lock_dst
.
top
*
pitch
+
lock_dst
.
left
*
bpp
;
src_format
=
src
->
resource
.
format
;
dst_format
=
src_format
;
}
else
if
(
!
rect
)
{
ret
=
IWineD3DSurface_Map
(
src_surface
,
&
slock
,
&
lock_src
,
WINED3DLOCK_READONLY
);
if
(
FAILED
(
ret
))
goto
error
;
ret
=
IWineD3DSurface_Map
(
iface
,
&
dlock
,
&
lock_dst
,
0
);
if
(
FAILED
(
ret
))
goto
error
;
sbuf
=
slock
.
pBits
;
dbuf
=
dlock
.
pBits
;
TRACE
(
"Dst is at %p, Src is at %p.
\n
"
,
dbuf
,
sbuf
);
src_format
=
src
->
resource
.
format
;
dst_format
=
dst_surface
->
resource
.
format
;
locked_rect
->
pBits
=
surface
->
resource
.
allocatedMemory
;
surface
->
lockedRect
.
left
=
0
;
surface
->
lockedRect
.
top
=
0
;
surface
->
lockedRect
.
right
=
surface
->
resource
.
width
;
surface
->
lockedRect
.
bottom
=
surface
->
resource
.
height
;
}
/* Handle compressed surfaces first... */
if
(
src_format
->
flags
&
dst_format
->
flags
&
WINED3DFMT_FLAG_COMPRESSED
)
else
{
UINT
row_block_coun
t
;
const
struct
wined3d_format
*
format
=
surface
->
resource
.
forma
t
;
TRACE
(
"compressed -> compressed copy
\n
"
);
if
(
trans
)
FIXME
(
"trans arg not supported when a compressed surface is involved
\n
"
);
if
(
dstx
||
dsty
)
FIXME
(
"offset for destination surface is not supported
\n
"
);
if
(
src
->
resource
.
format
->
id
!=
dst_surface
->
resource
.
format
->
id
)
if
((
format
->
flags
&
(
WINED3DFMT_FLAG_COMPRESSED
|
WINED3DFMT_FLAG_BROKEN_PITCH
))
==
WINED3DFMT_FLAG_COMPRESSED
)
{
FIXME
(
"compressed -> compressed copy only supported for the same type of surface
\n
"
);
ret
=
WINED3DERR_WRONGTEXTUREFORMAT
;
goto
error
;
/* Compressed textures are block based, so calculate the offset of
* the block that contains the top-left pixel of the locked rectangle. */
locked_rect
->
pBits
=
surface
->
resource
.
allocatedMemory
+
((
rect
->
top
/
format
->
block_height
)
*
locked_rect
->
Pitch
)
+
((
rect
->
left
/
format
->
block_width
)
*
format
->
block_byte_count
);
}
row_block_count
=
(
w
+
dst_format
->
block_width
-
1
)
/
dst_format
->
block_width
;
for
(
y
=
0
;
y
<
h
;
y
+=
dst_format
->
block_height
)
else
{
memcpy
(
dbuf
,
sbuf
,
row_block_count
*
dst_format
->
block_byte_count
);
dbuf
+=
dlock
.
Pitch
;
sbuf
+=
slock
.
Pitch
;
locked_rect
->
pBits
=
surface
->
resource
.
allocatedMemory
+
(
locked_rect
->
Pitch
*
rect
->
top
)
+
(
rect
->
left
*
format
->
byte_count
)
;
}
goto
error
;
surface
->
lockedRect
.
left
=
rect
->
left
;
surface
->
lockedRect
.
top
=
rect
->
top
;
surface
->
lockedRect
.
right
=
rect
->
right
;
surface
->
lockedRect
.
bottom
=
rect
->
bottom
;
}
if
((
src_format
->
flags
&
WINED3DFMT_FLAG_COMPRESSED
)
&&
!
(
dst_format
->
flags
&
WINED3DFMT_FLAG_COMPRESSED
))
TRACE
(
"Locked rect %s.
\n
"
,
wine_dbgstr_rect
(
&
surface
->
lockedRect
));
TRACE
(
"Returning memory %p, pitch %u.
\n
"
,
locked_rect
->
pBits
,
locked_rect
->
Pitch
);
return
WINED3D_OK
;
}
static
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_GetDC
(
IWineD3DSurface
*
iface
,
HDC
*
dc
)
{
IWineD3DSurfaceImpl
*
surface
=
(
IWineD3DSurfaceImpl
*
)
iface
;
HRESULT
hr
;
TRACE
(
"iface %p, dc %p.
\n
"
,
iface
,
dc
);
if
(
surface
->
flags
&
SFLAG_USERPTR
)
{
/* TODO: Use the libtxc_dxtn.so shared library to do software
* decompression. */
ERR
(
"Software decompression not supported.
\n
"
);
goto
error
;
ERR
(
"Not supported on surfaces with application-provided memory.
\n
"
);
return
WINEDDERR_NODC
;
}
if
(
trans
&
(
WINEDDBLTFAST_SRCCOLORKEY
|
WINEDDBLTFAST_DESTCOLORKEY
))
{
DWORD
keylow
,
keyhigh
;
DWORD
mask
=
src
->
resource
.
format
->
red_mask
|
src
->
resource
.
format
->
green_mask
|
src
->
resource
.
format
->
blue_mask
;
/* Give more detailed info for ddraw. */
if
(
surface
->
flags
&
SFLAG_DCINUSE
)
return
WINEDDERR_DCALREADYCREATED
;
/* For some 8-bit formats like L8 and P8 color masks don't make sense
*/
if
(
!
mask
&&
bpp
==
1
)
mask
=
0xff
;
/* Can't GetDC if the surface is locked.
*/
if
(
surface
->
flags
&
SFLAG_LOCKED
)
return
WINED3DERR_INVALIDCALL
;
TRACE
(
"Color keyed copy.
\n
"
);
if
(
trans
&
WINEDDBLTFAST_SRCCOLORKEY
)
hr
=
surface
->
surface_ops
->
surface_getdc
(
surface
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
surface
->
resource
.
format
->
id
==
WINED3DFMT_P8_UINT
||
surface
->
resource
.
format
->
id
==
WINED3DFMT_P8_UINT_A8_UNORM
)
{
/* GetDC on palettized formats is unsupported in D3D9, and the method
* is missing in D3D8, so this should only be used for DX <=7
* surfaces (with non-device palettes). */
const
PALETTEENTRY
*
pal
=
NULL
;
if
(
surface
->
palette
)
{
keylow
=
src
->
SrcBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
src
->
SrcBltCKey
.
dwColorSpaceHighValue
;
pal
=
surface
->
palette
->
palents
;
}
else
{
/* I'm not sure if this is correct. */
FIXME
(
"WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.
\n
"
);
keylow
=
dst_surface
->
DestBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
dst_surface
->
DestBltCKey
.
dwColorSpaceHighValue
;
}
struct
wined3d_swapchain
*
swapchain
=
surface
->
resource
.
device
->
swapchains
[
0
];
IWineD3DSurfaceImpl
*
dds_primary
=
swapchain
->
front_buffer
;
#define COPYBOX_COLORKEY(type) \
do { \
const type *s = (const type *)sbuf; \
type *d = (type *)dbuf; \
type tmp; \
for (y = 0; y < h; y++) \
{ \
for (x = 0; x < w; x++) \
{ \
tmp = s[x]; \
if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \
} \
s = (const type *)((const BYTE *)s + slock.Pitch); \
d = (type *)((BYTE *)d + dlock.Pitch); \
} \
} while(0)
if
(
dds_primary
&&
dds_primary
->
palette
)
pal
=
dds_primary
->
palette
->
palents
;
}
switch
(
bpp
)
if
(
pal
)
{
case
1
:
COPYBOX_COLORKEY
(
BYTE
);
break
;
case
2
:
COPYBOX_COLORKEY
(
WORD
);
break
;
case
4
:
COPYBOX_COLORKEY
(
DWORD
);
break
;
case
3
:
{
const
BYTE
*
s
;
DWORD
tmp
;
BYTE
*
d
;
s
=
sbuf
;
d
=
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 %u.
\n
"
,
bpp
*
8
);
ret
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
}
#undef COPYBOX_COLORKEY
TRACE
(
"Copy done.
\n
"
);
}
else
{
int
width
=
w
*
bpp
;
INT
sbufpitch
,
dbufpitch
;
TRACE
(
"No color key copy.
\n
"
);
/* Handle overlapping surfaces. */
if
(
sbuf
<
dbuf
)
{
sbuf
+=
(
h
-
1
)
*
slock
.
Pitch
;
dbuf
+=
(
h
-
1
)
*
dlock
.
Pitch
;
sbufpitch
=
-
slock
.
Pitch
;
dbufpitch
=
-
dlock
.
Pitch
;
}
else
{
sbufpitch
=
slock
.
Pitch
;
dbufpitch
=
dlock
.
Pitch
;
}
for
(
y
=
0
;
y
<
h
;
++
y
)
{
/* This is pretty easy, a line for line memcpy. */
memmove
(
dbuf
,
sbuf
,
width
);
sbuf
+=
sbufpitch
;
dbuf
+=
dbufpitch
;
}
TRACE
(
"Copy done.
\n
"
);
}
error:
if
(
src
==
dst_surface
)
{
IWineD3DSurface_Unmap
(
iface
);
}
else
{
IWineD3DSurface_Unmap
(
iface
);
IWineD3DSurface_Unmap
(
src_surface
);
}
return
ret
;
}
static
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_Unmap
(
IWineD3DSurface
*
iface
)
{
IWineD3DSurfaceImpl
*
surface
=
(
IWineD3DSurfaceImpl
*
)
iface
;
TRACE
(
"iface %p.
\n
"
,
iface
);
if
(
!
(
surface
->
flags
&
SFLAG_LOCKED
))
{
WARN
(
"Trying to unmap unmapped surface.
\n
"
);
return
WINEDDERR_NOTLOCKED
;
}
surface
->
flags
&=
~
SFLAG_LOCKED
;
surface
->
surface_ops
->
surface_unmap
(
surface
);
return
WINED3D_OK
;
}
static
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_Map
(
IWineD3DSurface
*
iface
,
WINED3DLOCKED_RECT
*
locked_rect
,
const
RECT
*
rect
,
DWORD
flags
)
{
IWineD3DSurfaceImpl
*
surface
=
(
IWineD3DSurfaceImpl
*
)
iface
;
TRACE
(
"iface %p, locked_rect %p, rect %s, flags %#x.
\n
"
,
iface
,
locked_rect
,
wine_dbgstr_rect
(
rect
),
flags
);
if
(
surface
->
flags
&
SFLAG_LOCKED
)
{
WARN
(
"Surface is already mapped.
\n
"
);
return
WINED3DERR_INVALIDCALL
;
}
surface
->
flags
|=
SFLAG_LOCKED
;
if
(
!
(
surface
->
flags
&
SFLAG_LOCKABLE
))
WARN
(
"Trying to lock unlockable surface.
\n
"
);
surface
->
surface_ops
->
surface_map
(
surface
,
rect
,
flags
);
locked_rect
->
Pitch
=
IWineD3DSurface_GetPitch
(
iface
);
if
(
!
rect
)
{
locked_rect
->
pBits
=
surface
->
resource
.
allocatedMemory
;
surface
->
lockedRect
.
left
=
0
;
surface
->
lockedRect
.
top
=
0
;
surface
->
lockedRect
.
right
=
surface
->
resource
.
width
;
surface
->
lockedRect
.
bottom
=
surface
->
resource
.
height
;
}
else
{
const
struct
wined3d_format
*
format
=
surface
->
resource
.
format
;
if
((
format
->
flags
&
(
WINED3DFMT_FLAG_COMPRESSED
|
WINED3DFMT_FLAG_BROKEN_PITCH
))
==
WINED3DFMT_FLAG_COMPRESSED
)
{
/* Compressed textures are block based, so calculate the offset of
* the block that contains the top-left pixel of the locked rectangle. */
locked_rect
->
pBits
=
surface
->
resource
.
allocatedMemory
+
((
rect
->
top
/
format
->
block_height
)
*
locked_rect
->
Pitch
)
+
((
rect
->
left
/
format
->
block_width
)
*
format
->
block_byte_count
);
}
else
{
locked_rect
->
pBits
=
surface
->
resource
.
allocatedMemory
+
(
locked_rect
->
Pitch
*
rect
->
top
)
+
(
rect
->
left
*
format
->
byte_count
);
}
surface
->
lockedRect
.
left
=
rect
->
left
;
surface
->
lockedRect
.
top
=
rect
->
top
;
surface
->
lockedRect
.
right
=
rect
->
right
;
surface
->
lockedRect
.
bottom
=
rect
->
bottom
;
}
TRACE
(
"Locked rect %s.
\n
"
,
wine_dbgstr_rect
(
&
surface
->
lockedRect
));
TRACE
(
"Returning memory %p, pitch %u.
\n
"
,
locked_rect
->
pBits
,
locked_rect
->
Pitch
);
return
WINED3D_OK
;
}
static
HRESULT
WINAPI
IWineD3DBaseSurfaceImpl_GetDC
(
IWineD3DSurface
*
iface
,
HDC
*
dc
)
{
IWineD3DSurfaceImpl
*
surface
=
(
IWineD3DSurfaceImpl
*
)
iface
;
HRESULT
hr
;
TRACE
(
"iface %p, dc %p.
\n
"
,
iface
,
dc
);
if
(
surface
->
flags
&
SFLAG_USERPTR
)
{
ERR
(
"Not supported on surfaces with application-provided memory.
\n
"
);
return
WINEDDERR_NODC
;
}
/* Give more detailed info for ddraw. */
if
(
surface
->
flags
&
SFLAG_DCINUSE
)
return
WINEDDERR_DCALREADYCREATED
;
/* Can't GetDC if the surface is locked. */
if
(
surface
->
flags
&
SFLAG_LOCKED
)
return
WINED3DERR_INVALIDCALL
;
hr
=
surface
->
surface_ops
->
surface_getdc
(
surface
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
surface
->
resource
.
format
->
id
==
WINED3DFMT_P8_UINT
||
surface
->
resource
.
format
->
id
==
WINED3DFMT_P8_UINT_A8_UNORM
)
{
/* GetDC on palettized formats is unsupported in D3D9, and the method
* is missing in D3D8, so this should only be used for DX <=7
* surfaces (with non-device palettes). */
const
PALETTEENTRY
*
pal
=
NULL
;
if
(
surface
->
palette
)
{
pal
=
surface
->
palette
->
palents
;
}
else
{
struct
wined3d_swapchain
*
swapchain
=
surface
->
resource
.
device
->
swapchains
[
0
];
IWineD3DSurfaceImpl
*
dds_primary
=
swapchain
->
front_buffer
;
if
(
dds_primary
&&
dds_primary
->
palette
)
pal
=
dds_primary
->
palette
->
palents
;
}
if
(
pal
)
{
RGBQUAD
col
[
256
];
unsigned
int
i
;
for
(
i
=
0
;
i
<
256
;
++
i
)
RGBQUAD
col
[
256
];
unsigned
int
i
;
for
(
i
=
0
;
i
<
256
;
++
i
)
{
col
[
i
].
rgbRed
=
pal
[
i
].
peRed
;
col
[
i
].
rgbGreen
=
pal
[
i
].
peGreen
;
...
...
@@ -5894,7 +5705,6 @@ HRESULT surface_color_fill(IWineD3DSurfaceImpl *s, const RECT *rect, const WINED
return
blitter
->
color_fill
(
device
,
s
,
rect
,
color
);
}
/* Not called from the VTable */
/* Do not call while under the GL lock. */
static
HRESULT
IWineD3DSurfaceImpl_BltOverride
(
IWineD3DSurfaceImpl
*
dst_surface
,
const
RECT
*
DestRect
,
IWineD3DSurfaceImpl
*
src_surface
,
const
RECT
*
SrcRect
,
DWORD
flags
,
const
WINEDDBLTFX
*
DDBltFx
,
...
...
@@ -6385,61 +6195,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT
return
IWineD3DBaseSurfaceImpl_Blt
(
iface
,
DestRect
,
src_surface
,
SrcRect
,
flags
,
DDBltFx
,
Filter
);
}
static
HRESULT
WINAPI
IWineD3DSurfaceImpl_BltFast
(
IWineD3DSurface
*
iface
,
DWORD
dstx
,
DWORD
dsty
,
IWineD3DSurface
*
src_surface
,
const
RECT
*
rsrc
,
DWORD
trans
)
{
IWineD3DSurfaceImpl
*
This
=
(
IWineD3DSurfaceImpl
*
)
iface
;
IWineD3DSurfaceImpl
*
src
=
(
IWineD3DSurfaceImpl
*
)
src_surface
;
IWineD3DDeviceImpl
*
device
=
This
->
resource
.
device
;
TRACE
(
"iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.
\n
"
,
iface
,
dstx
,
dsty
,
src_surface
,
wine_dbgstr_rect
(
rsrc
),
trans
);
if
((
This
->
flags
&
SFLAG_LOCKED
)
||
(
src
->
flags
&
SFLAG_LOCKED
))
{
WARN
(
" Surface is busy, returning DDERR_SURFACEBUSY
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
if
(
device
->
inScene
&&
(
This
==
device
->
depth_stencil
||
src
==
device
->
depth_stencil
))
{
TRACE
(
"Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL
\n
"
);
return
WINED3DERR_INVALIDCALL
;
}
/* Special cases for RenderTargets */
if
((
This
->
resource
.
usage
&
WINED3DUSAGE_RENDERTARGET
)
||
(
src
->
resource
.
usage
&
WINED3DUSAGE_RENDERTARGET
))
{
RECT
SrcRect
,
DstRect
;
DWORD
flags
=
0
;
surface_get_rect
(
src
,
rsrc
,
&
SrcRect
);
DstRect
.
left
=
dstx
;
DstRect
.
top
=
dsty
;
DstRect
.
right
=
dstx
+
SrcRect
.
right
-
SrcRect
.
left
;
DstRect
.
bottom
=
dsty
+
SrcRect
.
bottom
-
SrcRect
.
top
;
/* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
if
(
trans
&
WINEDDBLTFAST_SRCCOLORKEY
)
flags
|=
WINEDDBLT_KEYSRC
;
if
(
trans
&
WINEDDBLTFAST_DESTCOLORKEY
)
flags
|=
WINEDDBLT_KEYDEST
;
if
(
trans
&
WINEDDBLTFAST_WAIT
)
flags
|=
WINEDDBLT_WAIT
;
if
(
trans
&
WINEDDBLTFAST_DONOTWAIT
)
flags
|=
WINEDDBLT_DONOTWAIT
;
if
(
SUCCEEDED
(
IWineD3DSurfaceImpl_BltOverride
(
This
,
&
DstRect
,
src
,
&
SrcRect
,
flags
,
NULL
,
WINED3DTEXF_POINT
)))
return
WINED3D_OK
;
}
return
IWineD3DBaseSurfaceImpl_BltFast
(
iface
,
dstx
,
dsty
,
src_surface
,
rsrc
,
trans
);
}
/* GL locking is done by the caller */
static
void
surface_depth_blt
(
IWineD3DSurfaceImpl
*
This
,
const
struct
wined3d_gl_info
*
gl_info
,
GLuint
texture
,
GLsizei
w
,
GLsizei
h
,
GLenum
target
)
...
...
@@ -7101,7 +6856,7 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
IWineD3DBaseSurfaceImpl_GetFlipStatus
,
IWineD3DBaseSurfaceImpl_IsLost
,
IWineD3DBaseSurfaceImpl_Restore
,
IWineD3DSurfaceImpl_BltFast
,
IWineD3D
Base
SurfaceImpl_BltFast
,
IWineD3DBaseSurfaceImpl_GetPalette
,
IWineD3DBaseSurfaceImpl_SetPalette
,
IWineD3DBaseSurfaceImpl_SetColorKey
,
...
...
@@ -7292,6 +7047,278 @@ static BOOL cpu_blit_supported(const struct wined3d_gl_info *gl_info, enum wined
return
FALSE
;
}
static
HRESULT
surface_cpu_bltfast
(
IWineD3DSurfaceImpl
*
dst_surface
,
DWORD
dst_x
,
DWORD
dst_y
,
IWineD3DSurfaceImpl
*
src_surface
,
const
RECT
*
src_rect
,
DWORD
trans
)
{
const
struct
wined3d_format
*
src_format
,
*
dst_format
;
RECT
lock_src
,
lock_dst
,
lock_union
;
WINED3DLOCKED_RECT
dlock
,
slock
;
HRESULT
hr
=
WINED3D_OK
;
int
bpp
,
w
,
h
,
x
,
y
;
const
BYTE
*
sbuf
;
BYTE
*
dbuf
;
RECT
rsrc2
;
TRACE
(
"dst_surface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.
\n
"
,
dst_surface
,
dst_x
,
dst_y
,
src_surface
,
wine_dbgstr_rect
(
src_rect
),
trans
);
if
((
dst_surface
->
flags
&
SFLAG_LOCKED
)
||
(
src_surface
->
flags
&
SFLAG_LOCKED
))
{
WARN
(
" Surface is busy, returning DDERR_SURFACEBUSY
\n
"
);
return
WINEDDERR_SURFACEBUSY
;
}
if
(
!
src_rect
)
{
WARN
(
"src_rect is NULL!
\n
"
);
rsrc2
.
left
=
0
;
rsrc2
.
top
=
0
;
rsrc2
.
right
=
src_surface
->
resource
.
width
;
rsrc2
.
bottom
=
src_surface
->
resource
.
height
;
src_rect
=
&
rsrc2
;
}
/* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate. */
if
((
src_rect
->
bottom
>
src_surface
->
resource
.
height
)
||
(
src_rect
->
bottom
<
0
)
||
(
src_rect
->
top
>
src_surface
->
resource
.
height
)
||
(
src_rect
->
top
<
0
)
||
(
src_rect
->
left
>
src_surface
->
resource
.
width
)
||
(
src_rect
->
left
<
0
)
||
(
src_rect
->
right
>
src_surface
->
resource
.
width
)
||
(
src_rect
->
right
<
0
)
||
(
src_rect
->
right
<
src_rect
->
left
)
||
(
src_rect
->
bottom
<
src_rect
->
top
))
{
WARN
(
"Application gave us bad source rectangle for BltFast.
\n
"
);
return
WINEDDERR_INVALIDRECT
;
}
h
=
src_rect
->
bottom
-
src_rect
->
top
;
if
(
h
>
dst_surface
->
resource
.
height
-
dst_y
)
h
=
dst_surface
->
resource
.
height
-
dst_y
;
if
(
h
>
src_surface
->
resource
.
height
-
src_rect
->
top
)
h
=
src_surface
->
resource
.
height
-
src_rect
->
top
;
if
(
h
<=
0
)
return
WINEDDERR_INVALIDRECT
;
w
=
src_rect
->
right
-
src_rect
->
left
;
if
(
w
>
dst_surface
->
resource
.
width
-
dst_x
)
w
=
dst_surface
->
resource
.
width
-
dst_x
;
if
(
w
>
src_surface
->
resource
.
width
-
src_rect
->
left
)
w
=
src_surface
->
resource
.
width
-
src_rect
->
left
;
if
(
w
<=
0
)
return
WINEDDERR_INVALIDRECT
;
/* Now compute the locking rectangle... */
lock_src
.
left
=
src_rect
->
left
;
lock_src
.
top
=
src_rect
->
top
;
lock_src
.
right
=
lock_src
.
left
+
w
;
lock_src
.
bottom
=
lock_src
.
top
+
h
;
lock_dst
.
left
=
dst_x
;
lock_dst
.
top
=
dst_y
;
lock_dst
.
right
=
dst_x
+
w
;
lock_dst
.
bottom
=
dst_y
+
h
;
bpp
=
dst_surface
->
resource
.
format
->
byte_count
;
/* We need to lock the surfaces, or we won't get refreshes when done. */
if
(
src_surface
==
dst_surface
)
{
int
pitch
;
UnionRect
(
&
lock_union
,
&
lock_src
,
&
lock_dst
);
/* Lock the union of the two rectangles */
hr
=
IWineD3DSurface_Map
((
IWineD3DSurface
*
)
dst_surface
,
&
dlock
,
&
lock_union
,
0
);
if
(
FAILED
(
hr
))
goto
error
;
pitch
=
dlock
.
Pitch
;
slock
.
Pitch
=
dlock
.
Pitch
;
/* Since slock was originally copied from this surface's description, we can just reuse it. */
sbuf
=
dst_surface
->
resource
.
allocatedMemory
+
lock_src
.
top
*
pitch
+
lock_src
.
left
*
bpp
;
dbuf
=
dst_surface
->
resource
.
allocatedMemory
+
lock_dst
.
top
*
pitch
+
lock_dst
.
left
*
bpp
;
src_format
=
src_surface
->
resource
.
format
;
dst_format
=
src_format
;
}
else
{
hr
=
IWineD3DSurface_Map
((
IWineD3DSurface
*
)
src_surface
,
&
slock
,
&
lock_src
,
WINED3DLOCK_READONLY
);
if
(
FAILED
(
hr
))
goto
error
;
hr
=
IWineD3DSurface_Map
((
IWineD3DSurface
*
)
dst_surface
,
&
dlock
,
&
lock_dst
,
0
);
if
(
FAILED
(
hr
))
goto
error
;
sbuf
=
slock
.
pBits
;
dbuf
=
dlock
.
pBits
;
TRACE
(
"Dst is at %p, Src is at %p.
\n
"
,
dbuf
,
sbuf
);
src_format
=
src_surface
->
resource
.
format
;
dst_format
=
dst_surface
->
resource
.
format
;
}
/* Handle compressed surfaces first... */
if
(
src_format
->
flags
&
dst_format
->
flags
&
WINED3DFMT_FLAG_COMPRESSED
)
{
UINT
row_block_count
;
TRACE
(
"compressed -> compressed copy
\n
"
);
if
(
trans
)
FIXME
(
"trans arg not supported when a compressed surface is involved
\n
"
);
if
(
dst_x
||
dst_y
)
FIXME
(
"offset for destination surface is not supported
\n
"
);
if
(
src_surface
->
resource
.
format
->
id
!=
dst_surface
->
resource
.
format
->
id
)
{
FIXME
(
"compressed -> compressed copy only supported for the same type of surface
\n
"
);
hr
=
WINED3DERR_WRONGTEXTUREFORMAT
;
goto
error
;
}
row_block_count
=
(
w
+
dst_format
->
block_width
-
1
)
/
dst_format
->
block_width
;
for
(
y
=
0
;
y
<
h
;
y
+=
dst_format
->
block_height
)
{
memcpy
(
dbuf
,
sbuf
,
row_block_count
*
dst_format
->
block_byte_count
);
dbuf
+=
dlock
.
Pitch
;
sbuf
+=
slock
.
Pitch
;
}
goto
error
;
}
if
((
src_format
->
flags
&
WINED3DFMT_FLAG_COMPRESSED
)
&&
!
(
dst_format
->
flags
&
WINED3DFMT_FLAG_COMPRESSED
))
{
/* TODO: Use the libtxc_dxtn.so shared library to do software
* decompression. */
ERR
(
"Software decompression not supported.
\n
"
);
goto
error
;
}
if
(
trans
&
(
WINEDDBLTFAST_SRCCOLORKEY
|
WINEDDBLTFAST_DESTCOLORKEY
))
{
DWORD
keylow
,
keyhigh
;
DWORD
mask
=
src_surface
->
resource
.
format
->
red_mask
|
src_surface
->
resource
.
format
->
green_mask
|
src_surface
->
resource
.
format
->
blue_mask
;
/* For some 8-bit formats like L8 and P8 color masks don't make sense */
if
(
!
mask
&&
bpp
==
1
)
mask
=
0xff
;
TRACE
(
"Color keyed copy.
\n
"
);
if
(
trans
&
WINEDDBLTFAST_SRCCOLORKEY
)
{
keylow
=
src_surface
->
SrcBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
src_surface
->
SrcBltCKey
.
dwColorSpaceHighValue
;
}
else
{
/* I'm not sure if this is correct. */
FIXME
(
"WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.
\n
"
);
keylow
=
dst_surface
->
DestBltCKey
.
dwColorSpaceLowValue
;
keyhigh
=
dst_surface
->
DestBltCKey
.
dwColorSpaceHighValue
;
}
#define COPYBOX_COLORKEY(type) \
do { \
const type *s = (const type *)sbuf; \
type *d = (type *)dbuf; \
type tmp; \
for (y = 0; y < h; y++) \
{ \
for (x = 0; x < w; x++) \
{ \
tmp = s[x]; \
if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \
} \
s = (const type *)((const BYTE *)s + slock.Pitch); \
d = (type *)((BYTE *)d + dlock.Pitch); \
} \
} while(0)
switch
(
bpp
)
{
case
1
:
COPYBOX_COLORKEY
(
BYTE
);
break
;
case
2
:
COPYBOX_COLORKEY
(
WORD
);
break
;
case
4
:
COPYBOX_COLORKEY
(
DWORD
);
break
;
case
3
:
{
const
BYTE
*
s
;
DWORD
tmp
;
BYTE
*
d
;
s
=
sbuf
;
d
=
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 %u.
\n
"
,
bpp
*
8
);
hr
=
WINED3DERR_NOTAVAILABLE
;
goto
error
;
}
#undef COPYBOX_COLORKEY
TRACE
(
"Copy done.
\n
"
);
}
else
{
int
width
=
w
*
bpp
;
INT
sbufpitch
,
dbufpitch
;
TRACE
(
"No color key copy.
\n
"
);
/* Handle overlapping surfaces. */
if
(
sbuf
<
dbuf
)
{
sbuf
+=
(
h
-
1
)
*
slock
.
Pitch
;
dbuf
+=
(
h
-
1
)
*
dlock
.
Pitch
;
sbufpitch
=
-
slock
.
Pitch
;
dbufpitch
=
-
dlock
.
Pitch
;
}
else
{
sbufpitch
=
slock
.
Pitch
;
dbufpitch
=
dlock
.
Pitch
;
}
for
(
y
=
0
;
y
<
h
;
++
y
)
{
/* This is pretty easy, a line for line memcpy. */
memmove
(
dbuf
,
sbuf
,
width
);
sbuf
+=
sbufpitch
;
dbuf
+=
dbufpitch
;
}
TRACE
(
"Copy done.
\n
"
);
}
error:
if
(
src_surface
==
dst_surface
)
{
IWineD3DSurface_Unmap
((
IWineD3DSurface
*
)
dst_surface
);
}
else
{
IWineD3DSurface_Unmap
((
IWineD3DSurface
*
)
dst_surface
);
IWineD3DSurface_Unmap
((
IWineD3DSurface
*
)
src_surface
);
}
return
hr
;
}
/* Do not call while under the GL lock. */
static
HRESULT
cpu_blit_color_fill
(
IWineD3DDeviceImpl
*
device
,
IWineD3DSurfaceImpl
*
dst_surface
,
const
RECT
*
dst_rect
,
const
WINED3DCOLORVALUE
*
color
)
...
...
dlls/wined3d/wined3d_private.h
View file @
29c95df7
...
...
@@ -2027,6 +2027,8 @@ struct wined3d_surface_ops
void
(
*
surface_unmap
)(
struct
IWineD3DSurfaceImpl
*
surface
);
HRESULT
(
*
surface_getdc
)(
struct
IWineD3DSurfaceImpl
*
surface
);
HRESULT
(
*
surface_flip
)(
struct
IWineD3DSurfaceImpl
*
surface
,
struct
IWineD3DSurfaceImpl
*
override
);
HRESULT
(
*
surface_bltfast
)(
struct
IWineD3DSurfaceImpl
*
dst_surface
,
DWORD
dst_x
,
DWORD
dst_y
,
IWineD3DSurfaceImpl
*
src_surface
,
const
RECT
*
src_rect
,
DWORD
trans
);
HRESULT
(
*
surface_set_mem
)(
struct
IWineD3DSurfaceImpl
*
surface
,
void
*
mem
);
};
...
...
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