wined3d: Get rid of some asserts.
[wine.git] / dlls / wined3d / surface_base.c
blob44b94236caa972f8a4c96fb4518cc36194d8cd75
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
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "config.h"
30 #include "wine/port.h"
31 #include "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
35 /* See also float_16_to_32() in wined3d_private.h */
36 static inline unsigned short float_32_to_16(const float *in)
38 int exp = 0;
39 float tmp = fabs(*in);
40 unsigned int mantissa;
41 unsigned short ret;
43 /* Deal with special numbers */
44 if(*in == 0.0) return 0x0000;
45 if(isnan(*in)) return 0x7C01;
46 if(isinf(*in)) return (*in < 0.0 ? 0xFC00 : 0x7c00);
48 if(tmp < pow(2, 10)) {
51 tmp = tmp * 2.0;
52 exp--;
53 }while(tmp < pow(2, 10));
54 } else if(tmp >= pow(2, 11)) {
57 tmp /= 2.0;
58 exp++;
59 }while(tmp >= pow(2, 11));
62 mantissa = (unsigned int) tmp;
63 if(tmp - mantissa >= 0.5) mantissa++; /* round to nearest, away from zero */
65 exp += 10; /* Normalize the mantissa */
66 exp += 15; /* Exponent is encoded with excess 15 */
68 if(exp > 30) { /* too big */
69 ret = 0x7c00; /* INF */
70 } else if(exp <= 0) {
71 /* exp == 0: Non-normalized mantissa. Returns 0x0000 (=0.0) for too small numbers */
72 while(exp <= 0) {
73 mantissa = mantissa >> 1;
74 exp++;
76 ret = mantissa & 0x3ff;
77 } else {
78 ret = (exp << 10) | (mantissa & 0x3ff);
81 ret |= ((*in < 0.0 ? 1 : 0) << 15); /* Add the sign */
82 return ret;
86 /* Do NOT define GLINFO_LOCATION in this file. THIS CODE MUST NOT USE IT */
88 /* *******************************************
89 IWineD3DSurface IUnknown parts follow
90 ******************************************* */
91 HRESULT WINAPI IWineD3DBaseSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
93 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
94 /* Warn ,but be nice about things */
95 TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
97 if (IsEqualGUID(riid, &IID_IUnknown)
98 || IsEqualGUID(riid, &IID_IWineD3DBase)
99 || IsEqualGUID(riid, &IID_IWineD3DResource)
100 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
101 IUnknown_AddRef((IUnknown*)iface);
102 *ppobj = This;
103 return S_OK;
105 *ppobj = NULL;
106 return E_NOINTERFACE;
109 ULONG WINAPI IWineD3DBaseSurfaceImpl_AddRef(IWineD3DSurface *iface) {
110 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
111 ULONG ref = InterlockedIncrement(&This->resource.ref);
112 TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
113 return ref;
116 /* ****************************************************
117 IWineD3DSurface IWineD3DResource parts follow
118 **************************************************** */
119 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
120 return resource_get_device((IWineD3DResource *)iface, ppDevice);
123 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
124 return resource_set_private_data((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
127 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
128 return resource_get_private_data((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
131 HRESULT WINAPI IWineD3DBaseSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
132 return resource_free_private_data((IWineD3DResource *)iface, refguid);
135 DWORD WINAPI IWineD3DBaseSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
136 return resource_set_priority((IWineD3DResource *)iface, PriorityNew);
139 DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
140 return resource_get_priority((IWineD3DResource *)iface);
143 WINED3DRESOURCETYPE WINAPI IWineD3DBaseSurfaceImpl_GetType(IWineD3DSurface *iface) {
144 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
145 return resource_get_type((IWineD3DResource *)iface);
148 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
149 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
150 return resource_get_parent((IWineD3DResource *)iface, pParent);
153 /* ******************************************************
154 IWineD3DSurface IWineD3DSurface parts follow
155 ****************************************************** */
157 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
158 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
159 IWineD3DBase *container = 0;
161 TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
163 if (!ppContainer) {
164 ERR("Called without a valid ppContainer.\n");
167 /* Standalone surfaces return the device as container. */
168 if (This->container) {
169 container = This->container;
170 } else {
171 container = (IWineD3DBase *)This->resource.wineD3DDevice;
174 TRACE("Relaying to QueryInterface\n");
175 return IUnknown_QueryInterface(container, riid, ppContainer);
178 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
179 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
181 TRACE("(%p) : copying into %p\n", This, pDesc);
183 pDesc->format = This->resource.format_desc->format;
184 pDesc->resource_type = This->resource.resourceType;
185 pDesc->usage = This->resource.usage;
186 pDesc->pool = This->resource.pool;
187 pDesc->size = This->resource.size; /* dx8 only */
188 pDesc->multisample_type = This->currentDesc.MultiSampleType;
189 pDesc->multisample_quality = This->currentDesc.MultiSampleQuality;
190 pDesc->width = This->currentDesc.Width;
191 pDesc->height = This->currentDesc.Height;
193 return WINED3D_OK;
196 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
197 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
198 TRACE("(%p)->(%x)\n", This, Flags);
200 switch (Flags)
202 case WINEDDGBS_CANBLT:
203 case WINEDDGBS_ISBLTDONE:
204 return WINED3D_OK;
206 default:
207 return WINED3DERR_INVALIDCALL;
211 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
212 /* XXX: DDERR_INVALIDSURFACETYPE */
214 TRACE("(%p)->(%08x)\n",iface,Flags);
215 switch (Flags) {
216 case WINEDDGFS_CANFLIP:
217 case WINEDDGFS_ISFLIPDONE:
218 return WINED3D_OK;
220 default:
221 return WINED3DERR_INVALIDCALL;
225 HRESULT WINAPI IWineD3DBaseSurfaceImpl_IsLost(IWineD3DSurface *iface) {
226 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
227 TRACE("(%p)\n", This);
229 /* D3D8 and 9 loose full devices, ddraw only surfaces */
230 return This->Flags & SFLAG_LOST ? WINED3DERR_DEVICELOST : WINED3D_OK;
233 HRESULT WINAPI IWineD3DBaseSurfaceImpl_Restore(IWineD3DSurface *iface) {
234 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
235 TRACE("(%p)\n", This);
237 /* So far we don't lose anything :) */
238 This->Flags &= ~SFLAG_LOST;
239 return WINED3D_OK;
242 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
243 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
244 IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
245 TRACE("(%p)->(%p)\n", This, Pal);
247 if(This->palette == PalImpl) {
248 TRACE("Nop palette change\n");
249 return WINED3D_OK;
252 if(This->palette != NULL)
253 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
254 This->palette->Flags &= ~WINEDDPCAPS_PRIMARYSURFACE;
256 This->palette = PalImpl;
258 if(PalImpl != NULL) {
259 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
260 (PalImpl)->Flags |= WINEDDPCAPS_PRIMARYSURFACE;
263 return IWineD3DSurface_RealizePalette(iface);
265 else return WINED3D_OK;
268 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, const WINEDDCOLORKEY *CKey)
270 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
271 TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
273 if ((Flags & WINEDDCKEY_COLORSPACE) != 0) {
274 FIXME(" colorkey value not supported (%08x) !\n", Flags);
275 return WINED3DERR_INVALIDCALL;
278 /* Dirtify the surface, but only if a key was changed */
279 if(CKey) {
280 switch (Flags & ~WINEDDCKEY_COLORSPACE) {
281 case WINEDDCKEY_DESTBLT:
282 This->DestBltCKey = *CKey;
283 This->CKeyFlags |= WINEDDSD_CKDESTBLT;
284 break;
286 case WINEDDCKEY_DESTOVERLAY:
287 This->DestOverlayCKey = *CKey;
288 This->CKeyFlags |= WINEDDSD_CKDESTOVERLAY;
289 break;
291 case WINEDDCKEY_SRCOVERLAY:
292 This->SrcOverlayCKey = *CKey;
293 This->CKeyFlags |= WINEDDSD_CKSRCOVERLAY;
294 break;
296 case WINEDDCKEY_SRCBLT:
297 This->SrcBltCKey = *CKey;
298 This->CKeyFlags |= WINEDDSD_CKSRCBLT;
299 break;
302 else {
303 switch (Flags & ~WINEDDCKEY_COLORSPACE) {
304 case WINEDDCKEY_DESTBLT:
305 This->CKeyFlags &= ~WINEDDSD_CKDESTBLT;
306 break;
308 case WINEDDCKEY_DESTOVERLAY:
309 This->CKeyFlags &= ~WINEDDSD_CKDESTOVERLAY;
310 break;
312 case WINEDDCKEY_SRCOVERLAY:
313 This->CKeyFlags &= ~WINEDDSD_CKSRCOVERLAY;
314 break;
316 case WINEDDCKEY_SRCBLT:
317 This->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
318 break;
322 return WINED3D_OK;
325 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
326 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
327 TRACE("(%p)->(%p)\n", This, Pal);
329 *Pal = (IWineD3DPalette *) This->palette;
330 return WINED3D_OK;
333 DWORD WINAPI IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
334 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
335 const struct GlPixelFormatDesc *format_desc = This->resource.format_desc;
336 DWORD ret;
337 TRACE("(%p)\n", This);
339 if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
341 /* Since compressed formats are block based, pitch means the amount of
342 * bytes to the next row of block rather than the next row of pixels. */
343 UINT row_block_count = (This->currentDesc.Width + format_desc->block_width - 1) / format_desc->block_width;
344 ret = row_block_count * format_desc->block_byte_count;
346 else
348 unsigned char alignment = This->resource.wineD3DDevice->surface_alignment;
349 ret = This->resource.format_desc->byte_count * This->currentDesc.Width; /* Bytes / row */
350 ret = (ret + alignment - 1) & ~(alignment - 1);
352 TRACE("(%p) Returning %d\n", This, ret);
353 return ret;
356 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
357 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
358 LONG w, h;
360 TRACE("(%p)->(%d,%d) Stub!\n", This, X, Y);
362 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
364 TRACE("(%p): Not an overlay surface\n", This);
365 return WINEDDERR_NOTAOVERLAYSURFACE;
368 w = This->overlay_destrect.right - This->overlay_destrect.left;
369 h = This->overlay_destrect.bottom - This->overlay_destrect.top;
370 This->overlay_destrect.left = X;
371 This->overlay_destrect.top = Y;
372 This->overlay_destrect.right = X + w;
373 This->overlay_destrect.bottom = Y + h;
375 IWineD3DSurface_DrawOverlay(iface);
377 return WINED3D_OK;
380 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
381 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
382 HRESULT hr;
384 TRACE("(%p)->(%p,%p)\n", This, X, Y);
386 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
388 TRACE("(%p): Not an overlay surface\n", This);
389 return WINEDDERR_NOTAOVERLAYSURFACE;
391 if(This->overlay_dest == NULL) {
392 *X = 0; *Y = 0;
393 hr = WINEDDERR_OVERLAYNOTVISIBLE;
394 } else {
395 *X = This->overlay_destrect.left;
396 *Y = This->overlay_destrect.top;
397 hr = WINED3D_OK;
400 TRACE("Returning 0x%08x, position %d, %d\n", hr, *X, *Y);
401 return hr;
404 HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
405 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
406 IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
408 FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
410 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
412 TRACE("(%p): Not an overlay surface\n", This);
413 return WINEDDERR_NOTAOVERLAYSURFACE;
416 return WINED3D_OK;
419 HRESULT WINAPI IWineD3DBaseSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, const RECT *SrcRect,
420 IWineD3DSurface *DstSurface, const RECT *DstRect, DWORD Flags, const WINEDDOVERLAYFX *FX)
422 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
423 IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
424 TRACE("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
426 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
428 WARN("(%p): Not an overlay surface\n", This);
429 return WINEDDERR_NOTAOVERLAYSURFACE;
430 } else if(!DstSurface) {
431 WARN("(%p): Dest surface is NULL\n", This);
432 return WINED3DERR_INVALIDCALL;
435 if(SrcRect) {
436 This->overlay_srcrect = *SrcRect;
437 } else {
438 This->overlay_srcrect.left = 0;
439 This->overlay_srcrect.top = 0;
440 This->overlay_srcrect.right = This->currentDesc.Width;
441 This->overlay_srcrect.bottom = This->currentDesc.Height;
444 if(DstRect) {
445 This->overlay_destrect = *DstRect;
446 } else {
447 This->overlay_destrect.left = 0;
448 This->overlay_destrect.top = 0;
449 This->overlay_destrect.right = Dst ? Dst->currentDesc.Width : 0;
450 This->overlay_destrect.bottom = Dst ? Dst->currentDesc.Height : 0;
453 if(This->overlay_dest && (This->overlay_dest != Dst || Flags & WINEDDOVER_HIDE)) {
454 list_remove(&This->overlay_entry);
457 if(Flags & WINEDDOVER_SHOW) {
458 if(This->overlay_dest != Dst) {
459 This->overlay_dest = Dst;
460 list_add_tail(&Dst->overlays, &This->overlay_entry);
462 } else if(Flags & WINEDDOVER_HIDE) {
463 /* tests show that the rectangles are erased on hide */
464 This->overlay_srcrect.left = 0; This->overlay_srcrect.top = 0;
465 This->overlay_srcrect.right = 0; This->overlay_srcrect.bottom = 0;
466 This->overlay_destrect.left = 0; This->overlay_destrect.top = 0;
467 This->overlay_destrect.right = 0; This->overlay_destrect.bottom = 0;
468 This->overlay_dest = NULL;
471 IWineD3DSurface_DrawOverlay(iface);
473 return WINED3D_OK;
476 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD3DClipper *clipper)
478 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
479 TRACE("(%p)->(%p)\n", This, clipper);
481 This->clipper = clipper;
482 return WINED3D_OK;
485 HRESULT WINAPI IWineD3DBaseSurfaceImpl_GetClipper(IWineD3DSurface *iface, IWineD3DClipper **clipper)
487 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
488 TRACE("(%p)->(%p)\n", This, clipper);
490 *clipper = This->clipper;
491 if(*clipper) {
492 IWineD3DClipper_AddRef(*clipper);
494 return WINED3D_OK;
497 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
498 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
500 TRACE("This %p, container %p\n", This, container);
502 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
504 TRACE("Setting container to %p from %p\n", container, This->container);
505 This->container = container;
507 return WINED3D_OK;
510 HRESULT WINAPI IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
511 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
512 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(format,
513 &This->resource.wineD3DDevice->adapter->gl_info);
515 if (This->resource.format_desc->format != WINED3DFMT_UNKNOWN)
517 FIXME("(%p) : The format of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
518 return WINED3DERR_INVALIDCALL;
521 TRACE("(%p) : Setting texture format to (%d,%s)\n", This, format, debug_d3dformat(format));
523 This->resource.size = surface_calculate_size(format_desc, This->resource.wineD3DDevice->surface_alignment,
524 This->pow2Width, This->pow2Height);
526 This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
528 This->resource.format_desc = format_desc;
530 TRACE("(%p) : Size %d, bytesPerPixel %d\n", This, This->resource.size, format_desc->byte_count);
532 return WINED3D_OK;
535 HRESULT IWineD3DBaseSurfaceImpl_CreateDIBSection(IWineD3DSurface *iface) {
536 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
537 const struct GlPixelFormatDesc *format_desc = This->resource.format_desc;
538 int extraline = 0;
539 SYSTEM_INFO sysInfo;
540 BITMAPINFO* b_info;
541 HDC ddc;
542 DWORD *masks;
543 UINT usage;
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_R8G8B8:
596 usage = DIB_RGB_COLORS;
597 b_info->bmiHeader.biCompression = BI_RGB;
598 break;
600 case WINED3DFMT_X1R5G5B5:
601 case WINED3DFMT_A1R5G5B5:
602 case WINED3DFMT_A4R4G4B4:
603 case WINED3DFMT_X4R4G4B4:
604 case WINED3DFMT_R3G3B2:
605 case WINED3DFMT_A8R3G3B2:
606 case WINED3DFMT_R10G10B10A2_UNORM:
607 case WINED3DFMT_R8G8B8A8_UNORM:
608 case WINED3DFMT_X8B8G8R8:
609 case WINED3DFMT_A2R10G10B10:
610 case WINED3DFMT_R5G6B5:
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 struct d3dfmt_convertor_desc {
728 WINED3DFORMAT from, to;
729 void (*convert)(const BYTE *src, BYTE *dst, DWORD pitch_in, DWORD pitch_out, unsigned int w, unsigned int h);
732 static const struct d3dfmt_convertor_desc convertors[] =
734 {WINED3DFMT_R32_FLOAT, WINED3DFMT_R16_FLOAT, convert_r32_float_r16_float},
735 {WINED3DFMT_R5G6B5, WINED3DFMT_X8R8G8B8, convert_r5g6b5_x8r8g8b8},
738 static inline const struct d3dfmt_convertor_desc *find_convertor(WINED3DFORMAT from, WINED3DFORMAT to)
740 unsigned int i;
741 for(i = 0; i < (sizeof(convertors) / sizeof(convertors[0])); i++) {
742 if(convertors[i].from == from && convertors[i].to == to) {
743 return &convertors[i];
746 return NULL;
749 /*****************************************************************************
750 * surface_convert_format
752 * Creates a duplicate of a surface in a different format. Is used by Blt to
753 * blit between surfaces with different formats
755 * Parameters
756 * source: Source surface
757 * fmt: Requested destination format
759 *****************************************************************************/
760 static IWineD3DSurfaceImpl *surface_convert_format(IWineD3DSurfaceImpl *source, WINED3DFORMAT to_fmt) {
761 IWineD3DSurface *ret = NULL;
762 const struct d3dfmt_convertor_desc *conv;
763 WINED3DLOCKED_RECT lock_src, lock_dst;
764 HRESULT hr;
766 conv = find_convertor(source->resource.format_desc->format, to_fmt);
767 if(!conv) {
768 FIXME("Cannot find a conversion function from format %s to %s\n",
769 debug_d3dformat(source->resource.format_desc->format), debug_d3dformat(to_fmt));
770 return NULL;
773 IWineD3DDevice_CreateSurface((IWineD3DDevice *)source->resource.wineD3DDevice, source->currentDesc.Width,
774 source->currentDesc.Height, to_fmt, TRUE /* lockable */, TRUE /* discard */, 0 /* level */, &ret,
775 0 /* usage */, WINED3DPOOL_SCRATCH, WINED3DMULTISAMPLE_NONE /* TODO: Multisampled conversion */,
776 0 /* MultiSampleQuality */, IWineD3DSurface_GetImplType((IWineD3DSurface *) source), NULL /* parent */);
777 if(!ret) {
778 ERR("Failed to create a destination surface for conversion\n");
779 return NULL;
782 memset(&lock_src, 0, sizeof(lock_src));
783 memset(&lock_dst, 0, sizeof(lock_dst));
785 hr = IWineD3DSurface_LockRect((IWineD3DSurface *) source, &lock_src, NULL, WINED3DLOCK_READONLY);
786 if(FAILED(hr)) {
787 ERR("Failed to lock the source surface\n");
788 IWineD3DSurface_Release(ret);
789 return NULL;
791 hr = IWineD3DSurface_LockRect(ret, &lock_dst, NULL, WINED3DLOCK_READONLY);
792 if(FAILED(hr)) {
793 ERR("Failed to lock the dest surface\n");
794 IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
795 IWineD3DSurface_Release(ret);
796 return NULL;
799 conv->convert(lock_src.pBits, lock_dst.pBits, lock_src.Pitch, lock_dst.Pitch,
800 source->currentDesc.Width, source->currentDesc.Height);
802 IWineD3DSurface_UnlockRect(ret);
803 IWineD3DSurface_UnlockRect((IWineD3DSurface *) source);
805 return (IWineD3DSurfaceImpl *) ret;
808 /*****************************************************************************
809 * _Blt_ColorFill
811 * Helper function that fills a memory area with a specific color
813 * Params:
814 * buf: memory address to start filling at
815 * width, height: Dimensions of the area to fill
816 * bpp: Bit depth of the surface
817 * lPitch: pitch of the surface
818 * color: Color to fill with
820 *****************************************************************************/
821 static HRESULT
822 _Blt_ColorFill(BYTE *buf,
823 int width, int height,
824 int bpp, LONG lPitch,
825 DWORD color)
827 int x, y;
828 LPBYTE first;
830 /* Do first row */
832 #define COLORFILL_ROW(type) \
834 type *d = (type *) buf; \
835 for (x = 0; x < width; x++) \
836 d[x] = (type) color; \
837 break; \
839 switch(bpp)
841 case 1: COLORFILL_ROW(BYTE)
842 case 2: COLORFILL_ROW(WORD)
843 case 3:
845 BYTE *d = buf;
846 for (x = 0; x < width; x++,d+=3)
848 d[0] = (color ) & 0xFF;
849 d[1] = (color>> 8) & 0xFF;
850 d[2] = (color>>16) & 0xFF;
852 break;
854 case 4: COLORFILL_ROW(DWORD)
855 default:
856 FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
857 return WINED3DERR_NOTAVAILABLE;
860 #undef COLORFILL_ROW
862 /* Now copy first row */
863 first = buf;
864 for (y = 1; y < height; y++)
866 buf += lPitch;
867 memcpy(buf, first, width * bpp);
869 return WINED3D_OK;
872 /*****************************************************************************
873 * IWineD3DSurface::Blt, SW emulation version
875 * Performs blits to a surface, eigher from a source of source-less blts
876 * This is the main functionality of DirectDraw
878 * Params:
879 * DestRect: Destination rectangle to write to
880 * SrcSurface: Source surface, can be NULL
881 * SrcRect: Source rectangle
882 *****************************************************************************/
883 HRESULT WINAPI IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *DestRect, IWineD3DSurface *SrcSurface,
884 const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter)
886 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
887 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
888 RECT xdst,xsrc;
889 HRESULT ret = WINED3D_OK;
890 WINED3DLOCKED_RECT dlock, slock;
891 int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
892 const struct GlPixelFormatDesc *sEntry, *dEntry;
893 int x, y;
894 const BYTE *sbuf;
895 BYTE *dbuf;
896 TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, Src, SrcRect, Flags, DDBltFx);
898 if (TRACE_ON(d3d_surface))
900 if (DestRect) TRACE("\tdestrect :%dx%d-%dx%d\n",
901 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
902 if (SrcRect) TRACE("\tsrcrect :%dx%d-%dx%d\n",
903 SrcRect->left, SrcRect->top, SrcRect->right, SrcRect->bottom);
904 #if 0
905 TRACE("\tflags: ");
906 DDRAW_dump_DDBLT(Flags);
907 if (Flags & WINEDDBLT_DDFX)
909 TRACE("\tblitfx: ");
910 DDRAW_dump_DDBLTFX(DDBltFx->dwDDFX);
912 #endif
915 if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
917 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
918 return WINEDDERR_SURFACEBUSY;
921 if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) {
922 /* Can happen when d3d9 apps do a StretchRect call which isn't handled in gl */
923 FIXME("Filters not supported in software blit\n");
926 /* First check for the validity of source / destination rectangles. This was
927 * verified using a test application + by MSDN.
929 if ((Src != NULL) && (SrcRect != NULL) &&
930 ((SrcRect->bottom > Src->currentDesc.Height)||(SrcRect->bottom < 0) ||
931 (SrcRect->top > Src->currentDesc.Height)||(SrcRect->top < 0) ||
932 (SrcRect->left > Src->currentDesc.Width) ||(SrcRect->left < 0) ||
933 (SrcRect->right > Src->currentDesc.Width) ||(SrcRect->right < 0) ||
934 (SrcRect->right < SrcRect->left) ||(SrcRect->bottom < SrcRect->top)))
936 WARN("Application gave us bad source rectangle for Blt.\n");
937 return WINEDDERR_INVALIDRECT;
939 /* For the Destination rect, it can be out of bounds on the condition that a clipper
940 * is set for the given surface.
942 if ((/*This->clipper == NULL*/ TRUE) && (DestRect) &&
943 ((DestRect->bottom > This->currentDesc.Height)||(DestRect->bottom < 0) ||
944 (DestRect->top > This->currentDesc.Height)||(DestRect->top < 0) ||
945 (DestRect->left > This->currentDesc.Width) ||(DestRect->left < 0) ||
946 (DestRect->right > This->currentDesc.Width) ||(DestRect->right < 0) ||
947 (DestRect->right < DestRect->left) ||(DestRect->bottom < DestRect->top)))
949 WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n");
950 return WINEDDERR_INVALIDRECT;
953 /* Now handle negative values in the rectangles. Warning: only supported for now
954 in the 'simple' cases (ie not in any stretching / rotation cases).
956 First, the case where nothing is to be done.
958 if ((DestRect && ((DestRect->bottom <= 0) || (DestRect->right <= 0) ||
959 (DestRect->top >= (int) This->currentDesc.Height) ||
960 (DestRect->left >= (int) This->currentDesc.Width))) ||
961 ((Src != NULL) && (SrcRect != NULL) &&
962 ((SrcRect->bottom <= 0) || (SrcRect->right <= 0) ||
963 (SrcRect->top >= (int) Src->currentDesc.Height) ||
964 (SrcRect->left >= (int) Src->currentDesc.Width)) ))
966 TRACE("Nothing to be done !\n");
967 return WINED3D_OK;
970 if (DestRect)
972 xdst = *DestRect;
974 else
976 xdst.top = 0;
977 xdst.bottom = This->currentDesc.Height;
978 xdst.left = 0;
979 xdst.right = This->currentDesc.Width;
982 if (SrcRect)
984 xsrc = *SrcRect;
986 else
988 if (Src)
990 xsrc.top = 0;
991 xsrc.bottom = Src->currentDesc.Height;
992 xsrc.left = 0;
993 xsrc.right = Src->currentDesc.Width;
995 else
997 memset(&xsrc,0,sizeof(xsrc));
1001 /* The easy case : the source-less blits.... */
1002 if (Src == NULL && DestRect)
1004 RECT full_rect;
1005 RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */
1007 full_rect.left = 0;
1008 full_rect.top = 0;
1009 full_rect.right = This->currentDesc.Width;
1010 full_rect.bottom = This->currentDesc.Height;
1011 IntersectRect(&temp_rect, &full_rect, DestRect);
1012 xdst = temp_rect;
1014 else if (DestRect)
1016 /* Only handle clipping on the destination rectangle */
1017 int clip_horiz = (DestRect->left < 0) || (DestRect->right > (int) This->currentDesc.Width );
1018 int clip_vert = (DestRect->top < 0) || (DestRect->bottom > (int) This->currentDesc.Height);
1019 if (clip_vert || clip_horiz)
1021 /* Now check if this is a special case or not... */
1022 if ((((DestRect->bottom - DestRect->top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) ||
1023 (((DestRect->right - DestRect->left) != (xsrc.right - xsrc.left)) && clip_horiz) ||
1024 (Flags & WINEDDBLT_DDFX))
1026 WARN("Out of screen rectangle in special case. Not handled right now.\n");
1027 return WINED3D_OK;
1030 if (clip_horiz)
1032 if (DestRect->left < 0) { xsrc.left -= DestRect->left; xdst.left = 0; }
1033 if (DestRect->right > This->currentDesc.Width)
1035 xsrc.right -= (DestRect->right - (int) This->currentDesc.Width);
1036 xdst.right = (int) This->currentDesc.Width;
1039 if (clip_vert)
1041 if (DestRect->top < 0)
1043 xsrc.top -= DestRect->top;
1044 xdst.top = 0;
1046 if (DestRect->bottom > This->currentDesc.Height)
1048 xsrc.bottom -= (DestRect->bottom - (int) This->currentDesc.Height);
1049 xdst.bottom = (int) This->currentDesc.Height;
1052 /* And check if after clipping something is still to be done... */
1053 if ((xdst.bottom <= 0) || (xdst.right <= 0) ||
1054 (xdst.top >= (int) This->currentDesc.Height) ||
1055 (xdst.left >= (int) This->currentDesc.Width) ||
1056 (xsrc.bottom <= 0) || (xsrc.right <= 0) ||
1057 (xsrc.top >= (int) Src->currentDesc.Height) ||
1058 (xsrc.left >= (int) Src->currentDesc.Width))
1060 TRACE("Nothing to be done after clipping !\n");
1061 return WINED3D_OK;
1066 if (Src == This)
1068 IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
1069 slock = dlock;
1070 sEntry = This->resource.format_desc;
1071 dEntry = sEntry;
1073 else
1075 dEntry = This->resource.format_desc;
1076 if (Src)
1078 if (This->resource.format_desc->format != Src->resource.format_desc->format)
1080 Src = surface_convert_format(Src, dEntry->format);
1081 if(!Src) {
1082 /* The conv function writes a FIXME */
1083 WARN("Cannot convert source surface format to dest format\n");
1084 goto release;
1087 IWineD3DSurface_LockRect((IWineD3DSurface *) Src, &slock, NULL, WINED3DLOCK_READONLY);
1088 sEntry = Src->resource.format_desc;
1090 else
1092 sEntry = dEntry;
1094 if (DestRect)
1095 IWineD3DSurface_LockRect(iface, &dlock, &xdst, 0);
1096 else
1097 IWineD3DSurface_LockRect(iface, &dlock, NULL, 0);
1100 if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX;
1102 if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_FOURCC)
1104 if (!DestRect || Src == This)
1106 memcpy(dlock.pBits, slock.pBits, This->resource.size);
1107 goto release;
1111 bpp = This->resource.format_desc->byte_count;
1112 srcheight = xsrc.bottom - xsrc.top;
1113 srcwidth = xsrc.right - xsrc.left;
1114 dstheight = xdst.bottom - xdst.top;
1115 dstwidth = xdst.right - xdst.left;
1116 width = (xdst.right - xdst.left) * bpp;
1118 if (DestRect && Src != This)
1119 dbuf = dlock.pBits;
1120 else
1121 dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp);
1123 if (Flags & WINEDDBLT_WAIT)
1125 Flags &= ~WINEDDBLT_WAIT;
1127 if (Flags & WINEDDBLT_ASYNC)
1129 static BOOL displayed = FALSE;
1130 if (!displayed)
1131 FIXME("Can't handle WINEDDBLT_ASYNC flag right now.\n");
1132 displayed = TRUE;
1133 Flags &= ~WINEDDBLT_ASYNC;
1135 if (Flags & WINEDDBLT_DONOTWAIT)
1137 /* WINEDDBLT_DONOTWAIT appeared in DX7 */
1138 static BOOL displayed = FALSE;
1139 if (!displayed)
1140 FIXME("Can't handle WINEDDBLT_DONOTWAIT flag right now.\n");
1141 displayed = TRUE;
1142 Flags &= ~WINEDDBLT_DONOTWAIT;
1145 /* First, all the 'source-less' blits */
1146 if (Flags & WINEDDBLT_COLORFILL)
1148 ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
1149 dlock.Pitch, DDBltFx->u5.dwFillColor);
1150 Flags &= ~WINEDDBLT_COLORFILL;
1153 if (Flags & WINEDDBLT_DEPTHFILL)
1155 FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
1157 if (Flags & WINEDDBLT_ROP)
1159 /* Catch some degenerate cases here */
1160 switch(DDBltFx->dwROP)
1162 case BLACKNESS:
1163 ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,0);
1164 break;
1165 case 0xAA0029: /* No-op */
1166 break;
1167 case WHITENESS:
1168 ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,dlock.Pitch,~0);
1169 break;
1170 case SRCCOPY: /* well, we do that below ? */
1171 break;
1172 default:
1173 FIXME("Unsupported raster op: %08x Pattern: %p\n", DDBltFx->dwROP, DDBltFx->u5.lpDDSPattern);
1174 goto error;
1176 Flags &= ~WINEDDBLT_ROP;
1178 if (Flags & WINEDDBLT_DDROPS)
1180 FIXME("\tDdraw Raster Ops: %08x Pattern: %p\n", DDBltFx->dwDDROP, DDBltFx->u5.lpDDSPattern);
1182 /* Now the 'with source' blits */
1183 if (Src)
1185 const BYTE *sbase;
1186 int sx, xinc, sy, yinc;
1188 if (!dstwidth || !dstheight) /* hmm... stupid program ? */
1189 goto release;
1190 sbase = (BYTE*)slock.pBits+(xsrc.top*slock.Pitch)+xsrc.left*bpp;
1191 xinc = (srcwidth << 16) / dstwidth;
1192 yinc = (srcheight << 16) / dstheight;
1194 if (!Flags)
1196 /* No effects, we can cheat here */
1197 if (dstwidth == srcwidth)
1199 if (dstheight == srcheight)
1201 /* No stretching in either direction. This needs to be as
1202 * fast as possible */
1203 sbuf = sbase;
1205 /* check for overlapping surfaces */
1206 if (Src != This || xdst.top < xsrc.top ||
1207 xdst.right <= xsrc.left || xsrc.right <= xdst.left)
1209 /* no overlap, or dst above src, so copy from top downwards */
1210 for (y = 0; y < dstheight; y++)
1212 memcpy(dbuf, sbuf, width);
1213 sbuf += slock.Pitch;
1214 dbuf += dlock.Pitch;
1217 else if (xdst.top > xsrc.top) /* copy from bottom upwards */
1219 sbuf += (slock.Pitch*dstheight);
1220 dbuf += (dlock.Pitch*dstheight);
1221 for (y = 0; y < dstheight; y++)
1223 sbuf -= slock.Pitch;
1224 dbuf -= dlock.Pitch;
1225 memcpy(dbuf, sbuf, width);
1228 else /* src and dst overlapping on the same line, use memmove */
1230 for (y = 0; y < dstheight; y++)
1232 memmove(dbuf, sbuf, width);
1233 sbuf += slock.Pitch;
1234 dbuf += dlock.Pitch;
1237 } else {
1238 /* Stretching in Y direction only */
1239 for (y = sy = 0; y < dstheight; y++, sy += yinc) {
1240 sbuf = sbase + (sy >> 16) * slock.Pitch;
1241 memcpy(dbuf, sbuf, width);
1242 dbuf += dlock.Pitch;
1246 else
1248 /* Stretching in X direction */
1249 int last_sy = -1;
1250 for (y = sy = 0; y < dstheight; y++, sy += yinc)
1252 sbuf = sbase + (sy >> 16) * slock.Pitch;
1254 if ((sy >> 16) == (last_sy >> 16))
1256 /* this sourcerow is the same as last sourcerow -
1257 * copy already stretched row
1259 memcpy(dbuf, dbuf - dlock.Pitch, width);
1261 else
1263 #define STRETCH_ROW(type) { \
1264 const type *s = (const type *)sbuf; \
1265 type *d = (type *)dbuf; \
1266 for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
1267 d[x] = s[sx >> 16]; \
1268 break; }
1270 switch(bpp)
1272 case 1: STRETCH_ROW(BYTE)
1273 case 2: STRETCH_ROW(WORD)
1274 case 4: STRETCH_ROW(DWORD)
1275 case 3:
1277 const BYTE *s;
1278 BYTE *d = dbuf;
1279 for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
1281 DWORD pixel;
1283 s = sbuf+3*(sx>>16);
1284 pixel = s[0]|(s[1]<<8)|(s[2]<<16);
1285 d[0] = (pixel )&0xff;
1286 d[1] = (pixel>> 8)&0xff;
1287 d[2] = (pixel>>16)&0xff;
1288 d+=3;
1290 break;
1292 default:
1293 FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
1294 ret = WINED3DERR_NOTAVAILABLE;
1295 goto error;
1297 #undef STRETCH_ROW
1299 dbuf += dlock.Pitch;
1300 last_sy = sy;
1304 else
1306 LONG dstyinc = dlock.Pitch, dstxinc = bpp;
1307 DWORD keylow = 0xFFFFFFFF, keyhigh = 0, keymask = 0xFFFFFFFF;
1308 DWORD destkeylow = 0x0, destkeyhigh = 0xFFFFFFFF, destkeymask = 0xFFFFFFFF;
1309 if (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE))
1311 /* The color keying flags are checked for correctness in ddraw */
1312 if (Flags & WINEDDBLT_KEYSRC)
1314 keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
1315 keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
1317 else if (Flags & WINEDDBLT_KEYSRCOVERRIDE)
1319 keylow = DDBltFx->ddckSrcColorkey.dwColorSpaceLowValue;
1320 keyhigh = DDBltFx->ddckSrcColorkey.dwColorSpaceHighValue;
1323 if (Flags & WINEDDBLT_KEYDEST)
1325 /* Destination color keys are taken from the source surface ! */
1326 destkeylow = Src->DestBltCKey.dwColorSpaceLowValue;
1327 destkeyhigh = Src->DestBltCKey.dwColorSpaceHighValue;
1329 else if (Flags & WINEDDBLT_KEYDESTOVERRIDE)
1331 destkeylow = DDBltFx->ddckDestColorkey.dwColorSpaceLowValue;
1332 destkeyhigh = DDBltFx->ddckDestColorkey.dwColorSpaceHighValue;
1335 if(bpp == 1)
1337 keymask = 0xff;
1339 else
1341 keymask = sEntry->red_mask
1342 | sEntry->green_mask
1343 | sEntry->blue_mask;
1345 Flags &= ~(WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE);
1348 if (Flags & WINEDDBLT_DDFX)
1350 LPBYTE dTopLeft, dTopRight, dBottomLeft, dBottomRight, tmp;
1351 LONG tmpxy;
1352 dTopLeft = dbuf;
1353 dTopRight = dbuf+((dstwidth-1)*bpp);
1354 dBottomLeft = dTopLeft+((dstheight-1)*dlock.Pitch);
1355 dBottomRight = dBottomLeft+((dstwidth-1)*bpp);
1357 if (DDBltFx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY)
1359 /* I don't think we need to do anything about this flag */
1360 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_ARITHSTRETCHY\n");
1362 if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORLEFTRIGHT)
1364 tmp = dTopRight;
1365 dTopRight = dTopLeft;
1366 dTopLeft = tmp;
1367 tmp = dBottomRight;
1368 dBottomRight = dBottomLeft;
1369 dBottomLeft = tmp;
1370 dstxinc = dstxinc *-1;
1372 if (DDBltFx->dwDDFX & WINEDDBLTFX_MIRRORUPDOWN)
1374 tmp = dTopLeft;
1375 dTopLeft = dBottomLeft;
1376 dBottomLeft = tmp;
1377 tmp = dTopRight;
1378 dTopRight = dBottomRight;
1379 dBottomRight = tmp;
1380 dstyinc = dstyinc *-1;
1382 if (DDBltFx->dwDDFX & WINEDDBLTFX_NOTEARING)
1384 /* I don't think we need to do anything about this flag */
1385 WARN("Flags=DDBLT_DDFX nothing done for WINEDDBLTFX_NOTEARING\n");
1387 if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE180)
1389 tmp = dBottomRight;
1390 dBottomRight = dTopLeft;
1391 dTopLeft = tmp;
1392 tmp = dBottomLeft;
1393 dBottomLeft = dTopRight;
1394 dTopRight = tmp;
1395 dstxinc = dstxinc * -1;
1396 dstyinc = dstyinc * -1;
1398 if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE270)
1400 tmp = dTopLeft;
1401 dTopLeft = dBottomLeft;
1402 dBottomLeft = dBottomRight;
1403 dBottomRight = dTopRight;
1404 dTopRight = tmp;
1405 tmpxy = dstxinc;
1406 dstxinc = dstyinc;
1407 dstyinc = tmpxy;
1408 dstxinc = dstxinc * -1;
1410 if (DDBltFx->dwDDFX & WINEDDBLTFX_ROTATE90)
1412 tmp = dTopLeft;
1413 dTopLeft = dTopRight;
1414 dTopRight = dBottomRight;
1415 dBottomRight = dBottomLeft;
1416 dBottomLeft = tmp;
1417 tmpxy = dstxinc;
1418 dstxinc = dstyinc;
1419 dstyinc = tmpxy;
1420 dstyinc = dstyinc * -1;
1422 if (DDBltFx->dwDDFX & WINEDDBLTFX_ZBUFFERBASEDEST)
1424 /* I don't think we need to do anything about this flag */
1425 WARN("Flags=WINEDDBLT_DDFX nothing done for WINEDDBLTFX_ZBUFFERBASEDEST\n");
1427 dbuf = dTopLeft;
1428 Flags &= ~(WINEDDBLT_DDFX);
1431 #define COPY_COLORKEY_FX(type) { \
1432 const type *s; \
1433 type *d = (type *)dbuf, *dx, tmp; \
1434 for (y = sy = 0; y < dstheight; y++, sy += yinc) { \
1435 s = (const type*)(sbase + (sy >> 16) * slock.Pitch); \
1436 dx = d; \
1437 for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
1438 tmp = s[sx >> 16]; \
1439 if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) && \
1440 ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) { \
1441 dx[0] = tmp; \
1443 dx = (type*)(((LPBYTE)dx)+dstxinc); \
1445 d = (type*)(((LPBYTE)d)+dstyinc); \
1447 break; }
1449 switch (bpp) {
1450 case 1: COPY_COLORKEY_FX(BYTE)
1451 case 2: COPY_COLORKEY_FX(WORD)
1452 case 4: COPY_COLORKEY_FX(DWORD)
1453 case 3:
1455 const BYTE *s;
1456 BYTE *d = dbuf, *dx;
1457 for (y = sy = 0; y < dstheight; y++, sy += yinc)
1459 sbuf = sbase + (sy >> 16) * slock.Pitch;
1460 dx = d;
1461 for (x = sx = 0; x < dstwidth; x++, sx+= xinc)
1463 DWORD pixel, dpixel = 0;
1464 s = sbuf+3*(sx>>16);
1465 pixel = s[0]|(s[1]<<8)|(s[2]<<16);
1466 dpixel = dx[0]|(dx[1]<<8)|(dx[2]<<16);
1467 if (((pixel & keymask) < keylow || (pixel & keymask) > keyhigh) &&
1468 ((dpixel & keymask) >= destkeylow || (dpixel & keymask) <= keyhigh))
1470 dx[0] = (pixel )&0xff;
1471 dx[1] = (pixel>> 8)&0xff;
1472 dx[2] = (pixel>>16)&0xff;
1474 dx+= dstxinc;
1476 d += dstyinc;
1478 break;
1480 default:
1481 FIXME("%s color-keyed blit not implemented for bpp %d!\n",
1482 (Flags & WINEDDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
1483 ret = WINED3DERR_NOTAVAILABLE;
1484 goto error;
1485 #undef COPY_COLORKEY_FX
1490 error:
1491 if (Flags && FIXME_ON(d3d_surface))
1493 FIXME("\tUnsupported flags: %08x\n", Flags);
1496 release:
1497 IWineD3DSurface_UnlockRect(iface);
1498 if (Src && Src != This) IWineD3DSurface_UnlockRect((IWineD3DSurface *) Src);
1499 /* Release the converted surface if any */
1500 if (Src && SrcSurface != (IWineD3DSurface *) Src) IWineD3DSurface_Release((IWineD3DSurface *) Src);
1501 return ret;
1504 /*****************************************************************************
1505 * IWineD3DSurface::BltFast, SW emulation version
1507 * This is the software implementation of BltFast, as used by GDI surfaces
1508 * and as a fallback for OpenGL surfaces. This code is taken from the old
1509 * DirectDraw code, and was originally written by TransGaming.
1511 * Params:
1512 * dstx:
1513 * dsty:
1514 * Source: Source surface to copy from
1515 * rsrc: Source rectangle
1516 * trans: Some Flags
1518 * Returns:
1519 * WINED3D_OK on success
1521 *****************************************************************************/
1522 HRESULT WINAPI IWineD3DBaseSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty,
1523 IWineD3DSurface *Source, const RECT *rsrc, DWORD trans)
1525 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1526 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) Source;
1528 int bpp, w, h, x, y;
1529 WINED3DLOCKED_RECT dlock,slock;
1530 HRESULT ret = WINED3D_OK;
1531 RECT rsrc2;
1532 RECT lock_src, lock_dst, lock_union;
1533 const BYTE *sbuf;
1534 BYTE *dbuf;
1535 const struct GlPixelFormatDesc *sEntry, *dEntry;
1537 if (TRACE_ON(d3d_surface))
1539 TRACE("(%p)->(%d,%d,%p,%p,%08x)\n", This,dstx,dsty,Src,rsrc,trans);
1541 if (rsrc)
1543 TRACE("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,
1544 rsrc->right,rsrc->bottom);
1546 else
1548 TRACE(" srcrect: NULL\n");
1552 if ((This->Flags & SFLAG_LOCKED) ||
1553 (Src->Flags & SFLAG_LOCKED))
1555 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1556 return WINEDDERR_SURFACEBUSY;
1559 if (!rsrc)
1561 WARN("rsrc is NULL!\n");
1562 rsrc2.left = 0;
1563 rsrc2.top = 0;
1564 rsrc2.right = Src->currentDesc.Width;
1565 rsrc2.bottom = Src->currentDesc.Height;
1566 rsrc = &rsrc2;
1569 /* Check source rect for validity. Copied from normal Blt. Fixes Baldur's Gate.*/
1570 if ((rsrc->bottom > Src->currentDesc.Height) || (rsrc->bottom < 0) ||
1571 (rsrc->top > Src->currentDesc.Height) || (rsrc->top < 0) ||
1572 (rsrc->left > Src->currentDesc.Width) || (rsrc->left < 0) ||
1573 (rsrc->right > Src->currentDesc.Width) || (rsrc->right < 0) ||
1574 (rsrc->right < rsrc->left) || (rsrc->bottom < rsrc->top))
1576 WARN("Application gave us bad source rectangle for BltFast.\n");
1577 return WINEDDERR_INVALIDRECT;
1580 h = rsrc->bottom - rsrc->top;
1581 if (h > This->currentDesc.Height-dsty) h = This->currentDesc.Height-dsty;
1582 if (h > Src->currentDesc.Height-rsrc->top) h=Src->currentDesc.Height-rsrc->top;
1583 if (h <= 0) return WINEDDERR_INVALIDRECT;
1585 w = rsrc->right - rsrc->left;
1586 if (w > This->currentDesc.Width-dstx) w = This->currentDesc.Width-dstx;
1587 if (w > Src->currentDesc.Width-rsrc->left) w = Src->currentDesc.Width-rsrc->left;
1588 if (w <= 0) return WINEDDERR_INVALIDRECT;
1590 /* Now compute the locking rectangle... */
1591 lock_src.left = rsrc->left;
1592 lock_src.top = rsrc->top;
1593 lock_src.right = lock_src.left + w;
1594 lock_src.bottom = lock_src.top + h;
1596 lock_dst.left = dstx;
1597 lock_dst.top = dsty;
1598 lock_dst.right = dstx + w;
1599 lock_dst.bottom = dsty + h;
1601 bpp = This->resource.format_desc->byte_count;
1603 /* We need to lock the surfaces, or we won't get refreshes when done. */
1604 if (Src == This)
1606 int pitch;
1608 UnionRect(&lock_union, &lock_src, &lock_dst);
1610 /* Lock the union of the two rectangles */
1611 ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_union, 0);
1612 if(ret != WINED3D_OK) goto error;
1614 pitch = dlock.Pitch;
1615 slock.Pitch = dlock.Pitch;
1617 /* Since slock was originally copied from this surface's description, we can just reuse it */
1618 sbuf = This->resource.allocatedMemory + lock_src.top * pitch + lock_src.left * bpp;
1619 dbuf = This->resource.allocatedMemory + lock_dst.top * pitch + lock_dst.left * bpp;
1620 sEntry = Src->resource.format_desc;
1621 dEntry = sEntry;
1623 else
1625 ret = IWineD3DSurface_LockRect(Source, &slock, &lock_src, WINED3DLOCK_READONLY);
1626 if(ret != WINED3D_OK) goto error;
1627 ret = IWineD3DSurface_LockRect(iface, &dlock, &lock_dst, 0);
1628 if(ret != WINED3D_OK) goto error;
1630 sbuf = slock.pBits;
1631 dbuf = dlock.pBits;
1632 TRACE("Dst is at %p, Src is at %p\n", dbuf, sbuf);
1634 sEntry = Src->resource.format_desc;
1635 dEntry = This->resource.format_desc;
1638 /* Handle compressed surfaces first... */
1639 if (sEntry->Flags & dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED)
1641 UINT row_block_count;
1643 TRACE("compressed -> compressed copy\n");
1644 if (trans)
1645 FIXME("trans arg not supported when a compressed surface is involved\n");
1646 if (dstx || dsty)
1647 FIXME("offset for destination surface is not supported\n");
1648 if (Src->resource.format_desc->format != This->resource.format_desc->format)
1650 FIXME("compressed -> compressed copy only supported for the same type of surface\n");
1651 ret = WINED3DERR_WRONGTEXTUREFORMAT;
1652 goto error;
1655 row_block_count = (w + dEntry->block_width - 1) / dEntry->block_width;
1656 for (y = 0; y < h; y += dEntry->block_height)
1658 memcpy(dbuf, sbuf, row_block_count * dEntry->block_byte_count);
1659 dbuf += dlock.Pitch;
1660 sbuf += slock.Pitch;
1663 goto error;
1665 if ((sEntry->Flags & WINED3DFMT_FLAG_COMPRESSED) && !(dEntry->Flags & WINED3DFMT_FLAG_COMPRESSED))
1667 /* TODO: Use the libtxc_dxtn.so shared library to do
1668 * software decompression
1670 ERR("Software decompression not supported.\n");
1671 goto error;
1674 if (trans & (WINEDDBLTFAST_SRCCOLORKEY | WINEDDBLTFAST_DESTCOLORKEY))
1676 DWORD keylow, keyhigh;
1677 TRACE("Color keyed copy\n");
1678 if (trans & WINEDDBLTFAST_SRCCOLORKEY)
1680 keylow = Src->SrcBltCKey.dwColorSpaceLowValue;
1681 keyhigh = Src->SrcBltCKey.dwColorSpaceHighValue;
1683 else
1685 /* I'm not sure if this is correct */
1686 FIXME("WINEDDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
1687 keylow = This->DestBltCKey.dwColorSpaceLowValue;
1688 keyhigh = This->DestBltCKey.dwColorSpaceHighValue;
1691 #define COPYBOX_COLORKEY(type) { \
1692 const type *s = (const type *)sbuf; \
1693 type *d = (type *)dbuf; \
1694 type tmp; \
1695 for (y = 0; y < h; y++) { \
1696 for (x = 0; x < w; x++) { \
1697 tmp = s[x]; \
1698 if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
1700 s = (const type *)((const BYTE *)s + slock.Pitch); \
1701 d = (type *)((BYTE *)d + dlock.Pitch); \
1703 break; \
1706 switch (bpp) {
1707 case 1: COPYBOX_COLORKEY(BYTE)
1708 case 2: COPYBOX_COLORKEY(WORD)
1709 case 4: COPYBOX_COLORKEY(DWORD)
1710 case 3:
1712 const BYTE *s;
1713 BYTE *d;
1714 DWORD tmp;
1715 s = sbuf;
1716 d = dbuf;
1717 for (y = 0; y < h; y++)
1719 for (x = 0; x < w * 3; x += 3)
1721 tmp = (DWORD)s[x] + ((DWORD)s[x + 1] << 8) + ((DWORD)s[x + 2] << 16);
1722 if (tmp < keylow || tmp > keyhigh)
1724 d[x + 0] = s[x + 0];
1725 d[x + 1] = s[x + 1];
1726 d[x + 2] = s[x + 2];
1729 s += slock.Pitch;
1730 d += dlock.Pitch;
1732 break;
1734 default:
1735 FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
1736 ret = WINED3DERR_NOTAVAILABLE;
1737 goto error;
1739 #undef COPYBOX_COLORKEY
1740 TRACE("Copy Done\n");
1742 else
1744 int width = w * bpp;
1745 INT sbufpitch, dbufpitch;
1747 TRACE("NO color key copy\n");
1748 /* Handle overlapping surfaces */
1749 if (sbuf < dbuf)
1751 sbuf += (h - 1) * slock.Pitch;
1752 dbuf += (h - 1) * dlock.Pitch;
1753 sbufpitch = -slock.Pitch;
1754 dbufpitch = -dlock.Pitch;
1756 else
1758 sbufpitch = slock.Pitch;
1759 dbufpitch = dlock.Pitch;
1761 for (y = 0; y < h; y++)
1763 /* This is pretty easy, a line for line memcpy */
1764 memmove(dbuf, sbuf, width);
1765 sbuf += sbufpitch;
1766 dbuf += dbufpitch;
1768 TRACE("Copy done\n");
1771 error:
1772 if (Src == This)
1774 IWineD3DSurface_UnlockRect(iface);
1776 else
1778 IWineD3DSurface_UnlockRect(iface);
1779 IWineD3DSurface_UnlockRect(Source);
1782 return ret;
1785 HRESULT WINAPI IWineD3DBaseSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags)
1787 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1789 TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n",
1790 This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
1792 pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
1794 if (NULL == pRect)
1796 pLockedRect->pBits = This->resource.allocatedMemory;
1797 This->lockedRect.left = 0;
1798 This->lockedRect.top = 0;
1799 This->lockedRect.right = This->currentDesc.Width;
1800 This->lockedRect.bottom = This->currentDesc.Height;
1802 TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n",
1803 &This->lockedRect, This->lockedRect.left, This->lockedRect.top,
1804 This->lockedRect.right, This->lockedRect.bottom);
1806 else
1808 const struct GlPixelFormatDesc *format_desc = This->resource.format_desc;
1810 TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n",
1811 pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
1813 if (format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
1815 /* Compressed textures are block based, so calculate the offset of
1816 * the block that contains the top-left pixel of the locked rectangle. */
1817 pLockedRect->pBits = This->resource.allocatedMemory
1818 + ((pRect->top / format_desc->block_height) * pLockedRect->Pitch)
1819 + ((pRect->left / format_desc->block_width) * format_desc->block_byte_count);
1821 else
1823 pLockedRect->pBits = This->resource.allocatedMemory +
1824 (pLockedRect->Pitch * pRect->top) +
1825 (pRect->left * format_desc->byte_count);
1827 This->lockedRect.left = pRect->left;
1828 This->lockedRect.top = pRect->top;
1829 This->lockedRect.right = pRect->right;
1830 This->lockedRect.bottom = pRect->bottom;
1833 /* No dirtifying is needed for this surface implementation */
1834 TRACE("returning memory@%p, pitch(%d)\n", pLockedRect->pBits, pLockedRect->Pitch);
1836 return WINED3D_OK;
1839 void WINAPI IWineD3DBaseSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL srgb) {
1840 ERR("Should not be called on base texture\n");
1841 return;
1844 /* TODO: think about moving this down to resource? */
1845 const void *WINAPI IWineD3DBaseSurfaceImpl_GetData(IWineD3DSurface *iface)
1847 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1849 /* This should only be called for sysmem textures, it may be a good idea
1850 * to extend this to all pools at some point in the future */
1851 if (This->resource.pool != WINED3DPOOL_SYSTEMMEM)
1853 FIXME("(%p) Attempting to get system memory for a non-system memory texture\n", iface);
1855 return This->resource.allocatedMemory;