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