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