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