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