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