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