rpcrt4: Fix the argument size of conformant arrays.
[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_draw;
772             GLint  prev_depth_test;
773             GLint  prev_rasterpos[4];
774
775             /* Some drivers(radeon dri, others?) don't like exceptions during
776              * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
777              * after ReleaseDC. Reading it will cause an exception, which x11drv will
778              * catch to put the dib section in InSync mode, which leads to a crash
779              * and a blocked x server on my radeon card.
780              *
781              * The following lines read the dib section so it is put in inSync mode
782              * before glDrawPixels is called and the crash is prevented. There won't
783              * be any interfering gdi accesses, because UnlockRect is called from
784              * ReleaseDC, and the app won't use the dc any more afterwards.
785              */
786             if(This->Flags & SFLAG_DIBSECTION) {
787                 volatile BYTE read;
788                 read = This->resource.allocatedMemory[0];
789             }
790
791             ENTER_GL();
792
793             glFlush();
794             vcheckGLcall("glFlush");
795             glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
796             vcheckGLcall("glIntegerv");
797             glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
798             vcheckGLcall("glIntegerv");
799             glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
800             vcheckGLcall("glIntegerv");
801             glPixelZoom(1.0, -1.0);
802             vcheckGLcall("glPixelZoom");
803             prev_depth_test = glIsEnabled(GL_DEPTH_TEST);
804
805             /* glDrawPixels transforms the raster position as though it was a vertex -
806                we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
807                per drawprim (and leave set - it will sort itself out due to last_was_rhw */
808             d3ddevice_set_ortho(This->resource.wineD3DDevice);
809
810             if (iface ==  implSwapChain->frontBuffer) {
811                 glDrawBuffer(GL_FRONT);
812                 checkGLcall("glDrawBuffer GL_FRONT");
813             } else if (backbuf || iface == myDevice->renderTarget) {
814                 glDrawBuffer(GL_BACK);
815                 checkGLcall("glDrawBuffer GL_BACK");
816             }
817
818             /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
819             glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
820             glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
821
822             /* And back buffers are not blended */
823             glDisable(GL_BLEND);
824             glDisable(GL_DEPTH_TEST);
825
826             glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
827             vcheckGLcall("glRasterPos2f");
828
829             switch (This->resource.format) {
830             case WINED3DFMT_X4R4G4B4:
831                 {
832                     int size;
833                     unsigned short *data;
834                     data = (unsigned short *)This->resource.allocatedMemory;
835                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
836                     while(size > 0) {
837                             *data |= 0xF000;
838                             data++;
839                             size--;
840                     }
841                 }
842             case WINED3DFMT_A4R4G4B4:
843                 {
844                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
845                                  GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, This->resource.allocatedMemory);
846                     vcheckGLcall("glDrawPixels");
847                 }
848                 break;
849             case WINED3DFMT_R5G6B5:
850                 {
851                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
852                                  GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
853                     vcheckGLcall("glDrawPixels");
854                 }
855                 break;
856             case WINED3DFMT_X1R5G5B5:
857                 {
858                     int size;
859                     unsigned short *data;
860                     data = (unsigned short *)This->resource.allocatedMemory;
861                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
862                     while(size > 0) {
863                             *data |= 0x8000;
864                             data++;
865                             size--;
866                     }
867                 }
868             case WINED3DFMT_A1R5G5B5:
869                 {
870                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
871                                  GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, This->resource.allocatedMemory);
872                     vcheckGLcall("glDrawPixels");
873                 }
874                 break;
875             case WINED3DFMT_R8G8B8:
876                 {
877                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
878                                  GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
879                     vcheckGLcall("glDrawPixels");
880                 }
881                 break;
882             case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it 
883                                         could be any random value this fixes the intro move in Pirates! */
884                 {
885                     int size;
886                     unsigned int *data;
887                     data = (unsigned int *)This->resource.allocatedMemory;
888                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
889                     while(size > 0) {
890                             *data |= 0xFF000000;
891                             data++;
892                             size--;
893                     }
894                 }
895             case WINED3DFMT_A8R8G8B8:
896                 {
897                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
898                     vcheckGLcall("glPixelStorei");
899                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
900                                  GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
901                     vcheckGLcall("glDrawPixels");
902                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
903                     vcheckGLcall("glPixelStorei");
904                 }
905                 break;
906             case WINED3DFMT_A2R10G10B10:
907                 {
908                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
909                     vcheckGLcall("glPixelStorei");
910                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
911                                  GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, This->resource.allocatedMemory);
912                     vcheckGLcall("glDrawPixels");
913                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
914                     vcheckGLcall("glPixelStorei");
915                 }
916                 break;
917             default:
918                 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
919             }
920
921             glPixelZoom(1.0,1.0);
922             vcheckGLcall("glPixelZoom");
923             glDrawBuffer(prev_draw);
924             vcheckGLcall("glDrawBuffer");
925             glRasterPos3iv(&prev_rasterpos[0]);
926             vcheckGLcall("glRasterPos3iv");
927             if(prev_depth_test) glEnable(GL_DEPTH_TEST);
928
929             /* Reset to previous pack row length / blending state */
930             glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
931             if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
932
933             LEAVE_GL();
934
935             /** restore clean dirty state */
936             IWineD3DSurface_CleanDirtyRect(iface);
937
938         } else {
939             FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
940         }
941         IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
942
943     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
944
945         if (iface == myDevice->depthStencilBuffer) {
946             FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
947         } else {
948             FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
949         }
950
951     } else {
952         FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
953     }
954
955     unlock_end:
956     This->Flags &= ~SFLAG_LOCKED;
957     memset(&This->lockedRect, 0, sizeof(RECT));
958     return WINED3D_OK;
959 }
960
961 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
962     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
963     WINED3DLOCKED_RECT lock;
964     UINT usage;
965     BITMAPINFO* b_info;
966     HDC ddc;
967     DWORD *masks;
968     HRESULT hr;
969     RGBQUAD col[256];
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] = get_bitmask_red(This->resource.format);
1053                 masks[1] = get_bitmask_green(This->resource.format);
1054                 masks[2] = get_bitmask_blue(This->resource.format);
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
1190     /* Default values: From the surface */
1191     *format = D3DFmt2GLFmt(This->resource.wineD3DDevice,
1192                            This->resource.format);
1193     *internal = D3DFmt2GLIntFmt(This->resource.wineD3DDevice,
1194                                 This->resource.format);
1195     *type = D3DFmt2GLType(This->resource.wineD3DDevice,
1196                           This->resource.format);
1197     *convert = NO_CONVERSION;
1198     *target_bpp = This->bytesPerPixel;
1199
1200     /* Ok, now look if we have to do any conversion */
1201     switch(This->resource.format) {
1202         case WINED3DFMT_P8:
1203             /* ****************
1204                 Paletted Texture
1205                 **************** */
1206             if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) || colorkey_active) {
1207                 *format = GL_RGBA;
1208                 *internal = GL_RGBA;
1209                 *type = GL_UNSIGNED_BYTE;
1210                 *target_bpp = 4;
1211                 if(colorkey_active) {
1212                     *convert = CONVERT_PALETTED;
1213                 } else {
1214                     *convert = CONVERT_PALETTED_CK;
1215                 }
1216             }
1217
1218             break;
1219
1220         case WINED3DFMT_R3G3B2:
1221             /* **********************
1222                 GL_UNSIGNED_BYTE_3_3_2
1223                 ********************** */
1224             if (colorkey_active) {
1225                 /* This texture format will never be used.. So do not care about color keying
1226                     up until the point in time it will be needed :-) */
1227                 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1228             }
1229             break;
1230
1231         case WINED3DFMT_R5G6B5:
1232             if (colorkey_active) {
1233                 *convert = CONVERT_CK_565;
1234                 *format = GL_RGBA;
1235                 *internal = GL_RGBA;
1236                 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1237             }
1238             break;
1239
1240         case WINED3DFMT_R8G8B8:
1241             if (colorkey_active) {
1242                 *convert = CONVERT_CK_RGB24;
1243                 *format = GL_RGBA;
1244                 *internal = GL_RGBA;
1245                 *type = GL_UNSIGNED_INT_8_8_8_8;
1246                 *target_bpp = 4;
1247             }
1248             break;
1249
1250         case WINED3DFMT_X8R8G8B8:
1251             if (colorkey_active) {
1252                 *convert = CONVERT_RGB32_888;
1253                 *format = GL_RGBA;
1254                 *internal = GL_RGBA;
1255                 *type = GL_UNSIGNED_INT_8_8_8_8;
1256             }
1257             break;
1258 #if 0
1259         /* Not sure if we should do color keying on Alpha-Enabled surfaces */
1260         case WINED3DFMT_A4R4G4B4:
1261             if (colorkey_active)
1262             {
1263                 *convert = CONVERT_CK_4444_ARGB;
1264                 *format = GL_RGBA;
1265                 *internal = GL_RGBA;
1266                 *type = GL_UNSIGNED_SHORT_4_4_4_4;
1267             }
1268             break;
1269
1270         case WINED3DFMT_A1R5G5B5:
1271             if (colorkey_active)
1272             {
1273                 *convert = CONVERT_CK_1555;
1274             }
1275
1276         case WINED3DFMT_A8R8G8B8:
1277             if (colorkey_active)
1278             {
1279                 *convert = CONVERT_CK_8888_ARGB;
1280                 *format = GL_RGBA;
1281                 *internal = GL_RGBA;
1282                 *type = GL_UNSIGNED_INT_8_8_8_8;
1283             }
1284             break;
1285 #endif
1286         default:
1287             break;
1288     }
1289
1290     return WINED3D_OK;
1291 }
1292
1293 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, unsigned long len, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) {
1294     TRACE("(%p)->(%p),(%ld,%d,%p)\n", src, dst, len, convert, surf);
1295
1296     switch (convert) {
1297         case NO_CONVERSION:
1298         {
1299             memcpy(dst, src, len * surf->bytesPerPixel);
1300             break;
1301         }
1302         case CONVERT_PALETTED:
1303         case CONVERT_PALETTED_CK:
1304         {
1305             IWineD3DPaletteImpl* pal = surf->palette;
1306             BYTE table[256][4];
1307             unsigned int i;
1308             unsigned int x;
1309
1310             if( pal == NULL) {
1311                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1312             }
1313
1314             if (pal == NULL) {
1315                 /* Still no palette? Use the device's palette */
1316                 /* Get the surface's palette */
1317                 for (i = 0; i < 256; i++) {
1318                     IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice;
1319
1320                     table[i][0] = device->palettes[device->currentPalette][i].peRed;
1321                     table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1322                     table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1323                     if ((convert == CONVERT_PALETTED_CK) &&
1324                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1325                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1326                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1327                           one often used by application to prevent the nice purple borders when bi-linear
1328                           filtering is on */
1329                         table[i][3] = 0x00;
1330                     } else {
1331                         table[i][3] = 0xFF;
1332                     }
1333                 }
1334             } else {
1335                 TRACE("Using surface palette %p\n", pal);
1336                 /* Get the surface's palette */
1337                 for (i = 0; i < 256; i++) {
1338                     table[i][0] = pal->palents[i].peRed;
1339                     table[i][1] = pal->palents[i].peGreen;
1340                     table[i][2] = pal->palents[i].peBlue;
1341                     if ((convert == CONVERT_PALETTED_CK) &&
1342                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1343                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1344                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1345                           one often used by application to prevent the nice purple borders when bi-linear
1346                           filtering is on */
1347                         table[i][3] = 0x00;
1348                     } else {
1349                         table[i][3] = 0xFF;
1350                     }
1351                 }
1352             }
1353
1354             for (x = 0; x < len; x++) {
1355                 BYTE color = *src++;
1356                 *dst++ = table[color][0];
1357                 *dst++ = table[color][1];
1358                 *dst++ = table[color][2];
1359                 *dst++ = table[color][3];
1360             }
1361         }
1362         break;
1363
1364         case CONVERT_CK_565:
1365         {
1366             /* Converting the 565 format in 5551 packed to emulate color-keying.
1367
1368               Note : in all these conversion, it would be best to average the averaging
1369                       pixels to get the color of the pixel that will be color-keyed to
1370                       prevent 'color bleeding'. This will be done later on if ever it is
1371                       too visible.
1372
1373               Note2: when using color-keying + alpha, are the alpha bits part of the
1374                       color-space or not ?
1375             */
1376             unsigned int x;
1377             WORD *Source = (WORD *) src;
1378             WORD *Dest = (WORD *) dst;
1379
1380             TRACE("Color keyed 565\n");
1381
1382             for (x = 0; x < len; x++ ) {
1383                 WORD color = *Source++;
1384                 *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1385                 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1386                     (color > surf->SrcBltCKey.dwColorSpaceHighValue)) {
1387                     *Dest |= 0x0001;
1388                 }
1389                 Dest++;
1390             }
1391         }
1392         break;
1393
1394         case CONVERT_CK_1555:
1395         {
1396             unsigned int x;
1397             WORD *Source = (WORD *) src;
1398             WORD *Dest = (WORD *) dst;
1399
1400             for (x = 0; x < len * sizeof(WORD); x+=sizeof(WORD)) {
1401                 WORD color = *Source++;
1402                 *Dest = (color & 0x7FFF);
1403                 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1404                     (color > surf->SrcBltCKey.dwColorSpaceHighValue))
1405                     *Dest |= (color & 0x8000);
1406                 Dest++;
1407             }
1408         }
1409         break;
1410
1411         case CONVERT_CK_4444_ARGB:
1412         {
1413             /* Move the four Alpha bits... */
1414             unsigned int x;
1415             WORD *Source = (WORD *) src;
1416             WORD *Dest = (WORD *) dst;
1417
1418             for (x = 0; x < len; x++) {
1419                 WORD color = *Source++;
1420                 *dst = (color & 0x0FFF) << 4;
1421                 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1422                     (color > surf->SrcBltCKey.dwColorSpaceHighValue))
1423                     *Dest |= (color & 0xF000) >> 12;
1424                 Dest++;
1425             }
1426         } break;
1427
1428         default:
1429             ERR("Unsupported conversation type %d\n", convert);
1430     }
1431
1432     return WINED3D_OK;
1433 }
1434
1435 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1436     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1437
1438     if (This->Flags & SFLAG_INTEXTURE) {
1439         TRACE("Surface already in texture\n");
1440         return WINED3D_OK;
1441     }
1442     if (!(This->Flags & SFLAG_DIRTY)) {
1443         TRACE("surface isn't dirty\n");
1444         return WINED3D_OK;
1445     }
1446
1447     This->Flags &= ~SFLAG_DIRTY;
1448
1449     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1450     *  These resources are not bound by device size or format restrictions. Because of this,
1451     *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1452     *  However, these resources can always be created, locked, and copied.
1453     */
1454     if (This->resource.pool == WINED3DPOOL_SCRATCH)
1455     {
1456         FIXME("(%p) Operation not supported for scratch textures\n",This);
1457         return WINED3DERR_INVALIDCALL;
1458     }
1459
1460     if (This->Flags & SFLAG_INPBUFFER) {
1461         ENTER_GL();
1462
1463         if (This->glDescription.level != 0)
1464             FIXME("Surface in texture is only supported for level 0\n");
1465         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1466                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1467                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1468                  This->resource.format == WINED3DFMT_DXT5)
1469             FIXME("Format %d not supported\n", This->resource.format);
1470         else {
1471             GLint prevRead;
1472             glGetIntegerv(GL_READ_BUFFER, &prevRead);
1473             vcheckGLcall("glGetIntegerv");
1474             glReadBuffer(GL_BACK);
1475             vcheckGLcall("glReadBuffer");
1476
1477             glCopyTexImage2D(This->glDescription.target,
1478                              This->glDescription.level,
1479                              This->glDescription.glFormatInternal,
1480                              0,
1481                              0,
1482                              This->currentDesc.Width,
1483                              This->currentDesc.Height,
1484                              0);
1485
1486             checkGLcall("glCopyTexImage2D");
1487             glReadBuffer(prevRead);
1488             vcheckGLcall("glReadBuffer");
1489             TRACE("Updating target %d\n", This->glDescription.target);
1490             This->Flags |= SFLAG_INTEXTURE;
1491         }
1492         LEAVE_GL();
1493         return WINED3D_OK;
1494     }
1495
1496     /* TODO: Compressed non-power 2 support */
1497
1498     if (This->resource.format == WINED3DFMT_DXT1 ||
1499         This->resource.format == WINED3DFMT_DXT2 ||
1500         This->resource.format == WINED3DFMT_DXT3 ||
1501         This->resource.format == WINED3DFMT_DXT4 ||
1502         This->resource.format == WINED3DFMT_DXT5) {
1503         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1504             FIXME("Using DXT1/3/5 without advertized support\n");
1505         } else if (This->resource.allocatedMemory) {
1506             TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
1507                   This->glDescription.target,
1508                   This->glDescription.level,
1509                   This->glDescription.glFormatInternal,
1510                   This->currentDesc.Width,
1511                   This->currentDesc.Height,
1512                   0,
1513                   This->resource.size,
1514                   This->resource.allocatedMemory);
1515
1516             ENTER_GL();
1517
1518             GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
1519                                                   This->glDescription.level,
1520                                                   This->glDescription.glFormatInternal,
1521                                                   This->currentDesc.Width,
1522                                                   This->currentDesc.Height,
1523                                                   0,
1524                                                   This->resource.size,
1525                                                   This->resource.allocatedMemory);
1526             checkGLcall("glCommpressedTexImage2D");
1527
1528             LEAVE_GL();
1529
1530             if(!(This->Flags & SFLAG_DONOTFREE)){
1531                 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1532                 This->resource.allocatedMemory = NULL;
1533             }
1534         }
1535     } else {
1536         GLenum format, internal, type;
1537         CONVERT_TYPES convert;
1538         int bpp;
1539         BYTE *mem;
1540
1541         d3dfmt_get_conv(This, TRUE /* We need color keying */, &format, &internal, &type, &convert, &bpp);
1542
1543         if((convert != NO_CONVERSION) &&
1544            This->resource.allocatedMemory) {
1545             int width = This->glRect.right - This->glRect.left;
1546             int height = This->glRect.bottom - This->glRect.top;
1547             int row;
1548
1549             mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
1550             if(!mem) {
1551                 ERR("Out of memory %d, %d!\n", width, height);
1552                 return WINED3DERR_OUTOFVIDEOMEMORY;
1553             }
1554
1555             for(row = This->glRect.top; row < This->glRect.bottom; row++) {
1556                 BYTE *cur = This->resource.allocatedMemory + row * This->pow2Width * This->bytesPerPixel;
1557                 d3dfmt_convert_surface(cur + This->glRect.left * This->bytesPerPixel,
1558                                        mem + row * width * bpp,
1559                                        width,
1560                                        convert,
1561                                        This);
1562             }
1563             This->Flags |= SFLAG_CONVERTED;
1564         } else {
1565             This->Flags &= ~SFLAG_CONVERTED;
1566             mem = This->resource.allocatedMemory;
1567         }
1568
1569        /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
1570         if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE) ) {
1571
1572
1573             TRACE("non power of two support\n");
1574             ENTER_GL();
1575             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,
1576                 This->glDescription.target,
1577                 This->glDescription.level,
1578                 debug_d3dformat(This->resource.format),
1579                 This->glDescription.glFormatInternal,
1580                 This->pow2Width,
1581                 This->pow2Height,
1582                 0,
1583                 This->glDescription.glFormat,
1584                 This->glDescription.glType,
1585                 NULL);
1586
1587             glTexImage2D(This->glDescription.target,
1588                          This->glDescription.level,
1589                          This->glDescription.glFormatInternal,
1590                          This->pow2Width,
1591                          This->pow2Height,
1592                          0/*border*/,
1593                          This->glDescription.glFormat,
1594                          This->glDescription.glType,
1595                          NULL);
1596
1597             checkGLcall("glTexImage2D");
1598             if (This->resource.allocatedMemory != NULL) {
1599                 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
1600                 /* And map the non-power two data into the top left corner */
1601                 glTexSubImage2D(
1602                     This->glDescription.target,
1603                     This->glDescription.level,
1604                     0 /* xoffset */,
1605                     0 /* ysoffset */ ,
1606                     This->currentDesc.Width,
1607                     This->currentDesc.Height,
1608                     This->glDescription.glFormat,
1609                     This->glDescription.glType,
1610                     This->resource.allocatedMemory
1611                 );
1612                 checkGLcall("glTexSubImage2D");
1613             }
1614             LEAVE_GL();
1615
1616         } else {
1617
1618             TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%ld, h=%ld,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1619                 This->glDescription.target,
1620                 This->glDescription.level,
1621                 debug_d3dformat(This->resource.format),
1622                 This->glDescription.glFormatInternal,
1623                 This->glRect.right - This->glRect.left,
1624                 This->glRect.bottom - This->glRect.top,
1625                 0,
1626                 This->glDescription.glFormat,
1627                 This->glDescription.glType,
1628                 mem);
1629
1630             ENTER_GL();
1631
1632             /* OK, create the texture */
1633             glTexImage2D(This->glDescription.target,
1634                         This->glDescription.level,
1635                         internal,
1636                         This->glRect.right - This->glRect.left,
1637                         This->glRect.bottom - This->glRect.top,
1638                         0 /* border */,
1639                         format,
1640                         type,
1641                         mem);
1642
1643             checkGLcall("glTexImage2D");
1644
1645             LEAVE_GL();
1646         }
1647         if(mem != This->resource.allocatedMemory)
1648             HeapFree(GetProcessHeap(), 0, mem);
1649
1650 #if 0
1651         {
1652             static unsigned int gen = 0;
1653             char buffer[4096];
1654             ++gen;
1655             if ((gen % 10) == 0) {
1656                 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1657                 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1658             }
1659             /*
1660              * debugging crash code
1661             if (gen == 250) {
1662               void** test = NULL;
1663               *test = 0;
1664             }
1665             */
1666         }
1667 #endif
1668         if(!(This->Flags & SFLAG_DONOTFREE)){
1669             HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1670             This->resource.allocatedMemory = NULL;
1671         }
1672
1673     }
1674
1675     return WINED3D_OK;
1676 }
1677
1678 #include <errno.h>
1679 #include <stdio.h>
1680 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1681     FILE* f = NULL;
1682     UINT i, y;
1683     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1684     char *allocatedMemory;
1685     char *textureRow;
1686     IWineD3DSwapChain *swapChain = NULL;
1687     int width, height;
1688     GLuint tmpTexture;
1689     DWORD color;
1690     /*FIXME:
1691     Textures my not be stored in ->allocatedgMemory and a GlTexture
1692     so we should lock the surface before saving a snapshot, or at least check that
1693     */
1694     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1695     by calling GetTexImage and in compressed form by calling
1696     GetCompressedTexImageARB.  Queried compressed images can be saved and
1697     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
1698     texture images do not need to be processed by the GL and should
1699     significantly improve texture loading performance relative to uncompressed
1700     images. */
1701
1702 /* Setup the width and height to be the internal texture width and height. */
1703     width  = This->pow2Width;
1704     height = This->pow2Height;
1705 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1706     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1707
1708     if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1709 /* 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 */
1710         GLint prevRead;
1711         ENTER_GL();
1712         FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1713         glEnable(GL_TEXTURE_2D);
1714
1715         glGenTextures(1, &tmpTexture);
1716         glBindTexture(GL_TEXTURE_2D, tmpTexture);
1717
1718         glTexImage2D(GL_TEXTURE_2D,
1719                         0,
1720                         GL_RGBA,
1721                         width,
1722                         height,
1723                         0/*border*/,
1724                         GL_RGBA,
1725                         GL_UNSIGNED_INT_8_8_8_8_REV,
1726                         NULL);
1727
1728         glGetIntegerv(GL_READ_BUFFER, &prevRead);
1729         vcheckGLcall("glGetIntegerv");
1730         glReadBuffer(GL_BACK);
1731         vcheckGLcall("glReadBuffer");
1732         glCopyTexImage2D(GL_TEXTURE_2D,
1733                             0,
1734                             GL_RGBA,
1735                             0,
1736                             0,
1737                             width,
1738                             height,
1739                             0);
1740
1741         checkGLcall("glCopyTexImage2D");
1742         glReadBuffer(prevRead);
1743         LEAVE_GL();
1744
1745     } else { /* bind the real texture */
1746         IWineD3DSurface_PreLoad(iface);
1747     }
1748     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
1749     ENTER_GL();
1750     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1751     glGetTexImage(GL_TEXTURE_2D,
1752                 This->glDescription.level,
1753                 GL_RGBA,
1754                 GL_UNSIGNED_INT_8_8_8_8_REV,
1755                 allocatedMemory);
1756     checkGLcall("glTexImage2D");
1757     if (tmpTexture) {
1758         glBindTexture(GL_TEXTURE_2D, 0);
1759         glDeleteTextures(1, &tmpTexture);
1760     }
1761     LEAVE_GL();
1762
1763     f = fopen(filename, "w+");
1764     if (NULL == f) {
1765         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1766         return WINED3DERR_INVALIDCALL;
1767     }
1768 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1769     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
1770 /* TGA header */
1771     fputc(0,f);
1772     fputc(0,f);
1773     fputc(2,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     fputc(0,f);
1782     fputc(0,f);
1783 /* short width*/
1784     fwrite(&width,2,1,f);
1785 /* short height */
1786     fwrite(&height,2,1,f);
1787 /* format rgba */
1788     fputc(0x20,f);
1789     fputc(0x28,f);
1790 /* raw data */
1791     /* 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*/
1792     if(swapChain)
1793         textureRow = allocatedMemory + (width * (height - 1) *4);
1794     else
1795         textureRow = allocatedMemory;
1796     for (y = 0 ; y < height; y++) {
1797         for (i = 0; i < width;  i++) {
1798             color = *((DWORD*)textureRow);
1799             fputc((color >> 16) & 0xFF, f); /* B */
1800             fputc((color >>  8) & 0xFF, f); /* G */
1801             fputc((color >>  0) & 0xFF, f); /* R */
1802             fputc((color >> 24) & 0xFF, f); /* A */
1803             textureRow += 4;
1804         }
1805         /* take two rows of the pointer to the texture memory */
1806         if(swapChain)
1807             (textureRow-= width << 3);
1808
1809     }
1810     TRACE("Closing file\n");
1811     fclose(f);
1812
1813     if(swapChain) {
1814         IWineD3DSwapChain_Release(swapChain);
1815     }
1816     HeapFree(GetProcessHeap(), 0, allocatedMemory);
1817     return WINED3D_OK;
1818 }
1819
1820 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1821     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1822     This->Flags &= ~SFLAG_DIRTY;
1823     This->dirtyRect.left   = This->currentDesc.Width;
1824     This->dirtyRect.top    = This->currentDesc.Height;
1825     This->dirtyRect.right  = 0;
1826     This->dirtyRect.bottom = 0;
1827     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
1828           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1829     return WINED3D_OK;
1830 }
1831
1832 /**
1833  *   Slightly inefficient way to handle multiple dirty rects but it works :)
1834  */
1835 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1836     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1837     IWineD3DBaseTexture *baseTexture = NULL;
1838     This->Flags |= SFLAG_DIRTY;
1839     if (NULL != pDirtyRect) {
1840         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
1841         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
1842         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
1843         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1844     } else {
1845         This->dirtyRect.left   = 0;
1846         This->dirtyRect.top    = 0;
1847         This->dirtyRect.right  = This->currentDesc.Width;
1848         This->dirtyRect.bottom = This->currentDesc.Height;
1849     }
1850     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
1851           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1852     /* if the container is a basetexture then mark it dirty. */
1853     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
1854         TRACE("Passing to conatiner\n");
1855         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1856         IWineD3DBaseTexture_Release(baseTexture);
1857     }
1858     return WINED3D_OK;
1859 }
1860
1861 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
1862     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1863
1864     TRACE("This %p, container %p\n", This, container);
1865
1866     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
1867
1868     TRACE("Setting container to %p from %p\n", container, This->container);
1869     This->container = container;
1870
1871     return WINED3D_OK;
1872 }
1873
1874 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
1875     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1876
1877     if (This->resource.format != WINED3DFMT_UNKNOWN) {
1878         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
1879         return WINED3DERR_INVALIDCALL;
1880     }
1881
1882     TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
1883     if (format == WINED3DFMT_UNKNOWN) {
1884         This->resource.size = 0;
1885     } else if (format == WINED3DFMT_DXT1) {
1886         /* DXT1 is half byte per pixel */
1887         This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4)) >> 1;
1888
1889     } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
1890                format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
1891         This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4));
1892     } else {
1893         This->resource.size = (This->pow2Width * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * This->pow2Height;
1894     }
1895
1896
1897     /* Setup some glformat defaults */
1898     if (format != WINED3DFMT_UNKNOWN) {
1899         This->glDescription.glFormat         = D3DFmt2GLFmt(This->resource.wineD3DDevice, format);
1900         This->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This->resource.wineD3DDevice, format);
1901         This->glDescription.glType           = D3DFmt2GLType(This->resource.wineD3DDevice, format);
1902     } else {
1903         This->glDescription.glFormat         = 0;
1904         This->glDescription.glFormatInternal = 0;
1905         This->glDescription.glType           = 0;
1906     }
1907
1908     if (format != WINED3DFMT_UNKNOWN) {
1909         This->bytesPerPixel = D3DFmtGetBpp(This->resource.wineD3DDevice, format);
1910         This->pow2Size      = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
1911     } else {
1912         This->bytesPerPixel = 0;
1913         This->pow2Size      = 0;
1914     }
1915
1916     This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
1917
1918     This->resource.format = format;
1919
1920     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);
1921
1922     return WINED3D_OK;
1923 }
1924
1925 /* TODO: replace this function with context management routines */
1926 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
1927     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1928
1929     if(inPBuffer) {
1930         This->Flags |= SFLAG_INPBUFFER;
1931     } else {
1932         This->Flags &= ~SFLAG_INPBUFFER;
1933     }
1934
1935     if(inTexture) {
1936         This->Flags |= SFLAG_INTEXTURE;
1937     } else {
1938         This->Flags &= ~SFLAG_INTEXTURE;
1939     }
1940
1941     return WINED3D_OK;
1942 }
1943
1944 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
1945     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1946     IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
1947     TRACE("(%p)->(%p,%lx)\n", This, override, Flags);
1948
1949     /* Flipping is only supported on RenderTargets */
1950     if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
1951
1952     if(override) {
1953         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
1954          * FIXME("(%p) Target override is not supported by now\n", This);
1955          * Additionally, it isn't really possible to support triple-buffering
1956          * properly on opengl at all
1957          */
1958     }
1959
1960     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
1961     return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
1962 }
1963
1964 /* Not called from the VTable */
1965 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
1966     D3DRECT rect;
1967     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
1968     IWineD3DSwapChainImpl *swapchain = NULL;
1969     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
1970     BOOL SrcOK = TRUE;
1971
1972     TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
1973
1974     /* Get the swapchain. One of the surfaces has to be a primary surface */
1975     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
1976     if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1977     else if(Src) {
1978         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&swapchain);
1979         if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1980         else return WINED3DERR_INVALIDCALL;
1981     } else {
1982         swapchain = NULL;
1983     }
1984
1985     if (DestRect) {
1986         rect.x1 = DestRect->left;
1987         rect.y1 = DestRect->top;
1988         rect.x2 = DestRect->right;
1989         rect.y2 = DestRect->bottom;
1990     } else {
1991         rect.x1 = 0;
1992         rect.y1 = 0;
1993         rect.x2 = This->currentDesc.Width;
1994         rect.y2 = This->currentDesc.Height;
1995     }
1996
1997     /* Half-life does a Blt from the back buffer to the front buffer,
1998      * Full surface size, no flags... Use present instead
1999      */
2000     if(Src)
2001     {
2002         /* First, check if we can do a Flip */
2003
2004         /* Check rects - IWineD3DDevice_Present doesn't handle them */
2005         if( SrcRect ) {
2006             if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
2007                 (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
2008                 SrcOK = TRUE;
2009             }
2010         } else {
2011             SrcOK = TRUE;
2012         }
2013
2014         /* Check the Destination rect and the surface sizes */
2015         if(SrcOK &&
2016            (rect.x1 == 0) && (rect.y1 == 0) &&
2017            (rect.x2 ==  This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
2018            (This->currentDesc.Width == Src->currentDesc.Width) &&
2019            (This->currentDesc.Height == Src->currentDesc.Height)) {
2020             /* These flags are unimportant for the flag check, remove them */
2021
2022             if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
2023                 if( swapchain->backBuffer && ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer[0]) ) {
2024
2025                     D3DSWAPEFFECT orig_swap = swapchain->presentParms.SwapEffect;
2026
2027                     /* The idea behind this is that a glReadPixels and a glDrawPixels call
2028                      * take very long, while a flip is fast.
2029                      * This applies to Half-Life, which does such Blts every time it finished
2030                      * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2031                      * menu. This is also used by all apps when they do windowed rendering
2032                      *
2033                      * The problem is that flipping is not really the same as copying. After a
2034                      * Blt the front buffer is a copy of the back buffer, and the back buffer is
2035                      * untouched. Therefore it's necessary to override the swap effect
2036                      * and to set it back after the flip.
2037                      */
2038
2039                     swapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
2040
2041                     TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2042                     IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
2043                                             NULL, NULL, 0, NULL);
2044
2045                     swapchain->presentParms.SwapEffect = orig_swap;
2046
2047                     return WINED3D_OK;
2048                 }
2049             }
2050         }
2051
2052         /* Blt from texture to rendertarget? */
2053         if( ( ( (IWineD3DSurface *) This == swapchain->frontBuffer) ||
2054               ( swapchain->backBuffer && (IWineD3DSurface *) This == swapchain->backBuffer[0]) )
2055               &&
2056               ( ( (IWineD3DSurface *) Src != swapchain->frontBuffer) &&
2057                 ( swapchain->backBuffer && (IWineD3DSurface *) Src != swapchain->backBuffer[0]) ) ) {
2058             float glTexCoord[4];
2059             DWORD oldCKey;
2060             GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha;
2061             GLint alphafunc;
2062             GLclampf alpharef;
2063             GLint oldStencil;
2064             RECT SourceRectangle;
2065             GLint oldDraw;
2066
2067             TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
2068
2069             if(SrcRect) {
2070                 SourceRectangle.left = SrcRect->left;
2071                 SourceRectangle.right = SrcRect->right;
2072                 SourceRectangle.top = SrcRect->top;
2073                 SourceRectangle.bottom = SrcRect->bottom;
2074             } else {
2075                 SourceRectangle.left = 0;
2076                 SourceRectangle.right = Src->currentDesc.Width;
2077                 SourceRectangle.top = 0;
2078                 SourceRectangle.bottom = Src->currentDesc.Height;
2079             }
2080
2081             if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
2082                 /* Fall back to software */
2083                 WARN("(%p) Source texture area (%ld,%ld)-(%ld,%ld) is too big\n", Src,
2084                      SourceRectangle.left, SourceRectangle.top,
2085                      SourceRectangle.right, SourceRectangle.bottom);
2086                 return WINED3DERR_INVALIDCALL;
2087             }
2088
2089             /* Color keying: Check if we have to do a color keyed blt,
2090              * and if not check if a color key is activated.
2091              */
2092             oldCKey = Src->CKeyFlags;
2093             if(!(Flags & DDBLT_KEYSRC) && 
2094                Src->CKeyFlags & DDSD_CKSRCBLT) {
2095                 /* Ok, the surface has a color key, but we shall not use it - 
2096                  * Deactivate it for now and dirtify the surface to reload it
2097                  */
2098                 Src->CKeyFlags &= ~DDSD_CKSRCBLT;
2099                 Src->Flags |= SFLAG_DIRTY;
2100             }
2101
2102             /* Now load the surface */
2103             IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
2104
2105             ENTER_GL();
2106
2107             /* Save all the old stuff until we have a proper opengl state manager */
2108             oldLight = glIsEnabled(GL_LIGHTING);
2109             oldFog = glIsEnabled(GL_FOG);
2110             oldDepth = glIsEnabled(GL_DEPTH_TEST);
2111             oldBlend = glIsEnabled(GL_BLEND);
2112             oldCull = glIsEnabled(GL_CULL_FACE);
2113             oldAlpha = glIsEnabled(GL_ALPHA_TEST);
2114             oldStencil = glIsEnabled(GL_STENCIL_TEST);
2115
2116             glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphafunc);
2117             checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC");
2118             glGetFloatv(GL_ALPHA_TEST_REF, &alpharef);
2119             checkGLcall("glGetFloatv GL_ALPHA_TEST_REF");
2120
2121             glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
2122             if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer) {
2123                 TRACE("Drawing to front buffer\n");
2124                 glDrawBuffer(GL_FRONT);
2125                 checkGLcall("glDrawBuffer GL_FRONT");
2126             }
2127
2128             /* Unbind the old texture */
2129             glBindTexture(GL_TEXTURE_2D, 0);
2130
2131             if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2132             /* We use texture unit 0 for blts */
2133                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
2134                 checkGLcall("glActiveTextureARB");
2135             } else {
2136                 WARN("Multi-texturing is unsupported in the local OpenGL implementation\n");
2137             }
2138
2139             /* Disable some fancy graphics effects */
2140             glDisable(GL_LIGHTING);
2141             checkGLcall("glDisable GL_LIGHTING");
2142             glDisable(GL_DEPTH_TEST);
2143             checkGLcall("glDisable GL_DEPTH_TEST");
2144             glDisable(GL_FOG);
2145             checkGLcall("glDisable GL_FOG");
2146             glDisable(GL_BLEND);
2147             checkGLcall("glDisable GL_BLEND");
2148             glDisable(GL_CULL_FACE);
2149             checkGLcall("glDisable GL_CULL_FACE");
2150             glDisable(GL_STENCIL_TEST);
2151             checkGLcall("glDisable GL_STENCIL_TEST");
2152
2153             /* Ok, we need 2d textures, but not 1D or 3D */
2154             glDisable(GL_TEXTURE_1D);
2155             checkGLcall("glDisable GL_TEXTURE_1D");
2156             glEnable(GL_TEXTURE_2D);
2157             checkGLcall("glEnable GL_TEXTURE_2D");
2158             glDisable(GL_TEXTURE_3D);
2159             checkGLcall("glDisable GL_TEXTURE_3D");
2160
2161             /* Bind the texture */
2162             glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2163             checkGLcall("glBindTexture");
2164
2165             glEnable(GL_SCISSOR_TEST);
2166
2167             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2168
2169             /* No filtering for blts */
2170             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
2171                             GL_NEAREST);
2172             checkGLcall("glTexParameteri");
2173             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
2174                             GL_NEAREST);
2175             checkGLcall("glTexParameteri");
2176             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2177             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2178             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2179             checkGLcall("glTexEnvi");
2180
2181             /* This is for color keying */
2182             if(Flags & DDBLT_KEYSRC) {
2183                 glEnable(GL_ALPHA_TEST);
2184                 checkGLcall("glEnable GL_ALPHA_TEST");
2185                 glAlphaFunc(GL_NOTEQUAL, 0.0);
2186                 checkGLcall("glAlphaFunc\n");
2187             } else {
2188                 glDisable(GL_ALPHA_TEST);
2189                 checkGLcall("glDisable GL_ALPHA_TEST");
2190             }
2191
2192             /* Draw a textured quad
2193              */
2194             d3ddevice_set_ortho(This->resource.wineD3DDevice);
2195
2196             glBegin(GL_QUADS);
2197
2198             glColor3d(1.0f, 1.0f, 1.0f);
2199             glTexCoord2f(glTexCoord[0], glTexCoord[2]);
2200             glVertex3f(rect.x1,
2201                        rect.y1,
2202                        0.0);
2203
2204             glTexCoord2f(glTexCoord[0], glTexCoord[3]);
2205             glVertex3f(rect.x1, rect.y2, 0.0);
2206
2207             glTexCoord2f(glTexCoord[1], glTexCoord[3]);
2208             glVertex3f(rect.x2,
2209                        rect.y2,
2210                        0.0);
2211
2212             glTexCoord2f(glTexCoord[1], glTexCoord[2]);
2213             glVertex3f(rect.x2,
2214                        rect.y1,
2215                        0.0);
2216             glEnd();
2217             checkGLcall("glEnd");
2218
2219             /* Unbind the texture */
2220             glBindTexture(GL_TEXTURE_2D, 0);
2221             checkGLcall("glEnable glBindTexture");
2222
2223             /* Restore the old settings */
2224             if(oldLight) {
2225                 glEnable(GL_LIGHTING);
2226                 checkGLcall("glEnable GL_LIGHTING");
2227             }
2228             if(oldFog) {
2229                 glEnable(GL_FOG);
2230                 checkGLcall("glEnable GL_FOG");
2231             }
2232             if(oldDepth) {
2233                 glEnable(GL_DEPTH_TEST);
2234                 checkGLcall("glEnable GL_DEPTH_TEST");
2235             }
2236             if(oldBlend) {
2237                 glEnable(GL_BLEND);
2238                 checkGLcall("glEnable GL_BLEND");
2239             }
2240             if(oldCull) {
2241                 glEnable(GL_CULL_FACE);
2242                 checkGLcall("glEnable GL_CULL_FACE");
2243             }
2244             if(oldStencil) {
2245                 glEnable(GL_STENCIL_TEST);
2246                 checkGLcall("glEnable GL_STENCIL_TEST");
2247             }
2248             if(!oldAlpha) {
2249                 glDisable(GL_ALPHA_TEST);
2250                 checkGLcall("glDisable GL_ALPHA_TEST");
2251             } else {
2252                 glEnable(GL_ALPHA_TEST);
2253                 checkGLcall("glEnable GL_ALPHA_TEST");
2254             }
2255
2256             glAlphaFunc(alphafunc, alpharef);
2257             checkGLcall("glAlphaFunc\n");
2258
2259             if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer && oldDraw == GL_BACK) {
2260                 glDrawBuffer(oldDraw);
2261             }
2262
2263             /* Restore the color key */
2264             if(oldCKey != Src->CKeyFlags) {
2265                 Src->CKeyFlags = oldCKey;
2266                 Src->Flags |= SFLAG_DIRTY;
2267             }
2268
2269             LEAVE_GL();
2270
2271             /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2272             This->Flags |= SFLAG_GLDIRTY;
2273
2274             return WINED3D_OK;
2275         }
2276
2277
2278         /* Blt from rendertarget to texture? */
2279         if( (SrcSurface == swapchain->frontBuffer) ||
2280             (swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) ) {
2281             if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
2282                 ( swapchain->backBuffer && (IWineD3DSurface *) This != swapchain->backBuffer[0]) ) {
2283                 UINT row;
2284                 D3DRECT srect;
2285                 float xrel, yrel;
2286
2287                 TRACE("Blt from rendertarget to texture\n");
2288
2289                 /* Call preload for the surface to make sure it isn't dirty */
2290                 IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2291
2292                 if(SrcRect) {
2293                     srect.x1 = SrcRect->left;
2294                     srect.y1 = SrcRect->top;
2295                     srect.x2 = SrcRect->right;
2296                     srect.y2 = SrcRect->bottom;
2297                 } else {
2298                     srect.x1 = 0;
2299                     srect.y1 = 0;
2300                     srect.x2 = Src->currentDesc.Width;
2301                     srect.y2 = Src->currentDesc.Height;
2302                 }
2303
2304                 ENTER_GL();
2305
2306                 /* Bind the target texture */
2307                 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2308                 checkGLcall("glBindTexture");
2309                 if(swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) {
2310                     glReadBuffer(GL_BACK);
2311                 } else {
2312                     glReadBuffer(GL_FRONT);
2313                 }
2314                 checkGLcall("glReadBuffer");
2315
2316                 xrel = (float) (srect.x2 - srect.x1) / (float) (rect.x2 - rect.x1);
2317                 yrel = (float) (srect.y2 - srect.y1) / (float) (rect.y2 - rect.y1);
2318
2319                 /* I have to process this row by row to swap the image,
2320                  * otherwise it would be upside down, so streching in y direction
2321                  * doesn't cost extra time
2322                  *
2323                  * However, streching in x direction can be avoided if not necessary
2324                  */
2325                 for(row = rect.y1; row < rect.y2; row++) {
2326                     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2327                         /* Well, that stuff works, but it's very slow.
2328                          * find a better way instead
2329                          */
2330                         UINT col;
2331                         for(col = rect.x1; col < rect.x2; col++) {
2332                             glCopyTexSubImage2D(GL_TEXTURE_2D,
2333                                                 0, /* level */
2334                                                 rect.x1 + col, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2335                                                 srect.x1 + col * xrel, Src->currentDesc.Height - srect.y2 + row * yrel,
2336                                                 1, 1);
2337                         }
2338                     } else {
2339                         glCopyTexSubImage2D(GL_TEXTURE_2D,
2340                                             0, /* level */
2341                                             rect.x1, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2342                                             srect.x1, Src->currentDesc.Height - srect.y2 + row * yrel,
2343                                             rect.x2, 1);
2344                     }
2345                 }
2346
2347                 vcheckGLcall("glCopyTexSubImage2D");
2348                 LEAVE_GL();
2349
2350                 if(!(This->Flags & SFLAG_DONOTFREE)) {
2351                     HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2352                     This->resource.allocatedMemory = NULL;
2353                 } else {
2354                     This->Flags |= SFLAG_GLDIRTY;
2355                 }
2356
2357                 return WINED3D_OK;
2358             }
2359         }
2360     }
2361
2362     if (Flags & DDBLT_COLORFILL) {
2363         /* This is easy to handle for the D3D Device... */
2364         DWORD color;
2365         IWineD3DSwapChainImpl *implSwapChain;
2366         GLint  prev_draw;
2367
2368         TRACE("Colorfill\n");
2369
2370         /* The color as given in the Blt function is in the format of the frame-buffer...
2371          * 'clear' expect it in ARGB format => we need to do some conversion :-)
2372          */
2373         if (This->resource.format == WINED3DFMT_P8) {
2374             if (This->palette) {
2375                 color = ((0xFF000000) |
2376                           (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2377                           (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2378                           (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2379             } else {
2380                 color = 0xFF000000;
2381             }
2382         }
2383         else if (This->resource.format == WINED3DFMT_R5G6B5) {
2384             if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2385                 color = 0xFFFFFFFF;
2386             } else {
2387                 color = ((0xFF000000) |
2388                           ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2389                           ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2390                           ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2391             }
2392         }
2393         else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2394                   (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2395             color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2396         }
2397         else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2398             color = DDBltFx->u5.dwFillColor;
2399         }
2400         else {
2401             ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2402             return WINED3DERR_INVALIDCALL;
2403         }
2404
2405         /* Are we drawing to the Front buffer or the back buffer? */
2406         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2407         vcheckGLcall("glIntegerv");
2408
2409         TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2410         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
2411         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
2412         if(implSwapChain->backBuffer && This == (IWineD3DSurfaceImpl*) implSwapChain->backBuffer[0]) {
2413             glDrawBuffer(GL_BACK);
2414             checkGLcall("glDrawBuffer(GL_BACK)");
2415         }
2416         else if (This == (IWineD3DSurfaceImpl*) implSwapChain->frontBuffer) {
2417             glDrawBuffer(GL_FRONT);
2418             checkGLcall("glDrawBuffer(GL_FRONT)");
2419         }
2420         else {
2421             ERR("Wrong surface type for BLT override(not on swapchain) !\n");
2422             return WINED3DERR_INVALIDCALL;
2423         }
2424
2425         TRACE("(%p) executing Render Target override, color = %lx\n", This, color);
2426
2427         IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2428                               1 /* Number of rectangles */,
2429                               &rect,
2430                               D3DCLEAR_TARGET,
2431                               color,
2432                               0.0 /* Z */,
2433                               0 /* Stencil */);
2434
2435         /* Restore the original draw buffer */
2436         glDrawBuffer(prev_draw);
2437         vcheckGLcall("glDrawBuffer");
2438
2439         return WINED3D_OK;
2440     }
2441
2442     /* Default: Fall back to the generic blt */
2443     return WINED3DERR_INVALIDCALL;
2444 }
2445
2446 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2447     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2448     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2449     TRACE("(%p)->(%p,%p,%p,%lx,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2450     TRACE("(%p): Usage is %08lx\n", This, This->resource.usage);
2451
2452     /* Special cases for RenderTargets */
2453     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2454         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2455         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2456     }
2457
2458     /* For the rest call the X11 surface implementation.
2459      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2460      * other Blts are rather rare
2461      */
2462     return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2463 }
2464
2465 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2466     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2467     TRACE("(%p)->(%lx)\n", This, Flags);
2468
2469     switch (Flags)
2470     {
2471     case DDGBS_CANBLT:
2472     case DDGBS_ISBLTDONE:
2473         return DD_OK;
2474
2475     default:
2476         return DDERR_INVALIDPARAMS;
2477     }
2478 }
2479
2480 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2481     /* XXX: DDERR_INVALIDSURFACETYPE */
2482
2483     TRACE("(%p)->(%08lx)\n",iface,Flags);
2484     switch (Flags) {
2485     case DDGFS_CANFLIP:
2486     case DDGFS_ISFLIPDONE:
2487         return DD_OK;
2488
2489     default:
2490         return DDERR_INVALIDPARAMS;
2491     }
2492 }
2493
2494 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2495     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2496     TRACE("(%p)\n", This);
2497
2498     return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2499 }
2500
2501 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2502     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2503     TRACE("(%p)\n", This);
2504
2505     /* So far we don't lose anything :) */
2506     This->Flags &= ~SFLAG_LOST;
2507     return WINED3D_OK;
2508 }
2509
2510 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2511     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2512     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2513     TRACE("(%p)->(%ld, %ld, %p, %p, %08lx\n", iface, dstx, dsty, Source, rsrc, trans);
2514
2515     /* Special cases for RenderTargets */
2516     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2517         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2518
2519         RECT SrcRect, DstRect;
2520
2521         if(rsrc) {
2522             SrcRect.left = rsrc->left;
2523             SrcRect.top= rsrc->top;
2524             SrcRect.bottom = rsrc->bottom;
2525             SrcRect.right = rsrc->right;
2526         } else {
2527             SrcRect.left = 0;
2528             SrcRect.top = 0;
2529             SrcRect.right = srcImpl->currentDesc.Width;
2530             SrcRect.bottom = srcImpl->currentDesc.Height;
2531         }
2532
2533         DstRect.left = dstx;
2534         DstRect.top=dsty;
2535         DstRect.right = dstx + SrcRect.right - SrcRect.left;
2536         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2537
2538         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, 0, NULL) == WINED3D_OK) return WINED3D_OK;
2539     }
2540
2541
2542     return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2543 }
2544
2545 HRESULT WINAPI IWineD3DSurfaceImpl_SetPixelFormat(IWineD3DSurface *iface, WINED3DFORMAT Format, BYTE *Surface, DWORD Size) {
2546     FIXME("This is unimplemented for now(d3d7 merge)\n");
2547     return WINED3DERR_INVALIDCALL;
2548 }
2549
2550 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2551     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2552     TRACE("(%p)->(%p)\n", This, Pal);
2553
2554     *Pal = (IWineD3DPalette *) This->palette;
2555     return DD_OK;
2556 }
2557
2558 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2559     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2560     RGBQUAD col[256];
2561     IWineD3DPaletteImpl *pal = This->palette;
2562     unsigned int n;
2563     TRACE("(%p)\n", This);
2564
2565     if(This->resource.format == WINED3DFMT_P8 ||
2566        This->resource.format == WINED3DFMT_A8P8)
2567     {
2568         TRACE("Dirtifying surface\n");
2569         This->Flags |= SFLAG_DIRTY;
2570     }
2571
2572     if(This->Flags & SFLAG_DIBSECTION) {
2573         TRACE("(%p): Updating the hdc's palette\n", This);
2574         for (n=0; n<256; n++) {
2575             if(pal) {
2576                 col[n].rgbRed   = pal->palents[n].peRed;
2577                 col[n].rgbGreen = pal->palents[n].peGreen;
2578                 col[n].rgbBlue  = pal->palents[n].peBlue;
2579             } else {
2580                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2581                 /* Use the default device palette */
2582                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
2583                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
2584                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
2585             }
2586             col[n].rgbReserved = 0;
2587         }
2588         SetDIBColorTable(This->hDC, 0, 256, col);
2589     }
2590
2591     return WINED3D_OK;
2592 }
2593
2594 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
2595     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2596     IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
2597     TRACE("(%p)->(%p)\n", This, Pal);
2598
2599     if(This->palette != NULL) 
2600         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
2601             This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
2602
2603     if(PalImpl != NULL) {
2604         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2605             /* Set the device's main palette if the palette
2606              * wasn't a primary palette before
2607              */
2608             if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
2609                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2610                 unsigned int i;
2611
2612                 for(i=0; i < 256; i++) {
2613                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
2614                 }
2615             }
2616
2617             (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
2618         }
2619     }
2620     This->palette = PalImpl;
2621
2622     return IWineD3DSurface_RealizePalette(iface);
2623 }
2624
2625 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
2626     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2627     BOOL dirtify = FALSE;
2628     TRACE("(%p)->(%08lx,%p)\n", This, Flags, CKey);
2629
2630     if ((Flags & DDCKEY_COLORSPACE) != 0) {
2631         FIXME(" colorkey value not supported (%08lx) !\n", Flags);
2632         return DDERR_INVALIDPARAMS;
2633     }
2634
2635     /* Dirtify the surface, but only if a key was changed */
2636     if(CKey) {
2637         switch (Flags & ~DDCKEY_COLORSPACE) {
2638             case DDCKEY_DESTBLT:
2639                 if(!(This->CKeyFlags & DDSD_CKDESTBLT)) {
2640                     dirtify = TRUE;
2641                 } else {
2642                     dirtify = memcmp(&This->DestBltCKey, CKey, sizeof(*CKey) ) != 0;
2643                 }
2644                 This->DestBltCKey = *CKey;
2645                 This->CKeyFlags |= DDSD_CKDESTBLT;
2646                 break;
2647
2648             case DDCKEY_DESTOVERLAY:
2649                 if(!(This->CKeyFlags & DDSD_CKDESTOVERLAY)) {
2650                     dirtify = TRUE;
2651                 } else {
2652                     dirtify = memcmp(&This->DestOverlayCKey, CKey, sizeof(*CKey)) != 0;
2653                 }
2654                 This->DestOverlayCKey = *CKey;
2655                 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
2656                 break;
2657
2658             case DDCKEY_SRCOVERLAY:
2659                 if(!(This->CKeyFlags & DDSD_CKSRCOVERLAY)) {
2660                     dirtify = TRUE;
2661                 } else {
2662                     dirtify = memcmp(&This->SrcOverlayCKey, CKey, sizeof(*CKey)) != 0;
2663                 }
2664                 This->SrcOverlayCKey = *CKey;
2665                 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
2666                 break;
2667
2668             case DDCKEY_SRCBLT:
2669                 if(!(This->CKeyFlags & DDSD_CKSRCBLT)) {
2670                     dirtify = TRUE;
2671                 } else {
2672                     dirtify = memcmp(&This->SrcBltCKey, CKey, sizeof(*CKey)) != 0;
2673                 }
2674                 This->SrcBltCKey = *CKey;
2675                 This->CKeyFlags |= DDSD_CKSRCBLT;
2676                 break;
2677         }
2678     }
2679     else {
2680         switch (Flags & ~DDCKEY_COLORSPACE) {
2681             case DDCKEY_DESTBLT:
2682                 dirtify = This->CKeyFlags & DDSD_CKDESTBLT;
2683                 This->CKeyFlags &= ~DDSD_CKDESTBLT;
2684                 break;
2685
2686             case DDCKEY_DESTOVERLAY:
2687                 dirtify = This->CKeyFlags & DDSD_CKDESTOVERLAY;
2688                 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
2689                 break;
2690
2691             case DDCKEY_SRCOVERLAY:
2692                 dirtify = This->CKeyFlags & DDSD_CKSRCOVERLAY;
2693                 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
2694                 break;
2695
2696             case DDCKEY_SRCBLT:
2697                 dirtify = This->CKeyFlags & DDSD_CKSRCBLT;
2698                 This->CKeyFlags &= ~DDSD_CKSRCBLT;
2699                 break;
2700         }
2701     }
2702
2703     if(dirtify) {
2704         TRACE("Color key changed, dirtifying surface\n");
2705         This->Flags |= SFLAG_DIRTY;
2706     }
2707
2708     return WINED3D_OK;
2709 }
2710
2711 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
2712     /** Check against the maximum texture sizes supported by the video card **/
2713     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2714
2715     TRACE("%p\n", This);
2716     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
2717         /* one of three options
2718         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)
2719         2: Set the texture to the maxium size (bad idea)
2720         3:    WARN and return WINED3DERR_NOTAVAILABLE;
2721         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.
2722         */
2723         WARN("(%p) Creating an oversized surface\n", This);
2724         This->Flags |= SFLAG_OVERSIZE;
2725
2726         /* This will be initialized on the first blt */
2727         This->glRect.left = 0;
2728         This->glRect.top = 0;
2729         This->glRect.right = 0;
2730         This->glRect.bottom = 0;
2731     } else {
2732         /* No oversize, gl rect is the full texture size */
2733         This->Flags &= ~SFLAG_OVERSIZE;
2734         This->glRect.left = 0;
2735         This->glRect.top = 0;
2736         This->glRect.right = This->pow2Width;
2737         This->glRect.bottom = This->pow2Height;
2738     }
2739
2740     return WINED3D_OK;
2741 }
2742
2743 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
2744     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2745     DWORD ret;
2746     TRACE("(%p)\n", This);
2747
2748     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
2749          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
2750           ie pitch = (width/4) * bytes per block                                  */
2751     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
2752         ret = (This->currentDesc.Width >> 2) << 3;
2753     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
2754              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
2755         ret = (This->currentDesc.Width >> 2) << 4;
2756     else {
2757         if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2758             /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
2759             ret = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
2760         } else {
2761             ret = This->bytesPerPixel * This->pow2Width;
2762         }
2763     }
2764     TRACE("(%p) Returning %ld\n", This, ret);
2765     return ret;
2766 }
2767
2768 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
2769 {
2770     /* IUnknown */
2771     IWineD3DSurfaceImpl_QueryInterface,
2772     IWineD3DSurfaceImpl_AddRef,
2773     IWineD3DSurfaceImpl_Release,
2774     /* IWineD3DResource */
2775     IWineD3DSurfaceImpl_GetParent,
2776     IWineD3DSurfaceImpl_GetDevice,
2777     IWineD3DSurfaceImpl_SetPrivateData,
2778     IWineD3DSurfaceImpl_GetPrivateData,
2779     IWineD3DSurfaceImpl_FreePrivateData,
2780     IWineD3DSurfaceImpl_SetPriority,
2781     IWineD3DSurfaceImpl_GetPriority,
2782     IWineD3DSurfaceImpl_PreLoad,
2783     IWineD3DSurfaceImpl_GetType,
2784     /* IWineD3DSurface */
2785     IWineD3DSurfaceImpl_GetContainerParent,
2786     IWineD3DSurfaceImpl_GetContainer,
2787     IWineD3DSurfaceImpl_GetDesc,
2788     IWineD3DSurfaceImpl_LockRect,
2789     IWineD3DSurfaceImpl_UnlockRect,
2790     IWineD3DSurfaceImpl_GetDC,
2791     IWineD3DSurfaceImpl_ReleaseDC,
2792     IWineD3DSurfaceImpl_Flip,
2793     IWineD3DSurfaceImpl_Blt,
2794     IWineD3DSurfaceImpl_GetBltStatus,
2795     IWineD3DSurfaceImpl_GetFlipStatus,
2796     IWineD3DSurfaceImpl_IsLost,
2797     IWineD3DSurfaceImpl_Restore,
2798     IWineD3DSurfaceImpl_BltFast,
2799     IWineD3DSurfaceImpl_SetPixelFormat,
2800     IWineD3DSurfaceImpl_GetPalette,
2801     IWineD3DSurfaceImpl_SetPalette,
2802     IWineD3DSurfaceImpl_RealizePalette,
2803     IWineD3DSurfaceImpl_SetColorKey,
2804     IWineD3DSurfaceImpl_GetPitch,
2805     /* Internal use: */
2806     IWineD3DSurfaceImpl_CleanDirtyRect,
2807     IWineD3DSurfaceImpl_AddDirtyRect,
2808     IWineD3DSurfaceImpl_LoadTexture,
2809     IWineD3DSurfaceImpl_SaveSnapshot,
2810     IWineD3DSurfaceImpl_SetContainer,
2811     IWineD3DSurfaceImpl_SetPBufferState,
2812     IWineD3DSurfaceImpl_SetGlTextureDesc,
2813     IWineD3DSurfaceImpl_GetGlDesc,
2814     IWineD3DSurfaceImpl_GetData,
2815     IWineD3DSurfaceImpl_SetFormat,
2816     IWineD3DSurfaceImpl_PrivateSetup
2817 };