Remove redundant check.
[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_IWineD3DResource)
44         || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
45         IUnknown_AddRef((IUnknown*)iface);
46         *ppobj = This;
47         return D3D_OK;
48     }
49     return E_NOINTERFACE;
50 }
51
52 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
53     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
54     ULONG ref = InterlockedIncrement(&This->resource.ref);
55     TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
56     return ref;
57 }
58
59 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
60     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
61     ULONG ref = InterlockedDecrement(&This->resource.ref);
62     TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
63     if (ref == 0) {
64         TRACE("(%p) : cleaning up\n", This);
65         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
66             ENTER_GL();
67             TRACE("Deleting texture %d\n", This->glDescription.textureName);
68             glDeleteTextures(1, &This->glDescription.textureName);
69             LEAVE_GL();
70         }
71         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
72
73         TRACE("(%p) Released\n", This);
74         HeapFree(GetProcessHeap(), 0, This);
75
76     }
77     return ref;
78 }
79
80 /* ****************************************************
81    IWineD3DSurface IWineD3DResource parts follow
82    **************************************************** */
83 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
84     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
85 }
86
87 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
88     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
89 }
90
91 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
92     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
93 }
94
95 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
96     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
97 }
98
99 DWORD   WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
100     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
101 }
102
103 DWORD   WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
104     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
105 }
106
107 void    WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
108     /* TODO: re-write the way textures and managed,
109     *  use a 'opengl context manager' to manage RenderTarget surfaces
110     ** *********************************************************/
111
112     /* TODO: check for locks */
113     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
114     IWineD3DBaseTexture *baseTexture = NULL;
115     TRACE("(%p)Checking to see if the container is a base texture\n", This);
116     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == D3D_OK) {
117         TRACE("Passing to conatiner\n");
118         IWineD3DBaseTexture_PreLoad(baseTexture);
119         IWineD3DBaseTexture_Release(baseTexture);
120     } else {
121     TRACE("(%p) : About to load surface\n", This);
122     ENTER_GL();
123 #if 0 /* TODO: context manager support */
124      IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
125 #endif
126     glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
127     if (This->glDescription.level == 0 &&  This->glDescription.textureName == 0) {
128           glGenTextures(1, &This->glDescription.textureName);
129           checkGLcall("glGenTextures");
130           TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
131           glBindTexture(This->glDescription.target, This->glDescription.textureName);
132           checkGLcall("glBindTexture");
133           IWineD3DSurface_LoadTexture(iface);
134           /* This is where we should be reducing the amount of GLMemoryUsed */
135     } else {
136         if (This->glDescription.level == 0) {
137           glBindTexture(This->glDescription.target, This->glDescription.textureName);
138           checkGLcall("glBindTexture");
139           IWineD3DSurface_LoadTexture(iface);
140         } else  if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
141             /* assume this is a coding error not a real error for now */
142             FIXME("Mipmap surface has a glTexture bound to it!\n");
143         }
144     }
145     if (This->resource.pool == D3DPOOL_DEFAULT) {
146        /* Tell opengl to try and keep this texture in video ram (well mostly) */
147        GLclampf tmp;
148        tmp = 0.9f;
149         glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
150     }
151     /* TODO: disable texture support, if it wastn't enabled when we entered. */
152 #if 0 /* TODO: context manager support */
153      IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
154               /* we don't care when the state is disabled(if atall) */);
155 #endif
156     LEAVE_GL();
157     }
158     return;
159 }
160
161 D3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
162     TRACE("(%p) : calling resourceimpl_GetType\n", iface);
163     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
164 }
165
166 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
167     TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
168     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
169 }
170
171 /* ******************************************************
172    IWineD3DSurface IWineD3DSurface parts follow
173    ****************************************************** */
174
175 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
176     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
177     HRESULT hr;
178     if (ppContainer == NULL) {
179             ERR("Get container called witout a null ppContainer\n");
180         return E_NOINTERFACE;
181     }
182     TRACE("(%p) : Relaying to queryInterface %p %p\n", This, ppContainer, *ppContainer);
183     /** From MSDN:
184      * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
185      * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
186      * GetContainer will return the Direct3D device used to create the surface.
187      */
188     hr = IUnknown_QueryInterface(This->container, riid, ppContainer);
189     return hr;
190 }
191
192 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
193     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
194
195     TRACE("(%p) : copying into %p\n", This, pDesc);
196     if(pDesc->Format != NULL)             *(pDesc->Format) = This->resource.format;
197     if(pDesc->Type != NULL)               *(pDesc->Type)   = This->resource.resourceType;
198     if(pDesc->Usage != NULL)              *(pDesc->Usage)              = This->resource.usage;
199     if(pDesc->Pool != NULL)               *(pDesc->Pool)               = This->resource.pool;
200     if(pDesc->Size != NULL)               *(pDesc->Size)               = This->resource.size;   /* dx8 only */
201     if(pDesc->MultiSampleType != NULL)    *(pDesc->MultiSampleType)    = This->currentDesc.MultiSampleType;
202     if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
203     if(pDesc->Width != NULL)              *(pDesc->Width)              = This->currentDesc.Width;
204     if(pDesc->Height != NULL)             *(pDesc->Height)             = This->currentDesc.Height;
205     return D3D_OK;
206 }
207
208 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
209     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
210     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
211     if (This->glDescription.textureName == 0 && textureName != 0) {
212         This->Dirty = TRUE;
213         IWineD3DSurface_AddDirtyRect(iface, NULL);
214     }
215     This->glDescription.textureName = textureName;
216     This->glDescription.target      = target;
217 }
218
219 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
220     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
221     TRACE("(%p) : returning %p\n", This, &This->glDescription);
222     *glDescription = &This->glDescription;
223 }
224
225 /* TODO: think about moving this down to resource? */
226 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
227     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
228     /* 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  */
229     if (This->resource.pool != D3DPOOL_SYSTEMMEM) {
230         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
231     }
232     return (CONST void*)(This->resource.allocatedMemory);
233 }
234
235 HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
236     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
237     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
238     IWineD3DSwapChainImpl *swapchain = NULL;
239     static UINT messages = 0; /* holds flags to disable fixme messages */
240
241     /* fixme: should we really lock as such? */
242     if (This->inTexture && This->inPBuffer) {
243         FIXME("Warning: Surface is in texture memory or pbuffer\n");
244         This->inTexture = 0;
245         This->inPBuffer = 0;
246     }
247
248     if (FALSE == This->lockable) {
249         /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
250               texture regions, and since the destination is an unlockable region we need
251               to tolerate this                                                           */
252         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
253         /*return D3DERR_INVALIDCALL; */
254     }
255
256     if (This->resource.usage & D3DUSAGE_RENDERTARGET) {
257         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
258
259         if (swapchain != NULL ||  iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
260             if (swapchain != NULL && iface ==  swapchain->backBuffer) {
261                 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
262             } else if (swapchain != NULL && iface ==  swapchain->frontBuffer) {
263                 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
264             } else if (iface == myDevice->renderTarget) {
265                 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
266             } else if (iface == myDevice->depthStencilBuffer) {
267                 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
268             }
269
270             if (NULL != swapchain) {
271                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
272             }
273             swapchain = NULL;
274         }
275     } else {
276         TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
277     }
278
279     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
280          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
281           ie pitch = (width/4) * bytes per block                                  */
282     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
283         pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 3;
284     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
285              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
286         pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 4;
287     else
288         pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
289
290     if (NULL == pRect) {
291         pLockedRect->pBits = This->resource.allocatedMemory;
292         This->lockedRect.left   = 0;
293         This->lockedRect.top    = 0;
294         This->lockedRect.right  = This->currentDesc.Width;
295         This->lockedRect.bottom = This->currentDesc.Height;
296         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);
297     } else {
298         TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
299
300         if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
301             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
302         } else {
303             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
304         }
305         This->lockedRect.left   = pRect->left;
306         This->lockedRect.top    = pRect->top;
307         This->lockedRect.right  = pRect->right;
308         This->lockedRect.bottom = pRect->bottom;
309     }
310
311     if (This->nonpow2) {
312         TRACE("Locking non-power 2 texture\n");
313     }
314
315     if (0 == This->resource.usage || This->resource.usage & D3DUSAGE_DYNAMIC) {
316         /* classic surface  TODO: non 2d surfaces?
317         Thease resources may be POOL_SYSTEMMEM, so they must not access the device */
318         TRACE("locking an ordinarary surface\n");
319         /* Check to see if memory has already been allocated fro the sufrace*/
320         if (NULL == This->resource.allocatedMemory) { /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
321             /* Non-systemmemory surfaces */
322
323             /*Surface has no memory currently allocate to it!*/
324             TRACE("(%p) Locking rect\n" , This);
325             This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
326
327             /*Now I have to copy thing bits back*/  
328             This->activeLock = TRUE; /* When this flag is set to true, laoding the surface again won't free THis->resource.allocatedMemory */
329             /* TODO: make activeLock a bit more intelegent, maybe implement a method to purge the texture memory. */
330             ENTER_GL();
331
332             /* Make sure that the texture is loaded */
333             IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
334
335             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);
336
337             if (This->resource.format == WINED3DFMT_DXT1 ||
338                 This->resource.format == WINED3DFMT_DXT2 ||
339                 This->resource.format == WINED3DFMT_DXT3 ||
340                 This->resource.format == WINED3DFMT_DXT4 ||
341                 This->resource.format == WINED3DFMT_DXT5) {
342                 TRACE("Locking a compressed texture\n");
343                 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
344                     GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
345                                                         This->glDescription.level,
346                                                         This->resource.allocatedMemory);
347
348                 } else {
349                     FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
350                 }
351             } else {
352                 glGetTexImage(This->glDescription.target,
353                             This->glDescription.level,
354                             This->glDescription.glFormat,
355                             This->glDescription.glType,
356                             This->resource.allocatedMemory);
357                 vcheckGLcall("glGetTexImage");
358             }
359             LEAVE_GL();
360         } else { /* Nothing to do */
361             TRACE("Memory %p already allocted for texture\n",  This->resource.allocatedMemory);
362         }
363
364         if (NULL == pRect) {
365             pLockedRect->pBits = This->resource.allocatedMemory;
366         }  else{
367             if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
368                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
369             } else {
370                 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
371             }
372         }
373
374     } else if (D3DUSAGE_RENDERTARGET & This->resource.usage && !(Flags&D3DLOCK_DISCARD)) { /* render surfaces */
375
376         GLint  prev_store;
377         GLint  prev_read;
378         BOOL notInContext = FALSE;
379         IWineD3DSwapChainImpl *targetSwapChain = NULL;
380
381
382         ENTER_GL();
383
384             /**
385              * for render->surface copy begin to begin of allocatedMemory
386              * unlock can be more easy
387              */
388
389         TRACE("locking a render target\n");
390
391         if (This->resource.allocatedMemory == NULL)
392                 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
393
394         This->activeLock = TRUE; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
395         pLockedRect->pBits = This->resource.allocatedMemory;
396
397         glFlush();
398         vcheckGLcall("glFlush");
399         glGetIntegerv(GL_READ_BUFFER, &prev_read);
400         vcheckGLcall("glIntegerv");
401         glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
402         vcheckGLcall("glIntegerv");
403
404  /* Here's what we have to do:
405             See if the swapchain has the same context as the renderTarget or the surface is the render target.
406             Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
407             and use the front back buffer as required.
408             if not, we need to switch contexts and then switchback at the end.
409          */
410         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
411         IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
412
413         /* 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! */
414         if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
415                 if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
416                     TRACE("locking back buffer\n");
417                    glReadBuffer(GL_BACK);
418                 } else if (iface == swapchain->frontBuffer) {
419                    TRACE("locking front\n");
420                    glReadBuffer(GL_FRONT);
421                 } else if (iface == myDevice->depthStencilBuffer) {
422                     FIXME("Stencil Buffer lock unsupported for now\n");
423                 } else {
424                    FIXME("(%p) Shouldn't have got here!\n", This);
425                    glReadBuffer(GL_BACK);
426                 }
427         } else if (swapchain != NULL) {
428             IWineD3DSwapChainImpl *implSwapChain;
429             IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
430             if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
431                     /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
432                     if (iface == swapchain->backBuffer) {
433                         glReadBuffer(GL_BACK);
434                     } else if (iface == swapchain->frontBuffer) {
435                         glReadBuffer(GL_FRONT);
436                     } else if (iface == myDevice->depthStencilBuffer) {
437                         FIXME("Stencil Buffer lock unsupported for now\n");
438                     } else {
439                         FIXME("Should have got here!\n");
440                         glReadBuffer(GL_BACK);
441                     }
442             } else {
443                 /* We need to switch contexts to be able to read the buffer!!! */
444                 FIXME("The buffer requested isn't in the current openGL context\n");
445                 notInContext = TRUE;
446                 /* TODO: check the contexts, to see if were shared with the current context */
447             }
448             IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
449         }
450         if (swapchain != NULL)       IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
451         if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
452
453
454         /** the depth stencil in openGL has a format of GL_FLOAT
455         * which should be good for WINED3DFMT_D16_LOCKABLE
456         * and WINED3DFMT_D16
457         * it is unclear what format the stencil buffer is in except.
458         * 'Each index is converted to fixed point...
459         * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
460         * mappings in the table GL_PIXEL_MAP_S_TO_S.
461         * glReadPixels(This->lockedRect.left,
462         *             This->lockedRect.bottom - j - 1,
463         *             This->lockedRect.right - This->lockedRect.left,
464         *             1,
465         *             GL_DEPTH_COMPONENT,
466         *             type,
467         *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
468             *****************************************/
469         if (!notInContext) { /* Only read the buffer if it's in the current context */
470             long j;
471 #if 0
472             /* 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,
473             *  This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
474             *  run ten times faster!
475             * ************************************/
476             BOOL ati_performance_hack = FALSE;
477             ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
478 #endif
479             if ((This->lockedRect.left == 0 &&  This->lockedRect.top == 0 &&
480                 This->lockedRect.right == This->currentDesc.Width
481                 && This->lockedRect.bottom ==  This->currentDesc.Height)) {
482                     glReadPixels(0, 0,
483                     This->currentDesc.Width,
484                     This->currentDesc.Height,
485                     This->glDescription.glFormat,
486                     This->glDescription.glType,
487                     (char *)pLockedRect->pBits);
488             } else if (This->lockedRect.left == 0 &&  This->lockedRect.right == This->currentDesc.Width) {
489                     glReadPixels(0,
490                     This->lockedRect.top,
491                     This->currentDesc.Width,
492                     This->currentDesc.Height,
493                     This->glDescription.glFormat,
494                     This->glDescription.glType,
495                     (char *)pLockedRect->pBits);
496             } else{
497
498                 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
499                     glReadPixels(This->lockedRect.left, 
500                                  This->lockedRect.bottom - j - 1, 
501                                  This->lockedRect.right - This->lockedRect.left, 
502                                  1,
503                                  This->glDescription.glFormat,
504                                  This->glDescription.glType,
505                                  (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
506
507                 }
508             }
509             vcheckGLcall("glReadPixels");
510             TRACE("Resetting buffer\n");
511             glReadBuffer(prev_read);
512             vcheckGLcall("glReadBuffer");
513         }
514         LEAVE_GL();
515
516     } else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
517
518         if (!messages & 1) {
519             FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
520             /*
521
522             glReadPixels(This->lockedRect.left,
523             This->lockedRect.bottom - j - 1,
524             This->lockedRect.right - This->lockedRect.left,
525             1,
526             GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
527
528             )
529             */
530             messages |= 1;
531         }
532     } else {
533         FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
534     }
535
536     if (Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY)) {
537         /* Don't dirtify */
538     } else {
539         IWineD3DBaseTexture *pBaseTexture;
540         /**
541          * Dirtify on lock
542          * as seen in msdn docs
543          */
544         IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
545
546         /** Dirtify Container if needed */
547         if (D3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
548             TRACE("Making container dirty\n");
549             IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
550             IWineD3DBaseTexture_Release(pBaseTexture);
551         } else {
552             TRACE("Surface is standalone, no need to dirty the container\n");
553         }
554     }
555
556     TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Dirty);
557
558     This->locked = TRUE;
559     return D3D_OK;
560 }
561
562 HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
563     GLint skipBytes = 0;
564     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
565     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
566     const char *buffername = "";
567     IWineD3DSwapChainImpl *swapchain = NULL;
568
569     if (FALSE == This->locked) {
570         WARN("trying to Unlock an unlocked surf@%p\n", This);
571         return D3DERR_INVALIDCALL;
572     }
573
574     if (D3DUSAGE_RENDERTARGET & This->resource.usage) {
575         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
576
577         if ((swapchain != NULL) &&  iface ==  swapchain->backBuffer) {
578                 buffername = "backBuffer";
579         } else if ((swapchain != NULL) && iface ==  swapchain->frontBuffer) {
580                 buffername = "frontBuffer";
581         } else if (iface == myDevice->depthStencilBuffer) {
582                 buffername = "depthStencilBuffer";
583         } else if (iface == myDevice->renderTarget) {
584                 buffername = "renderTarget";
585         }
586     }
587
588     if (swapchain != NULL) {
589         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
590     }
591
592     TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Dirty);
593
594     if (FALSE == This->Dirty) {
595         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
596         goto unlock_end;
597     }
598
599     if (0 == This->resource.usage) { /* classic surface */
600         /**
601          * nothing to do
602          * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
603          */
604     } else if (D3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
605
606         /****************************
607         * TODO: Render targets are 'special' and
608         * ?some? locking needs to be passed onto the context manager
609         * so that it becomes possible to use auxilary buffers, pbuffers
610         * render-to-texture, shared, cached contexts etc...
611         * ****************************/
612         IWineD3DSwapChainImpl *implSwapChain;
613         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
614
615         if (iface ==  implSwapChain->backBuffer || iface ==  implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
616             GLint  prev_store;
617             GLint  prev_draw;
618             GLint  prev_rasterpos[4];
619
620             ENTER_GL();
621
622             glFlush();
623             vcheckGLcall("glFlush");
624             glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
625             vcheckGLcall("glIntegerv");
626             glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
627             vcheckGLcall("glIntegerv");
628             glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
629             vcheckGLcall("glIntegerv");
630             glPixelZoom(1.0, -1.0);
631             vcheckGLcall("glPixelZoom");
632
633             /* glDrawPixels transforms the raster position as though it was a vertex -
634                we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
635                per drawprim (and leave set - it will sort itself out due to last_was_rhw */
636             if (!myDevice->last_was_rhw) {
637
638                 double X, Y, height, width, minZ, maxZ;
639                 myDevice->last_was_rhw = TRUE;
640
641                 /* Transformed already into viewport coordinates, so we do not need transform
642                    matrices. Reset all matrices to identity and leave the default matrix in world
643                    mode.                                                                         */
644                 glMatrixMode(GL_MODELVIEW);
645                 checkGLcall("glMatrixMode");
646                 glLoadIdentity();
647                 checkGLcall("glLoadIdentity");
648
649                 glMatrixMode(GL_PROJECTION);
650                 checkGLcall("glMatrixMode");
651                 glLoadIdentity();
652                 checkGLcall("glLoadIdentity");
653
654                 /* Set up the viewport to be full viewport */
655                 X      = myDevice->stateBlock->viewport.X;
656                 Y      = myDevice->stateBlock->viewport.Y;
657                 height = myDevice->stateBlock->viewport.Height;
658                 width  = myDevice->stateBlock->viewport.Width;
659                 minZ   = myDevice->stateBlock->viewport.MinZ;
660                 maxZ   = myDevice->stateBlock->viewport.MaxZ;
661                 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
662                 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
663                 checkGLcall("glOrtho");
664
665                 /* Window Coord 0 is the middle of the first pixel, so translate by half
666                    a pixel (See comment above glTranslate below)                         */
667                 glTranslatef(0.5, 0.5, 0);
668                 checkGLcall("glTranslatef(0.5, 0.5, 0)");
669             }
670
671             if (iface ==  implSwapChain->backBuffer || iface == myDevice->renderTarget) {
672                 glDrawBuffer(GL_BACK);
673             } else if (iface ==  implSwapChain->frontBuffer) {
674                 glDrawBuffer(GL_FRONT);
675             }
676
677             vcheckGLcall("glDrawBuffer");
678
679             /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
680             glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
681             glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
682
683             /* And back buffers are not blended */
684             glDisable(GL_BLEND);
685
686             glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
687             vcheckGLcall("glRasterPos2f");
688             switch (This->resource.format) {
689             case WINED3DFMT_R5G6B5:
690                 {
691                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
692                                  GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
693                     vcheckGLcall("glDrawPixels");
694                 }
695                 break;
696             case WINED3DFMT_R8G8B8:
697                 {
698                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
699                                  GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
700                     vcheckGLcall("glDrawPixels");
701                 }
702                 break;
703             case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it 
704                                         could be any random value this fixes the intro move in Pirates! */
705                 {
706                     int size;
707                     unsigned int *data;
708                     data = (unsigned int *)This->resource.allocatedMemory;
709                     size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
710                     while(size > 0) {
711                             *data |= 0xFF000000;
712                             data++;
713                             size--;
714                     }
715                 }
716             case WINED3DFMT_A8R8G8B8:
717                 {
718                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
719                     vcheckGLcall("glPixelStorei");
720                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
721                                  GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
722                     vcheckGLcall("glDrawPixels");
723                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
724                     vcheckGLcall("glPixelStorei");
725                 }
726                 break;
727             case WINED3DFMT_A2R10G10B10:
728                 {
729                     glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
730                     vcheckGLcall("glPixelStorei");
731                     glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
732                                  GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, This->resource.allocatedMemory);
733                     vcheckGLcall("glDrawPixels");
734                     glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
735                     vcheckGLcall("glPixelStorei");
736                 }
737                 break;
738             default:
739                 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
740             }
741
742             glPixelZoom(1.0,1.0);
743             vcheckGLcall("glPixelZoom");
744             glDrawBuffer(prev_draw);
745             vcheckGLcall("glDrawBuffer");
746             glRasterPos3iv(&prev_rasterpos[0]);
747             vcheckGLcall("glRasterPos3iv");
748
749             /* Reset to previous pack row length / blending state */
750             glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
751             if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
752
753             LEAVE_GL();
754
755             /** restore clean dirty state */
756             IWineD3DSurface_CleanDirtyRect(iface);
757
758         } else {
759             FIXME("unsupported unlocking to Rendering surface surf@%p usage(%lu)\n", This, This->resource.usage);
760         }
761         IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
762
763     } else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
764
765         if (iface == myDevice->depthStencilBuffer) {
766             FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
767         } else {
768             FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
769         }
770
771     } else {
772         FIXME("unsupported unlocking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
773     }
774
775     unlock_end:
776     This->locked = FALSE;
777     memset(&This->lockedRect, 0, sizeof(RECT));
778     return D3D_OK;
779 }
780
781 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
782     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
783     FIXME("No support for GetDC yet for surface %p\n", This);
784     return D3DERR_INVALIDCALL;
785 }
786
787 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
788     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
789     FIXME("No support for ReleaseDC yet for surface %p\n", This);
790     return D3DERR_INVALIDCALL;
791 }
792
793 /* ******************************************************
794    IWineD3DSurface Internal (No mapping to directx api) parts follow
795    ****************************************************** */
796 HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
797     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
798
799     if (This->inTexture) {
800         TRACE("Surface already in texture\n");
801         return D3D_OK;
802     }
803     if (This->Dirty == FALSE) {
804         TRACE("surface isn't dirty\n");
805         return D3D_OK;
806     }
807
808     This->Dirty = FALSE;
809
810     /* Resources are placed in system RAM and do not need to be recreated when a device is lost. These resources are not bound by device size or format restrictions. Because of this, these resources cannot be accessed by the Direct3D device nor set as textures or render targets. However, these resources can always be created, locked, and copied. */
811     if (This->resource.pool == D3DPOOL_SCRATCH || This->resource.pool == D3DPOOL_SYSTEMMEM) /*never store scratch or system mem textures in the video ram*/
812     {
813         FIXME("(%p) Opperation not supported for scratch or SYSTEMMEM textures\n",This);
814         return D3DERR_INVALIDCALL;
815     }
816
817     if (This->inPBuffer) {
818         ENTER_GL();
819
820         if (This->glDescription.level != 0)
821             FIXME("Surface in texture is only supported for level 0\n");
822         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
823                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
824                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
825                  This->resource.format == WINED3DFMT_DXT5)
826             FIXME("Format %d not supported\n", This->resource.format);
827         else {
828             GLint prevRead;
829             glGetIntegerv(GL_READ_BUFFER, &prevRead);
830             vcheckGLcall("glGetIntegerv");
831             glReadBuffer(GL_BACK);
832             vcheckGLcall("glReadBuffer");
833
834             glCopyTexImage2D(This->glDescription.target,
835                              This->glDescription.level,
836                              This->glDescription.glFormatInternal,
837                              0,
838                              0,
839                              This->currentDesc.Width,
840                              This->currentDesc.Height,
841                              0);
842
843             checkGLcall("glCopyTexImage2D");
844             glReadBuffer(prevRead);
845             vcheckGLcall("glReadBuffer");
846             TRACE("Updating target %d\n", This->glDescription.target);
847             This->inTexture = TRUE;
848         }
849         LEAVE_GL();
850         return D3D_OK;
851     }
852
853     if ((This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) &&
854         !GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
855         /**
856          * wanted a paletted texture and not really support it in HW
857          * so software emulation code begin
858          */
859         UINT i;
860         PALETTEENTRY* pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
861         VOID* surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->currentDesc.Width * This->currentDesc.Height * sizeof(DWORD));
862         BYTE* dst = (BYTE*) surface;
863         BYTE* src = (BYTE*) This->resource.allocatedMemory;
864
865         for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
866             BYTE color = *src++;
867             *dst++ = pal[color].peRed;
868             *dst++ = pal[color].peGreen;
869             *dst++ = pal[color].peBlue;
870             if (This->resource.format == WINED3DFMT_A8P8)
871                 *dst++ = pal[color].peFlags;
872             else
873                 *dst++ = 0xFF;
874         }
875
876         ENTER_GL();
877
878         TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
879               This->glDescription.target,
880               This->glDescription.level,
881               GL_RGBA,
882               This->currentDesc.Width,
883               This->currentDesc.Height,
884               0,
885               GL_RGBA,
886               GL_UNSIGNED_BYTE,
887               surface);
888         glTexImage2D(This->glDescription.target,
889                      This->glDescription.level,
890                      GL_RGBA,
891                      This->currentDesc.Width,
892                      This->currentDesc.Height,
893                      0,
894                      GL_RGBA,
895                      GL_UNSIGNED_BYTE,
896                      surface);
897         checkGLcall("glTexImage2D");
898         HeapFree(GetProcessHeap(), 0, surface);
899
900         LEAVE_GL();
901
902         return D3D_OK;
903     }
904
905     /* TODO: Compressed non-power 2 support */
906
907     if (This->resource.format == WINED3DFMT_DXT1 ||
908         This->resource.format == WINED3DFMT_DXT2 ||
909         This->resource.format == WINED3DFMT_DXT3 ||
910         This->resource.format == WINED3DFMT_DXT4 ||
911         This->resource.format == WINED3DFMT_DXT5) {
912         if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
913             TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
914                   This->glDescription.target,
915                   This->glDescription.level,
916                   This->glDescription.glFormatInternal,
917                   This->currentDesc.Width,
918                   This->currentDesc.Height,
919                   0,
920                   This->resource.size,
921                   This->resource.allocatedMemory);
922
923             ENTER_GL();
924
925             GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
926                                                   This->glDescription.level,
927                                                   This->glDescription.glFormatInternal,
928                                                   This->currentDesc.Width,
929                                                   This->currentDesc.Height,
930                                                   0,
931                                                   This->resource.size,
932                                                   This->resource.allocatedMemory);
933             checkGLcall("glCommpressedTexTexImage2D");
934
935             LEAVE_GL();
936
937             if(This->activeLock == FALSE){
938                 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
939                 This->resource.allocatedMemory = NULL;
940             }
941
942         } else {
943             FIXME("Using DXT1/3/5 without advertized support\n");
944         }
945     } else {
946
947        /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
948         if (This->nonpow2 == TRUE) {
949
950             TRACE("non power of two support\n");
951             ENTER_GL();
952             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,
953                 This->glDescription.target,
954                 This->glDescription.level,
955                 debug_d3dformat(This->resource.format),
956                 This->glDescription.glFormatInternal,
957                 This->pow2Width,
958                 This->pow2Height,
959                 0,
960                 This->glDescription.glFormat,
961                 This->glDescription.glType,
962                 NULL);
963
964             glTexImage2D(This->glDescription.target,
965                          This->glDescription.level,
966                          This->glDescription.glFormatInternal,
967                          This->pow2Width,
968                          This->pow2Height,
969                          0/*border*/,
970                          This->glDescription.glFormat,
971                          This->glDescription.glType,
972                          NULL);
973
974             checkGLcall("glTexImage2D");
975             if (This->resource.allocatedMemory != NULL) {
976                 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
977                 /* And map the non-power two data into the top left corner */
978                 glTexSubImage2D(
979                     This->glDescription.target,
980                     This->glDescription.level,
981                     0 /* xoffset */,
982                     0 /* ysoffset */ ,
983                     This->currentDesc.Width,
984                     This->currentDesc.Height,
985                     This->glDescription.glFormat,
986                     This->glDescription.glType,
987                     This->resource.allocatedMemory
988                 );
989                 checkGLcall("glTexSubImage2D");
990             }
991             LEAVE_GL();
992
993         } else {
994
995             TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
996                 This->glDescription.target,
997                 This->glDescription.level,
998                 debug_d3dformat(This->resource.format),
999                 This->glDescription.glFormatInternal,
1000                 This->currentDesc.Width,
1001                 This->currentDesc.Height,
1002                 0,
1003                 This->glDescription.glFormat,
1004                 This->glDescription.glType,
1005                 This->resource.allocatedMemory);
1006
1007             ENTER_GL();
1008             glTexImage2D(This->glDescription.target,
1009                         This->glDescription.level,
1010                         This->glDescription.glFormatInternal,
1011                         This->currentDesc.Width,
1012                         This->currentDesc.Height,
1013                         0 /* border */,
1014                         This->glDescription.glFormat,
1015                         This->glDescription.glType,
1016                         This->resource.allocatedMemory);
1017             checkGLcall("glTexImage2D");
1018             LEAVE_GL();
1019         }
1020
1021 #if 0
1022         {
1023             static unsigned int gen = 0;
1024             char buffer[4096];
1025             ++gen;
1026             if ((gen % 10) == 0) {
1027                 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1028                 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1029             }
1030             /*
1031              * debugging crash code
1032             if (gen == 250) {
1033               void** test = NULL;
1034               *test = 0;
1035             }
1036             */
1037         }
1038 #endif
1039         if(This->activeLock == FALSE){
1040             HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1041             This->resource.allocatedMemory = NULL;
1042         }
1043
1044     }
1045
1046     return D3D_OK;
1047 }
1048
1049 #include <errno.h>
1050 #include <stdio.h>
1051 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1052     FILE* f = NULL;
1053     ULONG i;
1054     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1055
1056     f = fopen(filename, "w+");
1057     if (NULL == f) {
1058         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1059         return D3DERR_INVALIDCALL;
1060     }
1061
1062     TRACE("opened %s with format %s\n", filename, debug_d3dformat(This->resource.format));
1063
1064     fprintf(f, "P6\n%u %u\n255\n", This->currentDesc.Width, This->currentDesc.Height);
1065     switch (This->resource.format) {
1066     case WINED3DFMT_X8R8G8B8:
1067     case WINED3DFMT_A8R8G8B8:
1068         {
1069             DWORD color;
1070             for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1071                 color = ((DWORD*) This->resource.allocatedMemory)[i];
1072                 fputc((color >> 16) & 0xFF, f);
1073                 fputc((color >>  8) & 0xFF, f);
1074                 fputc((color >>  0) & 0xFF, f);
1075             }
1076         }
1077         break;
1078     case WINED3DFMT_R8G8B8:
1079         {
1080             BYTE* color;
1081             for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1082                 color = ((BYTE*) This->resource.allocatedMemory) + (3 * i);
1083                 fputc((color[0]) & 0xFF, f);
1084                 fputc((color[1]) & 0xFF, f);
1085                 fputc((color[2]) & 0xFF, f);
1086             }
1087         }
1088         break;
1089     case WINED3DFMT_A1R5G5B5:
1090         {
1091             WORD color;
1092             for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1093                 color = ((WORD*) This->resource.allocatedMemory)[i];
1094                 fputc(((color >> 10) & 0x1F) * 255 / 31, f);
1095                 fputc(((color >>  5) & 0x1F) * 255 / 31, f);
1096                 fputc(((color >>  0) & 0x1F) * 255 / 31, f);
1097             }
1098         }
1099         break;
1100     case WINED3DFMT_A4R4G4B4:
1101         {
1102             WORD color;
1103             for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1104                 color = ((WORD*) This->resource.allocatedMemory)[i];
1105                 fputc(((color >>  8) & 0x0F) * 255 / 15, f);
1106                 fputc(((color >>  4) & 0x0F) * 255 / 15, f);
1107                 fputc(((color >>  0) & 0x0F) * 255 / 15, f);
1108             }
1109         }
1110         break;
1111
1112     case WINED3DFMT_R5G6B5:
1113         {
1114             WORD color;
1115             for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1116                 color = ((WORD*) This->resource.allocatedMemory)[i];
1117                 fputc(((color >> 11) & 0x1F) * 255 / 31, f);
1118                 fputc(((color >>  5) & 0x3F) * 255 / 63, f);
1119                 fputc(((color >>  0) & 0x1F) * 255 / 31, f);
1120             }
1121         }
1122         break;
1123     default:
1124         FIXME("Unimplemented dump mode format(%u,%s)\n", This->resource.format, debug_d3dformat(This->resource.format));
1125     }
1126     fclose(f);
1127     return D3D_OK;
1128 }
1129
1130 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1131     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1132     This->Dirty = FALSE;
1133     This->dirtyRect.left   = This->currentDesc.Width;
1134     This->dirtyRect.top    = This->currentDesc.Height;
1135     This->dirtyRect.right  = 0;
1136     This->dirtyRect.bottom = 0;
1137     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1138           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1139     return D3D_OK;
1140 }
1141
1142 /**
1143  *   Slightly inefficient way to handle multiple dirty rects but it works :)
1144  */
1145 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1146     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1147     IWineD3DBaseTexture *baseTexture = NULL;
1148     This->Dirty = TRUE;
1149     if (NULL != pDirtyRect) {
1150         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
1151         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
1152         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
1153         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1154     } else {
1155         This->dirtyRect.left   = 0;
1156         This->dirtyRect.top    = 0;
1157         This->dirtyRect.right  = This->currentDesc.Width;
1158         This->dirtyRect.bottom = This->currentDesc.Height;
1159     }
1160     TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1161           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1162     /* if the container is a basetexture then mark it dirty. */
1163     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == D3D_OK) {
1164         TRACE("Passing to conatiner\n");
1165         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1166         IWineD3DBaseTexture_Release(baseTexture);
1167     }
1168     return D3D_OK;
1169 }
1170
1171 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IUnknown *container) {
1172     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1173     TRACE("Setting container to %p from %p\n", container, This->container);
1174     This->container = container;
1175     return D3D_OK;
1176 }
1177
1178 /* TODO: replace this function with context management routines */
1179 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
1180     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1181
1182     This->inPBuffer = inPBuffer;
1183     This->inTexture = inTexture;
1184     return D3D_OK;
1185 }
1186
1187 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
1188 {
1189     /* IUnknown */
1190     IWineD3DSurfaceImpl_QueryInterface,
1191     IWineD3DSurfaceImpl_AddRef,
1192     IWineD3DSurfaceImpl_Release,
1193     /* IWineD3DResource */
1194     IWineD3DSurfaceImpl_GetParent,
1195     IWineD3DSurfaceImpl_GetDevice,
1196     IWineD3DSurfaceImpl_SetPrivateData,
1197     IWineD3DSurfaceImpl_GetPrivateData,
1198     IWineD3DSurfaceImpl_FreePrivateData,
1199     IWineD3DSurfaceImpl_SetPriority,
1200     IWineD3DSurfaceImpl_GetPriority,
1201     IWineD3DSurfaceImpl_PreLoad,
1202     IWineD3DSurfaceImpl_GetType,
1203     /* IWineD3DSurface */
1204     IWineD3DSurfaceImpl_GetContainer,
1205     IWineD3DSurfaceImpl_GetDesc,
1206     IWineD3DSurfaceImpl_LockRect,
1207     IWineD3DSurfaceImpl_UnlockRect,
1208     IWineD3DSurfaceImpl_GetDC,
1209     IWineD3DSurfaceImpl_ReleaseDC,
1210     /* Internal use: */
1211     IWineD3DSurfaceImpl_CleanDirtyRect,
1212     IWineD3DSurfaceImpl_AddDirtyRect,
1213     IWineD3DSurfaceImpl_LoadTexture,
1214     IWineD3DSurfaceImpl_SaveSnapshot,
1215     IWineD3DSurfaceImpl_SetContainer,
1216     IWineD3DSurfaceImpl_SetPBufferState,
1217     IWineD3DSurfaceImpl_SetGlTextureDesc,
1218     IWineD3DSurfaceImpl_GetGlDesc,
1219     IWineD3DSurfaceImpl_GetData
1220 };