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