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