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