wined3d: Fix single buffering.
[wine] / dlls / wined3d / surface.c
1 /*
2  * IWineD3DSurface Implementation
3  *
4  * Copyright 1998 Lionel Ulmer
5  * Copyright 2000-2001 TransGaming Technologies Inc.
6  * Copyright 2002-2005 Jason Edmeades
7  * Copyright 2002-2003 Raphael Junqueira
8  * Copyright 2004 Christian Costa
9  * Copyright 2005 Oliver Stieber
10  * Copyright 2006 Stefan Dösinger for CodeWeavers
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include "wine/port.h"
29 #include "wined3d_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
33
34 /* *******************************************
35    IWineD3DSurface IUnknown parts follow
36    ******************************************* */
37 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
38 {
39     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
40     /* Warn ,but be nice about things */
41     TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
42     if (riid == NULL) {
43         ERR("Probably FIXME: Calling query interface with NULL riid\n");
44     }
45     if (IsEqualGUID(riid, &IID_IUnknown)
46         || IsEqualGUID(riid, &IID_IWineD3DBase)
47         || IsEqualGUID(riid, &IID_IWineD3DResource)
48         || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
49         IUnknown_AddRef((IUnknown*)iface);
50         *ppobj = This;
51         return S_OK;
52     }
53     *ppobj = NULL;
54     return E_NOINTERFACE;
55 }
56
57 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
58     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
59     ULONG ref = InterlockedIncrement(&This->resource.ref);
60     TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
61     return ref;
62 }
63
64 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
65     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
66     ULONG ref = InterlockedDecrement(&This->resource.ref);
67     TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
68     if (ref == 0) {
69         IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
70         TRACE("(%p) : cleaning up\n", This);
71         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
72             ENTER_GL();
73             TRACE("Deleting texture %d\n", This->glDescription.textureName);
74             glDeleteTextures(1, &This->glDescription.textureName);
75             LEAVE_GL();
76         }
77
78         if(This->Flags & SFLAG_DIBSECTION) {
79             /* Release the DC */
80             SelectObject(This->hDC, This->dib.holdbitmap);
81             DeleteDC(This->hDC);
82             /* Release the DIB section */
83             DeleteObject(This->dib.DIBsection);
84             This->dib.bitmap_data = NULL;
85             This->resource.allocatedMemory = NULL;
86         }
87
88         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
89         if(iface == device->ddraw_primary)
90             device->ddraw_primary = NULL;
91
92         TRACE("(%p) Released\n", This);
93         HeapFree(GetProcessHeap(), 0, This);
94
95     }
96     return ref;
97 }
98
99 /* ****************************************************
100    IWineD3DSurface IWineD3DResource parts follow
101    **************************************************** */
102 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
103     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
104 }
105
106 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
107     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
108 }
109
110 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
111     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
112 }
113
114 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
115     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
116 }
117
118 DWORD   WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
119     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
120 }
121
122 DWORD   WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
123     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
124 }
125
126 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
127     /* TODO: re-write the way textures and managed,
128     *  use a 'opengl context manager' to manage RenderTarget surfaces
129     ** *********************************************************/
130
131     /* TODO: check for locks */
132     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
133     IWineD3DBaseTexture *baseTexture = NULL;
134     TRACE("(%p)Checking to see if the container is a base texture\n", This);
135     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
136         TRACE("Passing to conatiner\n");
137         IWineD3DBaseTexture_PreLoad(baseTexture);
138         IWineD3DBaseTexture_Release(baseTexture);
139     } else {
140     TRACE("(%p) : About to load surface\n", This);
141     ENTER_GL();
142 #if 0 /* TODO: context manager support */
143      IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
144 #endif
145     glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
146     if (This->glDescription.level == 0 &&  This->glDescription.textureName == 0) {
147           glGenTextures(1, &This->glDescription.textureName);
148           checkGLcall("glGenTextures");
149           TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
150           glBindTexture(This->glDescription.target, This->glDescription.textureName);
151           checkGLcall("glBindTexture");
152           IWineD3DSurface_LoadTexture(iface);
153           /* This is where we should be reducing the amount of GLMemoryUsed */
154     } else {
155         if (This->glDescription.level == 0) {
156           glBindTexture(This->glDescription.target, This->glDescription.textureName);
157           checkGLcall("glBindTexture");
158           IWineD3DSurface_LoadTexture(iface);
159         } else  if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
160             /* assume this is a coding error not a real error for now */
161             FIXME("Mipmap surface has a glTexture bound to it!\n");
162         }
163     }
164     if (This->resource.pool == WINED3DPOOL_DEFAULT) {
165        /* Tell opengl to try and keep this texture in video ram (well mostly) */
166        GLclampf tmp;
167        tmp = 0.9f;
168         glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
169     }
170     /* TODO: disable texture support, if it wastn't enabled when we entered. */
171 #if 0 /* TODO: context manager support */
172      IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
173               /* we don't care when the state is disabled(if atall) */);
174 #endif
175     LEAVE_GL();
176     }
177     return;
178 }
179
180 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
181     TRACE("(%p) : calling resourceimpl_GetType\n", iface);
182     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
183 }
184
185 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
186     TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
187     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
188 }
189
190 /* ******************************************************
191    IWineD3DSurface IWineD3DSurface parts follow
192    ****************************************************** */
193
194 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
195     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
196
197     TRACE("(%p) : ppContainerParent %p)\n", This, ppContainerParent);
198
199     if (!ppContainerParent) {
200         ERR("(%p) : Called without a valid ppContainerParent.\n", This);
201     }
202
203     if (This->container) {
204         IWineD3DBase_GetParent(This->container, ppContainerParent);
205         if (!ppContainerParent) {
206             /* WineD3D objects should always have a parent */
207             ERR("(%p) : GetParent returned NULL\n", This);
208         }
209         IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */
210     } else {
211         *ppContainerParent = NULL;
212     }
213
214     return WINED3D_OK;
215 }
216
217 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
218     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
219     IWineD3DBase *container = 0;
220
221     TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
222
223     if (!ppContainer) {
224         ERR("Called without a valid ppContainer.\n");
225     }
226
227     /** From MSDN:
228      * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
229      * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
230      * GetContainer will return the Direct3D device used to create the surface.
231      */
232     if (This->container) {
233         container = This->container;
234     } else {
235         container = (IWineD3DBase *)This->resource.wineD3DDevice;
236     }
237
238     TRACE("Relaying to QueryInterface\n");
239     return IUnknown_QueryInterface(container, riid, ppContainer);
240 }
241
242 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
243     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
244
245     TRACE("(%p) : copying into %p\n", This, pDesc);
246     if(pDesc->Format != NULL)             *(pDesc->Format) = This->resource.format;
247     if(pDesc->Type != NULL)               *(pDesc->Type)   = This->resource.resourceType;
248     if(pDesc->Usage != NULL)              *(pDesc->Usage)              = This->resource.usage;
249     if(pDesc->Pool != NULL)               *(pDesc->Pool)               = This->resource.pool;
250     if(pDesc->Size != NULL)               *(pDesc->Size)               = This->resource.size;   /* dx8 only */
251     if(pDesc->MultiSampleType != NULL)    *(pDesc->MultiSampleType)    = This->currentDesc.MultiSampleType;
252     if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
253     if(pDesc->Width != NULL)              *(pDesc->Width)              = This->currentDesc.Width;
254     if(pDesc->Height != NULL)             *(pDesc->Height)             = This->currentDesc.Height;
255     return WINED3D_OK;
256 }
257
258 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
259     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
260     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
261     if (This->glDescription.textureName == 0 && textureName != 0) {
262         This->Flags |= SFLAG_DIRTY;
263         IWineD3DSurface_AddDirtyRect(iface, NULL);
264     }
265     This->glDescription.textureName = textureName;
266     This->glDescription.target      = target;
267 }
268
269 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
270     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
271     TRACE("(%p) : returning %p\n", This, &This->glDescription);
272     *glDescription = &This->glDescription;
273 }
274
275 /* TODO: think about moving this down to resource? */
276 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
277     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
278     /* 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  */
279     if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
280         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
281     }
282     return (CONST void*)(This->resource.allocatedMemory);
283 }
284
285 static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
286     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
287     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
288     IWineD3DSwapChainImpl *swapchain = NULL;
289     static UINT messages = 0; /* holds flags to disable fixme messages */
290     BOOL backbuf = FALSE;
291
292     /* fixme: should we really lock as such? */
293     if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INPBUFFER)) ==
294                       (SFLAG_INTEXTURE | SFLAG_INPBUFFER) ) {
295         FIXME("Warning: Surface is in texture memory or pbuffer\n");
296         This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INPBUFFER);
297     }
298
299     if (!(This->Flags & SFLAG_LOCKABLE)) {
300         /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
301               texture regions, and since the destination is an unlockable region we need
302               to tolerate this                                                           */
303         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
304         /*return WINED3DERR_INVALIDCALL; */
305     }
306
307     if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
308         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
309
310         if (swapchain != NULL ||  iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
311             if(swapchain != NULL) {
312                 int i;
313                 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
314                     if(iface == swapchain->backBuffer[i]) {
315                         backbuf = TRUE;
316                         break;
317                     }
318                 }
319             }
320             if (backbuf) {
321                 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
322             } else if (swapchain != NULL && iface ==  swapchain->frontBuffer) {
323                 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
324             } else if (iface == myDevice->renderTarget) {
325                 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
326             } else if (iface == myDevice->depthStencilBuffer) {
327                 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
328             }
329
330             if (NULL != swapchain) {
331                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
332             }
333             swapchain = NULL;
334         }
335     } else {
336         TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
337     }
338
339     pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
340
341     if (NULL == pRect) {
342         pLockedRect->pBits = This->resource.allocatedMemory;
343         This->lockedRect.left   = 0;
344         This->lockedRect.top    = 0;
345         This->lockedRect.right  = This->currentDesc.Width;
346         This->lockedRect.bottom = This->currentDesc.Height;
347         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);
348     } else {
349         TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
350
351         if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
352             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
353         } else {
354             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
355         }
356         This->lockedRect.left   = pRect->left;
357         This->lockedRect.top    = pRect->top;
358         This->lockedRect.right  = pRect->right;
359         This->lockedRect.bottom = pRect->bottom;
360     }
361
362     if (This->Flags & SFLAG_NONPOW2) {
363         TRACE("Locking non-power 2 texture\n");
364     }
365
366     if (0 == This->resource.usage || This->resource.usage & WINED3DUSAGE_DYNAMIC) {
367         /* classic surface  TODO: non 2d surfaces?
368         These resources may be POOL_SYSTEMMEM, so they must not access the device */
369         TRACE("locking an ordinarary surface\n");
370         /* Check to see if memory has already been allocated from the surface*/
371         if ((NULL == This->resource.allocatedMemory) ||
372             (This->Flags & SFLAG_GLDIRTY) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
373             /* Non-system memory surfaces */
374
375             This->Flags &= ~SFLAG_GLDIRTY;
376
377             /*Surface has no memory currently allocated to it!*/
378             TRACE("(%p) Locking rect\n" , This);
379             if(!This->resource.allocatedMemory) {
380                 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
381             }
382             if (0 != This->glDescription.textureName) {
383                 /* Now I have to copy thing bits back */
384                 This->Flags |= SFLAG_ACTIVELOCK; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
385                 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
386                 ENTER_GL();
387     
388                 /* Make sure that the texture is loaded */
389                 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
390     
391                 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);
392     
393                 if (This->resource.format == WINED3DFMT_DXT1 ||
394                     This->resource.format == WINED3DFMT_DXT2 ||
395                     This->resource.format == WINED3DFMT_DXT3 ||
396                     This->resource.format == WINED3DFMT_DXT4 ||
397                     This->resource.format == WINED3DFMT_DXT5) {
398                     TRACE("Locking a compressed texture\n");
399                     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
400                         GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
401                                                             This->glDescription.level,
402                                                             This->resource.allocatedMemory);
403     
404                     } else {
405                         FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
406                     }
407                 } else {
408                     glGetTexImage(This->glDescription.target,
409                                 This->glDescription.level,
410                                 This->glDescription.glFormat,
411                                 This->glDescription.glType,
412                                 This->resource.allocatedMemory);
413                     vcheckGLcall("glGetTexImage");
414                     if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
415                         /* some games (e.g. warhammer 40k) don't work with the odd pitchs properly, preventing
416                         the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
417                         repack the texture so that the bpp * width pitch can be used instead of the bpp * pow2width.
418         
419                         Were doing this...
420         
421                         instead of boxing the texture :
422                         |<-texture width ->|  -->pow2width|   /\
423                         |111111111111111111|              |   |
424                         |222 Texture 222222| boxed empty  | texture height
425                         |3333 Data 33333333|              |   |
426                         |444444444444444444|              |   \/
427                         -----------------------------------   |
428                         |     boxed  empty | boxed empty  | pow2height
429                         |                  |              |   \/
430                         -----------------------------------
431         
432         
433                         were repacking the data to the expected texture width
434         
435                         |<-texture width ->|  -->pow2width|   /\
436                         |111111111111111111222222222222222|   |
437                         |222333333333333333333444444444444| texture height
438                         |444444                           |   |
439                         |                                 |   \/
440                         |                                 |   |
441                         |            empty                | pow2height
442                         |                                 |   \/
443                         -----------------------------------
444         
445                         == is the same as
446         
447                         |<-texture width ->|    /\
448                         |111111111111111111|
449                         |222222222222222222|texture height
450                         |333333333333333333|
451                         |444444444444444444|    \/
452                         --------------------
453         
454                         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.
455         
456                         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.
457                         */
458                         if (This->Flags & SFLAG_NONPOW2) {
459                             BYTE* dataa, *datab;
460                             int pitcha = 0, pitchb = 0;
461                             int y;
462                             pitcha = This->bytesPerPixel * This->currentDesc.Width;
463                             pitchb = This->bytesPerPixel * This->pow2Width;
464                             datab = dataa = This->resource.allocatedMemory;
465                             FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, pitcha, pitchb);
466                             for (y = 1 ; y < This->currentDesc.Height; y++) {
467                                 dataa += pitcha; /* skip the first row */
468                                 datab += pitchb;
469                                 memcpy(dataa, datab, pitcha);
470                             }
471                         }
472                     }
473                 }
474                 LEAVE_GL();
475             }
476         } else { /* Nothing to do */
477             TRACE("Memory %p already allocted for texture\n",  This->resource.allocatedMemory);
478         }
479
480         if (NULL == pRect) {
481             pLockedRect->pBits = This->resource.allocatedMemory;
482         }  else{
483             if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
484                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
485             } else {
486                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
487             }
488         }
489
490     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage ){ /* render surfaces */
491         if((!(Flags&WINED3DLOCK_DISCARD) && (This->Flags & SFLAG_GLDIRTY)) || !This->resource.allocatedMemory) {
492             GLint  prev_store;
493             GLint  prev_read;
494             BOOL notInContext = FALSE;
495             IWineD3DSwapChainImpl *targetSwapChain = NULL;
496
497
498             ENTER_GL();
499
500                 /**
501                 * for render->surface copy begin to begin of allocatedMemory
502                 * unlock can be more easy
503                 */
504
505             TRACE("locking a render target\n");
506
507             if (This->resource.allocatedMemory == NULL)
508                     This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
509
510             This->Flags |= SFLAG_ACTIVELOCK; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
511             pLockedRect->pBits = This->resource.allocatedMemory;
512
513             glFlush();
514             vcheckGLcall("glFlush");
515             glGetIntegerv(GL_READ_BUFFER, &prev_read);
516             vcheckGLcall("glIntegerv");
517             glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
518             vcheckGLcall("glIntegerv");
519
520     /* Here's what we have to do:
521                 See if the swapchain has the same context as the renderTarget or the surface is the render target.
522                 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
523                 and use the front back buffer as required.
524                 if not, we need to switch contexts and then switchback at the end.
525             */
526             IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
527             IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
528
529             /* 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! */
530             if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
531                     if (iface == swapchain->frontBuffer) {
532                         TRACE("locking front\n");
533                         glReadBuffer(GL_FRONT);
534                     }
535                     else if (iface == myDevice->renderTarget || backbuf) {
536                         TRACE("locking back buffer\n");
537                         glReadBuffer(GL_BACK);
538                     } else if (iface == myDevice->depthStencilBuffer) {
539                         FIXME("Stencil Buffer lock unsupported for now\n");
540                     } else {
541                       FIXME("(%p) Shouldn't have got here!\n", This);
542                       glReadBuffer(GL_BACK);
543                     }
544             } else if (swapchain != NULL) {
545                 IWineD3DSwapChainImpl *implSwapChain;
546                 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
547                 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
548                         /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
549                         if (backbuf) {
550                             glReadBuffer(GL_BACK);
551                         } else if (iface == swapchain->frontBuffer) {
552                             glReadBuffer(GL_FRONT);
553                         } else if (iface == myDevice->depthStencilBuffer) {
554                             FIXME("Stencil Buffer lock unsupported for now\n");
555                         } else {
556                             FIXME("Should have got here!\n");
557                             glReadBuffer(GL_BACK);
558                         }
559                 } else {
560                     /* We need to switch contexts to be able to read the buffer!!! */
561                     FIXME("The buffer requested isn't in the current openGL context\n");
562                     notInContext = TRUE;
563                     /* TODO: check the contexts, to see if were shared with the current context */
564                 }
565                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
566             }
567             if (swapchain != NULL)       IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
568             if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
569
570             /** the depth stencil in openGL has a format of GL_FLOAT
571             * which should be good for WINED3DFMT_D16_LOCKABLE
572             * and WINED3DFMT_D16
573             * it is unclear what format the stencil buffer is in except.
574             * 'Each index is converted to fixed point...
575             * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
576             * mappings in the table GL_PIXEL_MAP_S_TO_S.
577             * glReadPixels(This->lockedRect.left,
578             *             This->lockedRect.bottom - j - 1,
579             *             This->lockedRect.right - This->lockedRect.left,
580             *             1,
581             *             GL_DEPTH_COMPONENT,
582             *             type,
583             *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
584                 *****************************************/
585             if (!notInContext) { /* Only read the buffer if it's in the current context */
586                 long j;
587
588 #if 0
589                 /* 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,
590                 *  This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
591                 *  run ten times faster!
592                 * ************************************/
593                 BOOL ati_performance_hack = FALSE;
594                 ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
595 #endif
596                 if ((This->lockedRect.left == 0 &&  This->lockedRect.top == 0 &&
597                     This->lockedRect.right == This->currentDesc.Width
598                     && This->lockedRect.bottom ==  This->currentDesc.Height)) {
599                         BYTE *row, *top, *bottom;
600                         int i;
601
602                         glReadPixels(0, 0,
603                         This->currentDesc.Width,
604                         This->currentDesc.Height,
605                         This->glDescription.glFormat,
606                         This->glDescription.glType,
607                         (char *)pLockedRect->pBits);
608
609                         /* glReadPixels returns the image upside down, and there is no way to prevent this.
610                           Flip the lines in software*/
611                         row = HeapAlloc(GetProcessHeap(), 0, pLockedRect->Pitch);
612                         if(!row) {
613                             ERR("Out of memory\n");
614                             return E_OUTOFMEMORY;
615                         }
616                         top = This->resource.allocatedMemory;
617                         bottom = ( (BYTE *) This->resource.allocatedMemory) + pLockedRect->Pitch * ( This->currentDesc.Height - 1);
618                         for(i = 0; i < This->currentDesc.Height / 2; i++) {
619                             memcpy(row, top, pLockedRect->Pitch);
620                             memcpy(top, bottom, pLockedRect->Pitch);
621                             memcpy(bottom, row, pLockedRect->Pitch);
622                             top += pLockedRect->Pitch;
623                             bottom -= pLockedRect->Pitch;
624                         }
625                         HeapFree(GetProcessHeap(), 0, row);
626
627                         This->Flags &= ~SFLAG_GLDIRTY;
628
629                 } else if (This->lockedRect.left == 0 &&  This->lockedRect.right == This->currentDesc.Width) {
630                         glReadPixels(0,
631                         This->lockedRect.top,
632                         This->currentDesc.Width,
633                         This->currentDesc.Height,
634                         This->glDescription.glFormat,
635                         This->glDescription.glType,
636                         (char *)pLockedRect->pBits);
637                 } else{
638
639                     for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
640                         glReadPixels(This->lockedRect.left, 
641                                     This->lockedRect.bottom - j - 1, 
642                                     This->lockedRect.right - This->lockedRect.left, 
643                                     1,
644                                     This->glDescription.glFormat,
645                                     This->glDescription.glType,
646                                     (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
647
648                     }
649                 }
650
651                 vcheckGLcall("glReadPixels");
652                 TRACE("Resetting buffer\n");
653
654                 glReadBuffer(prev_read);
655                 vcheckGLcall("glReadBuffer");
656             }
657             LEAVE_GL();
658         }
659     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
660
661         if (!messages & 1) {
662             FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
663             /*
664
665             glReadPixels(This->lockedRect.left,
666             This->lockedRect.bottom - j - 1,
667             This->lockedRect.right - This->lockedRect.left,
668             1,
669             GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
670
671             )
672             */
673             messages |= 1;
674         }
675     } else {
676         FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
677     }
678
679     if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
680         /* Don't dirtify */
681     } else {
682         IWineD3DBaseTexture *pBaseTexture;
683         /**
684          * Dirtify on lock
685          * as seen in msdn docs
686          */
687         IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
688
689         /** Dirtify Container if needed */
690         if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
691             TRACE("Making container dirty\n");
692             IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
693             IWineD3DBaseTexture_Release(pBaseTexture);
694         } else {
695             TRACE("Surface is standalone, no need to dirty the container\n");
696         }
697     }
698
699     TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Flags & SFLAG_DIRTY ? 0 : 1);
700
701     This->Flags |= SFLAG_LOCKED;
702     return WINED3D_OK;
703 }
704
705 static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
706     GLint skipBytes = 0;
707     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
708     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
709     const char *buffername = "";
710     IWineD3DSwapChainImpl *swapchain = NULL;
711     BOOL backbuf = FALSE;
712
713     if (!(This->Flags & SFLAG_LOCKED)) {
714         WARN("trying to Unlock an unlocked surf@%p\n", This);
715         return WINED3DERR_INVALIDCALL;
716     }
717
718     if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
719         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
720
721         if(swapchain) {
722             int i;
723             for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
724                 if(iface == swapchain->backBuffer[i]) {
725                     backbuf = TRUE;
726                     break;
727                 }
728             }
729         }
730
731         if (backbuf) {
732                 buffername = "backBuffer";
733         } else if ((swapchain != NULL) && iface ==  swapchain->frontBuffer) {
734                 buffername = "frontBuffer";
735         } else if (iface == myDevice->depthStencilBuffer) {
736                 buffername = "depthStencilBuffer";
737         } else if (iface == myDevice->renderTarget) {
738                 buffername = "renderTarget";
739         }
740     }
741
742     if (swapchain != NULL) {
743         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
744     }
745
746     TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Flags & SFLAG_DIRTY ? 1 : 0);
747
748     if (!(This->Flags & SFLAG_DIRTY)) {
749         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
750         goto unlock_end;
751     }
752
753     if (0 == This->resource.usage) { /* classic surface */
754         /**
755          * nothing to do
756          * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
757          */
758     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
759
760         /****************************
761         * TODO: Render targets are 'special' and
762         * ?some? locking needs to be passed onto the context manager
763         * so that it becomes possible to use auxiliary buffers, pbuffers
764         * render-to-texture, shared, cached contexts etc...
765         * ****************************/
766         IWineD3DSwapChainImpl *implSwapChain;
767         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
768
769         if (backbuf || iface ==  implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
770             GLint  prev_store;
771             GLint  prev_depth_test;
772             GLint  prev_rasterpos[4];
773
774             /* Some drivers(radeon dri, others?) don't like exceptions during
775              * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
776              * after ReleaseDC. Reading it will cause an exception, which x11drv will
777              * catch to put the dib section in InSync mode, which leads to a crash
778              * and a blocked x server on my radeon card.
779              *
780              * The following lines read the dib section so it is put in inSync mode
781              * before glDrawPixels is called and the crash is prevented. There won't
782              * be any interfering gdi accesses, because UnlockRect is called from
783              * ReleaseDC, and the app won't use the dc any more afterwards.
784              */
785             if(This->Flags & SFLAG_DIBSECTION) {
786                 volatile BYTE read;
787                 read = This->resource.allocatedMemory[0];
788             }
789
790             ENTER_GL();
791
792             glFlush();
793             vcheckGLcall("glFlush");
794             glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
795             vcheckGLcall("glIntegerv");
796             glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
797             vcheckGLcall("glIntegerv");
798             glPixelZoom(1.0, -1.0);
799             vcheckGLcall("glPixelZoom");
800             prev_depth_test = glIsEnabled(GL_DEPTH_TEST);
801
802             /* glDrawPixels transforms the raster position as though it was a vertex -
803                we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
804                per drawprim (and leave set - it will sort itself out due to last_was_rhw */
805             d3ddevice_set_ortho(This->resource.wineD3DDevice);
806
807             if (iface ==  implSwapChain->frontBuffer) {
808                 glDrawBuffer(GL_FRONT);
809                 checkGLcall("glDrawBuffer GL_FRONT");
810             } else if (backbuf || iface == myDevice->renderTarget) {
811                 glDrawBuffer(GL_BACK);
812                 checkGLcall("glDrawBuffer GL_BACK");
813             }
814
815             /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
816             glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
817             glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
818
819             /* And back buffers are not blended */
820             glDisable(GL_BLEND);
821             glDisable(GL_DEPTH_TEST);
822
823             glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
824             vcheckGLcall("glRasterPos2f");
825
826             switch (This->resource.format) {
827             case WINED3DFMT_X4R4G4B4:
828                 {
829                     int size;
830                     unsigned short *data;
831                     data = (unsigned short *)This->resource.allocatedMemory;
832                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
833                     while(size > 0) {
834                             *data |= 0xF000;
835                             data++;
836                             size--;
837                     }
838                 }
839             case WINED3DFMT_A4R4G4B4:
840                 {
841                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
842                                  GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, This->resource.allocatedMemory);
843                     vcheckGLcall("glDrawPixels");
844                 }
845                 break;
846             case WINED3DFMT_R5G6B5:
847                 {
848                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
849                                  GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
850                     vcheckGLcall("glDrawPixels");
851                 }
852                 break;
853             case WINED3DFMT_X1R5G5B5:
854                 {
855                     int size;
856                     unsigned short *data;
857                     data = (unsigned short *)This->resource.allocatedMemory;
858                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
859                     while(size > 0) {
860                             *data |= 0x8000;
861                             data++;
862                             size--;
863                     }
864                 }
865             case WINED3DFMT_A1R5G5B5:
866                 {
867                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
868                                  GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, This->resource.allocatedMemory);
869                     vcheckGLcall("glDrawPixels");
870                 }
871                 break;
872             case WINED3DFMT_R8G8B8:
873                 {
874                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
875                                  GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
876                     vcheckGLcall("glDrawPixels");
877                 }
878                 break;
879             case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it 
880                                         could be any random value this fixes the intro move in Pirates! */
881                 {
882                     int size;
883                     unsigned int *data;
884                     data = (unsigned int *)This->resource.allocatedMemory;
885                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
886                     while(size > 0) {
887                             *data |= 0xFF000000;
888                             data++;
889                             size--;
890                     }
891                 }
892             case WINED3DFMT_A8R8G8B8:
893                 {
894                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
895                     vcheckGLcall("glPixelStorei");
896                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
897                                  GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
898                     vcheckGLcall("glDrawPixels");
899                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
900                     vcheckGLcall("glPixelStorei");
901                 }
902                 break;
903             case WINED3DFMT_A2R10G10B10:
904                 {
905                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
906                     vcheckGLcall("glPixelStorei");
907                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
908                                  GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, This->resource.allocatedMemory);
909                     vcheckGLcall("glDrawPixels");
910                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
911                     vcheckGLcall("glPixelStorei");
912                 }
913                 break;
914             default:
915                 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
916             }
917
918             glPixelZoom(1.0,1.0);
919             vcheckGLcall("glPixelZoom");
920             if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
921                 glDrawBuffer(GL_BACK);
922                 vcheckGLcall("glDrawBuffer");
923             }
924             glRasterPos3iv(&prev_rasterpos[0]);
925             vcheckGLcall("glRasterPos3iv");
926             if(prev_depth_test) glEnable(GL_DEPTH_TEST);
927
928             /* Reset to previous pack row length / blending state */
929             glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
930             if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
931
932             LEAVE_GL();
933
934             /** restore clean dirty state */
935             IWineD3DSurface_CleanDirtyRect(iface);
936
937         } else {
938             FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
939         }
940         IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
941
942     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
943
944         if (iface == myDevice->depthStencilBuffer) {
945             FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
946         } else {
947             FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
948         }
949
950     } else {
951         FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
952     }
953
954     unlock_end:
955     This->Flags &= ~SFLAG_LOCKED;
956     memset(&This->lockedRect, 0, sizeof(RECT));
957     return WINED3D_OK;
958 }
959
960 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
961     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
962     WINED3DLOCKED_RECT lock;
963     UINT usage;
964     BITMAPINFO* b_info;
965     HDC ddc;
966     DWORD *masks;
967     HRESULT hr;
968     RGBQUAD col[256];
969     const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
970
971     TRACE("(%p)->(%p)\n",This,pHDC);
972
973     /* Give more detailed info for ddraw */
974     if (This->Flags & SFLAG_DCINUSE)
975         return DDERR_DCALREADYCREATED;
976
977     /* Can't GetDC if the surface is locked */
978     if (This->Flags & SFLAG_LOCKED)
979         return WINED3DERR_INVALIDCALL;
980
981     memset(&lock, 0, sizeof(lock)); /* To be sure */
982
983     /* Create a DIB section if there isn't a hdc yet */
984     if(!This->hDC) {
985         if(This->Flags & SFLAG_ACTIVELOCK) {
986             ERR("Creating a DIB section while a lock is active. Uncertain consequences\n");
987         }
988
989         switch (This->bytesPerPixel) {
990             case 2:
991             case 4:
992                 /* Allocate extra space to store the RGB bit masks. */
993                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
994                 break;
995
996             case 3:
997                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
998                 break;
999
1000             default:
1001                 /* Allocate extra space for a palette. */
1002                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1003                                   sizeof(BITMAPINFOHEADER)
1004                                   + sizeof(RGBQUAD)
1005                                   * (1 << (This->bytesPerPixel * 8)));
1006                 break;
1007         }
1008
1009         b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1010         if( (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
1011             b_info->bmiHeader.biWidth = This->currentDesc.Width;
1012             b_info->bmiHeader.biHeight = -This->currentDesc.Height;
1013             /* Use the full pow2 image size(assigned below) because LockRect
1014              * will need it for a full glGetTexImage call
1015              */
1016         } else {
1017             b_info->bmiHeader.biWidth = This->pow2Width;
1018             b_info->bmiHeader.biHeight = -This->pow2Height;
1019         }
1020         b_info->bmiHeader.biPlanes = 1;
1021         b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
1022
1023         b_info->bmiHeader.biSizeImage = This->resource.size;
1024
1025         b_info->bmiHeader.biXPelsPerMeter = 0;
1026         b_info->bmiHeader.biYPelsPerMeter = 0;
1027         b_info->bmiHeader.biClrUsed = 0;
1028         b_info->bmiHeader.biClrImportant = 0;
1029
1030         /* Get the bit masks */
1031         masks = (DWORD *) &(b_info->bmiColors);
1032         switch (This->resource.format) {
1033             case WINED3DFMT_R8G8B8:
1034                 usage = DIB_RGB_COLORS;
1035                 b_info->bmiHeader.biCompression = BI_RGB;
1036                 break;
1037
1038             case WINED3DFMT_X1R5G5B5:
1039             case WINED3DFMT_A1R5G5B5:
1040             case WINED3DFMT_A4R4G4B4:
1041             case WINED3DFMT_X4R4G4B4:
1042             case WINED3DFMT_R3G3B2:
1043             case WINED3DFMT_A8R3G3B2:
1044             case WINED3DFMT_A2B10G10R10:
1045             case WINED3DFMT_A8B8G8R8:
1046             case WINED3DFMT_X8B8G8R8:
1047             case WINED3DFMT_A2R10G10B10:
1048             case WINED3DFMT_R5G6B5:
1049             case WINED3DFMT_A16B16G16R16:
1050                 usage = 0;
1051                 b_info->bmiHeader.biCompression = BI_BITFIELDS;
1052                 masks[0] = formatEntry->redMask;
1053                 masks[1] = formatEntry->greenMask;
1054                 masks[2] = formatEntry->blueMask;
1055                 break;
1056
1057             default:
1058                 /* Don't know palette */
1059                 b_info->bmiHeader.biCompression = BI_RGB;
1060                 usage = 0;
1061                 break;
1062         }
1063
1064         ddc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1065         if (ddc == 0) {
1066             HeapFree(GetProcessHeap(), 0, b_info);
1067             return HRESULT_FROM_WIN32(GetLastError());
1068         }
1069
1070         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);
1071         This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
1072         DeleteDC(ddc);
1073
1074         if (!This->dib.DIBsection) {
1075             ERR("CreateDIBSection failed!\n");
1076             return HRESULT_FROM_WIN32(GetLastError());
1077         }
1078         HeapFree(GetProcessHeap(), 0, b_info);
1079
1080         TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
1081
1082         /* copy the existing surface to the dib section */
1083         if(This->resource.allocatedMemory) {
1084             memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->resource.size);
1085             /* We won't need that any more */
1086             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1087         } else {
1088             /* This is to make LockRect read the gl Texture although memory is allocated */
1089             This->Flags |= SFLAG_GLDIRTY;
1090         }
1091
1092         /* Use the dib section from now on */
1093         This->resource.allocatedMemory = This->dib.bitmap_data;
1094
1095         /* Now allocate a HDC */
1096         This->hDC = CreateCompatibleDC(0);
1097         This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
1098         TRACE("using wined3d palette %p\n", This->palette);
1099         SelectPalette(This->hDC,
1100                       This->palette ? This->palette->hpal : 0,
1101                       FALSE);
1102
1103         This->Flags |= SFLAG_DIBSECTION;
1104     }
1105
1106     /* Lock the surface */
1107     hr = IWineD3DSurface_LockRect(iface,
1108                                   &lock,
1109                                   NULL,
1110                                   0);
1111     if(FAILED(hr)) {
1112         ERR("IWineD3DSurface_LockRect failed with hr = %08lx\n", hr);
1113         /* keep the dib section */
1114         return hr;
1115     }
1116
1117     if(This->resource.format == WINED3DFMT_P8 ||
1118         This->resource.format == WINED3DFMT_A8P8) {
1119         unsigned int n;
1120         if(This->palette) {
1121             PALETTEENTRY ent[256];
1122
1123             GetPaletteEntries(This->palette->hpal, 0, 256, ent);
1124             for (n=0; n<256; n++) {
1125                 col[n].rgbRed   = ent[n].peRed;
1126                 col[n].rgbGreen = ent[n].peGreen;
1127                 col[n].rgbBlue  = ent[n].peBlue;
1128                 col[n].rgbReserved = 0;
1129             }
1130         } else {
1131             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1132
1133             for (n=0; n<256; n++) {
1134                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
1135                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1136                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
1137                 col[n].rgbReserved = 0;
1138             }
1139
1140         }
1141         SetDIBColorTable(This->hDC, 0, 256, col);
1142     }
1143
1144     *pHDC = This->hDC;
1145     TRACE("returning %p\n",*pHDC);
1146     This->Flags |= SFLAG_DCINUSE;
1147
1148     return WINED3D_OK;
1149 }
1150
1151 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1152     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1153
1154     TRACE("(%p)->(%p)\n",This,hDC);
1155
1156     if (!(This->Flags & SFLAG_DCINUSE))
1157         return D3DERR_INVALIDCALL;
1158
1159     /* we locked first, so unlock now */
1160     IWineD3DSurface_UnlockRect(iface);
1161
1162     This->Flags &= ~SFLAG_DCINUSE;
1163
1164     return WINED3D_OK;
1165 }
1166
1167 /* ******************************************************
1168    IWineD3DSurface Internal (No mapping to directx api) parts follow
1169    ****************************************************** */
1170
1171 typedef enum {
1172     NO_CONVERSION,
1173     CONVERT_PALETTED,
1174     CONVERT_PALETTED_CK,
1175     CONVERT_CK_565,
1176     CONVERT_CK_5551,
1177     CONVERT_CK_4444,
1178     CONVERT_CK_4444_ARGB,
1179     CONVERT_CK_1555,
1180     CONVERT_555,
1181     CONVERT_CK_RGB24,
1182     CONVERT_CK_8888,
1183     CONVERT_CK_8888_ARGB,
1184     CONVERT_RGB32_888
1185 } CONVERT_TYPES;
1186
1187 HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp) {
1188     BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & DDSD_CKSRCBLT);
1189     const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1190
1191     /* Default values: From the surface */
1192     *format = formatEntry->glFormat;
1193     *internal = formatEntry->glInternal;
1194     *type = formatEntry->glType;
1195     *convert = NO_CONVERSION;
1196     *target_bpp = This->bytesPerPixel;
1197
1198     /* Ok, now look if we have to do any conversion */
1199     switch(This->resource.format) {
1200         case WINED3DFMT_P8:
1201             /* ****************
1202                 Paletted Texture
1203                 **************** */
1204             if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) || colorkey_active) {
1205                 *format = GL_RGBA;
1206                 *internal = GL_RGBA;
1207                 *type = GL_UNSIGNED_BYTE;
1208                 *target_bpp = 4;
1209                 if(colorkey_active) {
1210                     *convert = CONVERT_PALETTED;
1211                 } else {
1212                     *convert = CONVERT_PALETTED_CK;
1213                 }
1214             }
1215
1216             break;
1217
1218         case WINED3DFMT_R3G3B2:
1219             /* **********************
1220                 GL_UNSIGNED_BYTE_3_3_2
1221                 ********************** */
1222             if (colorkey_active) {
1223                 /* This texture format will never be used.. So do not care about color keying
1224                     up until the point in time it will be needed :-) */
1225                 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1226             }
1227             break;
1228
1229         case WINED3DFMT_R5G6B5:
1230             if (colorkey_active) {
1231                 *convert = CONVERT_CK_565;
1232                 *format = GL_RGBA;
1233                 *internal = GL_RGBA;
1234                 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1235             }
1236             break;
1237
1238         case WINED3DFMT_R8G8B8:
1239             if (colorkey_active) {
1240                 *convert = CONVERT_CK_RGB24;
1241                 *format = GL_RGBA;
1242                 *internal = GL_RGBA;
1243                 *type = GL_UNSIGNED_INT_8_8_8_8;
1244                 *target_bpp = 4;
1245             }
1246             break;
1247
1248         case WINED3DFMT_X8R8G8B8:
1249             if (colorkey_active) {
1250                 *convert = CONVERT_RGB32_888;
1251                 *format = GL_RGBA;
1252                 *internal = GL_RGBA;
1253                 *type = GL_UNSIGNED_INT_8_8_8_8;
1254             }
1255             break;
1256 #if 0
1257         /* Not sure if we should do color keying on Alpha-Enabled surfaces */
1258         case WINED3DFMT_A4R4G4B4:
1259             if (colorkey_active)
1260             {
1261                 *convert = CONVERT_CK_4444_ARGB;
1262                 *format = GL_RGBA;
1263                 *internal = GL_RGBA;
1264                 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1265             }
1266             break;
1267
1268         case WINED3DFMT_A1R5G5B5:
1269             if (colorkey_active)
1270             {
1271                 *convert = CONVERT_CK_1555;
1272             }
1273
1274         case WINED3DFMT_A8R8G8B8:
1275             if (colorkey_active)
1276             {
1277                 *convert = CONVERT_CK_8888_ARGB;
1278                 *format = GL_RGBA;
1279                 *internal = GL_RGBA;
1280                 *type = GL_UNSIGNED_INT_8_8_8_8;
1281             }
1282             break;
1283 #endif
1284         default:
1285             break;
1286     }
1287
1288     return WINED3D_OK;
1289 }
1290
1291 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, unsigned long len, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) {
1292     TRACE("(%p)->(%p),(%ld,%d,%p)\n", src, dst, len, convert, surf);
1293
1294     switch (convert) {
1295         case NO_CONVERSION:
1296         {
1297             memcpy(dst, src, len * surf->bytesPerPixel);
1298             break;
1299         }
1300         case CONVERT_PALETTED:
1301         case CONVERT_PALETTED_CK:
1302         {
1303             IWineD3DPaletteImpl* pal = surf->palette;
1304             BYTE table[256][4];
1305             unsigned int i;
1306             unsigned int x;
1307
1308             if( pal == NULL) {
1309                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1310             }
1311
1312             if (pal == NULL) {
1313                 /* Still no palette? Use the device's palette */
1314                 /* Get the surface's palette */
1315                 for (i = 0; i < 256; i++) {
1316                     IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice;
1317
1318                     table[i][0] = device->palettes[device->currentPalette][i].peRed;
1319                     table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1320                     table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1321                     if ((convert == CONVERT_PALETTED_CK) &&
1322                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1323                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1324                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1325                           one often used by application to prevent the nice purple borders when bi-linear
1326                           filtering is on */
1327                         table[i][3] = 0x00;
1328                     } else {
1329                         table[i][3] = 0xFF;
1330                     }
1331                 }
1332             } else {
1333                 TRACE("Using surface palette %p\n", pal);
1334                 /* Get the surface's palette */
1335                 for (i = 0; i < 256; i++) {
1336                     table[i][0] = pal->palents[i].peRed;
1337                     table[i][1] = pal->palents[i].peGreen;
1338                     table[i][2] = pal->palents[i].peBlue;
1339                     if ((convert == CONVERT_PALETTED_CK) &&
1340                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1341                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1342                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1343                           one often used by application to prevent the nice purple borders when bi-linear
1344                           filtering is on */
1345                         table[i][3] = 0x00;
1346                     } else {
1347                         table[i][3] = 0xFF;
1348                     }
1349                 }
1350             }
1351
1352             for (x = 0; x < len; x++) {
1353                 BYTE color = *src++;
1354                 *dst++ = table[color][0];
1355                 *dst++ = table[color][1];
1356                 *dst++ = table[color][2];
1357                 *dst++ = table[color][3];
1358             }
1359         }
1360         break;
1361
1362         case CONVERT_CK_565:
1363         {
1364             /* Converting the 565 format in 5551 packed to emulate color-keying.
1365
1366               Note : in all these conversion, it would be best to average the averaging
1367                       pixels to get the color of the pixel that will be color-keyed to
1368                       prevent 'color bleeding'. This will be done later on if ever it is
1369                       too visible.
1370
1371               Note2: when using color-keying + alpha, are the alpha bits part of the
1372                       color-space or not ?
1373             */
1374             unsigned int x;
1375             WORD *Source = (WORD *) src;
1376             WORD *Dest = (WORD *) dst;
1377
1378             TRACE("Color keyed 565\n");
1379
1380             for (x = 0; x < len; x++ ) {
1381                 WORD color = *Source++;
1382                 *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1383                 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1384                     (color > surf->SrcBltCKey.dwColorSpaceHighValue)) {
1385                     *Dest |= 0x0001;
1386                 }
1387                 Dest++;
1388             }
1389         }
1390         break;
1391
1392         case CONVERT_CK_1555:
1393         {
1394             unsigned int x;
1395             WORD *Source = (WORD *) src;
1396             WORD *Dest = (WORD *) dst;
1397
1398             for (x = 0; x < len * sizeof(WORD); x+=sizeof(WORD)) {
1399                 WORD color = *Source++;
1400                 *Dest = (color & 0x7FFF);
1401                 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1402                     (color > surf->SrcBltCKey.dwColorSpaceHighValue))
1403                     *Dest |= (color & 0x8000);
1404                 Dest++;
1405             }
1406         }
1407         break;
1408
1409         case CONVERT_CK_4444_ARGB:
1410         {
1411             /* Move the four Alpha bits... */
1412             unsigned int x;
1413             WORD *Source = (WORD *) src;
1414             WORD *Dest = (WORD *) dst;
1415
1416             for (x = 0; x < len; x++) {
1417                 WORD color = *Source++;
1418                 *dst = (color & 0x0FFF) << 4;
1419                 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1420                     (color > surf->SrcBltCKey.dwColorSpaceHighValue))
1421                     *Dest |= (color & 0xF000) >> 12;
1422                 Dest++;
1423             }
1424         } break;
1425
1426         default:
1427             ERR("Unsupported conversation type %d\n", convert);
1428     }
1429
1430     return WINED3D_OK;
1431 }
1432
1433 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1434     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1435
1436     if (This->Flags & SFLAG_INTEXTURE) {
1437         TRACE("Surface already in texture\n");
1438         return WINED3D_OK;
1439     }
1440     if (!(This->Flags & SFLAG_DIRTY)) {
1441         TRACE("surface isn't dirty\n");
1442         return WINED3D_OK;
1443     }
1444
1445     This->Flags &= ~SFLAG_DIRTY;
1446
1447     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1448     *  These resources are not bound by device size or format restrictions. Because of this,
1449     *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1450     *  However, these resources can always be created, locked, and copied.
1451     */
1452     if (This->resource.pool == WINED3DPOOL_SCRATCH)
1453     {
1454         FIXME("(%p) Operation not supported for scratch textures\n",This);
1455         return WINED3DERR_INVALIDCALL;
1456     }
1457
1458     if (This->Flags & SFLAG_INPBUFFER) {
1459         ENTER_GL();
1460
1461         if (This->glDescription.level != 0)
1462             FIXME("Surface in texture is only supported for level 0\n");
1463         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1464                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1465                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1466                  This->resource.format == WINED3DFMT_DXT5)
1467             FIXME("Format %d not supported\n", This->resource.format);
1468         else {
1469             GLint prevRead;
1470             glGetIntegerv(GL_READ_BUFFER, &prevRead);
1471             vcheckGLcall("glGetIntegerv");
1472             glReadBuffer(GL_BACK);
1473             vcheckGLcall("glReadBuffer");
1474
1475             glCopyTexImage2D(This->glDescription.target,
1476                              This->glDescription.level,
1477                              This->glDescription.glFormatInternal,
1478                              0,
1479                              0,
1480                              This->currentDesc.Width,
1481                              This->currentDesc.Height,
1482                              0);
1483
1484             checkGLcall("glCopyTexImage2D");
1485             glReadBuffer(prevRead);
1486             vcheckGLcall("glReadBuffer");
1487             TRACE("Updating target %d\n", This->glDescription.target);
1488             This->Flags |= SFLAG_INTEXTURE;
1489         }
1490         LEAVE_GL();
1491         return WINED3D_OK;
1492     }
1493
1494     /* TODO: Compressed non-power 2 support */
1495
1496     if (This->resource.format == WINED3DFMT_DXT1 ||
1497         This->resource.format == WINED3DFMT_DXT2 ||
1498         This->resource.format == WINED3DFMT_DXT3 ||
1499         This->resource.format == WINED3DFMT_DXT4 ||
1500         This->resource.format == WINED3DFMT_DXT5) {
1501         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1502             FIXME("Using DXT1/3/5 without advertized support\n");
1503         } else if (This->resource.allocatedMemory) {
1504             TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
1505                   This->glDescription.target,
1506                   This->glDescription.level,
1507                   This->glDescription.glFormatInternal,
1508                   This->currentDesc.Width,
1509                   This->currentDesc.Height,
1510                   0,
1511                   This->resource.size,
1512                   This->resource.allocatedMemory);
1513
1514             ENTER_GL();
1515
1516             GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
1517                                                   This->glDescription.level,
1518                                                   This->glDescription.glFormatInternal,
1519                                                   This->currentDesc.Width,
1520                                                   This->currentDesc.Height,
1521                                                   0,
1522                                                   This->resource.size,
1523                                                   This->resource.allocatedMemory);
1524             checkGLcall("glCommpressedTexImage2D");
1525
1526             LEAVE_GL();
1527
1528             if(!(This->Flags & SFLAG_DONOTFREE)){
1529                 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1530                 This->resource.allocatedMemory = NULL;
1531             }
1532         }
1533     } else {
1534         GLenum format, internal, type;
1535         CONVERT_TYPES convert;
1536         int bpp;
1537         BYTE *mem;
1538
1539         d3dfmt_get_conv(This, TRUE /* We need color keying */, &format, &internal, &type, &convert, &bpp);
1540
1541         if((convert != NO_CONVERSION) &&
1542            This->resource.allocatedMemory) {
1543             int width = This->glRect.right - This->glRect.left;
1544             int height = This->glRect.bottom - This->glRect.top;
1545             int row;
1546
1547             mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
1548             if(!mem) {
1549                 ERR("Out of memory %d, %d!\n", width, height);
1550                 return WINED3DERR_OUTOFVIDEOMEMORY;
1551             }
1552
1553             for(row = This->glRect.top; row < This->glRect.bottom; row++) {
1554                 BYTE *cur = This->resource.allocatedMemory + row * This->pow2Width * This->bytesPerPixel;
1555                 d3dfmt_convert_surface(cur + This->glRect.left * This->bytesPerPixel,
1556                                        mem + row * width * bpp,
1557                                        width,
1558                                        convert,
1559                                        This);
1560             }
1561             This->Flags |= SFLAG_CONVERTED;
1562         } else {
1563             This->Flags &= ~SFLAG_CONVERTED;
1564             mem = This->resource.allocatedMemory;
1565         }
1566
1567        /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
1568         if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE) ) {
1569
1570
1571             TRACE("non power of two support\n");
1572             ENTER_GL();
1573             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,
1574                 This->glDescription.target,
1575                 This->glDescription.level,
1576                 debug_d3dformat(This->resource.format),
1577                 This->glDescription.glFormatInternal,
1578                 This->pow2Width,
1579                 This->pow2Height,
1580                 0,
1581                 This->glDescription.glFormat,
1582                 This->glDescription.glType,
1583                 NULL);
1584
1585             glTexImage2D(This->glDescription.target,
1586                          This->glDescription.level,
1587                          This->glDescription.glFormatInternal,
1588                          This->pow2Width,
1589                          This->pow2Height,
1590                          0/*border*/,
1591                          This->glDescription.glFormat,
1592                          This->glDescription.glType,
1593                          NULL);
1594
1595             checkGLcall("glTexImage2D");
1596             if (This->resource.allocatedMemory != NULL) {
1597                 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
1598                 /* And map the non-power two data into the top left corner */
1599                 glTexSubImage2D(
1600                     This->glDescription.target,
1601                     This->glDescription.level,
1602                     0 /* xoffset */,
1603                     0 /* ysoffset */ ,
1604                     This->currentDesc.Width,
1605                     This->currentDesc.Height,
1606                     This->glDescription.glFormat,
1607                     This->glDescription.glType,
1608                     This->resource.allocatedMemory
1609                 );
1610                 checkGLcall("glTexSubImage2D");
1611             }
1612             LEAVE_GL();
1613
1614         } else {
1615
1616             TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%ld, h=%ld,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1617                 This->glDescription.target,
1618                 This->glDescription.level,
1619                 debug_d3dformat(This->resource.format),
1620                 This->glDescription.glFormatInternal,
1621                 This->glRect.right - This->glRect.left,
1622                 This->glRect.bottom - This->glRect.top,
1623                 0,
1624                 This->glDescription.glFormat,
1625                 This->glDescription.glType,
1626                 mem);
1627
1628             ENTER_GL();
1629
1630             /* OK, create the texture */
1631             glTexImage2D(This->glDescription.target,
1632                         This->glDescription.level,
1633                         internal,
1634                         This->glRect.right - This->glRect.left,
1635                         This->glRect.bottom - This->glRect.top,
1636                         0 /* border */,
1637                         format,
1638                         type,
1639                         mem);
1640
1641             checkGLcall("glTexImage2D");
1642
1643             LEAVE_GL();
1644         }
1645         if(mem != This->resource.allocatedMemory)
1646             HeapFree(GetProcessHeap(), 0, mem);
1647
1648 #if 0
1649         {
1650             static unsigned int gen = 0;
1651             char buffer[4096];
1652             ++gen;
1653             if ((gen % 10) == 0) {
1654                 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1655                 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1656             }
1657             /*
1658              * debugging crash code
1659             if (gen == 250) {
1660               void** test = NULL;
1661               *test = 0;
1662             }
1663             */
1664         }
1665 #endif
1666         if(!(This->Flags & SFLAG_DONOTFREE)){
1667             HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1668             This->resource.allocatedMemory = NULL;
1669         }
1670
1671     }
1672
1673     return WINED3D_OK;
1674 }
1675
1676 #include <errno.h>
1677 #include <stdio.h>
1678 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1679     FILE* f = NULL;
1680     UINT i, y;
1681     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1682     char *allocatedMemory;
1683     char *textureRow;
1684     IWineD3DSwapChain *swapChain = NULL;
1685     int width, height;
1686     GLuint tmpTexture;
1687     DWORD color;
1688     /*FIXME:
1689     Textures my not be stored in ->allocatedgMemory and a GlTexture
1690     so we should lock the surface before saving a snapshot, or at least check that
1691     */
1692     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1693     by calling GetTexImage and in compressed form by calling
1694     GetCompressedTexImageARB.  Queried compressed images can be saved and
1695     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
1696     texture images do not need to be processed by the GL and should
1697     significantly improve texture loading performance relative to uncompressed
1698     images. */
1699
1700 /* Setup the width and height to be the internal texture width and height. */
1701     width  = This->pow2Width;
1702     height = This->pow2Height;
1703 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1704     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1705
1706     if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1707 /* 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 */
1708         GLint prevRead;
1709         ENTER_GL();
1710         FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1711         glEnable(GL_TEXTURE_2D);
1712
1713         glGenTextures(1, &tmpTexture);
1714         glBindTexture(GL_TEXTURE_2D, tmpTexture);
1715
1716         glTexImage2D(GL_TEXTURE_2D,
1717                         0,
1718                         GL_RGBA,
1719                         width,
1720                         height,
1721                         0/*border*/,
1722                         GL_RGBA,
1723                         GL_UNSIGNED_INT_8_8_8_8_REV,
1724                         NULL);
1725
1726         glGetIntegerv(GL_READ_BUFFER, &prevRead);
1727         vcheckGLcall("glGetIntegerv");
1728         glReadBuffer(GL_BACK);
1729         vcheckGLcall("glReadBuffer");
1730         glCopyTexImage2D(GL_TEXTURE_2D,
1731                             0,
1732                             GL_RGBA,
1733                             0,
1734                             0,
1735                             width,
1736                             height,
1737                             0);
1738
1739         checkGLcall("glCopyTexImage2D");
1740         glReadBuffer(prevRead);
1741         LEAVE_GL();
1742
1743     } else { /* bind the real texture */
1744         IWineD3DSurface_PreLoad(iface);
1745     }
1746     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
1747     ENTER_GL();
1748     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1749     glGetTexImage(GL_TEXTURE_2D,
1750                 This->glDescription.level,
1751                 GL_RGBA,
1752                 GL_UNSIGNED_INT_8_8_8_8_REV,
1753                 allocatedMemory);
1754     checkGLcall("glTexImage2D");
1755     if (tmpTexture) {
1756         glBindTexture(GL_TEXTURE_2D, 0);
1757         glDeleteTextures(1, &tmpTexture);
1758     }
1759     LEAVE_GL();
1760
1761     f = fopen(filename, "w+");
1762     if (NULL == f) {
1763         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1764         return WINED3DERR_INVALIDCALL;
1765     }
1766 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1767     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
1768 /* TGA header */
1769     fputc(0,f);
1770     fputc(0,f);
1771     fputc(2,f);
1772     fputc(0,f);
1773     fputc(0,f);
1774     fputc(0,f);
1775     fputc(0,f);
1776     fputc(0,f);
1777     fputc(0,f);
1778     fputc(0,f);
1779     fputc(0,f);
1780     fputc(0,f);
1781 /* short width*/
1782     fwrite(&width,2,1,f);
1783 /* short height */
1784     fwrite(&height,2,1,f);
1785 /* format rgba */
1786     fputc(0x20,f);
1787     fputc(0x28,f);
1788 /* raw data */
1789     /* 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*/
1790     if(swapChain)
1791         textureRow = allocatedMemory + (width * (height - 1) *4);
1792     else
1793         textureRow = allocatedMemory;
1794     for (y = 0 ; y < height; y++) {
1795         for (i = 0; i < width;  i++) {
1796             color = *((DWORD*)textureRow);
1797             fputc((color >> 16) & 0xFF, f); /* B */
1798             fputc((color >>  8) & 0xFF, f); /* G */
1799             fputc((color >>  0) & 0xFF, f); /* R */
1800             fputc((color >> 24) & 0xFF, f); /* A */
1801             textureRow += 4;
1802         }
1803         /* take two rows of the pointer to the texture memory */
1804         if(swapChain)
1805             (textureRow-= width << 3);
1806
1807     }
1808     TRACE("Closing file\n");
1809     fclose(f);
1810
1811     if(swapChain) {
1812         IWineD3DSwapChain_Release(swapChain);
1813     }
1814     HeapFree(GetProcessHeap(), 0, allocatedMemory);
1815     return WINED3D_OK;
1816 }
1817
1818 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1819     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1820     This->Flags &= ~SFLAG_DIRTY;
1821     This->dirtyRect.left   = This->currentDesc.Width;
1822     This->dirtyRect.top    = This->currentDesc.Height;
1823     This->dirtyRect.right  = 0;
1824     This->dirtyRect.bottom = 0;
1825     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
1826           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1827     return WINED3D_OK;
1828 }
1829
1830 /**
1831  *   Slightly inefficient way to handle multiple dirty rects but it works :)
1832  */
1833 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1834     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1835     IWineD3DBaseTexture *baseTexture = NULL;
1836     This->Flags |= SFLAG_DIRTY;
1837     if (NULL != pDirtyRect) {
1838         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
1839         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
1840         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
1841         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1842     } else {
1843         This->dirtyRect.left   = 0;
1844         This->dirtyRect.top    = 0;
1845         This->dirtyRect.right  = This->currentDesc.Width;
1846         This->dirtyRect.bottom = This->currentDesc.Height;
1847     }
1848     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
1849           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1850     /* if the container is a basetexture then mark it dirty. */
1851     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
1852         TRACE("Passing to conatiner\n");
1853         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1854         IWineD3DBaseTexture_Release(baseTexture);
1855     }
1856     return WINED3D_OK;
1857 }
1858
1859 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
1860     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1861
1862     TRACE("This %p, container %p\n", This, container);
1863
1864     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
1865
1866     TRACE("Setting container to %p from %p\n", container, This->container);
1867     This->container = container;
1868
1869     return WINED3D_OK;
1870 }
1871
1872 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
1873     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1874     const PixelFormatDesc *formatEntry = getFormatDescEntry(format);
1875
1876     if (This->resource.format != WINED3DFMT_UNKNOWN) {
1877         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
1878         return WINED3DERR_INVALIDCALL;
1879     }
1880
1881     TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
1882     if (format == WINED3DFMT_UNKNOWN) {
1883         This->resource.size = 0;
1884     } else if (format == WINED3DFMT_DXT1) {
1885         /* DXT1 is half byte per pixel */
1886         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4)) >> 1;
1887
1888     } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
1889                format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
1890         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4));
1891     } else {
1892         This->resource.size = (This->pow2Width * formatEntry->bpp) * This->pow2Height;
1893     }
1894
1895
1896     /* Setup some glformat defaults */
1897     This->glDescription.glFormat         = formatEntry->glFormat;
1898     This->glDescription.glFormatInternal = formatEntry->glInternal;
1899     This->glDescription.glType           = formatEntry->glType;
1900
1901     if (format != WINED3DFMT_UNKNOWN) {
1902         This->bytesPerPixel = formatEntry->bpp;
1903         This->pow2Size      = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
1904     } else {
1905         This->bytesPerPixel = 0;
1906         This->pow2Size      = 0;
1907     }
1908
1909     This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
1910
1911     This->resource.format = format;
1912
1913     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);
1914
1915     return WINED3D_OK;
1916 }
1917
1918 /* TODO: replace this function with context management routines */
1919 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
1920     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1921
1922     if(inPBuffer) {
1923         This->Flags |= SFLAG_INPBUFFER;
1924     } else {
1925         This->Flags &= ~SFLAG_INPBUFFER;
1926     }
1927
1928     if(inTexture) {
1929         This->Flags |= SFLAG_INTEXTURE;
1930     } else {
1931         This->Flags &= ~SFLAG_INTEXTURE;
1932     }
1933
1934     return WINED3D_OK;
1935 }
1936
1937 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
1938     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1939     IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
1940     TRACE("(%p)->(%p,%lx)\n", This, override, Flags);
1941
1942     /* Flipping is only supported on RenderTargets */
1943     if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
1944
1945     if(override) {
1946         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
1947          * FIXME("(%p) Target override is not supported by now\n", This);
1948          * Additionally, it isn't really possible to support triple-buffering
1949          * properly on opengl at all
1950          */
1951     }
1952
1953     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
1954     return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
1955 }
1956
1957 /* Not called from the VTable */
1958 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
1959     D3DRECT rect;
1960     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
1961     IWineD3DSwapChainImpl *swapchain = NULL;
1962     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
1963     BOOL SrcOK = TRUE;
1964
1965     TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
1966
1967     /* Get the swapchain. One of the surfaces has to be a primary surface */
1968     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
1969     if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1970     else if(Src) {
1971         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&swapchain);
1972         if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1973         else return WINED3DERR_INVALIDCALL;
1974     } else {
1975         swapchain = NULL;
1976     }
1977
1978     if (DestRect) {
1979         rect.x1 = DestRect->left;
1980         rect.y1 = DestRect->top;
1981         rect.x2 = DestRect->right;
1982         rect.y2 = DestRect->bottom;
1983     } else {
1984         rect.x1 = 0;
1985         rect.y1 = 0;
1986         rect.x2 = This->currentDesc.Width;
1987         rect.y2 = This->currentDesc.Height;
1988     }
1989
1990     /* Half-life does a Blt from the back buffer to the front buffer,
1991      * Full surface size, no flags... Use present instead
1992      */
1993     if(Src)
1994     {
1995         /* First, check if we can do a Flip */
1996
1997         /* Check rects - IWineD3DDevice_Present doesn't handle them */
1998         if( SrcRect ) {
1999             if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
2000                 (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
2001                 SrcOK = TRUE;
2002             }
2003         } else {
2004             SrcOK = TRUE;
2005         }
2006
2007         /* Check the Destination rect and the surface sizes */
2008         if(SrcOK &&
2009            (rect.x1 == 0) && (rect.y1 == 0) &&
2010            (rect.x2 ==  This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
2011            (This->currentDesc.Width == Src->currentDesc.Width) &&
2012            (This->currentDesc.Height == Src->currentDesc.Height)) {
2013             /* These flags are unimportant for the flag check, remove them */
2014
2015             if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
2016                 if( swapchain->backBuffer && ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer[0]) ) {
2017
2018                     D3DSWAPEFFECT orig_swap = swapchain->presentParms.SwapEffect;
2019
2020                     /* The idea behind this is that a glReadPixels and a glDrawPixels call
2021                      * take very long, while a flip is fast.
2022                      * This applies to Half-Life, which does such Blts every time it finished
2023                      * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2024                      * menu. This is also used by all apps when they do windowed rendering
2025                      *
2026                      * The problem is that flipping is not really the same as copying. After a
2027                      * Blt the front buffer is a copy of the back buffer, and the back buffer is
2028                      * untouched. Therefore it's necessary to override the swap effect
2029                      * and to set it back after the flip.
2030                      */
2031
2032                     swapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
2033
2034                     TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2035                     IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
2036                                             NULL, NULL, 0, NULL);
2037
2038                     swapchain->presentParms.SwapEffect = orig_swap;
2039
2040                     return WINED3D_OK;
2041                 }
2042             }
2043         }
2044
2045         /* Blt from texture to rendertarget? */
2046         if( ( ( (IWineD3DSurface *) This == swapchain->frontBuffer) ||
2047               ( swapchain->backBuffer && (IWineD3DSurface *) This == swapchain->backBuffer[0]) )
2048               &&
2049               ( ( (IWineD3DSurface *) Src != swapchain->frontBuffer) &&
2050                 ( swapchain->backBuffer && (IWineD3DSurface *) Src != swapchain->backBuffer[0]) ) ) {
2051             float glTexCoord[4];
2052             DWORD oldCKey;
2053             GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha;
2054             GLint alphafunc;
2055             GLclampf alpharef;
2056             GLint oldStencil;
2057             RECT SourceRectangle;
2058             GLint oldDraw;
2059
2060             TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
2061
2062             if(SrcRect) {
2063                 SourceRectangle.left = SrcRect->left;
2064                 SourceRectangle.right = SrcRect->right;
2065                 SourceRectangle.top = SrcRect->top;
2066                 SourceRectangle.bottom = SrcRect->bottom;
2067             } else {
2068                 SourceRectangle.left = 0;
2069                 SourceRectangle.right = Src->currentDesc.Width;
2070                 SourceRectangle.top = 0;
2071                 SourceRectangle.bottom = Src->currentDesc.Height;
2072             }
2073
2074             if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
2075                 /* Fall back to software */
2076                 WARN("(%p) Source texture area (%ld,%ld)-(%ld,%ld) is too big\n", Src,
2077                      SourceRectangle.left, SourceRectangle.top,
2078                      SourceRectangle.right, SourceRectangle.bottom);
2079                 return WINED3DERR_INVALIDCALL;
2080             }
2081
2082             /* Color keying: Check if we have to do a color keyed blt,
2083              * and if not check if a color key is activated.
2084              */
2085             oldCKey = Src->CKeyFlags;
2086             if(!(Flags & DDBLT_KEYSRC) && 
2087                Src->CKeyFlags & DDSD_CKSRCBLT) {
2088                 /* Ok, the surface has a color key, but we shall not use it - 
2089                  * Deactivate it for now and dirtify the surface to reload it
2090                  */
2091                 Src->CKeyFlags &= ~DDSD_CKSRCBLT;
2092                 Src->Flags |= SFLAG_DIRTY;
2093             }
2094
2095             /* Now load the surface */
2096             IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
2097
2098             ENTER_GL();
2099
2100             /* Save all the old stuff until we have a proper opengl state manager */
2101             oldLight = glIsEnabled(GL_LIGHTING);
2102             oldFog = glIsEnabled(GL_FOG);
2103             oldDepth = glIsEnabled(GL_DEPTH_TEST);
2104             oldBlend = glIsEnabled(GL_BLEND);
2105             oldCull = glIsEnabled(GL_CULL_FACE);
2106             oldAlpha = glIsEnabled(GL_ALPHA_TEST);
2107             oldStencil = glIsEnabled(GL_STENCIL_TEST);
2108
2109             glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphafunc);
2110             checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC");
2111             glGetFloatv(GL_ALPHA_TEST_REF, &alpharef);
2112             checkGLcall("glGetFloatv GL_ALPHA_TEST_REF");
2113
2114             glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
2115             if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer) {
2116                 TRACE("Drawing to front buffer\n");
2117                 glDrawBuffer(GL_FRONT);
2118                 checkGLcall("glDrawBuffer GL_FRONT");
2119             }
2120
2121             /* Unbind the old texture */
2122             glBindTexture(GL_TEXTURE_2D, 0);
2123
2124             if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2125             /* We use texture unit 0 for blts */
2126                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
2127                 checkGLcall("glActiveTextureARB");
2128             } else {
2129                 WARN("Multi-texturing is unsupported in the local OpenGL implementation\n");
2130             }
2131
2132             /* Disable some fancy graphics effects */
2133             glDisable(GL_LIGHTING);
2134             checkGLcall("glDisable GL_LIGHTING");
2135             glDisable(GL_DEPTH_TEST);
2136             checkGLcall("glDisable GL_DEPTH_TEST");
2137             glDisable(GL_FOG);
2138             checkGLcall("glDisable GL_FOG");
2139             glDisable(GL_BLEND);
2140             checkGLcall("glDisable GL_BLEND");
2141             glDisable(GL_CULL_FACE);
2142             checkGLcall("glDisable GL_CULL_FACE");
2143             glDisable(GL_STENCIL_TEST);
2144             checkGLcall("glDisable GL_STENCIL_TEST");
2145
2146             /* Ok, we need 2d textures, but not 1D or 3D */
2147             glDisable(GL_TEXTURE_1D);
2148             checkGLcall("glDisable GL_TEXTURE_1D");
2149             glEnable(GL_TEXTURE_2D);
2150             checkGLcall("glEnable GL_TEXTURE_2D");
2151             glDisable(GL_TEXTURE_3D);
2152             checkGLcall("glDisable GL_TEXTURE_3D");
2153
2154             /* Bind the texture */
2155             glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2156             checkGLcall("glBindTexture");
2157
2158             glEnable(GL_SCISSOR_TEST);
2159
2160             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2161
2162             /* No filtering for blts */
2163             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
2164                             GL_NEAREST);
2165             checkGLcall("glTexParameteri");
2166             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
2167                             GL_NEAREST);
2168             checkGLcall("glTexParameteri");
2169             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2170             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2171             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2172             checkGLcall("glTexEnvi");
2173
2174             /* This is for color keying */
2175             if(Flags & DDBLT_KEYSRC) {
2176                 glEnable(GL_ALPHA_TEST);
2177                 checkGLcall("glEnable GL_ALPHA_TEST");
2178                 glAlphaFunc(GL_NOTEQUAL, 0.0);
2179                 checkGLcall("glAlphaFunc\n");
2180             } else {
2181                 glDisable(GL_ALPHA_TEST);
2182                 checkGLcall("glDisable GL_ALPHA_TEST");
2183             }
2184
2185             /* Draw a textured quad
2186              */
2187             d3ddevice_set_ortho(This->resource.wineD3DDevice);
2188
2189             glBegin(GL_QUADS);
2190
2191             glColor3d(1.0f, 1.0f, 1.0f);
2192             glTexCoord2f(glTexCoord[0], glTexCoord[2]);
2193             glVertex3f(rect.x1,
2194                        rect.y1,
2195                        0.0);
2196
2197             glTexCoord2f(glTexCoord[0], glTexCoord[3]);
2198             glVertex3f(rect.x1, rect.y2, 0.0);
2199
2200             glTexCoord2f(glTexCoord[1], glTexCoord[3]);
2201             glVertex3f(rect.x2,
2202                        rect.y2,
2203                        0.0);
2204
2205             glTexCoord2f(glTexCoord[1], glTexCoord[2]);
2206             glVertex3f(rect.x2,
2207                        rect.y1,
2208                        0.0);
2209             glEnd();
2210             checkGLcall("glEnd");
2211
2212             /* Unbind the texture */
2213             glBindTexture(GL_TEXTURE_2D, 0);
2214             checkGLcall("glEnable glBindTexture");
2215
2216             /* Restore the old settings */
2217             if(oldLight) {
2218                 glEnable(GL_LIGHTING);
2219                 checkGLcall("glEnable GL_LIGHTING");
2220             }
2221             if(oldFog) {
2222                 glEnable(GL_FOG);
2223                 checkGLcall("glEnable GL_FOG");
2224             }
2225             if(oldDepth) {
2226                 glEnable(GL_DEPTH_TEST);
2227                 checkGLcall("glEnable GL_DEPTH_TEST");
2228             }
2229             if(oldBlend) {
2230                 glEnable(GL_BLEND);
2231                 checkGLcall("glEnable GL_BLEND");
2232             }
2233             if(oldCull) {
2234                 glEnable(GL_CULL_FACE);
2235                 checkGLcall("glEnable GL_CULL_FACE");
2236             }
2237             if(oldStencil) {
2238                 glEnable(GL_STENCIL_TEST);
2239                 checkGLcall("glEnable GL_STENCIL_TEST");
2240             }
2241             if(!oldAlpha) {
2242                 glDisable(GL_ALPHA_TEST);
2243                 checkGLcall("glDisable GL_ALPHA_TEST");
2244             } else {
2245                 glEnable(GL_ALPHA_TEST);
2246                 checkGLcall("glEnable GL_ALPHA_TEST");
2247             }
2248
2249             glAlphaFunc(alphafunc, alpharef);
2250             checkGLcall("glAlphaFunc\n");
2251
2252             if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer && oldDraw == GL_BACK) {
2253                 glDrawBuffer(oldDraw);
2254             }
2255
2256             /* Restore the color key */
2257             if(oldCKey != Src->CKeyFlags) {
2258                 Src->CKeyFlags = oldCKey;
2259                 Src->Flags |= SFLAG_DIRTY;
2260             }
2261
2262             LEAVE_GL();
2263
2264             /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2265             This->Flags |= SFLAG_GLDIRTY;
2266
2267             return WINED3D_OK;
2268         }
2269
2270
2271         /* Blt from rendertarget to texture? */
2272         if( (SrcSurface == swapchain->frontBuffer) ||
2273             (swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) ) {
2274             if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
2275                 ( swapchain->backBuffer && (IWineD3DSurface *) This != swapchain->backBuffer[0]) ) {
2276                 UINT row;
2277                 D3DRECT srect;
2278                 float xrel, yrel;
2279
2280                 TRACE("Blt from rendertarget to texture\n");
2281
2282                 /* Call preload for the surface to make sure it isn't dirty */
2283                 IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2284
2285                 if(SrcRect) {
2286                     srect.x1 = SrcRect->left;
2287                     srect.y1 = SrcRect->top;
2288                     srect.x2 = SrcRect->right;
2289                     srect.y2 = SrcRect->bottom;
2290                 } else {
2291                     srect.x1 = 0;
2292                     srect.y1 = 0;
2293                     srect.x2 = Src->currentDesc.Width;
2294                     srect.y2 = Src->currentDesc.Height;
2295                 }
2296
2297                 ENTER_GL();
2298
2299                 /* Bind the target texture */
2300                 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2301                 checkGLcall("glBindTexture");
2302                 if(swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) {
2303                     glReadBuffer(GL_BACK);
2304                 } else {
2305                     glReadBuffer(GL_FRONT);
2306                 }
2307                 checkGLcall("glReadBuffer");
2308
2309                 xrel = (float) (srect.x2 - srect.x1) / (float) (rect.x2 - rect.x1);
2310                 yrel = (float) (srect.y2 - srect.y1) / (float) (rect.y2 - rect.y1);
2311
2312                 /* I have to process this row by row to swap the image,
2313                  * otherwise it would be upside down, so streching in y direction
2314                  * doesn't cost extra time
2315                  *
2316                  * However, streching in x direction can be avoided if not necessary
2317                  */
2318                 for(row = rect.y1; row < rect.y2; row++) {
2319                     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2320                         /* Well, that stuff works, but it's very slow.
2321                          * find a better way instead
2322                          */
2323                         UINT col;
2324                         for(col = rect.x1; col < rect.x2; col++) {
2325                             glCopyTexSubImage2D(GL_TEXTURE_2D,
2326                                                 0, /* level */
2327                                                 rect.x1 + col, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2328                                                 srect.x1 + col * xrel, Src->currentDesc.Height - srect.y2 + row * yrel,
2329                                                 1, 1);
2330                         }
2331                     } else {
2332                         glCopyTexSubImage2D(GL_TEXTURE_2D,
2333                                             0, /* level */
2334                                             rect.x1, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2335                                             srect.x1, Src->currentDesc.Height - srect.y2 + row * yrel,
2336                                             rect.x2, 1);
2337                     }
2338                 }
2339
2340                 vcheckGLcall("glCopyTexSubImage2D");
2341                 LEAVE_GL();
2342
2343                 if(!(This->Flags & SFLAG_DONOTFREE)) {
2344                     HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2345                     This->resource.allocatedMemory = NULL;
2346                 } else {
2347                     This->Flags |= SFLAG_GLDIRTY;
2348                 }
2349
2350                 return WINED3D_OK;
2351             }
2352         }
2353     }
2354
2355     if (Flags & DDBLT_COLORFILL) {
2356         /* This is easy to handle for the D3D Device... */
2357         DWORD color;
2358         IWineD3DSwapChainImpl *implSwapChain;
2359
2360         TRACE("Colorfill\n");
2361
2362         /* The color as given in the Blt function is in the format of the frame-buffer...
2363          * 'clear' expect it in ARGB format => we need to do some conversion :-)
2364          */
2365         if (This->resource.format == WINED3DFMT_P8) {
2366             if (This->palette) {
2367                 color = ((0xFF000000) |
2368                           (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2369                           (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2370                           (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2371             } else {
2372                 color = 0xFF000000;
2373             }
2374         }
2375         else if (This->resource.format == WINED3DFMT_R5G6B5) {
2376             if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2377                 color = 0xFFFFFFFF;
2378             } else {
2379                 color = ((0xFF000000) |
2380                           ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2381                           ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2382                           ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2383             }
2384         }
2385         else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2386                   (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2387             color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2388         }
2389         else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2390             color = DDBltFx->u5.dwFillColor;
2391         }
2392         else {
2393             ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2394             return WINED3DERR_INVALIDCALL;
2395         }
2396
2397         TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2398         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
2399         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
2400         if(implSwapChain->backBuffer && This == (IWineD3DSurfaceImpl*) implSwapChain->backBuffer[0]) {
2401             glDrawBuffer(GL_BACK);
2402             checkGLcall("glDrawBuffer(GL_BACK)");
2403         }
2404         else if (This == (IWineD3DSurfaceImpl*) implSwapChain->frontBuffer) {
2405             glDrawBuffer(GL_FRONT);
2406             checkGLcall("glDrawBuffer(GL_FRONT)");
2407         }
2408         else {
2409             ERR("Wrong surface type for BLT override(not on swapchain) !\n");
2410             return WINED3DERR_INVALIDCALL;
2411         }
2412
2413         TRACE("(%p) executing Render Target override, color = %lx\n", This, color);
2414
2415         IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2416                               1 /* Number of rectangles */,
2417                               &rect,
2418                               D3DCLEAR_TARGET,
2419                               color,
2420                               0.0 /* Z */,
2421                               0 /* Stencil */);
2422
2423         /* Restore the original draw buffer */
2424         if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
2425             glDrawBuffer(GL_BACK);
2426             vcheckGLcall("glDrawBuffer");
2427         }
2428
2429         return WINED3D_OK;
2430     }
2431
2432     /* Default: Fall back to the generic blt */
2433     return WINED3DERR_INVALIDCALL;
2434 }
2435
2436 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2437     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2438     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2439     TRACE("(%p)->(%p,%p,%p,%lx,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2440     TRACE("(%p): Usage is %08lx\n", This, This->resource.usage);
2441
2442     /* Special cases for RenderTargets */
2443     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2444         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2445         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2446     }
2447
2448     /* For the rest call the X11 surface implementation.
2449      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2450      * other Blts are rather rare
2451      */
2452     return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2453 }
2454
2455 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2456     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2457     TRACE("(%p)->(%lx)\n", This, Flags);
2458
2459     switch (Flags)
2460     {
2461     case DDGBS_CANBLT:
2462     case DDGBS_ISBLTDONE:
2463         return DD_OK;
2464
2465     default:
2466         return DDERR_INVALIDPARAMS;
2467     }
2468 }
2469
2470 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2471     /* XXX: DDERR_INVALIDSURFACETYPE */
2472
2473     TRACE("(%p)->(%08lx)\n",iface,Flags);
2474     switch (Flags) {
2475     case DDGFS_CANFLIP:
2476     case DDGFS_ISFLIPDONE:
2477         return DD_OK;
2478
2479     default:
2480         return DDERR_INVALIDPARAMS;
2481     }
2482 }
2483
2484 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2485     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2486     TRACE("(%p)\n", This);
2487
2488     return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2489 }
2490
2491 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2492     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2493     TRACE("(%p)\n", This);
2494
2495     /* So far we don't lose anything :) */
2496     This->Flags &= ~SFLAG_LOST;
2497     return WINED3D_OK;
2498 }
2499
2500 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2501     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2502     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2503     TRACE("(%p)->(%ld, %ld, %p, %p, %08lx\n", iface, dstx, dsty, Source, rsrc, trans);
2504
2505     /* Special cases for RenderTargets */
2506     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2507         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2508
2509         RECT SrcRect, DstRect;
2510
2511         if(rsrc) {
2512             SrcRect.left = rsrc->left;
2513             SrcRect.top= rsrc->top;
2514             SrcRect.bottom = rsrc->bottom;
2515             SrcRect.right = rsrc->right;
2516         } else {
2517             SrcRect.left = 0;
2518             SrcRect.top = 0;
2519             SrcRect.right = srcImpl->currentDesc.Width;
2520             SrcRect.bottom = srcImpl->currentDesc.Height;
2521         }
2522
2523         DstRect.left = dstx;
2524         DstRect.top=dsty;
2525         DstRect.right = dstx + SrcRect.right - SrcRect.left;
2526         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2527
2528         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, 0, NULL) == WINED3D_OK) return WINED3D_OK;
2529     }
2530
2531
2532     return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2533 }
2534
2535 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2536     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2537     TRACE("(%p)->(%p)\n", This, Pal);
2538
2539     *Pal = (IWineD3DPalette *) This->palette;
2540     return DD_OK;
2541 }
2542
2543 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2544     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2545     RGBQUAD col[256];
2546     IWineD3DPaletteImpl *pal = This->palette;
2547     unsigned int n;
2548     TRACE("(%p)\n", This);
2549
2550     if(This->resource.format == WINED3DFMT_P8 ||
2551        This->resource.format == WINED3DFMT_A8P8)
2552     {
2553         TRACE("Dirtifying surface\n");
2554         This->Flags |= SFLAG_DIRTY;
2555     }
2556
2557     if(This->Flags & SFLAG_DIBSECTION) {
2558         TRACE("(%p): Updating the hdc's palette\n", This);
2559         for (n=0; n<256; n++) {
2560             if(pal) {
2561                 col[n].rgbRed   = pal->palents[n].peRed;
2562                 col[n].rgbGreen = pal->palents[n].peGreen;
2563                 col[n].rgbBlue  = pal->palents[n].peBlue;
2564             } else {
2565                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2566                 /* Use the default device palette */
2567                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
2568                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
2569                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
2570             }
2571             col[n].rgbReserved = 0;
2572         }
2573         SetDIBColorTable(This->hDC, 0, 256, col);
2574     }
2575
2576     return WINED3D_OK;
2577 }
2578
2579 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
2580     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2581     IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
2582     TRACE("(%p)->(%p)\n", This, Pal);
2583
2584     if(This->palette != NULL) 
2585         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
2586             This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
2587
2588     if(PalImpl != NULL) {
2589         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2590             /* Set the device's main palette if the palette
2591              * wasn't a primary palette before
2592              */
2593             if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
2594                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2595                 unsigned int i;
2596
2597                 for(i=0; i < 256; i++) {
2598                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
2599                 }
2600             }
2601
2602             (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
2603         }
2604     }
2605     This->palette = PalImpl;
2606
2607     return IWineD3DSurface_RealizePalette(iface);
2608 }
2609
2610 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
2611     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2612     BOOL dirtify = FALSE;
2613     TRACE("(%p)->(%08lx,%p)\n", This, Flags, CKey);
2614
2615     if ((Flags & DDCKEY_COLORSPACE) != 0) {
2616         FIXME(" colorkey value not supported (%08lx) !\n", Flags);
2617         return DDERR_INVALIDPARAMS;
2618     }
2619
2620     /* Dirtify the surface, but only if a key was changed */
2621     if(CKey) {
2622         switch (Flags & ~DDCKEY_COLORSPACE) {
2623             case DDCKEY_DESTBLT:
2624                 if(!(This->CKeyFlags & DDSD_CKDESTBLT)) {
2625                     dirtify = TRUE;
2626                 } else {
2627                     dirtify = memcmp(&This->DestBltCKey, CKey, sizeof(*CKey) ) != 0;
2628                 }
2629                 This->DestBltCKey = *CKey;
2630                 This->CKeyFlags |= DDSD_CKDESTBLT;
2631                 break;
2632
2633             case DDCKEY_DESTOVERLAY:
2634                 if(!(This->CKeyFlags & DDSD_CKDESTOVERLAY)) {
2635                     dirtify = TRUE;
2636                 } else {
2637                     dirtify = memcmp(&This->DestOverlayCKey, CKey, sizeof(*CKey)) != 0;
2638                 }
2639                 This->DestOverlayCKey = *CKey;
2640                 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
2641                 break;
2642
2643             case DDCKEY_SRCOVERLAY:
2644                 if(!(This->CKeyFlags & DDSD_CKSRCOVERLAY)) {
2645                     dirtify = TRUE;
2646                 } else {
2647                     dirtify = memcmp(&This->SrcOverlayCKey, CKey, sizeof(*CKey)) != 0;
2648                 }
2649                 This->SrcOverlayCKey = *CKey;
2650                 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
2651                 break;
2652
2653             case DDCKEY_SRCBLT:
2654                 if(!(This->CKeyFlags & DDSD_CKSRCBLT)) {
2655                     dirtify = TRUE;
2656                 } else {
2657                     dirtify = memcmp(&This->SrcBltCKey, CKey, sizeof(*CKey)) != 0;
2658                 }
2659                 This->SrcBltCKey = *CKey;
2660                 This->CKeyFlags |= DDSD_CKSRCBLT;
2661                 break;
2662         }
2663     }
2664     else {
2665         switch (Flags & ~DDCKEY_COLORSPACE) {
2666             case DDCKEY_DESTBLT:
2667                 dirtify = This->CKeyFlags & DDSD_CKDESTBLT;
2668                 This->CKeyFlags &= ~DDSD_CKDESTBLT;
2669                 break;
2670
2671             case DDCKEY_DESTOVERLAY:
2672                 dirtify = This->CKeyFlags & DDSD_CKDESTOVERLAY;
2673                 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
2674                 break;
2675
2676             case DDCKEY_SRCOVERLAY:
2677                 dirtify = This->CKeyFlags & DDSD_CKSRCOVERLAY;
2678                 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
2679                 break;
2680
2681             case DDCKEY_SRCBLT:
2682                 dirtify = This->CKeyFlags & DDSD_CKSRCBLT;
2683                 This->CKeyFlags &= ~DDSD_CKSRCBLT;
2684                 break;
2685         }
2686     }
2687
2688     if(dirtify) {
2689         TRACE("Color key changed, dirtifying surface\n");
2690         This->Flags |= SFLAG_DIRTY;
2691     }
2692
2693     return WINED3D_OK;
2694 }
2695
2696 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
2697     /** Check against the maximum texture sizes supported by the video card **/
2698     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2699
2700     TRACE("%p\n", This);
2701     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
2702         /* one of three options
2703         1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
2704         2: Set the texture to the maxium size (bad idea)
2705         3:    WARN and return WINED3DERR_NOTAVAILABLE;
2706         4: Create the surface, but allow it to be used only for DirectDraw Blts. Some apps(e.g. Swat 3) create textures with a Height of 16 and a Width > 3000 and blt 16x16 letter areas from them to the render target.
2707         */
2708         WARN("(%p) Creating an oversized surface\n", This);
2709         This->Flags |= SFLAG_OVERSIZE;
2710
2711         /* This will be initialized on the first blt */
2712         This->glRect.left = 0;
2713         This->glRect.top = 0;
2714         This->glRect.right = 0;
2715         This->glRect.bottom = 0;
2716     } else {
2717         /* No oversize, gl rect is the full texture size */
2718         This->Flags &= ~SFLAG_OVERSIZE;
2719         This->glRect.left = 0;
2720         This->glRect.top = 0;
2721         This->glRect.right = This->pow2Width;
2722         This->glRect.bottom = This->pow2Height;
2723     }
2724
2725     return WINED3D_OK;
2726 }
2727
2728 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
2729     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2730     DWORD ret;
2731     TRACE("(%p)\n", This);
2732
2733     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
2734          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
2735           ie pitch = (width/4) * bytes per block                                  */
2736     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
2737         ret = (This->currentDesc.Width >> 2) << 3;
2738     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
2739              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
2740         ret = (This->currentDesc.Width >> 2) << 4;
2741     else {
2742         if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2743             /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
2744             ret = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
2745         } else {
2746             ret = This->bytesPerPixel * This->pow2Width;
2747         }
2748     }
2749     TRACE("(%p) Returning %ld\n", This, ret);
2750     return ret;
2751 }
2752
2753 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
2754 {
2755     /* IUnknown */
2756     IWineD3DSurfaceImpl_QueryInterface,
2757     IWineD3DSurfaceImpl_AddRef,
2758     IWineD3DSurfaceImpl_Release,
2759     /* IWineD3DResource */
2760     IWineD3DSurfaceImpl_GetParent,
2761     IWineD3DSurfaceImpl_GetDevice,
2762     IWineD3DSurfaceImpl_SetPrivateData,
2763     IWineD3DSurfaceImpl_GetPrivateData,
2764     IWineD3DSurfaceImpl_FreePrivateData,
2765     IWineD3DSurfaceImpl_SetPriority,
2766     IWineD3DSurfaceImpl_GetPriority,
2767     IWineD3DSurfaceImpl_PreLoad,
2768     IWineD3DSurfaceImpl_GetType,
2769     /* IWineD3DSurface */
2770     IWineD3DSurfaceImpl_GetContainerParent,
2771     IWineD3DSurfaceImpl_GetContainer,
2772     IWineD3DSurfaceImpl_GetDesc,
2773     IWineD3DSurfaceImpl_LockRect,
2774     IWineD3DSurfaceImpl_UnlockRect,
2775     IWineD3DSurfaceImpl_GetDC,
2776     IWineD3DSurfaceImpl_ReleaseDC,
2777     IWineD3DSurfaceImpl_Flip,
2778     IWineD3DSurfaceImpl_Blt,
2779     IWineD3DSurfaceImpl_GetBltStatus,
2780     IWineD3DSurfaceImpl_GetFlipStatus,
2781     IWineD3DSurfaceImpl_IsLost,
2782     IWineD3DSurfaceImpl_Restore,
2783     IWineD3DSurfaceImpl_BltFast,
2784     IWineD3DSurfaceImpl_GetPalette,
2785     IWineD3DSurfaceImpl_SetPalette,
2786     IWineD3DSurfaceImpl_RealizePalette,
2787     IWineD3DSurfaceImpl_SetColorKey,
2788     IWineD3DSurfaceImpl_GetPitch,
2789     /* Internal use: */
2790     IWineD3DSurfaceImpl_CleanDirtyRect,
2791     IWineD3DSurfaceImpl_AddDirtyRect,
2792     IWineD3DSurfaceImpl_LoadTexture,
2793     IWineD3DSurfaceImpl_SaveSnapshot,
2794     IWineD3DSurfaceImpl_SetContainer,
2795     IWineD3DSurfaceImpl_SetPBufferState,
2796     IWineD3DSurfaceImpl_SetGlTextureDesc,
2797     IWineD3DSurfaceImpl_GetGlDesc,
2798     IWineD3DSurfaceImpl_GetData,
2799     IWineD3DSurfaceImpl_SetFormat,
2800     IWineD3DSurfaceImpl_PrivateSetup
2801 };