wined3d: Add support for shader model 3.0 I/O registers.
[wine] / dlls / wined3d / surface.c
1 /*
2  * IWineD3DSurface Implementation
3  *
4  * Copyright 1998 Lionel Ulmer
5  * Copyright 2000-2001 TransGaming Technologies Inc.
6  * Copyright 2002-2005 Jason Edmeades
7  * Copyright 2002-2003 Raphael Junqueira
8  * Copyright 2004 Christian Costa
9  * Copyright 2005 Oliver Stieber
10  * Copyright 2006 Stefan Dösinger for CodeWeavers
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include "wine/port.h"
29 #include "wined3d_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
33
34 /* *******************************************
35    IWineD3DSurface IUnknown parts follow
36    ******************************************* */
37 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
38 {
39     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
40     /* Warn ,but be nice about things */
41     TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
42     if (riid == NULL) {
43         ERR("Probably FIXME: Calling query interface with NULL riid\n");
44     }
45     if (IsEqualGUID(riid, &IID_IUnknown)
46         || IsEqualGUID(riid, &IID_IWineD3DBase)
47         || IsEqualGUID(riid, &IID_IWineD3DResource)
48         || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
49         IUnknown_AddRef((IUnknown*)iface);
50         *ppobj = This;
51         return S_OK;
52     }
53     *ppobj = NULL;
54     return E_NOINTERFACE;
55 }
56
57 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
58     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
59     ULONG ref = InterlockedIncrement(&This->resource.ref);
60     TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
61     return ref;
62 }
63
64 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
65     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
66     ULONG ref = InterlockedDecrement(&This->resource.ref);
67     TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
68     if (ref == 0) {
69         IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
70         TRACE("(%p) : cleaning up\n", This);
71         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
72             ENTER_GL();
73             TRACE("Deleting texture %d\n", This->glDescription.textureName);
74             glDeleteTextures(1, &This->glDescription.textureName);
75             LEAVE_GL();
76         }
77
78         if(This->Flags & SFLAG_DIBSECTION) {
79             /* Release the DC */
80             SelectObject(This->hDC, This->dib.holdbitmap);
81             DeleteDC(This->hDC);
82             /* Release the DIB section */
83             DeleteObject(This->dib.DIBsection);
84             This->dib.bitmap_data = NULL;
85             This->resource.allocatedMemory = NULL;
86         }
87
88         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
89         if(iface == device->ddraw_primary)
90             device->ddraw_primary = NULL;
91
92         TRACE("(%p) Released\n", This);
93         HeapFree(GetProcessHeap(), 0, This);
94
95     }
96     return ref;
97 }
98
99 /* ****************************************************
100    IWineD3DSurface IWineD3DResource parts follow
101    **************************************************** */
102 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
103     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
104 }
105
106 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
107     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
108 }
109
110 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
111     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
112 }
113
114 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
115     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
116 }
117
118 DWORD   WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
119     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
120 }
121
122 DWORD   WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
123     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
124 }
125
126 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
127     /* TODO: re-write the way textures and managed,
128     *  use a 'opengl context manager' to manage RenderTarget surfaces
129     ** *********************************************************/
130
131     /* TODO: check for locks */
132     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
133     IWineD3DBaseTexture *baseTexture = NULL;
134     TRACE("(%p)Checking to see if the container is a base texture\n", This);
135     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
136         TRACE("Passing to conatiner\n");
137         IWineD3DBaseTexture_PreLoad(baseTexture);
138         IWineD3DBaseTexture_Release(baseTexture);
139     } else {
140     TRACE("(%p) : About to load surface\n", This);
141     ENTER_GL();
142 #if 0 /* TODO: context manager support */
143      IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
144 #endif
145     glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
146     if (This->glDescription.level == 0 &&  This->glDescription.textureName == 0) {
147           glGenTextures(1, &This->glDescription.textureName);
148           checkGLcall("glGenTextures");
149           TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
150           glBindTexture(This->glDescription.target, This->glDescription.textureName);
151           checkGLcall("glBindTexture");
152           IWineD3DSurface_LoadTexture(iface);
153           /* This is where we should be reducing the amount of GLMemoryUsed */
154     } else {
155         if (This->glDescription.level == 0) {
156           glBindTexture(This->glDescription.target, This->glDescription.textureName);
157           checkGLcall("glBindTexture");
158           IWineD3DSurface_LoadTexture(iface);
159         } else  if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
160             /* assume this is a coding error not a real error for now */
161             FIXME("Mipmap surface has a glTexture bound to it!\n");
162         }
163     }
164     if (This->resource.pool == WINED3DPOOL_DEFAULT) {
165        /* Tell opengl to try and keep this texture in video ram (well mostly) */
166        GLclampf tmp;
167        tmp = 0.9f;
168         glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
169     }
170     /* TODO: disable texture support, if it wastn't enabled when we entered. */
171 #if 0 /* TODO: context manager support */
172      IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
173               /* we don't care when the state is disabled(if atall) */);
174 #endif
175     LEAVE_GL();
176     }
177     return;
178 }
179
180 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
181     TRACE("(%p) : calling resourceimpl_GetType\n", iface);
182     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
183 }
184
185 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
186     TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
187     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
188 }
189
190 /* ******************************************************
191    IWineD3DSurface IWineD3DSurface parts follow
192    ****************************************************** */
193
194 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
195     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
196
197     TRACE("(%p) : ppContainerParent %p)\n", This, ppContainerParent);
198
199     if (!ppContainerParent) {
200         ERR("(%p) : Called without a valid ppContainerParent.\n", This);
201     }
202
203     if (This->container) {
204         IWineD3DBase_GetParent(This->container, ppContainerParent);
205         if (!ppContainerParent) {
206             /* WineD3D objects should always have a parent */
207             ERR("(%p) : GetParent returned NULL\n", This);
208         }
209         IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */
210     } else {
211         *ppContainerParent = NULL;
212     }
213
214     return WINED3D_OK;
215 }
216
217 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
218     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
219     IWineD3DBase *container = 0;
220
221     TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
222
223     if (!ppContainer) {
224         ERR("Called without a valid ppContainer.\n");
225     }
226
227     /** From MSDN:
228      * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
229      * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
230      * GetContainer will return the Direct3D device used to create the surface.
231      */
232     if (This->container) {
233         container = This->container;
234     } else {
235         container = (IWineD3DBase *)This->resource.wineD3DDevice;
236     }
237
238     TRACE("Relaying to QueryInterface\n");
239     return IUnknown_QueryInterface(container, riid, ppContainer);
240 }
241
242 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
243     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
244
245     TRACE("(%p) : copying into %p\n", This, pDesc);
246     if(pDesc->Format != NULL)             *(pDesc->Format) = This->resource.format;
247     if(pDesc->Type != NULL)               *(pDesc->Type)   = This->resource.resourceType;
248     if(pDesc->Usage != NULL)              *(pDesc->Usage)              = This->resource.usage;
249     if(pDesc->Pool != NULL)               *(pDesc->Pool)               = This->resource.pool;
250     if(pDesc->Size != NULL)               *(pDesc->Size)               = This->resource.size;   /* dx8 only */
251     if(pDesc->MultiSampleType != NULL)    *(pDesc->MultiSampleType)    = This->currentDesc.MultiSampleType;
252     if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
253     if(pDesc->Width != NULL)              *(pDesc->Width)              = This->currentDesc.Width;
254     if(pDesc->Height != NULL)             *(pDesc->Height)             = This->currentDesc.Height;
255     return WINED3D_OK;
256 }
257
258 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
259     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
260     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
261     if (This->glDescription.textureName == 0 && textureName != 0) {
262         This->Flags |= SFLAG_DIRTY;
263         IWineD3DSurface_AddDirtyRect(iface, NULL);
264     }
265     This->glDescription.textureName = textureName;
266     This->glDescription.target      = target;
267 }
268
269 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
270     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
271     TRACE("(%p) : returning %p\n", This, &This->glDescription);
272     *glDescription = &This->glDescription;
273 }
274
275 /* TODO: think about moving this down to resource? */
276 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
277     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
278     /* This should only be called for sysmem textures, it may be a good idea to extend this to all pools at some point in the futture  */
279     if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
280         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
281     }
282     return (CONST void*)(This->resource.allocatedMemory);
283 }
284
285 static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
286     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
287     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
288     IWineD3DSwapChainImpl *swapchain = NULL;
289     static UINT messages = 0; /* holds flags to disable fixme messages */
290
291     /* fixme: should we really lock as such? */
292     if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INPBUFFER)) ==
293                       (SFLAG_INTEXTURE | SFLAG_INPBUFFER) ) {
294         FIXME("Warning: Surface is in texture memory or pbuffer\n");
295         This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INPBUFFER);
296     }
297
298     if (!(This->Flags & SFLAG_LOCKABLE)) {
299         /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
300               texture regions, and since the destination is an unlockable region we need
301               to tolerate this                                                           */
302         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
303         /*return WINED3DERR_INVALIDCALL; */
304     }
305
306     if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
307         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
308
309         if (swapchain != NULL ||  iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
310             if (swapchain != NULL && iface ==  swapchain->backBuffer) {
311                 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
312             } else if (swapchain != NULL && iface ==  swapchain->frontBuffer) {
313                 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
314             } else if (iface == myDevice->renderTarget) {
315                 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
316             } else if (iface == myDevice->depthStencilBuffer) {
317                 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
318             }
319
320             if (NULL != swapchain) {
321                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
322             }
323             swapchain = NULL;
324         }
325     } else {
326         TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
327     }
328
329     pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
330
331     if (NULL == pRect) {
332         pLockedRect->pBits = This->resource.allocatedMemory;
333         This->lockedRect.left   = 0;
334         This->lockedRect.top    = 0;
335         This->lockedRect.right  = This->currentDesc.Width;
336         This->lockedRect.bottom = This->currentDesc.Height;
337         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);
338     } else {
339         TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
340
341         if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
342             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
343         } else {
344             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
345         }
346         This->lockedRect.left   = pRect->left;
347         This->lockedRect.top    = pRect->top;
348         This->lockedRect.right  = pRect->right;
349         This->lockedRect.bottom = pRect->bottom;
350     }
351
352     if (This->Flags & SFLAG_NONPOW2) {
353         TRACE("Locking non-power 2 texture\n");
354     }
355
356     if (0 == This->resource.usage || This->resource.usage & WINED3DUSAGE_DYNAMIC) {
357         /* classic surface  TODO: non 2d surfaces?
358         These resources may be POOL_SYSTEMMEM, so they must not access the device */
359         TRACE("locking an ordinarary surface\n");
360         /* Check to see if memory has already been allocated from the surface*/
361         if ((NULL == This->resource.allocatedMemory) ||
362             (This->Flags & SFLAG_GLDIRTY) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
363             /* Non-system memory surfaces */
364
365             This->Flags &= ~SFLAG_GLDIRTY;
366
367             /*Surface has no memory currently allocated to it!*/
368             TRACE("(%p) Locking rect\n" , This);
369             if(!This->resource.allocatedMemory) {
370                 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
371             }
372             if (0 != This->glDescription.textureName) {
373                 /* Now I have to copy thing bits back */
374                 This->Flags |= SFLAG_ACTIVELOCK; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
375                 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
376                 ENTER_GL();
377     
378                 /* Make sure that the texture is loaded */
379                 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
380     
381                 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);
382     
383                 if (This->resource.format == WINED3DFMT_DXT1 ||
384                     This->resource.format == WINED3DFMT_DXT2 ||
385                     This->resource.format == WINED3DFMT_DXT3 ||
386                     This->resource.format == WINED3DFMT_DXT4 ||
387                     This->resource.format == WINED3DFMT_DXT5) {
388                     TRACE("Locking a compressed texture\n");
389                     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
390                         GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
391                                                             This->glDescription.level,
392                                                             This->resource.allocatedMemory);
393     
394                     } else {
395                         FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
396                     }
397                 } else {
398                     glGetTexImage(This->glDescription.target,
399                                 This->glDescription.level,
400                                 This->glDescription.glFormat,
401                                 This->glDescription.glType,
402                                 This->resource.allocatedMemory);
403                     vcheckGLcall("glGetTexImage");
404                     if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
405                         /* some games (e.g. warhammer 40k) don't work with the odd pitchs properly, preventing
406                         the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
407                         repack the texture so that the bpp * width pitch can be used instead of the bpp * pow2width.
408         
409                         Were doing this...
410         
411                         instead of boxing the texture :
412                         |<-texture width ->|  -->pow2width|   /\
413                         |111111111111111111|              |   |
414                         |222 Texture 222222| boxed empty  | texture height
415                         |3333 Data 33333333|              |   |
416                         |444444444444444444|              |   \/
417                         -----------------------------------   |
418                         |     boxed  empty | boxed empty  | pow2height
419                         |                  |              |   \/
420                         -----------------------------------
421         
422         
423                         were repacking the data to the expected texture width
424         
425                         |<-texture width ->|  -->pow2width|   /\
426                         |111111111111111111222222222222222|   |
427                         |222333333333333333333444444444444| texture height
428                         |444444                           |   |
429                         |                                 |   \/
430                         |                                 |   |
431                         |            empty                | pow2height
432                         |                                 |   \/
433                         -----------------------------------
434         
435                         == is the same as
436         
437                         |<-texture width ->|    /\
438                         |111111111111111111|
439                         |222222222222222222|texture height
440                         |333333333333333333|
441                         |444444444444444444|    \/
442                         --------------------
443         
444                         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.
445         
446                         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.
447                         */
448                         if (This->Flags & SFLAG_NONPOW2) {
449                             BYTE* dataa, *datab;
450                             int pitcha = 0, pitchb = 0;
451                             int y;
452                             pitcha = This->bytesPerPixel * This->currentDesc.Width;
453                             pitchb = This->bytesPerPixel * This->pow2Width;
454                             datab = dataa = This->resource.allocatedMemory;
455                             FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, pitcha, pitchb);
456                             for (y = 1 ; y < This->currentDesc.Height; y++) {
457                                 dataa += pitcha; /* skip the first row */
458                                 datab += pitchb;
459                                 memcpy(dataa, datab, pitcha);
460                             }
461                         }
462                     }
463                 }
464                 LEAVE_GL();
465             }
466         } else { /* Nothing to do */
467             TRACE("Memory %p already allocted for texture\n",  This->resource.allocatedMemory);
468         }
469
470         if (NULL == pRect) {
471             pLockedRect->pBits = This->resource.allocatedMemory;
472         }  else{
473             if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
474                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
475             } else {
476                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
477             }
478         }
479
480     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage ){ /* render surfaces */
481         if((!(Flags&WINED3DLOCK_DISCARD) && (This->Flags & SFLAG_GLDIRTY)) || !This->resource.allocatedMemory) {
482             GLint  prev_store;
483             GLint  prev_read;
484             BOOL notInContext = FALSE;
485             IWineD3DSwapChainImpl *targetSwapChain = NULL;
486
487
488             ENTER_GL();
489
490                 /**
491                 * for render->surface copy begin to begin of allocatedMemory
492                 * unlock can be more easy
493                 */
494
495             TRACE("locking a render target\n");
496
497             if (This->resource.allocatedMemory == NULL)
498                     This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
499
500             This->Flags |= SFLAG_ACTIVELOCK; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
501             pLockedRect->pBits = This->resource.allocatedMemory;
502
503             glFlush();
504             vcheckGLcall("glFlush");
505             glGetIntegerv(GL_READ_BUFFER, &prev_read);
506             vcheckGLcall("glIntegerv");
507             glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
508             vcheckGLcall("glIntegerv");
509
510     /* Here's what we have to do:
511                 See if the swapchain has the same context as the renderTarget or the surface is the render target.
512                 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
513                 and use the front back buffer as required.
514                 if not, we need to switch contexts and then switchback at the end.
515             */
516             IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
517             IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
518
519             /* 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! */
520             if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
521                     if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
522                         TRACE("locking back buffer\n");
523                       glReadBuffer(GL_BACK);
524                     } else if (iface == swapchain->frontBuffer) {
525                       TRACE("locking front\n");
526                       glReadBuffer(GL_FRONT);
527                     } else if (iface == myDevice->depthStencilBuffer) {
528                         FIXME("Stencil Buffer lock unsupported for now\n");
529                     } else {
530                       FIXME("(%p) Shouldn't have got here!\n", This);
531                       glReadBuffer(GL_BACK);
532                     }
533             } else if (swapchain != NULL) {
534                 IWineD3DSwapChainImpl *implSwapChain;
535                 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
536                 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
537                         /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
538                         if (iface == swapchain->backBuffer) {
539                             glReadBuffer(GL_BACK);
540                         } else if (iface == swapchain->frontBuffer) {
541                             glReadBuffer(GL_FRONT);
542                         } else if (iface == myDevice->depthStencilBuffer) {
543                             FIXME("Stencil Buffer lock unsupported for now\n");
544                         } else {
545                             FIXME("Should have got here!\n");
546                             glReadBuffer(GL_BACK);
547                         }
548                 } else {
549                     /* We need to switch contexts to be able to read the buffer!!! */
550                     FIXME("The buffer requested isn't in the current openGL context\n");
551                     notInContext = TRUE;
552                     /* TODO: check the contexts, to see if were shared with the current context */
553                 }
554                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
555             }
556             if (swapchain != NULL)       IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
557             if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
558
559             /** the depth stencil in openGL has a format of GL_FLOAT
560             * which should be good for WINED3DFMT_D16_LOCKABLE
561             * and WINED3DFMT_D16
562             * it is unclear what format the stencil buffer is in except.
563             * 'Each index is converted to fixed point...
564             * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
565             * mappings in the table GL_PIXEL_MAP_S_TO_S.
566             * glReadPixels(This->lockedRect.left,
567             *             This->lockedRect.bottom - j - 1,
568             *             This->lockedRect.right - This->lockedRect.left,
569             *             1,
570             *             GL_DEPTH_COMPONENT,
571             *             type,
572             *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
573                 *****************************************/
574             if (!notInContext) { /* Only read the buffer if it's in the current context */
575                 long j;
576
577 #if 0
578                 /* 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,
579                 *  This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
580                 *  run ten times faster!
581                 * ************************************/
582                 BOOL ati_performance_hack = FALSE;
583                 ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
584 #endif
585                 if ((This->lockedRect.left == 0 &&  This->lockedRect.top == 0 &&
586                     This->lockedRect.right == This->currentDesc.Width
587                     && This->lockedRect.bottom ==  This->currentDesc.Height)) {
588                         BYTE *row, *top, *bottom;
589                         int i;
590
591                         glReadPixels(0, 0,
592                         This->currentDesc.Width,
593                         This->currentDesc.Height,
594                         This->glDescription.glFormat,
595                         This->glDescription.glType,
596                         (char *)pLockedRect->pBits);
597
598                         /* glReadPixels returns the image upside down, and there is no way to prevent this.
599                           Flip the lines in software*/
600                         row = HeapAlloc(GetProcessHeap(), 0, pLockedRect->Pitch);
601                         if(!row) {
602                             ERR("Out of memory\n");
603                             return E_OUTOFMEMORY;
604                         }
605                         top = This->resource.allocatedMemory;
606                         bottom = ( (BYTE *) This->resource.allocatedMemory) + pLockedRect->Pitch * ( This->currentDesc.Height - 1);
607                         for(i = 0; i < This->currentDesc.Height / 2; i++) {
608                             memcpy(row, top, pLockedRect->Pitch);
609                             memcpy(top, bottom, pLockedRect->Pitch);
610                             memcpy(bottom, row, pLockedRect->Pitch);
611                             top += pLockedRect->Pitch;
612                             bottom -= pLockedRect->Pitch;
613                         }
614                         HeapFree(GetProcessHeap(), 0, row);
615
616                         This->Flags &= ~SFLAG_GLDIRTY;
617
618                 } else if (This->lockedRect.left == 0 &&  This->lockedRect.right == This->currentDesc.Width) {
619                         glReadPixels(0,
620                         This->lockedRect.top,
621                         This->currentDesc.Width,
622                         This->currentDesc.Height,
623                         This->glDescription.glFormat,
624                         This->glDescription.glType,
625                         (char *)pLockedRect->pBits);
626                 } else{
627
628                     for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
629                         glReadPixels(This->lockedRect.left, 
630                                     This->lockedRect.bottom - j - 1, 
631                                     This->lockedRect.right - This->lockedRect.left, 
632                                     1,
633                                     This->glDescription.glFormat,
634                                     This->glDescription.glType,
635                                     (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
636
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 static 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->frontBuffer) {
788                 glDrawBuffer(GL_FRONT);
789                 checkGLcall("glDrawBuffer GL_FRONT");
790             } else if (iface ==  implSwapChain->backBuffer || iface == myDevice->renderTarget) {
791                 glDrawBuffer(GL_BACK);
792                 checkGLcall("glDrawBuffer GL_BACK");
793             }
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 static 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 static 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 static HRESULT 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             /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2248             This->Flags |= SFLAG_GLDIRTY;
2249
2250             return WINED3D_OK;
2251         }
2252
2253
2254         /* Blt from rendertarget to texture? */
2255         if( (SrcSurface == swapchain->frontBuffer) ||
2256             (SrcSurface == swapchain->backBuffer) ) {
2257             if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
2258                 ( (IWineD3DSurface *) This != swapchain->backBuffer) ) {
2259                 UINT row;
2260                 D3DRECT srect;
2261                 float xrel, yrel;
2262
2263                 TRACE("Blt from rendertarget to texture\n");
2264
2265                 /* Call preload for the surface to make sure it isn't dirty */
2266                 IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2267
2268                 if(SrcRect) {
2269                     srect.x1 = SrcRect->left;
2270                     srect.y1 = SrcRect->top;
2271                     srect.x2 = SrcRect->right;
2272                     srect.y2 = SrcRect->bottom;
2273                 } else {
2274                     srect.x1 = 0;
2275                     srect.y1 = 0;
2276                     srect.x2 = Src->currentDesc.Width;
2277                     srect.y2 = Src->currentDesc.Height;
2278                 }
2279
2280                 ENTER_GL();
2281
2282                 /* Bind the target texture */
2283                 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2284                 checkGLcall("glBindTexture");
2285                 if(SrcSurface == swapchain->backBuffer) {
2286                     glReadBuffer(GL_BACK);
2287                 } else {
2288                     glReadBuffer(GL_FRONT);
2289                 }
2290                 checkGLcall("glReadBuffer");
2291
2292                 xrel = (float) (srect.x2 - srect.x1) / (float) (rect.x2 - rect.x1);
2293                 yrel = (float) (srect.y2 - srect.y1) / (float) (rect.y2 - rect.y1);
2294
2295                 /* I have to process this row by row to swap the image,
2296                  * otherwise it would be upside down, so streching in y direction
2297                  * doesn't cost extra time
2298                  *
2299                  * However, streching in x direction can be avoided if not necessary
2300                  */
2301                 for(row = rect.y1; row < rect.y2; row++) {
2302                     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2303                         /* Well, that stuff works, but it's very slow.
2304                          * find a better way instead
2305                          */
2306                         UINT col;
2307                         for(col = rect.x1; col < rect.x2; col++) {
2308                             glCopyTexSubImage2D(GL_TEXTURE_2D,
2309                                                 0, /* level */
2310                                                 rect.x1 + col, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2311                                                 srect.x1 + col * xrel, Src->currentDesc.Height - srect.y2 + row * yrel,
2312                                                 1, 1);
2313                         }
2314                     } else {
2315                         glCopyTexSubImage2D(GL_TEXTURE_2D,
2316                                             0, /* level */
2317                                             rect.x1, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2318                                             srect.x1, Src->currentDesc.Height - srect.y2 + row * yrel,
2319                                             rect.x2, 1);
2320                     }
2321                 }
2322
2323                 vcheckGLcall("glCopyTexSubImage2D");
2324                 LEAVE_GL();
2325
2326                 if(!(This->Flags & SFLAG_DONOTFREE)) {
2327                     HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2328                     This->resource.allocatedMemory = NULL;
2329                 } else {
2330                     This->Flags |= SFLAG_GLDIRTY;
2331                 }
2332
2333                 return WINED3D_OK;
2334             }
2335         }
2336     }
2337
2338     if (Flags & DDBLT_COLORFILL) {
2339         /* This is easy to handle for the D3D Device... */
2340         DWORD color;
2341         IWineD3DSwapChainImpl *implSwapChain;
2342         GLint  prev_draw;
2343
2344         TRACE("Colorfill\n");
2345
2346         /* The color as given in the Blt function is in the format of the frame-buffer...
2347          * 'clear' expect it in ARGB format => we need to do some conversion :-)
2348          */
2349         if (This->resource.format == WINED3DFMT_P8) {
2350             if (This->palette) {
2351                 color = ((0xFF000000) |
2352                           (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2353                           (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2354                           (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2355             } else {
2356                 color = 0xFF000000;
2357             }
2358         }
2359         else if (This->resource.format == WINED3DFMT_R5G6B5) {
2360             if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2361                 color = 0xFFFFFFFF;
2362             } else {
2363                 color = ((0xFF000000) |
2364                           ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2365                           ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2366                           ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2367             }
2368         }
2369         else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2370                   (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2371             color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2372         }
2373         else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2374             color = DDBltFx->u5.dwFillColor;
2375         }
2376         else {
2377             ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2378             return WINED3DERR_INVALIDCALL;
2379         }
2380
2381         /* Are we drawing to the Front buffer or the back buffer? */
2382         glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2383         vcheckGLcall("glIntegerv");
2384
2385         TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2386         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
2387         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
2388         if(This ==  (IWineD3DSurfaceImpl*) implSwapChain->backBuffer) {
2389             glDrawBuffer(GL_BACK);
2390             checkGLcall("glDrawBuffer(GL_BACK)");
2391         }
2392         else if (This == (IWineD3DSurfaceImpl*) implSwapChain->frontBuffer) {
2393             glDrawBuffer(GL_FRONT);
2394             checkGLcall("glDrawBuffer(GL_FRONT)");
2395         }
2396         else {
2397             ERR("Wrong surface type for BLT override(not on swapchain) !\n");
2398             return WINED3DERR_INVALIDCALL;
2399         }
2400
2401         TRACE("(%p) executing Render Target override, color = %lx\n", This, color);
2402
2403         IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2404                               1 /* Number of rectangles */,
2405                               &rect,
2406                               D3DCLEAR_TARGET,
2407                               color,
2408                               0.0 /* Z */,
2409                               0 /* Stencil */);
2410
2411         /* Restore the original draw buffer */
2412         glDrawBuffer(prev_draw);
2413         vcheckGLcall("glDrawBuffer");
2414
2415         return WINED3D_OK;
2416     }
2417
2418     /* Default: Fall back to the generic blt */
2419     return WINED3DERR_INVALIDCALL;
2420 }
2421
2422 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2423     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2424     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2425     TRACE("(%p)->(%p,%p,%p,%lx,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2426     TRACE("(%p): Usage is %08lx\n", This, This->resource.usage);
2427
2428     /* Special cases for RenderTargets */
2429     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2430         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2431         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2432     }
2433
2434     /* For the rest call the X11 surface implementation.
2435      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2436      * other Blts are rather rare
2437      */
2438     return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2439 }
2440
2441 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2442     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2443     TRACE("(%p)->(%lx)\n", This, Flags);
2444
2445     switch (Flags)
2446     {
2447     case DDGBS_CANBLT:
2448     case DDGBS_ISBLTDONE:
2449         return DD_OK;
2450
2451     default:
2452         return DDERR_INVALIDPARAMS;
2453     }
2454 }
2455
2456 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2457     /* XXX: DDERR_INVALIDSURFACETYPE */
2458
2459     TRACE("(%p)->(%08lx)\n",iface,Flags);
2460     switch (Flags) {
2461     case DDGFS_CANFLIP:
2462     case DDGFS_ISFLIPDONE:
2463         return DD_OK;
2464
2465     default:
2466         return DDERR_INVALIDPARAMS;
2467     }
2468 }
2469
2470 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2471     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2472     TRACE("(%p)\n", This);
2473
2474     return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2475 }
2476
2477 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2478     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2479     TRACE("(%p)\n", This);
2480
2481     /* So far we don't lose anything :) */
2482     This->Flags &= ~SFLAG_LOST;
2483     return WINED3D_OK;
2484 }
2485
2486 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2487     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2488     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2489     TRACE("(%p)->(%ld, %ld, %p, %p, %08lx\n", iface, dstx, dsty, Source, rsrc, trans);
2490
2491     /* Special cases for RenderTargets */
2492     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2493         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2494
2495         RECT SrcRect, DstRect;
2496
2497         if(rsrc) {
2498             SrcRect.left = rsrc->left;
2499             SrcRect.top= rsrc->top;
2500             SrcRect.bottom = rsrc->bottom;
2501             SrcRect.right = rsrc->right;
2502         } else {
2503             SrcRect.left = 0;
2504             SrcRect.top = 0;
2505             SrcRect.right = srcImpl->currentDesc.Width;
2506             SrcRect.bottom = srcImpl->currentDesc.Height;
2507         }
2508
2509         DstRect.left = dstx;
2510         DstRect.top=dsty;
2511         DstRect.right = dstx + SrcRect.right - SrcRect.left;
2512         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2513
2514         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, 0, NULL) == WINED3D_OK) return WINED3D_OK;
2515     }
2516
2517
2518     return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2519 }
2520
2521 HRESULT WINAPI IWineD3DSurfaceImpl_SetPixelFormat(IWineD3DSurface *iface, WINED3DFORMAT Format, BYTE *Surface, DWORD Size) {
2522     FIXME("This is unimplemented for now(d3d7 merge)\n");
2523     return WINED3DERR_INVALIDCALL;
2524 }
2525
2526 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2527     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2528     TRACE("(%p)->(%p)\n", This, Pal);
2529
2530     *Pal = (IWineD3DPalette *) This->palette;
2531     return DD_OK;
2532 }
2533
2534 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2535     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2536     RGBQUAD col[256];
2537     IWineD3DPaletteImpl *pal = This->palette;
2538     unsigned int n;
2539     TRACE("(%p)\n", This);
2540
2541     if(This->resource.format == WINED3DFMT_P8 ||
2542        This->resource.format == WINED3DFMT_A8P8)
2543     {
2544         TRACE("Dirtifying surface\n");
2545         This->Flags |= SFLAG_DIRTY;
2546     }
2547
2548     if(This->Flags & SFLAG_DIBSECTION) {
2549         TRACE("(%p): Updating the hdc's palette\n", This);
2550         for (n=0; n<256; n++) {
2551             if(pal) {
2552                 col[n].rgbRed   = pal->palents[n].peRed;
2553                 col[n].rgbGreen = pal->palents[n].peGreen;
2554                 col[n].rgbBlue  = pal->palents[n].peBlue;
2555             } else {
2556                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2557                 /* Use the default device palette */
2558                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
2559                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
2560                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
2561             }
2562             col[n].rgbReserved = 0;
2563         }
2564         SetDIBColorTable(This->hDC, 0, 256, col);
2565     }
2566
2567     return WINED3D_OK;
2568 }
2569
2570 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
2571     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2572     IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
2573     TRACE("(%p)->(%p)\n", This, Pal);
2574
2575     if(This->palette != NULL) 
2576         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
2577             This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
2578
2579     if(PalImpl != NULL) {
2580         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2581             /* Set the device's main palette if the palette
2582              * wasn't a primary palette before
2583              */
2584             if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
2585                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2586                 unsigned int i;
2587
2588                 for(i=0; i < 256; i++) {
2589                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
2590                 }
2591             }
2592
2593             (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
2594         }
2595     }
2596     This->palette = PalImpl;
2597
2598     return IWineD3DSurface_RealizePalette(iface);
2599 }
2600
2601 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
2602     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2603     BOOL dirtify = FALSE;
2604     TRACE("(%p)->(%08lx,%p)\n", This, Flags, CKey);
2605
2606     if ((Flags & DDCKEY_COLORSPACE) != 0) {
2607         FIXME(" colorkey value not supported (%08lx) !\n", Flags);
2608         return DDERR_INVALIDPARAMS;
2609     }
2610
2611     /* Dirtify the surface, but only if a key was changed */
2612     if(CKey) {
2613         switch (Flags & ~DDCKEY_COLORSPACE) {
2614             case DDCKEY_DESTBLT:
2615                 if(!(This->CKeyFlags & DDSD_CKDESTBLT)) {
2616                     dirtify = TRUE;
2617                 } else {
2618                     dirtify = memcmp(&This->DestBltCKey, CKey, sizeof(*CKey) ) != 0;
2619                 }
2620                 This->DestBltCKey = *CKey;
2621                 This->CKeyFlags |= DDSD_CKDESTBLT;
2622                 break;
2623
2624             case DDCKEY_DESTOVERLAY:
2625                 if(!(This->CKeyFlags & DDSD_CKDESTOVERLAY)) {
2626                     dirtify = TRUE;
2627                 } else {
2628                     dirtify = memcmp(&This->DestOverlayCKey, CKey, sizeof(*CKey)) != 0;
2629                 }
2630                 This->DestOverlayCKey = *CKey;
2631                 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
2632                 break;
2633
2634             case DDCKEY_SRCOVERLAY:
2635                 if(!(This->CKeyFlags & DDSD_CKSRCOVERLAY)) {
2636                     dirtify = TRUE;
2637                 } else {
2638                     dirtify = memcmp(&This->SrcOverlayCKey, CKey, sizeof(*CKey)) != 0;
2639                 }
2640                 This->SrcOverlayCKey = *CKey;
2641                 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
2642                 break;
2643
2644             case DDCKEY_SRCBLT:
2645                 if(!(This->CKeyFlags & DDSD_CKSRCBLT)) {
2646                     dirtify = TRUE;
2647                 } else {
2648                     dirtify = memcmp(&This->SrcBltCKey, CKey, sizeof(*CKey)) != 0;
2649                 }
2650                 This->SrcBltCKey = *CKey;
2651                 This->CKeyFlags |= DDSD_CKSRCBLT;
2652                 break;
2653         }
2654     }
2655     else {
2656         switch (Flags & ~DDCKEY_COLORSPACE) {
2657             case DDCKEY_DESTBLT:
2658                 dirtify = This->CKeyFlags & DDSD_CKDESTBLT;
2659                 This->CKeyFlags &= ~DDSD_CKDESTBLT;
2660                 break;
2661
2662             case DDCKEY_DESTOVERLAY:
2663                 dirtify = This->CKeyFlags & DDSD_CKDESTOVERLAY;
2664                 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
2665                 break;
2666
2667             case DDCKEY_SRCOVERLAY:
2668                 dirtify = This->CKeyFlags & DDSD_CKSRCOVERLAY;
2669                 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
2670                 break;
2671
2672             case DDCKEY_SRCBLT:
2673                 dirtify = This->CKeyFlags & DDSD_CKSRCBLT;
2674                 This->CKeyFlags &= ~DDSD_CKSRCBLT;
2675                 break;
2676         }
2677     }
2678
2679     if(dirtify) {
2680         TRACE("Color key changed, dirtifying surface\n");
2681         This->Flags |= SFLAG_DIRTY;
2682     }
2683
2684     return WINED3D_OK;
2685 }
2686
2687 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
2688     /** Check against the maximum texture sizes supported by the video card **/
2689     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2690
2691     TRACE("%p\n", This);
2692     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
2693         /* one of three options
2694         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)
2695         2: Set the texture to the maxium size (bad idea)
2696         3:    WARN and return WINED3DERR_NOTAVAILABLE;
2697         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.
2698         */
2699         WARN("(%p) Creating an oversized surface\n", This);
2700         This->Flags |= SFLAG_OVERSIZE;
2701
2702         /* This will be initialized on the first blt */
2703         This->glRect.left = 0;
2704         This->glRect.top = 0;
2705         This->glRect.right = 0;
2706         This->glRect.bottom = 0;
2707     } else {
2708         /* No oversize, gl rect is the full texture size */
2709         This->Flags &= ~SFLAG_OVERSIZE;
2710         This->glRect.left = 0;
2711         This->glRect.top = 0;
2712         This->glRect.right = This->pow2Width;
2713         This->glRect.bottom = This->pow2Height;
2714     }
2715
2716     return WINED3D_OK;
2717 }
2718
2719 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
2720     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2721     DWORD ret;
2722     TRACE("(%p)\n", This);
2723
2724     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
2725          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
2726           ie pitch = (width/4) * bytes per block                                  */
2727     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
2728         ret = (This->currentDesc.Width >> 2) << 3;
2729     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
2730              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
2731         ret = (This->currentDesc.Width >> 2) << 4;
2732     else {
2733         if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2734             /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
2735             ret = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
2736         } else {
2737             ret = This->bytesPerPixel * This->pow2Width;
2738         }
2739     }
2740     TRACE("(%p) Returning %ld\n", This, ret);
2741     return ret;
2742 }
2743
2744 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
2745 {
2746     /* IUnknown */
2747     IWineD3DSurfaceImpl_QueryInterface,
2748     IWineD3DSurfaceImpl_AddRef,
2749     IWineD3DSurfaceImpl_Release,
2750     /* IWineD3DResource */
2751     IWineD3DSurfaceImpl_GetParent,
2752     IWineD3DSurfaceImpl_GetDevice,
2753     IWineD3DSurfaceImpl_SetPrivateData,
2754     IWineD3DSurfaceImpl_GetPrivateData,
2755     IWineD3DSurfaceImpl_FreePrivateData,
2756     IWineD3DSurfaceImpl_SetPriority,
2757     IWineD3DSurfaceImpl_GetPriority,
2758     IWineD3DSurfaceImpl_PreLoad,
2759     IWineD3DSurfaceImpl_GetType,
2760     /* IWineD3DSurface */
2761     IWineD3DSurfaceImpl_GetContainerParent,
2762     IWineD3DSurfaceImpl_GetContainer,
2763     IWineD3DSurfaceImpl_GetDesc,
2764     IWineD3DSurfaceImpl_LockRect,
2765     IWineD3DSurfaceImpl_UnlockRect,
2766     IWineD3DSurfaceImpl_GetDC,
2767     IWineD3DSurfaceImpl_ReleaseDC,
2768     IWineD3DSurfaceImpl_Flip,
2769     IWineD3DSurfaceImpl_Blt,
2770     IWineD3DSurfaceImpl_GetBltStatus,
2771     IWineD3DSurfaceImpl_GetFlipStatus,
2772     IWineD3DSurfaceImpl_IsLost,
2773     IWineD3DSurfaceImpl_Restore,
2774     IWineD3DSurfaceImpl_BltFast,
2775     IWineD3DSurfaceImpl_SetPixelFormat,
2776     IWineD3DSurfaceImpl_GetPalette,
2777     IWineD3DSurfaceImpl_SetPalette,
2778     IWineD3DSurfaceImpl_RealizePalette,
2779     IWineD3DSurfaceImpl_SetColorKey,
2780     IWineD3DSurfaceImpl_GetPitch,
2781     /* Internal use: */
2782     IWineD3DSurfaceImpl_CleanDirtyRect,
2783     IWineD3DSurfaceImpl_AddDirtyRect,
2784     IWineD3DSurfaceImpl_LoadTexture,
2785     IWineD3DSurfaceImpl_SaveSnapshot,
2786     IWineD3DSurfaceImpl_SetContainer,
2787     IWineD3DSurfaceImpl_SetPBufferState,
2788     IWineD3DSurfaceImpl_SetGlTextureDesc,
2789     IWineD3DSurfaceImpl_GetGlDesc,
2790     IWineD3DSurfaceImpl_GetData,
2791     IWineD3DSurfaceImpl_SetFormat,
2792     IWineD3DSurfaceImpl_PrivateSetup
2793 };