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 if ( (This
->Flags
& SFLAG_LOCKED
) || ((Src
!= NULL
) && (Src
->Flags
& SFLAG_LOCKED
)))
975 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
976 return WINEDDERR_SURFACEBUSY
;
979 if(Filter
!= WINED3DTEXF_NONE
&& Filter
!= WINED3DTEXF_POINT
) {
980 /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
981 FIXME("Filters not supported in software blit\n");
984 /* First check for the validity of source / destination rectangles.
985 * This was verified using a test application + by MSDN. */
991 if (SrcRect
->right
< SrcRect
->left
|| SrcRect
->bottom
< SrcRect
->top
992 || SrcRect
->left
> Src
->currentDesc
.Width
|| SrcRect
->left
< 0
993 || SrcRect
->top
> Src
->currentDesc
.Height
|| SrcRect
->top
< 0
994 || SrcRect
->right
> Src
->currentDesc
.Width
|| SrcRect
->right
< 0
995 || SrcRect
->bottom
> Src
->currentDesc
.Height
|| SrcRect
->bottom
< 0)
997 WARN("Application gave us bad source rectangle for Blt.\n");
998 return WINEDDERR_INVALIDRECT
;
1001 if (!SrcRect
->right
|| !SrcRect
->bottom
1002 || SrcRect
->left
== (int)Src
->currentDesc
.Width
1003 || SrcRect
->top
== (int)Src
->currentDesc
.Height
)
1005 TRACE("Nothing to be done.\n");
1016 xsrc
.right
= Src
->currentDesc
.Width
;
1017 xsrc
.bottom
= Src
->currentDesc
.Height
;
1021 memset(&xsrc
, 0, sizeof(xsrc
));
1026 /* For the Destination rect, it can be out of bounds on the condition
1027 * that a clipper is set for the given surface. */
1028 if (!This
->clipper
&& (DestRect
->right
< DestRect
->left
|| DestRect
->bottom
< DestRect
->top
1029 || DestRect
->left
> This
->currentDesc
.Width
|| DestRect
->left
< 0
1030 || DestRect
->top
> This
->currentDesc
.Height
|| DestRect
->top
< 0
1031 || DestRect
->right
> This
->currentDesc
.Width
|| DestRect
->right
< 0
1032 || DestRect
->bottom
> This
->currentDesc
.Height
|| DestRect
->bottom
< 0))
1034 WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
1035 return WINEDDERR_INVALIDRECT
;
1038 if (DestRect
->right
<= 0 || DestRect
->bottom
<= 0
1039 || DestRect
->left
>= (int)This
->currentDesc
.Width
1040 || DestRect
->top
>= (int)This
->currentDesc
.Height
)
1042 TRACE("Nothing to be done.\n");
1052 full_rect
.right
= This
->currentDesc
.Width
;
1053 full_rect
.bottom
= This
->currentDesc
.Height
;
1054 IntersectRect(&xdst
, &full_rect
, DestRect
);
1058 BOOL clip_horiz
, clip_vert
;
1061 clip_horiz
= xdst
.left
< 0 || xdst
.right
> (int)This
->currentDesc
.Width
;
1062 clip_vert
= xdst
.top
< 0 || xdst
.bottom
> (int)This
->currentDesc
.Height
;
1064 if (clip_vert
|| clip_horiz
)
1066 /* Now check if this is a special case or not... */
1067 if ((Flags
& WINEDDBLT_DDFX
)
1068 || (clip_horiz
&& xdst
.right
- xdst
.left
!= xsrc
.right
- xsrc
.left
)
1069 || (clip_vert
&& xdst
.bottom
- xdst
.top
!= xsrc
.bottom
- xsrc
.top
))
1071 WARN("Out of screen rectangle in special case. Not handled right now.\n");
1079 xsrc
.left
-= xdst
.left
;
1082 if (xdst
.right
> This
->currentDesc
.Width
)
1084 xsrc
.right
-= (xdst
.right
- (int)This
->currentDesc
.Width
);
1085 xdst
.right
= (int)This
->currentDesc
.Width
;
1093 xsrc
.top
-= xdst
.top
;
1096 if (xdst
.bottom
> This
->currentDesc
.Height
)
1098 xsrc
.bottom
-= (xdst
.bottom
- (int)This
->currentDesc
.Height
);
1099 xdst
.bottom
= (int)This
->currentDesc
.Height
;
1103 /* And check if after clipping something is still to be done... */
1104 if ((xdst
.right
<= 0) || (xdst
.bottom
<= 0)
1105 || (xdst
.left
>= (int)This
->currentDesc
.Width
)
1106 || (xdst
.top
>= (int)This
->currentDesc
.Height
)
1107 || (xsrc
.right
<= 0) || (xsrc
.bottom
<= 0)
1108 || (xsrc
.left
>= (int) Src
->currentDesc
.Width
)
1109 || (xsrc
.top
>= (int)Src
->currentDesc
.Height
))
1111 TRACE("Nothing to be done after clipping.\n");
1121 xdst
.right
= This
->currentDesc
.Width
;
1122 xdst
.bottom
= This
->currentDesc
.Height
;
1127 IWineD3DSurface_LockRect(iface
, &dlock
, NULL
, 0);
1129 sEntry
= This
->resource
.format_desc
;
1134 dEntry
= This
->resource
.format_desc
;
1137 if (This
->resource
.format_desc
->format
!= Src
->resource
.format_desc
->format
)
1139 Src
= surface_convert_format(Src
, dEntry
->format
);
1141 /* The conv function writes a FIXME */
1142 WARN("Cannot convert source surface format to dest format\n");
1146 IWineD3DSurface_LockRect((IWineD3DSurface
*) Src
, &slock
, NULL
, WINED3DLOCK_READONLY
);
1147 sEntry
= Src
->resource
.format_desc
;
1154 IWineD3DSurface_LockRect(iface
, &dlock
, &xdst
, 0);
1156 IWineD3DSurface_LockRect(iface
, &dlock
, NULL
, 0);
1159 if (!DDBltFx
|| !(DDBltFx
->dwDDFX
)) Flags
&= ~WINEDDBLT_DDFX
;
1161 if (sEntry
->Flags
& dEntry
->Flags
& WINED3DFMT_FLAG_FOURCC
)
1163 if (!DestRect
|| Src
== This
)
1165 memcpy(dlock
.pBits
, slock
.pBits
, This
->resource
.size
);
1170 bpp
= This
->resource
.format_desc
->byte_count
;
1171 srcheight
= xsrc
.bottom
- xsrc
.top
;
1172 srcwidth
= xsrc
.right
- xsrc
.left
;
1173 dstheight
= xdst
.bottom
- xdst
.top
;
1174 dstwidth
= xdst
.right
- xdst
.left
;
1175 width
= (xdst
.right
- xdst
.left
) * bpp
;
1177 if (DestRect
&& Src
!= This
)
1180 dbuf
= (BYTE
*)dlock
.pBits
+(xdst
.top
*dlock
.Pitch
)+(xdst
.left
*bpp
);
1182 if (Flags
& WINEDDBLT_WAIT
)
1184 Flags
&= ~WINEDDBLT_WAIT
;
1186 if (Flags
& WINEDDBLT_ASYNC
)
1188 static BOOL displayed
= FALSE
;
1190 FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n");
1192 Flags
&= ~WINEDDBLT_ASYNC
;
1194 if (Flags
& WINEDDBLT_DONOTWAIT
)
1196 /* WINEDDBLT_DONOTWAIT appeared in DX7 */
1197 static BOOL displayed
= FALSE
;
1199 FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n");
1201 Flags
&= ~WINEDDBLT_DONOTWAIT
;
1204 /* First, all the 'source-less' blits */
1205 if (Flags
& WINEDDBLT_COLORFILL
)
1207 ret
= _Blt_ColorFill(dbuf
, dstwidth
, dstheight
, bpp
,
1208 dlock
.Pitch
, DDBltFx
->u5
.dwFillColor
);
1209 Flags
&= ~WINEDDBLT_COLORFILL
;
1212 if (Flags
& WINEDDBLT_DEPTHFILL
)
1214 FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
1216 if (Flags
& WINEDDBLT_ROP
)
1218 /* Catch some degenerate cases here */
1219 switch(DDBltFx
->dwROP
)
1222 ret
= _Blt_ColorFill(dbuf
,dstwidth
,dstheight
,bpp
,dlock
.Pitch
,0);
1224 case 0xAA0029: /* No-op */
1227 ret
= _Blt_ColorFill(dbuf
,dstwidth
,dstheight
,bpp
,dlock
.Pitch
,~0);
1229 case SRCCOPY
: /* well, we do that below ? */
1232 FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx
->dwROP
, DDBltFx
->u5
.lpDDSPattern
);
1235 Flags
&= ~WINEDDBLT_ROP
;
1237 if (Flags
& WINEDDBLT_DDROPS
)
1239 FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx
->dwDDROP
, DDBltFx
->u5
.lpDDSPattern
);
1241 /* Now the 'with source' blits */
1245 int sx
, xinc
, sy
, yinc
;
1247 if (!dstwidth
|| !dstheight
) /* hmm... stupid program ? */
1249 sbase
= (BYTE
*)slock
.pBits
+(xsrc
.top
*slock
.Pitch
)+xsrc
.left
*bpp
;
1250 xinc
= (srcwidth
<< 16) / dstwidth
;
1251 yinc
= (srcheight
<< 16) / dstheight
;
1255 /* No effects, we can cheat here */
1256 if (dstwidth
== srcwidth
)
1258 if (dstheight
== srcheight
)
1260 /* No stretching in either direction. This needs to be as
1261 * fast as possible */
1264 /* check for overlapping surfaces */
1265 if (Src
!= This
|| xdst
.top
< xsrc
.top
||
1266 xdst
.right
<= xsrc
.left
|| xsrc
.right
<= xdst
.left
)
1268 /* no overlap, or dst above src, so copy from top downwards */
1269 for (y
= 0; y
< dstheight
; y
++)
1271 memcpy(dbuf
, sbuf
, width
);
1272 sbuf
+= slock
.Pitch
;
1273 dbuf
+= dlock
.Pitch
;
1276 else if (xdst
.top
> xsrc
.top
) /* copy from bottom upwards */
1278 sbuf
+= (slock
.Pitch
*dstheight
);
1279 dbuf
+= (dlock
.Pitch
*dstheight
);
1280 for (y
= 0; y
< dstheight
; y
++)
1282 sbuf
-= slock
.Pitch
;
1283 dbuf
-= dlock
.Pitch
;
1284 memcpy(dbuf
, sbuf
, width
);
1287 else /* src and dst overlapping on the same line, use memmove */
1289 for (y
= 0; y
< dstheight
; y
++)
1291 memmove(dbuf
, sbuf
, width
);
1292 sbuf
+= slock
.Pitch
;
1293 dbuf
+= dlock
.Pitch
;
1297 /* Stretching in Y direction only */
1298 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
) {
1299 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1300 memcpy(dbuf
, sbuf
, width
);
1301 dbuf
+= dlock
.Pitch
;
1307 /* Stretching in X direction */
1309 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
)
1311 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1313 if ((sy
>> 16) == (last_sy
>> 16))
1315 /* this sourcerow is the same as last sourcerow -
1316 * copy already stretched row
1318 memcpy(dbuf
, dbuf
- dlock
.Pitch
, width
);
1322 #define STRETCH_ROW(type) { \
1323 const type *s = (const type *)sbuf; \
1324 type *d = (type *)dbuf; \
1325 for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
1326 d[x] = s[sx >> 16]; \
1331 case 1: STRETCH_ROW(BYTE
)
1332 case 2: STRETCH_ROW(WORD
)
1333 case 4: STRETCH_ROW(DWORD
)
1338 for (x
= sx
= 0; x
< dstwidth
; x
++, sx
+= xinc
)
1342 s
= sbuf
+3*(sx
>>16);
1343 pixel
= s
[0]|(s
[1]<<8)|(s
[2]<<16);
1344 d
[0] = (pixel
)&0xff;
1345 d
[1] = (pixel
>> 8)&0xff;
1346 d
[2] = (pixel
>>16)&0xff;
1352 FIXME("Stretched blit not implemented for bpp %d!\n", bpp
*8);
1353 ret
= WINED3DERR_NOTAVAILABLE
;
1358 dbuf
+= dlock
.Pitch
;
1365 LONG dstyinc
= dlock
.Pitch
, dstxinc
= bpp
;
1366 DWORD keylow
= 0xFFFFFFFF, keyhigh
= 0, keymask
= 0xFFFFFFFF;
1367 DWORD destkeylow
= 0x0, destkeyhigh
= 0xFFFFFFFF, destkeymask
= 0xFFFFFFFF;
1368 if (Flags
& (WINEDDBLT_KEYSRC
| WINEDDBLT_KEYDEST
| WINEDDBLT_KEYSRCOVERRIDE
| WINEDDBLT_KEYDESTOVERRIDE
))
1370 /* The color keying flags are checked for correctness in ddraw */
1371 if (Flags
& WINEDDBLT_KEYSRC
)
1373 keylow
= Src
->SrcBltCKey
.dwColorSpaceLowValue
;
1374 keyhigh
= Src
->SrcBltCKey
.dwColorSpaceHighValue
;
1376 else if (Flags
& WINEDDBLT_KEYSRCOVERRIDE
)
1378 keylow
= DDBltFx
->ddckSrcColorkey
.dwColorSpaceLowValue
;
1379 keyhigh
= DDBltFx
->ddckSrcColorkey
.dwColorSpaceHighValue
;
1382 if (Flags
& WINEDDBLT_KEYDEST
)
1384 /* Destination color keys are taken from the source surface ! */
1385 destkeylow
= Src
->DestBltCKey
.dwColorSpaceLowValue
;
1386 destkeyhigh
= Src
->DestBltCKey
.dwColorSpaceHighValue
;
1388 else if (Flags
& WINEDDBLT_KEYDESTOVERRIDE
)
1390 destkeylow
= DDBltFx
->ddckDestColorkey
.dwColorSpaceLowValue
;
1391 destkeyhigh
= DDBltFx
->ddckDestColorkey
.dwColorSpaceHighValue
;
1400 keymask
= sEntry
->red_mask
1401 | sEntry
->green_mask
1402 | sEntry
->blue_mask
;
1404 Flags
&= ~(WINEDDBLT_KEYSRC
| WINEDDBLT_KEYDEST
| WINEDDBLT_KEYSRCOVERRIDE
| WINEDDBLT_KEYDESTOVERRIDE
);
1407 if (Flags
& WINEDDBLT_DDFX
)
1409 LPBYTE dTopLeft
, dTopRight
, dBottomLeft
, dBottomRight
, tmp
;
1412 dTopRight
= dbuf
+((dstwidth
-1)*bpp
);
1413 dBottomLeft
= dTopLeft
+((dstheight
-1)*dlock
.Pitch
);
1414 dBottomRight
= dBottomLeft
+((dstwidth
-1)*bpp
);
1416 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ARITHSTRETCHY
)
1418 /* I don't think we need to do anything about this flag */
1419 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
1421 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_MIRRORLEFTRIGHT
)
1424 dTopRight
= dTopLeft
;
1427 dBottomRight
= dBottomLeft
;
1429 dstxinc
= dstxinc
*-1;
1431 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_MIRRORUPDOWN
)
1434 dTopLeft
= dBottomLeft
;
1437 dTopRight
= dBottomRight
;
1439 dstyinc
= dstyinc
*-1;
1441 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_NOTEARING
)
1443 /* I don't think we need to do anything about this flag */
1444 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
1446 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE180
)
1449 dBottomRight
= dTopLeft
;
1452 dBottomLeft
= dTopRight
;
1454 dstxinc
= dstxinc
* -1;
1455 dstyinc
= dstyinc
* -1;
1457 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE270
)
1460 dTopLeft
= dBottomLeft
;
1461 dBottomLeft
= dBottomRight
;
1462 dBottomRight
= dTopRight
;
1467 dstxinc
= dstxinc
* -1;
1469 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ROTATE90
)
1472 dTopLeft
= dTopRight
;
1473 dTopRight
= dBottomRight
;
1474 dBottomRight
= dBottomLeft
;
1479 dstyinc
= dstyinc
* -1;
1481 if (DDBltFx
->dwDDFX
& WINEDDBLTFX_ZBUFFERBASEDEST
)
1483 /* I don't think we need to do anything about this flag */
1484 WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
1487 Flags
&= ~(WINEDDBLT_DDFX
);
1490 #define COPY_COLORKEY_FX(type) { \
1492 type *d = (type *)dbuf, *dx, tmp; \
1493 for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
1494 s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \
1496 for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
1497 tmp = s[sx >> 16]; \
1498 if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
1499 ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
1502 dx = (type*)(((LPBYTE)dx)+dstxinc); \
1504 d = (type*)(((LPBYTE)d)+dstyinc); \
1509 case 1: COPY_COLORKEY_FX(BYTE
)
1510 case 2: COPY_COLORKEY_FX(WORD
)
1511 case 4: COPY_COLORKEY_FX(DWORD
)
1515 BYTE
*d
= dbuf
, *dx
;
1516 for (y
= sy
= 0; y
< dstheight
; y
++, sy
+= yinc
)
1518 sbuf
= sbase
+ (sy
>> 16) * slock
.Pitch
;
1520 for (x
= sx
= 0; x
< dstwidth
; x
++, sx
+= xinc
)
1522 DWORD pixel
, dpixel
= 0;
1523 s
= sbuf
+3*(sx
>>16);
1524 pixel
= s
[0]|(s
[1]<<8)|(s
[2]<<16);
1525 dpixel
= dx
[0]|(dx
[1]<<8)|(dx
[2]<<16);
1526 if (((pixel
& keymask
) < keylow
|| (pixel
& keymask
) > keyhigh
) &&
1527 ((dpixel
& keymask
) >= destkeylow
|| (dpixel
& keymask
) <= keyhigh
))
1529 dx
[0] = (pixel
)&0xff;
1530 dx
[1] = (pixel
>> 8)&0xff;
1531 dx
[2] = (pixel
>>16)&0xff;
1540 FIXME("%s color-keyed blit not implemented for bpp %d!\n",
1541 (Flags
& WINEDDBLT_KEYSRC
) ? "Source" : "Destination", bpp
*8);
1542 ret
= WINED3DERR_NOTAVAILABLE
;
1544 #undef COPY_COLORKEY_FX
1550 if (Flags
&& FIXME_ON(d3d_surface
))
1552 FIXME("\tUnsupported flags: %08x\n", Flags
);
1556 IWineD3DSurface_UnlockRect(iface
);
1557 if (Src
&& Src
!= This
) IWineD3DSurface_UnlockRect((IWineD3DSurface
*) Src
);
1558 /* Release the converted surface if any */
1559 if (Src
&& SrcSurface
!= (IWineD3DSurface
*) Src
) IWineD3DSurface_Release((IWineD3DSurface
*) Src
);
1563 /*****************************************************************************
1564 * IWineD3DSurface::BltFast, SW emulation version
1566 * This is the software implementation of BltFast, as used by GDI surfaces
1567 * and as a fallback for OpenGL surfaces. This code is taken from the old
1568 * DirectDraw code, and was originally written by TransGaming.
1573 * Source: Source surface to copy from
1574 * rsrc: Source rectangle
1578 * WINED3D_OK on success
1580 *****************************************************************************/
1581 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface
*iface
, DWORD dstx
, DWORD dsty
,
1582 IWineD3DSurface
*Source
, const RECT
*rsrc
, DWORD trans
)
1584 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
1585 IWineD3DSurfaceImpl
*Src
= (IWineD3DSurfaceImpl
*) Source
;
1587 int bpp
, w
, h
, x
, y
;
1588 WINED3DLOCKED_RECT dlock
,slock
;
1589 HRESULT ret
= WINED3D_OK
;
1591 RECT lock_src
, lock_dst
, lock_union
;
1594 const struct wined3d_format_desc
*sEntry
, *dEntry
;
1596 if (TRACE_ON(d3d_surface
))
1598 TRACE("(%p)->(%d,%d,%p,%p,%08x)\n", This
,dstx
,dsty
,Src
,rsrc
,trans
);
1602 TRACE("\tsrcrect: %dx%d-%dx%d\n",rsrc
->left
,rsrc
->top
,
1603 rsrc
->right
,rsrc
->bottom
);
1607 TRACE(" srcrect: NULL\n");
1611 if ((This
->Flags
& SFLAG_LOCKED
) ||
1612 (Src
->Flags
& SFLAG_LOCKED
))
1614 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1615 return WINEDDERR_SURFACEBUSY
;
1620 WARN("rsrc is NULL!\n");
1623 rsrc2
.right
= Src
->currentDesc
.Width
;
1624 rsrc2
.bottom
= Src
->currentDesc
.Height
;
1628 /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
1629 if ((rsrc
->bottom
> Src
->currentDesc
.Height
) || (rsrc
->bottom
< 0) ||
1630 (rsrc
->top
> Src
->currentDesc
.Height
) || (rsrc
->top
< 0) ||
1631 (rsrc
->left
> Src
->currentDesc
.Width
) || (rsrc
->left
< 0) ||
1632 (rsrc
->right
> Src
->currentDesc
.Width
) || (rsrc
->right
< 0) ||
1633 (rsrc
->right
< rsrc
->left
) || (rsrc
->bottom
< rsrc
->top
))
1635 WARN("Application gave us bad source rectangle for BltFast.\n");
1636 return WINEDDERR_INVALIDRECT
;
1639 h
= rsrc
->bottom
- rsrc
->top
;
1640 if (h
> This
->currentDesc
.Height
-dsty
) h
= This
->currentDesc
.Height
-dsty
;
1641 if (h
> Src
->currentDesc
.Height
-rsrc
->top
) h
=Src
->currentDesc
.Height
-rsrc
->top
;
1642 if (h
<= 0) return WINEDDERR_INVALIDRECT
;
1644 w
= rsrc
->right
- rsrc
->left
;
1645 if (w
> This
->currentDesc
.Width
-dstx
) w
= This
->currentDesc
.Width
-dstx
;
1646 if (w
> Src
->currentDesc
.Width
-rsrc
->left
) w
= Src
->currentDesc
.Width
-rsrc
->left
;
1647 if (w
<= 0) return WINEDDERR_INVALIDRECT
;
1649 /* Now compute the locking rectangle... */
1650 lock_src
.left
= rsrc
->left
;
1651 lock_src
.top
= rsrc
->top
;
1652 lock_src
.right
= lock_src
.left
+ w
;
1653 lock_src
.bottom
= lock_src
.top
+ h
;
1655 lock_dst
.left
= dstx
;
1656 lock_dst
.top
= dsty
;
1657 lock_dst
.right
= dstx
+ w
;
1658 lock_dst
.bottom
= dsty
+ h
;
1660 bpp
= This
->resource
.format_desc
->byte_count
;
1662 /* We need to lock the surfaces, or we won't get refreshes when done. */
1667 UnionRect(&lock_union
, &lock_src
, &lock_dst
);
1669 /* Lock the union of the two rectangles */
1670 ret
= IWineD3DSurface_LockRect(iface
, &dlock
, &lock_union
, 0);
1671 if(ret
!= WINED3D_OK
) goto error
;
1673 pitch
= dlock
.Pitch
;
1674 slock
.Pitch
= dlock
.Pitch
;
1676 /* Since slock was originally copied from this surface's description, we can just reuse it */
1677 sbuf
= This
->resource
.allocatedMemory
+ lock_src
.top
* pitch
+ lock_src
.left
* bpp
;
1678 dbuf
= This
->resource
.allocatedMemory
+ lock_dst
.top
* pitch
+ lock_dst
.left
* bpp
;
1679 sEntry
= Src
->resource
.format_desc
;
1684 ret
= IWineD3DSurface_LockRect(Source
, &slock
, &lock_src
, WINED3DLOCK_READONLY
);
1685 if(ret
!= WINED3D_OK
) goto error
;
1686 ret
= IWineD3DSurface_LockRect(iface
, &dlock
, &lock_dst
, 0);
1687 if(ret
!= WINED3D_OK
) goto error
;
1691 TRACE("Dst is at %p, Src is at %p\n", dbuf
, sbuf
);
1693 sEntry
= Src
->resource
.format_desc
;
1694 dEntry
= This
->resource
.format_desc
;
1697 /* Handle compressed surfaces first... */
1698 if (sEntry
->Flags
& dEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
)
1700 UINT row_block_count
;
1702 TRACE("compressed -> compressed copy\n");
1704 FIXME("trans arg not supported when a compressed surface is involved\n");
1706 FIXME("offset for destination surface is not supported\n");
1707 if (Src
->resource
.format_desc
->format
!= This
->resource
.format_desc
->format
)
1709 FIXME("compressed -> compressed copy only supported for the same type of surface\n");
1710 ret
= WINED3DERR_WRONGTEXTUREFORMAT
;
1714 row_block_count
= (w
+ dEntry
->block_width
- 1) / dEntry
->block_width
;
1715 for (y
= 0; y
< h
; y
+= dEntry
->block_height
)
1717 memcpy(dbuf
, sbuf
, row_block_count
* dEntry
->block_byte_count
);
1718 dbuf
+= dlock
.Pitch
;
1719 sbuf
+= slock
.Pitch
;
1724 if ((sEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
) && !(dEntry
->Flags
& WINED3DFMT_FLAG_COMPRESSED
))
1726 /* TODO: Use the libtxc_dxtn.so shared library to do
1727 * software decompression
1729 ERR("Software decompression not supported.\n");
1733 if (trans
& (WINEDDBLTFAST_SRCCOLORKEY
| WINEDDBLTFAST_DESTCOLORKEY
))
1735 DWORD keylow
, keyhigh
;
1736 DWORD mask
= Src
->resource
.format_desc
->red_mask
|
1737 Src
->resource
.format_desc
->green_mask
|
1738 Src
->resource
.format_desc
->blue_mask
;
1740 /* For some 8-bit formats like L8 and P8 color masks don't make sense */
1744 TRACE("Color keyed copy\n");
1745 if (trans
& WINEDDBLTFAST_SRCCOLORKEY
)
1747 keylow
= Src
->SrcBltCKey
.dwColorSpaceLowValue
;
1748 keyhigh
= Src
->SrcBltCKey
.dwColorSpaceHighValue
;
1752 /* I'm not sure if this is correct */
1753 FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
1754 keylow
= This
->DestBltCKey
.dwColorSpaceLowValue
;
1755 keyhigh
= This
->DestBltCKey
.dwColorSpaceHighValue
;
1758 #define COPYBOX_COLORKEY(type) { \
1759 const type *s = (const type *)sbuf; \
1760 type *d = (type *)dbuf; \
1762 for (y = 0; y < h; y++) { \
1763 for (x = 0; x < w; x++) { \
1765 if ((tmp & mask) < keylow || (tmp & mask) > keyhigh) d[x] = tmp; \
1767 s = (const type *)((const BYTE *)s + slock.Pitch); \
1768 d = (type *)((BYTE *)d + dlock.Pitch); \
1774 case 1: COPYBOX_COLORKEY(BYTE
)
1775 case 2: COPYBOX_COLORKEY(WORD
)
1776 case 4: COPYBOX_COLORKEY(DWORD
)
1784 for (y
= 0; y
< h
; y
++)
1786 for (x
= 0; x
< w
* 3; x
+= 3)
1788 tmp
= (DWORD
)s
[x
] + ((DWORD
)s
[x
+ 1] << 8) + ((DWORD
)s
[x
+ 2] << 16);
1789 if (tmp
< keylow
|| tmp
> keyhigh
)
1791 d
[x
+ 0] = s
[x
+ 0];
1792 d
[x
+ 1] = s
[x
+ 1];
1793 d
[x
+ 2] = s
[x
+ 2];
1802 FIXME("Source color key blitting not supported for bpp %d\n",bpp
*8);
1803 ret
= WINED3DERR_NOTAVAILABLE
;
1806 #undef COPYBOX_COLORKEY
1807 TRACE("Copy Done\n");
1811 int width
= w
* bpp
;
1812 INT sbufpitch
, dbufpitch
;
1814 TRACE("NO color key copy\n");
1815 /* Handle overlapping surfaces */
1818 sbuf
+= (h
- 1) * slock
.Pitch
;
1819 dbuf
+= (h
- 1) * dlock
.Pitch
;
1820 sbufpitch
= -slock
.Pitch
;
1821 dbufpitch
= -dlock
.Pitch
;
1825 sbufpitch
= slock
.Pitch
;
1826 dbufpitch
= dlock
.Pitch
;
1828 for (y
= 0; y
< h
; y
++)
1830 /* This is pretty easy, a line for line memcpy */
1831 memmove(dbuf
, sbuf
, width
);
1835 TRACE("Copy done\n");
1841 IWineD3DSurface_UnlockRect(iface
);
1845 IWineD3DSurface_UnlockRect(iface
);
1846 IWineD3DSurface_UnlockRect(Source
);
1852 HRESULT WINAPI
IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface
*iface
, WINED3DLOCKED_RECT
* pLockedRect
, CONST RECT
* pRect
, DWORD Flags
)
1854 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1856 TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
1857 This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
1859 pLockedRect
->Pitch
= IWineD3DSurface_GetPitch(iface
);
1863 pLockedRect
->pBits
= This
->resource
.allocatedMemory
;
1864 This
->lockedRect
.left
= 0;
1865 This
->lockedRect
.top
= 0;
1866 This
->lockedRect
.right
= This
->currentDesc
.Width
;
1867 This
->lockedRect
.bottom
= This
->currentDesc
.Height
;
1869 TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n",
1870 &This
->lockedRect
, This
->lockedRect
.left
, This
->lockedRect
.top
,
1871 This
->lockedRect
.right
, This
->lockedRect
.bottom
);
1875 const struct wined3d_format_desc
*format_desc
= This
->resource
.format_desc
;
1877 TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
1878 pRect
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
1880 if (format_desc
->Flags
& WINED3DFMT_FLAG_COMPRESSED
)
1882 /* Compressed textures are block based, so calculate the offset of
1883 * the block that contains the top-left pixel of the locked rectangle. */
1884 pLockedRect
->pBits
= This
->resource
.allocatedMemory
1885 + ((pRect
->top
/ format_desc
->block_height
) * pLockedRect
->Pitch
)
1886 + ((pRect
->left
/ format_desc
->block_width
) * format_desc
->block_byte_count
);
1890 pLockedRect
->pBits
= This
->resource
.allocatedMemory
+
1891 (pLockedRect
->Pitch
* pRect
->top
) +
1892 (pRect
->left
* format_desc
->byte_count
);
1894 This
->lockedRect
.left
= pRect
->left
;
1895 This
->lockedRect
.top
= pRect
->top
;
1896 This
->lockedRect
.right
= pRect
->right
;
1897 This
->lockedRect
.bottom
= pRect
->bottom
;
1900 /* No dirtifying is needed for this surface implementation */
1901 TRACE("returning memory@%p, pitch(%d)\n", pLockedRect
->pBits
, pLockedRect
->Pitch
);
1906 void WINAPI
IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface
*iface
, BOOL srgb
) {
1907 ERR("Should not be called on base texture\n");
1910 /* TODO: think about moving this down to resource? */
1911 const void *WINAPI
IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface
*iface
)
1913 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1915 /* This should only be called for sysmem textures, it may be a good idea
1916 * to extend this to all pools at some point in the future */
1917 if (This
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
)
1919 FIXME("(%p) Attempting to get system memory for a non-system memory texture\n", iface
);
1921 return This
->resource
.allocatedMemory
;