2 * IWineD3DSurface Implementation
4 * Copyright 2000-2001 TransGaming Technologies Inc.
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2002-2003 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/port.h"
27 #include "wined3d_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
30 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
32 /* *******************************************
33 IWineD3DSurface IUnknown parts follow
34 ******************************************* */
35 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
37 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
38 /* Warn ,but be nice about things */
39 TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
41 ERR("Probably FIXME: Calling query interface with NULL riid\n");
43 if (IsEqualGUID(riid, &IID_IUnknown)
44 || IsEqualGUID(riid, &IID_IWineD3DBase)
45 || IsEqualGUID(riid, &IID_IWineD3DResource)
46 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
47 IUnknown_AddRef((IUnknown*)iface);
55 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
56 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
57 ULONG ref = InterlockedIncrement(&This->resource.ref);
58 TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
62 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
63 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
64 ULONG ref = InterlockedDecrement(&This->resource.ref);
65 TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
67 TRACE("(%p) : cleaning up\n", This);
68 if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
70 TRACE("Deleting texture %d\n", This->glDescription.textureName);
71 glDeleteTextures(1, &This->glDescription.textureName);
75 if(This->Flags & SFLAG_DIBSECTION) {
77 SelectObject(This->hDC, This->dib.holdbitmap);
79 /* Release the DIB section */
80 DeleteObject(This->dib.DIBsection);
81 This->dib.bitmap_data = NULL;
82 This->resource.allocatedMemory = NULL;
85 IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
87 TRACE("(%p) Released\n", This);
88 HeapFree(GetProcessHeap(), 0, This);
94 /* ****************************************************
95 IWineD3DSurface IWineD3DResource parts follow
96 **************************************************** */
97 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
98 return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
101 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
102 return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
105 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
106 return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
109 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
110 return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
113 DWORD WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
114 return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
117 DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
118 return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
121 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
122 /* TODO: re-write the way textures and managed,
123 * use a 'opengl context manager' to manage RenderTarget surfaces
124 ** *********************************************************/
126 /* TODO: check for locks */
127 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
128 IWineD3DBaseTexture *baseTexture = NULL;
129 TRACE("(%p)Checking to see if the container is a base texture\n", This);
130 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
131 TRACE("Passing to conatiner\n");
132 IWineD3DBaseTexture_PreLoad(baseTexture);
133 IWineD3DBaseTexture_Release(baseTexture);
135 TRACE("(%p) : About to load surface\n", This);
137 #if 0 /* TODO: context manager support */
138 IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
140 glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
141 if (This->glDescription.level == 0 && This->glDescription.textureName == 0) {
142 glGenTextures(1, &This->glDescription.textureName);
143 checkGLcall("glGenTextures");
144 TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
145 glBindTexture(This->glDescription.target, This->glDescription.textureName);
146 checkGLcall("glBindTexture");
147 IWineD3DSurface_LoadTexture(iface);
148 /* This is where we should be reducing the amount of GLMemoryUsed */
150 if (This->glDescription.level == 0) {
151 glBindTexture(This->glDescription.target, This->glDescription.textureName);
152 checkGLcall("glBindTexture");
153 IWineD3DSurface_LoadTexture(iface);
154 } else if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
155 /* assume this is a coding error not a real error for now */
156 FIXME("Mipmap surface has a glTexture bound to it!\n");
159 if (This->resource.pool == WINED3DPOOL_DEFAULT) {
160 /* Tell opengl to try and keep this texture in video ram (well mostly) */
163 glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
165 /* TODO: disable texture support, if it wastn't enabled when we entered. */
166 #if 0 /* TODO: context manager support */
167 IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
168 /* we don't care when the state is disabled(if atall) */);
175 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
176 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
177 return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
180 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
181 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
182 return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
185 /* ******************************************************
186 IWineD3DSurface IWineD3DSurface parts follow
187 ****************************************************** */
189 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
190 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
192 TRACE("(%p) : ppContainerParent %p)\n", This, ppContainerParent);
194 if (!ppContainerParent) {
195 ERR("(%p) : Called without a valid ppContainerParent.\n", This);
198 if (This->container) {
199 IWineD3DBase_GetParent(This->container, ppContainerParent);
200 if (!ppContainerParent) {
201 /* WineD3D objects should always have a parent */
202 ERR("(%p) : GetParent returned NULL\n", This);
204 IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */
206 *ppContainerParent = NULL;
212 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
213 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
214 IWineD3DBase *container = 0;
216 TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
219 ERR("Called without a valid ppContainer.\n");
223 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
224 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
225 * GetContainer will return the Direct3D device used to create the surface.
227 if (This->container) {
228 container = This->container;
230 container = (IWineD3DBase *)This->resource.wineD3DDevice;
233 TRACE("Relaying to QueryInterface\n");
234 if (IUnknown_QueryInterface(container, riid, ppContainer) != S_OK)
235 return WINED3DERR_INVALIDCALL;
240 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
241 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
243 TRACE("(%p) : copying into %p\n", This, pDesc);
244 if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format;
245 if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType;
246 if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage;
247 if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool;
248 if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */
249 if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
250 if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
251 if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width;
252 if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height;
256 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
257 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
258 TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
259 if (This->glDescription.textureName == 0 && textureName != 0) {
260 This->Flags |= SFLAG_DIRTY;
261 IWineD3DSurface_AddDirtyRect(iface, NULL);
263 This->glDescription.textureName = textureName;
264 This->glDescription.target = target;
267 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
268 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
269 TRACE("(%p) : returning %p\n", This, &This->glDescription);
270 *glDescription = &This->glDescription;
273 /* TODO: think about moving this down to resource? */
274 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
275 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
276 /* This should only be called for sysmem textures, it may be a good idea to extend this to all pools at some point in the futture */
277 if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
278 FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
280 return (CONST void*)(This->resource.allocatedMemory);
283 HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
284 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
285 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
286 IWineD3DSwapChainImpl *swapchain = NULL;
287 static UINT messages = 0; /* holds flags to disable fixme messages */
289 /* fixme: should we really lock as such? */
290 if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INPBUFFER)) ==
291 (SFLAG_INTEXTURE | SFLAG_INPBUFFER) ) {
292 FIXME("Warning: Surface is in texture memory or pbuffer\n");
293 This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INPBUFFER);
296 if (!(This->Flags & SFLAG_LOCKABLE)) {
297 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
298 texture regions, and since the destination is an unlockable region we need
300 TRACE("Warning: trying to lock unlockable surf@%p\n", This);
301 /*return WINED3DERR_INVALIDCALL; */
304 if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
305 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
307 if (swapchain != NULL || iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
308 if (swapchain != NULL && iface == swapchain->backBuffer) {
309 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
310 } else if (swapchain != NULL && iface == swapchain->frontBuffer) {
311 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
312 } else if (iface == myDevice->renderTarget) {
313 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
314 } else if (iface == myDevice->depthStencilBuffer) {
315 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
318 if (NULL != swapchain) {
319 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
324 TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
327 pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
330 pLockedRect->pBits = This->resource.allocatedMemory;
331 This->lockedRect.left = 0;
332 This->lockedRect.top = 0;
333 This->lockedRect.right = This->currentDesc.Width;
334 This->lockedRect.bottom = This->currentDesc.Height;
335 TRACE("Locked Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", &This->lockedRect, This->lockedRect.left, This->lockedRect.top, This->lockedRect.right, This->lockedRect.bottom);
337 TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
339 if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
340 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
342 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
344 This->lockedRect.left = pRect->left;
345 This->lockedRect.top = pRect->top;
346 This->lockedRect.right = pRect->right;
347 This->lockedRect.bottom = pRect->bottom;
350 if (This->Flags & SFLAG_NONPOW2) {
351 TRACE("Locking non-power 2 texture\n");
354 if (0 == This->resource.usage || This->resource.usage & WINED3DUSAGE_DYNAMIC) {
355 /* classic surface TODO: non 2d surfaces?
356 These resources may be POOL_SYSTEMMEM, so they must not access the device */
357 TRACE("locking an ordinarary surface\n");
358 /* Check to see if memory has already been allocated from the surface*/
359 if ((NULL == This->resource.allocatedMemory) ||
360 (This->Flags & SFLAG_NEWDC) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
361 /* Non-system memory surfaces */
363 /*Surface has no memory currently allocated to it!*/
364 TRACE("(%p) Locking rect\n" , This);
365 if(!This->resource.allocatedMemory) {
366 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
368 if (0 != This->glDescription.textureName) {
369 /* Now I have to copy thing bits back */
370 This->Flags |= SFLAG_ACTIVELOCK; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
371 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
374 /* Make sure that the texture is loaded */
375 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
377 TRACE("(%p) glGetTexImage level(%d), fmt(%d), typ(%d), mem(%p)\n" , This, This->glDescription.level, This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
379 if (This->resource.format == WINED3DFMT_DXT1 ||
380 This->resource.format == WINED3DFMT_DXT2 ||
381 This->resource.format == WINED3DFMT_DXT3 ||
382 This->resource.format == WINED3DFMT_DXT4 ||
383 This->resource.format == WINED3DFMT_DXT5) {
384 TRACE("Locking a compressed texture\n");
385 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
386 GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
387 This->glDescription.level,
388 This->resource.allocatedMemory);
391 FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
394 glGetTexImage(This->glDescription.target,
395 This->glDescription.level,
396 This->glDescription.glFormat,
397 This->glDescription.glType,
398 This->resource.allocatedMemory);
399 vcheckGLcall("glGetTexImage");
400 if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
401 /* some games (e.g. warhammer 40k) don't work with the odd pitchs properly, preventing
402 the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
403 repack the texture so that the bpp * width pitch can be used instead of the bpp * pow2width.
407 instead of boxing the texture :
408 |<-texture width ->| -->pow2width| /\
409 |111111111111111111| | |
410 |222 Texture 222222| boxed empty | texture height
411 |3333 Data 33333333| | |
412 |444444444444444444| | \/
413 ----------------------------------- |
414 | boxed empty | boxed empty | pow2height
416 -----------------------------------
419 were repacking the data to the expected texture width
421 |<-texture width ->| -->pow2width| /\
422 |111111111111111111222222222222222| |
423 |222333333333333333333444444444444| texture height
429 -----------------------------------
433 |<-texture width ->| /\
435 |222222222222222222|texture height
437 |444444444444444444| \/
440 this also means that any references to allocatedMemory should work with the data as if were a standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
442 internally the texture is still stored in a boxed format so any references to textureName will get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
444 if (This->Flags & SFLAG_NONPOW2) {
446 int pitcha = 0, pitchb = 0;
448 pitcha = This->bytesPerPixel * This->currentDesc.Width;
449 pitchb = This->bytesPerPixel * This->pow2Width;
450 datab = dataa = This->resource.allocatedMemory;
451 FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, pitcha, pitchb);
452 for (y = 1 ; y < This->currentDesc.Height; y++) {
453 dataa += pitcha; /* skip the first row */
455 memcpy(dataa, datab, pitcha);
462 } else { /* Nothing to do */
463 TRACE("Memory %p already allocted for texture\n", This->resource.allocatedMemory);
467 pLockedRect->pBits = This->resource.allocatedMemory;
469 if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
470 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
472 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
476 } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage && !(Flags&WINED3DLOCK_DISCARD)) { /* render surfaces */
480 BOOL notInContext = FALSE;
481 IWineD3DSwapChainImpl *targetSwapChain = NULL;
487 * for render->surface copy begin to begin of allocatedMemory
488 * unlock can be more easy
491 TRACE("locking a render target\n");
493 if (This->resource.allocatedMemory == NULL)
494 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
496 This->Flags |= SFLAG_ACTIVELOCK; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
497 pLockedRect->pBits = This->resource.allocatedMemory;
500 vcheckGLcall("glFlush");
501 glGetIntegerv(GL_READ_BUFFER, &prev_read);
502 vcheckGLcall("glIntegerv");
503 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
504 vcheckGLcall("glIntegerv");
506 /* Here's what we have to do:
507 See if the swapchain has the same context as the renderTarget or the surface is the render target.
508 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
509 and use the front back buffer as required.
510 if not, we need to switch contexts and then switchback at the end.
512 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
513 IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
515 /* NOTE: In a shared context environment the renderTarget will use the same context as the implicit swapchain (we're not in a shared environment yet! */
516 if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
517 if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
518 TRACE("locking back buffer\n");
519 glReadBuffer(GL_BACK);
520 } else if (iface == swapchain->frontBuffer) {
521 TRACE("locking front\n");
522 glReadBuffer(GL_FRONT);
523 } else if (iface == myDevice->depthStencilBuffer) {
524 FIXME("Stencil Buffer lock unsupported for now\n");
526 FIXME("(%p) Shouldn't have got here!\n", This);
527 glReadBuffer(GL_BACK);
529 } else if (swapchain != NULL) {
530 IWineD3DSwapChainImpl *implSwapChain;
531 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
532 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
533 /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
534 if (iface == swapchain->backBuffer) {
535 glReadBuffer(GL_BACK);
536 } else if (iface == swapchain->frontBuffer) {
537 glReadBuffer(GL_FRONT);
538 } else if (iface == myDevice->depthStencilBuffer) {
539 FIXME("Stencil Buffer lock unsupported for now\n");
541 FIXME("Should have got here!\n");
542 glReadBuffer(GL_BACK);
545 /* We need to switch contexts to be able to read the buffer!!! */
546 FIXME("The buffer requested isn't in the current openGL context\n");
548 /* TODO: check the contexts, to see if were shared with the current context */
550 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
552 if (swapchain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
553 if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
556 /** the depth stencil in openGL has a format of GL_FLOAT
557 * which should be good for WINED3DFMT_D16_LOCKABLE
559 * it is unclear what format the stencil buffer is in except.
560 * 'Each index is converted to fixed point...
561 * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
562 * mappings in the table GL_PIXEL_MAP_S_TO_S.
563 * glReadPixels(This->lockedRect.left,
564 * This->lockedRect.bottom - j - 1,
565 * This->lockedRect.right - This->lockedRect.left,
567 * GL_DEPTH_COMPONENT,
569 * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
570 *****************************************/
571 if (!notInContext) { /* Only read the buffer if it's in the current context */
574 /* Bizarly it takes 120 millseconds to get an 800x600 region a line at a time, but only 10 to get the whole lot every time,
575 * This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
576 * run ten times faster!
577 * ************************************/
578 BOOL ati_performance_hack = FALSE;
579 ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
581 if ((This->lockedRect.left == 0 && This->lockedRect.top == 0 &&
582 This->lockedRect.right == This->currentDesc.Width
583 && This->lockedRect.bottom == This->currentDesc.Height)) {
585 This->currentDesc.Width,
586 This->currentDesc.Height,
587 This->glDescription.glFormat,
588 This->glDescription.glType,
589 (char *)pLockedRect->pBits);
590 } else if (This->lockedRect.left == 0 && This->lockedRect.right == This->currentDesc.Width) {
592 This->lockedRect.top,
593 This->currentDesc.Width,
594 This->currentDesc.Height,
595 This->glDescription.glFormat,
596 This->glDescription.glType,
597 (char *)pLockedRect->pBits);
600 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
601 glReadPixels(This->lockedRect.left,
602 This->lockedRect.bottom - j - 1,
603 This->lockedRect.right - This->lockedRect.left,
605 This->glDescription.glFormat,
606 This->glDescription.glType,
607 (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
611 vcheckGLcall("glReadPixels");
612 TRACE("Resetting buffer\n");
613 glReadBuffer(prev_read);
614 vcheckGLcall("glReadBuffer");
618 } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
621 FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
624 glReadPixels(This->lockedRect.left,
625 This->lockedRect.bottom - j - 1,
626 This->lockedRect.right - This->lockedRect.left,
628 GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
635 FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
638 if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
641 IWineD3DBaseTexture *pBaseTexture;
644 * as seen in msdn docs
646 IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
648 /** Dirtify Container if needed */
649 if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
650 TRACE("Making container dirty\n");
651 IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
652 IWineD3DBaseTexture_Release(pBaseTexture);
654 TRACE("Surface is standalone, no need to dirty the container\n");
658 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Flags & SFLAG_DIRTY ? 0 : 1);
660 This->Flags |= SFLAG_LOCKED;
664 HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
666 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
667 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
668 const char *buffername = "";
669 IWineD3DSwapChainImpl *swapchain = NULL;
671 if (!(This->Flags & SFLAG_LOCKED)) {
672 WARN("trying to Unlock an unlocked surf@%p\n", This);
673 return WINED3DERR_INVALIDCALL;
676 if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
677 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
679 if ((swapchain != NULL) && iface == swapchain->backBuffer) {
680 buffername = "backBuffer";
681 } else if ((swapchain != NULL) && iface == swapchain->frontBuffer) {
682 buffername = "frontBuffer";
683 } else if (iface == myDevice->depthStencilBuffer) {
684 buffername = "depthStencilBuffer";
685 } else if (iface == myDevice->renderTarget) {
686 buffername = "renderTarget";
690 if (swapchain != NULL) {
691 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
694 TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Flags & SFLAG_DIRTY ? 1 : 0);
696 if (!(This->Flags & SFLAG_DIRTY)) {
697 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
701 if (0 == This->resource.usage) { /* classic surface */
704 * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
706 } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
708 /****************************
709 * TODO: Render targets are 'special' and
710 * ?some? locking needs to be passed onto the context manager
711 * so that it becomes possible to use auxiliary buffers, pbuffers
712 * render-to-texture, shared, cached contexts etc...
713 * ****************************/
714 IWineD3DSwapChainImpl *implSwapChain;
715 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
717 if (iface == implSwapChain->backBuffer || iface == implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
720 GLint prev_rasterpos[4];
722 /* Some drivers(radeon dri, others?) don't like exceptions during
723 * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
724 * after ReleaseDC. Reading it will cause an exception, which x11drv will
725 * catch to put the dib section in InSync mode, which leads to a crash
726 * and a blocked x server on my radeon card.
728 * The following lines read the dib section so it is put in inSync mode
729 * before glDrawPixels is called and the crash is prevented. There won't
730 * be any interfering gdi accesses, because UnlockRect is called from
731 * ReleaseDC, and the app won't use the dc any more afterwards.
733 if(This->Flags & SFLAG_DIBSECTION) {
735 read = This->resource.allocatedMemory[0];
741 vcheckGLcall("glFlush");
742 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
743 vcheckGLcall("glIntegerv");
744 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
745 vcheckGLcall("glIntegerv");
746 glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
747 vcheckGLcall("glIntegerv");
748 glPixelZoom(1.0, -1.0);
749 vcheckGLcall("glPixelZoom");
751 /* glDrawPixels transforms the raster position as though it was a vertex -
752 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
753 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
754 if ( (!myDevice->last_was_rhw) || (myDevice->viewport_changed) ) {
756 double X, Y, height, width, minZ, maxZ;
757 myDevice->last_was_rhw = TRUE;
758 myDevice->viewport_changed = FALSE;
760 /* Transformed already into viewport coordinates, so we do not need transform
761 matrices. Reset all matrices to identity and leave the default matrix in world
763 glMatrixMode(GL_MODELVIEW);
764 checkGLcall("glMatrixMode");
766 checkGLcall("glLoadIdentity");
768 glMatrixMode(GL_PROJECTION);
769 checkGLcall("glMatrixMode");
771 checkGLcall("glLoadIdentity");
773 /* Set up the viewport to be full viewport */
774 X = myDevice->stateBlock->viewport.X;
775 Y = myDevice->stateBlock->viewport.Y;
776 height = myDevice->stateBlock->viewport.Height;
777 width = myDevice->stateBlock->viewport.Width;
778 minZ = myDevice->stateBlock->viewport.MinZ;
779 maxZ = myDevice->stateBlock->viewport.MaxZ;
780 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
781 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
782 checkGLcall("glOrtho");
784 /* Window Coord 0 is the middle of the first pixel, so translate by half
785 a pixel (See comment above glTranslate below) */
786 glTranslatef(0.5, 0.5, 0);
787 checkGLcall("glTranslatef(0.5, 0.5, 0)");
790 if (iface == implSwapChain->backBuffer || iface == myDevice->renderTarget) {
791 glDrawBuffer(GL_BACK);
792 } else if (iface == implSwapChain->frontBuffer) {
793 glDrawBuffer(GL_FRONT);
796 vcheckGLcall("glDrawBuffer");
798 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
799 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
800 glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
802 /* And back buffers are not blended */
805 glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
806 vcheckGLcall("glRasterPos2f");
807 switch (This->resource.format) {
808 case WINED3DFMT_X4R4G4B4:
811 unsigned short *data;
812 data = (unsigned short *)This->resource.allocatedMemory;
813 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
820 case WINED3DFMT_A4R4G4B4:
822 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
823 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, This->resource.allocatedMemory);
824 vcheckGLcall("glDrawPixels");
827 case WINED3DFMT_R5G6B5:
829 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
830 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
831 vcheckGLcall("glDrawPixels");
834 case WINED3DFMT_X1R5G5B5:
837 unsigned short *data;
838 data = (unsigned short *)This->resource.allocatedMemory;
839 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
846 case WINED3DFMT_A1R5G5B5:
848 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
849 GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, This->resource.allocatedMemory);
850 vcheckGLcall("glDrawPixels");
853 case WINED3DFMT_R8G8B8:
855 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
856 GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
857 vcheckGLcall("glDrawPixels");
860 case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it
861 could be any random value this fixes the intro move in Pirates! */
865 data = (unsigned int *)This->resource.allocatedMemory;
866 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
873 case WINED3DFMT_A8R8G8B8:
875 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
876 vcheckGLcall("glPixelStorei");
877 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
878 GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
879 vcheckGLcall("glDrawPixels");
880 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
881 vcheckGLcall("glPixelStorei");
884 case WINED3DFMT_A2R10G10B10:
886 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
887 vcheckGLcall("glPixelStorei");
888 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
889 GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, This->resource.allocatedMemory);
890 vcheckGLcall("glDrawPixels");
891 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
892 vcheckGLcall("glPixelStorei");
896 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
899 glPixelZoom(1.0,1.0);
900 vcheckGLcall("glPixelZoom");
901 glDrawBuffer(prev_draw);
902 vcheckGLcall("glDrawBuffer");
903 glRasterPos3iv(&prev_rasterpos[0]);
904 vcheckGLcall("glRasterPos3iv");
906 /* Reset to previous pack row length / blending state */
907 glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
908 if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
912 /** restore clean dirty state */
913 IWineD3DSurface_CleanDirtyRect(iface);
916 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
918 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
920 } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
922 if (iface == myDevice->depthStencilBuffer) {
923 FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
925 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
929 FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
933 This->Flags &= ~SFLAG_LOCKED;
934 memset(&This->lockedRect, 0, sizeof(RECT));
938 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
939 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
940 WINED3DLOCKED_RECT lock;
947 TRACE("(%p)->(%p)\n",This,pHDC);
949 /* Give more detailed info for ddraw */
950 if (This->Flags & SFLAG_DCINUSE)
951 return DDERR_DCALREADYCREATED;
953 /* Can't GetDC if the surface is locked */
954 if (This->Flags & SFLAG_LOCKED)
955 return WINED3DERR_INVALIDCALL;
957 memset(&lock, 0, sizeof(lock)); /* To be sure */
959 /* Create a DIB section if there isn't a hdc yet */
964 if(This->Flags & SFLAG_ACTIVELOCK)
966 ERR("Creating a DIB section while a lock is active. Uncertain consequences\n");
969 switch (This->bytesPerPixel)
973 /* Allocate extra space to store the RGB bit masks. */
974 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
978 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
982 /* Allocate extra space for a palette. */
983 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
984 sizeof(BITMAPINFOHEADER)
986 * (1 << (This->bytesPerPixel * 8)));
990 b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
991 b_info->bmiHeader.biWidth = This->pow2Width;
992 b_info->bmiHeader.biHeight = -This->pow2Height;
993 b_info->bmiHeader.biPlanes = 1;
994 b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
996 b_info->bmiHeader.biSizeImage = This->resource.size;
998 b_info->bmiHeader.biXPelsPerMeter = 0;
999 b_info->bmiHeader.biYPelsPerMeter = 0;
1000 b_info->bmiHeader.biClrUsed = 0;
1001 b_info->bmiHeader.biClrImportant = 0;
1003 /* Get the bit masks */
1004 masks = (DWORD *) &(b_info->bmiColors);
1005 switch (This->resource.format)
1007 case WINED3DFMT_R8G8B8:
1008 usage = DIB_RGB_COLORS;
1009 b_info->bmiHeader.biCompression = BI_RGB;
1012 case WINED3DFMT_X1R5G5B5:
1013 case WINED3DFMT_A1R5G5B5:
1014 case WINED3DFMT_A4R4G4B4:
1015 case WINED3DFMT_X4R4G4B4:
1016 case WINED3DFMT_R3G3B2:
1017 case WINED3DFMT_A8R3G3B2:
1018 case WINED3DFMT_A2B10G10R10:
1019 case WINED3DFMT_A8B8G8R8:
1020 case WINED3DFMT_X8B8G8R8:
1021 case WINED3DFMT_A2R10G10B10:
1022 case WINED3DFMT_R5G6B5:
1023 case WINED3DFMT_A16B16G16R16:
1025 b_info->bmiHeader.biCompression = BI_BITFIELDS;
1026 masks[0] = get_bitmask_red(This->resource.format);
1027 masks[1] = get_bitmask_green(This->resource.format);
1028 masks[2] = get_bitmask_blue(This->resource.format);
1032 /* Don't know palette */
1033 b_info->bmiHeader.biCompression = BI_RGB;
1038 ddc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1041 HeapFree(GetProcessHeap(), 0, b_info);
1042 return HRESULT_FROM_WIN32(GetLastError());
1045 TRACE("Creating a DIB section with size %ldx%ldx%d, size=%ld\n", b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
1046 This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
1049 if (!This->dib.DIBsection)
1051 ERR("CreateDIBSection failed!\n");
1052 return HRESULT_FROM_WIN32(GetLastError());
1054 HeapFree(GetProcessHeap(), 0, b_info);
1056 TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
1058 /* copy the existing surface to the dib section */
1059 if(This->resource.allocatedMemory)
1061 memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->resource.size);
1062 /* We won't need that any more */
1063 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1066 /* Use the dib section from now on */
1067 This->resource.allocatedMemory = This->dib.bitmap_data;
1069 /* Now allocate a HDC */
1070 This->hDC = CreateCompatibleDC(0);
1071 This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
1072 TRACE("using wined3d palette %p\n", This->palette);
1073 SelectPalette(This->hDC,
1074 This->palette ? This->palette->hpal : 0,
1077 if(This->resource.format == WINED3DFMT_P8 ||
1078 This->resource.format == WINED3DFMT_A8P8)
1083 PALETTEENTRY ent[256];
1085 GetPaletteEntries(This->palette->hpal, 0, 256, ent);
1086 for (n=0; n<256; n++)
1088 col[n].rgbRed = ent[n].peRed;
1089 col[n].rgbGreen = ent[n].peGreen;
1090 col[n].rgbBlue = ent[n].peBlue;
1091 col[n].rgbReserved = 0;
1096 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1098 for (n=0; n<256; n++)
1100 col[n].rgbRed = device->palettes[device->currentPalette][n].peRed;
1101 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1102 col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue;
1103 col[n].rgbReserved = 0;
1107 SetDIBColorTable(This->hDC, 0, 256, col);
1110 /* This is to make LockRect read the gl Texture although memory is allocated */
1111 This->Flags |= SFLAG_NEWDC;
1113 This->Flags |= SFLAG_DIBSECTION;
1116 /* Lock the surface */
1117 hr = IWineD3DSurface_LockRect(iface,
1121 This->Flags &= ~SFLAG_NEWDC;
1124 ERR("IWineD3DSurface_LockRect failed with hr = %08lx\n", hr);
1125 /* keep the dib section */
1130 TRACE("returning %p\n",*pHDC);
1131 This->Flags |= SFLAG_DCINUSE;
1136 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1137 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1139 TRACE("(%p)->(%p)\n",This,hDC);
1141 if (!(This->Flags & SFLAG_DCINUSE))
1142 return D3DERR_INVALIDCALL;
1144 /* we locked first, so unlock now */
1145 IWineD3DSurface_UnlockRect(iface);
1147 This->Flags &= ~SFLAG_DCINUSE;
1152 /* ******************************************************
1153 IWineD3DSurface Internal (No mapping to directx api) parts follow
1154 ****************************************************** */
1155 HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1156 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1158 if (This->Flags & SFLAG_INTEXTURE) {
1159 TRACE("Surface already in texture\n");
1162 if (!(This->Flags & SFLAG_DIRTY)) {
1163 TRACE("surface isn't dirty\n");
1167 This->Flags &= ~SFLAG_DIRTY;
1169 /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1170 * These resources are not bound by device size or format restrictions. Because of this,
1171 * these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1172 * However, these resources can always be created, locked, and copied.
1173 * In general never store scratch or system mem textures in the video ram. However it is allowed
1174 * for system memory textures when WINED3DDEVCAPS_TEXTURESYSTEMMEMORY is set but it isn't right now.
1176 if (This->resource.pool == WINED3DPOOL_SCRATCH || This->resource.pool == WINED3DPOOL_SYSTEMMEM)
1178 FIXME("(%p) Operation not supported for scratch or SYSTEMMEM textures\n",This);
1179 return WINED3DERR_INVALIDCALL;
1182 if (This->Flags & SFLAG_INPBUFFER) {
1185 if (This->glDescription.level != 0)
1186 FIXME("Surface in texture is only supported for level 0\n");
1187 else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1188 This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1189 This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1190 This->resource.format == WINED3DFMT_DXT5)
1191 FIXME("Format %d not supported\n", This->resource.format);
1194 glGetIntegerv(GL_READ_BUFFER, &prevRead);
1195 vcheckGLcall("glGetIntegerv");
1196 glReadBuffer(GL_BACK);
1197 vcheckGLcall("glReadBuffer");
1199 glCopyTexImage2D(This->glDescription.target,
1200 This->glDescription.level,
1201 This->glDescription.glFormatInternal,
1204 This->currentDesc.Width,
1205 This->currentDesc.Height,
1208 checkGLcall("glCopyTexImage2D");
1209 glReadBuffer(prevRead);
1210 vcheckGLcall("glReadBuffer");
1211 TRACE("Updating target %d\n", This->glDescription.target);
1212 This->Flags |= SFLAG_INTEXTURE;
1218 if ((This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) &&
1219 !GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
1221 * wanted a paletted texture and not really support it in HW
1222 * so software emulation code begin
1225 PALETTEENTRY* pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
1226 VOID* surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->currentDesc.Width * This->currentDesc.Height * sizeof(DWORD));
1227 BYTE* dst = (BYTE*) surface;
1228 BYTE* src = (BYTE*) This->resource.allocatedMemory;
1230 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1231 BYTE color = *src++;
1232 *dst++ = pal[color].peRed;
1233 *dst++ = pal[color].peGreen;
1234 *dst++ = pal[color].peBlue;
1235 if (This->resource.format == WINED3DFMT_A8P8)
1236 *dst++ = pal[color].peFlags;
1243 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1244 This->glDescription.target,
1245 This->glDescription.level,
1247 This->currentDesc.Width,
1248 This->currentDesc.Height,
1253 glTexImage2D(This->glDescription.target,
1254 This->glDescription.level,
1256 This->currentDesc.Width,
1257 This->currentDesc.Height,
1262 checkGLcall("glTexImage2D");
1263 HeapFree(GetProcessHeap(), 0, surface);
1270 /* TODO: Compressed non-power 2 support */
1272 if (This->resource.format == WINED3DFMT_DXT1 ||
1273 This->resource.format == WINED3DFMT_DXT2 ||
1274 This->resource.format == WINED3DFMT_DXT3 ||
1275 This->resource.format == WINED3DFMT_DXT4 ||
1276 This->resource.format == WINED3DFMT_DXT5) {
1277 if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1278 FIXME("Using DXT1/3/5 without advertized support\n");
1279 } else if (This->resource.allocatedMemory) {
1280 TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
1281 This->glDescription.target,
1282 This->glDescription.level,
1283 This->glDescription.glFormatInternal,
1284 This->currentDesc.Width,
1285 This->currentDesc.Height,
1287 This->resource.size,
1288 This->resource.allocatedMemory);
1292 GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
1293 This->glDescription.level,
1294 This->glDescription.glFormatInternal,
1295 This->currentDesc.Width,
1296 This->currentDesc.Height,
1298 This->resource.size,
1299 This->resource.allocatedMemory);
1300 checkGLcall("glCommpressedTexImage2D");
1304 if(!(This->Flags & SFLAG_DONOTFREE)){
1305 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1306 This->resource.allocatedMemory = NULL;
1311 /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
1312 if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2)) {
1315 TRACE("non power of two support\n");
1317 TRACE("(%p) Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n", This,
1318 This->glDescription.target,
1319 This->glDescription.level,
1320 debug_d3dformat(This->resource.format),
1321 This->glDescription.glFormatInternal,
1325 This->glDescription.glFormat,
1326 This->glDescription.glType,
1329 glTexImage2D(This->glDescription.target,
1330 This->glDescription.level,
1331 This->glDescription.glFormatInternal,
1335 This->glDescription.glFormat,
1336 This->glDescription.glType,
1339 checkGLcall("glTexImage2D");
1340 if (This->resource.allocatedMemory != NULL) {
1341 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
1342 /* And map the non-power two data into the top left corner */
1344 This->glDescription.target,
1345 This->glDescription.level,
1348 This->currentDesc.Width,
1349 This->currentDesc.Height,
1350 This->glDescription.glFormat,
1351 This->glDescription.glType,
1352 This->resource.allocatedMemory
1354 checkGLcall("glTexSubImage2D");
1360 TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1361 This->glDescription.target,
1362 This->glDescription.level,
1363 debug_d3dformat(This->resource.format),
1364 This->glDescription.glFormatInternal,
1368 This->glDescription.glFormat,
1369 This->glDescription.glType,
1370 This->resource.allocatedMemory);
1373 glTexImage2D(This->glDescription.target,
1374 This->glDescription.level,
1375 This->glDescription.glFormatInternal,
1379 This->glDescription.glFormat,
1380 This->glDescription.glType,
1381 This->resource.allocatedMemory);
1382 checkGLcall("glTexImage2D");
1388 static unsigned int gen = 0;
1391 if ((gen % 10) == 0) {
1392 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1393 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1396 * debugging crash code
1404 if(!(This->Flags & SFLAG_DONOTFREE)){
1405 HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1406 This->resource.allocatedMemory = NULL;
1416 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1419 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1420 char *allocatedMemory;
1422 IWineD3DSwapChain *swapChain = NULL;
1427 Textures my not be stored in ->allocatedgMemory and a GlTexture
1428 so we should lock the surface before saving a snapshot, or at least check that
1430 /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1431 by calling GetTexImage and in compressed form by calling
1432 GetCompressedTexImageARB. Queried compressed images can be saved and
1433 later reused by calling CompressedTexImage[123]DARB. Pre-compressed
1434 texture images do not need to be processed by the GL and should
1435 significantly improve texture loading performance relative to uncompressed
1438 /* Setup the width and height to be the internal texture width and height. */
1439 width = This->pow2Width;
1440 height = This->pow2Height;
1441 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1442 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1444 if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1445 /* we don't want to interfere with the back buffer so read the data into a temporary texture and then save the data out of the temporary texture */
1448 FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1449 glEnable(GL_TEXTURE_2D);
1451 glGenTextures(1, &tmpTexture);
1452 glBindTexture(GL_TEXTURE_2D, tmpTexture);
1454 glTexImage2D(GL_TEXTURE_2D,
1461 GL_UNSIGNED_INT_8_8_8_8_REV,
1464 glGetIntegerv(GL_READ_BUFFER, &prevRead);
1465 vcheckGLcall("glGetIntegerv");
1466 glReadBuffer(GL_BACK);
1467 vcheckGLcall("glReadBuffer");
1468 glCopyTexImage2D(GL_TEXTURE_2D,
1477 checkGLcall("glCopyTexImage2D");
1478 glReadBuffer(prevRead);
1481 } else { /* bind the real texture */
1482 IWineD3DSurface_PreLoad(iface);
1484 allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4);
1486 FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1487 glGetTexImage(GL_TEXTURE_2D,
1488 This->glDescription.level,
1490 GL_UNSIGNED_INT_8_8_8_8_REV,
1492 checkGLcall("glTexImage2D");
1494 glBindTexture(GL_TEXTURE_2D, 0);
1495 glDeleteTextures(1, &tmpTexture);
1499 f = fopen(filename, "w+");
1501 ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1502 return WINED3DERR_INVALIDCALL;
1504 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1505 TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
1520 fwrite(&width,2,1,f);
1522 fwrite(&height,2,1,f);
1527 /* if the data is upside down if we've fetched it from a back buffer, so it needs flipping again to make it the correct way up*/
1529 textureRow = allocatedMemory + (width * (height - 1) *4);
1531 textureRow = allocatedMemory;
1532 for (y = 0 ; y < height; y++) {
1533 for (i = 0; i < width; i++) {
1534 color = *((DWORD*)textureRow);
1535 fputc((color >> 16) & 0xFF, f); /* B */
1536 fputc((color >> 8) & 0xFF, f); /* G */
1537 fputc((color >> 0) & 0xFF, f); /* R */
1538 fputc((color >> 24) & 0xFF, f); /* A */
1541 /* take two rows of the pointer to the texture memory */
1543 (textureRow-= width << 3);
1546 TRACE("Closing file\n");
1550 IWineD3DSwapChain_Release(swapChain);
1552 HeapFree(GetProcessHeap(), 0, allocatedMemory);
1556 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1557 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1558 This->Flags &= ~SFLAG_DIRTY;
1559 This->dirtyRect.left = This->currentDesc.Width;
1560 This->dirtyRect.top = This->currentDesc.Height;
1561 This->dirtyRect.right = 0;
1562 This->dirtyRect.bottom = 0;
1563 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
1564 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1569 * Slightly inefficient way to handle multiple dirty rects but it works :)
1571 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1572 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1573 IWineD3DBaseTexture *baseTexture = NULL;
1574 This->Flags |= SFLAG_DIRTY;
1575 if (NULL != pDirtyRect) {
1576 This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
1577 This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
1578 This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
1579 This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1581 This->dirtyRect.left = 0;
1582 This->dirtyRect.top = 0;
1583 This->dirtyRect.right = This->currentDesc.Width;
1584 This->dirtyRect.bottom = This->currentDesc.Height;
1586 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
1587 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1588 /* if the container is a basetexture then mark it dirty. */
1589 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
1590 TRACE("Passing to conatiner\n");
1591 IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1592 IWineD3DBaseTexture_Release(baseTexture);
1597 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
1598 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1600 TRACE("This %p, container %p\n", This, container);
1602 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
1604 TRACE("Setting container to %p from %p\n", container, This->container);
1605 This->container = container;
1610 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
1611 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1613 if (This->resource.format != WINED3DFMT_UNKNOWN) {
1614 FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
1615 return WINED3DERR_INVALIDCALL;
1618 TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
1619 if (format == WINED3DFMT_UNKNOWN) {
1620 This->resource.size = 0;
1621 } else if (format == WINED3DFMT_DXT1) {
1622 /* DXT1 is half byte per pixel */
1623 This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4)) >> 1;
1625 } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
1626 format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
1627 This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4));
1629 This->resource.size = (This->pow2Width * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * This->pow2Height;
1633 /* Setup some glformat defaults */
1634 if (format != WINED3DFMT_UNKNOWN) {
1635 This->glDescription.glFormat = D3DFmt2GLFmt(This->resource.wineD3DDevice, format);
1636 This->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This->resource.wineD3DDevice, format);
1637 This->glDescription.glType = D3DFmt2GLType(This->resource.wineD3DDevice, format);
1639 This->glDescription.glFormat = 0;
1640 This->glDescription.glFormatInternal = 0;
1641 This->glDescription.glType = 0;
1644 if (format != WINED3DFMT_UNKNOWN) {
1645 This->bytesPerPixel = D3DFmtGetBpp(This->resource.wineD3DDevice, format);
1646 This->pow2Size = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
1648 This->bytesPerPixel = 0;
1652 This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
1654 This->resource.format = format;
1656 TRACE("(%p) : Size %d, pow2Size %d, bytesPerPixel %d, glFormat %d, glFotmatInternal %d, glType %d\n", This, This->resource.size, This->pow2Size, This->bytesPerPixel, This->glDescription.glFormat, This->glDescription.glFormatInternal, This->glDescription.glType);
1661 /* TODO: replace this function with context management routines */
1662 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL inTexture) {
1663 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1666 This->Flags |= SFLAG_INPBUFFER;
1668 This->Flags &= ~SFLAG_INPBUFFER;
1672 This->Flags |= SFLAG_INTEXTURE;
1674 This->Flags &= ~SFLAG_INTEXTURE;
1680 HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
1681 FIXME("This is unimplemented for now(d3d7 merge)\n");
1682 return WINED3DERR_INVALIDCALL;
1685 HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
1686 FIXME("This is unimplemented for now(d3d7 merge)\n");
1687 return WINED3DERR_INVALIDCALL;
1690 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
1691 FIXME("This is unimplemented for now(d3d7 merge)\n");
1692 return WINED3DERR_INVALIDCALL;
1695 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
1696 FIXME("This is unimplemented for now(d3d7 merge)\n");
1697 return WINED3DERR_INVALIDCALL;
1700 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
1701 FIXME("This is unimplemented for now(d3d7 merge)\n");
1702 return WINED3DERR_INVALIDCALL;
1705 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
1706 FIXME("This is unimplemented for now(d3d7 merge)\n");
1707 return WINED3DERR_INVALIDCALL;
1710 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
1711 FIXME("This is unimplemented for now(d3d7 merge)\n");
1712 return WINED3DERR_INVALIDCALL;
1715 HRESULT WINAPI IWineD3DSurfaceImpl_SetPixelFormat(IWineD3DSurface *iface, WINED3DFORMAT Format, BYTE *Surface, DWORD Size) {
1716 FIXME("This is unimplemented for now(d3d7 merge)\n");
1717 return WINED3DERR_INVALIDCALL;
1720 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
1721 FIXME("This is unimplemented for now(d3d7 merge)\n");
1722 return WINED3DERR_INVALIDCALL;
1725 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
1726 FIXME("This is unimplemented for now(d3d7 merge)\n");
1727 return WINED3DERR_INVALIDCALL;
1730 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
1731 FIXME("This is unimplemented for now(d3d7 merge)\n");
1732 return WINED3DERR_INVALIDCALL;
1735 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
1736 FIXME("This is unimplemented for now(d3d7 merge)\n");
1737 return WINED3DERR_INVALIDCALL;
1740 HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
1741 /* Nothing to do for now */
1745 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
1746 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1748 TRACE("(%p)\n", This);
1750 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
1751 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
1752 ie pitch = (width/4) * bytes per block */
1753 if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
1754 ret = (This->currentDesc.Width >> 2) << 3;
1755 else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
1756 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
1757 ret = (This->currentDesc.Width >> 2) << 4;
1759 if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
1760 /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
1761 ret = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
1763 ret = This->bytesPerPixel * This->pow2Width;
1766 TRACE("(%p) Returning %ld\n", This, ret);
1770 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
1773 IWineD3DSurfaceImpl_QueryInterface,
1774 IWineD3DSurfaceImpl_AddRef,
1775 IWineD3DSurfaceImpl_Release,
1776 /* IWineD3DResource */
1777 IWineD3DSurfaceImpl_GetParent,
1778 IWineD3DSurfaceImpl_GetDevice,
1779 IWineD3DSurfaceImpl_SetPrivateData,
1780 IWineD3DSurfaceImpl_GetPrivateData,
1781 IWineD3DSurfaceImpl_FreePrivateData,
1782 IWineD3DSurfaceImpl_SetPriority,
1783 IWineD3DSurfaceImpl_GetPriority,
1784 IWineD3DSurfaceImpl_PreLoad,
1785 IWineD3DSurfaceImpl_GetType,
1786 /* IWineD3DSurface */
1787 IWineD3DSurfaceImpl_GetContainerParent,
1788 IWineD3DSurfaceImpl_GetContainer,
1789 IWineD3DSurfaceImpl_GetDesc,
1790 IWineD3DSurfaceImpl_LockRect,
1791 IWineD3DSurfaceImpl_UnlockRect,
1792 IWineD3DSurfaceImpl_GetDC,
1793 IWineD3DSurfaceImpl_ReleaseDC,
1794 IWineD3DSurfaceImpl_Flip,
1795 IWineD3DSurfaceImpl_Blt,
1796 IWineD3DSurfaceImpl_GetBltStatus,
1797 IWineD3DSurfaceImpl_GetFlipStatus,
1798 IWineD3DSurfaceImpl_IsLost,
1799 IWineD3DSurfaceImpl_Restore,
1800 IWineD3DSurfaceImpl_BltFast,
1801 IWineD3DSurfaceImpl_SetPixelFormat,
1802 IWineD3DSurfaceImpl_GetPalette,
1803 IWineD3DSurfaceImpl_SetPalette,
1804 IWineD3DSurfaceImpl_RealizePalette,
1805 IWineD3DSurfaceImpl_SetColorKey,
1806 IWineD3DSurfaceImpl_GetPitch,
1808 IWineD3DSurfaceImpl_CleanDirtyRect,
1809 IWineD3DSurfaceImpl_AddDirtyRect,
1810 IWineD3DSurfaceImpl_LoadTexture,
1811 IWineD3DSurfaceImpl_SaveSnapshot,
1812 IWineD3DSurfaceImpl_SetContainer,
1813 IWineD3DSurfaceImpl_SetPBufferState,
1814 IWineD3DSurfaceImpl_SetGlTextureDesc,
1815 IWineD3DSurfaceImpl_GetGlDesc,
1816 IWineD3DSurfaceImpl_GetData,
1817 IWineD3DSurfaceImpl_SetFormat,
1818 IWineD3DSurfaceImpl_PrivateSetup