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