wined3d: Define the surface alignment in the header.
[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, UINT pitch, UINT height, UINT outpitch, 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,
994                                    height,
995                                    pitch * 4,
996                                    CONVERT_PALETTED,
997                                    This);
998         }
999         break;
1000
1001         default:
1002             FIXME("Unsupported Format %u in locking func\n", This->resource.format);
1003
1004             /* Give it a try */
1005             type = This->glDescription.glType;
1006             fmt = This->glDescription.glFormat;
1007             mem = This->resource.allocatedMemory;
1008     }
1009
1010     glDrawPixels(This->lockedRect.right - This->lockedRect.left,
1011                  (This->lockedRect.bottom - This->lockedRect.top)-1,
1012                  fmt, type,
1013                  mem);
1014     checkGLcall("glDrawPixels");
1015     glPixelZoom(1.0,1.0);
1016     vcheckGLcall("glPixelZoom");
1017
1018     glRasterPos3iv(&prev_rasterpos[0]);
1019     vcheckGLcall("glRasterPos3iv");
1020
1021     /* Reset to previous pack row length */
1022     glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
1023     vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
1024     if(storechanged) {
1025         glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1026         vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES");
1027     }
1028
1029     if(mem != This->resource.allocatedMemory) HeapFree(GetProcessHeap(), 0, mem);
1030     return;
1031 }
1032
1033 static void flush_to_framebuffer_texture(IWineD3DSurface *iface) {
1034     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1035     float glTexCoord[4];
1036
1037     glTexCoord[0] = 0.0; /* left */
1038     glTexCoord[1] = (float) This->currentDesc.Width / (float) This->pow2Width; /* right */
1039     glTexCoord[2] = 0.0; /* top */
1040     glTexCoord[3] = (float) This->currentDesc.Height / (float) This->pow2Height; /* bottom */
1041
1042     IWineD3DSurface_PreLoad(iface);
1043
1044     ENTER_GL();
1045
1046     /* Disable some fancy graphics effects */
1047     glDisable(GL_LIGHTING);
1048     checkGLcall("glDisable GL_LIGHTING");
1049     glDisable(GL_DEPTH_TEST);
1050     checkGLcall("glDisable GL_DEPTH_TEST");
1051     glDisable(GL_FOG);
1052     checkGLcall("glDisable GL_FOG");
1053     glDisable(GL_CULL_FACE);
1054     checkGLcall("glDisable GL_CULL_FACE");
1055     glDisable(GL_BLEND);
1056     checkGLcall("glDisable GL_BLEND");
1057     glDisable(GL_STENCIL_TEST);
1058     checkGLcall("glDisable GL_STENCIL_TEST");
1059
1060     glEnable(GL_TEXTURE_2D);
1061     glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
1062     checkGLcall("glEnable glBindTexture");
1063
1064     /* No filtering for blts */
1065     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1066     checkGLcall("glTexParameteri");
1067     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1068     checkGLcall("glTexParameteri");
1069
1070     /* Start drawing a quad */
1071     glBegin(GL_QUADS);
1072
1073     glColor3d(1.0f, 1.0f, 1.0f);
1074     glTexCoord2f(glTexCoord[0], glTexCoord[2]);
1075     glVertex3f(0, 0, 0.0);
1076
1077     glTexCoord2f(glTexCoord[0], glTexCoord[3]);
1078     glVertex3f(0, This->currentDesc.Height, 0.0);
1079
1080     glTexCoord2f(glTexCoord[1], glTexCoord[3]);
1081     glVertex3d(This->currentDesc.Width, This->currentDesc.Height, 0.0);
1082
1083     glTexCoord2f(glTexCoord[1], glTexCoord[2]);
1084     glVertex3f(This->currentDesc.Width, 0, 0.0);
1085
1086     glEnd();
1087     checkGLcall("glEnd");
1088
1089     /* Unbind the texture */
1090     glBindTexture(GL_TEXTURE_2D, 0);
1091     checkGLcall("glEnable glBindTexture");
1092
1093     LEAVE_GL();
1094 }
1095
1096 static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
1097     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1098     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
1099     const char *buffername = "";
1100     IWineD3DSwapChainImpl *swapchain = NULL;
1101     BOOL backbuf = FALSE;
1102
1103     if (!(This->Flags & SFLAG_LOCKED)) {
1104         WARN("trying to Unlock an unlocked surf@%p\n", This);
1105         return WINED3DERR_INVALIDCALL;
1106     }
1107
1108     if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
1109         IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1110
1111         if(swapchain) {
1112             int i;
1113             for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
1114                 if(iface == swapchain->backBuffer[i]) {
1115                     backbuf = TRUE;
1116                     break;
1117                 }
1118             }
1119         }
1120
1121         if (backbuf) {
1122                 buffername = "backBuffer";
1123         } else if ((swapchain != NULL) && iface ==  swapchain->frontBuffer) {
1124                 buffername = "frontBuffer";
1125         } else if (iface == myDevice->depthStencilBuffer) {
1126                 buffername = "depthStencilBuffer";
1127         } else if (iface == myDevice->renderTarget) {
1128                 buffername = "renderTarget";
1129         }
1130     }
1131
1132     if (swapchain != NULL) {
1133         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
1134     }
1135
1136     TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Flags & SFLAG_DIRTY ? 1 : 0);
1137
1138     if (!(This->Flags & SFLAG_DIRTY)) {
1139         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
1140         goto unlock_end;
1141     }
1142
1143     if (0 == This->resource.usage) { /* classic surface */
1144         /**
1145          * nothing to do
1146          * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
1147          */
1148     } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
1149
1150         /****************************
1151         * TODO: Render targets are 'special' and
1152         * ?some? locking needs to be passed onto the context manager
1153         * so that it becomes possible to use auxiliary buffers, pbuffers
1154         * render-to-texture, shared, cached contexts etc...
1155         * ****************************/
1156         IWineD3DSwapChainImpl *implSwapChain;
1157         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
1158
1159         if (backbuf || iface ==  implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
1160             int tex;
1161
1162             ENTER_GL();
1163
1164             /* glDrawPixels transforms the raster position as though it was a vertex -
1165                we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
1166                per drawprim (and leave set - it will sort itself out due to last_was_rhw */
1167             d3ddevice_set_ortho(This->resource.wineD3DDevice);
1168
1169             if (iface ==  implSwapChain->frontBuffer) {
1170                 glDrawBuffer(GL_FRONT);
1171                 checkGLcall("glDrawBuffer GL_FRONT");
1172             } else if (backbuf || iface == myDevice->renderTarget) {
1173                 glDrawBuffer(GL_BACK);
1174                 checkGLcall("glDrawBuffer GL_BACK");
1175             }
1176
1177             /* Disable higher textures before calling glDrawPixels */
1178             for(tex = 1; tex < GL_LIMITS(samplers); tex++) {
1179                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1180                     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + tex));
1181                     checkGLcall("glActiveTextureARB");
1182                 }
1183                 glDisable(GL_TEXTURE_2D);
1184                 checkGLcall("glDisable GL_TEXTURE_2D");
1185                 glDisable(GL_TEXTURE_1D);
1186                 checkGLcall("glDisable GL_TEXTURE_1D");
1187             }
1188             /* Activate texture 0, but don't disable it necessarilly */
1189             if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1190                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
1191                 checkGLcall("glActiveTextureARB");
1192             }
1193
1194             /* And back buffers are not blended. Disable the depth test, 
1195                that helps performance */
1196             glDisable(GL_BLEND);
1197             glDisable(GL_DEPTH_TEST);
1198             glDisable(GL_FOG);
1199
1200             switch(wined3d_settings.rendertargetlock_mode) {
1201                 case RTL_AUTO:
1202                 case RTL_READDRAW:
1203                 case RTL_TEXDRAW:
1204                     flush_to_framebuffer_drawpixels(This);
1205                     break;
1206
1207                 case RTL_READTEX:
1208                 case RTL_TEXTEX:
1209                     flush_to_framebuffer_texture(iface);
1210                     break;
1211
1212                 case RTL_DISABLE:
1213                 {
1214                     static BOOL warned = FALSE;
1215                     if(!warned) {
1216                         ERR("The application tries to write to the render target, but render target locking is disabled\n");
1217                         warned = TRUE;
1218                     }
1219                 }
1220                 break;
1221             }
1222
1223             if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
1224                 glDrawBuffer(GL_BACK);
1225                 vcheckGLcall("glDrawBuffer");
1226             }
1227             if(myDevice->stateBlock->renderState[D3DRS_ZENABLE] == D3DZB_TRUE ||
1228                myDevice->stateBlock->renderState[D3DRS_ZENABLE] == D3DZB_USEW) glEnable(GL_DEPTH_TEST);
1229             if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
1230             if (myDevice->stateBlock->renderState[D3DRS_FOGENABLE]) glEnable(GL_FOG);
1231
1232             LEAVE_GL();
1233
1234             /** restore clean dirty state */
1235             IWineD3DSurface_CleanDirtyRect(iface);
1236
1237         } else {
1238             FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1239         }
1240         IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
1241
1242     } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
1243
1244         if (iface == myDevice->depthStencilBuffer) {
1245             FIXME("TODO stencil depth surface unlocking surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1246         } else {
1247             FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1248         }
1249
1250     } else {
1251         FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1252     }
1253
1254     unlock_end:
1255     This->Flags &= ~SFLAG_LOCKED;
1256     memset(&This->lockedRect, 0, sizeof(RECT));
1257     return WINED3D_OK;
1258 }
1259
1260 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
1261     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1262     WINED3DLOCKED_RECT lock;
1263     UINT usage;
1264     BITMAPINFO* b_info;
1265     HDC ddc;
1266     DWORD *masks;
1267     HRESULT hr;
1268     RGBQUAD col[256];
1269     const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1270
1271     TRACE("(%p)->(%p)\n",This,pHDC);
1272
1273     if(This->Flags & SFLAG_USERPTR) {
1274         ERR("Not supported on surfaces with an application-provided surfaces\n");
1275         return DDERR_NODC;
1276     }
1277
1278     /* Give more detailed info for ddraw */
1279     if (This->Flags & SFLAG_DCINUSE)
1280         return DDERR_DCALREADYCREATED;
1281
1282     /* Can't GetDC if the surface is locked */
1283     if (This->Flags & SFLAG_LOCKED)
1284         return WINED3DERR_INVALIDCALL;
1285
1286     memset(&lock, 0, sizeof(lock)); /* To be sure */
1287
1288     /* Create a DIB section if there isn't a hdc yet */
1289     if(!This->hDC) {
1290         int extraline = 0;
1291         SYSTEM_INFO sysInfo;
1292
1293         if(This->Flags & SFLAG_ACTIVELOCK) {
1294             ERR("Creating a DIB section while a lock is active. Uncertain consequences\n");
1295         }
1296
1297         switch (This->bytesPerPixel) {
1298             case 2:
1299             case 4:
1300                 /* Allocate extra space to store the RGB bit masks. */
1301                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
1302                 break;
1303
1304             case 3:
1305                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
1306                 break;
1307
1308             default:
1309                 /* Allocate extra space for a palette. */
1310                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1311                                   sizeof(BITMAPINFOHEADER)
1312                                   + sizeof(RGBQUAD)
1313                                   * (1 << (This->bytesPerPixel * 8)));
1314                 break;
1315         }
1316
1317         if (!b_info)
1318             return E_OUTOFMEMORY;
1319
1320         /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
1321          * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
1322          * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
1323          * add an extra line to the dib section
1324          */
1325         GetSystemInfo(&sysInfo);
1326         if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) {
1327             extraline = 1;
1328             TRACE("Adding an extra line to the dib section\n");
1329         }
1330
1331         b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1332         if( (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
1333             b_info->bmiHeader.biWidth = This->currentDesc.Width;
1334             b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
1335             b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
1336             /* Use the full pow2 image size(assigned below) because LockRect
1337              * will need it for a full glGetTexImage call
1338              */
1339         } else {
1340             b_info->bmiHeader.biWidth = This->pow2Width;
1341             b_info->bmiHeader.biHeight = -This->pow2Height -extraline;
1342             b_info->bmiHeader.biSizeImage = This->resource.size + extraline  * IWineD3DSurface_GetPitch(iface);
1343         }
1344         b_info->bmiHeader.biPlanes = 1;
1345         b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
1346
1347         b_info->bmiHeader.biXPelsPerMeter = 0;
1348         b_info->bmiHeader.biYPelsPerMeter = 0;
1349         b_info->bmiHeader.biClrUsed = 0;
1350         b_info->bmiHeader.biClrImportant = 0;
1351
1352         /* Get the bit masks */
1353         masks = (DWORD *) &(b_info->bmiColors);
1354         switch (This->resource.format) {
1355             case WINED3DFMT_R8G8B8:
1356                 usage = DIB_RGB_COLORS;
1357                 b_info->bmiHeader.biCompression = BI_RGB;
1358                 break;
1359
1360             case WINED3DFMT_X1R5G5B5:
1361             case WINED3DFMT_A1R5G5B5:
1362             case WINED3DFMT_A4R4G4B4:
1363             case WINED3DFMT_X4R4G4B4:
1364             case WINED3DFMT_R3G3B2:
1365             case WINED3DFMT_A8R3G3B2:
1366             case WINED3DFMT_A2B10G10R10:
1367             case WINED3DFMT_A8B8G8R8:
1368             case WINED3DFMT_X8B8G8R8:
1369             case WINED3DFMT_A2R10G10B10:
1370             case WINED3DFMT_R5G6B5:
1371             case WINED3DFMT_A16B16G16R16:
1372                 usage = 0;
1373                 b_info->bmiHeader.biCompression = BI_BITFIELDS;
1374                 masks[0] = formatEntry->redMask;
1375                 masks[1] = formatEntry->greenMask;
1376                 masks[2] = formatEntry->blueMask;
1377                 break;
1378
1379             default:
1380                 /* Don't know palette */
1381                 b_info->bmiHeader.biCompression = BI_RGB;
1382                 usage = 0;
1383                 break;
1384         }
1385
1386         ddc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1387         if (ddc == 0) {
1388             HeapFree(GetProcessHeap(), 0, b_info);
1389             return HRESULT_FROM_WIN32(GetLastError());
1390         }
1391
1392         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);
1393         This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
1394         DeleteDC(ddc);
1395
1396         if (!This->dib.DIBsection) {
1397             ERR("CreateDIBSection failed!\n");
1398             HeapFree(GetProcessHeap(), 0, b_info);
1399             return HRESULT_FROM_WIN32(GetLastError());
1400         }
1401
1402         TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
1403
1404         /* copy the existing surface to the dib section */
1405         if(This->resource.allocatedMemory) {
1406             memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, b_info->bmiHeader.biSizeImage);
1407             /* We won't need that any more */
1408             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1409         } else {
1410             /* This is to make LockRect read the gl Texture although memory is allocated */
1411             This->Flags |= SFLAG_GLDIRTY;
1412         }
1413
1414         HeapFree(GetProcessHeap(), 0, b_info);
1415
1416         /* Use the dib section from now on */
1417         This->resource.allocatedMemory = This->dib.bitmap_data;
1418
1419         /* Now allocate a HDC */
1420         This->hDC = CreateCompatibleDC(0);
1421         This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
1422         TRACE("using wined3d palette %p\n", This->palette);
1423         SelectPalette(This->hDC,
1424                       This->palette ? This->palette->hpal : 0,
1425                       FALSE);
1426
1427         This->Flags |= SFLAG_DIBSECTION;
1428     }
1429
1430     /* Lock the surface */
1431     hr = IWineD3DSurface_LockRect(iface,
1432                                   &lock,
1433                                   NULL,
1434                                   0);
1435     if(FAILED(hr)) {
1436         ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
1437         /* keep the dib section */
1438         return hr;
1439     }
1440
1441     if(This->resource.format == WINED3DFMT_P8 ||
1442         This->resource.format == WINED3DFMT_A8P8) {
1443         unsigned int n;
1444         if(This->palette) {
1445             PALETTEENTRY ent[256];
1446
1447             GetPaletteEntries(This->palette->hpal, 0, 256, ent);
1448             for (n=0; n<256; n++) {
1449                 col[n].rgbRed   = ent[n].peRed;
1450                 col[n].rgbGreen = ent[n].peGreen;
1451                 col[n].rgbBlue  = ent[n].peBlue;
1452                 col[n].rgbReserved = 0;
1453             }
1454         } else {
1455             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1456
1457             for (n=0; n<256; n++) {
1458                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
1459                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1460                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
1461                 col[n].rgbReserved = 0;
1462             }
1463
1464         }
1465         SetDIBColorTable(This->hDC, 0, 256, col);
1466     }
1467
1468     *pHDC = This->hDC;
1469     TRACE("returning %p\n",*pHDC);
1470     This->Flags |= SFLAG_DCINUSE;
1471
1472     return WINED3D_OK;
1473 }
1474
1475 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1476     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1477
1478     TRACE("(%p)->(%p)\n",This,hDC);
1479
1480     if (!(This->Flags & SFLAG_DCINUSE))
1481         return D3DERR_INVALIDCALL;
1482
1483     /* we locked first, so unlock now */
1484     IWineD3DSurface_UnlockRect(iface);
1485
1486     This->Flags &= ~SFLAG_DCINUSE;
1487
1488     return WINED3D_OK;
1489 }
1490
1491 /* ******************************************************
1492    IWineD3DSurface Internal (No mapping to directx api) parts follow
1493    ****************************************************** */
1494
1495 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) {
1496     BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & DDSD_CKSRCBLT);
1497     const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1498
1499     /* Default values: From the surface */
1500     *format = formatEntry->glFormat;
1501     *internal = formatEntry->glInternal;
1502     *type = formatEntry->glType;
1503     *convert = NO_CONVERSION;
1504     *target_bpp = This->bytesPerPixel;
1505
1506     /* Ok, now look if we have to do any conversion */
1507     switch(This->resource.format) {
1508         case WINED3DFMT_P8:
1509             /* ****************
1510                 Paletted Texture
1511                 **************** */
1512             /* Use conversion when the paletted texture extension is not available, or when it is available make sure it is used
1513              * for texturing as it won't work for calls like glDraw-/glReadPixels and further also use conversion in case of color keying.
1514              */
1515             if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) || colorkey_active || (!use_texturing && GL_SUPPORT(EXT_PALETTED_TEXTURE)) ) {
1516                 *format = GL_RGBA;
1517                 *internal = GL_RGBA;
1518                 *type = GL_UNSIGNED_BYTE;
1519                 *target_bpp = 4;
1520                 if(colorkey_active) {
1521                     *convert = CONVERT_PALETTED_CK;
1522                 } else {
1523                     *convert = CONVERT_PALETTED;
1524                 }
1525             }
1526
1527             break;
1528
1529         case WINED3DFMT_R3G3B2:
1530             /* **********************
1531                 GL_UNSIGNED_BYTE_3_3_2
1532                 ********************** */
1533             if (colorkey_active) {
1534                 /* This texture format will never be used.. So do not care about color keying
1535                     up until the point in time it will be needed :-) */
1536                 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1537             }
1538             break;
1539
1540         case WINED3DFMT_R5G6B5:
1541             if (colorkey_active) {
1542                 *convert = CONVERT_CK_565;
1543                 *format = GL_RGBA;
1544                 *internal = GL_RGBA;
1545                 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1546             }
1547             break;
1548
1549         case WINED3DFMT_R8G8B8:
1550             if (colorkey_active) {
1551                 *convert = CONVERT_CK_RGB24;
1552                 *format = GL_RGBA;
1553                 *internal = GL_RGBA;
1554                 *type = GL_UNSIGNED_INT_8_8_8_8;
1555                 *target_bpp = 4;
1556             }
1557             break;
1558
1559         case WINED3DFMT_X8R8G8B8:
1560             if (colorkey_active) {
1561                 *convert = CONVERT_RGB32_888;
1562                 *format = GL_RGBA;
1563                 *internal = GL_RGBA;
1564                 *type = GL_UNSIGNED_INT_8_8_8_8;
1565             }
1566             break;
1567
1568         default:
1569             break;
1570     }
1571
1572     return WINED3D_OK;
1573 }
1574
1575 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) {
1576     BYTE *dest;
1577     TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert, surf);
1578
1579     switch (convert) {
1580         case NO_CONVERSION:
1581         {
1582             memcpy(dst, src, pitch * height);
1583             break;
1584         }
1585         case CONVERT_PALETTED:
1586         case CONVERT_PALETTED_CK:
1587         {
1588             IWineD3DPaletteImpl* pal = surf->palette;
1589             BYTE table[256][4];
1590             unsigned int i;
1591             unsigned int x, y;
1592
1593             if( pal == NULL) {
1594                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1595             }
1596
1597             if (pal == NULL) {
1598                 /* Still no palette? Use the device's palette */
1599                 /* Get the surface's palette */
1600                 for (i = 0; i < 256; i++) {
1601                     IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice;
1602
1603                     table[i][0] = device->palettes[device->currentPalette][i].peRed;
1604                     table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1605                     table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1606                     if ((convert == CONVERT_PALETTED_CK) &&
1607                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1608                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1609                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1610                           one often used by application to prevent the nice purple borders when bi-linear
1611                           filtering is on */
1612                         table[i][3] = 0x00;
1613                     } else {
1614                         table[i][3] = 0xFF;
1615                     }
1616                 }
1617             } else {
1618                 TRACE("Using surface palette %p\n", pal);
1619                 /* Get the surface's palette */
1620                 for (i = 0; i < 256; i++) {
1621                     table[i][0] = pal->palents[i].peRed;
1622                     table[i][1] = pal->palents[i].peGreen;
1623                     table[i][2] = pal->palents[i].peBlue;
1624                     if ((convert == CONVERT_PALETTED_CK) &&
1625                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1626                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1627                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1628                           one often used by application to prevent the nice purple borders when bi-linear
1629                           filtering is on */
1630                         table[i][3] = 0x00;
1631                     } else {
1632                         table[i][3] = 0xFF;
1633                     }
1634                 }
1635             }
1636
1637             for (y = 0; y < height; y++)
1638             {
1639                 dest = dst + outpitch * y;
1640                 /* This is an 1 bpp format, using the pitch here is fine */
1641                 for (x = 0; x < pitch; x++) {
1642                     BYTE color = *src++;
1643                     *dest++ = table[color][0];
1644                     *dest++ = table[color][1];
1645                     *dest++ = table[color][2];
1646                     *dest++ = table[color][3];
1647                 }
1648             }
1649         }
1650         break;
1651
1652         case CONVERT_CK_565:
1653         {
1654             /* Converting the 565 format in 5551 packed to emulate color-keying.
1655
1656               Note : in all these conversion, it would be best to average the averaging
1657                       pixels to get the color of the pixel that will be color-keyed to
1658                       prevent 'color bleeding'. This will be done later on if ever it is
1659                       too visible.
1660
1661               Note2: Nvidia documents say that their driver does not support alpha + color keying
1662                      on the same surface and disables color keying in such a case
1663             */
1664             unsigned int x, y;
1665             WORD *Source;
1666             WORD *Dest;
1667
1668             TRACE("Color keyed 565\n");
1669
1670             for (y = 0; y < height; y++) {
1671                 Source = (WORD *) (src + y * pitch);
1672                 Dest = (WORD *) (dst + y * outpitch);
1673                 for (x = 0; x < pitch / 2; x++ ) {
1674                     WORD color = *Source++;
1675                     *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1676                     if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1677                         (color > surf->SrcBltCKey.dwColorSpaceHighValue)) {
1678                         *Dest |= 0x0001;
1679                     }
1680                     Dest++;
1681                 }
1682             }
1683         }
1684         break;
1685
1686         default:
1687             ERR("Unsupported conversation type %d\n", convert);
1688     }
1689     return WINED3D_OK;
1690 }
1691
1692 /* This function is used in case of 8bit paletted textures to upload the palette.
1693    For now it only supports GL_EXT_paletted_texture extension but support for other
1694    extensions like ARB_fragment_program and ATI_fragment_shaders will be added aswell.
1695 */
1696 void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
1697     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1698     IWineD3DPaletteImpl* pal = This->palette;
1699     BYTE table[256][4];
1700     int i;
1701
1702     if (pal == NULL) {
1703         /* Still no palette? Use the device's palette */
1704         /* Get the surface's palette */
1705         for (i = 0; i < 256; i++) {
1706             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1707
1708             table[i][0] = device->palettes[device->currentPalette][i].peRed;
1709             table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1710             table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1711             if ((convert == CONVERT_PALETTED_CK) &&
1712                 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1713                 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1714                 /* We should maybe here put a more 'neutral' color than the standard bright purple
1715                    one often used by application to prevent the nice purple borders when bi-linear
1716                    filtering is on */
1717                 table[i][3] = 0x00;
1718             } else {
1719                 table[i][3] = 0xFF;
1720             }
1721         }
1722     } else {
1723         TRACE("Using surface palette %p\n", pal);
1724         /* Get the surface's palette */
1725         for (i = 0; i < 256; i++) {
1726             table[i][0] = pal->palents[i].peRed;
1727             table[i][1] = pal->palents[i].peGreen;
1728             table[i][2] = pal->palents[i].peBlue;
1729             if ((convert == CONVERT_PALETTED_CK) &&
1730                 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1731                 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1732                 /* We should maybe here put a more 'neutral' color than the standard bright purple
1733                    one often used by application to prevent the nice purple borders when bi-linear
1734                    filtering is on */
1735                 table[i][3] = 0x00;
1736             } else {
1737                 table[i][3] = 0xFF;
1738             }
1739         }
1740     }
1741     GL_EXTCALL(glColorTableEXT(GL_TEXTURE_2D,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table));
1742 }
1743
1744 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1745     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1746     GLenum format, internal, type;
1747     CONVERT_TYPES convert;
1748     int bpp;
1749     int width, pitch, outpitch;
1750     BYTE *mem;
1751
1752     if (This->Flags & SFLAG_INTEXTURE) {
1753         TRACE("Surface already in texture\n");
1754         return WINED3D_OK;
1755     }
1756     if (This->Flags & SFLAG_DIRTY) {
1757         TRACE("Reloading because surface is dirty\n");
1758     } else if(/* Reload: gl texture has ck, now no ckey is set OR */
1759               ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & DDSD_CKSRCBLT))) ||
1760               /* Reload: vice versa  OR */
1761               ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & DDSD_CKSRCBLT)) ||
1762               /* Also reload: Color key is active AND the color key has changed */
1763               ((This->CKeyFlags & DDSD_CKSRCBLT) && (
1764                 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
1765                 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
1766         TRACE("Reloading because of color keying\n");
1767     } else {
1768         TRACE("surface isn't dirty\n");
1769         return WINED3D_OK;
1770     }
1771
1772     This->Flags &= ~SFLAG_DIRTY;
1773
1774     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1775     *  These resources are not bound by device size or format restrictions. Because of this,
1776     *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1777     *  However, these resources can always be created, locked, and copied.
1778     */
1779     if (This->resource.pool == WINED3DPOOL_SCRATCH && !(This->Flags & SFLAG_FORCELOAD) )
1780     {
1781         FIXME("(%p) Operation not supported for scratch textures\n",This);
1782         return WINED3DERR_INVALIDCALL;
1783     }
1784
1785     if (This->Flags & SFLAG_INPBUFFER) {
1786         if (This->glDescription.level != 0)
1787             FIXME("Surface in texture is only supported for level 0\n");
1788         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1789                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1790                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1791                  This->resource.format == WINED3DFMT_DXT5)
1792             FIXME("Format %d not supported\n", This->resource.format);
1793         else {
1794             GLint prevRead;
1795
1796             ENTER_GL();
1797
1798             glGetIntegerv(GL_READ_BUFFER, &prevRead);
1799             vcheckGLcall("glGetIntegerv");
1800             glReadBuffer(GL_BACK);
1801             vcheckGLcall("glReadBuffer");
1802
1803             glCopyTexImage2D(This->glDescription.target,
1804                              This->glDescription.level,
1805                              This->glDescription.glFormatInternal,
1806                              0,
1807                              0,
1808                              This->currentDesc.Width,
1809                              This->currentDesc.Height,
1810                              0);
1811
1812             checkGLcall("glCopyTexImage2D");
1813             glReadBuffer(prevRead);
1814             vcheckGLcall("glReadBuffer");
1815
1816             LEAVE_GL();
1817
1818             TRACE("Updating target %d\n", This->glDescription.target);
1819             This->Flags |= SFLAG_INTEXTURE;
1820         }
1821         return WINED3D_OK;
1822     }
1823
1824     if(This->CKeyFlags & DDSD_CKSRCBLT) {
1825         This->Flags |= SFLAG_GLCKEY;
1826         This->glCKey = This->SrcBltCKey;
1827     }
1828     else This->Flags &= ~SFLAG_GLCKEY;
1829
1830     d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp);
1831
1832     /* The width is in 'length' not in bytes */
1833     if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)
1834         width = This->currentDesc.Width;
1835     else
1836         width = This->pow2Width;
1837
1838     pitch = IWineD3DSurface_GetPitch(iface);
1839
1840     if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
1841         int height = This->glRect.bottom - This->glRect.top;
1842
1843         /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
1844         outpitch = width * bpp;
1845         outpitch = (outpitch + 3) & ~3;
1846
1847         mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
1848         if(!mem) {
1849             ERR("Out of memory %d, %d!\n", outpitch, height);
1850             return WINED3DERR_OUTOFVIDEOMEMORY;
1851         }
1852         d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, height, outpitch, convert, This);
1853
1854         This->Flags |= SFLAG_CONVERTED;
1855     } else if (This->resource.format == WINED3DFMT_P8 && GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
1856         d3dfmt_p8_upload_palette(iface, convert);
1857         This->Flags &= ~SFLAG_CONVERTED;
1858         mem = This->resource.allocatedMemory;
1859     } else {
1860         This->Flags &= ~SFLAG_CONVERTED;
1861         mem = This->resource.allocatedMemory;
1862     }
1863
1864     /* Make sure the correct pitch is used */
1865     glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
1866
1867     if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
1868         TRACE("non power of two support\n");
1869         surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
1870         if (mem) {
1871             surface_upload_data(This, This->pow2Width, This->pow2Height, format, type, mem);
1872         }
1873     } else {
1874         surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
1875         if (mem) {
1876             surface_upload_data(This, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
1877         }
1878     }
1879
1880     /* Restore the default pitch */
1881     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1882
1883     if (mem != This->resource.allocatedMemory)
1884         HeapFree(GetProcessHeap(), 0, mem);
1885
1886 #if 0
1887     {
1888         static unsigned int gen = 0;
1889         char buffer[4096];
1890         ++gen;
1891         if ((gen % 10) == 0) {
1892             snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1893             IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1894         }
1895         /*
1896          * debugging crash code
1897          if (gen == 250) {
1898          void** test = NULL;
1899          *test = 0;
1900          }
1901          */
1902     }
1903 #endif
1904
1905     if (!(This->Flags & SFLAG_DONOTFREE)) {
1906         HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1907         This->resource.allocatedMemory = NULL;
1908     }
1909
1910     return WINED3D_OK;
1911 }
1912
1913 #include <errno.h>
1914 #include <stdio.h>
1915 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1916     FILE* f = NULL;
1917     UINT i, y;
1918     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1919     char *allocatedMemory;
1920     char *textureRow;
1921     IWineD3DSwapChain *swapChain = NULL;
1922     int width, height;
1923     GLuint tmpTexture = 0;
1924     DWORD color;
1925     /*FIXME:
1926     Textures my not be stored in ->allocatedgMemory and a GlTexture
1927     so we should lock the surface before saving a snapshot, or at least check that
1928     */
1929     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1930     by calling GetTexImage and in compressed form by calling
1931     GetCompressedTexImageARB.  Queried compressed images can be saved and
1932     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
1933     texture images do not need to be processed by the GL and should
1934     significantly improve texture loading performance relative to uncompressed
1935     images. */
1936
1937 /* Setup the width and height to be the internal texture width and height. */
1938     width  = This->pow2Width;
1939     height = This->pow2Height;
1940 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1941     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1942
1943     if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1944 /* 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 */
1945         GLint prevRead;
1946         ENTER_GL();
1947         FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1948         glEnable(GL_TEXTURE_2D);
1949
1950         glGenTextures(1, &tmpTexture);
1951         glBindTexture(GL_TEXTURE_2D, tmpTexture);
1952
1953         glTexImage2D(GL_TEXTURE_2D,
1954                         0,
1955                         GL_RGBA,
1956                         width,
1957                         height,
1958                         0/*border*/,
1959                         GL_RGBA,
1960                         GL_UNSIGNED_INT_8_8_8_8_REV,
1961                         NULL);
1962
1963         glGetIntegerv(GL_READ_BUFFER, &prevRead);
1964         vcheckGLcall("glGetIntegerv");
1965         glReadBuffer(GL_BACK);
1966         vcheckGLcall("glReadBuffer");
1967         glCopyTexImage2D(GL_TEXTURE_2D,
1968                             0,
1969                             GL_RGBA,
1970                             0,
1971                             0,
1972                             width,
1973                             height,
1974                             0);
1975
1976         checkGLcall("glCopyTexImage2D");
1977         glReadBuffer(prevRead);
1978         LEAVE_GL();
1979
1980     } else { /* bind the real texture */
1981         IWineD3DSurface_PreLoad(iface);
1982     }
1983     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
1984     ENTER_GL();
1985     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1986     glGetTexImage(GL_TEXTURE_2D,
1987                 This->glDescription.level,
1988                 GL_RGBA,
1989                 GL_UNSIGNED_INT_8_8_8_8_REV,
1990                 allocatedMemory);
1991     checkGLcall("glTexImage2D");
1992     if (tmpTexture) {
1993         glBindTexture(GL_TEXTURE_2D, 0);
1994         glDeleteTextures(1, &tmpTexture);
1995     }
1996     LEAVE_GL();
1997
1998     f = fopen(filename, "w+");
1999     if (NULL == f) {
2000         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
2001         return WINED3DERR_INVALIDCALL;
2002     }
2003 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
2004     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
2005 /* TGA header */
2006     fputc(0,f);
2007     fputc(0,f);
2008     fputc(2,f);
2009     fputc(0,f);
2010     fputc(0,f);
2011     fputc(0,f);
2012     fputc(0,f);
2013     fputc(0,f);
2014     fputc(0,f);
2015     fputc(0,f);
2016     fputc(0,f);
2017     fputc(0,f);
2018 /* short width*/
2019     fwrite(&width,2,1,f);
2020 /* short height */
2021     fwrite(&height,2,1,f);
2022 /* format rgba */
2023     fputc(0x20,f);
2024     fputc(0x28,f);
2025 /* raw data */
2026     /* 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*/
2027     if(swapChain)
2028         textureRow = allocatedMemory + (width * (height - 1) *4);
2029     else
2030         textureRow = allocatedMemory;
2031     for (y = 0 ; y < height; y++) {
2032         for (i = 0; i < width;  i++) {
2033             color = *((DWORD*)textureRow);
2034             fputc((color >> 16) & 0xFF, f); /* B */
2035             fputc((color >>  8) & 0xFF, f); /* G */
2036             fputc((color >>  0) & 0xFF, f); /* R */
2037             fputc((color >> 24) & 0xFF, f); /* A */
2038             textureRow += 4;
2039         }
2040         /* take two rows of the pointer to the texture memory */
2041         if(swapChain)
2042             (textureRow-= width << 3);
2043
2044     }
2045     TRACE("Closing file\n");
2046     fclose(f);
2047
2048     if(swapChain) {
2049         IWineD3DSwapChain_Release(swapChain);
2050     }
2051     HeapFree(GetProcessHeap(), 0, allocatedMemory);
2052     return WINED3D_OK;
2053 }
2054
2055 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
2056     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2057     This->Flags &= ~SFLAG_DIRTY;
2058     This->dirtyRect.left   = This->currentDesc.Width;
2059     This->dirtyRect.top    = This->currentDesc.Height;
2060     This->dirtyRect.right  = 0;
2061     This->dirtyRect.bottom = 0;
2062     TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
2063           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2064     return WINED3D_OK;
2065 }
2066
2067 /**
2068  *   Slightly inefficient way to handle multiple dirty rects but it works :)
2069  */
2070 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
2071     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2072     IWineD3DBaseTexture *baseTexture = NULL;
2073     This->Flags |= SFLAG_DIRTY;
2074     if (NULL != pDirtyRect) {
2075         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
2076         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
2077         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
2078         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
2079     } else {
2080         This->dirtyRect.left   = 0;
2081         This->dirtyRect.top    = 0;
2082         This->dirtyRect.right  = This->currentDesc.Width;
2083         This->dirtyRect.bottom = This->currentDesc.Height;
2084     }
2085     TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
2086           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2087     /* if the container is a basetexture then mark it dirty. */
2088     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2089         TRACE("Passing to conatiner\n");
2090         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
2091         IWineD3DBaseTexture_Release(baseTexture);
2092     }
2093     return WINED3D_OK;
2094 }
2095
2096 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
2097     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2098
2099     TRACE("This %p, container %p\n", This, container);
2100
2101     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
2102
2103     TRACE("Setting container to %p from %p\n", container, This->container);
2104     This->container = container;
2105
2106     return WINED3D_OK;
2107 }
2108
2109 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
2110     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2111     const PixelFormatDesc *formatEntry = getFormatDescEntry(format);
2112
2113     if (This->resource.format != WINED3DFMT_UNKNOWN) {
2114         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
2115         return WINED3DERR_INVALIDCALL;
2116     }
2117
2118     TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
2119     if (format == WINED3DFMT_UNKNOWN) {
2120         This->resource.size = 0;
2121     } else if (format == WINED3DFMT_DXT1) {
2122         /* DXT1 is half byte per pixel */
2123         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4)) >> 1;
2124
2125     } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
2126                format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
2127         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4));
2128     } else {
2129         This->resource.size = ((This->pow2Width * formatEntry->bpp) + 3) & ~3;
2130         This->resource.size *= This->pow2Height;
2131     }
2132
2133
2134     /* Setup some glformat defaults */
2135     This->glDescription.glFormat         = formatEntry->glFormat;
2136     This->glDescription.glFormatInternal = formatEntry->glInternal;
2137     This->glDescription.glType           = formatEntry->glType;
2138
2139     if (format != WINED3DFMT_UNKNOWN) {
2140         This->bytesPerPixel = formatEntry->bpp;
2141         This->pow2Size      = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
2142     } else {
2143         This->bytesPerPixel = 0;
2144         This->pow2Size      = 0;
2145     }
2146
2147     This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
2148
2149     This->resource.format = format;
2150
2151     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);
2152
2153     return WINED3D_OK;
2154 }
2155
2156 HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2157     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2158
2159     /* Render targets depend on their hdc, and we can't create a hdc on a user pointer */
2160     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2161         ERR("Not supported on render targets\n");
2162         return WINED3DERR_INVALIDCALL;
2163     }
2164
2165     if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2166         WARN("Surface is locked or the HDC is in use\n");
2167         return WINED3DERR_INVALIDCALL;
2168     }
2169
2170     if(Mem && Mem != This->resource.allocatedMemory) {
2171
2172         /* Do I have to copy the old surface content? */
2173         if(This->Flags & SFLAG_DIBSECTION) {
2174                 /* Release the DC. No need to hold the critical section for the update
2175                  * Thread because this thread runs only on front buffers, but this method
2176                  * fails for render targets in the check above.
2177                  */
2178                 SelectObject(This->hDC, This->dib.holdbitmap);
2179                 DeleteDC(This->hDC);
2180                 /* Release the DIB section */
2181                 DeleteObject(This->dib.DIBsection);
2182                 This->dib.bitmap_data = NULL;
2183                 This->resource.allocatedMemory = NULL;
2184                 This->hDC = NULL;
2185                 This->Flags &= ~SFLAG_DIBSECTION;
2186         } else if(!(This->Flags & SFLAG_USERPTR)) {
2187             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2188         }
2189         This->resource.allocatedMemory = Mem;
2190         This->Flags |= SFLAG_USERPTR;
2191     } else if(This->Flags & SFLAG_USERPTR) {
2192         /* Lockrect and GetDC will re-create the dib section and allocated memory */
2193         This->resource.allocatedMemory = NULL;
2194         This->Flags &= ~SFLAG_USERPTR;
2195     }
2196     return WINED3D_OK;
2197 }
2198
2199 /* TODO: replace this function with context management routines */
2200 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
2201     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2202
2203     if(inPBuffer) {
2204         This->Flags |= SFLAG_INPBUFFER;
2205     } else {
2206         This->Flags &= ~SFLAG_INPBUFFER;
2207     }
2208
2209     if(inTexture) {
2210         This->Flags |= SFLAG_INTEXTURE;
2211     } else {
2212         This->Flags &= ~SFLAG_INTEXTURE;
2213     }
2214
2215     return WINED3D_OK;
2216 }
2217
2218 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2219     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2220     IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
2221     TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2222
2223     /* Flipping is only supported on RenderTargets */
2224     if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
2225
2226     if(override) {
2227         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
2228          * FIXME("(%p) Target override is not supported by now\n", This);
2229          * Additionally, it isn't really possible to support triple-buffering
2230          * properly on opengl at all
2231          */
2232     }
2233
2234     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2235     return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
2236 }
2237
2238 /* Not called from the VTable */
2239 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2240     D3DRECT rect;
2241     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2242     IWineD3DSwapChainImpl *swapchain = NULL;
2243     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2244     BOOL SrcOK = TRUE;
2245
2246     TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2247
2248     /* Get the swapchain. One of the surfaces has to be a primary surface */
2249     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
2250     if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2251     else if(Src) {
2252         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&swapchain);
2253         if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2254         else return WINED3DERR_INVALIDCALL;
2255     } else {
2256         swapchain = NULL;
2257     }
2258
2259     if (DestRect) {
2260         rect.x1 = DestRect->left;
2261         rect.y1 = DestRect->top;
2262         rect.x2 = DestRect->right;
2263         rect.y2 = DestRect->bottom;
2264     } else {
2265         rect.x1 = 0;
2266         rect.y1 = 0;
2267         rect.x2 = This->currentDesc.Width;
2268         rect.y2 = This->currentDesc.Height;
2269     }
2270
2271     /* Half-life does a Blt from the back buffer to the front buffer,
2272      * Full surface size, no flags... Use present instead
2273      */
2274     if(Src)
2275     {
2276         /* First, check if we can do a Flip */
2277
2278         /* Check rects - IWineD3DDevice_Present doesn't handle them */
2279         if( SrcRect ) {
2280             if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
2281                 (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
2282                 SrcOK = TRUE;
2283             }
2284         } else {
2285             SrcOK = TRUE;
2286         }
2287
2288         /* Check the Destination rect and the surface sizes */
2289         if(SrcOK &&
2290            (rect.x1 == 0) && (rect.y1 == 0) &&
2291            (rect.x2 ==  This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
2292            (This->currentDesc.Width == Src->currentDesc.Width) &&
2293            (This->currentDesc.Height == Src->currentDesc.Height)) {
2294             /* These flags are unimportant for the flag check, remove them */
2295
2296             if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
2297                 if( swapchain->backBuffer && ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer[0]) ) {
2298
2299                     D3DSWAPEFFECT orig_swap = swapchain->presentParms.SwapEffect;
2300
2301                     /* The idea behind this is that a glReadPixels and a glDrawPixels call
2302                      * take very long, while a flip is fast.
2303                      * This applies to Half-Life, which does such Blts every time it finished
2304                      * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2305                      * menu. This is also used by all apps when they do windowed rendering
2306                      *
2307                      * The problem is that flipping is not really the same as copying. After a
2308                      * Blt the front buffer is a copy of the back buffer, and the back buffer is
2309                      * untouched. Therefore it's necessary to override the swap effect
2310                      * and to set it back after the flip.
2311                      */
2312
2313                     swapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
2314
2315                     TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2316                     IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
2317                                             NULL, NULL, 0, NULL);
2318
2319                     swapchain->presentParms.SwapEffect = orig_swap;
2320
2321                     return WINED3D_OK;
2322                 }
2323             }
2324         }
2325
2326         /* Blt from texture to rendertarget? */
2327         if( ( ( (IWineD3DSurface *) This == swapchain->frontBuffer) ||
2328               ( swapchain->backBuffer && (IWineD3DSurface *) This == swapchain->backBuffer[0]) )
2329               &&
2330               ( ( (IWineD3DSurface *) Src != swapchain->frontBuffer) &&
2331                 ( swapchain->backBuffer && (IWineD3DSurface *) Src != swapchain->backBuffer[0]) ) ) {
2332             float glTexCoord[4];
2333             DWORD oldCKey;
2334             DDCOLORKEY oldBltCKey = {0,0};
2335             GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha;
2336             GLint alphafunc;
2337             GLclampf alpharef;
2338             GLint oldStencil;
2339             RECT SourceRectangle;
2340             GLint oldDraw;
2341
2342             TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
2343
2344             if(SrcRect) {
2345                 SourceRectangle.left = SrcRect->left;
2346                 SourceRectangle.right = SrcRect->right;
2347                 SourceRectangle.top = SrcRect->top;
2348                 SourceRectangle.bottom = SrcRect->bottom;
2349             } else {
2350                 SourceRectangle.left = 0;
2351                 SourceRectangle.right = Src->currentDesc.Width;
2352                 SourceRectangle.top = 0;
2353                 SourceRectangle.bottom = Src->currentDesc.Height;
2354             }
2355
2356             if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
2357                 /* Fall back to software */
2358                 WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
2359                      SourceRectangle.left, SourceRectangle.top,
2360                      SourceRectangle.right, SourceRectangle.bottom);
2361                 return WINED3DERR_INVALIDCALL;
2362             }
2363
2364             /* Color keying: Check if we have to do a color keyed blt,
2365              * and if not check if a color key is activated.
2366              */
2367             oldCKey = Src->CKeyFlags;
2368             if(!(Flags & DDBLT_KEYSRC) && 
2369                Src->CKeyFlags & DDSD_CKSRCBLT) {
2370                 /* Ok, the surface has a color key, but we shall not use it -
2371                  * Deactivate it for now, LoadTexture will catch this
2372                  */
2373                 Src->CKeyFlags &= ~DDSD_CKSRCBLT;
2374             }
2375
2376             /* Color keying */
2377             if(Flags & DDBLT_KEYDEST) {
2378                 oldBltCKey = This->SrcBltCKey;
2379                 /* Temporary replace the source color key with the destination one. We do this because the color conversion code which
2380                  * is in the end called from LoadTexture works with the source color. At the end of this function we restore the color key.
2381                  */
2382                 This->SrcBltCKey = This->DestBltCKey;
2383             } else if (Flags & DDBLT_KEYSRC)
2384                 oldBltCKey = This->SrcBltCKey;
2385
2386             /* Now load the surface */
2387             IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
2388
2389             ENTER_GL();
2390
2391             /* Save all the old stuff until we have a proper opengl state manager */
2392             oldLight = glIsEnabled(GL_LIGHTING);
2393             oldFog = glIsEnabled(GL_FOG);
2394             oldDepth = glIsEnabled(GL_DEPTH_TEST);
2395             oldBlend = glIsEnabled(GL_BLEND);
2396             oldCull = glIsEnabled(GL_CULL_FACE);
2397             oldAlpha = glIsEnabled(GL_ALPHA_TEST);
2398             oldStencil = glIsEnabled(GL_STENCIL_TEST);
2399
2400             glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphafunc);
2401             checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC");
2402             glGetFloatv(GL_ALPHA_TEST_REF, &alpharef);
2403             checkGLcall("glGetFloatv GL_ALPHA_TEST_REF");
2404
2405             glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
2406             if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer) {
2407                 TRACE("Drawing to front buffer\n");
2408                 glDrawBuffer(GL_FRONT);
2409                 checkGLcall("glDrawBuffer GL_FRONT");
2410             }
2411
2412             /* Unbind the old texture */
2413             glBindTexture(GL_TEXTURE_2D, 0);
2414
2415             if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2416             /* We use texture unit 0 for blts */
2417                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
2418                 checkGLcall("glActiveTextureARB");
2419             } else {
2420                 WARN("Multi-texturing is unsupported in the local OpenGL implementation\n");
2421             }
2422
2423             /* Disable some fancy graphics effects */
2424             glDisable(GL_LIGHTING);
2425             checkGLcall("glDisable GL_LIGHTING");
2426             glDisable(GL_DEPTH_TEST);
2427             checkGLcall("glDisable GL_DEPTH_TEST");
2428             glDisable(GL_FOG);
2429             checkGLcall("glDisable GL_FOG");
2430             glDisable(GL_BLEND);
2431             checkGLcall("glDisable GL_BLEND");
2432             glDisable(GL_CULL_FACE);
2433             checkGLcall("glDisable GL_CULL_FACE");
2434             glDisable(GL_STENCIL_TEST);
2435             checkGLcall("glDisable GL_STENCIL_TEST");
2436
2437             /* Ok, we need 2d textures, but not 1D or 3D */
2438             glDisable(GL_TEXTURE_1D);
2439             checkGLcall("glDisable GL_TEXTURE_1D");
2440             glEnable(GL_TEXTURE_2D);
2441             checkGLcall("glEnable GL_TEXTURE_2D");
2442             glDisable(GL_TEXTURE_3D);
2443             checkGLcall("glDisable GL_TEXTURE_3D");
2444
2445             /* Bind the texture */
2446             glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2447             checkGLcall("glBindTexture");
2448
2449             glEnable(GL_SCISSOR_TEST);
2450
2451             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2452
2453             /* No filtering for blts */
2454             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
2455                             GL_NEAREST);
2456             checkGLcall("glTexParameteri");
2457             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
2458                             GL_NEAREST);
2459             checkGLcall("glTexParameteri");
2460             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2461             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2462             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2463             checkGLcall("glTexEnvi");
2464
2465             /* This is for color keying */
2466             if(Flags & DDBLT_KEYSRC) {
2467                 glEnable(GL_ALPHA_TEST);
2468                 checkGLcall("glEnable GL_ALPHA_TEST");
2469                 glAlphaFunc(GL_NOTEQUAL, 0.0);
2470                 checkGLcall("glAlphaFunc\n");
2471             } else {
2472                 glDisable(GL_ALPHA_TEST);
2473                 checkGLcall("glDisable GL_ALPHA_TEST");
2474             }
2475
2476             /* Draw a textured quad
2477              */
2478             d3ddevice_set_ortho(This->resource.wineD3DDevice);
2479
2480             glBegin(GL_QUADS);
2481
2482             glColor3d(1.0f, 1.0f, 1.0f);
2483             glTexCoord2f(glTexCoord[0], glTexCoord[2]);
2484             glVertex3f(rect.x1,
2485                        rect.y1,
2486                        0.0);
2487
2488             glTexCoord2f(glTexCoord[0], glTexCoord[3]);
2489             glVertex3f(rect.x1, rect.y2, 0.0);
2490
2491             glTexCoord2f(glTexCoord[1], glTexCoord[3]);
2492             glVertex3f(rect.x2,
2493                        rect.y2,
2494                        0.0);
2495
2496             glTexCoord2f(glTexCoord[1], glTexCoord[2]);
2497             glVertex3f(rect.x2,
2498                        rect.y1,
2499                        0.0);
2500             glEnd();
2501             checkGLcall("glEnd");
2502
2503             /* Unbind the texture */
2504             glBindTexture(GL_TEXTURE_2D, 0);
2505             checkGLcall("glEnable glBindTexture");
2506
2507             /* Restore the old settings */
2508             if(oldLight) {
2509                 glEnable(GL_LIGHTING);
2510                 checkGLcall("glEnable GL_LIGHTING");
2511             }
2512             if(oldFog) {
2513                 glEnable(GL_FOG);
2514                 checkGLcall("glEnable GL_FOG");
2515             }
2516             if(oldDepth) {
2517                 glEnable(GL_DEPTH_TEST);
2518                 checkGLcall("glEnable GL_DEPTH_TEST");
2519             }
2520             if(oldBlend) {
2521                 glEnable(GL_BLEND);
2522                 checkGLcall("glEnable GL_BLEND");
2523             }
2524             if(oldCull) {
2525                 glEnable(GL_CULL_FACE);
2526                 checkGLcall("glEnable GL_CULL_FACE");
2527             }
2528             if(oldStencil) {
2529                 glEnable(GL_STENCIL_TEST);
2530                 checkGLcall("glEnable GL_STENCIL_TEST");
2531             }
2532             if(!oldAlpha) {
2533                 glDisable(GL_ALPHA_TEST);
2534                 checkGLcall("glDisable GL_ALPHA_TEST");
2535             } else {
2536                 glEnable(GL_ALPHA_TEST);
2537                 checkGLcall("glEnable GL_ALPHA_TEST");
2538             }
2539
2540             glAlphaFunc(alphafunc, alpharef);
2541             checkGLcall("glAlphaFunc\n");
2542
2543             if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer && oldDraw == GL_BACK) {
2544                 glDrawBuffer(oldDraw);
2545             }
2546
2547             /* Restore the color key flags */
2548             if(oldCKey != Src->CKeyFlags) {
2549                 Src->CKeyFlags = oldCKey;
2550             }
2551
2552             /* Restore the old color key */
2553             if (Flags & (DDBLT_KEYSRC | DDBLT_KEYDEST))
2554                 This->SrcBltCKey = oldBltCKey;
2555
2556             LEAVE_GL();
2557
2558             /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2559             This->Flags |= SFLAG_GLDIRTY;
2560
2561             return WINED3D_OK;
2562         }
2563
2564
2565         /* Blt from rendertarget to texture? */
2566         if( (SrcSurface == swapchain->frontBuffer) ||
2567             (swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) ) {
2568             if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
2569                 ( swapchain->backBuffer && (IWineD3DSurface *) This != swapchain->backBuffer[0]) ) {
2570                 UINT row;
2571                 D3DRECT srect;
2572                 float xrel, yrel;
2573
2574                 TRACE("Blt from rendertarget to texture\n");
2575
2576                 /* Call preload for the surface to make sure it isn't dirty */
2577                 IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2578
2579                 if(SrcRect) {
2580                     srect.x1 = SrcRect->left;
2581                     srect.y1 = SrcRect->top;
2582                     srect.x2 = SrcRect->right;
2583                     srect.y2 = SrcRect->bottom;
2584                 } else {
2585                     srect.x1 = 0;
2586                     srect.y1 = 0;
2587                     srect.x2 = Src->currentDesc.Width;
2588                     srect.y2 = Src->currentDesc.Height;
2589                 }
2590
2591                 ENTER_GL();
2592
2593                 /* Bind the target texture */
2594                 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2595                 checkGLcall("glBindTexture");
2596                 if(swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) {
2597                     glReadBuffer(GL_BACK);
2598                 } else {
2599                     glReadBuffer(GL_FRONT);
2600                 }
2601                 checkGLcall("glReadBuffer");
2602
2603                 xrel = (float) (srect.x2 - srect.x1) / (float) (rect.x2 - rect.x1);
2604                 yrel = (float) (srect.y2 - srect.y1) / (float) (rect.y2 - rect.y1);
2605
2606                 /* I have to process this row by row to swap the image,
2607                  * otherwise it would be upside down, so streching in y direction
2608                  * doesn't cost extra time
2609                  *
2610                  * However, streching in x direction can be avoided if not necessary
2611                  */
2612                 for(row = rect.y1; row < rect.y2; row++) {
2613                     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2614                         /* Well, that stuff works, but it's very slow.
2615                          * find a better way instead
2616                          */
2617                         UINT col;
2618                         for(col = rect.x1; col < rect.x2; col++) {
2619                             glCopyTexSubImage2D(GL_TEXTURE_2D,
2620                                                 0, /* level */
2621                                                 rect.x1 + col, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2622                                                 srect.x1 + col * xrel, Src->currentDesc.Height - srect.y2 + row * yrel,
2623                                                 1, 1);
2624                         }
2625                     } else {
2626                         glCopyTexSubImage2D(GL_TEXTURE_2D,
2627                                             0, /* level */
2628                                             rect.x1, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2629                                             srect.x1, Src->currentDesc.Height - srect.y2 + row * yrel,
2630                                             rect.x2, 1);
2631                     }
2632                 }
2633
2634                 vcheckGLcall("glCopyTexSubImage2D");
2635                 LEAVE_GL();
2636
2637                 if(!(This->Flags & SFLAG_DONOTFREE)) {
2638                     HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2639                     This->resource.allocatedMemory = NULL;
2640                 } else {
2641                     This->Flags |= SFLAG_GLDIRTY;
2642                 }
2643
2644                 return WINED3D_OK;
2645             }
2646         }
2647     }
2648
2649     if (Flags & DDBLT_COLORFILL) {
2650         /* This is easy to handle for the D3D Device... */
2651         DWORD color;
2652         IWineD3DSwapChainImpl *implSwapChain;
2653
2654         TRACE("Colorfill\n");
2655
2656         /* The color as given in the Blt function is in the format of the frame-buffer...
2657          * 'clear' expect it in ARGB format => we need to do some conversion :-)
2658          */
2659         if (This->resource.format == WINED3DFMT_P8) {
2660             if (This->palette) {
2661                 color = ((0xFF000000) |
2662                           (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2663                           (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2664                           (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2665             } else {
2666                 color = 0xFF000000;
2667             }
2668         }
2669         else if (This->resource.format == WINED3DFMT_R5G6B5) {
2670             if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2671                 color = 0xFFFFFFFF;
2672             } else {
2673                 color = ((0xFF000000) |
2674                           ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2675                           ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2676                           ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2677             }
2678         }
2679         else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2680                   (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2681             color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2682         }
2683         else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2684             color = DDBltFx->u5.dwFillColor;
2685         }
2686         else {
2687             ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2688             return WINED3DERR_INVALIDCALL;
2689         }
2690
2691         TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2692         IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
2693         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
2694         if(implSwapChain->backBuffer && This == (IWineD3DSurfaceImpl*) implSwapChain->backBuffer[0]) {
2695             glDrawBuffer(GL_BACK);
2696             checkGLcall("glDrawBuffer(GL_BACK)");
2697         }
2698         else if (This == (IWineD3DSurfaceImpl*) implSwapChain->frontBuffer) {
2699             glDrawBuffer(GL_FRONT);
2700             checkGLcall("glDrawBuffer(GL_FRONT)");
2701         }
2702         else {
2703             ERR("Wrong surface type for BLT override(not on swapchain) !\n");
2704             return WINED3DERR_INVALIDCALL;
2705         }
2706
2707         TRACE("(%p) executing Render Target override, color = %x\n", This, color);
2708
2709         IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2710                               1 /* Number of rectangles */,
2711                               &rect,
2712                               D3DCLEAR_TARGET,
2713                               color,
2714                               0.0 /* Z */,
2715                               0 /* Stencil */);
2716
2717         /* Restore the original draw buffer */
2718         if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
2719             glDrawBuffer(GL_BACK);
2720             vcheckGLcall("glDrawBuffer");
2721         }
2722
2723         return WINED3D_OK;
2724     }
2725
2726     /* Default: Fall back to the generic blt */
2727     return WINED3DERR_INVALIDCALL;
2728 }
2729
2730 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2731     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2732     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2733     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2734     TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
2735
2736     /* Special cases for RenderTargets */
2737     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2738         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2739         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2740     }
2741
2742     /* For the rest call the X11 surface implementation.
2743      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2744      * other Blts are rather rare
2745      */
2746     return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2747 }
2748
2749 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2750     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2751     TRACE("(%p)->(%x)\n", This, Flags);
2752
2753     switch (Flags)
2754     {
2755     case DDGBS_CANBLT:
2756     case DDGBS_ISBLTDONE:
2757         return DD_OK;
2758
2759     default:
2760         return DDERR_INVALIDPARAMS;
2761     }
2762 }
2763
2764 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2765     /* XXX: DDERR_INVALIDSURFACETYPE */
2766
2767     TRACE("(%p)->(%08x)\n",iface,Flags);
2768     switch (Flags) {
2769     case DDGFS_CANFLIP:
2770     case DDGFS_ISFLIPDONE:
2771         return DD_OK;
2772
2773     default:
2774         return DDERR_INVALIDPARAMS;
2775     }
2776 }
2777
2778 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2779     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2780     TRACE("(%p)\n", This);
2781
2782     return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2783 }
2784
2785 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2786     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2787     TRACE("(%p)\n", This);
2788
2789     /* So far we don't lose anything :) */
2790     This->Flags &= ~SFLAG_LOST;
2791     return WINED3D_OK;
2792 }
2793
2794 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2795     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2796     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2797     TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
2798
2799     /* Special cases for RenderTargets */
2800     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2801         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2802
2803         RECT SrcRect, DstRect;
2804         DWORD Flags=0;
2805
2806         if(rsrc) {
2807             SrcRect.left = rsrc->left;
2808             SrcRect.top= rsrc->top;
2809             SrcRect.bottom = rsrc->bottom;
2810             SrcRect.right = rsrc->right;
2811         } else {
2812             SrcRect.left = 0;
2813             SrcRect.top = 0;
2814             SrcRect.right = srcImpl->currentDesc.Width;
2815             SrcRect.bottom = srcImpl->currentDesc.Height;
2816         }
2817
2818         DstRect.left = dstx;
2819         DstRect.top=dsty;
2820         DstRect.right = dstx + SrcRect.right - SrcRect.left;
2821         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2822
2823         /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
2824         if(trans & DDBLTFAST_SRCCOLORKEY)
2825             Flags |= DDBLT_KEYSRC;
2826         if(trans & DDBLTFAST_DESTCOLORKEY)
2827             Flags |= DDBLT_KEYDEST;
2828         if(trans & DDBLTFAST_WAIT)
2829             Flags |= DDBLT_WAIT;
2830         if(trans & DDBLTFAST_DONOTWAIT)
2831             Flags |= DDBLT_DONOTWAIT;
2832
2833         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL) == WINED3D_OK) return WINED3D_OK;
2834     }
2835
2836
2837     return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2838 }
2839
2840 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2841     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2842     TRACE("(%p)->(%p)\n", This, Pal);
2843
2844     *Pal = (IWineD3DPalette *) This->palette;
2845     return DD_OK;
2846 }
2847
2848 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2849     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2850     RGBQUAD col[256];
2851     IWineD3DPaletteImpl *pal = This->palette;
2852     unsigned int n;
2853     TRACE("(%p)\n", This);
2854
2855     if(This->resource.format == WINED3DFMT_P8 ||
2856        This->resource.format == WINED3DFMT_A8P8)
2857     {
2858         TRACE("Dirtifying surface\n");
2859         This->Flags |= SFLAG_DIRTY;
2860     }
2861
2862     if(This->Flags & SFLAG_DIBSECTION) {
2863         TRACE("(%p): Updating the hdc's palette\n", This);
2864         for (n=0; n<256; n++) {
2865             if(pal) {
2866                 col[n].rgbRed   = pal->palents[n].peRed;
2867                 col[n].rgbGreen = pal->palents[n].peGreen;
2868                 col[n].rgbBlue  = pal->palents[n].peBlue;
2869             } else {
2870                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2871                 /* Use the default device palette */
2872                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
2873                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
2874                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
2875             }
2876             col[n].rgbReserved = 0;
2877         }
2878         SetDIBColorTable(This->hDC, 0, 256, col);
2879     }
2880
2881     return WINED3D_OK;
2882 }
2883
2884 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
2885     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2886     IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
2887     TRACE("(%p)->(%p)\n", This, Pal);
2888
2889     if(This->palette != NULL) 
2890         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
2891             This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
2892
2893     if(PalImpl != NULL) {
2894         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2895             /* Set the device's main palette if the palette
2896              * wasn't a primary palette before
2897              */
2898             if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
2899                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2900                 unsigned int i;
2901
2902                 for(i=0; i < 256; i++) {
2903                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
2904                 }
2905             }
2906
2907             (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
2908         }
2909     }
2910     This->palette = PalImpl;
2911
2912     return IWineD3DSurface_RealizePalette(iface);
2913 }
2914
2915 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
2916     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2917     TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
2918
2919     if ((Flags & DDCKEY_COLORSPACE) != 0) {
2920         FIXME(" colorkey value not supported (%08x) !\n", Flags);
2921         return DDERR_INVALIDPARAMS;
2922     }
2923
2924     /* Dirtify the surface, but only if a key was changed */
2925     if(CKey) {
2926         switch (Flags & ~DDCKEY_COLORSPACE) {
2927             case DDCKEY_DESTBLT:
2928                 This->DestBltCKey = *CKey;
2929                 This->CKeyFlags |= DDSD_CKDESTBLT;
2930                 break;
2931
2932             case DDCKEY_DESTOVERLAY:
2933                 This->DestOverlayCKey = *CKey;
2934                 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
2935                 break;
2936
2937             case DDCKEY_SRCOVERLAY:
2938                 This->SrcOverlayCKey = *CKey;
2939                 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
2940                 break;
2941
2942             case DDCKEY_SRCBLT:
2943                 This->SrcBltCKey = *CKey;
2944                 This->CKeyFlags |= DDSD_CKSRCBLT;
2945                 break;
2946         }
2947     }
2948     else {
2949         switch (Flags & ~DDCKEY_COLORSPACE) {
2950             case DDCKEY_DESTBLT:
2951                 This->CKeyFlags &= ~DDSD_CKDESTBLT;
2952                 break;
2953
2954             case DDCKEY_DESTOVERLAY:
2955                 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
2956                 break;
2957
2958             case DDCKEY_SRCOVERLAY:
2959                 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
2960                 break;
2961
2962             case DDCKEY_SRCBLT:
2963                 This->CKeyFlags &= ~DDSD_CKSRCBLT;
2964                 break;
2965         }
2966     }
2967
2968     return WINED3D_OK;
2969 }
2970
2971 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
2972     /** Check against the maximum texture sizes supported by the video card **/
2973     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2974
2975     TRACE("%p\n", This);
2976     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
2977         /* one of three options
2978         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)
2979         2: Set the texture to the maxium size (bad idea)
2980         3:    WARN and return WINED3DERR_NOTAVAILABLE;
2981         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.
2982         */
2983         WARN("(%p) Creating an oversized surface\n", This);
2984         This->Flags |= SFLAG_OVERSIZE;
2985
2986         /* This will be initialized on the first blt */
2987         This->glRect.left = 0;
2988         This->glRect.top = 0;
2989         This->glRect.right = 0;
2990         This->glRect.bottom = 0;
2991     } else {
2992         /* No oversize, gl rect is the full texture size */
2993         This->Flags &= ~SFLAG_OVERSIZE;
2994         This->glRect.left = 0;
2995         This->glRect.top = 0;
2996         This->glRect.right = This->pow2Width;
2997         This->glRect.bottom = This->pow2Height;
2998     }
2999
3000     return WINED3D_OK;
3001 }
3002
3003 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
3004     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3005     DWORD ret;
3006     TRACE("(%p)\n", This);
3007
3008     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
3009          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
3010           ie pitch = (width/4) * bytes per block                                  */
3011     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
3012         ret = (This->currentDesc.Width >> 2) << 3;
3013     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
3014              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
3015         ret = (This->currentDesc.Width >> 2) << 4;
3016     else {
3017         if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
3018             /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
3019             ret = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
3020         } else {
3021             ret = This->bytesPerPixel * This->pow2Width;
3022         }
3023         /* Surfaces are 32 bit aligned */
3024         ret = (ret + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
3025     }
3026     TRACE("(%p) Returning %d\n", This, ret);
3027     return ret;
3028 }
3029
3030 HRESULT WINAPI IWineD3DSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
3031     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3032
3033     FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y);
3034
3035     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3036     {
3037         TRACE("(%p): Not an overlay surface\n", This);
3038         return DDERR_NOTAOVERLAYSURFACE;
3039     }
3040
3041     return WINED3D_OK;
3042 }
3043
3044 HRESULT WINAPI IWineD3DSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
3045     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3046
3047     FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y);
3048
3049     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3050     {
3051         TRACE("(%p): Not an overlay surface\n", This);
3052         return DDERR_NOTAOVERLAYSURFACE;
3053     }
3054
3055     return WINED3D_OK;
3056 }
3057
3058 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
3059     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3060     IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
3061
3062     FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
3063
3064     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3065     {
3066         TRACE("(%p): Not an overlay surface\n", This);
3067         return DDERR_NOTAOVERLAYSURFACE;
3068     }
3069
3070     return WINED3D_OK;
3071 }
3072
3073 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX) {
3074     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3075     IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
3076     FIXME("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
3077
3078     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3079     {
3080         TRACE("(%p): Not an overlay surface\n", This);
3081         return DDERR_NOTAOVERLAYSURFACE;
3082     }
3083
3084     return WINED3D_OK;
3085 }
3086
3087 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
3088 {
3089     /* IUnknown */
3090     IWineD3DSurfaceImpl_QueryInterface,
3091     IWineD3DSurfaceImpl_AddRef,
3092     IWineD3DSurfaceImpl_Release,
3093     /* IWineD3DResource */
3094     IWineD3DSurfaceImpl_GetParent,
3095     IWineD3DSurfaceImpl_GetDevice,
3096     IWineD3DSurfaceImpl_SetPrivateData,
3097     IWineD3DSurfaceImpl_GetPrivateData,
3098     IWineD3DSurfaceImpl_FreePrivateData,
3099     IWineD3DSurfaceImpl_SetPriority,
3100     IWineD3DSurfaceImpl_GetPriority,
3101     IWineD3DSurfaceImpl_PreLoad,
3102     IWineD3DSurfaceImpl_GetType,
3103     /* IWineD3DSurface */
3104     IWineD3DSurfaceImpl_GetContainerParent,
3105     IWineD3DSurfaceImpl_GetContainer,
3106     IWineD3DSurfaceImpl_GetDesc,
3107     IWineD3DSurfaceImpl_LockRect,
3108     IWineD3DSurfaceImpl_UnlockRect,
3109     IWineD3DSurfaceImpl_GetDC,
3110     IWineD3DSurfaceImpl_ReleaseDC,
3111     IWineD3DSurfaceImpl_Flip,
3112     IWineD3DSurfaceImpl_Blt,
3113     IWineD3DSurfaceImpl_GetBltStatus,
3114     IWineD3DSurfaceImpl_GetFlipStatus,
3115     IWineD3DSurfaceImpl_IsLost,
3116     IWineD3DSurfaceImpl_Restore,
3117     IWineD3DSurfaceImpl_BltFast,
3118     IWineD3DSurfaceImpl_GetPalette,
3119     IWineD3DSurfaceImpl_SetPalette,
3120     IWineD3DSurfaceImpl_RealizePalette,
3121     IWineD3DSurfaceImpl_SetColorKey,
3122     IWineD3DSurfaceImpl_GetPitch,
3123     IWineD3DSurfaceImpl_SetMem,
3124     IWineD3DSurfaceImpl_SetOverlayPosition,
3125     IWineD3DSurfaceImpl_GetOverlayPosition,
3126     IWineD3DSurfaceImpl_UpdateOverlayZOrder,
3127     IWineD3DSurfaceImpl_UpdateOverlay,
3128     /* Internal use: */
3129     IWineD3DSurfaceImpl_CleanDirtyRect,
3130     IWineD3DSurfaceImpl_AddDirtyRect,
3131     IWineD3DSurfaceImpl_LoadTexture,
3132     IWineD3DSurfaceImpl_SaveSnapshot,
3133     IWineD3DSurfaceImpl_SetContainer,
3134     IWineD3DSurfaceImpl_SetPBufferState,
3135     IWineD3DSurfaceImpl_SetGlTextureDesc,
3136     IWineD3DSurfaceImpl_GetGlDesc,
3137     IWineD3DSurfaceImpl_GetData,
3138     IWineD3DSurfaceImpl_SetFormat,
3139     IWineD3DSurfaceImpl_PrivateSetup
3140 };