x11drv: Fix the regression caused by the recent ShowWindow fixes.
[wine] / dlls / wined3d / surface.c
1 /*
2  * IWineD3DSurface Implementation
3  *
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
9  * Copyright 2006 Stefan Dösinger for CodeWeavers
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #include "config.h"
27 #include "wine/port.h"
28 #include "wined3d_private.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
32
33 /* *******************************************
34    IWineD3DSurface IUnknown parts follow
35    ******************************************* */
36 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
37 {
38     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
39     /* Warn ,but be nice about things */
40     TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
41     if (riid == NULL) {
42         ERR("Probably FIXME: Calling query interface with NULL riid\n");
43     }
44     if (IsEqualGUID(riid, &IID_IUnknown)
45         || IsEqualGUID(riid, &IID_IWineD3DBase)
46         || IsEqualGUID(riid, &IID_IWineD3DResource)
47         || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
48         IUnknown_AddRef((IUnknown*)iface);
49         *ppobj = This;
50         return S_OK;
51     }
52     *ppobj = NULL;
53     return E_NOINTERFACE;
54 }
55
56 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
57     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
58     ULONG ref = InterlockedIncrement(&This->resource.ref);
59     TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
60     return ref;
61 }
62
63 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
64     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
65     ULONG ref = InterlockedDecrement(&This->resource.ref);
66     TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
67     if (ref == 0) {
68         IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
69         TRACE("(%p) : cleaning up\n", This);
70         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
71             ENTER_GL();
72             TRACE("Deleting texture %d\n", This->glDescription.textureName);
73             glDeleteTextures(1, &This->glDescription.textureName);
74             LEAVE_GL();
75         }
76
77         if(This->Flags & SFLAG_DIBSECTION) {
78             /* Release the DC */
79             SelectObject(This->hDC, This->dib.holdbitmap);
80             DeleteDC(This->hDC);
81             /* Release the DIB section */
82             DeleteObject(This->dib.DIBsection);
83             This->dib.bitmap_data = NULL;
84             This->resource.allocatedMemory = NULL;
85         }
86
87         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
88         if(iface == device->ddraw_primary)
89             device->ddraw_primary = NULL;
90
91         TRACE("(%p) Released\n", This);
92         HeapFree(GetProcessHeap(), 0, This);
93
94     }
95     return ref;
96 }
97
98 /* ****************************************************
99    IWineD3DSurface IWineD3DResource parts follow
100    **************************************************** */
101 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
102     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
103 }
104
105 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
106     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
107 }
108
109 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
110     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
111 }
112
113 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
114     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
115 }
116
117 DWORD   WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
118     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
119 }
120
121 DWORD   WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
122     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
123 }
124
125 void    WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
126     /* TODO: re-write the way textures and managed,
127     *  use a 'opengl context manager' to manage RenderTarget surfaces
128     ** *********************************************************/
129
130     /* TODO: check for locks */
131     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
132     IWineD3DBaseTexture *baseTexture = NULL;
133     TRACE("(%p)Checking to see if the container is a base texture\n", This);
134     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
135         TRACE("Passing to conatiner\n");
136         IWineD3DBaseTexture_PreLoad(baseTexture);
137         IWineD3DBaseTexture_Release(baseTexture);
138     } else {
139     TRACE("(%p) : About to load surface\n", This);
140     ENTER_GL();
141 #if 0 /* TODO: context manager support */
142      IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
143 #endif
144     glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
145     if (This->glDescription.level == 0 &&  This->glDescription.textureName == 0) {
146           glGenTextures(1, &This->glDescription.textureName);
147           checkGLcall("glGenTextures");
148           TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
149           glBindTexture(This->glDescription.target, This->glDescription.textureName);
150           checkGLcall("glBindTexture");
151           IWineD3DSurface_LoadTexture(iface);
152           /* This is where we should be reducing the amount of GLMemoryUsed */
153     } else {
154         if (This->glDescription.level == 0) {
155           glBindTexture(This->glDescription.target, This->glDescription.textureName);
156           checkGLcall("glBindTexture");
157           IWineD3DSurface_LoadTexture(iface);
158         } else  if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
159             /* assume this is a coding error not a real error for now */
160             FIXME("Mipmap surface has a glTexture bound to it!\n");
161         }
162     }
163     if (This->resource.pool == WINED3DPOOL_DEFAULT) {
164        /* Tell opengl to try and keep this texture in video ram (well mostly) */
165        GLclampf tmp;
166        tmp = 0.9f;
167         glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
168     }
169     /* TODO: disable texture support, if it wastn't enabled when we entered. */
170 #if 0 /* TODO: context manager support */
171      IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
172               /* we don't care when the state is disabled(if atall) */);
173 #endif
174     LEAVE_GL();
175     }
176     return;
177 }
178
179 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
180     TRACE("(%p) : calling resourceimpl_GetType\n", iface);
181     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
182 }
183
184 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
185     TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
186     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
187 }
188
189 /* ******************************************************
190    IWineD3DSurface IWineD3DSurface parts follow
191    ****************************************************** */
192
193 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
194     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
195
196     TRACE("(%p) : ppContainerParent %p)\n", This, ppContainerParent);
197
198     if (!ppContainerParent) {
199         ERR("(%p) : Called without a valid ppContainerParent.\n", This);
200     }
201
202     if (This->container) {
203         IWineD3DBase_GetParent(This->container, ppContainerParent);
204         if (!ppContainerParent) {
205             /* WineD3D objects should always have a parent */
206             ERR("(%p) : GetParent returned NULL\n", This);
207         }
208         IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */
209     } else {
210         *ppContainerParent = NULL;
211     }
212
213     return WINED3D_OK;
214 }
215
216 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
217     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
218     IWineD3DBase *container = 0;
219
220     TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
221
222     if (!ppContainer) {
223         ERR("Called without a valid ppContainer.\n");
224     }
225
226     /** From MSDN:
227      * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
228      * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
229      * GetContainer will return the Direct3D device used to create the surface.
230      */
231     if (This->container) {
232         container = This->container;
233     } else {
234         container = (IWineD3DBase *)This->resource.wineD3DDevice;
235     }
236
237     TRACE("Relaying to QueryInterface\n");
238     if (IUnknown_QueryInterface(container, riid, ppContainer) != S_OK)
239         return WINED3DERR_INVALIDCALL;
240
241     return WINED3D_OK;
242 }
243
244 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
245     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
246
247     TRACE("(%p) : copying into %p\n", This, pDesc);
248     if(pDesc->Format != NULL)             *(pDesc->Format) = This->resource.format;
249     if(pDesc->Type != NULL)               *(pDesc->Type)   = This->resource.resourceType;
250     if(pDesc->Usage != NULL)              *(pDesc->Usage)              = This->resource.usage;
251     if(pDesc->Pool != NULL)               *(pDesc->Pool)               = This->resource.pool;
252     if(pDesc->Size != NULL)               *(pDesc->Size)               = This->resource.size;   /* dx8 only */
253     if(pDesc->MultiSampleType != NULL)    *(pDesc->MultiSampleType)    = This->currentDesc.MultiSampleType;
254     if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
255     if(pDesc->Width != NULL)              *(pDesc->Width)              = This->currentDesc.Width;
256     if(pDesc->Height != NULL)             *(pDesc->Height)             = This->currentDesc.Height;
257     return WINED3D_OK;
258 }
259
260 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
261     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
262     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
263     if (This->glDescription.textureName == 0 && textureName != 0) {
264         This->Flags |= SFLAG_DIRTY;
265         IWineD3DSurface_AddDirtyRect(iface, NULL);
266     }
267     This->glDescription.textureName = textureName;
268     This->glDescription.target      = target;
269 }
270
271 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
272     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
273     TRACE("(%p) : returning %p\n", This, &This->glDescription);
274     *glDescription = &This->glDescription;
275 }
276
277 /* TODO: think about moving this down to resource? */
278 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
279     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
280     /* 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  */
281     if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
282         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
283     }
284     return (CONST void*)(This->resource.allocatedMemory);
285 }
286
287 HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
288     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
289     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
290     IWineD3DSwapChainImpl *swapchain = NULL;
291     static UINT messages = 0; /* holds flags to disable fixme messages */
292
293     /* fixme: should we really lock as such? */
294     if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INPBUFFER)) ==
295                       (SFLAG_INTEXTURE | SFLAG_INPBUFFER) ) {
296         FIXME("Warning: Surface is in texture memory or pbuffer\n");
297         This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INPBUFFER);
298     }
299
300     if (!(This->Flags & SFLAG_LOCKABLE)) {
301         /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
302               texture regions, and since the destination is an unlockable region we need
303               to tolerate this                                                           */
304         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
305         /*return WINED3DERR_INVALIDCALL; */
306     }
307
308     if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
309         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
310
311         if (swapchain != NULL ||  iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
312             if (swapchain != NULL && iface ==  swapchain->backBuffer) {
313                 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
314             } else if (swapchain != NULL && iface ==  swapchain->frontBuffer) {
315                 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
316             } else if (iface == myDevice->renderTarget) {
317                 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
318             } else if (iface == myDevice->depthStencilBuffer) {
319                 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
320             }
321
322             if (NULL != swapchain) {
323                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
324             }
325             swapchain = NULL;
326         }
327     } else {
328         TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
329     }
330
331     pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
332
333     if (NULL == pRect) {
334         pLockedRect->pBits = This->resource.allocatedMemory;
335         This->lockedRect.left   = 0;
336         This->lockedRect.top    = 0;
337         This->lockedRect.right  = This->currentDesc.Width;
338         This->lockedRect.bottom = This->currentDesc.Height;
339         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);
340     } else {
341         TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
342
343         if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
344             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
345         } else {
346             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
347         }
348         This->lockedRect.left   = pRect->left;
349         This->lockedRect.top    = pRect->top;
350         This->lockedRect.right  = pRect->right;
351         This->lockedRect.bottom = pRect->bottom;
352     }
353
354     if (This->Flags & SFLAG_NONPOW2) {
355         TRACE("Locking non-power 2 texture\n");
356     }
357
358     if (0 == This->resource.usage || This->resource.usage & WINED3DUSAGE_DYNAMIC) {
359         /* classic surface  TODO: non 2d surfaces?
360         These resources may be POOL_SYSTEMMEM, so they must not access the device */
361         TRACE("locking an ordinarary surface\n");
362         /* Check to see if memory has already been allocated from the surface*/
363         if ((NULL == This->resource.allocatedMemory) ||
364             (This->Flags & SFLAG_NEWDC) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
365             /* Non-system memory surfaces */
366
367             /*Surface has no memory currently allocated to it!*/
368             TRACE("(%p) Locking rect\n" , This);
369             if(!This->resource.allocatedMemory) {
370                 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
371             }
372             if (0 != This->glDescription.textureName) {
373                 /* Now I have to copy thing bits back */
374                 This->Flags |= SFLAG_ACTIVELOCK; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
375                 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
376                 ENTER_GL();
377     
378                 /* Make sure that the texture is loaded */
379                 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
380     
381                 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);
382     
383                 if (This->resource.format == WINED3DFMT_DXT1 ||
384                     This->resource.format == WINED3DFMT_DXT2 ||
385                     This->resource.format == WINED3DFMT_DXT3 ||
386                     This->resource.format == WINED3DFMT_DXT4 ||
387                     This->resource.format == WINED3DFMT_DXT5) {
388                     TRACE("Locking a compressed texture\n");
389                     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
390                         GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
391                                                             This->glDescription.level,
392                                                             This->resource.allocatedMemory);
393     
394                     } else {
395                         FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
396                     }
397                 } else {
398                     glGetTexImage(This->glDescription.target,
399                                 This->glDescription.level,
400                                 This->glDescription.glFormat,
401                                 This->glDescription.glType,
402                                 This->resource.allocatedMemory);
403                     vcheckGLcall("glGetTexImage");
404                     if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
405                         /* some games (e.g. warhammer 40k) don't work with the odd pitchs properly, preventing
406                         the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
407                         repack the texture so that the bpp * width pitch can be used instead of the bpp * pow2width.
408         
409                         Were doing this...
410         
411                         instead of boxing the texture :
412                         |<-texture width ->|  -->pow2width|   /\
413                         |111111111111111111|              |   |
414                         |222 Texture 222222| boxed empty  | texture height
415                         |3333 Data 33333333|              |   |
416                         |444444444444444444|              |   \/
417                         -----------------------------------   |
418                         |     boxed  empty | boxed empty  | pow2height
419                         |                  |              |   \/
420                         -----------------------------------
421         
422         
423                         were repacking the data to the expected texture width
424         
425                         |<-texture width ->|  -->pow2width|   /\
426                         |111111111111111111222222222222222|   |
427                         |222333333333333333333444444444444| texture height
428                         |444444                           |   |
429                         |                                 |   \/
430                         |                                 |   |
431                         |            empty                | pow2height
432                         |                                 |   \/
433                         -----------------------------------
434         
435                         == is the same as
436         
437                         |<-texture width ->|    /\
438                         |111111111111111111|
439                         |222222222222222222|texture height
440                         |333333333333333333|
441                         |444444444444444444|    \/
442                         --------------------
443         
444                         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.
445         
446                         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.
447                         */
448                         if (This->Flags & SFLAG_NONPOW2) {
449                             BYTE* dataa, *datab;
450                             int pitcha = 0, pitchb = 0;
451                             int y;
452                             pitcha = This->bytesPerPixel * This->currentDesc.Width;
453                             pitchb = This->bytesPerPixel * This->pow2Width;
454                             datab = dataa = This->resource.allocatedMemory;
455                             FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, pitcha, pitchb);
456                             for (y = 1 ; y < This->currentDesc.Height; y++) {
457                                 dataa += pitcha; /* skip the first row */
458                                 datab += pitchb;
459                                 memcpy(dataa, datab, pitcha);
460                             }
461                         }
462                     }
463                 }
464                 LEAVE_GL();
465             }
466         } else { /* Nothing to do */
467             TRACE("Memory %p already allocted for texture\n",  This->resource.allocatedMemory);
468         }
469
470         if (NULL == pRect) {
471             pLockedRect->pBits = This->resource.allocatedMemory;
472         }  else{
473             if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
474                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
475             } else {
476                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
477             }
478         }
479
480     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage && !(Flags&WINED3DLOCK_DISCARD)) { /* render surfaces */
481
482         GLint  prev_store;
483         GLint  prev_read;
484         BOOL notInContext = FALSE;
485         IWineD3DSwapChainImpl *targetSwapChain = NULL;
486
487
488         ENTER_GL();
489
490             /**
491              * for render->surface copy begin to begin of allocatedMemory
492              * unlock can be more easy
493              */
494
495         TRACE("locking a render target\n");
496
497         if (This->resource.allocatedMemory == NULL)
498                 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
499
500         This->Flags |= SFLAG_ACTIVELOCK; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
501         pLockedRect->pBits = This->resource.allocatedMemory;
502
503         glFlush();
504         vcheckGLcall("glFlush");
505         glGetIntegerv(GL_READ_BUFFER, &prev_read);
506         vcheckGLcall("glIntegerv");
507         glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
508         vcheckGLcall("glIntegerv");
509
510  /* Here's what we have to do:
511             See if the swapchain has the same context as the renderTarget or the surface is the render target.
512             Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
513             and use the front back buffer as required.
514             if not, we need to switch contexts and then switchback at the end.
515          */
516         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
517         IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
518
519         /* 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! */
520         if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
521                 if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
522                     TRACE("locking back buffer\n");
523                    glReadBuffer(GL_BACK);
524                 } else if (iface == swapchain->frontBuffer) {
525                    TRACE("locking front\n");
526                    glReadBuffer(GL_FRONT);
527                 } else if (iface == myDevice->depthStencilBuffer) {
528                     FIXME("Stencil Buffer lock unsupported for now\n");
529                 } else {
530                    FIXME("(%p) Shouldn't have got here!\n", This);
531                    glReadBuffer(GL_BACK);
532                 }
533         } else if (swapchain != NULL) {
534             IWineD3DSwapChainImpl *implSwapChain;
535             IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
536             if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
537                     /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
538                     if (iface == swapchain->backBuffer) {
539                         glReadBuffer(GL_BACK);
540                     } else if (iface == swapchain->frontBuffer) {
541                         glReadBuffer(GL_FRONT);
542                     } else if (iface == myDevice->depthStencilBuffer) {
543                         FIXME("Stencil Buffer lock unsupported for now\n");
544                     } else {
545                         FIXME("Should have got here!\n");
546                         glReadBuffer(GL_BACK);
547                     }
548             } else {
549                 /* We need to switch contexts to be able to read the buffer!!! */
550                 FIXME("The buffer requested isn't in the current openGL context\n");
551                 notInContext = TRUE;
552                 /* TODO: check the contexts, to see if were shared with the current context */
553             }
554             IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
555         }
556         if (swapchain != NULL)       IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
557         if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
558
559
560         /** the depth stencil in openGL has a format of GL_FLOAT
561         * which should be good for WINED3DFMT_D16_LOCKABLE
562         * and WINED3DFMT_D16
563         * it is unclear what format the stencil buffer is in except.
564         * 'Each index is converted to fixed point...
565         * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
566         * mappings in the table GL_PIXEL_MAP_S_TO_S.
567         * glReadPixels(This->lockedRect.left,
568         *             This->lockedRect.bottom - j - 1,
569         *             This->lockedRect.right - This->lockedRect.left,
570         *             1,
571         *             GL_DEPTH_COMPONENT,
572         *             type,
573         *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
574             *****************************************/
575         if (!notInContext) { /* Only read the buffer if it's in the current context */
576             long j;
577 #if 0
578             /* 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,
579             *  This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
580             *  run ten times faster!
581             * ************************************/
582             BOOL ati_performance_hack = FALSE;
583             ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
584 #endif
585             if ((This->lockedRect.left == 0 &&  This->lockedRect.top == 0 &&
586                 This->lockedRect.right == This->currentDesc.Width
587                 && This->lockedRect.bottom ==  This->currentDesc.Height)) {
588                     glReadPixels(0, 0,
589                     This->currentDesc.Width,
590                     This->currentDesc.Height,
591                     This->glDescription.glFormat,
592                     This->glDescription.glType,
593                     (char *)pLockedRect->pBits);
594             } else if (This->lockedRect.left == 0 &&  This->lockedRect.right == This->currentDesc.Width) {
595                     glReadPixels(0,
596                     This->lockedRect.top,
597                     This->currentDesc.Width,
598                     This->currentDesc.Height,
599                     This->glDescription.glFormat,
600                     This->glDescription.glType,
601                     (char *)pLockedRect->pBits);
602             } else{
603
604                 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
605                     glReadPixels(This->lockedRect.left, 
606                                  This->lockedRect.bottom - j - 1, 
607                                  This->lockedRect.right - This->lockedRect.left, 
608                                  1,
609                                  This->glDescription.glFormat,
610                                  This->glDescription.glType,
611                                  (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
612
613                 }
614             }
615             vcheckGLcall("glReadPixels");
616             TRACE("Resetting buffer\n");
617             glReadBuffer(prev_read);
618             vcheckGLcall("glReadBuffer");
619         }
620         LEAVE_GL();
621
622     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
623
624         if (!messages & 1) {
625             FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
626             /*
627
628             glReadPixels(This->lockedRect.left,
629             This->lockedRect.bottom - j - 1,
630             This->lockedRect.right - This->lockedRect.left,
631             1,
632             GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
633
634             )
635             */
636             messages |= 1;
637         }
638     } else {
639         FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
640     }
641
642     if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
643         /* Don't dirtify */
644     } else {
645         IWineD3DBaseTexture *pBaseTexture;
646         /**
647          * Dirtify on lock
648          * as seen in msdn docs
649          */
650         IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
651
652         /** Dirtify Container if needed */
653         if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
654             TRACE("Making container dirty\n");
655             IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
656             IWineD3DBaseTexture_Release(pBaseTexture);
657         } else {
658             TRACE("Surface is standalone, no need to dirty the container\n");
659         }
660     }
661
662     TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Flags & SFLAG_DIRTY ? 0 : 1);
663
664     This->Flags |= SFLAG_LOCKED;
665     return WINED3D_OK;
666 }
667
668 HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
669     GLint skipBytes = 0;
670     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
671     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
672     const char *buffername = "";
673     IWineD3DSwapChainImpl *swapchain = NULL;
674
675     if (!(This->Flags & SFLAG_LOCKED)) {
676         WARN("trying to Unlock an unlocked surf@%p\n", This);
677         return WINED3DERR_INVALIDCALL;
678     }
679
680     if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
681         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
682
683         if ((swapchain != NULL) &&  iface ==  swapchain->backBuffer) {
684                 buffername = "backBuffer";
685         } else if ((swapchain != NULL) && iface ==  swapchain->frontBuffer) {
686                 buffername = "frontBuffer";
687         } else if (iface == myDevice->depthStencilBuffer) {
688                 buffername = "depthStencilBuffer";
689         } else if (iface == myDevice->renderTarget) {
690                 buffername = "renderTarget";
691         }
692     }
693
694     if (swapchain != NULL) {
695         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
696     }
697
698     TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Flags & SFLAG_DIRTY ? 1 : 0);
699
700     if (!(This->Flags & SFLAG_DIRTY)) {
701         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
702         goto unlock_end;
703     }
704
705     if (0 == This->resource.usage) { /* classic surface */
706         /**
707          * nothing to do
708          * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
709          */
710     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
711
712         /****************************
713         * TODO: Render targets are 'special' and
714         * ?some? locking needs to be passed onto the context manager
715         * so that it becomes possible to use auxiliary buffers, pbuffers
716         * render-to-texture, shared, cached contexts etc...
717         * ****************************/
718         IWineD3DSwapChainImpl *implSwapChain;
719         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
720
721         if (iface ==  implSwapChain->backBuffer || iface ==  implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
722             GLint  prev_store;
723             GLint  prev_draw;
724             GLint  prev_rasterpos[4];
725
726             /* Some drivers(radeon dri, others?) don't like exceptions during
727              * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
728              * after ReleaseDC. Reading it will cause an exception, which x11drv will
729              * catch to put the dib section in InSync mode, which leads to a crash
730              * and a blocked x server on my radeon card.
731              *
732              * The following lines read the dib section so it is put in inSync mode
733              * before glDrawPixels is called and the crash is prevented. There won't
734              * be any interfering gdi accesses, because UnlockRect is called from
735              * ReleaseDC, and the app won't use the dc any more afterwards.
736              */
737             if(This->Flags & SFLAG_DIBSECTION) {
738                 volatile BYTE read;
739                 read = This->resource.allocatedMemory[0];
740             }
741
742             ENTER_GL();
743
744             glFlush();
745             vcheckGLcall("glFlush");
746             glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
747             vcheckGLcall("glIntegerv");
748             glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
749             vcheckGLcall("glIntegerv");
750             glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
751             vcheckGLcall("glIntegerv");
752             glPixelZoom(1.0, -1.0);
753             vcheckGLcall("glPixelZoom");
754
755             /* glDrawPixels transforms the raster position as though it was a vertex -
756                we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
757                per drawprim (and leave set - it will sort itself out due to last_was_rhw */
758             if ( (!myDevice->last_was_rhw) || (myDevice->viewport_changed) ) {
759
760                 double X, Y, height, width, minZ, maxZ;
761                 myDevice->last_was_rhw = TRUE;
762                 myDevice->viewport_changed = FALSE;
763
764                 /* Transformed already into viewport coordinates, so we do not need transform
765                    matrices. Reset all matrices to identity and leave the default matrix in world
766                    mode.                                                                         */
767                 glMatrixMode(GL_MODELVIEW);
768                 checkGLcall("glMatrixMode");
769                 glLoadIdentity();
770                 checkGLcall("glLoadIdentity");
771
772                 glMatrixMode(GL_PROJECTION);
773                 checkGLcall("glMatrixMode");
774                 glLoadIdentity();
775                 checkGLcall("glLoadIdentity");
776
777                 /* Set up the viewport to be full viewport */
778                 X      = myDevice->stateBlock->viewport.X;
779                 Y      = myDevice->stateBlock->viewport.Y;
780                 height = myDevice->stateBlock->viewport.Height;
781                 width  = myDevice->stateBlock->viewport.Width;
782                 minZ   = myDevice->stateBlock->viewport.MinZ;
783                 maxZ   = myDevice->stateBlock->viewport.MaxZ;
784                 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
785                 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
786                 checkGLcall("glOrtho");
787
788                 /* Window Coord 0 is the middle of the first pixel, so translate by half
789                    a pixel (See comment above glTranslate below)                         */
790                 glTranslatef(0.5, 0.5, 0);
791                 checkGLcall("glTranslatef(0.5, 0.5, 0)");
792             }
793
794             if (iface ==  implSwapChain->backBuffer || iface == myDevice->renderTarget) {
795                 glDrawBuffer(GL_BACK);
796             } else if (iface ==  implSwapChain->frontBuffer) {
797                 glDrawBuffer(GL_FRONT);
798             }
799
800             vcheckGLcall("glDrawBuffer");
801
802             /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
803             glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
804             glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
805
806             /* And back buffers are not blended */
807             glDisable(GL_BLEND);
808
809             glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
810             vcheckGLcall("glRasterPos2f");
811             switch (This->resource.format) {
812             case WINED3DFMT_X4R4G4B4:
813                 {
814                     int size;
815                     unsigned short *data;
816                     data = (unsigned short *)This->resource.allocatedMemory;
817                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
818                     while(size > 0) {
819                             *data |= 0xF000;
820                             data++;
821                             size--;
822                     }
823                 }
824             case WINED3DFMT_A4R4G4B4:
825                 {
826                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
827                                  GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, This->resource.allocatedMemory);
828                     vcheckGLcall("glDrawPixels");
829                 }
830                 break;
831             case WINED3DFMT_R5G6B5:
832                 {
833                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
834                                  GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
835                     vcheckGLcall("glDrawPixels");
836                 }
837                 break;
838             case WINED3DFMT_X1R5G5B5:
839                 {
840                     int size;
841                     unsigned short *data;
842                     data = (unsigned short *)This->resource.allocatedMemory;
843                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
844                     while(size > 0) {
845                             *data |= 0x8000;
846                             data++;
847                             size--;
848                     }
849                 }
850             case WINED3DFMT_A1R5G5B5:
851                 {
852                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
853                                  GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, This->resource.allocatedMemory);
854                     vcheckGLcall("glDrawPixels");
855                 }
856                 break;
857             case WINED3DFMT_R8G8B8:
858                 {
859                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
860                                  GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
861                     vcheckGLcall("glDrawPixels");
862                 }
863                 break;
864             case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it 
865                                         could be any random value this fixes the intro move in Pirates! */
866                 {
867                     int size;
868                     unsigned int *data;
869                     data = (unsigned int *)This->resource.allocatedMemory;
870                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
871                     while(size > 0) {
872                             *data |= 0xFF000000;
873                             data++;
874                             size--;
875                     }
876                 }
877             case WINED3DFMT_A8R8G8B8:
878                 {
879                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
880                     vcheckGLcall("glPixelStorei");
881                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
882                                  GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
883                     vcheckGLcall("glDrawPixels");
884                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
885                     vcheckGLcall("glPixelStorei");
886                 }
887                 break;
888             case WINED3DFMT_A2R10G10B10:
889                 {
890                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
891                     vcheckGLcall("glPixelStorei");
892                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
893                                  GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, This->resource.allocatedMemory);
894                     vcheckGLcall("glDrawPixels");
895                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
896                     vcheckGLcall("glPixelStorei");
897                 }
898                 break;
899             default:
900                 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
901             }
902
903             glPixelZoom(1.0,1.0);
904             vcheckGLcall("glPixelZoom");
905             glDrawBuffer(prev_draw);
906             vcheckGLcall("glDrawBuffer");
907             glRasterPos3iv(&prev_rasterpos[0]);
908             vcheckGLcall("glRasterPos3iv");
909
910             /* Reset to previous pack row length / blending state */
911             glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
912             if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
913
914             LEAVE_GL();
915
916             /** restore clean dirty state */
917             IWineD3DSurface_CleanDirtyRect(iface);
918
919         } else {
920             FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
921         }
922         IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
923
924     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
925
926         if (iface == myDevice->depthStencilBuffer) {
927             FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
928         } else {
929             FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
930         }
931
932     } else {
933         FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
934     }
935
936     unlock_end:
937     This->Flags &= ~SFLAG_LOCKED;
938     memset(&This->lockedRect, 0, sizeof(RECT));
939     return WINED3D_OK;
940 }
941
942 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
943     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
944     WINED3DLOCKED_RECT lock;
945     UINT usage;
946     BITMAPINFO* b_info;
947     HDC ddc;
948     DWORD *masks;
949     HRESULT hr;
950     RGBQUAD col[256];
951
952     TRACE("(%p)->(%p)\n",This,pHDC);
953
954     /* Give more detailed info for ddraw */
955     if (This->Flags & SFLAG_DCINUSE)
956         return DDERR_DCALREADYCREATED;
957
958     /* Can't GetDC if the surface is locked */
959     if (This->Flags & SFLAG_LOCKED)
960         return WINED3DERR_INVALIDCALL;
961
962     memset(&lock, 0, sizeof(lock)); /* To be sure */
963
964     /* Create a DIB section if there isn't a hdc yet */
965     if(!This->hDC) {
966         if(This->Flags & SFLAG_ACTIVELOCK) {
967             ERR("Creating a DIB section while a lock is active. Uncertain consequences\n");
968         }
969
970         switch (This->bytesPerPixel) {
971             case 2:
972             case 4:
973                 /* Allocate extra space to store the RGB bit masks. */
974                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
975                 break;
976
977             case 3:
978                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
979                 break;
980
981             default:
982                 /* Allocate extra space for a palette. */
983                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
984                                   sizeof(BITMAPINFOHEADER)
985                                   + sizeof(RGBQUAD)
986                                   * (1 << (This->bytesPerPixel * 8)));
987                 break;
988         }
989
990         b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
991         if( (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
992             b_info->bmiHeader.biWidth = This->currentDesc.Width;
993             b_info->bmiHeader.biHeight = -This->currentDesc.Height;
994             /* Use the full pow2 image size(assigned below) because LockRect
995              * will need it for a full glGetTexImage call
996              */
997         } else {
998             b_info->bmiHeader.biWidth = This->pow2Width;
999             b_info->bmiHeader.biHeight = -This->pow2Height;
1000         }
1001         b_info->bmiHeader.biPlanes = 1;
1002         b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
1003
1004         b_info->bmiHeader.biSizeImage = This->resource.size;
1005
1006         b_info->bmiHeader.biXPelsPerMeter = 0;
1007         b_info->bmiHeader.biYPelsPerMeter = 0;
1008         b_info->bmiHeader.biClrUsed = 0;
1009         b_info->bmiHeader.biClrImportant = 0;
1010
1011         /* Get the bit masks */
1012         masks = (DWORD *) &(b_info->bmiColors);
1013         switch (This->resource.format) {
1014             case WINED3DFMT_R8G8B8:
1015                 usage = DIB_RGB_COLORS;
1016                 b_info->bmiHeader.biCompression = BI_RGB;
1017                 break;
1018
1019             case WINED3DFMT_X1R5G5B5:
1020             case WINED3DFMT_A1R5G5B5:
1021             case WINED3DFMT_A4R4G4B4:
1022             case WINED3DFMT_X4R4G4B4:
1023             case WINED3DFMT_R3G3B2:
1024             case WINED3DFMT_A8R3G3B2:
1025             case WINED3DFMT_A2B10G10R10:
1026             case WINED3DFMT_A8B8G8R8:
1027             case WINED3DFMT_X8B8G8R8:
1028             case WINED3DFMT_A2R10G10B10:
1029             case WINED3DFMT_R5G6B5:
1030             case WINED3DFMT_A16B16G16R16:
1031                 usage = 0;
1032                 b_info->bmiHeader.biCompression = BI_BITFIELDS;
1033                 masks[0] = get_bitmask_red(This->resource.format);
1034                 masks[1] = get_bitmask_green(This->resource.format);
1035                 masks[2] = get_bitmask_blue(This->resource.format);
1036                 break;
1037
1038             default:
1039                 /* Don't know palette */
1040                 b_info->bmiHeader.biCompression = BI_RGB;
1041                 usage = 0;
1042                 break;
1043         }
1044
1045         ddc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1046         if (ddc == 0) {
1047             HeapFree(GetProcessHeap(), 0, b_info);
1048             return HRESULT_FROM_WIN32(GetLastError());
1049         }
1050
1051         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);
1052         This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
1053         DeleteDC(ddc);
1054
1055         if (!This->dib.DIBsection) {
1056             ERR("CreateDIBSection failed!\n");
1057             return HRESULT_FROM_WIN32(GetLastError());
1058         }
1059         HeapFree(GetProcessHeap(), 0, b_info);
1060
1061         TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
1062
1063         /* copy the existing surface to the dib section */
1064         if(This->resource.allocatedMemory) {
1065             memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->resource.size);
1066             /* We won't need that any more */
1067             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1068         }
1069
1070         /* Use the dib section from now on */
1071         This->resource.allocatedMemory = This->dib.bitmap_data;
1072
1073         /* Now allocate a HDC */
1074         This->hDC = CreateCompatibleDC(0);
1075         This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
1076         TRACE("using wined3d palette %p\n", This->palette);
1077         SelectPalette(This->hDC,
1078                       This->palette ? This->palette->hpal : 0,
1079                       FALSE);
1080
1081         /* This is to make LockRect read the gl Texture although memory is allocated */
1082         This->Flags |= SFLAG_NEWDC;
1083
1084         This->Flags |= SFLAG_DIBSECTION;
1085     }
1086
1087     /* Lock the surface */
1088     hr = IWineD3DSurface_LockRect(iface,
1089                                   &lock,
1090                                   NULL,
1091                                   0);
1092     This->Flags &= ~SFLAG_NEWDC;
1093     if(FAILED(hr)) {
1094         ERR("IWineD3DSurface_LockRect failed with hr = %08lx\n", hr);
1095         /* keep the dib section */
1096         return hr;
1097     }
1098
1099     if(This->resource.format == WINED3DFMT_P8 ||
1100         This->resource.format == WINED3DFMT_A8P8) {
1101         unsigned int n;
1102         if(This->palette) {
1103             PALETTEENTRY ent[256];
1104
1105             GetPaletteEntries(This->palette->hpal, 0, 256, ent);
1106             for (n=0; n<256; n++) {
1107                 col[n].rgbRed   = ent[n].peRed;
1108                 col[n].rgbGreen = ent[n].peGreen;
1109                 col[n].rgbBlue  = ent[n].peBlue;
1110                 col[n].rgbReserved = 0;
1111             }
1112         } else {
1113             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1114
1115             for (n=0; n<256; n++) {
1116                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
1117                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1118                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
1119                 col[n].rgbReserved = 0;
1120             }
1121
1122         }
1123         SetDIBColorTable(This->hDC, 0, 256, col);
1124     }
1125
1126     *pHDC = This->hDC;
1127     TRACE("returning %p\n",*pHDC);
1128     This->Flags |= SFLAG_DCINUSE;
1129
1130     return WINED3D_OK;
1131 }
1132
1133 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1134     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1135
1136     TRACE("(%p)->(%p)\n",This,hDC);
1137
1138     if (!(This->Flags & SFLAG_DCINUSE))
1139         return D3DERR_INVALIDCALL;
1140
1141     /* we locked first, so unlock now */
1142     IWineD3DSurface_UnlockRect(iface);
1143
1144     This->Flags &= ~SFLAG_DCINUSE;
1145
1146     return WINED3D_OK;
1147 }
1148
1149 /* ******************************************************
1150    IWineD3DSurface Internal (No mapping to directx api) parts follow
1151    ****************************************************** */
1152 HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1153     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1154
1155     if (This->Flags & SFLAG_INTEXTURE) {
1156         TRACE("Surface already in texture\n");
1157         return WINED3D_OK;
1158     }
1159     if (!(This->Flags & SFLAG_DIRTY)) {
1160         TRACE("surface isn't dirty\n");
1161         return WINED3D_OK;
1162     }
1163
1164     This->Flags &= ~SFLAG_DIRTY;
1165
1166     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1167     *  These resources are not bound by device size or format restrictions. Because of this,
1168     *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1169     *  However, these resources can always be created, locked, and copied.
1170     *  In general never store scratch or system mem textures in the video ram. However it is allowed
1171     *  for system memory textures when WINED3DDEVCAPS_TEXTURESYSTEMMEMORY is set but it isn't right now.
1172     */
1173     if (This->resource.pool == WINED3DPOOL_SCRATCH || This->resource.pool == WINED3DPOOL_SYSTEMMEM)
1174     {
1175         FIXME("(%p) Operation not supported for scratch or SYSTEMMEM textures\n",This);
1176         return WINED3DERR_INVALIDCALL;
1177     }
1178
1179     if (This->Flags & SFLAG_INPBUFFER) {
1180         ENTER_GL();
1181
1182         if (This->glDescription.level != 0)
1183             FIXME("Surface in texture is only supported for level 0\n");
1184         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1185                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1186                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1187                  This->resource.format == WINED3DFMT_DXT5)
1188             FIXME("Format %d not supported\n", This->resource.format);
1189         else {
1190             GLint prevRead;
1191             glGetIntegerv(GL_READ_BUFFER, &prevRead);
1192             vcheckGLcall("glGetIntegerv");
1193             glReadBuffer(GL_BACK);
1194             vcheckGLcall("glReadBuffer");
1195
1196             glCopyTexImage2D(This->glDescription.target,
1197                              This->glDescription.level,
1198                              This->glDescription.glFormatInternal,
1199                              0,
1200                              0,
1201                              This->currentDesc.Width,
1202                              This->currentDesc.Height,
1203                              0);
1204
1205             checkGLcall("glCopyTexImage2D");
1206             glReadBuffer(prevRead);
1207             vcheckGLcall("glReadBuffer");
1208             TRACE("Updating target %d\n", This->glDescription.target);
1209             This->Flags |= SFLAG_INTEXTURE;
1210         }
1211         LEAVE_GL();
1212         return WINED3D_OK;
1213     }
1214
1215     if ((This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) &&
1216         !GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
1217         /**
1218          * wanted a paletted texture and not really support it in HW
1219          * so software emulation code begin
1220          */
1221         UINT i;
1222         PALETTEENTRY* pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
1223         VOID* surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->currentDesc.Width * This->currentDesc.Height * sizeof(DWORD));
1224         BYTE* dst = (BYTE*) surface;
1225         BYTE* src = (BYTE*) This->resource.allocatedMemory;
1226
1227         for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1228             BYTE color = *src++;
1229             *dst++ = pal[color].peRed;
1230             *dst++ = pal[color].peGreen;
1231             *dst++ = pal[color].peBlue;
1232             if (This->resource.format == WINED3DFMT_A8P8)
1233                 *dst++ = pal[color].peFlags;
1234             else
1235                 *dst++ = 0xFF;
1236         }
1237
1238         ENTER_GL();
1239
1240         TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1241               This->glDescription.target,
1242               This->glDescription.level,
1243               GL_RGBA,
1244               This->currentDesc.Width,
1245               This->currentDesc.Height,
1246               0,
1247               GL_RGBA,
1248               GL_UNSIGNED_BYTE,
1249               surface);
1250         glTexImage2D(This->glDescription.target,
1251                      This->glDescription.level,
1252                      GL_RGBA,
1253                      This->currentDesc.Width,
1254                      This->currentDesc.Height,
1255                      0,
1256                      GL_RGBA,
1257                      GL_UNSIGNED_BYTE,
1258                      surface);
1259         checkGLcall("glTexImage2D");
1260         HeapFree(GetProcessHeap(), 0, surface);
1261
1262         LEAVE_GL();
1263
1264         return WINED3D_OK;
1265     }
1266
1267     /* TODO: Compressed non-power 2 support */
1268
1269     if (This->resource.format == WINED3DFMT_DXT1 ||
1270         This->resource.format == WINED3DFMT_DXT2 ||
1271         This->resource.format == WINED3DFMT_DXT3 ||
1272         This->resource.format == WINED3DFMT_DXT4 ||
1273         This->resource.format == WINED3DFMT_DXT5) {
1274         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1275             FIXME("Using DXT1/3/5 without advertized support\n");
1276         } else if (This->resource.allocatedMemory) {
1277             TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
1278                   This->glDescription.target,
1279                   This->glDescription.level,
1280                   This->glDescription.glFormatInternal,
1281                   This->currentDesc.Width,
1282                   This->currentDesc.Height,
1283                   0,
1284                   This->resource.size,
1285                   This->resource.allocatedMemory);
1286
1287             ENTER_GL();
1288
1289             GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
1290                                                   This->glDescription.level,
1291                                                   This->glDescription.glFormatInternal,
1292                                                   This->currentDesc.Width,
1293                                                   This->currentDesc.Height,
1294                                                   0,
1295                                                   This->resource.size,
1296                                                   This->resource.allocatedMemory);
1297             checkGLcall("glCommpressedTexImage2D");
1298
1299             LEAVE_GL();
1300
1301             if(!(This->Flags & SFLAG_DONOTFREE)){
1302                 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1303                 This->resource.allocatedMemory = NULL;
1304             }
1305         }
1306     } else {
1307
1308        /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
1309         if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2)) {
1310
1311
1312             TRACE("non power of two support\n");
1313             ENTER_GL();
1314             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,
1315                 This->glDescription.target,
1316                 This->glDescription.level,
1317                 debug_d3dformat(This->resource.format),
1318                 This->glDescription.glFormatInternal,
1319                 This->pow2Width,
1320                 This->pow2Height,
1321                 0,
1322                 This->glDescription.glFormat,
1323                 This->glDescription.glType,
1324                 NULL);
1325
1326             glTexImage2D(This->glDescription.target,
1327                          This->glDescription.level,
1328                          This->glDescription.glFormatInternal,
1329                          This->pow2Width,
1330                          This->pow2Height,
1331                          0/*border*/,
1332                          This->glDescription.glFormat,
1333                          This->glDescription.glType,
1334                          NULL);
1335
1336             checkGLcall("glTexImage2D");
1337             if (This->resource.allocatedMemory != NULL) {
1338                 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
1339                 /* And map the non-power two data into the top left corner */
1340                 glTexSubImage2D(
1341                     This->glDescription.target,
1342                     This->glDescription.level,
1343                     0 /* xoffset */,
1344                     0 /* ysoffset */ ,
1345                     This->currentDesc.Width,
1346                     This->currentDesc.Height,
1347                     This->glDescription.glFormat,
1348                     This->glDescription.glType,
1349                     This->resource.allocatedMemory
1350                 );
1351                 checkGLcall("glTexSubImage2D");
1352             }
1353             LEAVE_GL();
1354
1355         } else {
1356
1357             TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1358                 This->glDescription.target,
1359                 This->glDescription.level,
1360                 debug_d3dformat(This->resource.format),
1361                 This->glDescription.glFormatInternal,
1362                 This->pow2Width,
1363                 This->pow2Height,
1364                 0,
1365                 This->glDescription.glFormat,
1366                 This->glDescription.glType,
1367                 This->resource.allocatedMemory);
1368
1369             ENTER_GL();
1370             glTexImage2D(This->glDescription.target,
1371                         This->glDescription.level,
1372                         This->glDescription.glFormatInternal,
1373                         This->pow2Width,
1374                         This->pow2Height,
1375                         0 /* border */,
1376                         This->glDescription.glFormat,
1377                         This->glDescription.glType,
1378                         This->resource.allocatedMemory);
1379             checkGLcall("glTexImage2D");
1380             LEAVE_GL();
1381         }
1382
1383 #if 0
1384         {
1385             static unsigned int gen = 0;
1386             char buffer[4096];
1387             ++gen;
1388             if ((gen % 10) == 0) {
1389                 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1390                 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1391             }
1392             /*
1393              * debugging crash code
1394             if (gen == 250) {
1395               void** test = NULL;
1396               *test = 0;
1397             }
1398             */
1399         }
1400 #endif
1401         if(!(This->Flags & SFLAG_DONOTFREE)){
1402             HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1403             This->resource.allocatedMemory = NULL;
1404         }
1405
1406     }
1407
1408     return WINED3D_OK;
1409 }
1410
1411 #include <errno.h>
1412 #include <stdio.h>
1413 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1414     FILE* f = NULL;
1415     UINT i, y;
1416     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1417     char *allocatedMemory;
1418     char *textureRow;
1419     IWineD3DSwapChain *swapChain = NULL;
1420     int width, height;
1421     GLuint tmpTexture;
1422     DWORD color;
1423     /*FIXME:
1424     Textures my not be stored in ->allocatedgMemory and a GlTexture
1425     so we should lock the surface before saving a snapshot, or at least check that
1426     */
1427     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1428     by calling GetTexImage and in compressed form by calling
1429     GetCompressedTexImageARB.  Queried compressed images can be saved and
1430     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
1431     texture images do not need to be processed by the GL and should
1432     significantly improve texture loading performance relative to uncompressed
1433     images. */
1434
1435 /* Setup the width and height to be the internal texture width and height. */
1436     width  = This->pow2Width;
1437     height = This->pow2Height;
1438 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1439     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1440
1441     if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1442 /* 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 */
1443         GLint prevRead;
1444         ENTER_GL();
1445         FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1446         glEnable(GL_TEXTURE_2D);
1447
1448         glGenTextures(1, &tmpTexture);
1449         glBindTexture(GL_TEXTURE_2D, tmpTexture);
1450
1451         glTexImage2D(GL_TEXTURE_2D,
1452                         0,
1453                         GL_RGBA,
1454                         width,
1455                         height,
1456                         0/*border*/,
1457                         GL_RGBA,
1458                         GL_UNSIGNED_INT_8_8_8_8_REV,
1459                         NULL);
1460
1461         glGetIntegerv(GL_READ_BUFFER, &prevRead);
1462         vcheckGLcall("glGetIntegerv");
1463         glReadBuffer(GL_BACK);
1464         vcheckGLcall("glReadBuffer");
1465         glCopyTexImage2D(GL_TEXTURE_2D,
1466                             0,
1467                             GL_RGBA,
1468                             0,
1469                             0,
1470                             width,
1471                             height,
1472                             0);
1473
1474         checkGLcall("glCopyTexImage2D");
1475         glReadBuffer(prevRead);
1476         LEAVE_GL();
1477
1478     } else { /* bind the real texture */
1479         IWineD3DSurface_PreLoad(iface);
1480     }
1481     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
1482     ENTER_GL();
1483     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1484     glGetTexImage(GL_TEXTURE_2D,
1485                 This->glDescription.level,
1486                 GL_RGBA,
1487                 GL_UNSIGNED_INT_8_8_8_8_REV,
1488                 allocatedMemory);
1489     checkGLcall("glTexImage2D");
1490     if (tmpTexture) {
1491         glBindTexture(GL_TEXTURE_2D, 0);
1492         glDeleteTextures(1, &tmpTexture);
1493     }
1494     LEAVE_GL();
1495
1496     f = fopen(filename, "w+");
1497     if (NULL == f) {
1498         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1499         return WINED3DERR_INVALIDCALL;
1500     }
1501 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1502     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
1503 /* TGA header */
1504     fputc(0,f);
1505     fputc(0,f);
1506     fputc(2,f);
1507     fputc(0,f);
1508     fputc(0,f);
1509     fputc(0,f);
1510     fputc(0,f);
1511     fputc(0,f);
1512     fputc(0,f);
1513     fputc(0,f);
1514     fputc(0,f);
1515     fputc(0,f);
1516 /* short width*/
1517     fwrite(&width,2,1,f);
1518 /* short height */
1519     fwrite(&height,2,1,f);
1520 /* format rgba */
1521     fputc(0x20,f);
1522     fputc(0x28,f);
1523 /* raw data */
1524     /* 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*/
1525     if(swapChain)
1526         textureRow = allocatedMemory + (width * (height - 1) *4);
1527     else
1528         textureRow = allocatedMemory;
1529     for (y = 0 ; y < height; y++) {
1530         for (i = 0; i < width;  i++) {
1531             color = *((DWORD*)textureRow);
1532             fputc((color >> 16) & 0xFF, f); /* B */
1533             fputc((color >>  8) & 0xFF, f); /* G */
1534             fputc((color >>  0) & 0xFF, f); /* R */
1535             fputc((color >> 24) & 0xFF, f); /* A */
1536             textureRow += 4;
1537         }
1538         /* take two rows of the pointer to the texture memory */
1539         if(swapChain)
1540             (textureRow-= width << 3);
1541
1542     }
1543     TRACE("Closing file\n");
1544     fclose(f);
1545
1546     if(swapChain) {
1547         IWineD3DSwapChain_Release(swapChain);
1548     }
1549     HeapFree(GetProcessHeap(), 0, allocatedMemory);
1550     return WINED3D_OK;
1551 }
1552
1553 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1554     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1555     This->Flags &= ~SFLAG_DIRTY;
1556     This->dirtyRect.left   = This->currentDesc.Width;
1557     This->dirtyRect.top    = This->currentDesc.Height;
1558     This->dirtyRect.right  = 0;
1559     This->dirtyRect.bottom = 0;
1560     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
1561           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1562     return WINED3D_OK;
1563 }
1564
1565 /**
1566  *   Slightly inefficient way to handle multiple dirty rects but it works :)
1567  */
1568 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1569     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1570     IWineD3DBaseTexture *baseTexture = NULL;
1571     This->Flags |= SFLAG_DIRTY;
1572     if (NULL != pDirtyRect) {
1573         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
1574         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
1575         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
1576         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1577     } else {
1578         This->dirtyRect.left   = 0;
1579         This->dirtyRect.top    = 0;
1580         This->dirtyRect.right  = This->currentDesc.Width;
1581         This->dirtyRect.bottom = This->currentDesc.Height;
1582     }
1583     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
1584           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1585     /* if the container is a basetexture then mark it dirty. */
1586     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
1587         TRACE("Passing to conatiner\n");
1588         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1589         IWineD3DBaseTexture_Release(baseTexture);
1590     }
1591     return WINED3D_OK;
1592 }
1593
1594 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
1595     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1596
1597     TRACE("This %p, container %p\n", This, container);
1598
1599     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
1600
1601     TRACE("Setting container to %p from %p\n", container, This->container);
1602     This->container = container;
1603
1604     return WINED3D_OK;
1605 }
1606
1607 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
1608     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1609
1610     if (This->resource.format != WINED3DFMT_UNKNOWN) {
1611         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
1612         return WINED3DERR_INVALIDCALL;
1613     }
1614
1615     TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
1616     if (format == WINED3DFMT_UNKNOWN) {
1617         This->resource.size = 0;
1618     } else if (format == WINED3DFMT_DXT1) {
1619         /* DXT1 is half byte per pixel */
1620         This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4)) >> 1;
1621
1622     } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
1623                format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
1624         This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4));
1625     } else {
1626         This->resource.size = (This->pow2Width * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * This->pow2Height;
1627     }
1628
1629
1630     /* Setup some glformat defaults */
1631     if (format != WINED3DFMT_UNKNOWN) {
1632         This->glDescription.glFormat         = D3DFmt2GLFmt(This->resource.wineD3DDevice, format);
1633         This->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This->resource.wineD3DDevice, format);
1634         This->glDescription.glType           = D3DFmt2GLType(This->resource.wineD3DDevice, format);
1635     } else {
1636         This->glDescription.glFormat         = 0;
1637         This->glDescription.glFormatInternal = 0;
1638         This->glDescription.glType           = 0;
1639     }
1640
1641     if (format != WINED3DFMT_UNKNOWN) {
1642         This->bytesPerPixel = D3DFmtGetBpp(This->resource.wineD3DDevice, format);
1643         This->pow2Size      = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
1644     } else {
1645         This->bytesPerPixel = 0;
1646         This->pow2Size      = 0;
1647     }
1648
1649     This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
1650
1651     This->resource.format = format;
1652
1653     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);
1654
1655     return WINED3D_OK;
1656 }
1657
1658 /* TODO: replace this function with context management routines */
1659 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
1660     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1661
1662     if(inPBuffer) {
1663         This->Flags |= SFLAG_INPBUFFER;
1664     } else {
1665         This->Flags &= ~SFLAG_INPBUFFER;
1666     }
1667
1668     if(inTexture) {
1669         This->Flags |= SFLAG_INTEXTURE;
1670     } else {
1671         This->Flags &= ~SFLAG_INTEXTURE;
1672     }
1673
1674     return WINED3D_OK;
1675 }
1676
1677 HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
1678     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1679     IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
1680     TRACE("(%p)->(%p,%lx)\n", This, override, Flags);
1681
1682     /* Flipping is only supported on RenderTargets */
1683     if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
1684
1685     if(override) {
1686         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
1687          * FIXME("(%p) Target override is not supported by now\n", This);
1688          * Additionally, it isn't really possible to support triple-buffering
1689          * properly on opengl at all
1690          */
1691     }
1692
1693     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
1694     return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
1695 }
1696
1697 HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
1698     FIXME("This is unimplemented for now(d3d7 merge)\n");
1699     return WINED3DERR_INVALIDCALL;
1700 }
1701
1702 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
1703     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1704     TRACE("(%p)->(%lx)\n", This, Flags);
1705
1706     switch (Flags)
1707     {
1708     case DDGBS_CANBLT:
1709     case DDGBS_ISBLTDONE:
1710         return DD_OK;
1711
1712     default:
1713         return DDERR_INVALIDPARAMS;
1714     }
1715 }
1716
1717 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
1718     /* XXX: DDERR_INVALIDSURFACETYPE */
1719
1720     TRACE("(%p)->(%08lx)\n",iface,Flags);
1721     switch (Flags) {
1722     case DDGFS_CANFLIP:
1723     case DDGFS_ISFLIPDONE:
1724         return DD_OK;
1725
1726     default:
1727         return DDERR_INVALIDPARAMS;
1728     }
1729 }
1730
1731 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
1732     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1733     TRACE("(%p)\n", This);
1734
1735     return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
1736 }
1737
1738 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
1739     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1740     TRACE("(%p)\n", This);
1741
1742     /* So far we don't lose anything :) */
1743     This->Flags &= ~SFLAG_LOST;
1744     return WINED3D_OK;
1745 }
1746
1747 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
1748     FIXME("This is unimplemented for now(d3d7 merge)\n");
1749     return WINED3DERR_INVALIDCALL;
1750 }
1751
1752 HRESULT WINAPI IWineD3DSurfaceImpl_SetPixelFormat(IWineD3DSurface *iface, WINED3DFORMAT Format, BYTE *Surface, DWORD Size) {
1753     FIXME("This is unimplemented for now(d3d7 merge)\n");
1754     return WINED3DERR_INVALIDCALL;
1755 }
1756
1757 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
1758     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1759     TRACE("(%p)->(%p)\n", This, Pal);
1760
1761     *Pal = (IWineD3DPalette *) This->palette;
1762     return DD_OK;
1763 }
1764
1765 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
1766     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1767     RGBQUAD col[256];
1768     IWineD3DPaletteImpl *pal = This->palette;
1769     unsigned int n;
1770     TRACE("(%p)\n", This);
1771
1772     if(This->resource.format == WINED3DFMT_P8 ||
1773        This->resource.format == WINED3DFMT_A8P8)
1774     {
1775         TRACE("Dirtifying surface\n");
1776         This->Flags |= SFLAG_DIRTY;
1777     }
1778
1779     if(This->Flags & SFLAG_DIBSECTION) {
1780         TRACE("(%p): Updating the hdc's palette\n", This);
1781         for (n=0; n<256; n++) {
1782             if(pal) {
1783                 col[n].rgbRed   = pal->palents[n].peRed;
1784                 col[n].rgbGreen = pal->palents[n].peGreen;
1785                 col[n].rgbBlue  = pal->palents[n].peBlue;
1786             } else {
1787                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1788                 /* Use the default device palette */
1789                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
1790                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1791                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
1792             }
1793             col[n].rgbReserved = 0;
1794         }
1795         SetDIBColorTable(This->hDC, 0, 256, col);
1796     }
1797
1798     return WINED3D_OK;
1799 }
1800
1801 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
1802     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1803     IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
1804     TRACE("(%p)->(%p)\n", This, Pal);
1805
1806     if(This->palette != NULL) 
1807         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
1808             This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
1809
1810     if(PalImpl != NULL) {
1811         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
1812             /* Set the device's main palette if the palette
1813              * wasn't a primary palette before
1814              */
1815             if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
1816                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1817                 unsigned int i;
1818
1819                 for(i=0; i < 256; i++) {
1820                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
1821                 }
1822             }
1823
1824             (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
1825         }
1826     }
1827     This->palette = PalImpl;
1828
1829     return IWineD3DSurface_RealizePalette(iface);
1830 }
1831
1832 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
1833     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1834     BOOL dirtify = FALSE;
1835     TRACE("(%p)->(%08lx,%p)\n", This, Flags, CKey);
1836
1837     if ((Flags & DDCKEY_COLORSPACE) != 0) {
1838         FIXME(" colorkey value not supported (%08lx) !\n", Flags);
1839         return DDERR_INVALIDPARAMS;
1840     }
1841
1842     /* Dirtify the surface, but only if a key was changed */
1843     if(CKey) {
1844         switch (Flags & ~DDCKEY_COLORSPACE) {
1845             case DDCKEY_DESTBLT:
1846                 if(!(This->CKeyFlags & DDSD_CKDESTBLT)) {
1847                     dirtify = TRUE;
1848                 } else {
1849                     dirtify = memcmp(&This->DestBltCKey, CKey, sizeof(*CKey) ) != 0;
1850                 }
1851                 This->DestBltCKey = *CKey;
1852                 This->CKeyFlags |= DDSD_CKDESTBLT;
1853                 break;
1854
1855             case DDCKEY_DESTOVERLAY:
1856                 if(!(This->CKeyFlags & DDSD_CKDESTOVERLAY)) {
1857                     dirtify = TRUE;
1858                 } else {
1859                     dirtify = memcmp(&This->DestOverlayCKey, CKey, sizeof(*CKey)) != 0;
1860                 }
1861                 This->DestOverlayCKey = *CKey;
1862                 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
1863                 break;
1864
1865             case DDCKEY_SRCOVERLAY:
1866                 if(!(This->CKeyFlags & DDSD_CKSRCOVERLAY)) {
1867                     dirtify = TRUE;
1868                 } else {
1869                     dirtify = memcmp(&This->SrcOverlayCKey, CKey, sizeof(*CKey)) != 0;
1870                 }
1871                 This->SrcOverlayCKey = *CKey;
1872                 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
1873                 break;
1874
1875             case DDCKEY_SRCBLT:
1876                 if(!(This->CKeyFlags & DDSD_CKSRCBLT)) {
1877                     dirtify = TRUE;
1878                 } else {
1879                     dirtify = memcmp(&This->SrcBltCKey, CKey, sizeof(*CKey)) != 0;
1880                 }
1881                 This->SrcBltCKey = *CKey;
1882                 This->CKeyFlags |= DDSD_CKSRCBLT;
1883                 break;
1884         }
1885     }
1886     else {
1887         switch (Flags & ~DDCKEY_COLORSPACE) {
1888             case DDCKEY_DESTBLT:
1889                 dirtify = This->CKeyFlags & DDSD_CKDESTBLT;
1890                 This->CKeyFlags &= ~DDSD_CKDESTBLT;
1891                 break;
1892
1893             case DDCKEY_DESTOVERLAY:
1894                 dirtify = This->CKeyFlags & DDSD_CKDESTOVERLAY;
1895                 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
1896                 break;
1897
1898             case DDCKEY_SRCOVERLAY:
1899                 dirtify = This->CKeyFlags & DDSD_CKSRCOVERLAY;
1900                 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
1901                 break;
1902
1903             case DDCKEY_SRCBLT:
1904                 dirtify = This->CKeyFlags & DDSD_CKSRCBLT;
1905                 This->CKeyFlags &= ~DDSD_CKSRCBLT;
1906                 break;
1907         }
1908     }
1909
1910     if(dirtify) {
1911         TRACE("Color key changed, dirtifying surface\n");
1912         This->Flags |= SFLAG_DIRTY;
1913     }
1914
1915     return WINED3D_OK;
1916 }
1917
1918 HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
1919     /* Nothing to do for now */
1920     return WINED3D_OK;
1921 }
1922
1923 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
1924     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
1925     DWORD ret;
1926     TRACE("(%p)\n", This);
1927
1928     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
1929          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
1930           ie pitch = (width/4) * bytes per block                                  */
1931     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
1932         ret = (This->currentDesc.Width >> 2) << 3;
1933     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
1934              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
1935         ret = (This->currentDesc.Width >> 2) << 4;
1936     else {
1937         if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
1938             /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
1939             ret = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
1940         } else {
1941             ret = This->bytesPerPixel * This->pow2Width;
1942         }
1943     }
1944     TRACE("(%p) Returning %ld\n", This, ret);
1945     return ret;
1946 }
1947
1948 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
1949 {
1950     /* IUnknown */
1951     IWineD3DSurfaceImpl_QueryInterface,
1952     IWineD3DSurfaceImpl_AddRef,
1953     IWineD3DSurfaceImpl_Release,
1954     /* IWineD3DResource */
1955     IWineD3DSurfaceImpl_GetParent,
1956     IWineD3DSurfaceImpl_GetDevice,
1957     IWineD3DSurfaceImpl_SetPrivateData,
1958     IWineD3DSurfaceImpl_GetPrivateData,
1959     IWineD3DSurfaceImpl_FreePrivateData,
1960     IWineD3DSurfaceImpl_SetPriority,
1961     IWineD3DSurfaceImpl_GetPriority,
1962     IWineD3DSurfaceImpl_PreLoad,
1963     IWineD3DSurfaceImpl_GetType,
1964     /* IWineD3DSurface */
1965     IWineD3DSurfaceImpl_GetContainerParent,
1966     IWineD3DSurfaceImpl_GetContainer,
1967     IWineD3DSurfaceImpl_GetDesc,
1968     IWineD3DSurfaceImpl_LockRect,
1969     IWineD3DSurfaceImpl_UnlockRect,
1970     IWineD3DSurfaceImpl_GetDC,
1971     IWineD3DSurfaceImpl_ReleaseDC,
1972     IWineD3DSurfaceImpl_Flip,
1973     IWineD3DSurfaceImpl_Blt,
1974     IWineD3DSurfaceImpl_GetBltStatus,
1975     IWineD3DSurfaceImpl_GetFlipStatus,
1976     IWineD3DSurfaceImpl_IsLost,
1977     IWineD3DSurfaceImpl_Restore,
1978     IWineD3DSurfaceImpl_BltFast,
1979     IWineD3DSurfaceImpl_SetPixelFormat,
1980     IWineD3DSurfaceImpl_GetPalette,
1981     IWineD3DSurfaceImpl_SetPalette,
1982     IWineD3DSurfaceImpl_RealizePalette,
1983     IWineD3DSurfaceImpl_SetColorKey,
1984     IWineD3DSurfaceImpl_GetPitch,
1985     /* Internal use: */
1986     IWineD3DSurfaceImpl_CleanDirtyRect,
1987     IWineD3DSurfaceImpl_AddDirtyRect,
1988     IWineD3DSurfaceImpl_LoadTexture,
1989     IWineD3DSurfaceImpl_SaveSnapshot,
1990     IWineD3DSurfaceImpl_SetContainer,
1991     IWineD3DSurfaceImpl_SetPBufferState,
1992     IWineD3DSurfaceImpl_SetGlTextureDesc,
1993     IWineD3DSurfaceImpl_GetGlDesc,
1994     IWineD3DSurfaceImpl_GetData,
1995     IWineD3DSurfaceImpl_SetFormat,
1996     IWineD3DSurfaceImpl_PrivateSetup
1997 };