shlwapi: Allow ' ' in hostname and password in UrlGetPart.
[wine/testsucceed.git] / dlls / wined3d / surface_base.c
blobc737f99c965c56ff50ec03d99fc3be0ee3028fed
1 /*
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
30 #include "config.h"
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)
39 int exp = 0;
40 float tmp = fabs(*in);
41 unsigned int mantissa;
42 unsigned short ret;
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)) {
52 tmp = tmp * 2.0f;
53 exp--;
54 }while(tmp < pow(2, 10));
55 } else if(tmp >= pow(2, 11)) {
58 tmp /= 2.0f;
59 exp++;
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 */
71 } else if(exp <= 0) {
72 /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */
73 while(exp <= 0) {
74 mantissa = mantissa >> 1;
75 exp++;
77 ret = mantissa & 0x3ff;
78 } else {
79 ret = (exp << 10) | (mantissa & 0x3ff);
82 ret |= ((*in < 0.0f ? 1 : 0) << 15); /* Add the sign */
83 return ret;
87 /* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */
89 /* *******************************************
90 IWineD3DSurface IUnknown parts follow
91 ******************************************* */
92 HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
94 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
95 /* Warn ,but be nice about things */
96 TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
98 if (IsEqualGUID(riid, &IID_IUnknown)
99 || IsEqualGUID(riid, &IID_IWineD3DBase)
100 || IsEqualGUID(riid, &IID_IWineD3DResource)
101 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
102 IUnknown_AddRef((IUnknown*)iface);
103 *ppobj = This;
104 return S_OK;
106 *ppobj = NULL;
107 return E_NOINTERFACE;
110 ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) {
111 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
112 ULONG ref = InterlockedIncrement(&This->resource.ref);
113 TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
114 return ref;
117 /* ****************************************************
118 IWineD3DSurface IWineD3DResource parts follow
119 **************************************************** */
120 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
121 return resource_set_private_data((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
124 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
125 return resource_get_private_data((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
128 HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
129 return resource_free_private_data((IWineD3DResource *)iface, refguid);
132 DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
133 return resource_set_priority((IWineD3DResource *)iface, PriorityNew);
136 DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
137 return resource_get_priority((IWineD3DResource *)iface);
140 WINED3DRESOURCETYPE WINAPI IWineD3DBaseSurfaceImpl_GetType(IWineD3DSurface *iface) {
141 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
142 return resource_get_type((IWineD3DResource *)iface);
145 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
146 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
147 return resource_get_parent((IWineD3DResource *)iface, pParent);
150 /* ******************************************************
151 IWineD3DSurface IWineD3DSurface parts follow
152 ****************************************************** */
154 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
155 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
156 IWineD3DBase *container = 0;
158 TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
160 if (!ppContainer) {
161 ERR("Called without a valid ppContainer.\n");
164 /* Standalone surfaces return the device as container. */
165 if (This->container) container = This->container;
166 else container = (IWineD3DBase *)This->resource.device;
168 TRACE("Relaying to QueryInterface\n");
169 return IUnknown_QueryInterface(container, riid, ppContainer);
172 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
173 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
175 TRACE("(%p) : copying into %p\n", This, pDesc);
177 pDesc->format = This->resource.format_desc->format;
178 pDesc->resource_type = This->resource.resourceType;
179 pDesc->usage = This->resource.usage;
180 pDesc->pool = This->resource.pool;
181 pDesc->size = This->resource.size; /* dx8 only */
182 pDesc->multisample_type = This->currentDesc.MultiSampleType;
183 pDesc->multisample_quality = This->currentDesc.MultiSampleQuality;
184 pDesc->width = This->currentDesc.Width;
185 pDesc->height = This->currentDesc.Height;
187 return WINED3D_OK;
190 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
191 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
192 TRACE("(%p)->(%x)\n", This, Flags);
194 switch (Flags)
196 case WINEDDGBS_CANBLT:
197 case WINEDDGBS_ISBLTDONE:
198 return WINED3D_OK;
200 default:
201 return WINED3DERR_INVALIDCALL;
205 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
206 /* XXX: DDERR_INVALIDSURFACETYPE */
208 TRACE("(%p)->(%08x)\n",iface,Flags);
209 switch (Flags) {
210 case WINEDDGFS_CANFLIP:
211 case WINEDDGFS_ISFLIPDONE:
212 return WINED3D_OK;
214 default:
215 return WINED3DERR_INVALIDCALL;
219 HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) {
220 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
221 TRACE("(%p)\n", This);
223 /* D3D8 and 9 loose full devices, ddraw only surfaces */
224 return This->Flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK;
227 HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) {
228 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
229 TRACE("(%p)\n", This);
231 /* So far we don't lose anything :) */
232 This->Flags &= ~SFLAG_LOST;
233 return WINED3D_OK;
236 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
237 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
238 IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
239 TRACE("(%p)->(%p)\n", This, Pal);
241 if(This->palette == PalImpl) {
242 TRACE("Nop palette change\n");
243 return WINED3D_OK;
246 if(This->palette != NULL)
247 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
248 This->palette->Flags &= ~WINEDDPCAPS_PRIMARYSURFACE;
250 This->palette = PalImpl;
252 if(PalImpl != NULL) {
253 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
254 (PalImpl)->Flags |= WINEDDPCAPS_PRIMARYSURFACE;
257 return IWineD3DSurface_RealizePalette(iface);
259 else return WINED3D_OK;
262 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, const WINEDDCOLORKEY *CKey)
264 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
265 TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
267 if ((Flags & WINEDDCKEY_COLORSPACE) != 0) {
268 FIXME(" colorkey value not supported (%08x) !\n", Flags);
269 return WINED3DERR_INVALIDCALL;
272 /* Dirtify the surface, but only if a key was changed */
273 if(CKey) {
274 switch (Flags & ~WINEDDCKEY_COLORSPACE) {
275 case WINEDDCKEY_DESTBLT:
276 This->DestBltCKey = *CKey;
277 This->CKeyFlags |= WINEDDSD_CKDESTBLT;
278 break;
280 case WINEDDCKEY_DESTOVERLAY:
281 This->DestOverlayCKey = *CKey;
282 This->CKeyFlags |= WINEDDSD_CKDESTOVERLAY;
283 break;
285 case WINEDDCKEY_SRCOVERLAY:
286 This->SrcOverlayCKey = *CKey;
287 This->CKeyFlags |= WINEDDSD_CKSRCOVERLAY;
288 break;
290 case WINEDDCKEY_SRCBLT:
291 This->SrcBltCKey = *CKey;
292 This->CKeyFlags |= WINEDDSD_CKSRCBLT;
293 break;
296 else {
297 switch (Flags & ~WINEDDCKEY_COLORSPACE) {
298 case WINEDDCKEY_DESTBLT:
299 This->CKeyFlags &= ~WINEDDSD_CKDESTBLT;
300 break;
302 case WINEDDCKEY_DESTOVERLAY:
303 This->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY;
304 break;
306 case WINEDDCKEY_SRCOVERLAY:
307 This->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY;
308 break;
310 case WINEDDCKEY_SRCBLT:
311 This->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
312 break;
316 return WINED3D_OK;
319 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
320 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
321 TRACE("(%p)->(%p)\n", This, Pal);
323 *Pal = (IWineD3DPalette *) This->palette;
324 return WINED3D_OK;
327 DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
328 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
329 const struct GlPixelFormatDesc *format_desc = This->resource.format_desc;
330 DWORD ret;
331 TRACE("(%p)\n", This);
333 if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
335 /* Since compressed formats are block based, pitch means the amount of
336 * bytes to the next row of block rather than the next row of pixels. */
337 UINT row_block_count = (This->currentDesc.Width + format_desc->block_width - 1) / format_desc->block_width;
338 ret = row_block_count * format_desc->block_byte_count;
340 else
342 unsigned char alignment = This->resource.device->surface_alignment;
343 ret = This->resource.format_desc->byte_count * This->currentDesc.Width; /* Bytes / row */
344 ret = (ret + alignment - 1) & ~(alignment - 1);
346 TRACE("(%p) Returning %d\n", This, ret);
347 return ret;
350 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
351 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
352 LONG w, h;
354 TRACE("(%p)->(%d,%d) Stub!\n", This, X, Y);
356 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
358 TRACE("(%p): Not an overlay surface\n", This);
359 return WINEDDERR_NOTAOVERLAYSURFACE;
362 w = This->overlay_destrect.right - This->overlay_destrect.left;
363 h = This->overlay_destrect.bottom - This->overlay_destrect.top;
364 This->overlay_destrect.left = X;
365 This->overlay_destrect.top = Y;
366 This->overlay_destrect.right = X + w;
367 This->overlay_destrect.bottom = Y + h;
369 IWineD3DSurface_DrawOverlay(iface);
371 return WINED3D_OK;
374 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
375 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
376 HRESULT hr;
378 TRACE("(%p)->(%p,%p)\n", This, X, Y);
380 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
382 TRACE("(%p): Not an overlay surface\n", This);
383 return WINEDDERR_NOTAOVERLAYSURFACE;
385 if(This->overlay_dest == NULL) {
386 *X = 0; *Y = 0;
387 hr = WINEDDERR_OVERLAYNOTVISIBLE;
388 } else {
389 *X = This->overlay_destrect.left;
390 *Y = This->overlay_destrect.top;
391 hr = WINED3D_OK;
394 TRACE("Returning 0x%08x, position %d, %d\n", hr, *X, *Y);
395 return hr;
398 HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
399 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
400 IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
402 FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
404 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
406 TRACE("(%p): Not an overlay surface\n", This);
407 return WINEDDERR_NOTAOVERLAYSURFACE;
410 return WINED3D_OK;
413 HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, const RECT *SrcRect,
414 IWineD3DSurface *DstSurface, const RECT *DstRect, DWORD Flags, const WINEDDOVERLAYFX *FX)
416 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
417 IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
418 TRACE("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
420 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
422 WARN("(%p): Not an overlay surface\n", This);
423 return WINEDDERR_NOTAOVERLAYSURFACE;
424 } else if(!DstSurface) {
425 WARN("(%p): Dest surface is NULL\n", This);
426 return WINED3DERR_INVALIDCALL;
429 if(SrcRect) {
430 This->overlay_srcrect = *SrcRect;
431 } else {
432 This->overlay_srcrect.left = 0;
433 This->overlay_srcrect.top = 0;
434 This->overlay_srcrect.right = This->currentDesc.Width;
435 This->overlay_srcrect.bottom = This->currentDesc.Height;
438 if(DstRect) {
439 This->overlay_destrect = *DstRect;
440 } else {
441 This->overlay_destrect.left = 0;
442 This->overlay_destrect.top = 0;
443 This->overlay_destrect.right = Dst ? Dst->currentDesc.Width : 0;
444 This->overlay_destrect.bottom = Dst ? Dst->currentDesc.Height : 0;
447 if(This->overlay_dest && (This->overlay_dest != Dst || Flags & WINEDDOVER_HIDE)) {
448 list_remove(&This->overlay_entry);
451 if(Flags & WINEDDOVER_SHOW) {
452 if(This->overlay_dest != Dst) {
453 This->overlay_dest = Dst;
454 list_add_tail(&Dst->overlays, &This->overlay_entry);
456 } else if(Flags & WINEDDOVER_HIDE) {
457 /* tests show that the rectangles are erased on hide */
458 This->overlay_srcrect.left = 0; This->overlay_srcrect.top = 0;
459 This->overlay_srcrect.right = 0; This->overlay_srcrect.bottom = 0;
460 This->overlay_destrect.left = 0; This->overlay_destrect.top = 0;
461 This->overlay_destrect.right = 0; This->overlay_destrect.bottom = 0;
462 This->overlay_dest = NULL;
465 IWineD3DSurface_DrawOverlay(iface);
467 return WINED3D_OK;
470 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD3DClipper *clipper)
472 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
473 TRACE("(%p)->(%p)\n", This, clipper);
475 This->clipper = clipper;
476 return WINED3D_OK;
479 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, IWineD3DClipper **clipper)
481 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
482 TRACE("(%p)->(%p)\n", This, clipper);
484 *clipper = This->clipper;
485 if(*clipper) {
486 IWineD3DClipper_AddRef(*clipper);
488 return WINED3D_OK;
491 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
492 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
494 TRACE("This %p, container %p\n", This, container);
496 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
498 TRACE("Setting container to %p from %p\n", container, This->container);
499 This->container = container;
501 return WINED3D_OK;
504 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
505 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
506 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format,
507 &This->resource.device->adapter->gl_info);
509 if (This->resource.format_desc->format != WINED3DFMT_UNKNOWN)
511 FIXME("(%p) : The format of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
512 return WINED3DERR_INVALIDCALL;
515 TRACE("(%p) : Setting texture format to (%d,%s)\n", This, format, debug_d3dformat(format));
517 This->resource.size = surface_calculate_size(format_desc, This->resource.device->surface_alignment,
518 This->pow2Width, This->pow2Height);
520 This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
522 This->resource.format_desc = format_desc;
524 TRACE("(%p) : Size %d, bytesPerPixel %d\n", This, This->resource.size, format_desc->byte_count);
526 return WINED3D_OK;
529 HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) {
530 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
531 const struct GlPixelFormatDesc *format_desc = This->resource.format_desc;
532 int extraline = 0;
533 SYSTEM_INFO sysInfo;
534 BITMAPINFO* b_info;
535 HDC ddc;
536 DWORD *masks;
537 UINT usage;
539 if(!(format_desc->Flags & WINED3DFMT_FLAG_GETDC))
541 WARN("Cannot use GetDC on a %s surface\n", debug_d3dformat(format_desc->format));
542 return WINED3DERR_INVALIDCALL;
545 switch (format_desc->byte_count)
547 case 2:
548 case 4:
549 /* Allocate extra space to store the RGB bit masks. */
550 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
551 break;
553 case 3:
554 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
555 break;
557 default:
558 /* Allocate extra space for a palette. */
559 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
560 sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << (format_desc->byte_count * 8)));
561 break;
564 if (!b_info)
565 return E_OUTOFMEMORY;
567 /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
568 * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
569 * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
570 * add an extra line to the dib section
572 GetSystemInfo(&sysInfo);
573 if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) {
574 extraline = 1;
575 TRACE("Adding an extra line to the dib section\n");
578 b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
579 /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */
580 b_info->bmiHeader.biWidth = IWineD3DSurface_GetPitch(iface) / format_desc->byte_count;
581 b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
582 b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
583 b_info->bmiHeader.biPlanes = 1;
584 b_info->bmiHeader.biBitCount = format_desc->byte_count * 8;
586 b_info->bmiHeader.biXPelsPerMeter = 0;
587 b_info->bmiHeader.biYPelsPerMeter = 0;
588 b_info->bmiHeader.biClrUsed = 0;
589 b_info->bmiHeader.biClrImportant = 0;
591 /* Get the bit masks */
592 masks = (DWORD *)b_info->bmiColors;
593 switch (This->resource.format_desc->format)
595 case WINED3DFMT_B8G8R8_UNORM:
596 usage = DIB_RGB_COLORS;
597 b_info->bmiHeader.biCompression = BI_RGB;
598 break;
600 case WINED3DFMT_B5G5R5X1_UNORM:
601 case WINED3DFMT_B5G5R5A1_UNORM:
602 case WINED3DFMT_B4G4R4A4_UNORM:
603 case WINED3DFMT_B4G4R4X4_UNORM:
604 case WINED3DFMT_B2G3R3_UNORM:
605 case WINED3DFMT_B2G3R3A8_UNORM:
606 case WINED3DFMT_R10G10B10A2_UNORM:
607 case WINED3DFMT_R8G8B8A8_UNORM:
608 case WINED3DFMT_R8G8B8X8_UNORM:
609 case WINED3DFMT_B10G10R10A2_UNORM:
610 case WINED3DFMT_B5G6R5_UNORM:
611 case WINED3DFMT_R16G16B16A16_UNORM:
612 usage = 0;
613 b_info->bmiHeader.biCompression = BI_BITFIELDS;
614 masks[0] = format_desc->red_mask;
615 masks[1] = format_desc->green_mask;
616 masks[2] = format_desc->blue_mask;
617 break;
619 default:
620 /* Don't know palette */
621 b_info->bmiHeader.biCompression = BI_RGB;
622 usage = 0;
623 break;
626 ddc = GetDC(0);
627 if (ddc == 0) {
628 HeapFree(GetProcessHeap(), 0, b_info);
629 return HRESULT_FROM_WIN32(GetLastError());
632 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);
633 This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
634 ReleaseDC(0, ddc);
636 if (!This->dib.DIBsection) {
637 ERR("CreateDIBSection failed!\n");
638 HeapFree(GetProcessHeap(), 0, b_info);
639 return HRESULT_FROM_WIN32(GetLastError());
642 TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
643 /* copy the existing surface to the dib section */
644 if(This->resource.allocatedMemory) {
645 memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->currentDesc.Height * IWineD3DSurface_GetPitch(iface));
646 } else {
647 /* This is to make LockRect read the gl Texture although memory is allocated */
648 This->Flags &= ~SFLAG_INSYSMEM;
650 This->dib.bitmap_size = b_info->bmiHeader.biSizeImage;
652 HeapFree(GetProcessHeap(), 0, b_info);
654 /* Now allocate a HDC */
655 This->hDC = CreateCompatibleDC(0);
656 This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
657 TRACE("using wined3d palette %p\n", This->palette);
658 SelectPalette(This->hDC,
659 This->palette ? This->palette->hpal : 0,
660 FALSE);
662 This->Flags |= SFLAG_DIBSECTION;
664 HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
665 This->resource.heapMemory = NULL;
667 return WINED3D_OK;
670 static void convert_r32_float_r16_float(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out,
671 unsigned int w, unsigned int h)
673 unsigned int x, y;
674 const float *src_f;
675 unsigned short *dst_s;
677 TRACE("Converting %dx%d pixels, pitches %d %d\n", w, h, pitch_in, pitch_out);
678 for(y = 0; y < h; y++) {
679 src_f = (const float *)(src + y * pitch_in);
680 dst_s = (unsigned short *) (dst + y * pitch_out);
681 for(x = 0; x < w; x++) {
682 dst_s[x] = float_32_to_16(src_f + x);
687 static void convert_r5g6b5_x8r8g8b8(const BYTE *src, BYTE *dst,
688 DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
690 static const unsigned char convert_5to8[] =
692 0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
693 0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
694 0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
695 0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
697 static const unsigned char convert_6to8[] =
699 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
700 0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d,
701 0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d,
702 0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
703 0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
704 0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
705 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf,
706 0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff,
708 unsigned int x, y;
710 TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
712 for (y = 0; y < h; ++y)
714 const WORD *src_line = (const WORD *)(src + y * pitch_in);
715 DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
716 for (x = 0; x < w; ++x)
718 WORD pixel = src_line[x];
719 dst_line[x] = 0xff000000
720 | convert_5to8[(pixel & 0xf800) >> 11] << 16
721 | convert_6to8[(pixel & 0x07e0) >> 5] << 8
722 | convert_5to8[(pixel & 0x001f)];
727 static void convert_a8r8g8b8_x8r8g8b8(const BYTE *src, BYTE *dst,
728 DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h)
730 unsigned int x, y;
732 TRACE("Converting %ux%u pixels, pitches %u %u\n", w, h, pitch_in, pitch_out);
734 for (y = 0; y < h; ++y)
736 const DWORD *src_line = (const DWORD *)(src + y * pitch_in);
737 DWORD *dst_line = (DWORD *)(dst + y * pitch_out);
739 for (x = 0; x < w; ++x)
741 dst_line[x] = 0xff000000 | (src_line[x] & 0xffffff);
746 struct d3dfmt_convertor_desc {
747 WINED3DFORMAT from, to;
748 void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h);
751 static const struct d3dfmt_convertor_desc convertors[] =
753 {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float},
754 {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_r5g6b5_x8r8g8b8},
755 {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_B8G8R8X8_UNORM, convert_a8r8g8b8_x8r8g8b8},
758 static inline const struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to)
760 unsigned int i;
761 for(i = 0; i < (sizeof(convertors) / sizeof(convertors[0])); i++) {
762 if(convertors[i].from == from && convertors[i].to == to) {
763 return &convertors[i];
766 return NULL;
769 /*****************************************************************************
770 * surface_convert_format
772 * Creates a duplicate of a surface in a different format. Is used by Blt to
773 * blit between surfaces with different formats
775 * Parameters
776 * source: Source surface
777 * fmt: Requested destination format
779 *****************************************************************************/
780 static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, WINED3DFORMAT to_fmt) {
781 IWineD3DSurface *ret = NULL;
782 const struct d3dfmt_convertor_desc *conv;
783 WINED3DLOCKED_RECT lock_src, lock_dst;
784 HRESULT hr;
786 conv = find_convertor(source->resource.format_desc->format, to_fmt);
787 if(!conv) {
788 FIXME("Cannot find a conversion function from format %s to %s\n",
789 debug_d3dformat(source->resource.format_desc->format), debug_d3dformat(to_fmt));
790 return NULL;
793 IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.device, source->currentDesc.Width,
794 source->currentDesc.Height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, &ret,
795 0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */,
796 0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source),
797 NULL /* parent */, &wined3d_null_parent_ops);
798 if(!ret) {
799 ERR("Failed to create a destination surface for conversion\n");
800 return NULL;
803 memset(&lock_src, 0, sizeof(lock_src));
804 memset(&lock_dst, 0, sizeof(lock_dst));
806 hr = IWineD3DSurface_LockRect((IWineD3DSurface *) source, &lock_src, NULL, WINED3DLOCK_READONLY);
807 if(FAILED(hr)) {
808 ERR("Failed to lock the source surface\n");
809 IWineD3DSurface_Release(ret);
810 return NULL;
812 hr = IWineD3DSurface_LockRect(ret, &lock_dst, NULL, WINED3DLOCK_READONLY);
813 if(FAILED(hr)) {
814 ERR("Failed to lock the dest surface\n");
815 IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
816 IWineD3DSurface_Release(ret);
817 return NULL;
820 conv->convert(lock_src.pBits, lock_dst.pBits, lock_src.Pitch, lock_dst.Pitch,
821 source->currentDesc.Width, source->currentDesc.Height);
823 IWineD3DSurface_UnlockRect(ret);
824 IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
826 return (IWineD3DSurfaceImpl *) ret;
829 /*****************************************************************************
830 * _Blt_ColorFill
832 * Helper function that fills a memory area with a specific color
834 * Params:
835 * buf: memory address to start filling at
836 * width, height: Dimensions of the area to fill
837 * bpp: Bit depth of the surface
838 * lPitch: pitch of the surface
839 * color: Color to fill with
841 *****************************************************************************/
842 static HRESULT
843 _Blt_ColorFill(BYTE *buf,
844 int width, int height,
845 int bpp, LONG lPitch,
846 DWORD color)
848 int x, y;
849 LPBYTE first;
851 /* Do first row */
853 #define COLORFILL_ROW(type) \
855 type *d = (type *) buf; \
856 for (x = 0; x < width; x++) \
857 d[x] = (type) color; \
858 break; \
860 switch(bpp)
862 case 1: COLORFILL_ROW(BYTE)
863 case 2: COLORFILL_ROW(WORD)
864 case 3:
866 BYTE *d = buf;
867 for (x = 0; x < width; x++,d+=3)
869 d[0] = (color ) & 0xFF;
870 d[1] = (color>> 8) & 0xFF;
871 d[2] = (color>>16) & 0xFF;
873 break;
875 case 4: COLORFILL_ROW(DWORD)
876 default:
877 FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
878 return WINED3DERR_NOTAVAILABLE;
881 #undef COLORFILL_ROW
883 /* Now copy first row */
884 first = buf;
885 for (y = 1; y < height; y++)
887 buf += lPitch;
888 memcpy(buf, first, width * bpp);
890 return WINED3D_OK;
893 /*****************************************************************************
894 * IWineD3DSurface::Blt, SW emulation version
896 * Performs blits to a surface, eigher from a source of source-less blts
897 * This is the main functionality of DirectDraw
899 * Params:
900 * DestRect: Destination rectangle to write to
901 * SrcSurface: Source surface, can be NULL
902 * SrcRect: Source rectangle
903 *****************************************************************************/
904 HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *DestRect, IWineD3DSurface *SrcSurface,
905 const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter)
907 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
908 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
909 RECT xdst,xsrc;
910 HRESULT ret = WINED3D_OK;
911 WINED3DLOCKED_RECT dlock, slock;
912 int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
913 const struct GlPixelFormatDesc *sEntry, *dEntry;
914 int x, y;
915 const BYTE *sbuf;
916 BYTE *dbuf;
917 TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
919 if (TRACE_ON(d3d_surface))
921 if (DestRect) TRACE("\tdestrect :%dx%d-%dx%d\n",
922 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
923 if (SrcRect) TRACE("\tsrcrect :%dx%d-%dx%d\n",
924 SrcRect->left, SrcRect->top, SrcRect->right, SrcRect->bottom);
925 #if 0
926 TRACE("\tflags: ");
927 DDRAW_dump_DDBLT(Flags);
928 if (Flags & WINEDDBLT_DDFX)
930 TRACE("\tblitfx: ");
931 DDRAW_dump_DDBLTFX(DDBltFx->dwDDFX);
933 #endif
936 if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
938 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
939 return WINEDDERR_SURFACEBUSY;
942 if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) {
943 /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
944 FIXME("Filters not supported in software blit\n");
947 /* First check for the validity of source / destination rectangles. This was
948 * verified using a test application + by MSDN.
950 if ((Src != NULL) && (SrcRect != NULL) &&
951 ((SrcRect->bottom > Src->currentDesc.Height)||(SrcRect->bottom < 0) ||
952 (SrcRect->top > Src->currentDesc.Height)||(SrcRect->top < 0) ||
953 (SrcRect->left > Src->currentDesc.Width) ||(SrcRect->left < 0) ||
954 (SrcRect->right > Src->currentDesc.Width) ||(SrcRect->right < 0) ||
955 (SrcRect->right < SrcRect->left) ||(SrcRect->bottom < SrcRect->top)))
957 WARN("Application gave us bad source rectangle for Blt.\n");
958 return WINEDDERR_INVALIDRECT;
960 /* For the Destination rect, it can be out of bounds on the condition that a clipper
961 * is set for the given surface.
963 if ((/*This->clipper == NULL*/ TRUE) && (DestRect) &&
964 ((DestRect->bottom > This->currentDesc.Height)||(DestRect->bottom < 0) ||
965 (DestRect->top > This->currentDesc.Height)||(DestRect->top < 0) ||
966 (DestRect->left > This->currentDesc.Width) ||(DestRect->left < 0) ||
967 (DestRect->right > This->currentDesc.Width) ||(DestRect->right < 0) ||
968 (DestRect->right < DestRect->left) ||(DestRect->bottom < DestRect->top)))
970 WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
971 return WINEDDERR_INVALIDRECT;
974 /* Now handle negative values in the rectangles. Warning: only supported for now
975 in the 'simple' cases (ie not in any stretching / rotation cases).
977 First, the case where nothing is to be done.
979 if ((DestRect && ((DestRect->bottom <= 0) || (DestRect->right <= 0) ||
980 (DestRect->top >= (int) This->currentDesc.Height) ||
981 (DestRect->left >= (int) This->currentDesc.Width))) ||
982 ((Src != NULL) && (SrcRect != NULL) &&
983 ((SrcRect->bottom <= 0) || (SrcRect->right <= 0) ||
984 (SrcRect->top >= (int) Src->currentDesc.Height) ||
985 (SrcRect->left >= (int) Src->currentDesc.Width)) ))
987 TRACE("Nothing to be done !\n");
988 return WINED3D_OK;
991 if (DestRect)
993 xdst = *DestRect;
995 else
997 xdst.top = 0;
998 xdst.bottom = This->currentDesc.Height;
999 xdst.left = 0;
1000 xdst.right = This->currentDesc.Width;
1003 if (SrcRect)
1005 xsrc = *SrcRect;
1007 else
1009 if (Src)
1011 xsrc.top = 0;
1012 xsrc.bottom = Src->currentDesc.Height;
1013 xsrc.left = 0;
1014 xsrc.right = Src->currentDesc.Width;
1016 else
1018 memset(&xsrc,0,sizeof(xsrc));
1022 /* The easy case : the source-less blits.... */
1023 if (Src == NULL && DestRect)
1025 RECT full_rect;
1026 RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */
1028 full_rect.left = 0;
1029 full_rect.top = 0;
1030 full_rect.right = This->currentDesc.Width;
1031 full_rect.bottom = This->currentDesc.Height;
1032 IntersectRect(&temp_rect, &full_rect, DestRect);
1033 xdst = temp_rect;
1035 else if (DestRect)
1037 /* Only handle clipping on the destination rectangle */
1038 int clip_horiz = (DestRect->left < 0) || (DestRect->right > (int) This->currentDesc.Width );
1039 int clip_vert = (DestRect->top < 0) || (DestRect->bottom > (int) This->currentDesc.Height);
1040 if (clip_vert || clip_horiz)
1042 /* Now check if this is a special case or not... */
1043 if ((((DestRect->bottom - DestRect->top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) ||
1044 (((DestRect->right - DestRect->left) != (xsrc.right - xsrc.left)) && clip_horiz) ||
1045 (Flags & WINEDDBLT_DDFX))
1047 WARN("Out of screen rectangle in special case. Not handled right now.\n");
1048 return WINED3D_OK;
1051 if (clip_horiz)
1053 if (DestRect->left < 0) { xsrc.left -= DestRect->left; xdst.left = 0; }
1054 if (DestRect->right > This->currentDesc.Width)
1056 xsrc.right -= (DestRect->right - (int) This->currentDesc.Width);
1057 xdst.right = (int) This->currentDesc.Width;
1060 if (clip_vert)
1062 if (DestRect->top < 0)
1064 xsrc.top -= DestRect->top;
1065 xdst.top = 0;
1067 if (DestRect->bottom > This->currentDesc.Height)
1069 xsrc.bottom -= (DestRect->bottom - (int) This->currentDesc.Height);
1070 xdst.bottom = (int) This->currentDesc.Height;
1073 /* And check if after clipping something is still to be done... */
1074 if ((xdst.bottom <= 0) || (xdst.right <= 0) ||
1075 (xdst.top >= (int) This->currentDesc.Height) ||
1076 (xdst.left >= (int) This->currentDesc.Width) ||
1077 (xsrc.bottom <= 0) || (xsrc.right <= 0) ||
1078 (xsrc.top >= (int) Src->currentDesc.Height) ||
1079 (xsrc.left >= (int) Src->currentDesc.Width))
1081 TRACE("Nothing to be done after clipping !\n");
1082 return WINED3D_OK;
1087 if (Src == This)
1089 IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
1090 slock = dlock;
1091 sEntry = This->resource.format_desc;
1092 dEntry = sEntry;
1094 else
1096 dEntry = This->resource.format_desc;
1097 if (Src)
1099 if (This->resource.format_desc->format != Src->resource.format_desc->format)
1101 Src = surface_convert_format(Src, dEntry->format);
1102 if(!Src) {
1103 /* The conv function writes a FIXME */
1104 WARN("Cannot convert source surface format to dest format\n");
1105 goto release;
1108 IWineD3DSurface_LockRect((IWineD3DSurface *) Src, &slock, NULL, WINED3DLOCK_READONLY);
1109 sEntry = Src->resource.format_desc;
1111 else
1113 sEntry = dEntry;
1115 if (DestRect)
1116 IWineD3DSurface_LockRect(iface, &dlock, &xdst, 0);
1117 else
1118 IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
1121 if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX;
1123 if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_FOURCC)
1125 if (!DestRect || Src == This)
1127 memcpy(dlock.pBits, slock.pBits, This->resource.size);
1128 goto release;
1132 bpp = This->resource.format_desc->byte_count;
1133 srcheight = xsrc.bottom - xsrc.top;
1134 srcwidth = xsrc.right - xsrc.left;
1135 dstheight = xdst.bottom - xdst.top;
1136 dstwidth = xdst.right - xdst.left;
1137 width = (xdst.right - xdst.left) * bpp;
1139 if (DestRect && Src != This)
1140 dbuf = dlock.pBits;
1141 else
1142 dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp);
1144 if (Flags & WINEDDBLT_WAIT)
1146 Flags &= ~WINEDDBLT_WAIT;
1148 if (Flags & WINEDDBLT_ASYNC)
1150 static BOOL displayed = FALSE;
1151 if (!displayed)
1152 FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n");
1153 displayed = TRUE;
1154 Flags &= ~WINEDDBLT_ASYNC;
1156 if (Flags & WINEDDBLT_DONOTWAIT)
1158 /* WINEDDBLT_DONOTWAIT appeared in DX7 */
1159 static BOOL displayed = FALSE;
1160 if (!displayed)
1161 FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n");
1162 displayed = TRUE;
1163 Flags &= ~WINEDDBLT_DONOTWAIT;
1166 /* First, all the 'source-less' blits */
1167 if (Flags & WINEDDBLT_COLORFILL)
1169 ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
1170 dlock.Pitch, DDBltFx->u5.dwFillColor);
1171 Flags &= ~WINEDDBLT_COLORFILL;
1174 if (Flags & WINEDDBLT_DEPTHFILL)
1176 FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
1178 if (Flags & WINEDDBLT_ROP)
1180 /* Catch some degenerate cases here */
1181 switch(DDBltFx->dwROP)
1183 case BLACKNESS:
1184 ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,0);
1185 break;
1186 case 0xAA0029: /* No-op */
1187 break;
1188 case WHITENESS:
1189 ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,~0);
1190 break;
1191 case SRCCOPY: /* well, we do that below ? */
1192 break;
1193 default:
1194 FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx->dwROP, DDBltFx->u5.lpDDSPattern);
1195 goto error;
1197 Flags &= ~WINEDDBLT_ROP;
1199 if (Flags & WINEDDBLT_DDROPS)
1201 FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx->dwDDROP, DDBltFx->u5.lpDDSPattern);
1203 /* Now the 'with source' blits */
1204 if (Src)
1206 const BYTE *sbase;
1207 int sx, xinc, sy, yinc;
1209 if (!dstwidth || !dstheight) /* hmm... stupid program ? */
1210 goto release;
1211 sbase = (BYTE*)slock.pBits+(xsrc.top*slock.Pitch)+xsrc.left*bpp;
1212 xinc = (srcwidth << 16) / dstwidth;
1213 yinc = (srcheight << 16) / dstheight;
1215 if (!Flags)
1217 /* No effects, we can cheat here */
1218 if (dstwidth == srcwidth)
1220 if (dstheight == srcheight)
1222 /* No stretching in either direction. This needs to be as
1223 * fast as possible */
1224 sbuf = sbase;
1226 /* check for overlapping surfaces */
1227 if (Src != This || xdst.top < xsrc.top ||
1228 xdst.right <= xsrc.left || xsrc.right <= xdst.left)
1230 /* no overlap, or dst above src, so copy from top downwards */
1231 for (y = 0; y < dstheight; y++)
1233 memcpy(dbuf, sbuf, width);
1234 sbuf += slock.Pitch;
1235 dbuf += dlock.Pitch;
1238 else if (xdst.top > xsrc.top) /* copy from bottom upwards */
1240 sbuf += (slock.Pitch*dstheight);
1241 dbuf += (dlock.Pitch*dstheight);
1242 for (y = 0; y < dstheight; y++)
1244 sbuf -= slock.Pitch;
1245 dbuf -= dlock.Pitch;
1246 memcpy(dbuf, sbuf, width);
1249 else /* src and dst overlapping on the same line, use memmove */
1251 for (y = 0; y < dstheight; y++)
1253 memmove(dbuf, sbuf, width);
1254 sbuf += slock.Pitch;
1255 dbuf += dlock.Pitch;
1258 } else {
1259 /* Stretching in Y direction only */
1260 for (y = sy = 0; y < dstheight; y++, sy += yinc) {
1261 sbuf = sbase + (sy >> 16) * slock.Pitch;
1262 memcpy(dbuf, sbuf, width);
1263 dbuf += dlock.Pitch;
1267 else
1269 /* Stretching in X direction */
1270 int last_sy = -1;
1271 for (y = sy = 0; y < dstheight; y++, sy += yinc)
1273 sbuf = sbase + (sy >> 16) * slock.Pitch;
1275 if ((sy >> 16) == (last_sy >> 16))
1277 /* this sourcerow is the same as last sourcerow -
1278 * copy already stretched row
1280 memcpy(dbuf, dbuf - dlock.Pitch, width);
1282 else
1284 #define STRETCH_ROW(type) { \
1285 const type *s = (const type *)sbuf; \
1286 type *d = (type *)dbuf; \
1287 for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
1288 d[x] = s[sx >> 16]; \
1289 break; }
1291 switch(bpp)
1293 case 1: STRETCH_ROW(BYTE)
1294 case 2: STRETCH_ROW(WORD)
1295 case 4: STRETCH_ROW(DWORD)
1296 case 3:
1298 const BYTE *s;
1299 BYTE *d = dbuf;
1300 for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
1302 DWORD pixel;
1304 s = sbuf+3*(sx>>16);
1305 pixel = s[0]|(s[1]<<8)|(s[2]<<16);
1306 d[0] = (pixel )&0xff;
1307 d[1] = (pixel>> 8)&0xff;
1308 d[2] = (pixel>>16)&0xff;
1309 d+=3;
1311 break;
1313 default:
1314 FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
1315 ret = WINED3DERR_NOTAVAILABLE;
1316 goto error;
1318 #undef STRETCH_ROW
1320 dbuf += dlock.Pitch;
1321 last_sy = sy;
1325 else
1327 LONG dstyinc = dlock.Pitch, dstxinc = bpp;
1328 DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF;
1329 DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF;
1330 if (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE))
1332 /* The color keying flags are checked for correctness in ddraw */
1333 if (Flags & WINEDDBLT_KEYSRC)
1335 keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
1336 keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
1338 else if (Flags & WINEDDBLT_KEYSRCOVERRIDE)
1340 keylow = DDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
1341 keyhigh = DDBltFx->ddckSrcColorkey.dwColorSpaceHighValue;
1344 if (Flags & WINEDDBLT_KEYDEST)
1346 /* Destination color keys are taken from the source surface ! */
1347 destkeylow = Src->DestBltCKey.dwColorSpaceLowValue;
1348 destkeyhigh = Src->DestBltCKey.dwColorSpaceHighValue;
1350 else if (Flags & WINEDDBLT_KEYDESTOVERRIDE)
1352 destkeylow = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
1353 destkeyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue;
1356 if(bpp == 1)
1358 keymask = 0xff;
1360 else
1362 keymask = sEntry->red_mask
1363 | sEntry->green_mask
1364 | sEntry->blue_mask;
1366 Flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE);
1369 if (Flags & WINEDDBLT_DDFX)
1371 LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp;
1372 LONG tmpxy;
1373 dTopLeft = dbuf;
1374 dTopRight = dbuf+((dstwidth-1)*bpp);
1375 dBottomLeft = dTopLeft+((dstheight-1)*dlock.Pitch);
1376 dBottomRight = dBottomLeft+((dstwidth-1)*bpp);
1378 if (DDBltFx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY)
1380 /* I don't think we need to do anything about this flag */
1381 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
1383 if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT)
1385 tmp = dTopRight;
1386 dTopRight = dTopLeft;
1387 dTopLeft = tmp;
1388 tmp = dBottomRight;
1389 dBottomRight = dBottomLeft;
1390 dBottomLeft = tmp;
1391 dstxinc = dstxinc *-1;
1393 if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN)
1395 tmp = dTopLeft;
1396 dTopLeft = dBottomLeft;
1397 dBottomLeft = tmp;
1398 tmp = dTopRight;
1399 dTopRight = dBottomRight;
1400 dBottomRight = tmp;
1401 dstyinc = dstyinc *-1;
1403 if (DDBltFx->dwDDFX & WINEDDBLTFX_NOTEARING)
1405 /* I don't think we need to do anything about this flag */
1406 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
1408 if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE180)
1410 tmp = dBottomRight;
1411 dBottomRight = dTopLeft;
1412 dTopLeft = tmp;
1413 tmp = dBottomLeft;
1414 dBottomLeft = dTopRight;
1415 dTopRight = tmp;
1416 dstxinc = dstxinc * -1;
1417 dstyinc = dstyinc * -1;
1419 if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE270)
1421 tmp = dTopLeft;
1422 dTopLeft = dBottomLeft;
1423 dBottomLeft = dBottomRight;
1424 dBottomRight = dTopRight;
1425 dTopRight = tmp;
1426 tmpxy = dstxinc;
1427 dstxinc = dstyinc;
1428 dstyinc = tmpxy;
1429 dstxinc = dstxinc * -1;
1431 if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE90)
1433 tmp = dTopLeft;
1434 dTopLeft = dTopRight;
1435 dTopRight = dBottomRight;
1436 dBottomRight = dBottomLeft;
1437 dBottomLeft = tmp;
1438 tmpxy = dstxinc;
1439 dstxinc = dstyinc;
1440 dstyinc = tmpxy;
1441 dstyinc = dstyinc * -1;
1443 if (DDBltFx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST)
1445 /* I don't think we need to do anything about this flag */
1446 WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
1448 dbuf = dTopLeft;
1449 Flags &= ~(WINEDDBLT_DDFX);
1452 #define COPY_COLORKEY_FX(type) { \
1453 const type *s; \
1454 type *d = (type *)dbuf, *dx, tmp; \
1455 for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
1456 s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \
1457 dx = d; \
1458 for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
1459 tmp = s[sx >> 16]; \
1460 if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
1461 ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
1462 dx[0] = tmp; \
1464 dx = (type*)(((LPBYTE)dx)+dstxinc); \
1466 d = (type*)(((LPBYTE)d)+dstyinc); \
1468 break; }
1470 switch (bpp) {
1471 case 1: COPY_COLORKEY_FX(BYTE)
1472 case 2: COPY_COLORKEY_FX(WORD)
1473 case 4: COPY_COLORKEY_FX(DWORD)
1474 case 3:
1476 const BYTE *s;
1477 BYTE *d = dbuf, *dx;
1478 for (y = sy = 0; y < dstheight; y++, sy += yinc)
1480 sbuf = sbase + (sy >> 16) * slock.Pitch;
1481 dx = d;
1482 for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
1484 DWORD pixel, dpixel = 0;
1485 s = sbuf+3*(sx>>16);
1486 pixel = s[0]|(s[1]<<8)|(s[2]<<16);
1487 dpixel = dx[0]|(dx[1]<<8)|(dx[2]<<16);
1488 if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) &&
1489 ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh))
1491 dx[0] = (pixel )&0xff;
1492 dx[1] = (pixel>> 8)&0xff;
1493 dx[2] = (pixel>>16)&0xff;
1495 dx+= dstxinc;
1497 d += dstyinc;
1499 break;
1501 default:
1502 FIXME("%s color-keyed blit not implemented for bpp %d!\n",
1503 (Flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
1504 ret = WINED3DERR_NOTAVAILABLE;
1505 goto error;
1506 #undef COPY_COLORKEY_FX
1511 error:
1512 if (Flags && FIXME_ON(d3d_surface))
1514 FIXME("\tUnsupported flags: %08x\n", Flags);
1517 release:
1518 IWineD3DSurface_UnlockRect(iface);
1519 if (Src && Src != This) IWineD3DSurface_UnlockRect((IWineD3DSurface *) Src);
1520 /* Release the converted surface if any */
1521 if (Src && SrcSurface != (IWineD3DSurface *) Src) IWineD3DSurface_Release((IWineD3DSurface *) Src);
1522 return ret;
1525 /*****************************************************************************
1526 * IWineD3DSurface::BltFast, SW emulation version
1528 * This is the software implementation of BltFast, as used by GDI surfaces
1529 * and as a fallback for OpenGL surfaces. This code is taken from the old
1530 * DirectDraw code, and was originally written by TransGaming.
1532 * Params:
1533 * dstx:
1534 * dsty:
1535 * Source: Source surface to copy from
1536 * rsrc: Source rectangle
1537 * trans: Some Flags
1539 * Returns:
1540 * WINED3D_OK on success
1542 *****************************************************************************/
1543 HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty,
1544 IWineD3DSurface *Source, const RECT *rsrc, DWORD trans)
1546 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1547 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) Source;
1549 int bpp, w, h, x, y;
1550 WINED3DLOCKED_RECT dlock,slock;
1551 HRESULT ret = WINED3D_OK;
1552 RECT rsrc2;
1553 RECT lock_src, lock_dst, lock_union;
1554 const BYTE *sbuf;
1555 BYTE *dbuf;
1556 const struct GlPixelFormatDesc *sEntry, *dEntry;
1558 if (TRACE_ON(d3d_surface))
1560 TRACE("(%p)->(%d,%d,%p,%p,%08x)\n", This,dstx,dsty,Src,rsrc,trans);
1562 if (rsrc)
1564 TRACE("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,
1565 rsrc->right,rsrc->bottom);
1567 else
1569 TRACE(" srcrect: NULL\n");
1573 if ((This->Flags & SFLAG_LOCKED) ||
1574 (Src->Flags & SFLAG_LOCKED))
1576 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1577 return WINEDDERR_SURFACEBUSY;
1580 if (!rsrc)
1582 WARN("rsrc is NULL!\n");
1583 rsrc2.left = 0;
1584 rsrc2.top = 0;
1585 rsrc2.right = Src->currentDesc.Width;
1586 rsrc2.bottom = Src->currentDesc.Height;
1587 rsrc = &rsrc2;
1590 /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
1591 if ((rsrc->bottom > Src->currentDesc.Height) || (rsrc->bottom < 0) ||
1592 (rsrc->top > Src->currentDesc.Height) || (rsrc->top < 0) ||
1593 (rsrc->left > Src->currentDesc.Width) || (rsrc->left < 0) ||
1594 (rsrc->right > Src->currentDesc.Width) || (rsrc->right < 0) ||
1595 (rsrc->right < rsrc->left) || (rsrc->bottom < rsrc->top))
1597 WARN("Application gave us bad source rectangle for BltFast.\n");
1598 return WINEDDERR_INVALIDRECT;
1601 h = rsrc->bottom - rsrc->top;
1602 if (h > This->currentDesc.Height-dsty) h = This->currentDesc.Height-dsty;
1603 if (h > Src->currentDesc.Height-rsrc->top) h=Src->currentDesc.Height-rsrc->top;
1604 if (h <= 0) return WINEDDERR_INVALIDRECT;
1606 w = rsrc->right - rsrc->left;
1607 if (w > This->currentDesc.Width-dstx) w = This->currentDesc.Width-dstx;
1608 if (w > Src->currentDesc.Width-rsrc->left) w = Src->currentDesc.Width-rsrc->left;
1609 if (w <= 0) return WINEDDERR_INVALIDRECT;
1611 /* Now compute the locking rectangle... */
1612 lock_src.left = rsrc->left;
1613 lock_src.top = rsrc->top;
1614 lock_src.right = lock_src.left + w;
1615 lock_src.bottom = lock_src.top + h;
1617 lock_dst.left = dstx;
1618 lock_dst.top = dsty;
1619 lock_dst.right = dstx + w;
1620 lock_dst.bottom = dsty + h;
1622 bpp = This->resource.format_desc->byte_count;
1624 /* We need to lock the surfaces, or we won't get refreshes when done. */
1625 if (Src == This)
1627 int pitch;
1629 UnionRect(&lock_union, &lock_src, &lock_dst);
1631 /* Lock the union of the two rectangles */
1632 ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_union, 0);
1633 if(ret != WINED3D_OK) goto error;
1635 pitch = dlock.Pitch;
1636 slock.Pitch = dlock.Pitch;
1638 /* Since slock was originally copied from this surface's description, we can just reuse it */
1639 sbuf = This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp;
1640 dbuf = This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp;
1641 sEntry = Src->resource.format_desc;
1642 dEntry = sEntry;
1644 else
1646 ret = IWineD3DSurface_LockRect(Source, &slock, &lock_src, WINED3DLOCK_READONLY);
1647 if(ret != WINED3D_OK) goto error;
1648 ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_dst, 0);
1649 if(ret != WINED3D_OK) goto error;
1651 sbuf = slock.pBits;
1652 dbuf = dlock.pBits;
1653 TRACE("Dst is at %p, Src is at %p\n", dbuf, sbuf);
1655 sEntry = Src->resource.format_desc;
1656 dEntry = This->resource.format_desc;
1659 /* Handle compressed surfaces first... */
1660 if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED)
1662 UINT row_block_count;
1664 TRACE("compressed -> compressed copy\n");
1665 if (trans)
1666 FIXME("trans arg not supported when a compressed surface is involved\n");
1667 if (dstx || dsty)
1668 FIXME("offset for destination surface is not supported\n");
1669 if (Src->resource.format_desc->format != This->resource.format_desc->format)
1671 FIXME("compressed -> compressed copy only supported for the same type of surface\n");
1672 ret = WINED3DERR_WRONGTEXTUREFORMAT;
1673 goto error;
1676 row_block_count = (w + dEntry->block_width - 1) / dEntry->block_width;
1677 for (y = 0; y < h; y += dEntry->block_height)
1679 memcpy(dbuf, sbuf, row_block_count * dEntry->block_byte_count);
1680 dbuf += dlock.Pitch;
1681 sbuf += slock.Pitch;
1684 goto error;
1686 if ((sEntry->Flags & WINED3DFMT_FLAG_COMPRESSED) && !(dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED))
1688 /* TODO: Use the libtxc_dxtn.so shared library to do
1689 * software decompression
1691 ERR("Software decompression not supported.\n");
1692 goto error;
1695 if (trans & (WINEDDBLTFAST_SRCCOLORKEY | WINEDDBLTFAST_DESTCOLORKEY))
1697 DWORD keylow, keyhigh;
1698 TRACE("Color keyed copy\n");
1699 if (trans & WINEDDBLTFAST_SRCCOLORKEY)
1701 keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
1702 keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
1704 else
1706 /* I'm not sure if this is correct */
1707 FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
1708 keylow = This->DestBltCKey.dwColorSpaceLowValue;
1709 keyhigh = This->DestBltCKey.dwColorSpaceHighValue;
1712 #define COPYBOX_COLORKEY(type) { \
1713 const type *s = (const type *)sbuf; \
1714 type *d = (type *)dbuf; \
1715 type tmp; \
1716 for (y = 0; y < h; y++) { \
1717 for (x = 0; x < w; x++) { \
1718 tmp = s[x]; \
1719 if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
1721 s = (const type *)((const BYTE *)s + slock.Pitch); \
1722 d = (type *)((BYTE *)d + dlock.Pitch); \
1724 break; \
1727 switch (bpp) {
1728 case 1: COPYBOX_COLORKEY(BYTE)
1729 case 2: COPYBOX_COLORKEY(WORD)
1730 case 4: COPYBOX_COLORKEY(DWORD)
1731 case 3:
1733 const BYTE *s;
1734 BYTE *d;
1735 DWORD tmp;
1736 s = sbuf;
1737 d = dbuf;
1738 for (y = 0; y < h; y++)
1740 for (x = 0; x < w * 3; x += 3)
1742 tmp = (DWORD)s[x] + ((DWORD)s[x + 1] << 8) + ((DWORD)s[x + 2] << 16);
1743 if (tmp < keylow || tmp > keyhigh)
1745 d[x + 0] = s[x + 0];
1746 d[x + 1] = s[x + 1];
1747 d[x + 2] = s[x + 2];
1750 s += slock.Pitch;
1751 d += dlock.Pitch;
1753 break;
1755 default:
1756 FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
1757 ret = WINED3DERR_NOTAVAILABLE;
1758 goto error;
1760 #undef COPYBOX_COLORKEY
1761 TRACE("Copy Done\n");
1763 else
1765 int width = w * bpp;
1766 INT sbufpitch, dbufpitch;
1768 TRACE("NO color key copy\n");
1769 /* Handle overlapping surfaces */
1770 if (sbuf < dbuf)
1772 sbuf += (h - 1) * slock.Pitch;
1773 dbuf += (h - 1) * dlock.Pitch;
1774 sbufpitch = -slock.Pitch;
1775 dbufpitch = -dlock.Pitch;
1777 else
1779 sbufpitch = slock.Pitch;
1780 dbufpitch = dlock.Pitch;
1782 for (y = 0; y < h; y++)
1784 /* This is pretty easy, a line for line memcpy */
1785 memmove(dbuf, sbuf, width);
1786 sbuf += sbufpitch;
1787 dbuf += dbufpitch;
1789 TRACE("Copy done\n");
1792 error:
1793 if (Src == This)
1795 IWineD3DSurface_UnlockRect(iface);
1797 else
1799 IWineD3DSurface_UnlockRect(iface);
1800 IWineD3DSurface_UnlockRect(Source);
1803 return ret;
1806 HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags)
1808 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1810 TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
1811 This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
1813 pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
1815 if (NULL == pRect)
1817 pLockedRect->pBits = This->resource.allocatedMemory;
1818 This->lockedRect.left = 0;
1819 This->lockedRect.top = 0;
1820 This->lockedRect.right = This->currentDesc.Width;
1821 This->lockedRect.bottom = This->currentDesc.Height;
1823 TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n",
1824 &This->lockedRect, This->lockedRect.left, This->lockedRect.top,
1825 This->lockedRect.right, This->lockedRect.bottom);
1827 else
1829 const struct GlPixelFormatDesc *format_desc = This->resource.format_desc;
1831 TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
1832 pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
1834 if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
1836 /* Compressed textures are block based, so calculate the offset of
1837 * the block that contains the top-left pixel of the locked rectangle. */
1838 pLockedRect->pBits = This->resource.allocatedMemory
1839 + ((pRect->top / format_desc->block_height) * pLockedRect->Pitch)
1840 + ((pRect->left / format_desc->block_width) * format_desc->block_byte_count);
1842 else
1844 pLockedRect->pBits = This->resource.allocatedMemory +
1845 (pLockedRect->Pitch * pRect->top) +
1846 (pRect->left * format_desc->byte_count);
1848 This->lockedRect.left = pRect->left;
1849 This->lockedRect.top = pRect->top;
1850 This->lockedRect.right = pRect->right;
1851 This->lockedRect.bottom = pRect->bottom;
1854 /* No dirtifying is needed for this surface implementation */
1855 TRACE("returning memory@%p, pitch(%d)\n", pLockedRect->pBits, pLockedRect->Pitch);
1857 return WINED3D_OK;
1860 void WINAPI IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL srgb) {
1861 ERR("Should not be called on base texture\n");
1862 return;
1865 /* TODO: think about moving this down to resource? */
1866 const void *WINAPI IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface *iface)
1868 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1870 /* This should only be called for sysmem textures, it may be a good idea
1871 * to extend this to all pools at some point in the future */
1872 if (This->resource.pool != WINED3DPOOL_SYSTEMMEM)
1874 FIXME("(%p) Attempting to get system memory for a non-system memory texture\n", iface);
1876 return This->resource.allocatedMemory;