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