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
< pow(2, 10)) {
54 }while(tmp
< pow(2, 10));
55 } else if(tmp
>= pow(2, 11)) {
60 }while(tmp
>= pow(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_GetContainer(IWineD3DSurface
* iface
, REFIID riid
, void** ppContainer
) {
152 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
153 IWineD3DBase
*container
= 0;
155 TRACE("(This %p, riid %s, ppContainer %p)\n", This
, debugstr_guid(riid
), ppContainer
);
158 ERR("Called without a valid ppContainer.\n");
161 /* Standalone surfaces return the device as container. */
162 if (This
->container
) container
= This
->container
;
163 else container
= (IWineD3DBase
*)This
->resource
.device
;
165 TRACE("Relaying to QueryInterface\n");
166 return IUnknown_QueryInterface(container
, riid
, ppContainer
);
169 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface
*iface
, WINED3DSURFACE_DESC
*pDesc
) {
170 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
172 TRACE("(%p) : copying into %p\n", This
, pDesc
);
174 pDesc
->format
= This
->resource
.format_desc
->format
;
175 pDesc
->resource_type
= This
->resource
.resourceType
;
176 pDesc
->usage
= This
->resource
.usage
;
177 pDesc
->pool
= This
->resource
.pool
;
178 pDesc
->size
= This
->resource
.size
; /* dx8 only */
179 pDesc
->multisample_type
= This
->currentDesc
.MultiSampleType
;
180 pDesc
->multisample_quality
= This
->currentDesc
.MultiSampleQuality
;
181 pDesc
->width
= This
->currentDesc
.Width
;
182 pDesc
->height
= This
->currentDesc
.Height
;
187 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface
*iface
, DWORD Flags
)
189 TRACE("iface %p, flags %#x.\n", iface
, Flags
);
193 case WINEDDGBS_CANBLT
:
194 case WINEDDGBS_ISBLTDONE
:
198 return WINED3DERR_INVALIDCALL
;
202 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface
*iface
, DWORD Flags
) {
203 /* XXX: DDERR_INVALIDSURFACETYPE */
205 TRACE("(%p)->(%08x)\n",iface
,Flags
);
207 case WINEDDGFS_CANFLIP
:
208 case WINEDDGFS_ISFLIPDONE
:
212 return WINED3DERR_INVALIDCALL
;
216 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface
*iface
) {
217 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
218 TRACE("(%p)\n", This
);
220 /* D3D8 and 9 loose full devices, ddraw only surfaces */
221 return This
->Flags
& SFLAG_LOST
? WINED3DERR_DEVICELOST
: WINED3D_OK
;
224 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface
*iface
) {
225 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
226 TRACE("(%p)\n", This
);
228 /* So far we don't lose anything :) */
229 This
->Flags
&= ~SFLAG_LOST
;
233 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface
*iface
, IWineD3DPalette
*Pal
) {
234 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
235 IWineD3DPaletteImpl
*PalImpl
= (IWineD3DPaletteImpl
*) Pal
;
236 TRACE("(%p)->(%p)\n", This
, Pal
);
238 if(This
->palette
== PalImpl
) {
239 TRACE("Nop palette change\n");
243 if(This
->palette
!= NULL
)
244 if(This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)
245 This
->palette
->Flags
&= ~WINEDDPCAPS_PRIMARYSURFACE
;
247 This
->palette
= PalImpl
;
249 if(PalImpl
!= NULL
) {
250 if(This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) {
251 (PalImpl
)->Flags
|= WINEDDPCAPS_PRIMARYSURFACE
;
254 return IWineD3DSurface_RealizePalette(iface
);
256 else return WINED3D_OK
;
259 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface
*iface
, DWORD Flags
, const WINEDDCOLORKEY
*CKey
)
261 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
262 TRACE("(%p)->(%08x,%p)\n", This
, Flags
, CKey
);
264 if ((Flags
& WINEDDCKEY_COLORSPACE
) != 0) {
265 FIXME(" colorkey value not supported (%08x) !\n", Flags
);
266 return WINED3DERR_INVALIDCALL
;
269 /* Dirtify the surface, but only if a key was changed */
271 switch (Flags
& ~WINEDDCKEY_COLORSPACE
) {
272 case WINEDDCKEY_DESTBLT
:
273 This
->DestBltCKey
= *CKey
;
274 This
->CKeyFlags
|= WINEDDSD_CKDESTBLT
;
277 case WINEDDCKEY_DESTOVERLAY
:
278 This
->DestOverlayCKey
= *CKey
;
279 This
->CKeyFlags
|= WINEDDSD_CKDESTOVERLAY
;
282 case WINEDDCKEY_SRCOVERLAY
:
283 This
->SrcOverlayCKey
= *CKey
;
284 This
->CKeyFlags
|= WINEDDSD_CKSRCOVERLAY
;
287 case WINEDDCKEY_SRCBLT
:
288 This
->SrcBltCKey
= *CKey
;
289 This
->CKeyFlags
|= WINEDDSD_CKSRCBLT
;
294 switch (Flags
& ~WINEDDCKEY_COLORSPACE
) {
295 case WINEDDCKEY_DESTBLT
:
296 This
->CKeyFlags
&= ~WINEDDSD_CKDESTBLT
;
299 case WINEDDCKEY_DESTOVERLAY
:
300 This
->CKeyFlags
&= ~WINEDDSD_CKDESTOVERLAY
;
303 case WINEDDCKEY_SRCOVERLAY
:
304 This
->CKeyFlags
&= ~WINEDDSD_CKSRCOVERLAY
;
307 case WINEDDCKEY_SRCBLT
:
308 This
->CKeyFlags
&= ~WINEDDSD_CKSRCBLT
;
316 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface
*iface
, IWineD3DPalette
**Pal
) {
317 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
318 TRACE("(%p)->(%p)\n", This
, Pal
);
320 *Pal
= (IWineD3DPalette
*) This
->palette
;
324 DWORD WINAPI
IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface
*iface
) {
325 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
326 const struct wined3d_format_desc
*format_desc
= This
->resource
.format_desc
;
328 TRACE("(%p)\n", This
);
330 if (format_desc
->Flags
& WINED3DFMT_FLAG_COMPRESSED
)
332 /* Since compressed formats are block based, pitch means the amount of
333 * bytes to the next row of block rather than the next row of pixels. */
334 UINT row_block_count
= (This
->currentDesc
.Width
+ format_desc
->block_width
- 1) / format_desc
->block_width
;
335 ret
= row_block_count
* format_desc
->block_byte_count
;
339 unsigned char alignment
= This
->resource
.device
->surface_alignment
;
340 ret
= This
->resource
.format_desc
->byte_count
* This
->currentDesc
.Width
; /* Bytes / row */
341 ret
= (ret
+ alignment
- 1) & ~(alignment
- 1);
343 TRACE("(%p) Returning %d\n", This
, ret
);
347 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface
*iface
, LONG X
, LONG Y
) {
348 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
351 TRACE("(%p)->(%d,%d) Stub!\n", This
, X
, Y
);
353 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
355 TRACE("(%p): Not an overlay surface\n", This
);
356 return WINEDDERR_NOTAOVERLAYSURFACE
;
359 w
= This
->overlay_destrect
.right
- This
->overlay_destrect
.left
;
360 h
= This
->overlay_destrect
.bottom
- This
->overlay_destrect
.top
;
361 This
->overlay_destrect
.left
= X
;
362 This
->overlay_destrect
.top
= Y
;
363 This
->overlay_destrect
.right
= X
+ w
;
364 This
->overlay_destrect
.bottom
= Y
+ h
;
366 IWineD3DSurface_DrawOverlay(iface
);
371 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface
*iface
, LONG
*X
, LONG
*Y
) {
372 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
375 TRACE("(%p)->(%p,%p)\n", This
, X
, Y
);
377 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
379 TRACE("(%p): Not an overlay surface\n", This
);
380 return WINEDDERR_NOTAOVERLAYSURFACE
;
382 if(This
->overlay_dest
== NULL
) {
384 hr
= WINEDDERR_OVERLAYNOTVISIBLE
;
386 *X
= This
->overlay_destrect
.left
;
387 *Y
= This
->overlay_destrect
.top
;
391 TRACE("Returning 0x%08x, position %d, %d\n", hr
, *X
, *Y
);
395 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface
*iface
, DWORD Flags
, IWineD3DSurface
*Ref
) {
396 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
398 FIXME("iface %p, flags %#x, ref %p stub!\n", iface
, Flags
, Ref
);
400 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
402 TRACE("(%p): Not an overlay surface\n", This
);
403 return WINEDDERR_NOTAOVERLAYSURFACE
;
409 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface
*iface
, const RECT
*SrcRect
,
410 IWineD3DSurface
*DstSurface
, const RECT
*DstRect
, DWORD Flags
, const WINEDDOVERLAYFX
*FX
)
412 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
413 IWineD3DSurfaceImpl
*Dst
= (IWineD3DSurfaceImpl
*) DstSurface
;
414 TRACE("(%p)->(%p, %p, %p, %08x, %p)\n", This
, SrcRect
, Dst
, DstRect
, Flags
, FX
);
416 if(!(This
->resource
.usage
& WINED3DUSAGE_OVERLAY
))
418 WARN("(%p): Not an overlay surface\n", This
);
419 return WINEDDERR_NOTAOVERLAYSURFACE
;
420 } else if(!DstSurface
) {
421 WARN("(%p): Dest surface is NULL\n", This
);
422 return WINED3DERR_INVALIDCALL
;
426 This
->overlay_srcrect
= *SrcRect
;
428 This
->overlay_srcrect
.left
= 0;
429 This
->overlay_srcrect
.top
= 0;
430 This
->overlay_srcrect
.right
= This
->currentDesc
.Width
;
431 This
->overlay_srcrect
.bottom
= This
->currentDesc
.Height
;
435 This
->overlay_destrect
= *DstRect
;
437 This
->overlay_destrect
.left
= 0;
438 This
->overlay_destrect
.top
= 0;
439 This
->overlay_destrect
.right
= Dst
? Dst
->currentDesc
.Width
: 0;
440 This
->overlay_destrect
.bottom
= Dst
? Dst
->currentDesc
.Height
: 0;
443 if(This
->overlay_dest
&& (This
->overlay_dest
!= Dst
|| Flags
& WINEDDOVER_HIDE
)) {
444 list_remove(&This
->overlay_entry
);
447 if(Flags
& WINEDDOVER_SHOW
) {
448 if(This
->overlay_dest
!= Dst
) {
449 This
->overlay_dest
= Dst
;
450 list_add_tail(&Dst
->overlays
, &This
->overlay_entry
);
452 } else if(Flags
& WINEDDOVER_HIDE
) {
453 /* tests show that the rectangles are erased on hide */
454 This
->overlay_srcrect
.left
= 0; This
->overlay_srcrect
.top
= 0;
455 This
->overlay_srcrect
.right
= 0; This
->overlay_srcrect
.bottom
= 0;
456 This
->overlay_destrect
.left
= 0; This
->overlay_destrect
.top
= 0;
457 This
->overlay_destrect
.right
= 0; This
->overlay_destrect
.bottom
= 0;
458 This
->overlay_dest
= NULL
;
461 IWineD3DSurface_DrawOverlay(iface
);
466 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface
*iface
, IWineD3DClipper
*clipper
)
468 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
469 TRACE("(%p)->(%p)\n", This
, clipper
);
471 This
->clipper
= clipper
;
475 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface
*iface
, IWineD3DClipper
**clipper
)
477 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
478 TRACE("(%p)->(%p)\n", This
, clipper
);
480 *clipper
= This
->clipper
;
482 IWineD3DClipper_AddRef(*clipper
);
487 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetContainer(IWineD3DSurface
*iface
, IWineD3DBase
*container
) {
488 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
490 TRACE("This %p, container %p\n", This
, container
);
492 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
494 TRACE("Setting container to %p from %p\n", container
, This
->container
);
495 This
->container
= container
;
500 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface
*iface
, WINED3DFORMAT format
) {
501 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
502 const struct wined3d_format_desc
*format_desc
= getFormatDescEntry(format
,
503 &This
->resource
.device
->adapter
->gl_info
);
505 if (This
->resource
.format_desc
->format
!= WINED3DFMT_UNKNOWN
)
507 FIXME("(%p) : The format of the surface must be WINED3DFORMAT_UNKNOWN\n", This
);
508 return WINED3DERR_INVALIDCALL
;
511 TRACE("(%p) : Setting texture format to (%d,%s)\n", This
, format
, debug_d3dformat(format
));
513 This
->resource
.size
= surface_calculate_size(format_desc
, This
->resource
.device
->surface_alignment
,
514 This
->pow2Width
, This
->pow2Height
);
516 This
->Flags
|= (WINED3DFMT_D16_LOCKABLE
== format
) ? SFLAG_LOCKABLE
: 0;
518 This
->resource
.format_desc
= format_desc
;
520 TRACE("(%p) : Size %d, bytesPerPixel %d\n", This
, This
->resource
.size
, format_desc
->byte_count
);
525 HRESULT
IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface
*iface
) {
526 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
527 const struct wined3d_format_desc
*format_desc
= This
->resource
.format_desc
;
535 if(!(format_desc
->Flags
& WINED3DFMT_FLAG_GETDC
))
537 WARN("Cannot use GetDC on a %s surface\n", debug_d3dformat(format_desc
->format
));
538 return WINED3DERR_INVALIDCALL
;
541 switch (format_desc
->byte_count
)
545 /* Allocate extra space to store the RGB bit masks. */
546 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 3 * sizeof(DWORD
));
550 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
));
554 /* Allocate extra space for a palette. */
555 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
556 sizeof(BITMAPINFOHEADER
) + sizeof(RGBQUAD
) * (1 << (format_desc
->byte_count
* 8)));
561 return E_OUTOFMEMORY
;
563 /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
564 * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
565 * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
566 * add an extra line to the dib section
568 GetSystemInfo(&sysInfo
);
569 if( ((This
->resource
.size
+ 3) % sysInfo
.dwPageSize
) < 4) {
571 TRACE("Adding an extra line to the dib section\n");
574 b_info
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
575 /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
576 b_info
->bmiHeader
.biWidth
= IWineD3DSurface_GetPitch(iface
) / format_desc
->byte_count
;
577 b_info
->bmiHeader
.biHeight
= -This
->currentDesc
.Height
-extraline
;
578 b_info
->bmiHeader
.biSizeImage
= ( This
->currentDesc
.Height
+ extraline
) * IWineD3DSurface_GetPitch(iface
);
579 b_info
->bmiHeader
.biPlanes
= 1;
580 b_info
->bmiHeader
.biBitCount
= format_desc
->byte_count
* 8;
582 b_info
->bmiHeader
.biXPelsPerMeter
= 0;
583 b_info
->bmiHeader
.biYPelsPerMeter
= 0;
584 b_info
->bmiHeader
.biClrUsed
= 0;
585 b_info
->bmiHeader
.biClrImportant
= 0;
587 /* Get the bit masks */
588 masks
= (DWORD
*)b_info
->bmiColors
;
589 switch (This
->resource
.format_desc
->format
)
591 case WINED3DFMT_B8G8R8_UNORM
:
592 usage
= DIB_RGB_COLORS
;
593 b_info
->bmiHeader
.biCompression
= BI_RGB
;
596 case WINED3DFMT_B5G5R5X1_UNORM
:
597 case WINED3DFMT_B5G5R5A1_UNORM
:
598 case WINED3DFMT_B4G4R4A4_UNORM
:
599 case WINED3DFMT_B4G4R4X4_UNORM
:
600 case WINED3DFMT_B2G3R3_UNORM
:
601 case WINED3DFMT_B2G3R3A8_UNORM
:
602 case WINED3DFMT_R10G10B10A2_UNORM
:
603 case WINED3DFMT_R8G8B8A8_UNORM
:
604 case WINED3DFMT_R8G8B8X8_UNORM
:
605 case WINED3DFMT_B10G10R10A2_UNORM
:
606 case WINED3DFMT_B5G6R5_UNORM
:
607 case WINED3DFMT_R16G16B16A16_UNORM
:
609 b_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
610 masks
[0] = format_desc
->red_mask
;
611 masks
[1] = format_desc
->green_mask
;
612 masks
[2] = format_desc
->blue_mask
;
616 /* Don't know palette */
617 b_info
->bmiHeader
.biCompression
= BI_RGB
;
624 HeapFree(GetProcessHeap(), 0, b_info
);
625 return HRESULT_FROM_WIN32(GetLastError());
628 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
);
629 This
->dib
.DIBsection
= CreateDIBSection(ddc
, b_info
, usage
, &This
->dib
.bitmap_data
, 0 /* Handle */, 0 /* Offset */);
632 if (!This
->dib
.DIBsection
) {
633 ERR("CreateDIBSection failed!\n");
634 HeapFree(GetProcessHeap(), 0, b_info
);
635 return HRESULT_FROM_WIN32(GetLastError());
638 TRACE("DIBSection at : %p\n", This
->dib
.bitmap_data
);
639 /* copy the existing surface to the dib section */
640 if(This
->resource
.allocatedMemory
) {
641 memcpy(This
->dib
.bitmap_data
, This
->resource
.allocatedMemory
, This
->currentDesc
.Height
* IWineD3DSurface_GetPitch(iface
));
643 /* This is to make LockRect read the gl Texture although memory is allocated */
644 This
->Flags
&= ~SFLAG_INSYSMEM
;
646 This
->dib
.bitmap_size
= b_info
->bmiHeader
.biSizeImage
;
648 HeapFree(GetProcessHeap(), 0, b_info
);
650 /* Now allocate a HDC */
651 This
->hDC
= CreateCompatibleDC(0);
652 This
->dib
.holdbitmap
= SelectObject(This
->hDC
, This
->dib
.DIBsection
);
653 TRACE("using wined3d palette %p\n", This
->palette
);
654 SelectPalette(This
->hDC
,
655 This
->palette
? This
->palette
->hpal
: 0,
658 This
->Flags
|= SFLAG_DIBSECTION
;
660 HeapFree(GetProcessHeap(), 0, This
->resource
.heapMemory
);
661 This
->resource
.heapMemory
= NULL
;
666 static void convert_r32_float_r16_float(const BYTE
*src
, BYTE
*dst
, DWORD pitch_in
, DWORD pitch_out
,
667 unsigned int w
, unsigned int h
)
671 unsigned short *dst_s
;
673 TRACE("Converting %dx%d pixels, pitches %d %d\n", w
, h
, pitch_in
, pitch_out
);
674 for(y
= 0; y
< h
; y
++) {
675 src_f
= (const float *)(src
+ y
* pitch_in
);
676 dst_s
= (unsigned short *) (dst
+ y
* pitch_out
);
677 for(x
= 0; x
< w
; x
++) {
678 dst_s
[x
] = float_32_to_16(src_f
+ x
);
683 static void convert_r5g6b5_x8r8g8b8(const BYTE
*src
, BYTE
*dst
,
684 DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
)
686 static const unsigned char convert_5to8
[] =
688 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
689 0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
690 0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
691 0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
693 static const unsigned char convert_6to8
[] =
695 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
696 0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d,
697 0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d,
698 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
699 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
700 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
701 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf,
702 0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff,
706 TRACE("Converting %ux%u pixels, pitches %u %u\n", w
, h
, pitch_in
, pitch_out
);
708 for (y
= 0; y
< h
; ++y
)
710 const WORD
*src_line
= (const WORD
*)(src
+ y
* pitch_in
);
711 DWORD
*dst_line
= (DWORD
*)(dst
+ y
* pitch_out
);
712 for (x
= 0; x
< w
; ++x
)
714 WORD pixel
= src_line
[x
];
715 dst_line
[x
] = 0xff000000
716 | convert_5to8
[(pixel
& 0xf800) >> 11] << 16
717 | convert_6to8
[(pixel
& 0x07e0) >> 5] << 8
718 | convert_5to8
[(pixel
& 0x001f)];
723 static void convert_a8r8g8b8_x8r8g8b8(const BYTE
*src
, BYTE
*dst
,
724 DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
)
728 TRACE("Converting %ux%u pixels, pitches %u %u\n", w
, h
, pitch_in
, pitch_out
);
730 for (y
= 0; y
< h
; ++y
)
732 const DWORD
*src_line
= (const DWORD
*)(src
+ y
* pitch_in
);
733 DWORD
*dst_line
= (DWORD
*)(dst
+ y
* pitch_out
);
735 for (x
= 0; x
< w
; ++x
)
737 dst_line
[x
] = 0xff000000 | (src_line
[x
] & 0xffffff);
742 static inline BYTE
cliptobyte(int x
)
744 return (BYTE
) ((x
< 0) ? 0 : ((x
> 255) ? 255 : x
));
747 static void convert_yuy2_x8r8g8b8(const BYTE
*src
, BYTE
*dst
,
748 DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
)
751 int c2
, d
, e
, r2
= 0, g2
= 0, b2
= 0;
753 TRACE("Converting %ux%u pixels, pitches %u %u\n", w
, h
, pitch_in
, pitch_out
);
755 for (y
= 0; y
< h
; ++y
)
757 const BYTE
*src_line
= src
+ y
* pitch_in
;
758 DWORD
*dst_line
= (DWORD
*)(dst
+ y
* pitch_out
);
759 for (x
= 0; x
< w
; ++x
)
761 /* YUV to RGB conversion formulas from http://en.wikipedia.org/wiki/YUV:
762 * C = Y - 16; D = U - 128; E = V - 128;
763 * R = cliptobyte((298 * C + 409 * E + 128) >> 8);
764 * G = cliptobyte((298 * C - 100 * D - 208 * E + 128) >> 8);
765 * B = cliptobyte((298 * C + 516 * D + 128) >> 8);
766 * Two adjacent YUY2 pixels are stored as four bytes: Y0 U Y1 V .
767 * U and V are shared between the pixels.
769 if (!(x
& 1)) /* for every even pixel, read new U and V */
771 d
= (int) src_line
[1] - 128;
772 e
= (int) src_line
[3] - 128;
774 g2
= - 100 * d
- 208 * e
+ 128;
777 c2
= 298 * ((int) src_line
[0] - 16);
778 dst_line
[x
] = 0xff000000
779 | cliptobyte((c2
+ r2
) >> 8) << 16 /* red */
780 | cliptobyte((c2
+ g2
) >> 8) << 8 /* green */
781 | cliptobyte((c2
+ b2
) >> 8); /* blue */
782 /* Scale RGB values to 0..255 range,
783 * then clip them if still not in range (may be negative),
784 * then shift them within DWORD if necessary.
791 struct d3dfmt_convertor_desc
{
792 WINED3DFORMAT from
, to
;
793 void (*convert
)(const BYTE
*src
, BYTE
*dst
, DWORD pitch_in
, DWORD pitch_out
, unsigned int w
, unsigned int h
);
796 static const struct d3dfmt_convertor_desc convertors
[] =
798 {WINED3DFMT_R32_FLOAT
, WINED3DFMT_R16_FLOAT
, convert_r32_float_r16_float
},
799 {WINED3DFMT_B5G6R5_UNORM
, WINED3DFMT_B8G8R8X8_UNORM
, convert_r5g6b5_x8r8g8b8
},
800 {WINED3DFMT_B8G8R8A8_UNORM
, WINED3DFMT_B8G8R8X8_UNORM
, convert_a8r8g8b8_x8r8g8b8
},
801 {WINED3DFMT_YUY2
, WINED3DFMT_B8G8R8X8_UNORM
, convert_yuy2_x8r8g8b8
},
804 static inline const struct d3dfmt_convertor_desc
*find_convertor(WINED3DFORMAT from
, WINED3DFORMAT to
)
807 for(i
= 0; i
< (sizeof(convertors
) / sizeof(convertors
[0])); i
++) {
808 if(convertors
[i
].from
== from
&& convertors
[i
].to
== to
) {
809 return &convertors
[i
];
815 /*****************************************************************************
816 * surface_convert_format
818 * Creates a duplicate of a surface in a different format. Is used by Blt to
819 * blit between surfaces with different formats
822 * source: Source surface
823 * fmt: Requested destination format
825 *****************************************************************************/
826 static IWineD3DSurfaceImpl
*surface_convert_format(IWineD3DSurfaceImpl
*source
, WINED3DFORMAT to_fmt
) {
827 IWineD3DSurface
*ret
= NULL
;
828 const struct d3dfmt_convertor_desc
*conv
;
829 WINED3DLOCKED_RECT lock_src
, lock_dst
;
832 conv
= find_convertor(source
->resource
.format_desc
->format
, to_fmt
);
834 FIXME("Cannot find a conversion function from format %s to %s\n",
835 debug_d3dformat(source
->resource
.format_desc
->format
), debug_d3dformat(to_fmt
));
839 IWineD3DDevice_CreateSurface((IWineD3DDevice
*)source
->resource
.device
, source
->currentDesc
.Width
,
840 source
->currentDesc
.Height
, to_fmt
, TRUE
/* lockable */, TRUE
/* discard */, 0 /* level */, &ret
,
841 0 /* usage */, WINED3DPOOL_SCRATCH
, WINED3DMULTISAMPLE_NONE
/* TODO: Multisampled conversion */,
842 0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface
*) source
),
843 NULL
/* parent */, &wined3d_null_parent_ops
);
845 ERR("Failed to create a destination surface for conversion\n");
849 memset(&lock_src
, 0, sizeof(lock_src
));
850 memset(&lock_dst
, 0, sizeof(lock_dst
));
852 hr
= IWineD3DSurface_LockRect((IWineD3DSurface
*) source
, &lock_src
, NULL
, WINED3DLOCK_READONLY
);
854 ERR("Failed to lock the source surface\n");
855 IWineD3DSurface_Release(ret
);
858 hr
= IWineD3DSurface_LockRect(ret
, &lock_dst
, NULL
, WINED3DLOCK_READONLY
);
860 ERR("Failed to lock the dest surface\n");
861 IWineD3DSurface_UnlockRect((IWineD3DSurface
*) source
);
862 IWineD3DSurface_Release(ret
);
866 conv
->convert(lock_src
.pBits
, lock_dst
.pBits
, lock_src
.Pitch
, lock_dst
.Pitch
,
867 source
->currentDesc
.Width
, source
->currentDesc
.Height
);
869 IWineD3DSurface_UnlockRect(ret
);
870 IWineD3DSurface_UnlockRect((IWineD3DSurface
*) source
);
872 return (IWineD3DSurfaceImpl
*) ret
;
875 /*****************************************************************************
878 * Helper function that fills a memory area with a specific color
881 * buf: memory address to start filling at
882 * width, height: Dimensions of the area to fill
883 * bpp: Bit depth of the surface
884 * lPitch: pitch of the surface
885 * color: Color to fill with
887 *****************************************************************************/
889 _Blt_ColorFill(BYTE
*buf
,
890 int width
, int height
,
891 int bpp
, LONG lPitch
,
899 #define COLORFILL_ROW(type) \
901 type *d = (type *) buf; \
902 for (x = 0; x < width; x++) \
903 d[x] = (type) color; \
908 case 1: COLORFILL_ROW(BYTE
)
909 case 2: COLORFILL_ROW(WORD
)
913 for (x
= 0; x
< width
; x
++,d
+=3)
915 d
[0] = (color
) & 0xFF;
916 d
[1] = (color
>> 8) & 0xFF;
917 d
[2] = (color
>>16) & 0xFF;
921 case 4: COLORFILL_ROW(DWORD
)
923 FIXME("Color fill not implemented for bpp %d!\n", bpp
*8);
924 return WINED3DERR_NOTAVAILABLE
;
929 /* Now copy first row */
931 for (y
= 1; y
< height
; y
++)
934 memcpy(buf
, first
, width
* bpp
);
939 /*****************************************************************************
940 * IWineD3DSurface::Blt, SW emulation version
942 * Performs a blit to a surface, with or without a source surface.
943 * This is the main functionality of DirectDraw
946 * DestRect: Destination rectangle to write to
947 * SrcSurface: Source surface, can be NULL
948 * SrcRect: Source rectangle
949 *****************************************************************************/
950 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface
*iface
, const RECT
*DestRect
, IWineD3DSurface
*SrcSurface
,
951 const RECT
*SrcRect
, DWORD Flags
, const WINEDDBLTFX
*DDBltFx
, WINED3DTEXTUREFILTERTYPE Filter
)
953 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
954 IWineD3DSurfaceImpl
*Src
= (IWineD3DSurfaceImpl
*) SrcSurface
;
956 HRESULT ret
= WINED3D_OK
;
957 WINED3DLOCKED_RECT dlock
, slock
;
958 int bpp
, srcheight
, srcwidth
, dstheight
, dstwidth
, width
;
959 const struct wined3d_format_desc
*sEntry
, *dEntry
;
963 TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This
, DestRect
, Src
, SrcRect
, Flags
, DDBltFx
);
965 if (TRACE_ON(d3d_surface
))
967 if (DestRect
) TRACE("\tdestrect :%dx%d-%dx%d\n",
968 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
969 if (SrcRect
) TRACE("\tsrcrect :%dx%d-%dx%d\n",
970 SrcRect
->left
, SrcRect
->top
, SrcRect
->right
, SrcRect
->bottom
);
973 DDRAW_dump_DDBLT(Flags
);
974 if (Flags
& WINEDDBLT_DDFX
)
977 DDRAW_dump_DDBLTFX(DDBltFx
->dwDDFX
);
982 if ( (This
->Flags
& SFLAG_LOCKED
) || ((Src
!= NULL
) && (Src
->Flags
& SFLAG_LOCKED
)))
984 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
985 return WINEDDERR_SURFACEBUSY
;
988 if(Filter
!= WINED3DTEXF_NONE
&& Filter
!= WINED3DTEXF_POINT
) {
989 /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
990 FIXME("Filters not supported in software blit\n");
993 /* First check for the validity of source / destination rectangles.
994 * This was verified using a test application + by MSDN. */
1000 if (SrcRect
->right
< SrcRect
->left
|| SrcRect
->bottom
< SrcRect
->top
1001 || SrcRect
->left
> Src
->currentDesc
.Width
|| SrcRect
->left
< 0
1002 || SrcRect
->top
> Src
->currentDesc
.Height
|| SrcRect
->top
< 0
1003 || SrcRect
->right
> Src
->currentDesc
.Width
|| SrcRect
->right
< 0
1004 || SrcRect
->bottom
> Src
->currentDesc
.Height
|| SrcRect
->bottom
< 0)
1006 WARN("Application gave us bad source rectangle for Blt.\n");
1007 return WINEDDERR_INVALIDRECT
;
1010 if (!SrcRect
->right
|| !SrcRect
->bottom
1011 || SrcRect
->left
== (int)Src
->currentDesc
.Width
1012 || SrcRect
->top
== (int)Src
->currentDesc
.Height
)
1014 TRACE("Nothing to be done.\n");
1025 xsrc
.right
= Src
->currentDesc
.Width
;
1026 xsrc
.bottom
= Src
->currentDesc
.Height
;
1030 memset(&xsrc
, 0, sizeof(xsrc
));
1035 /* For the Destination rect, it can be out of bounds on the condition
1036 * that a clipper is set for the given surface. */
1037 if (!This
->clipper
&& (DestRect
->right
< DestRect
->left
|| DestRect
->bottom
< DestRect
->top
1038 || DestRect
->left
> This
->currentDesc
.Width
|| DestRect
->left
< 0
1039 || DestRect
->top
> This
->currentDesc
.Height
|| DestRect
->top
< 0
1040 || DestRect
->right
> This
->currentDesc
.Width
|| DestRect
->right
< 0
1041 || DestRect
->bottom
> This
->currentDesc
.Height
|| DestRect
->bottom
< 0))
1043 WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
1044 return WINEDDERR_INVALIDRECT
;
1047 if (DestRect
->right
<= 0 || DestRect
->bottom
<= 0
1048 || DestRect
->left
>= (int)This
->currentDesc
.Width
1049 || DestRect
->top
>= (int)This
->currentDesc
.Height
)
1051 TRACE("Nothing to be done.\n");
1061 full_rect
.right
= This
->currentDesc
.Width
;
1062 full_rect
.bottom
= This
->currentDesc
.Height
;
1063 IntersectRect(&xdst
, &full_rect
, DestRect
);
1067 BOOL clip_horiz
, clip_vert
;
1070 clip_horiz
= xdst
.left
< 0 || xdst
.right
> (int)This
->currentDesc
.Width
;
1071 clip_vert
= xdst
.top
< 0 || xdst
.bottom
> (int)This
->currentDesc
.Height
;
1073 if (clip_vert
|| clip_horiz
)
1075 /* Now check if this is a special case or not... */
1076 if ((Flags
& WINEDDBLT_DDFX
)
1077 || (clip_horiz
&& xdst
.right
- xdst
.left
!= xsrc
.right
- xsrc
.left
)
1078 || (clip_vert
&& xdst
.bottom
- xdst
.top
!= xsrc
.bottom
- xsrc
.top
))
1080 WARN("Out of screen rectangle in special case. Not handled right now.\n");
1088 xsrc
.left
-= xdst
.left
;
1091 if (xdst
.right
> This
->currentDesc
.Width
)
1093 xsrc
.right
-= (xdst
.right
- (int)This
->currentDesc
.Width
);
1094 xdst
.right
= (int)This
->currentDesc
.Width
;
1102 xsrc
.top
-= xdst
.top
;
1105 if (xdst
.bottom
> This
->currentDesc
.Height
)
1107 xsrc
.bottom
-= (xdst
.bottom
- (int)This
->currentDesc
.Height
);
1108 xdst
.bottom
= (int)This
->currentDesc
.Height
;
1112 /* And check if after clipping something is still to be done... */
1113 if ((xdst
.right
<= 0) || (xdst
.bottom
<= 0)
1114 || (xdst
.left
>= (int)This
->currentDesc
.Width
)
1115 || (xdst
.top
>= (int)This
->currentDesc
.Height
)
1116 || (xsrc
.right
<= 0) || (xsrc
.bottom
<= 0)
1117 || (xsrc
.left
>= (int) Src
->currentDesc
.Width
)
1118 || (xsrc
.top
>= (int)Src
->currentDesc
.Height
))
1120 TRACE("Nothing to be done after clipping.\n");
1130 xdst
.right
= This
->currentDesc
.Width
;
1131 xdst
.bottom
= This
->currentDesc
.Height
;
1136 IWineD3DSurface_LockRect(iface
, &dlock
, NULL
, 0);
1138 sEntry
= This
->resource
.format_desc
;
1143 dEntry
= This
->resource
.format_desc
;
1146 if (This
->resource
.format_desc
->format
!= Src
->resource
.format_desc
->format
)
1148 Src
= surface_convert_format(Src
, dEntry
->format
);
1150 /* The conv function writes a FIXME */
1151 WARN("Cannot convert source surface format to dest format\n");
1155 IWineD3DSurface_LockRect((IWineD3DSurface
*) Src
, &slock
, NULL
, WINED3DLOCK_READONLY
);
1156 sEntry
= Src
->resource
.format_desc
;
1163 IWineD3DSurface_LockRect(iface
, &dlock
, &xdst
, 0);
1165 IWineD3DSurface_LockRect(iface
, &dlock
, NULL
, 0);
1168 if (!DDBltFx
|| !(DDBltFx
->dwDDFX
)) Flags
&= ~WINEDDBLT_DDFX
;
1170 if (sEntry
->Flags
& dEntry
->Flags
& WINED3DFMT_FLAG_FOURCC
)
1172 if (!DestRect
|| Src
== This
)
1174 memcpy(dlock
.pBits
, slock
.pBits
, This
->resource
.size
);
1179 bpp
= This
->resource
.format_desc
->byte_count
;
1180 srcheight
= xsrc
.bottom
- xsrc
.top
;
1181 srcwidth
= xsrc
.right
- xsrc
.left
;
1182 dstheight
= xdst
.bottom
- xdst
.top
;
1183 dstwidth
= xdst
.right
- xdst
.left
;
1184 width
= (xdst
.right
- xdst
.left
) * bpp
;
1186 if (DestRect
&& Src
!= This
)
1189 dbuf
= (BYTE
*)dlock
.pBits
+(xdst
.top
*dlock
.Pitch
)+(xdst
.left
*bpp
);
1191 if (Flags
& WINEDDBLT_WAIT
)
1193 Flags
&= ~WINEDDBLT_WAIT
;
1195 if (Flags
& WINEDDBLT_ASYNC
)
1197 static BOOL displayed
= FALSE
;
1199 FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n");
1201 Flags
&= ~WINEDDBLT_ASYNC
;
1203 if (Flags
& WINEDDBLT_DONOTWAIT
)
1205 /* WINEDDBLT_DONOTWAIT appeared in DX7 */
1206 static BOOL displayed
= FALSE
;
1208 FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n");
1210 Flags
&= ~WINEDDBLT_DONOTWAIT
;
1213 /* First, all the 'source-less' blits */
1214 if (Flags
& WINEDDBLT_COLORFILL
)
1216 ret
= _Blt_ColorFill(dbuf
, dstwidth
, dstheight
, bpp
,
1217 dlock
.Pitch
, DDBltFx
->u5
.dwFillColor
);
1218 Flags
&= ~WINEDDBLT_COLORFILL
;
1221 if (Flags
& WINEDDBLT_DEPTHFILL
)
1223 FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
1225 if (Flags
& WINEDDBLT_ROP
)
1227 /* Catch some degenerate cases here */
1228 switch(DDBltFx
->dwROP
)
1231 ret
= _Blt_ColorFill(dbuf
,dstwidth
,dstheight
,bpp
,dlock
.Pitch
,0);
1233 case 0xAA0029: /* No-op */
1236 ret
= _Blt_ColorFill(dbuf
,dstwidth
,dstheight
,bpp
,dlock
.Pitch
,~0);
1238 case SRCCOPY
: /* well, we do that below ? */
1241 FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx
->dwROP
, DDBltFx
->u5
.lpDDSPattern
);
1244 Flags
&= ~WINEDDBLT_ROP
;
1246 if (Flags
& WINEDDBLT_DDROPS
)
1248 FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx
->dwDDROP
, DDBltFx
->u5
.lpDDSPattern
);
1250 /* Now the 'with source' blits */
1254 int sx
, xinc
, sy
, yinc
;
1256 if (!dstwidth
|| !dstheight
) /* hmm... stupid program ? */
1258 sbase
= (BYTE
*)slock
.pBits
+(xsrc
.top
*slock
.Pitch
)+xsrc
.left
*bpp
;
1259 xinc
= (srcwidth
<< 16) / dstwidth
;
1260 yinc
= (srcheight
<< 16) / dstheight
;
1264 /* No effects, we can cheat here */
1265 if (dstwidth
== srcwidth
)
1267 if (dstheight
== srcheight
)
1269 /* No stretching in either direction. This needs to be as
1270 * fast as possible */
1273 /* check for overlapping surfaces */
1274 if (Src
!= This
|| xdst
.top
< xsrc
.top
||
1275 xdst
.right
<= xsrc
.left
|| xsrc
.right
<= xdst
.left
)
1277 /* no overlap, or dst above src, so copy from top downwards */
1278 for (y
= 0; y
< dstheight
; y
++)
1280 memcpy(dbuf
, sbuf
, width
);
1281 sbuf
+= slock
.Pitch
;
1282 dbuf
+= dlock
.Pitch
;
1285 else if (xdst
.top
> xsrc
.top
) /* copy from bottom upwards */
1287 sbuf
+= (slock
.Pitch
*dstheight
);
1288 dbuf
+= (dlock
.Pitch
*dstheight
);
1289 for (y
= 0; y
< dstheight
; y
++)
1291 sbuf
-= slock
.Pitch
;
1292 dbuf
-= dlock
.Pitch
;
1293 memcpy(dbuf
, sbuf
, width
);
1296 else /* src and dst overlapping on the same line, use memmove */
1298 for (y
= 0; y
< dstheight
; y
++)
1300 memmove(dbuf
, sbuf
, width
);
1301 sbuf
+= slock
.Pitch
;
1302 dbuf
+= dlock
.Pitch
;
1306 /* Stretching in Y direction only */
1307 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
) {
1308 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1309 memcpy(dbuf
, sbuf
, width
);
1310 dbuf
+= dlock
.Pitch
;
1316 /* Stretching in X direction */
1318 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
)
1320 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1322 if ((sy
>> 16) == (last_sy
>> 16))
1324 /* this sourcerow is the same as last sourcerow -
1325 * copy already stretched row
1327 memcpy(dbuf
, dbuf
- dlock
.Pitch
, width
);
1331 #define STRETCH_ROW(type) { \
1332 const type *s = (const type *)sbuf; \
1333 type *d = (type *)dbuf; \
1334 for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
1335 d[x] = s[sx >> 16]; \
1340 case 1: STRETCH_ROW(BYTE
)
1341 case 2: STRETCH_ROW(WORD
)
1342 case 4: STRETCH_ROW(DWORD
)
1347 for (x
= sx
= 0; x
< dstwidth
; x
++, sx
+= xinc
)
1351 s
= sbuf
+3*(sx
>>16);
1352 pixel
= s
[0]|(s
[1]<<8)|(s
[2]<<16);
1353 d
[0] = (pixel
)&0xff;
1354 d
[1] = (pixel
>> 8)&0xff;
1355 d
[2] = (pixel
>>16)&0xff;
1361 FIXME("Stretched blit not implemented for bpp %d!\n", bpp
*8);
1362 ret
= WINED3DERR_NOTAVAILABLE
;
1367 dbuf
+= dlock
.Pitch
;
1374 LONG dstyinc
= dlock
.Pitch
, dstxinc
= bpp
;
1375 DWORD keylow
= 0xFFFFFFFF, keyhigh
= 0, keymask
= 0xFFFFFFFF;
1376 DWORD destkeylow
= 0x0, destkeyhigh
= 0xFFFFFFFF, destkeymask
= 0xFFFFFFFF;
1377 if (Flags
& (WINEDDBLT_KEYSRC
| WINEDDBLT_KEYDEST
| WINEDDBLT_KEYSRCOVERRIDE
| WINEDDBLT_KEYDESTOVERRIDE
))
1379 /* The color keying flags are checked for correctness in ddraw */
1380 if (Flags
& WINEDDBLT_KEYSRC
)
1382 keylow
= Src
->SrcBltCKey
.dwColorSpaceLowValue
;
1383 keyhigh
= Src
->SrcBltCKey
.dwColorSpaceHighValue
;
1385 else if (Flags
& WINEDDBLT_KEYSRCOVERRIDE
)
1387 keylow
= DDBltFx
->ddckSrcColorkey
.dwColorSpaceLowValue
;
1388 keyhigh
= DDBltFx
->ddckSrcColorkey
.dwColorSpaceHighValue
;
1391 if (Flags
& WINEDDBLT_KEYDEST
)
1393 /* Destination color keys are taken from the source surface ! */
1394 destkeylow
= Src
->DestBltCKey
.dwColorSpaceLowValue
;
1395 destkeyhigh
= Src
->DestBltCKey
.dwColorSpaceHighValue
;
1397 else if (Flags
& WINEDDBLT_KEYDESTOVERRIDE
)
1399 destkeylow
= DDBltFx
->ddckDestColorkey
.dwColorSpaceLowValue
;
1400 destkeyhigh
= DDBltFx
->ddckDestColorkey
.dwColorSpaceHighValue
;
1409 keymask
= sEntry
->red_mask
1410 | sEntry
->green_mask
1411 | sEntry
->blue_mask
;
1413 Flags
&= ~(WINEDDBLT_KEYSRC
| WINEDDBLT_KEYDEST
| WINEDDBLT_KEYSRCOVERRIDE
| WINEDDBLT_KEYDESTOVERRIDE
);
1416 if (Flags
& WINEDDBLT_DDFX
)
1418 LPBYTE dTopLeft
, dTopRight
, dBottomLeft
, dBottomRight
, tmp
;
1421 dTopRight
= dbuf
+((dstwidth
-1)*bpp
);
1422 dBottomLeft
= dTopLeft
+((dstheight
-1)*dlock
.Pitch
);
1423 dBottomRight
= dBottomLeft
+((dstwidth
-1)*bpp
);
1425 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ARITHSTRETCHY
)
1427 /* I don't think we need to do anything about this flag */
1428 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
1430 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_MIRRORLEFTRIGHT
)
1433 dTopRight
= dTopLeft
;
1436 dBottomRight
= dBottomLeft
;
1438 dstxinc
= dstxinc
*-1;
1440 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_MIRRORUPDOWN
)
1443 dTopLeft
= dBottomLeft
;
1446 dTopRight
= dBottomRight
;
1448 dstyinc
= dstyinc
*-1;
1450 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_NOTEARING
)
1452 /* I don't think we need to do anything about this flag */
1453 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
1455 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE180
)
1458 dBottomRight
= dTopLeft
;
1461 dBottomLeft
= dTopRight
;
1463 dstxinc
= dstxinc
* -1;
1464 dstyinc
= dstyinc
* -1;
1466 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE270
)
1469 dTopLeft
= dBottomLeft
;
1470 dBottomLeft
= dBottomRight
;
1471 dBottomRight
= dTopRight
;
1476 dstxinc
= dstxinc
* -1;
1478 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE90
)
1481 dTopLeft
= dTopRight
;
1482 dTopRight
= dBottomRight
;
1483 dBottomRight
= dBottomLeft
;
1488 dstyinc
= dstyinc
* -1;
1490 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ZBUFFERBASEDEST
)
1492 /* I don't think we need to do anything about this flag */
1493 WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
1496 Flags
&= ~(WINEDDBLT_DDFX
);
1499 #define COPY_COLORKEY_FX(type) { \
1501 type *d = (type *)dbuf, *dx, tmp; \
1502 for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
1503 s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \
1505 for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
1506 tmp = s[sx >> 16]; \
1507 if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
1508 ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
1511 dx = (type*)(((LPBYTE)dx)+dstxinc); \
1513 d = (type*)(((LPBYTE)d)+dstyinc); \
1518 case 1: COPY_COLORKEY_FX(BYTE
)
1519 case 2: COPY_COLORKEY_FX(WORD
)
1520 case 4: COPY_COLORKEY_FX(DWORD
)
1524 BYTE
*d
= dbuf
, *dx
;
1525 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
)
1527 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1529 for (x
= sx
= 0; x
< dstwidth
; x
++, sx
+= xinc
)
1531 DWORD pixel
, dpixel
= 0;
1532 s
= sbuf
+3*(sx
>>16);
1533 pixel
= s
[0]|(s
[1]<<8)|(s
[2]<<16);
1534 dpixel
= dx
[0]|(dx
[1]<<8)|(dx
[2]<<16);
1535 if (((pixel
& keymask
) < keylow
|| (pixel
& keymask
) > keyhigh
) &&
1536 ((dpixel
& keymask
) >= destkeylow
|| (dpixel
& keymask
) <= keyhigh
))
1538 dx
[0] = (pixel
)&0xff;
1539 dx
[1] = (pixel
>> 8)&0xff;
1540 dx
[2] = (pixel
>>16)&0xff;
1549 FIXME("%s color-keyed blit not implemented for bpp %d!\n",
1550 (Flags
& WINEDDBLT_KEYSRC
) ? "Source" : "Destination", bpp
*8);
1551 ret
= WINED3DERR_NOTAVAILABLE
;
1553 #undef COPY_COLORKEY_FX
1559 if (Flags
&& FIXME_ON(d3d_surface
))
1561 FIXME("\tUnsupported flags: %08x\n", Flags
);
1565 IWineD3DSurface_UnlockRect(iface
);
1566 if (Src
&& Src
!= This
) IWineD3DSurface_UnlockRect((IWineD3DSurface
*) Src
);
1567 /* Release the converted surface if any */
1568 if (Src
&& SrcSurface
!= (IWineD3DSurface
*) Src
) IWineD3DSurface_Release((IWineD3DSurface
*) Src
);
1572 /*****************************************************************************
1573 * IWineD3DSurface::BltFast, SW emulation version
1575 * This is the software implementation of BltFast, as used by GDI surfaces
1576 * and as a fallback for OpenGL surfaces. This code is taken from the old
1577 * DirectDraw code, and was originally written by TransGaming.
1582 * Source: Source surface to copy from
1583 * rsrc: Source rectangle
1587 * WINED3D_OK on success
1589 *****************************************************************************/
1590 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface
*iface
, DWORD dstx
, DWORD dsty
,
1591 IWineD3DSurface
*Source
, const RECT
*rsrc
, DWORD trans
)
1593 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
1594 IWineD3DSurfaceImpl
*Src
= (IWineD3DSurfaceImpl
*) Source
;
1596 int bpp
, w
, h
, x
, y
;
1597 WINED3DLOCKED_RECT dlock
,slock
;
1598 HRESULT ret
= WINED3D_OK
;
1600 RECT lock_src
, lock_dst
, lock_union
;
1603 const struct wined3d_format_desc
*sEntry
, *dEntry
;
1605 if (TRACE_ON(d3d_surface
))
1607 TRACE("(%p)->(%d,%d,%p,%p,%08x)\n", This
,dstx
,dsty
,Src
,rsrc
,trans
);
1611 TRACE("\tsrcrect: %dx%d-%dx%d\n",rsrc
->left
,rsrc
->top
,
1612 rsrc
->right
,rsrc
->bottom
);
1616 TRACE(" srcrect: NULL\n");
1620 if ((This
->Flags
& SFLAG_LOCKED
) ||
1621 (Src
->Flags
& SFLAG_LOCKED
))
1623 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1624 return WINEDDERR_SURFACEBUSY
;
1629 WARN("rsrc is NULL!\n");
1632 rsrc2
.right
= Src
->currentDesc
.Width
;
1633 rsrc2
.bottom
= Src
->currentDesc
.Height
;
1637 /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
1638 if ((rsrc
->bottom
> Src
->currentDesc
.Height
) || (rsrc
->bottom
< 0) ||
1639 (rsrc
->top
> Src
->currentDesc
.Height
) || (rsrc
->top
< 0) ||
1640 (rsrc
->left
> Src
->currentDesc
.Width
) || (rsrc
->left
< 0) ||
1641 (rsrc
->right
> Src
->currentDesc
.Width
) || (rsrc
->right
< 0) ||
1642 (rsrc
->right
< rsrc
->left
) || (rsrc
->bottom
< rsrc
->top
))
1644 WARN("Application gave us bad source rectangle for BltFast.\n");
1645 return WINEDDERR_INVALIDRECT
;
1648 h
= rsrc
->bottom
- rsrc
->top
;
1649 if (h
> This
->currentDesc
.Height
-dsty
) h
= This
->currentDesc
.Height
-dsty
;
1650 if (h
> Src
->currentDesc
.Height
-rsrc
->top
) h
=Src
->currentDesc
.Height
-rsrc
->top
;
1651 if (h
<= 0) return WINEDDERR_INVALIDRECT
;
1653 w
= rsrc
->right
- rsrc
->left
;
1654 if (w
> This
->currentDesc
.Width
-dstx
) w
= This
->currentDesc
.Width
-dstx
;
1655 if (w
> Src
->currentDesc
.Width
-rsrc
->left
) w
= Src
->currentDesc
.Width
-rsrc
->left
;
1656 if (w
<= 0) return WINEDDERR_INVALIDRECT
;
1658 /* Now compute the locking rectangle... */
1659 lock_src
.left
= rsrc
->left
;
1660 lock_src
.top
= rsrc
->top
;
1661 lock_src
.right
= lock_src
.left
+ w
;
1662 lock_src
.bottom
= lock_src
.top
+ h
;
1664 lock_dst
.left
= dstx
;
1665 lock_dst
.top
= dsty
;
1666 lock_dst
.right
= dstx
+ w
;
1667 lock_dst
.bottom
= dsty
+ h
;
1669 bpp
= This
->resource
.format_desc
->byte_count
;
1671 /* We need to lock the surfaces, or we won't get refreshes when done. */
1676 UnionRect(&lock_union
, &lock_src
, &lock_dst
);
1678 /* Lock the union of the two rectangles */
1679 ret
= IWineD3DSurface_LockRect(iface
, &dlock
, &lock_union
, 0);
1680 if(ret
!= WINED3D_OK
) goto error
;
1682 pitch
= dlock
.Pitch
;
1683 slock
.Pitch
= dlock
.Pitch
;
1685 /* Since slock was originally copied from this surface's description, we can just reuse it */
1686 sbuf
= This
->resource
.allocatedMemory
+ lock_src
.top
* pitch
+ lock_src
.left
* bpp
;
1687 dbuf
= This
->resource
.allocatedMemory
+ lock_dst
.top
* pitch
+ lock_dst
.left
* bpp
;
1688 sEntry
= Src
->resource
.format_desc
;
1693 ret
= IWineD3DSurface_LockRect(Source
, &slock
, &lock_src
, WINED3DLOCK_READONLY
);
1694 if(ret
!= WINED3D_OK
) goto error
;
1695 ret
= IWineD3DSurface_LockRect(iface
, &dlock
, &lock_dst
, 0);
1696 if(ret
!= WINED3D_OK
) goto error
;
1700 TRACE("Dst is at %p, Src is at %p\n", dbuf
, sbuf
);
1702 sEntry
= Src
->resource
.format_desc
;
1703 dEntry
= This
->resource
.format_desc
;
1706 /* Handle compressed surfaces first... */
1707 if (sEntry
->Flags
& dEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
)
1709 UINT row_block_count
;
1711 TRACE("compressed -> compressed copy\n");
1713 FIXME("trans arg not supported when a compressed surface is involved\n");
1715 FIXME("offset for destination surface is not supported\n");
1716 if (Src
->resource
.format_desc
->format
!= This
->resource
.format_desc
->format
)
1718 FIXME("compressed -> compressed copy only supported for the same type of surface\n");
1719 ret
= WINED3DERR_WRONGTEXTUREFORMAT
;
1723 row_block_count
= (w
+ dEntry
->block_width
- 1) / dEntry
->block_width
;
1724 for (y
= 0; y
< h
; y
+= dEntry
->block_height
)
1726 memcpy(dbuf
, sbuf
, row_block_count
* dEntry
->block_byte_count
);
1727 dbuf
+= dlock
.Pitch
;
1728 sbuf
+= slock
.Pitch
;
1733 if ((sEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
) && !(dEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
))
1735 /* TODO: Use the libtxc_dxtn.so shared library to do
1736 * software decompression
1738 ERR("Software decompression not supported.\n");
1742 if (trans
& (WINEDDBLTFAST_SRCCOLORKEY
| WINEDDBLTFAST_DESTCOLORKEY
))
1744 DWORD keylow
, keyhigh
;
1745 DWORD mask
= Src
->resource
.format_desc
->red_mask
|
1746 Src
->resource
.format_desc
->green_mask
|
1747 Src
->resource
.format_desc
->blue_mask
;
1749 /* For some 8-bit formats like L8 and P8 color masks don't make sense */
1753 TRACE("Color keyed copy\n");
1754 if (trans
& WINEDDBLTFAST_SRCCOLORKEY
)
1756 keylow
= Src
->SrcBltCKey
.dwColorSpaceLowValue
;
1757 keyhigh
= Src
->SrcBltCKey
.dwColorSpaceHighValue
;
1761 /* I'm not sure if this is correct */
1762 FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
1763 keylow
= This
->DestBltCKey
.dwColorSpaceLowValue
;
1764 keyhigh
= This
->DestBltCKey
.dwColorSpaceHighValue
;
1767 #define COPYBOX_COLORKEY(type) { \
1768 const type *s = (const type *)sbuf; \
1769 type *d = (type *)dbuf; \
1771 for (y = 0; y < h; y++) { \
1772 for (x = 0; x < w; x++) { \
1774 if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \
1776 s = (const type *)((const BYTE *)s + slock.Pitch); \
1777 d = (type *)((BYTE *)d + dlock.Pitch); \
1783 case 1: COPYBOX_COLORKEY(BYTE
)
1784 case 2: COPYBOX_COLORKEY(WORD
)
1785 case 4: COPYBOX_COLORKEY(DWORD
)
1793 for (y
= 0; y
< h
; y
++)
1795 for (x
= 0; x
< w
* 3; x
+= 3)
1797 tmp
= (DWORD
)s
[x
] + ((DWORD
)s
[x
+ 1] << 8) + ((DWORD
)s
[x
+ 2] << 16);
1798 if (tmp
< keylow
|| tmp
> keyhigh
)
1800 d
[x
+ 0] = s
[x
+ 0];
1801 d
[x
+ 1] = s
[x
+ 1];
1802 d
[x
+ 2] = s
[x
+ 2];
1811 FIXME("Source color key blitting not supported for bpp %d\n",bpp
*8);
1812 ret
= WINED3DERR_NOTAVAILABLE
;
1815 #undef COPYBOX_COLORKEY
1816 TRACE("Copy Done\n");
1820 int width
= w
* bpp
;
1821 INT sbufpitch
, dbufpitch
;
1823 TRACE("NO color key copy\n");
1824 /* Handle overlapping surfaces */
1827 sbuf
+= (h
- 1) * slock
.Pitch
;
1828 dbuf
+= (h
- 1) * dlock
.Pitch
;
1829 sbufpitch
= -slock
.Pitch
;
1830 dbufpitch
= -dlock
.Pitch
;
1834 sbufpitch
= slock
.Pitch
;
1835 dbufpitch
= dlock
.Pitch
;
1837 for (y
= 0; y
< h
; y
++)
1839 /* This is pretty easy, a line for line memcpy */
1840 memmove(dbuf
, sbuf
, width
);
1844 TRACE("Copy done\n");
1850 IWineD3DSurface_UnlockRect(iface
);
1854 IWineD3DSurface_UnlockRect(iface
);
1855 IWineD3DSurface_UnlockRect(Source
);
1861 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface
*iface
, WINED3DLOCKED_RECT
* pLockedRect
, CONST RECT
* pRect
, DWORD Flags
)
1863 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1865 TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
1866 This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
1868 pLockedRect
->Pitch
= IWineD3DSurface_GetPitch(iface
);
1872 pLockedRect
->pBits
= This
->resource
.allocatedMemory
;
1873 This
->lockedRect
.left
= 0;
1874 This
->lockedRect
.top
= 0;
1875 This
->lockedRect
.right
= This
->currentDesc
.Width
;
1876 This
->lockedRect
.bottom
= This
->currentDesc
.Height
;
1878 TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n",
1879 &This
->lockedRect
, This
->lockedRect
.left
, This
->lockedRect
.top
,
1880 This
->lockedRect
.right
, This
->lockedRect
.bottom
);
1884 const struct wined3d_format_desc
*format_desc
= This
->resource
.format_desc
;
1886 TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
1887 pRect
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
1889 if (format_desc
->Flags
& WINED3DFMT_FLAG_COMPRESSED
)
1891 /* Compressed textures are block based, so calculate the offset of
1892 * the block that contains the top-left pixel of the locked rectangle. */
1893 pLockedRect
->pBits
= This
->resource
.allocatedMemory
1894 + ((pRect
->top
/ format_desc
->block_height
) * pLockedRect
->Pitch
)
1895 + ((pRect
->left
/ format_desc
->block_width
) * format_desc
->block_byte_count
);
1899 pLockedRect
->pBits
= This
->resource
.allocatedMemory
+
1900 (pLockedRect
->Pitch
* pRect
->top
) +
1901 (pRect
->left
* format_desc
->byte_count
);
1903 This
->lockedRect
.left
= pRect
->left
;
1904 This
->lockedRect
.top
= pRect
->top
;
1905 This
->lockedRect
.right
= pRect
->right
;
1906 This
->lockedRect
.bottom
= pRect
->bottom
;
1909 /* No dirtifying is needed for this surface implementation */
1910 TRACE("returning memory@%p, pitch(%d)\n", pLockedRect
->pBits
, pLockedRect
->Pitch
);
1915 void WINAPI
IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface
*iface
, BOOL srgb
) {
1916 ERR("Should not be called on base texture\n");
1919 /* TODO: think about moving this down to resource? */
1920 const void *WINAPI
IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface
*iface
)
1922 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1924 /* This should only be called for sysmem textures, it may be a good idea
1925 * to extend this to all pools at some point in the future */
1926 if (This
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
)
1928 FIXME("(%p) Attempting to get system memory for a non-system memory texture\n", iface
);
1930 return This
->resource
.allocatedMemory
;