wined3d: Split device creation and opengl initialization.
[wine] / dlls / wined3d / surface.c
1 /*
2  * IWineD3DSurface Implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2002-2003 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  * Copyright 2005 Oliver Stieber
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include "config.h"
25 #include "wine/port.h"
26 #include "wined3d_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
30
31 /* *******************************************
32    IWineD3DSurface IUnknown parts follow
33    ******************************************* */
34 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
35 {
36     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
37     /* Warn ,but be nice about things */
38     TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
39     if (riid == NULL) {
40         ERR("Probably FIXME: Calling query interface with NULL riid\n");
41     }
42     if (IsEqualGUID(riid, &IID_IUnknown)
43         || IsEqualGUID(riid, &IID_IWineD3DBase)
44         || IsEqualGUID(riid, &IID_IWineD3DResource)
45         || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
46         IUnknown_AddRef((IUnknown*)iface);
47         *ppobj = This;
48         return WINED3D_OK;
49     }
50     return E_NOINTERFACE;
51 }
52
53 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
54     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
55     ULONG ref = InterlockedIncrement(&This->resource.ref);
56     TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
57     return ref;
58 }
59
60 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
61     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
62     ULONG ref = InterlockedDecrement(&This->resource.ref);
63     TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
64     if (ref == 0) {
65         TRACE("(%p) : cleaning up\n", This);
66         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
67             ENTER_GL();
68             TRACE("Deleting texture %d\n", This->glDescription.textureName);
69             glDeleteTextures(1, &This->glDescription.textureName);
70             LEAVE_GL();
71         }
72         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
73
74         TRACE("(%p) Released\n", This);
75         HeapFree(GetProcessHeap(), 0, This);
76
77     }
78     return ref;
79 }
80
81 /* ****************************************************
82    IWineD3DSurface IWineD3DResource parts follow
83    **************************************************** */
84 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
85     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
86 }
87
88 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
89     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
90 }
91
92 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
93     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
94 }
95
96 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
97     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
98 }
99
100 DWORD   WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
101     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
102 }
103
104 DWORD   WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
105     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
106 }
107
108 void    WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
109     /* TODO: re-write the way textures and managed,
110     *  use a 'opengl context manager' to manage RenderTarget surfaces
111     ** *********************************************************/
112
113     /* TODO: check for locks */
114     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
115     IWineD3DBaseTexture *baseTexture = NULL;
116     TRACE("(%p)Checking to see if the container is a base texture\n", This);
117     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
118         TRACE("Passing to conatiner\n");
119         IWineD3DBaseTexture_PreLoad(baseTexture);
120         IWineD3DBaseTexture_Release(baseTexture);
121     } else {
122     TRACE("(%p) : About to load surface\n", This);
123     ENTER_GL();
124 #if 0 /* TODO: context manager support */
125      IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
126 #endif
127     glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
128     if (This->glDescription.level == 0 &&  This->glDescription.textureName == 0) {
129           glGenTextures(1, &This->glDescription.textureName);
130           checkGLcall("glGenTextures");
131           TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
132           glBindTexture(This->glDescription.target, This->glDescription.textureName);
133           checkGLcall("glBindTexture");
134           IWineD3DSurface_LoadTexture(iface);
135           /* This is where we should be reducing the amount of GLMemoryUsed */
136     } else {
137         if (This->glDescription.level == 0) {
138           glBindTexture(This->glDescription.target, This->glDescription.textureName);
139           checkGLcall("glBindTexture");
140           IWineD3DSurface_LoadTexture(iface);
141         } else  if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
142             /* assume this is a coding error not a real error for now */
143             FIXME("Mipmap surface has a glTexture bound to it!\n");
144         }
145     }
146     if (This->resource.pool == WINED3DPOOL_DEFAULT) {
147        /* Tell opengl to try and keep this texture in video ram (well mostly) */
148        GLclampf tmp;
149        tmp = 0.9f;
150         glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
151     }
152     /* TODO: disable texture support, if it wastn't enabled when we entered. */
153 #if 0 /* TODO: context manager support */
154      IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
155               /* we don't care when the state is disabled(if atall) */);
156 #endif
157     LEAVE_GL();
158     }
159     return;
160 }
161
162 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
163     TRACE("(%p) : calling resourceimpl_GetType\n", iface);
164     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
165 }
166
167 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
168     TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
169     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
170 }
171
172 /* ******************************************************
173    IWineD3DSurface IWineD3DSurface parts follow
174    ****************************************************** */
175
176 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
177     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
178
179     TRACE("(%p) : ppContainerParent %p)\n", This, ppContainerParent);
180
181     if (!ppContainerParent) {
182         ERR("(%p) : Called without a valid ppContainerParent.\n", This);
183     }
184
185     if (This->container) {
186         IWineD3DBase_GetParent(This->container, ppContainerParent);
187         if (!ppContainerParent) {
188             /* WineD3D objects should always have a parent */
189             ERR("(%p) : GetParent returned NULL\n", This);
190         }
191         IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */
192     } else {
193         *ppContainerParent = NULL;
194     }
195
196     return WINED3D_OK;
197 }
198
199 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
200     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
201     IWineD3DBase *container = 0;
202
203     TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
204
205     if (!ppContainer) {
206         ERR("Called without a valid ppContainer.\n");
207     }
208
209     /** From MSDN:
210      * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
211      * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
212      * GetContainer will return the Direct3D device used to create the surface.
213      */
214     if (This->container) {
215         container = This->container;
216     } else {
217         container = (IWineD3DBase *)This->resource.wineD3DDevice;
218     }
219
220     TRACE("Relaying to QueryInterface\n");
221     return IUnknown_QueryInterface(container, riid, ppContainer);
222 }
223
224 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
225     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
226
227     TRACE("(%p) : copying into %p\n", This, pDesc);
228     if(pDesc->Format != NULL)             *(pDesc->Format) = This->resource.format;
229     if(pDesc->Type != NULL)               *(pDesc->Type)   = This->resource.resourceType;
230     if(pDesc->Usage != NULL)              *(pDesc->Usage)              = This->resource.usage;
231     if(pDesc->Pool != NULL)               *(pDesc->Pool)               = This->resource.pool;
232     if(pDesc->Size != NULL)               *(pDesc->Size)               = This->resource.size;   /* dx8 only */
233     if(pDesc->MultiSampleType != NULL)    *(pDesc->MultiSampleType)    = This->currentDesc.MultiSampleType;
234     if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
235     if(pDesc->Width != NULL)              *(pDesc->Width)              = This->currentDesc.Width;
236     if(pDesc->Height != NULL)             *(pDesc->Height)             = This->currentDesc.Height;
237     return WINED3D_OK;
238 }
239
240 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
241     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
242     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
243     if (This->glDescription.textureName == 0 && textureName != 0) {
244         This->Dirty = TRUE;
245         IWineD3DSurface_AddDirtyRect(iface, NULL);
246     }
247     This->glDescription.textureName = textureName;
248     This->glDescription.target      = target;
249 }
250
251 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
252     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
253     TRACE("(%p) : returning %p\n", This, &This->glDescription);
254     *glDescription = &This->glDescription;
255 }
256
257 /* TODO: think about moving this down to resource? */
258 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
259     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
260     /* 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  */
261     if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
262         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
263     }
264     return (CONST void*)(This->resource.allocatedMemory);
265 }
266
267 HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
268     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
269     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
270     IWineD3DSwapChainImpl *swapchain = NULL;
271     static UINT messages = 0; /* holds flags to disable fixme messages */
272
273     /* fixme: should we really lock as such? */
274     if (This->inTexture && This->inPBuffer) {
275         FIXME("Warning: Surface is in texture memory or pbuffer\n");
276         This->inTexture = 0;
277         This->inPBuffer = 0;
278     }
279
280     if (FALSE == This->lockable) {
281         /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
282               texture regions, and since the destination is an unlockable region we need
283               to tolerate this                                                           */
284         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
285         /*return WINED3DERR_INVALIDCALL; */
286     }
287
288     if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
289         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
290
291         if (swapchain != NULL ||  iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
292             if (swapchain != NULL && iface ==  swapchain->backBuffer) {
293                 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
294             } else if (swapchain != NULL && iface ==  swapchain->frontBuffer) {
295                 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
296             } else if (iface == myDevice->renderTarget) {
297                 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
298             } else if (iface == myDevice->depthStencilBuffer) {
299                 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
300             }
301
302             if (NULL != swapchain) {
303                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
304             }
305             swapchain = NULL;
306         }
307     } else {
308         TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
309     }
310
311     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
312          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
313           ie pitch = (width/4) * bytes per block                                  */
314     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
315         pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 3;
316     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
317              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
318         pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 4;
319     else {
320         if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
321             /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
322             pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
323         } else {
324             pLockedRect->Pitch = This->bytesPerPixel * This->pow2Width;
325         }
326     }
327
328     if (NULL == pRect) {
329         pLockedRect->pBits = This->resource.allocatedMemory;
330         This->lockedRect.left   = 0;
331         This->lockedRect.top    = 0;
332         This->lockedRect.right  = This->currentDesc.Width;
333         This->lockedRect.bottom = This->currentDesc.Height;
334         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);
335     } else {
336         TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
337
338         if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
339             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
340         } else {
341             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
342         }
343         This->lockedRect.left   = pRect->left;
344         This->lockedRect.top    = pRect->top;
345         This->lockedRect.right  = pRect->right;
346         This->lockedRect.bottom = pRect->bottom;
347     }
348
349     if (This->nonpow2) {
350         TRACE("Locking non-power 2 texture\n");
351     }
352
353     if (0 == This->resource.usage || This->resource.usage & WINED3DUSAGE_DYNAMIC) {
354         /* classic surface  TODO: non 2d surfaces?
355         These resources may be POOL_SYSTEMMEM, so they must not access the device */
356         TRACE("locking an ordinarary surface\n");
357         /* Check to see if memory has already been allocated from the surface*/
358         if (NULL == This->resource.allocatedMemory) { /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
359             /* Non-system memory surfaces */
360
361             /*Surface has no memory currently allocated to it!*/
362             TRACE("(%p) Locking rect\n" , This);
363             This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
364             if (0 != This->glDescription.textureName) {
365                 /* Now I have to copy thing bits back */
366                 This->activeLock = TRUE; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
367                 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
368                 ENTER_GL();
369     
370                 /* Make sure that the texture is loaded */
371                 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
372     
373                 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);
374     
375                 if (This->resource.format == WINED3DFMT_DXT1 ||
376                     This->resource.format == WINED3DFMT_DXT2 ||
377                     This->resource.format == WINED3DFMT_DXT3 ||
378                     This->resource.format == WINED3DFMT_DXT4 ||
379                     This->resource.format == WINED3DFMT_DXT5) {
380                     TRACE("Locking a compressed texture\n");
381                     if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
382                         GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
383                                                             This->glDescription.level,
384                                                             This->resource.allocatedMemory);
385     
386                     } else {
387                         FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
388                     }
389                 } else {
390                     glGetTexImage(This->glDescription.target,
391                                 This->glDescription.level,
392                                 This->glDescription.glFormat,
393                                 This->glDescription.glType,
394                                 This->resource.allocatedMemory);
395                     vcheckGLcall("glGetTexImage");
396                     if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
397                         /* some games (e.g. warhammer 40k) don't work with the odd pitchs properly, preventing
398                         the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
399                         repack the texture so that the bpp * width pitch can be used instead of the bpp * pow2width.
400         
401                         Were doing this...
402         
403                         instead of boxing the texture :
404                         |<-texture width ->|  -->pow2width|   /\
405                         |111111111111111111|              |   |
406                         |222 Texture 222222| boxed empty  | texture height
407                         |3333 Data 33333333|              |   |
408                         |444444444444444444|              |   \/
409                         -----------------------------------   |
410                         |     boxed  empty | boxed empty  | pow2height
411                         |                  |              |   \/
412                         -----------------------------------
413         
414         
415                         were repacking the data to the expected texture width
416         
417                         |<-texture width ->|  -->pow2width|   /\
418                         |111111111111111111222222222222222|   |
419                         |222333333333333333333444444444444| texture height
420                         |444444                           |   |
421                         |                                 |   \/
422                         |                                 |   |
423                         |            empty                | pow2height
424                         |                                 |   \/
425                         -----------------------------------
426         
427                         == is the same as
428         
429                         |<-texture width ->|    /\
430                         |111111111111111111|
431                         |222222222222222222|texture height
432                         |333333333333333333|
433                         |444444444444444444|    \/
434                         --------------------
435         
436                         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.
437         
438                         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.
439                         */
440                         if (This->nonpow2) {
441                             BYTE* dataa, *datab;
442                             int pitcha = 0, pitchb = 0;
443                             int y;
444                             pitcha = This->bytesPerPixel * This->currentDesc.Width;
445                             pitchb = This->bytesPerPixel * This->pow2Width;
446                             datab = dataa = This->resource.allocatedMemory;
447                             FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, pitcha, pitchb);
448                             for (y = 1 ; y < This->currentDesc.Height; y++) {
449                                 dataa += pitcha; /* skip the first row */
450                                 datab += pitchb;
451                                 memcpy(dataa, datab, pitcha);
452                             }
453                         }
454                     }
455                 }
456                 LEAVE_GL();
457             }
458         } else { /* Nothing to do */
459             TRACE("Memory %p already allocted for texture\n",  This->resource.allocatedMemory);
460         }
461
462         if (NULL == pRect) {
463             pLockedRect->pBits = This->resource.allocatedMemory;
464         }  else{
465             if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
466                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
467             } else {
468                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
469             }
470         }
471
472     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage && !(Flags&WINED3DLOCK_DISCARD)) { /* render surfaces */
473
474         GLint  prev_store;
475         GLint  prev_read;
476         BOOL notInContext = FALSE;
477         IWineD3DSwapChainImpl *targetSwapChain = NULL;
478
479
480         ENTER_GL();
481
482             /**
483              * for render->surface copy begin to begin of allocatedMemory
484              * unlock can be more easy
485              */
486
487         TRACE("locking a render target\n");
488
489         if (This->resource.allocatedMemory == NULL)
490                 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
491
492         This->activeLock = TRUE; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
493         pLockedRect->pBits = This->resource.allocatedMemory;
494
495         glFlush();
496         vcheckGLcall("glFlush");
497         glGetIntegerv(GL_READ_BUFFER, &prev_read);
498         vcheckGLcall("glIntegerv");
499         glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
500         vcheckGLcall("glIntegerv");
501
502  /* Here's what we have to do:
503             See if the swapchain has the same context as the renderTarget or the surface is the render target.
504             Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
505             and use the front back buffer as required.
506             if not, we need to switch contexts and then switchback at the end.
507          */
508         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
509         IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
510
511         /* 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! */
512         if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
513                 if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
514                     TRACE("locking back buffer\n");
515                    glReadBuffer(GL_BACK);
516                 } else if (iface == swapchain->frontBuffer) {
517                    TRACE("locking front\n");
518                    glReadBuffer(GL_FRONT);
519                 } else if (iface == myDevice->depthStencilBuffer) {
520                     FIXME("Stencil Buffer lock unsupported for now\n");
521                 } else {
522                    FIXME("(%p) Shouldn't have got here!\n", This);
523                    glReadBuffer(GL_BACK);
524                 }
525         } else if (swapchain != NULL) {
526             IWineD3DSwapChainImpl *implSwapChain;
527             IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
528             if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
529                     /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
530                     if (iface == swapchain->backBuffer) {
531                         glReadBuffer(GL_BACK);
532                     } else if (iface == swapchain->frontBuffer) {
533                         glReadBuffer(GL_FRONT);
534                     } else if (iface == myDevice->depthStencilBuffer) {
535                         FIXME("Stencil Buffer lock unsupported for now\n");
536                     } else {
537                         FIXME("Should have got here!\n");
538                         glReadBuffer(GL_BACK);
539                     }
540             } else {
541                 /* We need to switch contexts to be able to read the buffer!!! */
542                 FIXME("The buffer requested isn't in the current openGL context\n");
543                 notInContext = TRUE;
544                 /* TODO: check the contexts, to see if were shared with the current context */
545             }
546             IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
547         }
548         if (swapchain != NULL)       IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
549         if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
550
551
552         /** the depth stencil in openGL has a format of GL_FLOAT
553         * which should be good for WINED3DFMT_D16_LOCKABLE
554         * and WINED3DFMT_D16
555         * it is unclear what format the stencil buffer is in except.
556         * 'Each index is converted to fixed point...
557         * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
558         * mappings in the table GL_PIXEL_MAP_S_TO_S.
559         * glReadPixels(This->lockedRect.left,
560         *             This->lockedRect.bottom - j - 1,
561         *             This->lockedRect.right - This->lockedRect.left,
562         *             1,
563         *             GL_DEPTH_COMPONENT,
564         *             type,
565         *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
566             *****************************************/
567         if (!notInContext) { /* Only read the buffer if it's in the current context */
568             long j;
569 #if 0
570             /* 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,
571             *  This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
572             *  run ten times faster!
573             * ************************************/
574             BOOL ati_performance_hack = FALSE;
575             ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
576 #endif
577             if ((This->lockedRect.left == 0 &&  This->lockedRect.top == 0 &&
578                 This->lockedRect.right == This->currentDesc.Width
579                 && This->lockedRect.bottom ==  This->currentDesc.Height)) {
580                     glReadPixels(0, 0,
581                     This->currentDesc.Width,
582                     This->currentDesc.Height,
583                     This->glDescription.glFormat,
584                     This->glDescription.glType,
585                     (char *)pLockedRect->pBits);
586             } else if (This->lockedRect.left == 0 &&  This->lockedRect.right == This->currentDesc.Width) {
587                     glReadPixels(0,
588                     This->lockedRect.top,
589                     This->currentDesc.Width,
590                     This->currentDesc.Height,
591                     This->glDescription.glFormat,
592                     This->glDescription.glType,
593                     (char *)pLockedRect->pBits);
594             } else{
595
596                 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
597                     glReadPixels(This->lockedRect.left, 
598                                  This->lockedRect.bottom - j - 1, 
599                                  This->lockedRect.right - This->lockedRect.left, 
600                                  1,
601                                  This->glDescription.glFormat,
602                                  This->glDescription.glType,
603                                  (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
604
605                 }
606             }
607             vcheckGLcall("glReadPixels");
608             TRACE("Resetting buffer\n");
609             glReadBuffer(prev_read);
610             vcheckGLcall("glReadBuffer");
611         }
612         LEAVE_GL();
613
614     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
615
616         if (!messages & 1) {
617             FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
618             /*
619
620             glReadPixels(This->lockedRect.left,
621             This->lockedRect.bottom - j - 1,
622             This->lockedRect.right - This->lockedRect.left,
623             1,
624             GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
625
626             )
627             */
628             messages |= 1;
629         }
630     } else {
631         FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
632     }
633
634     if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
635         /* Don't dirtify */
636     } else {
637         IWineD3DBaseTexture *pBaseTexture;
638         /**
639          * Dirtify on lock
640          * as seen in msdn docs
641          */
642         IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
643
644         /** Dirtify Container if needed */
645         if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
646             TRACE("Making container dirty\n");
647             IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
648             IWineD3DBaseTexture_Release(pBaseTexture);
649         } else {
650             TRACE("Surface is standalone, no need to dirty the container\n");
651         }
652     }
653
654     TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Dirty);
655
656     This->locked = TRUE;
657     return WINED3D_OK;
658 }
659
660 HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
661     GLint skipBytes = 0;
662     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
663     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
664     const char *buffername = "";
665     IWineD3DSwapChainImpl *swapchain = NULL;
666
667     if (FALSE == This->locked) {
668         WARN("trying to Unlock an unlocked surf@%p\n", This);
669         return WINED3DERR_INVALIDCALL;
670     }
671
672     if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
673         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
674
675         if ((swapchain != NULL) &&  iface ==  swapchain->backBuffer) {
676                 buffername = "backBuffer";
677         } else if ((swapchain != NULL) && iface ==  swapchain->frontBuffer) {
678                 buffername = "frontBuffer";
679         } else if (iface == myDevice->depthStencilBuffer) {
680                 buffername = "depthStencilBuffer";
681         } else if (iface == myDevice->renderTarget) {
682                 buffername = "renderTarget";
683         }
684     }
685
686     if (swapchain != NULL) {
687         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
688     }
689
690     TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Dirty);
691
692     if (FALSE == This->Dirty) {
693         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
694         goto unlock_end;
695     }
696
697     if (0 == This->resource.usage) { /* classic surface */
698         /**
699          * nothing to do
700          * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
701          */
702     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
703
704         /****************************
705         * TODO: Render targets are 'special' and
706         * ?some? locking needs to be passed onto the context manager
707         * so that it becomes possible to use auxiliary buffers, pbuffers
708         * render-to-texture, shared, cached contexts etc...
709         * ****************************/
710         IWineD3DSwapChainImpl *implSwapChain;
711         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
712
713         if (iface ==  implSwapChain->backBuffer || iface ==  implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
714             GLint  prev_store;
715             GLint  prev_draw;
716             GLint  prev_rasterpos[4];
717
718             ENTER_GL();
719
720             glFlush();
721             vcheckGLcall("glFlush");
722             glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
723             vcheckGLcall("glIntegerv");
724             glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
725             vcheckGLcall("glIntegerv");
726             glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
727             vcheckGLcall("glIntegerv");
728             glPixelZoom(1.0, -1.0);
729             vcheckGLcall("glPixelZoom");
730
731             /* glDrawPixels transforms the raster position as though it was a vertex -
732                we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
733                per drawprim (and leave set - it will sort itself out due to last_was_rhw */
734             if ( (!myDevice->last_was_rhw) || (myDevice->viewport_changed) ) {
735
736                 double X, Y, height, width, minZ, maxZ;
737                 myDevice->last_was_rhw = TRUE;
738                 myDevice->viewport_changed = FALSE;
739
740                 /* Transformed already into viewport coordinates, so we do not need transform
741                    matrices. Reset all matrices to identity and leave the default matrix in world
742                    mode.                                                                         */
743                 glMatrixMode(GL_MODELVIEW);
744                 checkGLcall("glMatrixMode");
745                 glLoadIdentity();
746                 checkGLcall("glLoadIdentity");
747
748                 glMatrixMode(GL_PROJECTION);
749                 checkGLcall("glMatrixMode");
750                 glLoadIdentity();
751                 checkGLcall("glLoadIdentity");
752
753                 /* Set up the viewport to be full viewport */
754                 X      = myDevice->stateBlock->viewport.X;
755                 Y      = myDevice->stateBlock->viewport.Y;
756                 height = myDevice->stateBlock->viewport.Height;
757                 width  = myDevice->stateBlock->viewport.Width;
758                 minZ   = myDevice->stateBlock->viewport.MinZ;
759                 maxZ   = myDevice->stateBlock->viewport.MaxZ;
760                 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
761                 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
762                 checkGLcall("glOrtho");
763
764                 /* Window Coord 0 is the middle of the first pixel, so translate by half
765                    a pixel (See comment above glTranslate below)                         */
766                 glTranslatef(0.5, 0.5, 0);
767                 checkGLcall("glTranslatef(0.5, 0.5, 0)");
768             }
769
770             if (iface ==  implSwapChain->backBuffer || iface == myDevice->renderTarget) {
771                 glDrawBuffer(GL_BACK);
772             } else if (iface ==  implSwapChain->frontBuffer) {
773                 glDrawBuffer(GL_FRONT);
774             }
775
776             vcheckGLcall("glDrawBuffer");
777
778             /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
779             glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
780             glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
781
782             /* And back buffers are not blended */
783             glDisable(GL_BLEND);
784
785             glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
786             vcheckGLcall("glRasterPos2f");
787             switch (This->resource.format) {
788             case WINED3DFMT_X4R4G4B4:
789                 {
790                     int size;
791                     unsigned short *data;
792                     data = (unsigned short *)This->resource.allocatedMemory;
793                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
794                     while(size > 0) {
795                             *data |= 0xF000;
796                             data++;
797                             size--;
798                     }
799                 }
800             case WINED3DFMT_A4R4G4B4:
801                 {
802                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
803                                  GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV, This->resource.allocatedMemory);
804                     vcheckGLcall("glDrawPixels");
805                 }
806                 break;
807             case WINED3DFMT_R5G6B5:
808                 {
809                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
810                                  GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
811                     vcheckGLcall("glDrawPixels");
812                 }
813                 break;
814             case WINED3DFMT_X1R5G5B5:
815                 {
816                     int size;
817                     unsigned short *data;
818                     data = (unsigned short *)This->resource.allocatedMemory;
819                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
820                     while(size > 0) {
821                             *data |= 0x8000;
822                             data++;
823                             size--;
824                     }
825                 }
826             case WINED3DFMT_A1R5G5B5:
827                 {
828                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
829                                  GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, This->resource.allocatedMemory);
830                     vcheckGLcall("glDrawPixels");
831                 }
832                 break;
833             case WINED3DFMT_R8G8B8:
834                 {
835                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
836                                  GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
837                     vcheckGLcall("glDrawPixels");
838                 }
839                 break;
840             case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it 
841                                         could be any random value this fixes the intro move in Pirates! */
842                 {
843                     int size;
844                     unsigned int *data;
845                     data = (unsigned int *)This->resource.allocatedMemory;
846                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
847                     while(size > 0) {
848                             *data |= 0xFF000000;
849                             data++;
850                             size--;
851                     }
852                 }
853             case WINED3DFMT_A8R8G8B8:
854                 {
855                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
856                     vcheckGLcall("glPixelStorei");
857                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
858                                  GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
859                     vcheckGLcall("glDrawPixels");
860                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
861                     vcheckGLcall("glPixelStorei");
862                 }
863                 break;
864             case WINED3DFMT_A2R10G10B10:
865                 {
866                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
867                     vcheckGLcall("glPixelStorei");
868                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
869                                  GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, This->resource.allocatedMemory);
870                     vcheckGLcall("glDrawPixels");
871                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
872                     vcheckGLcall("glPixelStorei");
873                 }
874                 break;
875             default:
876                 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
877             }
878
879             glPixelZoom(1.0,1.0);
880             vcheckGLcall("glPixelZoom");
881             glDrawBuffer(prev_draw);
882             vcheckGLcall("glDrawBuffer");
883             glRasterPos3iv(&prev_rasterpos[0]);
884             vcheckGLcall("glRasterPos3iv");
885
886             /* Reset to previous pack row length / blending state */
887             glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
888             if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
889
890             LEAVE_GL();
891
892             /** restore clean dirty state */
893             IWineD3DSurface_CleanDirtyRect(iface);
894
895         } else {
896             FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
897         }
898         IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
899
900     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
901
902         if (iface == myDevice->depthStencilBuffer) {
903             FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
904         } else {
905             FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
906         }
907
908     } else {
909         FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
910     }
911
912     unlock_end:
913     This->locked = FALSE;
914     memset(&This->lockedRect, 0, sizeof(RECT));
915     return WINED3D_OK;
916 }
917
918 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
919     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
920     FIXME("No support for GetDC yet for surface %p\n", This);
921     return WINED3DERR_INVALIDCALL;
922 }
923
924 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
925     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
926     FIXME("No support for ReleaseDC yet for surface %p\n", This);
927     return WINED3DERR_INVALIDCALL;
928 }
929
930 /* ******************************************************
931    IWineD3DSurface Internal (No mapping to directx api) parts follow
932    ****************************************************** */
933 HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
934     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
935
936     if (This->inTexture) {
937         TRACE("Surface already in texture\n");
938         return WINED3D_OK;
939     }
940     if (This->Dirty == FALSE) {
941         TRACE("surface isn't dirty\n");
942         return WINED3D_OK;
943     }
944
945     This->Dirty = FALSE;
946
947     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
948     *  These resources are not bound by device size or format restrictions. Because of this,
949     *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
950     *  However, these resources can always be created, locked, and copied.
951     *  In general never store scratch or system mem textures in the video ram. However it is allowed
952     *  for system memory textures when WINED3DDEVCAPS_TEXTURESYSTEMMEMORY is set but it isn't right now.
953     */
954     if (This->resource.pool == WINED3DPOOL_SCRATCH || This->resource.pool == WINED3DPOOL_SYSTEMMEM)
955     {
956         FIXME("(%p) Operation not supported for scratch or SYSTEMMEM textures\n",This);
957         return WINED3DERR_INVALIDCALL;
958     }
959
960     if (This->inPBuffer) {
961         ENTER_GL();
962
963         if (This->glDescription.level != 0)
964             FIXME("Surface in texture is only supported for level 0\n");
965         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
966                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
967                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
968                  This->resource.format == WINED3DFMT_DXT5)
969             FIXME("Format %d not supported\n", This->resource.format);
970         else {
971             GLint prevRead;
972             glGetIntegerv(GL_READ_BUFFER, &prevRead);
973             vcheckGLcall("glGetIntegerv");
974             glReadBuffer(GL_BACK);
975             vcheckGLcall("glReadBuffer");
976
977             glCopyTexImage2D(This->glDescription.target,
978                              This->glDescription.level,
979                              This->glDescription.glFormatInternal,
980                              0,
981                              0,
982                              This->currentDesc.Width,
983                              This->currentDesc.Height,
984                              0);
985
986             checkGLcall("glCopyTexImage2D");
987             glReadBuffer(prevRead);
988             vcheckGLcall("glReadBuffer");
989             TRACE("Updating target %d\n", This->glDescription.target);
990             This->inTexture = TRUE;
991         }
992         LEAVE_GL();
993         return WINED3D_OK;
994     }
995
996     if ((This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) &&
997         !GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
998         /**
999          * wanted a paletted texture and not really support it in HW
1000          * so software emulation code begin
1001          */
1002         UINT i;
1003         PALETTEENTRY* pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
1004         VOID* surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->currentDesc.Width * This->currentDesc.Height * sizeof(DWORD));
1005         BYTE* dst = (BYTE*) surface;
1006         BYTE* src = (BYTE*) This->resource.allocatedMemory;
1007
1008         for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1009             BYTE color = *src++;
1010             *dst++ = pal[color].peRed;
1011             *dst++ = pal[color].peGreen;
1012             *dst++ = pal[color].peBlue;
1013             if (This->resource.format == WINED3DFMT_A8P8)
1014                 *dst++ = pal[color].peFlags;
1015             else
1016                 *dst++ = 0xFF;
1017         }
1018
1019         ENTER_GL();
1020
1021         TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1022               This->glDescription.target,
1023               This->glDescription.level,
1024               GL_RGBA,
1025               This->currentDesc.Width,
1026               This->currentDesc.Height,
1027               0,
1028               GL_RGBA,
1029               GL_UNSIGNED_BYTE,
1030               surface);
1031         glTexImage2D(This->glDescription.target,
1032                      This->glDescription.level,
1033                      GL_RGBA,
1034                      This->currentDesc.Width,
1035                      This->currentDesc.Height,
1036                      0,
1037                      GL_RGBA,
1038                      GL_UNSIGNED_BYTE,
1039                      surface);
1040         checkGLcall("glTexImage2D");
1041         HeapFree(GetProcessHeap(), 0, surface);
1042
1043         LEAVE_GL();
1044
1045         return WINED3D_OK;
1046     }
1047
1048     /* TODO: Compressed non-power 2 support */
1049
1050     if (This->resource.format == WINED3DFMT_DXT1 ||
1051         This->resource.format == WINED3DFMT_DXT2 ||
1052         This->resource.format == WINED3DFMT_DXT3 ||
1053         This->resource.format == WINED3DFMT_DXT4 ||
1054         This->resource.format == WINED3DFMT_DXT5) {
1055         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1056             FIXME("Using DXT1/3/5 without advertized support\n");
1057         } else if (This->resource.allocatedMemory) {
1058             TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
1059                   This->glDescription.target,
1060                   This->glDescription.level,
1061                   This->glDescription.glFormatInternal,
1062                   This->currentDesc.Width,
1063                   This->currentDesc.Height,
1064                   0,
1065                   This->resource.size,
1066                   This->resource.allocatedMemory);
1067
1068             ENTER_GL();
1069
1070             GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
1071                                                   This->glDescription.level,
1072                                                   This->glDescription.glFormatInternal,
1073                                                   This->currentDesc.Width,
1074                                                   This->currentDesc.Height,
1075                                                   0,
1076                                                   This->resource.size,
1077                                                   This->resource.allocatedMemory);
1078             checkGLcall("glCommpressedTexImage2D");
1079
1080             LEAVE_GL();
1081
1082             if(This->activeLock == FALSE){
1083                 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1084                 This->resource.allocatedMemory = NULL;
1085             }
1086         }
1087     } else {
1088
1089        /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
1090         if (NP2_REPACK == wined3d_settings.nonpower2_mode && This->nonpow2 == TRUE) {
1091
1092
1093             TRACE("non power of two support\n");
1094             ENTER_GL();
1095             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,
1096                 This->glDescription.target,
1097                 This->glDescription.level,
1098                 debug_d3dformat(This->resource.format),
1099                 This->glDescription.glFormatInternal,
1100                 This->pow2Width,
1101                 This->pow2Height,
1102                 0,
1103                 This->glDescription.glFormat,
1104                 This->glDescription.glType,
1105                 NULL);
1106
1107             glTexImage2D(This->glDescription.target,
1108                          This->glDescription.level,
1109                          This->glDescription.glFormatInternal,
1110                          This->pow2Width,
1111                          This->pow2Height,
1112                          0/*border*/,
1113                          This->glDescription.glFormat,
1114                          This->glDescription.glType,
1115                          NULL);
1116
1117             checkGLcall("glTexImage2D");
1118             if (This->resource.allocatedMemory != NULL) {
1119                 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
1120                 /* And map the non-power two data into the top left corner */
1121                 glTexSubImage2D(
1122                     This->glDescription.target,
1123                     This->glDescription.level,
1124                     0 /* xoffset */,
1125                     0 /* ysoffset */ ,
1126                     This->currentDesc.Width,
1127                     This->currentDesc.Height,
1128                     This->glDescription.glFormat,
1129                     This->glDescription.glType,
1130                     This->resource.allocatedMemory
1131                 );
1132                 checkGLcall("glTexSubImage2D");
1133             }
1134             LEAVE_GL();
1135
1136         } else {
1137
1138             TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1139                 This->glDescription.target,
1140                 This->glDescription.level,
1141                 debug_d3dformat(This->resource.format),
1142                 This->glDescription.glFormatInternal,
1143                 This->pow2Width,
1144                 This->pow2Height,
1145                 0,
1146                 This->glDescription.glFormat,
1147                 This->glDescription.glType,
1148                 This->resource.allocatedMemory);
1149
1150             ENTER_GL();
1151             glTexImage2D(This->glDescription.target,
1152                         This->glDescription.level,
1153                         This->glDescription.glFormatInternal,
1154                         This->pow2Width,
1155                         This->pow2Height,
1156                         0 /* border */,
1157                         This->glDescription.glFormat,
1158                         This->glDescription.glType,
1159                         This->resource.allocatedMemory);
1160             checkGLcall("glTexImage2D");
1161             LEAVE_GL();
1162         }
1163
1164 #if 0
1165         {
1166             static unsigned int gen = 0;
1167             char buffer[4096];
1168             ++gen;
1169             if ((gen % 10) == 0) {
1170                 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1171                 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1172             }
1173             /*
1174              * debugging crash code
1175             if (gen == 250) {
1176               void** test = NULL;
1177               *test = 0;
1178             }
1179             */
1180         }
1181 #endif
1182         if(This->activeLock == FALSE){
1183             HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1184             This->resource.allocatedMemory = NULL;
1185         }
1186
1187     }
1188
1189     return WINED3D_OK;
1190 }
1191
1192 #include <errno.h>
1193 #include <stdio.h>
1194 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1195     FILE* f = NULL;
1196     UINT i, y;
1197     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1198     char *allocatedMemory;
1199     char *textureRow;
1200     IWineD3DSwapChain *swapChain = NULL;
1201     int width, height;
1202     GLuint tmpTexture;
1203     DWORD color;
1204     /*FIXME:
1205     Textures my not be stored in ->allocatedgMemory and a GlTexture
1206     so we should lock the surface before saving a snapshot, or at least check that
1207     */
1208     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1209     by calling GetTexImage and in compressed form by calling
1210     GetCompressedTexImageARB.  Queried compressed images can be saved and
1211     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
1212     texture images do not need to be processed by the GL and should
1213     significantly improve texture loading performance relative to uncompressed
1214     images. */
1215
1216 /* Setup the width and height to be the internal texture width and height. */
1217     width  = This->pow2Width;
1218     height = This->pow2Height;
1219 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1220     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1221
1222     if (swapChain || This->inPBuffer) { /* if were not a real texture then read the back buffer into a real texture*/
1223 /* 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 */
1224         GLint prevRead;
1225         ENTER_GL();
1226         FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1227         glEnable(GL_TEXTURE_2D);
1228
1229         glGenTextures(1, &tmpTexture);
1230         glBindTexture(GL_TEXTURE_2D, tmpTexture);
1231
1232         glTexImage2D(GL_TEXTURE_2D,
1233                         0,
1234                         GL_RGBA,
1235                         width,
1236                         height,
1237                         0/*border*/,
1238                         GL_RGBA,
1239                         GL_UNSIGNED_INT_8_8_8_8_REV,
1240                         NULL);
1241
1242         glGetIntegerv(GL_READ_BUFFER, &prevRead);
1243         vcheckGLcall("glGetIntegerv");
1244         glReadBuffer(GL_BACK);
1245         vcheckGLcall("glReadBuffer");
1246         glCopyTexImage2D(GL_TEXTURE_2D,
1247                             0,
1248                             GL_RGBA,
1249                             0,
1250                             0,
1251                             width,
1252                             height,
1253                             0);
1254
1255         checkGLcall("glCopyTexImage2D");
1256         glReadBuffer(prevRead);
1257         LEAVE_GL();
1258
1259     } else { /* bind the real texture */
1260         IWineD3DSurface_PreLoad(iface);
1261     }
1262     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
1263     ENTER_GL();
1264     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1265     glGetTexImage(GL_TEXTURE_2D,
1266                 This->glDescription.level,
1267                 GL_RGBA,
1268                 GL_UNSIGNED_INT_8_8_8_8_REV,
1269                 allocatedMemory);
1270     checkGLcall("glTexImage2D");
1271     if (tmpTexture) {
1272         glBindTexture(GL_TEXTURE_2D, 0);
1273         glDeleteTextures(1, &tmpTexture);
1274     }
1275     LEAVE_GL();
1276
1277     f = fopen(filename, "w+");
1278     if (NULL == f) {
1279         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1280         return WINED3DERR_INVALIDCALL;
1281     }
1282 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1283     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
1284 /* TGA header */
1285     fputc(0,f);
1286     fputc(0,f);
1287     fputc(2,f);
1288     fputc(0,f);
1289     fputc(0,f);
1290     fputc(0,f);
1291     fputc(0,f);
1292     fputc(0,f);
1293     fputc(0,f);
1294     fputc(0,f);
1295     fputc(0,f);
1296     fputc(0,f);
1297 /* short width*/
1298     fwrite(&width,2,1,f);
1299 /* short height */
1300     fwrite(&height,2,1,f);
1301 /* format rgba */
1302     fputc(0x20,f);
1303     fputc(0x28,f);
1304 /* raw data */
1305     /* 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*/
1306     if(swapChain)
1307         textureRow = allocatedMemory + (width * (height - 1) *4);
1308     else
1309         textureRow = allocatedMemory;
1310     for (y = 0 ; y < height; y++) {
1311         for (i = 0; i < width;  i++) {
1312             color = *((DWORD*)textureRow);
1313             fputc((color >> 16) & 0xFF, f); /* B */
1314             fputc((color >>  8) & 0xFF, f); /* G */
1315             fputc((color >>  0) & 0xFF, f); /* R */
1316             fputc((color >> 24) & 0xFF, f); /* A */
1317             textureRow += 4;
1318         }
1319         /* take two rows of the pointer to the texture memory */
1320         if(swapChain)
1321             (textureRow-= width << 3);
1322
1323     }
1324     TRACE("Closing file\n");
1325     fclose(f);
1326
1327     if(swapChain) {
1328         IWineD3DSwapChain_Release(swapChain);
1329     }
1330     HeapFree(GetProcessHeap(), 0, allocatedMemory);
1331     return WINED3D_OK;
1332 }
1333
1334 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1335     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1336     This->Dirty = FALSE;
1337     This->dirtyRect.left   = This->currentDesc.Width;
1338     This->dirtyRect.top    = This->currentDesc.Height;
1339     This->dirtyRect.right  = 0;
1340     This->dirtyRect.bottom = 0;
1341     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1342           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1343     return WINED3D_OK;
1344 }
1345
1346 /**
1347  *   Slightly inefficient way to handle multiple dirty rects but it works :)
1348  */
1349 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1350     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1351     IWineD3DBaseTexture *baseTexture = NULL;
1352     This->Dirty = TRUE;
1353     if (NULL != pDirtyRect) {
1354         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
1355         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
1356         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
1357         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1358     } else {
1359         This->dirtyRect.left   = 0;
1360         This->dirtyRect.top    = 0;
1361         This->dirtyRect.right  = This->currentDesc.Width;
1362         This->dirtyRect.bottom = This->currentDesc.Height;
1363     }
1364     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1365           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1366     /* if the container is a basetexture then mark it dirty. */
1367     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
1368         TRACE("Passing to conatiner\n");
1369         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1370         IWineD3DBaseTexture_Release(baseTexture);
1371     }
1372     return WINED3D_OK;
1373 }
1374
1375 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
1376     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1377
1378     TRACE("This %p, container %p\n", This, container);
1379
1380     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
1381
1382     TRACE("Setting container to %p from %p\n", container, This->container);
1383     This->container = container;
1384
1385     return WINED3D_OK;
1386 }
1387
1388 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
1389     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1390
1391     if (This->resource.format != WINED3DFMT_UNKNOWN) {
1392         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
1393         return WINED3DERR_INVALIDCALL;
1394     }
1395
1396     TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
1397     if (format == WINED3DFMT_UNKNOWN) {
1398         This->resource.size = 0;
1399     } else if (format == WINED3DFMT_DXT1) {
1400         /* DXT1 is half byte per pixel */
1401         This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4)) >> 1;
1402
1403     } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
1404                format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
1405         This->resource.size = ((max(This->pow2Width, 4) * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * max(This->pow2Height, 4));
1406     } else {
1407         This->resource.size = (This->pow2Width * D3DFmtGetBpp(This->resource.wineD3DDevice, format)) * This->pow2Height;
1408     }
1409
1410
1411     /* Setup some glformat defaults */
1412     if (format != WINED3DFMT_UNKNOWN) {
1413         This->glDescription.glFormat         = D3DFmt2GLFmt(This->resource.wineD3DDevice, format);
1414         This->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This->resource.wineD3DDevice, format);
1415         This->glDescription.glType           = D3DFmt2GLType(This->resource.wineD3DDevice, format);
1416     } else {
1417         This->glDescription.glFormat         = 0;
1418         This->glDescription.glFormatInternal = 0;
1419         This->glDescription.glType           = 0;
1420     }
1421
1422     if (format != WINED3DFMT_UNKNOWN) {
1423         This->bytesPerPixel = D3DFmtGetBpp(This->resource.wineD3DDevice, format);
1424         This->pow2Size      = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
1425     } else {
1426         This->bytesPerPixel = 0;
1427         This->pow2Size      = 0;
1428     }
1429
1430     This->lockable = (WINED3DFMT_D16_LOCKABLE == format) ? TRUE : This->lockable;
1431
1432     This->resource.format = format;
1433
1434     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);
1435
1436     return WINED3D_OK;
1437 }
1438
1439 /* TODO: replace this function with context management routines */
1440 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
1441     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1442
1443     This->inPBuffer = inPBuffer;
1444     This->inTexture = inTexture;
1445     return WINED3D_OK;
1446 }
1447
1448 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
1449 {
1450     /* IUnknown */
1451     IWineD3DSurfaceImpl_QueryInterface,
1452     IWineD3DSurfaceImpl_AddRef,
1453     IWineD3DSurfaceImpl_Release,
1454     /* IWineD3DResource */
1455     IWineD3DSurfaceImpl_GetParent,
1456     IWineD3DSurfaceImpl_GetDevice,
1457     IWineD3DSurfaceImpl_SetPrivateData,
1458     IWineD3DSurfaceImpl_GetPrivateData,
1459     IWineD3DSurfaceImpl_FreePrivateData,
1460     IWineD3DSurfaceImpl_SetPriority,
1461     IWineD3DSurfaceImpl_GetPriority,
1462     IWineD3DSurfaceImpl_PreLoad,
1463     IWineD3DSurfaceImpl_GetType,
1464     /* IWineD3DSurface */
1465     IWineD3DSurfaceImpl_GetContainerParent,
1466     IWineD3DSurfaceImpl_GetContainer,
1467     IWineD3DSurfaceImpl_GetDesc,
1468     IWineD3DSurfaceImpl_LockRect,
1469     IWineD3DSurfaceImpl_UnlockRect,
1470     IWineD3DSurfaceImpl_GetDC,
1471     IWineD3DSurfaceImpl_ReleaseDC,
1472     /* Internal use: */
1473     IWineD3DSurfaceImpl_CleanDirtyRect,
1474     IWineD3DSurfaceImpl_AddDirtyRect,
1475     IWineD3DSurfaceImpl_LoadTexture,
1476     IWineD3DSurfaceImpl_SaveSnapshot,
1477     IWineD3DSurfaceImpl_SetContainer,
1478     IWineD3DSurfaceImpl_SetPBufferState,
1479     IWineD3DSurfaceImpl_SetGlTextureDesc,
1480     IWineD3DSurfaceImpl_GetGlDesc,
1481     IWineD3DSurfaceImpl_GetData,
1482     IWineD3DSurfaceImpl_SetFormat
1483 };