2 * IWineD3DSurface Implementation of management(non-rendering) functions
4 * Copyright 1998 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2002-2005 Jason Edmeades
7 * Copyright 2002-2003 Raphael Junqueira
8 * Copyright 2004 Christian Costa
9 * Copyright 2005 Oliver Stieber
10 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
11 * Copyright 2007 Henri Verbeet
12 * Copyright 2006-2007 Roderick Colenbrander
13 * Copyright 2009 Henri Verbeet for CodeWeavers
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/port.h"
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface
);
36 /* See also float_16_to_32() in wined3d_private.h */
37 static inline unsigned short float_32_to_16(const float *in
)
40 float tmp
= fabs(*in
);
41 unsigned int mantissa
;
44 /* Deal with special numbers */
45 if (*in
== 0.0f
) return 0x0000;
46 if(isnan(*in
)) return 0x7C01;
47 if (isinf(*in
)) return (*in
< 0.0f
? 0xFC00 : 0x7c00);
49 if(tmp
< powf(2, 10)) {
54 }while(tmp
< powf(2, 10));
55 } else if(tmp
>= powf(2, 11)) {
60 }while(tmp
>= powf(2, 11));
63 mantissa
= (unsigned int) tmp
;
64 if(tmp
- mantissa
>= 0.5f
) mantissa
++; /* round to nearest, away from zero */
66 exp
+= 10; /* Normalize the mantissa */
67 exp
+= 15; /* Exponent is encoded with excess 15 */
69 if(exp
> 30) { /* too big */
70 ret
= 0x7c00; /* INF */
72 /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */
74 mantissa
= mantissa
>> 1;
77 ret
= mantissa
& 0x3ff;
79 ret
= (exp
<< 10) | (mantissa
& 0x3ff);
82 ret
|= ((*in
< 0.0f
? 1 : 0) << 15); /* Add the sign */
86 /* *******************************************
87 IWineD3DSurface IUnknown parts follow
88 ******************************************* */
89 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface
*iface
, REFIID riid
, LPVOID
*ppobj
)
91 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
92 /* Warn ,but be nice about things */
93 TRACE("(%p)->(%s,%p)\n", This
,debugstr_guid(riid
),ppobj
);
95 if (IsEqualGUID(riid
, &IID_IUnknown
)
96 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
97 || IsEqualGUID(riid
, &IID_IWineD3DResource
)
98 || IsEqualGUID(riid
, &IID_IWineD3DSurface
)) {
99 IUnknown_AddRef((IUnknown
*)iface
);
104 return E_NOINTERFACE
;
107 ULONG WINAPI
IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface
*iface
) {
108 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
109 ULONG ref
= InterlockedIncrement(&This
->resource
.ref
);
110 TRACE("(%p) : AddRef increasing from %d\n", This
,ref
- 1);
114 /* ****************************************************
115 IWineD3DSurface IWineD3DResource parts follow
116 **************************************************** */
117 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface
*iface
, REFGUID refguid
, CONST
void* pData
, DWORD SizeOfData
, DWORD Flags
) {
118 return resource_set_private_data((IWineD3DResource
*)iface
, refguid
, pData
, SizeOfData
, Flags
);
121 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface
*iface
, REFGUID refguid
, void* pData
, DWORD
* pSizeOfData
) {
122 return resource_get_private_data((IWineD3DResource
*)iface
, refguid
, pData
, pSizeOfData
);
125 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface
*iface
, REFGUID refguid
) {
126 return resource_free_private_data((IWineD3DResource
*)iface
, refguid
);
129 DWORD WINAPI
IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface
*iface
, DWORD PriorityNew
) {
130 return resource_set_priority((IWineD3DResource
*)iface
, PriorityNew
);
133 DWORD WINAPI
IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface
*iface
) {
134 return resource_get_priority((IWineD3DResource
*)iface
);
137 WINED3DRESOURCETYPE WINAPI
IWineD3DBaseSurfaceImpl_GetType(IWineD3DSurface
*iface
) {
138 TRACE("(%p) : calling resourceimpl_GetType\n", iface
);
139 return resource_get_type((IWineD3DResource
*)iface
);
142 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface
*iface
, IUnknown
**pParent
) {
143 TRACE("(%p) : calling resourceimpl_GetParent\n", iface
);
144 return resource_get_parent((IWineD3DResource
*)iface
, pParent
);
147 /* ******************************************************
148 IWineD3DSurface IWineD3DSurface parts follow
149 ****************************************************** */
151 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface
*iface
, WINED3DSURFACE_DESC
*pDesc
) {
152 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
154 TRACE("(%p) : copying into %p\n", This
, pDesc
);
156 pDesc
->format
= This
->resource
.format_desc
->id
;
157 pDesc
->resource_type
= This
->resource
.resourceType
;
158 pDesc
->usage
= This
->resource
.usage
;
159 pDesc
->pool
= This
->resource
.pool
;
160 pDesc
->size
= This
->resource
.size
; /* dx8 only */
161 pDesc
->multisample_type
= This
->currentDesc
.MultiSampleType
;
162 pDesc
->multisample_quality
= This
->currentDesc
.MultiSampleQuality
;
163 pDesc
->width
= This
->currentDesc
.Width
;
164 pDesc
->height
= This
->currentDesc
.Height
;
169 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface
*iface
, DWORD Flags
)
171 TRACE("iface %p, flags %#x.\n", iface
, Flags
);
175 case WINEDDGBS_CANBLT
:
176 case WINEDDGBS_ISBLTDONE
:
180 return WINED3DERR_INVALIDCALL
;
184 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface
*iface
, DWORD Flags
) {
185 /* XXX: DDERR_INVALIDSURFACETYPE */
187 TRACE("(%p)->(%08x)\n",iface
,Flags
);
189 case WINEDDGFS_CANFLIP
:
190 case WINEDDGFS_ISFLIPDONE
:
194 return WINED3DERR_INVALIDCALL
;
198 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface
*iface
) {
199 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
200 TRACE("(%p)\n", This
);
202 /* D3D8 and 9 loose full devices, ddraw only surfaces */
203 return This
->Flags
& SFLAG_LOST
? WINED3DERR_DEVICELOST
: WINED3D_OK
;
206 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface
*iface
) {
207 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
208 TRACE("(%p)\n", This
);
210 /* So far we don't lose anything :) */
211 This
->Flags
&= ~SFLAG_LOST
;
215 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface
*iface
, IWineD3DPalette
*Pal
) {
216 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
217 IWineD3DPaletteImpl
*PalImpl
= (IWineD3DPaletteImpl
*) Pal
;
218 TRACE("(%p)->(%p)\n", This
, Pal
);
220 if(This
->palette
== PalImpl
) {
221 TRACE("Nop palette change\n");
225 if(This
->palette
!= NULL
)
226 if(This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)
227 This
->palette
->Flags
&= ~WINEDDPCAPS_PRIMARYSURFACE
;
229 This
->palette
= PalImpl
;
231 if(PalImpl
!= NULL
) {
232 if(This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) {
233 (PalImpl
)->Flags
|= WINEDDPCAPS_PRIMARYSURFACE
;
236 return IWineD3DSurface_RealizePalette(iface
);
238 else return WINED3D_OK
;
241 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface
*iface
, DWORD Flags
, const WINEDDCOLORKEY
*CKey
)
243 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
244 TRACE("(%p)->(%08x,%p)\n", This
, Flags
, CKey
);
246 if ((Flags
& WINEDDCKEY_COLORSPACE
) != 0) {
247 FIXME(" colorkey value not supported (%08x) !\n", Flags
);
248 return WINED3DERR_INVALIDCALL
;
251 /* Dirtify the surface, but only if a key was changed */
253 switch (Flags
& ~WINEDDCKEY_COLORSPACE
) {
254 case WINEDDCKEY_DESTBLT
:
255 This
->DestBltCKey
= *CKey
;
256 This
->CKeyFlags
|= WINEDDSD_CKDESTBLT
;
259 case WINEDDCKEY_DESTOVERLAY
:
260 This
->DestOverlayCKey
= *CKey
;
261 This
->CKeyFlags
|= WINEDDSD_CKDESTOVERLAY
;
264 case WINEDDCKEY_SRCOVERLAY
:
265 This
->SrcOverlayCKey
= *CKey
;
266 This
->CKeyFlags
|= WINEDDSD_CKSRCOVERLAY
;
269 case WINEDDCKEY_SRCBLT
:
270 This
->SrcBltCKey
= *CKey
;
271 This
->CKeyFlags
|= WINEDDSD_CKSRCBLT
;
276 switch (Flags
& ~WINEDDCKEY_COLORSPACE
) {
277 case WINEDDCKEY_DESTBLT
:
278 This
->CKeyFlags
&= ~WINEDDSD_CKDESTBLT
;
281 case WINEDDCKEY_DESTOVERLAY
:
282 This
->CKeyFlags
&= ~WINEDDSD_CKDESTOVERLAY
;
285 case WINEDDCKEY_SRCOVERLAY
:
286 This
->CKeyFlags
&= ~WINEDDSD_CKSRCOVERLAY
;
289 case WINEDDCKEY_SRCBLT
:
290 This
->CKeyFlags
&= ~WINEDDSD_CKSRCBLT
;
298 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface
*iface
, IWineD3DPalette
**Pal
) {
299 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
300 TRACE("(%p)->(%p)\n", This
, Pal
);
302 *Pal
= (IWineD3DPalette
*) This
->palette
;
306 DWORD WINAPI
IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface
*iface
) {
307 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
308 const struct wined3d_format_desc
*format_desc
= This
->resource
.format_desc
;
310 TRACE("(%p)\n", This
);
312 if ((format_desc
->Flags
& (WINED3DFMT_FLAG_COMPRESSED
| WINED3DFMT_FLAG_BROKEN_PITCH
))
313 == WINED3DFMT_FLAG_COMPRESSED
)
315 /* Since compressed formats are block based, pitch means the amount of
316 * bytes to the next row of block rather than the next row of pixels. */
317 UINT row_block_count
= (This
->currentDesc
.Width
+ format_desc
->block_width
- 1) / format_desc
->block_width
;
318 ret
= row_block_count
* format_desc
->block_byte_count
;
322 unsigned char alignment
= This
->resource
.device
->surface_alignment
;
323 ret
= This
->resource
.format_desc
->byte_count
* This
->currentDesc
.Width
; /* Bytes / row */
324 ret
= (ret
+ alignment
- 1) & ~(alignment
- 1);
326 TRACE("(%p) Returning %d\n", This
, ret
);
330 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface
*iface
, LONG X
, LONG Y
) {
331 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
334 TRACE("(%p)->(%d,%d) Stub!\n", This
, X
, Y
);
336 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
338 TRACE("(%p): Not an overlay surface\n", This
);
339 return WINEDDERR_NOTAOVERLAYSURFACE
;
342 w
= This
->overlay_destrect
.right
- This
->overlay_destrect
.left
;
343 h
= This
->overlay_destrect
.bottom
- This
->overlay_destrect
.top
;
344 This
->overlay_destrect
.left
= X
;
345 This
->overlay_destrect
.top
= Y
;
346 This
->overlay_destrect
.right
= X
+ w
;
347 This
->overlay_destrect
.bottom
= Y
+ h
;
349 IWineD3DSurface_DrawOverlay(iface
);
354 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface
*iface
, LONG
*X
, LONG
*Y
) {
355 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
358 TRACE("(%p)->(%p,%p)\n", This
, X
, Y
);
360 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
362 TRACE("(%p): Not an overlay surface\n", This
);
363 return WINEDDERR_NOTAOVERLAYSURFACE
;
365 if(This
->overlay_dest
== NULL
) {
367 hr
= WINEDDERR_OVERLAYNOTVISIBLE
;
369 *X
= This
->overlay_destrect
.left
;
370 *Y
= This
->overlay_destrect
.top
;
374 TRACE("Returning 0x%08x, position %d, %d\n", hr
, *X
, *Y
);
378 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface
*iface
, DWORD Flags
, IWineD3DSurface
*Ref
) {
379 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
381 FIXME("iface %p, flags %#x, ref %p stub!\n", iface
, Flags
, Ref
);
383 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
385 TRACE("(%p): Not an overlay surface\n", This
);
386 return WINEDDERR_NOTAOVERLAYSURFACE
;
392 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface
*iface
, const RECT
*SrcRect
,
393 IWineD3DSurface
*DstSurface
, const RECT
*DstRect
, DWORD Flags
, const WINEDDOVERLAYFX
*FX
)
395 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
396 IWineD3DSurfaceImpl
*Dst
= (IWineD3DSurfaceImpl
*) DstSurface
;
397 TRACE("(%p)->(%p, %p, %p, %08x, %p)\n", This
, SrcRect
, Dst
, DstRect
, Flags
, FX
);
399 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
401 WARN("(%p): Not an overlay surface\n", This
);
402 return WINEDDERR_NOTAOVERLAYSURFACE
;
403 } else if(!DstSurface
) {
404 WARN("(%p): Dest surface is NULL\n", This
);
405 return WINED3DERR_INVALIDCALL
;
409 This
->overlay_srcrect
= *SrcRect
;
411 This
->overlay_srcrect
.left
= 0;
412 This
->overlay_srcrect
.top
= 0;
413 This
->overlay_srcrect
.right
= This
->currentDesc
.Width
;
414 This
->overlay_srcrect
.bottom
= This
->currentDesc
.Height
;
418 This
->overlay_destrect
= *DstRect
;
420 This
->overlay_destrect
.left
= 0;
421 This
->overlay_destrect
.top
= 0;
422 This
->overlay_destrect
.right
= Dst
? Dst
->currentDesc
.Width
: 0;
423 This
->overlay_destrect
.bottom
= Dst
? Dst
->currentDesc
.Height
: 0;
426 if(This
->overlay_dest
&& (This
->overlay_dest
!= Dst
|| Flags
& WINEDDOVER_HIDE
)) {
427 list_remove(&This
->overlay_entry
);
430 if(Flags
& WINEDDOVER_SHOW
) {
431 if(This
->overlay_dest
!= Dst
) {
432 This
->overlay_dest
= Dst
;
433 list_add_tail(&Dst
->overlays
, &This
->overlay_entry
);
435 } else if(Flags
& WINEDDOVER_HIDE
) {
436 /* tests show that the rectangles are erased on hide */
437 This
->overlay_srcrect
.left
= 0; This
->overlay_srcrect
.top
= 0;
438 This
->overlay_srcrect
.right
= 0; This
->overlay_srcrect
.bottom
= 0;
439 This
->overlay_destrect
.left
= 0; This
->overlay_destrect
.top
= 0;
440 This
->overlay_destrect
.right
= 0; This
->overlay_destrect
.bottom
= 0;
441 This
->overlay_dest
= NULL
;
444 IWineD3DSurface_DrawOverlay(iface
);
449 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface
*iface
, IWineD3DClipper
*clipper
)
451 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
452 TRACE("(%p)->(%p)\n", This
, clipper
);
454 This
->clipper
= clipper
;
458 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface
*iface
, IWineD3DClipper
**clipper
)
460 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
461 TRACE("(%p)->(%p)\n", This
, clipper
);
463 *clipper
= This
->clipper
;
465 IWineD3DClipper_AddRef(*clipper
);
470 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface
*iface
, enum wined3d_format_id format_id
)
472 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
473 const struct wined3d_format_desc
*format_desc
= getFormatDescEntry(format_id
,
474 &This
->resource
.device
->adapter
->gl_info
);
476 if (This
->resource
.format_desc
->id
!= WINED3DFMT_UNKNOWN
)
478 FIXME("(%p) : The format of the surface must be WINED3DFORMAT_UNKNOWN\n", This
);
479 return WINED3DERR_INVALIDCALL
;
482 TRACE("(%p) : Setting texture format to (%d,%s)\n", This
, format_id
, debug_d3dformat(format_id
));
484 This
->resource
.size
= wined3d_format_calculate_size(format_desc
, This
->resource
.device
->surface_alignment
,
485 This
->pow2Width
, This
->pow2Height
);
487 This
->Flags
|= (WINED3DFMT_D16_LOCKABLE
== format_id
) ? SFLAG_LOCKABLE
: 0;
489 This
->resource
.format_desc
= format_desc
;
491 TRACE("(%p) : Size %d, bytesPerPixel %d\n", This
, This
->resource
.size
, format_desc
->byte_count
);
496 HRESULT
IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface
*iface
) {
497 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
498 const struct wined3d_format_desc
*format_desc
= This
->resource
.format_desc
;
506 if(!(format_desc
->Flags
& WINED3DFMT_FLAG_GETDC
))
508 WARN("Cannot use GetDC on a %s surface\n", debug_d3dformat(format_desc
->id
));
509 return WINED3DERR_INVALIDCALL
;
512 switch (format_desc
->byte_count
)
516 /* Allocate extra space to store the RGB bit masks. */
517 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 3 * sizeof(DWORD
));
521 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
));
525 /* Allocate extra space for a palette. */
526 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
527 sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
) * (1 << (format_desc
->byte_count
* 8)));
532 return E_OUTOFMEMORY
;
534 /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
535 * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
536 * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
537 * add an extra line to the dib section
539 GetSystemInfo(&sysInfo
);
540 if( ((This
->resource
.size
+ 3) % sysInfo
.dwPageSize
) < 4) {
542 TRACE("Adding an extra line to the dib section\n");
545 b_info
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
546 /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
547 b_info
->bmiHeader
.biWidth
= IWineD3DSurface_GetPitch(iface
) / format_desc
->byte_count
;
548 b_info
->bmiHeader
.biHeight
= -This
->currentDesc
.Height
-extraline
;
549 b_info
->bmiHeader
.biSizeImage
= ( This
->currentDesc
.Height
+ extraline
) * IWineD3DSurface_GetPitch(iface
);
550 b_info
->bmiHeader
.biPlanes
= 1;
551 b_info
->bmiHeader
.biBitCount
= format_desc
->byte_count
* 8;
553 b_info
->bmiHeader
.biXPelsPerMeter
= 0;
554 b_info
->bmiHeader
.biYPelsPerMeter
= 0;
555 b_info
->bmiHeader
.biClrUsed
= 0;
556 b_info
->bmiHeader
.biClrImportant
= 0;
558 /* Get the bit masks */
559 masks
= (DWORD
*)b_info
->bmiColors
;
560 switch (This
->resource
.format_desc
->id
)
562 case WINED3DFMT_B8G8R8_UNORM
:
563 usage
= DIB_RGB_COLORS
;
564 b_info
->bmiHeader
.biCompression
= BI_RGB
;
567 case WINED3DFMT_B5G5R5X1_UNORM
:
568 case WINED3DFMT_B5G5R5A1_UNORM
:
569 case WINED3DFMT_B4G4R4A4_UNORM
:
570 case WINED3DFMT_B4G4R4X4_UNORM
:
571 case WINED3DFMT_B2G3R3_UNORM
:
572 case WINED3DFMT_B2G3R3A8_UNORM
:
573 case WINED3DFMT_R10G10B10A2_UNORM
:
574 case WINED3DFMT_R8G8B8A8_UNORM
:
575 case WINED3DFMT_R8G8B8X8_UNORM
:
576 case WINED3DFMT_B10G10R10A2_UNORM
:
577 case WINED3DFMT_B5G6R5_UNORM
:
578 case WINED3DFMT_R16G16B16A16_UNORM
:
580 b_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
581 masks
[0] = format_desc
->red_mask
;
582 masks
[1] = format_desc
->green_mask
;
583 masks
[2] = format_desc
->blue_mask
;
587 /* Don't know palette */
588 b_info
->bmiHeader
.biCompression
= BI_RGB
;
595 HeapFree(GetProcessHeap(), 0, b_info
);
596 return HRESULT_FROM_WIN32(GetLastError());
599 TRACE("Creating a DIB section with size %dx%dx%d, size=%d\n", b_info
->bmiHeader
.biWidth
, b_info
->bmiHeader
.biHeight
, b_info
->bmiHeader
.biBitCount
, b_info
->bmiHeader
.biSizeImage
);
600 This
->dib
.DIBsection
= CreateDIBSection(ddc
, b_info
, usage
, &This
->dib
.bitmap_data
, 0 /* Handle */, 0 /* Offset */);
603 if (!This
->dib
.DIBsection
) {
604 ERR("CreateDIBSection failed!\n");
605 HeapFree(GetProcessHeap(), 0, b_info
);
606 return HRESULT_FROM_WIN32(GetLastError());
609 TRACE("DIBSection at : %p\n", This
->dib
.bitmap_data
);
610 /* copy the existing surface to the dib section */
611 if(This
->resource
.allocatedMemory
) {
612 memcpy(This
->dib
.bitmap_data
, This
->resource
.allocatedMemory
, This
->currentDesc
.Height
* IWineD3DSurface_GetPitch(iface
));
614 /* This is to make LockRect read the gl Texture although memory is allocated */
615 This
->Flags
&= ~SFLAG_INSYSMEM
;
617 This
->dib
.bitmap_size
= b_info
->bmiHeader
.biSizeImage
;
619 HeapFree(GetProcessHeap(), 0, b_info
);
621 /* Now allocate a HDC */
622 This
->hDC
= CreateCompatibleDC(0);
623 This
->dib
.holdbitmap
= SelectObject(This
->hDC
, This
->dib
.DIBsection
);
624 TRACE("using wined3d palette %p\n", This
->palette
);
625 SelectPalette(This
->hDC
,
626 This
->palette
? This
->palette
->hpal
: 0,
629 This
->Flags
|= SFLAG_DIBSECTION
;
631 HeapFree(GetProcessHeap(), 0, This
->resource
.heapMemory
);
632 This
->resource
.heapMemory
= NULL
;
637 static void convert_r32_float_r16_float(const BYTE
*src
, BYTE
*dst
, DWORD pitch_in
, DWORD pitch_out
,
638 unsigned int w
, unsigned int h
)
642 unsigned short *dst_s
;
644 TRACE("Converting %dx%d pixels, pitches %d %d\n", w
, h
, pitch_in
, pitch_out
);
645 for(y
= 0; y
< h
; y
++) {
646 src_f
= (const float *)(src
+ y
* pitch_in
);
647 dst_s
= (unsigned short *) (dst
+ y
* pitch_out
);
648 for(x
= 0; x
< w
; x
++) {
649 dst_s
[x
] = float_32_to_16(src_f
+ x
);
654 static void convert_r5g6b5_x8r8g8b8(const BYTE
*src
, BYTE
*dst
,
655 DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
)
657 static const unsigned char convert_5to8
[] =
659 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
660 0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
661 0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
662 0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
664 static const unsigned char convert_6to8
[] =
666 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
667 0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d,
668 0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d,
669 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
670 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
671 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
672 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf,
673 0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff,
677 TRACE("Converting %ux%u pixels, pitches %u %u\n", w
, h
, pitch_in
, pitch_out
);
679 for (y
= 0; y
< h
; ++y
)
681 const WORD
*src_line
= (const WORD
*)(src
+ y
* pitch_in
);
682 DWORD
*dst_line
= (DWORD
*)(dst
+ y
* pitch_out
);
683 for (x
= 0; x
< w
; ++x
)
685 WORD pixel
= src_line
[x
];
686 dst_line
[x
] = 0xff000000
687 | convert_5to8
[(pixel
& 0xf800) >> 11] << 16
688 | convert_6to8
[(pixel
& 0x07e0) >> 5] << 8
689 | convert_5to8
[(pixel
& 0x001f)];
694 static void convert_a8r8g8b8_x8r8g8b8(const BYTE
*src
, BYTE
*dst
,
695 DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
)
699 TRACE("Converting %ux%u pixels, pitches %u %u\n", w
, h
, pitch_in
, pitch_out
);
701 for (y
= 0; y
< h
; ++y
)
703 const DWORD
*src_line
= (const DWORD
*)(src
+ y
* pitch_in
);
704 DWORD
*dst_line
= (DWORD
*)(dst
+ y
* pitch_out
);
706 for (x
= 0; x
< w
; ++x
)
708 dst_line
[x
] = 0xff000000 | (src_line
[x
] & 0xffffff);
713 static inline BYTE
cliptobyte(int x
)
715 return (BYTE
) ((x
< 0) ? 0 : ((x
> 255) ? 255 : x
));
718 static void convert_yuy2_x8r8g8b8(const BYTE
*src
, BYTE
*dst
,
719 DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
)
722 int c2
, d
, e
, r2
= 0, g2
= 0, b2
= 0;
724 TRACE("Converting %ux%u pixels, pitches %u %u\n", w
, h
, pitch_in
, pitch_out
);
726 for (y
= 0; y
< h
; ++y
)
728 const BYTE
*src_line
= src
+ y
* pitch_in
;
729 DWORD
*dst_line
= (DWORD
*)(dst
+ y
* pitch_out
);
730 for (x
= 0; x
< w
; ++x
)
732 /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV:
733 * C = Y - 16; D = U - 128; E = V - 128;
734 * R = cliptobyte((298 * C + 409 * E + 128) >> 8);
735 * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8);
736 * B = cliptobyte((298 * C + 516 * D + 128) >> 8);
737 * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V .
738 * U and V are shared between the pixels.
740 if (!(x
& 1)) /* for every even pixel, read new U and V */
742 d
= (int) src_line
[1] - 128;
743 e
= (int) src_line
[3] - 128;
745 g2
= - 100 * d
- 208 * e
+ 128;
748 c2
= 298 * ((int) src_line
[0] - 16);
749 dst_line
[x
] = 0xff000000
750 | cliptobyte((c2
+ r2
) >> 8) << 16 /* red */
751 | cliptobyte((c2
+ g2
) >> 8) << 8 /* green */
752 | cliptobyte((c2
+ b2
) >> 8); /* blue */
753 /* Scale RGB values to 0..255 range,
754 * then clip them if still not in range (may be negative),
755 * then shift them within DWORD if necessary.
762 struct d3dfmt_convertor_desc
764 enum wined3d_format_id from
, to
;
765 void (*convert
)(const BYTE
*src
, BYTE
*dst
, DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
);
768 static const struct d3dfmt_convertor_desc convertors
[] =
770 {WINED3DFMT_R32_FLOAT
, WINED3DFMT_R16_FLOAT
, convert_r32_float_r16_float
},
771 {WINED3DFMT_B5G6R5_UNORM
, WINED3DFMT_B8G8R8X8_UNORM
, convert_r5g6b5_x8r8g8b8
},
772 {WINED3DFMT_B8G8R8A8_UNORM
, WINED3DFMT_B8G8R8X8_UNORM
, convert_a8r8g8b8_x8r8g8b8
},
773 {WINED3DFMT_YUY2
, WINED3DFMT_B8G8R8X8_UNORM
, convert_yuy2_x8r8g8b8
},
776 static inline const struct d3dfmt_convertor_desc
*find_convertor(enum wined3d_format_id from
, enum wined3d_format_id to
)
779 for(i
= 0; i
< (sizeof(convertors
) / sizeof(convertors
[0])); i
++) {
780 if(convertors
[i
].from
== from
&& convertors
[i
].to
== to
) {
781 return &convertors
[i
];
787 /*****************************************************************************
788 * surface_convert_format
790 * Creates a duplicate of a surface in a different format. Is used by Blt to
791 * blit between surfaces with different formats
794 * source: Source surface
795 * fmt: Requested destination format
797 *****************************************************************************/
798 static IWineD3DSurfaceImpl
*surface_convert_format(IWineD3DSurfaceImpl
*source
, enum wined3d_format_id to_fmt
)
800 IWineD3DSurface
*ret
= NULL
;
801 const struct d3dfmt_convertor_desc
*conv
;
802 WINED3DLOCKED_RECT lock_src
, lock_dst
;
805 conv
= find_convertor(source
->resource
.format_desc
->id
, to_fmt
);
808 FIXME("Cannot find a conversion function from format %s to %s.\n",
809 debug_d3dformat(source
->resource
.format_desc
->id
), debug_d3dformat(to_fmt
));
813 IWineD3DDevice_CreateSurface((IWineD3DDevice
*)source
->resource
.device
, source
->currentDesc
.Width
,
814 source
->currentDesc
.Height
, to_fmt
, TRUE
/* lockable */, TRUE
/* discard */, 0 /* level */, &ret
,
815 0 /* usage */, WINED3DPOOL_SCRATCH
, WINED3DMULTISAMPLE_NONE
/* TODO: Multisampled conversion */,
816 0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface
*) source
),
817 NULL
/* parent */, &wined3d_null_parent_ops
);
819 ERR("Failed to create a destination surface for conversion\n");
823 memset(&lock_src
, 0, sizeof(lock_src
));
824 memset(&lock_dst
, 0, sizeof(lock_dst
));
826 hr
= IWineD3DSurface_LockRect((IWineD3DSurface
*) source
, &lock_src
, NULL
, WINED3DLOCK_READONLY
);
828 ERR("Failed to lock the source surface\n");
829 IWineD3DSurface_Release(ret
);
832 hr
= IWineD3DSurface_LockRect(ret
, &lock_dst
, NULL
, WINED3DLOCK_READONLY
);
834 ERR("Failed to lock the dest surface\n");
835 IWineD3DSurface_UnlockRect((IWineD3DSurface
*) source
);
836 IWineD3DSurface_Release(ret
);
840 conv
->convert(lock_src
.pBits
, lock_dst
.pBits
, lock_src
.Pitch
, lock_dst
.Pitch
,
841 source
->currentDesc
.Width
, source
->currentDesc
.Height
);
843 IWineD3DSurface_UnlockRect(ret
);
844 IWineD3DSurface_UnlockRect((IWineD3DSurface
*) source
);
846 return (IWineD3DSurfaceImpl
*) ret
;
849 /*****************************************************************************
852 * Helper function that fills a memory area with a specific color
855 * buf: memory address to start filling at
856 * width, height: Dimensions of the area to fill
857 * bpp: Bit depth of the surface
858 * lPitch: pitch of the surface
859 * color: Color to fill with
861 *****************************************************************************/
863 _Blt_ColorFill(BYTE
*buf
,
864 int width
, int height
,
865 int bpp
, LONG lPitch
,
873 #define COLORFILL_ROW(type) \
875 type *d = (type *) buf; \
876 for (x = 0; x < width; x++) \
877 d[x] = (type) color; \
882 case 1: COLORFILL_ROW(BYTE
)
883 case 2: COLORFILL_ROW(WORD
)
887 for (x
= 0; x
< width
; x
++,d
+=3)
889 d
[0] = (color
) & 0xFF;
890 d
[1] = (color
>> 8) & 0xFF;
891 d
[2] = (color
>>16) & 0xFF;
895 case 4: COLORFILL_ROW(DWORD
)
897 FIXME("Color fill not implemented for bpp %d!\n", bpp
*8);
898 return WINED3DERR_NOTAVAILABLE
;
903 /* Now copy first row */
905 for (y
= 1; y
< height
; y
++)
908 memcpy(buf
, first
, width
* bpp
);
913 /*****************************************************************************
914 * IWineD3DSurface::Blt, SW emulation version
916 * Performs a blit to a surface, with or without a source surface.
917 * This is the main functionality of DirectDraw
920 * DestRect: Destination rectangle to write to
921 * src_surface: Source surface, can be NULL
922 * SrcRect: Source rectangle
923 *****************************************************************************/
924 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface
*iface
, const RECT
*DestRect
, IWineD3DSurface
*src_surface
,
925 const RECT
*SrcRect
, DWORD Flags
, const WINEDDBLTFX
*DDBltFx
, WINED3DTEXTUREFILTERTYPE Filter
)
927 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
928 IWineD3DSurfaceImpl
*src
= (IWineD3DSurfaceImpl
*)src_surface
;
930 HRESULT ret
= WINED3D_OK
;
931 WINED3DLOCKED_RECT dlock
, slock
;
932 int bpp
, srcheight
, srcwidth
, dstheight
, dstwidth
, width
;
933 const struct wined3d_format_desc
*sEntry
, *dEntry
;
938 TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n",
939 iface
, wine_dbgstr_rect(DestRect
), src_surface
, wine_dbgstr_rect(SrcRect
),
940 Flags
, DDBltFx
, debug_d3dtexturefiltertype(Filter
));
942 if ((This
->Flags
& SFLAG_LOCKED
) || (src
&& (src
->Flags
& SFLAG_LOCKED
)))
944 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
945 return WINEDDERR_SURFACEBUSY
;
948 if(Filter
!= WINED3DTEXF_NONE
&& Filter
!= WINED3DTEXF_POINT
) {
949 /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
950 FIXME("Filters not supported in software blit\n");
953 /* First check for the validity of source / destination rectangles.
954 * This was verified using a test application + by MSDN. */
960 if (SrcRect
->right
< SrcRect
->left
|| SrcRect
->bottom
< SrcRect
->top
961 || SrcRect
->left
> src
->currentDesc
.Width
|| SrcRect
->left
< 0
962 || SrcRect
->top
> src
->currentDesc
.Height
|| SrcRect
->top
< 0
963 || SrcRect
->right
> src
->currentDesc
.Width
|| SrcRect
->right
< 0
964 || SrcRect
->bottom
> src
->currentDesc
.Height
|| SrcRect
->bottom
< 0)
966 WARN("Application gave us bad source rectangle for Blt.\n");
967 return WINEDDERR_INVALIDRECT
;
970 if (!SrcRect
->right
|| !SrcRect
->bottom
971 || SrcRect
->left
== (int)src
->currentDesc
.Width
972 || SrcRect
->top
== (int)src
->currentDesc
.Height
)
974 TRACE("Nothing to be done.\n");
985 xsrc
.right
= src
->currentDesc
.Width
;
986 xsrc
.bottom
= src
->currentDesc
.Height
;
990 memset(&xsrc
, 0, sizeof(xsrc
));
995 /* For the Destination rect, it can be out of bounds on the condition
996 * that a clipper is set for the given surface. */
997 if (!This
->clipper
&& (DestRect
->right
< DestRect
->left
|| DestRect
->bottom
< DestRect
->top
998 || DestRect
->left
> This
->currentDesc
.Width
|| DestRect
->left
< 0
999 || DestRect
->top
> This
->currentDesc
.Height
|| DestRect
->top
< 0
1000 || DestRect
->right
> This
->currentDesc
.Width
|| DestRect
->right
< 0
1001 || DestRect
->bottom
> This
->currentDesc
.Height
|| DestRect
->bottom
< 0))
1003 WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
1004 return WINEDDERR_INVALIDRECT
;
1007 if (DestRect
->right
<= 0 || DestRect
->bottom
<= 0
1008 || DestRect
->left
>= (int)This
->currentDesc
.Width
1009 || DestRect
->top
>= (int)This
->currentDesc
.Height
)
1011 TRACE("Nothing to be done.\n");
1021 full_rect
.right
= This
->currentDesc
.Width
;
1022 full_rect
.bottom
= This
->currentDesc
.Height
;
1023 IntersectRect(&xdst
, &full_rect
, DestRect
);
1027 BOOL clip_horiz
, clip_vert
;
1030 clip_horiz
= xdst
.left
< 0 || xdst
.right
> (int)This
->currentDesc
.Width
;
1031 clip_vert
= xdst
.top
< 0 || xdst
.bottom
> (int)This
->currentDesc
.Height
;
1033 if (clip_vert
|| clip_horiz
)
1035 /* Now check if this is a special case or not... */
1036 if ((Flags
& WINEDDBLT_DDFX
)
1037 || (clip_horiz
&& xdst
.right
- xdst
.left
!= xsrc
.right
- xsrc
.left
)
1038 || (clip_vert
&& xdst
.bottom
- xdst
.top
!= xsrc
.bottom
- xsrc
.top
))
1040 WARN("Out of screen rectangle in special case. Not handled right now.\n");
1048 xsrc
.left
-= xdst
.left
;
1051 if (xdst
.right
> This
->currentDesc
.Width
)
1053 xsrc
.right
-= (xdst
.right
- (int)This
->currentDesc
.Width
);
1054 xdst
.right
= (int)This
->currentDesc
.Width
;
1062 xsrc
.top
-= xdst
.top
;
1065 if (xdst
.bottom
> This
->currentDesc
.Height
)
1067 xsrc
.bottom
-= (xdst
.bottom
- (int)This
->currentDesc
.Height
);
1068 xdst
.bottom
= (int)This
->currentDesc
.Height
;
1072 /* And check if after clipping something is still to be done... */
1073 if ((xdst
.right
<= 0) || (xdst
.bottom
<= 0)
1074 || (xdst
.left
>= (int)This
->currentDesc
.Width
)
1075 || (xdst
.top
>= (int)This
->currentDesc
.Height
)
1076 || (xsrc
.right
<= 0) || (xsrc
.bottom
<= 0)
1077 || (xsrc
.left
>= (int)src
->currentDesc
.Width
)
1078 || (xsrc
.top
>= (int)src
->currentDesc
.Height
))
1080 TRACE("Nothing to be done after clipping.\n");
1090 xdst
.right
= This
->currentDesc
.Width
;
1091 xdst
.bottom
= This
->currentDesc
.Height
;
1096 IWineD3DSurface_LockRect(iface
, &dlock
, NULL
, 0);
1098 sEntry
= This
->resource
.format_desc
;
1103 dEntry
= This
->resource
.format_desc
;
1106 if (This
->resource
.format_desc
->id
!= src
->resource
.format_desc
->id
)
1108 src
= surface_convert_format(src
, dEntry
->id
);
1111 /* The conv function writes a FIXME */
1112 WARN("Cannot convert source surface format to dest format\n");
1116 IWineD3DSurface_LockRect((IWineD3DSurface
*)src
, &slock
, NULL
, WINED3DLOCK_READONLY
);
1117 sEntry
= src
->resource
.format_desc
;
1124 IWineD3DSurface_LockRect(iface
, &dlock
, &xdst
, 0);
1126 IWineD3DSurface_LockRect(iface
, &dlock
, NULL
, 0);
1129 if (!DDBltFx
|| !(DDBltFx
->dwDDFX
)) Flags
&= ~WINEDDBLT_DDFX
;
1131 if (sEntry
->Flags
& dEntry
->Flags
& WINED3DFMT_FLAG_FOURCC
)
1133 if (!DestRect
|| src
== This
)
1135 memcpy(dlock
.pBits
, slock
.pBits
, This
->resource
.size
);
1140 bpp
= This
->resource
.format_desc
->byte_count
;
1141 srcheight
= xsrc
.bottom
- xsrc
.top
;
1142 srcwidth
= xsrc
.right
- xsrc
.left
;
1143 dstheight
= xdst
.bottom
- xdst
.top
;
1144 dstwidth
= xdst
.right
- xdst
.left
;
1145 width
= (xdst
.right
- xdst
.left
) * bpp
;
1147 if (DestRect
&& src
!= This
)
1150 dbuf
= (BYTE
*)dlock
.pBits
+(xdst
.top
*dlock
.Pitch
)+(xdst
.left
*bpp
);
1152 if (Flags
& WINEDDBLT_WAIT
)
1154 Flags
&= ~WINEDDBLT_WAIT
;
1156 if (Flags
& WINEDDBLT_ASYNC
)
1158 static BOOL displayed
= FALSE
;
1160 FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n");
1162 Flags
&= ~WINEDDBLT_ASYNC
;
1164 if (Flags
& WINEDDBLT_DONOTWAIT
)
1166 /* WINEDDBLT_DONOTWAIT appeared in DX7 */
1167 static BOOL displayed
= FALSE
;
1169 FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n");
1171 Flags
&= ~WINEDDBLT_DONOTWAIT
;
1174 /* First, all the 'source-less' blits */
1175 if (Flags
& WINEDDBLT_COLORFILL
)
1177 ret
= _Blt_ColorFill(dbuf
, dstwidth
, dstheight
, bpp
,
1178 dlock
.Pitch
, DDBltFx
->u5
.dwFillColor
);
1179 Flags
&= ~WINEDDBLT_COLORFILL
;
1182 if (Flags
& WINEDDBLT_DEPTHFILL
)
1184 FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
1186 if (Flags
& WINEDDBLT_ROP
)
1188 /* Catch some degenerate cases here */
1189 switch(DDBltFx
->dwROP
)
1192 ret
= _Blt_ColorFill(dbuf
,dstwidth
,dstheight
,bpp
,dlock
.Pitch
,0);
1194 case 0xAA0029: /* No-op */
1197 ret
= _Blt_ColorFill(dbuf
,dstwidth
,dstheight
,bpp
,dlock
.Pitch
,~0);
1199 case SRCCOPY
: /* well, we do that below ? */
1202 FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx
->dwROP
, DDBltFx
->u5
.lpDDSPattern
);
1205 Flags
&= ~WINEDDBLT_ROP
;
1207 if (Flags
& WINEDDBLT_DDROPS
)
1209 FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx
->dwDDROP
, DDBltFx
->u5
.lpDDSPattern
);
1211 /* Now the 'with source' blits */
1215 int sx
, xinc
, sy
, yinc
;
1217 if (!dstwidth
|| !dstheight
) /* hmm... stupid program ? */
1219 sbase
= (BYTE
*)slock
.pBits
+(xsrc
.top
*slock
.Pitch
)+xsrc
.left
*bpp
;
1220 xinc
= (srcwidth
<< 16) / dstwidth
;
1221 yinc
= (srcheight
<< 16) / dstheight
;
1225 /* No effects, we can cheat here */
1226 if (dstwidth
== srcwidth
)
1228 if (dstheight
== srcheight
)
1230 /* No stretching in either direction. This needs to be as
1231 * fast as possible */
1234 /* check for overlapping surfaces */
1235 if (src
!= This
|| xdst
.top
< xsrc
.top
||
1236 xdst
.right
<= xsrc
.left
|| xsrc
.right
<= xdst
.left
)
1238 /* no overlap, or dst above src, so copy from top downwards */
1239 for (y
= 0; y
< dstheight
; y
++)
1241 memcpy(dbuf
, sbuf
, width
);
1242 sbuf
+= slock
.Pitch
;
1243 dbuf
+= dlock
.Pitch
;
1246 else if (xdst
.top
> xsrc
.top
) /* copy from bottom upwards */
1248 sbuf
+= (slock
.Pitch
*dstheight
);
1249 dbuf
+= (dlock
.Pitch
*dstheight
);
1250 for (y
= 0; y
< dstheight
; y
++)
1252 sbuf
-= slock
.Pitch
;
1253 dbuf
-= dlock
.Pitch
;
1254 memcpy(dbuf
, sbuf
, width
);
1257 else /* src and dst overlapping on the same line, use memmove */
1259 for (y
= 0; y
< dstheight
; y
++)
1261 memmove(dbuf
, sbuf
, width
);
1262 sbuf
+= slock
.Pitch
;
1263 dbuf
+= dlock
.Pitch
;
1267 /* Stretching in Y direction only */
1268 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
) {
1269 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1270 memcpy(dbuf
, sbuf
, width
);
1271 dbuf
+= dlock
.Pitch
;
1277 /* Stretching in X direction */
1279 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
)
1281 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1283 if ((sy
>> 16) == (last_sy
>> 16))
1285 /* this sourcerow is the same as last sourcerow -
1286 * copy already stretched row
1288 memcpy(dbuf
, dbuf
- dlock
.Pitch
, width
);
1292 #define STRETCH_ROW(type) { \
1293 const type *s = (const type *)sbuf; \
1294 type *d = (type *)dbuf; \
1295 for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
1296 d[x] = s[sx >> 16]; \
1301 case 1: STRETCH_ROW(BYTE
)
1302 case 2: STRETCH_ROW(WORD
)
1303 case 4: STRETCH_ROW(DWORD
)
1308 for (x
= sx
= 0; x
< dstwidth
; x
++, sx
+= xinc
)
1312 s
= sbuf
+3*(sx
>>16);
1313 pixel
= s
[0]|(s
[1]<<8)|(s
[2]<<16);
1314 d
[0] = (pixel
)&0xff;
1315 d
[1] = (pixel
>> 8)&0xff;
1316 d
[2] = (pixel
>>16)&0xff;
1322 FIXME("Stretched blit not implemented for bpp %d!\n", bpp
*8);
1323 ret
= WINED3DERR_NOTAVAILABLE
;
1328 dbuf
+= dlock
.Pitch
;
1335 LONG dstyinc
= dlock
.Pitch
, dstxinc
= bpp
;
1336 DWORD keylow
= 0xFFFFFFFF, keyhigh
= 0, keymask
= 0xFFFFFFFF;
1337 DWORD destkeylow
= 0x0, destkeyhigh
= 0xFFFFFFFF, destkeymask
= 0xFFFFFFFF;
1338 if (Flags
& (WINEDDBLT_KEYSRC
| WINEDDBLT_KEYDEST
| WINEDDBLT_KEYSRCOVERRIDE
| WINEDDBLT_KEYDESTOVERRIDE
))
1340 /* The color keying flags are checked for correctness in ddraw */
1341 if (Flags
& WINEDDBLT_KEYSRC
)
1343 keylow
= src
->SrcBltCKey
.dwColorSpaceLowValue
;
1344 keyhigh
= src
->SrcBltCKey
.dwColorSpaceHighValue
;
1346 else if (Flags
& WINEDDBLT_KEYSRCOVERRIDE
)
1348 keylow
= DDBltFx
->ddckSrcColorkey
.dwColorSpaceLowValue
;
1349 keyhigh
= DDBltFx
->ddckSrcColorkey
.dwColorSpaceHighValue
;
1352 if (Flags
& WINEDDBLT_KEYDEST
)
1354 /* Destination color keys are taken from the source surface ! */
1355 destkeylow
= src
->DestBltCKey
.dwColorSpaceLowValue
;
1356 destkeyhigh
= src
->DestBltCKey
.dwColorSpaceHighValue
;
1358 else if (Flags
& WINEDDBLT_KEYDESTOVERRIDE
)
1360 destkeylow
= DDBltFx
->ddckDestColorkey
.dwColorSpaceLowValue
;
1361 destkeyhigh
= DDBltFx
->ddckDestColorkey
.dwColorSpaceHighValue
;
1370 keymask
= sEntry
->red_mask
1371 | sEntry
->green_mask
1372 | sEntry
->blue_mask
;
1374 Flags
&= ~(WINEDDBLT_KEYSRC
| WINEDDBLT_KEYDEST
| WINEDDBLT_KEYSRCOVERRIDE
| WINEDDBLT_KEYDESTOVERRIDE
);
1377 if (Flags
& WINEDDBLT_DDFX
)
1379 LPBYTE dTopLeft
, dTopRight
, dBottomLeft
, dBottomRight
, tmp
;
1382 dTopRight
= dbuf
+((dstwidth
-1)*bpp
);
1383 dBottomLeft
= dTopLeft
+((dstheight
-1)*dlock
.Pitch
);
1384 dBottomRight
= dBottomLeft
+((dstwidth
-1)*bpp
);
1386 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ARITHSTRETCHY
)
1388 /* I don't think we need to do anything about this flag */
1389 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
1391 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_MIRRORLEFTRIGHT
)
1394 dTopRight
= dTopLeft
;
1397 dBottomRight
= dBottomLeft
;
1399 dstxinc
= dstxinc
*-1;
1401 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_MIRRORUPDOWN
)
1404 dTopLeft
= dBottomLeft
;
1407 dTopRight
= dBottomRight
;
1409 dstyinc
= dstyinc
*-1;
1411 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_NOTEARING
)
1413 /* I don't think we need to do anything about this flag */
1414 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
1416 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE180
)
1419 dBottomRight
= dTopLeft
;
1422 dBottomLeft
= dTopRight
;
1424 dstxinc
= dstxinc
* -1;
1425 dstyinc
= dstyinc
* -1;
1427 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE270
)
1430 dTopLeft
= dBottomLeft
;
1431 dBottomLeft
= dBottomRight
;
1432 dBottomRight
= dTopRight
;
1437 dstxinc
= dstxinc
* -1;
1439 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE90
)
1442 dTopLeft
= dTopRight
;
1443 dTopRight
= dBottomRight
;
1444 dBottomRight
= dBottomLeft
;
1449 dstyinc
= dstyinc
* -1;
1451 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ZBUFFERBASEDEST
)
1453 /* I don't think we need to do anything about this flag */
1454 WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
1457 Flags
&= ~(WINEDDBLT_DDFX
);
1460 #define COPY_COLORKEY_FX(type) { \
1462 type *d = (type *)dbuf, *dx, tmp; \
1463 for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
1464 s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \
1466 for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
1467 tmp = s[sx >> 16]; \
1468 if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
1469 ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
1472 dx = (type*)(((LPBYTE)dx)+dstxinc); \
1474 d = (type*)(((LPBYTE)d)+dstyinc); \
1479 case 1: COPY_COLORKEY_FX(BYTE
)
1480 case 2: COPY_COLORKEY_FX(WORD
)
1481 case 4: COPY_COLORKEY_FX(DWORD
)
1485 BYTE
*d
= dbuf
, *dx
;
1486 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
)
1488 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1490 for (x
= sx
= 0; x
< dstwidth
; x
++, sx
+= xinc
)
1492 DWORD pixel
, dpixel
= 0;
1493 s
= sbuf
+3*(sx
>>16);
1494 pixel
= s
[0]|(s
[1]<<8)|(s
[2]<<16);
1495 dpixel
= dx
[0]|(dx
[1]<<8)|(dx
[2]<<16);
1496 if (((pixel
& keymask
) < keylow
|| (pixel
& keymask
) > keyhigh
) &&
1497 ((dpixel
& keymask
) >= destkeylow
|| (dpixel
& keymask
) <= keyhigh
))
1499 dx
[0] = (pixel
)&0xff;
1500 dx
[1] = (pixel
>> 8)&0xff;
1501 dx
[2] = (pixel
>>16)&0xff;
1510 FIXME("%s color-keyed blit not implemented for bpp %d!\n",
1511 (Flags
& WINEDDBLT_KEYSRC
) ? "Source" : "Destination", bpp
*8);
1512 ret
= WINED3DERR_NOTAVAILABLE
;
1514 #undef COPY_COLORKEY_FX
1520 if (Flags
&& FIXME_ON(d3d_surface
))
1522 FIXME("\tUnsupported flags: %08x\n", Flags
);
1526 IWineD3DSurface_UnlockRect(iface
);
1527 if (src
&& src
!= This
) IWineD3DSurface_UnlockRect((IWineD3DSurface
*)src
);
1528 /* Release the converted surface if any */
1529 if (src
&& src_surface
!= (IWineD3DSurface
*)src
) IWineD3DSurface_Release((IWineD3DSurface
*)src
);
1533 /*****************************************************************************
1534 * IWineD3DSurface::BltFast, SW emulation version
1536 * This is the software implementation of BltFast, as used by GDI surfaces
1537 * and as a fallback for OpenGL surfaces. This code is taken from the old
1538 * DirectDraw code, and was originally written by TransGaming.
1543 * src_surface: Source surface to copy from
1544 * rsrc: Source rectangle
1548 * WINED3D_OK on success
1550 *****************************************************************************/
1551 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface
*iface
, DWORD dstx
, DWORD dsty
,
1552 IWineD3DSurface
*src_surface
, const RECT
*rsrc
, DWORD trans
)
1554 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1555 IWineD3DSurfaceImpl
*src
= (IWineD3DSurfaceImpl
*)src_surface
;
1557 int bpp
, w
, h
, x
, y
;
1558 WINED3DLOCKED_RECT dlock
,slock
;
1559 HRESULT ret
= WINED3D_OK
;
1561 RECT lock_src
, lock_dst
, lock_union
;
1564 const struct wined3d_format_desc
*sEntry
, *dEntry
;
1566 TRACE("iface %p, dst_x %u, dst_y %u, src_surface %p, src_rect %s, flags %#x.\n",
1567 iface
, dstx
, dsty
, src_surface
, wine_dbgstr_rect(rsrc
), trans
);
1569 if ((This
->Flags
& SFLAG_LOCKED
) || (src
->Flags
& SFLAG_LOCKED
))
1571 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1572 return WINEDDERR_SURFACEBUSY
;
1577 WARN("rsrc is NULL!\n");
1580 rsrc2
.right
= src
->currentDesc
.Width
;
1581 rsrc2
.bottom
= src
->currentDesc
.Height
;
1585 /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
1586 if ((rsrc
->bottom
> src
->currentDesc
.Height
) || (rsrc
->bottom
< 0)
1587 || (rsrc
->top
> src
->currentDesc
.Height
) || (rsrc
->top
< 0)
1588 || (rsrc
->left
> src
->currentDesc
.Width
) || (rsrc
->left
< 0)
1589 || (rsrc
->right
> src
->currentDesc
.Width
) || (rsrc
->right
< 0)
1590 || (rsrc
->right
< rsrc
->left
) || (rsrc
->bottom
< rsrc
->top
))
1592 WARN("Application gave us bad source rectangle for BltFast.\n");
1593 return WINEDDERR_INVALIDRECT
;
1596 h
= rsrc
->bottom
- rsrc
->top
;
1597 if (h
> This
->currentDesc
.Height
-dsty
) h
= This
->currentDesc
.Height
-dsty
;
1598 if (h
> src
->currentDesc
.Height
-rsrc
->top
) h
= src
->currentDesc
.Height
-rsrc
->top
;
1599 if (h
<= 0) return WINEDDERR_INVALIDRECT
;
1601 w
= rsrc
->right
- rsrc
->left
;
1602 if (w
> This
->currentDesc
.Width
-dstx
) w
= This
->currentDesc
.Width
-dstx
;
1603 if (w
> src
->currentDesc
.Width
-rsrc
->left
) w
= src
->currentDesc
.Width
-rsrc
->left
;
1604 if (w
<= 0) return WINEDDERR_INVALIDRECT
;
1606 /* Now compute the locking rectangle... */
1607 lock_src
.left
= rsrc
->left
;
1608 lock_src
.top
= rsrc
->top
;
1609 lock_src
.right
= lock_src
.left
+ w
;
1610 lock_src
.bottom
= lock_src
.top
+ h
;
1612 lock_dst
.left
= dstx
;
1613 lock_dst
.top
= dsty
;
1614 lock_dst
.right
= dstx
+ w
;
1615 lock_dst
.bottom
= dsty
+ h
;
1617 bpp
= This
->resource
.format_desc
->byte_count
;
1619 /* We need to lock the surfaces, or we won't get refreshes when done. */
1624 UnionRect(&lock_union
, &lock_src
, &lock_dst
);
1626 /* Lock the union of the two rectangles */
1627 ret
= IWineD3DSurface_LockRect(iface
, &dlock
, &lock_union
, 0);
1628 if(ret
!= WINED3D_OK
) goto error
;
1630 pitch
= dlock
.Pitch
;
1631 slock
.Pitch
= dlock
.Pitch
;
1633 /* Since slock was originally copied from this surface's description, we can just reuse it */
1634 sbuf
= This
->resource
.allocatedMemory
+ lock_src
.top
* pitch
+ lock_src
.left
* bpp
;
1635 dbuf
= This
->resource
.allocatedMemory
+ lock_dst
.top
* pitch
+ lock_dst
.left
* bpp
;
1636 sEntry
= src
->resource
.format_desc
;
1641 ret
= IWineD3DSurface_LockRect(src_surface
, &slock
, &lock_src
, WINED3DLOCK_READONLY
);
1642 if(ret
!= WINED3D_OK
) goto error
;
1643 ret
= IWineD3DSurface_LockRect(iface
, &dlock
, &lock_dst
, 0);
1644 if(ret
!= WINED3D_OK
) goto error
;
1648 TRACE("Dst is at %p, Src is at %p\n", dbuf
, sbuf
);
1650 sEntry
= src
->resource
.format_desc
;
1651 dEntry
= This
->resource
.format_desc
;
1654 /* Handle compressed surfaces first... */
1655 if (sEntry
->Flags
& dEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
)
1657 UINT row_block_count
;
1659 TRACE("compressed -> compressed copy\n");
1661 FIXME("trans arg not supported when a compressed surface is involved\n");
1663 FIXME("offset for destination surface is not supported\n");
1664 if (src
->resource
.format_desc
->id
!= This
->resource
.format_desc
->id
)
1666 FIXME("compressed -> compressed copy only supported for the same type of surface\n");
1667 ret
= WINED3DERR_WRONGTEXTUREFORMAT
;
1671 row_block_count
= (w
+ dEntry
->block_width
- 1) / dEntry
->block_width
;
1672 for (y
= 0; y
< h
; y
+= dEntry
->block_height
)
1674 memcpy(dbuf
, sbuf
, row_block_count
* dEntry
->block_byte_count
);
1675 dbuf
+= dlock
.Pitch
;
1676 sbuf
+= slock
.Pitch
;
1681 if ((sEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
) && !(dEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
))
1683 /* TODO: Use the libtxc_dxtn.so shared library to do
1684 * software decompression
1686 ERR("Software decompression not supported.\n");
1690 if (trans
& (WINEDDBLTFAST_SRCCOLORKEY
| WINEDDBLTFAST_DESTCOLORKEY
))
1692 DWORD keylow
, keyhigh
;
1693 DWORD mask
= src
->resource
.format_desc
->red_mask
1694 | src
->resource
.format_desc
->green_mask
1695 | src
->resource
.format_desc
->blue_mask
;
1697 /* For some 8-bit formats like L8 and P8 color masks don't make sense */
1701 TRACE("Color keyed copy\n");
1702 if (trans
& WINEDDBLTFAST_SRCCOLORKEY
)
1704 keylow
= src
->SrcBltCKey
.dwColorSpaceLowValue
;
1705 keyhigh
= src
->SrcBltCKey
.dwColorSpaceHighValue
;
1709 /* I'm not sure if this is correct */
1710 FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
1711 keylow
= This
->DestBltCKey
.dwColorSpaceLowValue
;
1712 keyhigh
= This
->DestBltCKey
.dwColorSpaceHighValue
;
1715 #define COPYBOX_COLORKEY(type) { \
1716 const type *s = (const type *)sbuf; \
1717 type *d = (type *)dbuf; \
1719 for (y = 0; y < h; y++) { \
1720 for (x = 0; x < w; x++) { \
1722 if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \
1724 s = (const type *)((const BYTE *)s + slock.Pitch); \
1725 d = (type *)((BYTE *)d + dlock.Pitch); \
1731 case 1: COPYBOX_COLORKEY(BYTE
)
1732 case 2: COPYBOX_COLORKEY(WORD
)
1733 case 4: COPYBOX_COLORKEY(DWORD
)
1741 for (y
= 0; y
< h
; y
++)
1743 for (x
= 0; x
< w
* 3; x
+= 3)
1745 tmp
= (DWORD
)s
[x
] + ((DWORD
)s
[x
+ 1] << 8) + ((DWORD
)s
[x
+ 2] << 16);
1746 if (tmp
< keylow
|| tmp
> keyhigh
)
1748 d
[x
+ 0] = s
[x
+ 0];
1749 d
[x
+ 1] = s
[x
+ 1];
1750 d
[x
+ 2] = s
[x
+ 2];
1759 FIXME("Source color key blitting not supported for bpp %d\n",bpp
*8);
1760 ret
= WINED3DERR_NOTAVAILABLE
;
1763 #undef COPYBOX_COLORKEY
1764 TRACE("Copy Done\n");
1768 int width
= w
* bpp
;
1769 INT sbufpitch
, dbufpitch
;
1771 TRACE("NO color key copy\n");
1772 /* Handle overlapping surfaces */
1775 sbuf
+= (h
- 1) * slock
.Pitch
;
1776 dbuf
+= (h
- 1) * dlock
.Pitch
;
1777 sbufpitch
= -slock
.Pitch
;
1778 dbufpitch
= -dlock
.Pitch
;
1782 sbufpitch
= slock
.Pitch
;
1783 dbufpitch
= dlock
.Pitch
;
1785 for (y
= 0; y
< h
; y
++)
1787 /* This is pretty easy, a line for line memcpy */
1788 memmove(dbuf
, sbuf
, width
);
1792 TRACE("Copy done\n");
1798 IWineD3DSurface_UnlockRect(iface
);
1802 IWineD3DSurface_UnlockRect(iface
);
1803 IWineD3DSurface_UnlockRect(src_surface
);
1809 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface
*iface
, WINED3DLOCKED_RECT
* pLockedRect
, CONST RECT
* pRect
, DWORD Flags
)
1811 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1813 TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
1814 This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
1816 pLockedRect
->Pitch
= IWineD3DSurface_GetPitch(iface
);
1820 pLockedRect
->pBits
= This
->resource
.allocatedMemory
;
1821 This
->lockedRect
.left
= 0;
1822 This
->lockedRect
.top
= 0;
1823 This
->lockedRect
.right
= This
->currentDesc
.Width
;
1824 This
->lockedRect
.bottom
= This
->currentDesc
.Height
;
1826 TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n",
1827 &This
->lockedRect
, This
->lockedRect
.left
, This
->lockedRect
.top
,
1828 This
->lockedRect
.right
, This
->lockedRect
.bottom
);
1832 const struct wined3d_format_desc
*format_desc
= This
->resource
.format_desc
;
1834 TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
1835 pRect
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
1837 if ((format_desc
->Flags
& (WINED3DFMT_FLAG_COMPRESSED
| WINED3DFMT_FLAG_BROKEN_PITCH
))
1838 == WINED3DFMT_FLAG_COMPRESSED
)
1840 /* Compressed textures are block based, so calculate the offset of
1841 * the block that contains the top-left pixel of the locked rectangle. */
1842 pLockedRect
->pBits
= This
->resource
.allocatedMemory
1843 + ((pRect
->top
/ format_desc
->block_height
) * pLockedRect
->Pitch
)
1844 + ((pRect
->left
/ format_desc
->block_width
) * format_desc
->block_byte_count
);
1848 pLockedRect
->pBits
= This
->resource
.allocatedMemory
+
1849 (pLockedRect
->Pitch
* pRect
->top
) +
1850 (pRect
->left
* format_desc
->byte_count
);
1852 This
->lockedRect
.left
= pRect
->left
;
1853 This
->lockedRect
.top
= pRect
->top
;
1854 This
->lockedRect
.right
= pRect
->right
;
1855 This
->lockedRect
.bottom
= pRect
->bottom
;
1858 /* No dirtifying is needed for this surface implementation */
1859 TRACE("returning memory@%p, pitch(%d)\n", pLockedRect
->pBits
, pLockedRect
->Pitch
);
1864 /* TODO: think about moving this down to resource? */
1865 const void *WINAPI
IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface
*iface
)
1867 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1869 /* This should only be called for sysmem textures, it may be a good idea
1870 * to extend this to all pools at some point in the future */
1871 if (This
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
)
1873 FIXME("(%p) Attempting to get system memory for a non-system memory texture\n", iface
);
1875 return This
->resource
.allocatedMemory
;