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