mshtml: Add IHTMLBodyElement bgColor tests.
[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-2008 Stefan Dösinger for CodeWeavers
11  * Copyright 2007-2008 Henri Verbeet
12  * Copyright 2006-2008 Roderick Colenbrander
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2.1 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28
29 #include "config.h"
30 #include "wine/port.h"
31 #include "wined3d_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
34 #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
35
36 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf);
37 static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey);
38 static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert);
39 static inline void clear_unused_channels(IWineD3DSurfaceImpl *This);
40 static void surface_remove_pbo(IWineD3DSurfaceImpl *This);
41
42 static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This) {
43     int active_sampler;
44
45     /* We don't need a specific texture unit, but after binding the texture the current unit is dirty.
46      * Read the unit back instead of switching to 0, this avoids messing around with the state manager's
47      * gl states. The current texture unit should always be a valid one.
48      *
49      * TODO: Track the current active texture per GL context instead of using glGet
50      */
51     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
52         GLint active_texture;
53         ENTER_GL();
54         glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
55         LEAVE_GL();
56         active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB];
57     } else {
58         active_sampler = 0;
59     }
60
61     if (active_sampler != -1) {
62         IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler));
63     }
64     IWineD3DSurface_BindTexture((IWineD3DSurface *)This);
65 }
66
67 /* This function checks if the primary render target uses the 8bit paletted format. */
68 static BOOL primary_render_target_is_p8(IWineD3DDeviceImpl *device)
69 {
70     if (device->render_targets && device->render_targets[0]) {
71         IWineD3DSurfaceImpl* render_target = (IWineD3DSurfaceImpl*)device->render_targets[0];
72         if((render_target->resource.usage & WINED3DUSAGE_RENDERTARGET) && (render_target->resource.format == WINED3DFMT_P8))
73             return TRUE;
74     }
75     return FALSE;
76 }
77
78 /* This call just downloads data, the caller is responsible for activating the
79  * right context and binding the correct texture. */
80 static void surface_download_data(IWineD3DSurfaceImpl *This) {
81     if (0 == This->glDescription.textureName) {
82         ERR("Surface does not have a texture, but SFLAG_INTEXTURE is set\n");
83         return;
84     }
85
86     /* Only support read back of converted P8 surfaces */
87     if(This->Flags & SFLAG_CONVERTED && (This->resource.format != WINED3DFMT_P8)) {
88         FIXME("Read back converted textures unsupported, format=%s\n", debug_d3dformat(This->resource.format));
89         return;
90     }
91
92     ENTER_GL();
93
94     if (This->resource.format == WINED3DFMT_DXT1 ||
95             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
96             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 ||
97             This->resource.format == WINED3DFMT_ATI2N) {
98         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* We can assume this as the texture would not have been created otherwise */
99             FIXME("(%p) : Attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
100         } else {
101             TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
102                 This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
103
104             if(This->Flags & SFLAG_PBO) {
105                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
106                 checkGLcall("glBindBufferARB");
107                 GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, NULL));
108                 checkGLcall("glGetCompressedTexImageARB()");
109                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
110                 checkGLcall("glBindBufferARB");
111             } else {
112                 GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory));
113                 checkGLcall("glGetCompressedTexImageARB()");
114             }
115         }
116         LEAVE_GL();
117     } else {
118         void *mem;
119         GLenum format = This->glDescription.glFormat;
120         GLenum type = This->glDescription.glType;
121         int src_pitch = 0;
122         int dst_pitch = 0;
123
124         /* In case of P8 the index is stored in the alpha component if the primary render target uses P8 */
125         if(This->resource.format == WINED3DFMT_P8 && primary_render_target_is_p8(This->resource.wineD3DDevice)) {
126             format = GL_ALPHA;
127             type = GL_UNSIGNED_BYTE;
128         }
129
130         if (This->Flags & SFLAG_NONPOW2) {
131             unsigned char alignment = This->resource.wineD3DDevice->surface_alignment;
132             src_pitch = This->bytesPerPixel * This->pow2Width;
133             dst_pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);
134             src_pitch = (src_pitch + alignment - 1) & ~(alignment - 1);
135             mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * This->pow2Height);
136         } else {
137             mem = This->resource.allocatedMemory;
138         }
139
140         TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
141                 format, type, mem);
142
143         if(This->Flags & SFLAG_PBO) {
144             GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
145             checkGLcall("glBindBufferARB");
146
147             glGetTexImage(This->glDescription.target, This->glDescription.level, format,
148                           type, NULL);
149             checkGLcall("glGetTexImage()");
150
151             GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
152             checkGLcall("glBindBufferARB");
153         } else {
154             glGetTexImage(This->glDescription.target, This->glDescription.level, format,
155                           type, mem);
156             checkGLcall("glGetTexImage()");
157         }
158         LEAVE_GL();
159
160         if (This->Flags & SFLAG_NONPOW2) {
161             LPBYTE src_data, dst_data;
162             int y;
163             /*
164              * Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
165              * the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
166              * repack the texture so that the bpp * width pitch can be used instead of bpp * pow2width.
167              *
168              * We're doing this...
169              *
170              * instead of boxing the texture :
171              * |<-texture width ->|  -->pow2width|   /\
172              * |111111111111111111|              |   |
173              * |222 Texture 222222| boxed empty  | texture height
174              * |3333 Data 33333333|              |   |
175              * |444444444444444444|              |   \/
176              * -----------------------------------   |
177              * |     boxed  empty | boxed empty  | pow2height
178              * |                  |              |   \/
179              * -----------------------------------
180              *
181              *
182              * we're repacking the data to the expected texture width
183              *
184              * |<-texture width ->|  -->pow2width|   /\
185              * |111111111111111111222222222222222|   |
186              * |222333333333333333333444444444444| texture height
187              * |444444                           |   |
188              * |                                 |   \/
189              * |                                 |   |
190              * |            empty                | pow2height
191              * |                                 |   \/
192              * -----------------------------------
193              *
194              * == is the same as
195              *
196              * |<-texture width ->|    /\
197              * |111111111111111111|
198              * |222222222222222222|texture height
199              * |333333333333333333|
200              * |444444444444444444|    \/
201              * --------------------
202              *
203              * this also means that any references to allocatedMemory should work with the data as if were a
204              * standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
205              *
206              * internally the texture is still stored in a boxed format so any references to textureName will
207              * get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
208              *
209              * Performance should not be an issue, because applications normally do not lock the surfaces when
210              * rendering. If an app does, the SFLAG_DYNLOCK flag will kick in and the memory copy won't be released,
211              * and doesn't have to be re-read.
212              */
213             src_data = mem;
214             dst_data = This->resource.allocatedMemory;
215             TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, src_pitch, dst_pitch);
216             for (y = 1 ; y < This->currentDesc.Height; y++) {
217                 /* skip the first row */
218                 src_data += src_pitch;
219                 dst_data += dst_pitch;
220                 memcpy(dst_data, src_data, dst_pitch);
221             }
222
223             HeapFree(GetProcessHeap(), 0, mem);
224         }
225     }
226
227     /* Surface has now been downloaded */
228     This->Flags |= SFLAG_INSYSMEM;
229 }
230
231 /* This call just uploads data, the caller is responsible for activating the
232  * right context and binding the correct texture. */
233 static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) {
234
235     if(This->heightscale != 1.0 && This->heightscale != 0.0) height *= This->heightscale;
236
237     if (This->resource.format == WINED3DFMT_DXT1 ||
238             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
239             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 ||
240             This->resource.format == WINED3DFMT_ATI2N) {
241         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
242             FIXME("Using DXT1/3/5 without advertized support\n");
243         } else {
244             /* glCompressedTexSubImage2D for uploading and glTexImage2D for allocating does not work well on some drivers(r200 dri, MacOS ATI driver)
245              * glCompressedTexImage2D does not accept NULL pointers. So for compressed textures surface_allocate_surface does nothing, and this
246              * function uses glCompressedTexImage2D instead of the SubImage call
247              */
248             TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d, data %p\n", This, width, height, data);
249             ENTER_GL();
250
251             if(This->Flags & SFLAG_PBO) {
252                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
253                 checkGLcall("glBindBufferARB");
254                 TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo, data);
255
256                 GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal,
257                         width, height, 0 /* border */, This->resource.size, NULL));
258                 checkGLcall("glCompressedTexSubImage2D");
259
260                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
261                 checkGLcall("glBindBufferARB");
262             } else {
263                 GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal,
264                         width, height, 0 /* border */, This->resource.size, data));
265                 checkGLcall("glCompressedTexSubImage2D");
266             }
267             LEAVE_GL();
268         }
269     } else {
270         TRACE("(%p) : Calling glTexSubImage2D w %d,  h %d, data, %p\n", This, width, height, data);
271         ENTER_GL();
272
273         if(This->Flags & SFLAG_PBO) {
274             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
275             checkGLcall("glBindBufferARB");
276             TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo, data);
277
278             glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, NULL);
279             checkGLcall("glTexSubImage2D");
280
281             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
282             checkGLcall("glBindBufferARB");
283         }
284         else {
285             glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, data);
286             checkGLcall("glTexSubImage2D");
287         }
288
289         LEAVE_GL();
290     }
291 }
292
293 /* This call just allocates the texture, the caller is responsible for
294  * activating the right context and binding the correct texture. */
295 static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) {
296     BOOL enable_client_storage = FALSE;
297     BYTE *mem = NULL;
298
299     if(This->heightscale != 1.0 && This->heightscale != 0.0) height *= This->heightscale;
300
301     TRACE("(%p) : Creating surface (target %#x)  level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n", This,
302             This->glDescription.target, This->glDescription.level, debug_d3dformat(This->resource.format), internal, width, height, format, type);
303
304     if (This->resource.format == WINED3DFMT_DXT1 ||
305             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
306             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 ||
307             This->resource.format == WINED3DFMT_ATI2N) {
308         /* glCompressedTexImage2D does not accept NULL pointers, so we cannot allocate a compressed texture without uploading data */
309         TRACE("Not allocating compressed surfaces, surface_upload_data will specify them\n");
310
311         /* We have to point GL to the client storage memory here, because upload_data might use a PBO. This means a double upload
312          * once, unfortunately
313          */
314         if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
315             /* Neither NONPOW2, DIBSECTION nor OVERSIZE flags can be set on compressed textures */
316             This->Flags |= SFLAG_CLIENT;
317             mem = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
318             ENTER_GL();
319             GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal,
320                        width, height, 0 /* border */, This->resource.size, mem));
321             LEAVE_GL();
322         }
323
324         return;
325     }
326
327     ENTER_GL();
328
329     if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
330         if(This->Flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_OVERSIZE | SFLAG_CONVERTED) || This->resource.allocatedMemory == NULL) {
331             /* In some cases we want to disable client storage.
332              * SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches
333              * SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues...
334              * SFLAG_OVERSIZE: The gl texture is smaller than the allocated memory
335              * SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface
336              * allocatedMemory == NULL: Not defined in the extension. Seems to disable client storage effectively
337              */
338             glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
339             checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
340             This->Flags &= ~SFLAG_CLIENT;
341             enable_client_storage = TRUE;
342         } else {
343             This->Flags |= SFLAG_CLIENT;
344
345             /* Point opengl to our allocated texture memory. Do not use resource.allocatedMemory here because
346              * it might point into a pbo. Instead use heapMemory, but get the alignment right.
347              */
348             mem = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
349         }
350     }
351     glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type, mem);
352     checkGLcall("glTexImage2D");
353
354     if(enable_client_storage) {
355         glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
356         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
357     }
358     LEAVE_GL();
359
360     This->Flags |= SFLAG_ALLOCATED;
361 }
362
363 /* In D3D the depth stencil dimensions have to be greater than or equal to the
364  * render target dimensions. With FBOs, the dimensions have to be an exact match. */
365 /* TODO: We should synchronize the renderbuffer's content with the texture's content. */
366 void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height) {
367     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
368     renderbuffer_entry_t *entry;
369     GLuint renderbuffer = 0;
370     unsigned int src_width, src_height;
371
372     src_width = This->pow2Width;
373     src_height = This->pow2Height;
374
375     /* A depth stencil smaller than the render target is not valid */
376     if (width > src_width || height > src_height) return;
377
378     /* Remove any renderbuffer set if the sizes match */
379     if (width == src_width && height == src_height) {
380         This->current_renderbuffer = NULL;
381         return;
382     }
383
384     /* Look if we've already got a renderbuffer of the correct dimensions */
385     LIST_FOR_EACH_ENTRY(entry, &This->renderbuffers, renderbuffer_entry_t, entry) {
386         if (entry->width == width && entry->height == height) {
387             renderbuffer = entry->id;
388             This->current_renderbuffer = entry;
389             break;
390         }
391     }
392
393     if (!renderbuffer) {
394         const GlPixelFormatDesc *glDesc;
395         getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc);
396
397         GL_EXTCALL(glGenRenderbuffersEXT(1, &renderbuffer));
398         GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer));
399         GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, glDesc->glFormat, width, height));
400
401         entry = HeapAlloc(GetProcessHeap(), 0, sizeof(renderbuffer_entry_t));
402         entry->width = width;
403         entry->height = height;
404         entry->id = renderbuffer;
405         list_add_head(&This->renderbuffers, &entry->entry);
406
407         This->current_renderbuffer = entry;
408     }
409
410     checkGLcall("set_compatible_renderbuffer");
411 }
412
413 GLenum surface_get_gl_buffer(IWineD3DSurface *iface, IWineD3DSwapChain *swapchain) {
414     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
415     IWineD3DSwapChainImpl *swapchain_impl = (IWineD3DSwapChainImpl *)swapchain;
416
417     TRACE("(%p) : swapchain %p\n", This, swapchain);
418
419     if (swapchain_impl->backBuffer && swapchain_impl->backBuffer[0] == iface) {
420         TRACE("Returning GL_BACK\n");
421         return GL_BACK;
422     } else if (swapchain_impl->frontBuffer == iface) {
423         TRACE("Returning GL_FRONT\n");
424         return GL_FRONT;
425     }
426
427     FIXME("Higher back buffer, returning GL_BACK\n");
428     return GL_BACK;
429 }
430
431 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
432     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
433     ULONG ref = InterlockedDecrement(&This->resource.ref);
434     TRACE("(%p) : Releasing from %d\n", This, ref + 1);
435     if (ref == 0) {
436         IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
437         renderbuffer_entry_t *entry, *entry2;
438         TRACE("(%p) : cleaning up\n", This);
439
440         /* Need a context to destroy the texture. Use the currently active render target, but only if
441          * the primary render target exists. Otherwise lastActiveRenderTarget is garbage, see above.
442          * When destroying the primary rt, Uninit3D will activate a context before doing anything
443          */
444         if(device->render_targets && device->render_targets[0]) {
445             ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
446         }
447
448         ENTER_GL();
449         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
450             TRACE("Deleting texture %d\n", This->glDescription.textureName);
451             glDeleteTextures(1, &This->glDescription.textureName);
452         }
453
454         if(This->Flags & SFLAG_PBO) {
455             /* Delete the PBO */
456             GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo));
457         }
458
459         LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) {
460             GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id));
461             HeapFree(GetProcessHeap(), 0, entry);
462         }
463         LEAVE_GL();
464
465         if(This->Flags & SFLAG_DIBSECTION) {
466             /* Release the DC */
467             SelectObject(This->hDC, This->dib.holdbitmap);
468             DeleteDC(This->hDC);
469             /* Release the DIB section */
470             DeleteObject(This->dib.DIBsection);
471             This->dib.bitmap_data = NULL;
472             This->resource.allocatedMemory = NULL;
473         }
474         if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL);
475
476         HeapFree(GetProcessHeap(), 0, This->palette9);
477
478         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
479
480         if(This->overlay_dest) {
481             list_remove(&This->overlay_entry);
482         }
483
484         TRACE("(%p) Released\n", This);
485         HeapFree(GetProcessHeap(), 0, This);
486
487     }
488     return ref;
489 }
490
491 /* ****************************************************
492    IWineD3DSurface IWineD3DResource parts follow
493    **************************************************** */
494
495 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
496     /* TODO: check for locks */
497     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
498     IWineD3DBaseTexture *baseTexture = NULL;
499     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
500
501     TRACE("(%p)Checking to see if the container is a base texture\n", This);
502     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
503         TRACE("Passing to container\n");
504         IWineD3DBaseTexture_PreLoad(baseTexture);
505         IWineD3DBaseTexture_Release(baseTexture);
506     } else {
507         TRACE("(%p) : About to load surface\n", This);
508
509         if(!device->isInDraw) {
510             ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
511         }
512
513         if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) {
514             if(palette9_changed(This)) {
515                 TRACE("Reloading surface because the d3d8/9 palette was changed\n");
516                 /* TODO: This is not necessarily needed with hw palettized texture support */
517                 IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
518                 /* Make sure the texture is reloaded because of the palette change, this kills performance though :( */
519                 IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE);
520             }
521         }
522
523         IWineD3DSurface_LoadTexture(iface, FALSE);
524
525         if (This->resource.pool == WINED3DPOOL_DEFAULT) {
526             /* Tell opengl to try and keep this texture in video ram (well mostly) */
527             GLclampf tmp;
528             tmp = 0.9f;
529             ENTER_GL();
530             glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
531             LEAVE_GL();
532         }
533     }
534     return;
535 }
536
537 static void surface_remove_pbo(IWineD3DSurfaceImpl *This) {
538     This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT);
539     This->resource.allocatedMemory =
540             (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
541
542     ENTER_GL();
543     GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
544     checkGLcall("glBindBuffer(GL_PIXEL_UNPACK_BUFFER, This->pbo)");
545     GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, This->resource.size, This->resource.allocatedMemory));
546     checkGLcall("glGetBufferSubData");
547     GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo));
548     checkGLcall("glDeleteBuffers");
549     LEAVE_GL();
550
551     This->pbo = 0;
552     This->Flags &= ~SFLAG_PBO;
553 }
554
555 static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) {
556     IWineD3DBaseTexture *texture = NULL;
557     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
558     renderbuffer_entry_t *entry, *entry2;
559     TRACE("(%p)\n", iface);
560
561     if(This->resource.pool == WINED3DPOOL_DEFAULT) {
562         /* Default pool resources are supposed to be destroyed before Reset is called.
563          * Implicit resources stay however. So this means we have an implicit render target
564          * or depth stencil. The content may be destroyed, but we still have to tear down
565          * opengl resources, so we cannot leave early.
566          *
567          * Put the most up to date surface location into the drawable. D3D-wise this content
568          * is undefined, so it would be nowhere, but that would make the location management
569          * more complicated. The drawable is a sane location, because if we mark sysmem or
570          * texture up to date, drawPrim will copy the uninitialized texture or sysmem to the
571          * uninitialized drawable. That's pointless and we'd have to allocate the texture /
572          * sysmem copy here.
573          */
574         if (This->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) {
575             IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
576         } else {
577             IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, TRUE);
578         }
579     } else {
580         /* Load the surface into system memory */
581         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
582         IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE);
583     }
584     IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE);
585     This->Flags &= ~SFLAG_ALLOCATED;
586
587     /* Destroy PBOs, but load them into real sysmem before */
588     if(This->Flags & SFLAG_PBO) {
589         surface_remove_pbo(This);
590     }
591
592     /* Destroy fbo render buffers. This is needed for implicit render targets, for
593      * all application-created targets the application has to release the surface
594      * before calling _Reset
595      */
596     LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) {
597         ENTER_GL();
598         GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id));
599         LEAVE_GL();
600         list_remove(&entry->entry);
601         HeapFree(GetProcessHeap(), 0, entry);
602     }
603     list_init(&This->renderbuffers);
604     This->current_renderbuffer = NULL;
605
606     /* If we're in a texture, the texture name belongs to the texture. Otherwise,
607      * destroy it
608      */
609     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **) &texture);
610     if(!texture) {
611         ENTER_GL();
612         glDeleteTextures(1, &This->glDescription.textureName);
613         This->glDescription.textureName = 0;
614         LEAVE_GL();
615     } else {
616         IWineD3DBaseTexture_Release(texture);
617     }
618     return;
619 }
620
621 /* ******************************************************
622    IWineD3DSurface IWineD3DSurface parts follow
623    ****************************************************** */
624
625 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
626     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
627     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
628     if (This->glDescription.textureName == 0 && textureName != 0) {
629         IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE);
630         if((This->Flags & SFLAG_LOCATIONS) == 0) {
631             /* In 1.0-rc4 and earlier, AddDirtyRect was called in the place of this if condition.
632              * This had the problem that a correctly set INDRAWABLE flag was removed if the PreLoad
633              * during the offscreen rendering readback triggered the creation of the GL texture.
634              * The change intended to keep the INDRAWABLE intact. To prevent unintended side effects
635              * before release, set the INSYSMEM flag like the old AddDirtyRect did.
636              */
637             WARN("Wine 1.0 safety path hit\n");
638             This->Flags |= SFLAG_INSYSMEM;
639         }
640     }
641     if(target == GL_TEXTURE_RECTANGLE_ARB && This->glDescription.target != target) {
642         This->Flags &= ~SFLAG_NORMCOORD;
643     } else if(This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB && target != GL_TEXTURE_RECTANGLE_ARB) {
644         This->Flags |= SFLAG_NORMCOORD;
645     }
646     This->glDescription.textureName = textureName;
647     This->glDescription.target      = target;
648     This->Flags &= ~SFLAG_ALLOCATED;
649 }
650
651 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
652     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
653     TRACE("(%p) : returning %p\n", This, &This->glDescription);
654     *glDescription = &This->glDescription;
655 }
656
657 /* TODO: think about moving this down to resource? */
658 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
659     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
660     /* 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 future  */
661     if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
662         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
663     }
664     return (CONST void*)(This->resource.allocatedMemory);
665 }
666
667 /* Read the framebuffer back into the surface */
668 static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) {
669     IWineD3DSwapChainImpl *swapchain;
670     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
671     BYTE *mem;
672     GLint fmt;
673     GLint type;
674     BYTE *row, *top, *bottom;
675     int i;
676     BOOL bpp;
677     RECT local_rect;
678     BOOL srcIsUpsideDown;
679
680     if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
681         static BOOL warned = FALSE;
682         if(!warned) {
683             ERR("The application tries to lock the render target, but render target locking is disabled\n");
684             warned = TRUE;
685         }
686         return;
687     }
688
689     IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
690     /* Activate the surface. Set it up for blitting now, although not necessarily needed for LockRect.
691      * Certain graphics drivers seem to dislike some enabled states when reading from opengl, the blitting usage
692      * should help here. Furthermore unlockrect will need the context set up for blitting. The context manager will find
693      * context->last_was_blit set on the unlock.
694      */
695     ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
696     ENTER_GL();
697
698     /* Select the correct read buffer, and give some debug output.
699      * There is no need to keep track of the current read buffer or reset it, every part of the code
700      * that reads sets the read buffer as desired.
701      */
702     if(!swapchain) {
703         /* Locking the primary render target which is not on a swapchain(=offscreen render target).
704          * Read from the back buffer
705          */
706         TRACE("Locking offscreen render target\n");
707         glReadBuffer(myDevice->offscreenBuffer);
708         srcIsUpsideDown = TRUE;
709     } else {
710         GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain);
711         TRACE("Locking %#x buffer\n", buffer);
712         glReadBuffer(buffer);
713         checkGLcall("glReadBuffer");
714
715         IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
716         srcIsUpsideDown = FALSE;
717     }
718
719     /* TODO: Get rid of the extra rectangle comparison and construction of a full surface rectangle */
720     if(!rect) {
721         local_rect.left = 0;
722         local_rect.top = 0;
723         local_rect.right = This->currentDesc.Width;
724         local_rect.bottom = This->currentDesc.Height;
725     } else {
726         local_rect = *rect;
727     }
728     /* TODO: Get rid of the extra GetPitch call, LockRect does that too. Cache the pitch */
729
730     switch(This->resource.format)
731     {
732         case WINED3DFMT_P8:
733         {
734             if(primary_render_target_is_p8(myDevice)) {
735                 /* In case of P8 render targets the index is stored in the alpha component */
736                 fmt = GL_ALPHA;
737                 type = GL_UNSIGNED_BYTE;
738                 mem = dest;
739                 bpp = This->bytesPerPixel;
740             } else {
741                 /* GL can't return palettized data, so read ARGB pixels into a
742                  * separate block of memory and convert them into palettized format
743                  * in software. Slow, but if the app means to use palettized render
744                  * targets and locks it...
745                  *
746                  * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
747                  * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
748                  * for the color channels when palettizing the colors.
749                  */
750                 fmt = GL_RGB;
751                 type = GL_UNSIGNED_BYTE;
752                 pitch *= 3;
753                 mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * 3);
754                 if(!mem) {
755                     ERR("Out of memory\n");
756                     LEAVE_GL();
757                     return;
758                 }
759                 bpp = This->bytesPerPixel * 3;
760             }
761         }
762         break;
763
764         default:
765             mem = dest;
766             fmt = This->glDescription.glFormat;
767             type = This->glDescription.glType;
768             bpp = This->bytesPerPixel;
769     }
770
771     if(This->Flags & SFLAG_PBO) {
772         GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
773         checkGLcall("glBindBufferARB");
774     }
775
776     glReadPixels(local_rect.left, local_rect.top,
777                  local_rect.right - local_rect.left,
778                  local_rect.bottom - local_rect.top,
779                  fmt, type, mem);
780     vcheckGLcall("glReadPixels");
781
782     if(This->Flags & SFLAG_PBO) {
783         GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
784         checkGLcall("glBindBufferARB");
785
786         /* Check if we need to flip the image. If we need to flip use glMapBufferARB
787          * to get a pointer to it and perform the flipping in software. This is a lot
788          * faster than calling glReadPixels for each line. In case we want more speed
789          * we should rerender it flipped in a FBO and read the data back from the FBO. */
790         if(!srcIsUpsideDown) {
791             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
792             checkGLcall("glBindBufferARB");
793
794             mem = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB));
795             checkGLcall("glMapBufferARB");
796         }
797     }
798
799     /* TODO: Merge this with the palettization loop below for P8 targets */
800     if(!srcIsUpsideDown) {
801         UINT len, off;
802         /* glReadPixels returns the image upside down, and there is no way to prevent this.
803             Flip the lines in software */
804         len = (local_rect.right - local_rect.left) * bpp;
805         off = local_rect.left * bpp;
806
807         row = HeapAlloc(GetProcessHeap(), 0, len);
808         if(!row) {
809             ERR("Out of memory\n");
810             if(This->resource.format == WINED3DFMT_P8) HeapFree(GetProcessHeap(), 0, mem);
811             LEAVE_GL();
812             return;
813         }
814
815         top = mem + pitch * local_rect.top;
816         bottom = mem + pitch * ( local_rect.bottom - local_rect.top - 1);
817         for(i = 0; i < (local_rect.bottom - local_rect.top) / 2; i++) {
818             memcpy(row, top + off, len);
819             memcpy(top + off, bottom + off, len);
820             memcpy(bottom + off, row, len);
821             top += pitch;
822             bottom -= pitch;
823         }
824         HeapFree(GetProcessHeap(), 0, row);
825
826         /* Unmap the temp PBO buffer */
827         if(This->Flags & SFLAG_PBO) {
828             GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
829             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
830         }
831     }
832
833     LEAVE_GL();
834
835     /* For P8 textures we need to perform an inverse palette lookup. This is done by searching for a palette
836      * index which matches the RGB value. Note this isn't guaranteed to work when there are multiple entries for
837      * the same color but we have no choice.
838      * In case of P8 render targets, the index is stored in the alpha component so no conversion is needed.
839      */
840     if((This->resource.format == WINED3DFMT_P8) && !primary_render_target_is_p8(myDevice)) {
841         PALETTEENTRY *pal = NULL;
842         DWORD width = pitch / 3;
843         int x, y, c;
844
845         if(This->palette) {
846             pal = This->palette->palents;
847         } else {
848             ERR("Palette is missing, cannot perform inverse palette lookup\n");
849             HeapFree(GetProcessHeap(), 0, mem);
850             return ;
851         }
852
853         for(y = local_rect.top; y < local_rect.bottom; y++) {
854             for(x = local_rect.left; x < local_rect.right; x++) {
855                 /*                      start              lines            pixels      */
856                 BYTE *blue =  mem + y * pitch + x * (sizeof(BYTE) * 3);
857                 BYTE *green = blue  + 1;
858                 BYTE *red =   green + 1;
859
860                 for(c = 0; c < 256; c++) {
861                     if(*red   == pal[c].peRed   &&
862                        *green == pal[c].peGreen &&
863                        *blue  == pal[c].peBlue)
864                     {
865                         *((BYTE *) dest + y * width + x) = c;
866                         break;
867                     }
868                 }
869             }
870         }
871         HeapFree(GetProcessHeap(), 0, mem);
872     }
873 }
874
875 /* Read the framebuffer contents into a texture */
876 static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This)
877 {
878     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
879     IWineD3DSwapChainImpl *swapchain;
880     int bpp;
881     GLenum format, internal, type;
882     CONVERT_TYPES convert;
883     GLint prevRead;
884
885     d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
886
887     IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
888     /* Activate the surface to read from. In some situations it isn't the currently active target(e.g. backbuffer
889      * locking during offscreen rendering). RESOURCELOAD is ok because glCopyTexSubImage2D isn't affected by any
890      * states in the stateblock, and no driver was found yet that had bugs in that regard.
891      */
892     ActivateContext(device, (IWineD3DSurface *) This, CTXUSAGE_RESOURCELOAD);
893     surface_bind_and_dirtify(This);
894     ENTER_GL();
895
896     glGetIntegerv(GL_READ_BUFFER, &prevRead);
897
898     /* Select the correct read buffer, and give some debug output.
899      * There is no need to keep track of the current read buffer or reset it, every part of the code
900      * that reads sets the read buffer as desired.
901      */
902     if(!swapchain) {
903         /* Locking the primary render target which is not on a swapchain(=offscreen render target).
904          * Read from the back buffer
905          */
906         TRACE("Locking offscreen render target\n");
907         glReadBuffer(device->offscreenBuffer);
908     } else {
909         GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain);
910         TRACE("Locking %#x buffer\n", buffer);
911         glReadBuffer(buffer);
912         checkGLcall("glReadBuffer");
913
914         IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
915     }
916
917     if(!(This->Flags & SFLAG_ALLOCATED)) {
918         surface_allocate_surface(This, internal, This->pow2Width,
919                                  This->pow2Height, format, type);
920     }
921
922     clear_unused_channels(This);
923
924     /* If !SrcIsUpsideDown we should flip the surface.
925      * This can be done using glCopyTexSubImage2D but this
926      * is VERY slow, so don't do that. We should prevent
927      * this code from getting called in such cases or perhaps
928      * we can use FBOs */
929
930     glCopyTexSubImage2D(This->glDescription.target,
931                         This->glDescription.level,
932                         0, 0, 0, 0,
933                         This->currentDesc.Width,
934                         This->currentDesc.Height);
935     checkGLcall("glCopyTexSubImage2D");
936
937     glReadBuffer(prevRead);
938     vcheckGLcall("glReadBuffer");
939
940     LEAVE_GL();
941     TRACE("Updated target %d\n", This->glDescription.target);
942 }
943
944 static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) {
945     /* Performance optimization: Count how often a surface is locked, if it is locked regularly do not throw away the system memory copy.
946      * This avoids the need to download the surface from opengl all the time. The surface is still downloaded if the opengl texture is
947      * changed
948      */
949     if(!(This->Flags & SFLAG_DYNLOCK)) {
950         This->lockCount++;
951         /* MAXLOCKCOUNT is defined in wined3d_private.h */
952         if(This->lockCount > MAXLOCKCOUNT) {
953             TRACE("Surface is locked regularly, not freeing the system memory copy any more\n");
954             This->Flags |= SFLAG_DYNLOCK;
955         }
956     }
957
958     /* Create a PBO for dynamically locked surfaces but don't do it for converted or non-pow2 surfaces.
959      * Also don't create a PBO for systemmem surfaces.
960      */
961     if(GL_SUPPORT(ARB_PIXEL_BUFFER_OBJECT) && (This->Flags & SFLAG_DYNLOCK) && !(This->Flags & (SFLAG_PBO | SFLAG_CONVERTED | SFLAG_NONPOW2)) && (This->resource.pool != WINED3DPOOL_SYSTEMMEM)) {
962         GLenum error;
963         IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
964
965         ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
966         ENTER_GL();
967
968         GL_EXTCALL(glGenBuffersARB(1, &This->pbo));
969         error = glGetError();
970         if(This->pbo == 0 || error != GL_NO_ERROR) {
971             ERR("Failed to bind the PBO with error %s (%#x)\n", debug_glerror(error), error);
972         }
973
974         TRACE("Attaching pbo=%#x to (%p)\n", This->pbo, This);
975
976         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
977         checkGLcall("glBindBufferARB");
978
979         GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->resource.size + 4, This->resource.allocatedMemory, GL_STREAM_DRAW_ARB));
980         checkGLcall("glBufferDataARB");
981
982         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
983         checkGLcall("glBindBufferARB");
984
985         /* We don't need the system memory anymore and we can't even use it for PBOs */
986         if(!(This->Flags & SFLAG_CLIENT)) {
987             HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
988             This->resource.heapMemory = NULL;
989         }
990         This->resource.allocatedMemory = NULL;
991         This->Flags |= SFLAG_PBO;
992         LEAVE_GL();
993     } else if(!(This->resource.allocatedMemory || This->Flags & SFLAG_PBO)) {
994         /* Whatever surface we have, make sure that there is memory allocated for the downloaded copy,
995          * or a pbo to map
996          */
997         if(!This->resource.heapMemory) {
998             This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT);
999         }
1000         This->resource.allocatedMemory =
1001                 (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
1002         if(This->Flags & SFLAG_INSYSMEM) {
1003             ERR("Surface without memory or pbo has SFLAG_INSYSMEM set!\n");
1004         }
1005     }
1006 }
1007
1008 static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
1009     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1010     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
1011     IWineD3DSwapChain *swapchain = NULL;
1012
1013     TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
1014
1015     /* This is also done in the base class, but we have to verify this before loading any data from
1016      * gl into the sysmem copy. The PBO may be mapped, a different rectangle locked, the discard flag
1017      * may interfere, and all other bad things may happen
1018      */
1019     if (This->Flags & SFLAG_LOCKED) {
1020         WARN("Surface is already locked, returning D3DERR_INVALIDCALL\n");
1021         return WINED3DERR_INVALIDCALL;
1022     }
1023     This->Flags |= SFLAG_LOCKED;
1024
1025     if (!(This->Flags & SFLAG_LOCKABLE))
1026     {
1027         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
1028     }
1029
1030     if (Flags & WINED3DLOCK_DISCARD) {
1031         /* Set SFLAG_INSYSMEM, so we'll never try to download the data from the texture. */
1032         TRACE("WINED3DLOCK_DISCARD flag passed, marking local copy as up to date\n");
1033         surface_prepare_system_memory(This); /* Makes sure memory is allocated */
1034         This->Flags |= SFLAG_INSYSMEM;
1035         goto lock_end;
1036     }
1037
1038     if (This->Flags & SFLAG_INSYSMEM) {
1039         TRACE("Local copy is up to date, not downloading data\n");
1040         surface_prepare_system_memory(This); /* Makes sure memory is allocated */
1041         goto lock_end;
1042     }
1043
1044     /* Now download the surface content from opengl
1045      * Use the render target readback if the surface is on a swapchain(=onscreen render target) or the current primary target
1046      * Offscreen targets which are not active at the moment or are higher targets(FBOs) can be locked with the texture path
1047      */
1048     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1049     if(swapchain || iface == myDevice->render_targets[0]) {
1050         const RECT *pass_rect = pRect;
1051
1052         /* IWineD3DSurface_LoadLocation does not check if the rectangle specifies the full surfaces
1053          * because most caller functions do not need that. So do that here
1054          */
1055         if(pRect &&
1056            pRect->top    == 0 &&
1057            pRect->left   == 0 &&
1058            pRect->right  == This->currentDesc.Width &&
1059            pRect->bottom == This->currentDesc.Height) {
1060             pass_rect = NULL;
1061         }
1062
1063         switch(wined3d_settings.rendertargetlock_mode) {
1064             case RTL_TEXDRAW:
1065             case RTL_TEXTEX:
1066                 FIXME("Reading from render target with a texture isn't implemented yet, falling back to framebuffer reading\n");
1067 #if 0
1068                 /* Disabled for now. LoadLocation prefers the texture over the drawable as the source. So if we copy to the
1069                  * texture first, then to sysmem, we'll avoid glReadPixels and use glCopyTexImage and glGetTexImage2D instead.
1070                  * This may be faster on some cards
1071                  */
1072                 IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* No partial texture copy yet */);
1073 #endif
1074                 /* drop through */
1075
1076             case RTL_AUTO:
1077             case RTL_READDRAW:
1078             case RTL_READTEX:
1079                 IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pRect);
1080                 break;
1081
1082             case RTL_DISABLE:
1083                 break;
1084         }
1085         if(swapchain) IWineD3DSwapChain_Release(swapchain);
1086
1087     } else if(iface == myDevice->stencilBufferTarget) {
1088         /** the depth stencil in openGL has a format of GL_FLOAT
1089          * which should be good for WINED3DFMT_D16_LOCKABLE
1090          * and WINED3DFMT_D16
1091          * it is unclear what format the stencil buffer is in except.
1092          * 'Each index is converted to fixed point...
1093          * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
1094          * mappings in the table GL_PIXEL_MAP_S_TO_S.
1095          * glReadPixels(This->lockedRect.left,
1096          *             This->lockedRect.bottom - j - 1,
1097          *             This->lockedRect.right - This->lockedRect.left,
1098          *             1,
1099          *             GL_DEPTH_COMPONENT,
1100          *             type,
1101          *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
1102          *
1103          * Depth Stencil surfaces which are not the current depth stencil target should have their data in a
1104          * gl texture(next path), or in local memory(early return because of set SFLAG_INSYSMEM above). If
1105          * none of that is the case the problem is not in this function :-)
1106          ********************************************/
1107         FIXME("Depth stencil locking not supported yet\n");
1108     } else {
1109         /* This path is for normal surfaces, offscreen render targets and everything else that is in a gl texture */
1110         TRACE("locking an ordinary surface\n");
1111         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */);
1112     }
1113
1114 lock_end:
1115     if(This->Flags & SFLAG_PBO) {
1116         ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
1117         ENTER_GL();
1118         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
1119         checkGLcall("glBindBufferARB");
1120
1121         /* This shouldn't happen but could occur if some other function didn't handle the PBO properly */
1122         if(This->resource.allocatedMemory) {
1123             ERR("The surface already has PBO memory allocated!\n");
1124         }
1125
1126         This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB));
1127         checkGLcall("glMapBufferARB");
1128
1129         /* Make sure the pbo isn't set anymore in order not to break non-pbo calls */
1130         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
1131         checkGLcall("glBindBufferARB");
1132
1133         LEAVE_GL();
1134     }
1135
1136     if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
1137         /* Don't dirtify */
1138     } else {
1139         IWineD3DBaseTexture *pBaseTexture;
1140         /**
1141          * Dirtify on lock
1142          * as seen in msdn docs
1143          */
1144         IWineD3DSurface_AddDirtyRect(iface, pRect);
1145
1146         /** Dirtify Container if needed */
1147         if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
1148             TRACE("Making container dirty\n");
1149             IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
1150             IWineD3DBaseTexture_Release(pBaseTexture);
1151         } else {
1152             TRACE("Surface is standalone, no need to dirty the container\n");
1153         }
1154     }
1155
1156     return IWineD3DBaseSurfaceImpl_LockRect(iface, pLockedRect, pRect, Flags);
1157 }
1158
1159 static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fmt, GLenum type, UINT bpp, const BYTE *mem) {
1160     GLint  prev_store;
1161     GLint  prev_rasterpos[4];
1162     GLint skipBytes = 0;
1163     UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);    /* target is argb, 4 byte */
1164     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
1165     IWineD3DSwapChainImpl *swapchain;
1166
1167     /* Activate the correct context for the render target */
1168     ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
1169     ENTER_GL();
1170
1171     IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
1172     if(!swapchain) {
1173         /* Primary offscreen render target */
1174         TRACE("Offscreen render target\n");
1175         glDrawBuffer(myDevice->offscreenBuffer);
1176         checkGLcall("glDrawBuffer(myDevice->offscreenBuffer)");
1177     } else {
1178         GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain);
1179         TRACE("Unlocking %#x buffer\n", buffer);
1180         glDrawBuffer(buffer);
1181         checkGLcall("glDrawBuffer");
1182
1183         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
1184     }
1185
1186     glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1187     vcheckGLcall("glIntegerv");
1188     glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
1189     vcheckGLcall("glIntegerv");
1190     glPixelZoom(1.0, -1.0);
1191     vcheckGLcall("glPixelZoom");
1192
1193     /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
1194     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
1195     glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
1196
1197     glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
1198     vcheckGLcall("glRasterPos2f");
1199
1200     /* Some drivers(radeon dri, others?) don't like exceptions during
1201      * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
1202      * after ReleaseDC. Reading it will cause an exception, which x11drv will
1203      * catch to put the dib section in InSync mode, which leads to a crash
1204      * and a blocked x server on my radeon card.
1205      *
1206      * The following lines read the dib section so it is put in InSync mode
1207      * before glDrawPixels is called and the crash is prevented. There won't
1208      * be any interfering gdi accesses, because UnlockRect is called from
1209      * ReleaseDC, and the app won't use the dc any more afterwards.
1210      */
1211     if((This->Flags & SFLAG_DIBSECTION) && !(This->Flags & SFLAG_PBO)) {
1212         volatile BYTE read;
1213         read = This->resource.allocatedMemory[0];
1214     }
1215
1216     if(This->Flags & SFLAG_PBO) {
1217         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
1218         checkGLcall("glBindBufferARB");
1219     }
1220
1221     /* When the surface is locked we only have to refresh the locked part else we need to update the whole image */
1222     if(This->Flags & SFLAG_LOCKED) {
1223         glDrawPixels(This->lockedRect.right - This->lockedRect.left,
1224                      (This->lockedRect.bottom - This->lockedRect.top)-1,
1225                      fmt, type,
1226                      mem + bpp * This->lockedRect.left + pitch * This->lockedRect.top);
1227         checkGLcall("glDrawPixels");
1228     } else {
1229         glDrawPixels(This->currentDesc.Width,
1230                      This->currentDesc.Height,
1231                      fmt, type, mem);
1232         checkGLcall("glDrawPixels");
1233     }
1234
1235     if(This->Flags & SFLAG_PBO) {
1236         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
1237         checkGLcall("glBindBufferARB");
1238     }
1239
1240     glPixelZoom(1.0,1.0);
1241     vcheckGLcall("glPixelZoom");
1242
1243     glRasterPos3iv(&prev_rasterpos[0]);
1244     vcheckGLcall("glRasterPos3iv");
1245
1246     /* Reset to previous pack row length */
1247     glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
1248     vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
1249
1250     if(!swapchain) {
1251         glDrawBuffer(myDevice->offscreenBuffer);
1252         checkGLcall("glDrawBuffer(myDevice->offscreenBuffer)");
1253     } else if(swapchain->backBuffer) {
1254         glDrawBuffer(GL_BACK);
1255         checkGLcall("glDrawBuffer(GL_BACK)");
1256     } else {
1257         glDrawBuffer(GL_FRONT);
1258         checkGLcall("glDrawBuffer(GL_FRONT)");
1259     }
1260     LEAVE_GL();
1261
1262     return;
1263 }
1264
1265 static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
1266     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1267     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
1268     IWineD3DSwapChainImpl *swapchain = NULL;
1269     BOOL fullsurface;
1270
1271     if (!(This->Flags & SFLAG_LOCKED)) {
1272         WARN("trying to Unlock an unlocked surf@%p\n", This);
1273         return WINED3DERR_INVALIDCALL;
1274     }
1275
1276     if (This->Flags & SFLAG_PBO) {
1277         TRACE("Freeing PBO memory\n");
1278         ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
1279         ENTER_GL();
1280         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
1281         GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
1282         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
1283         checkGLcall("glUnmapBufferARB");
1284         LEAVE_GL();
1285         This->resource.allocatedMemory = NULL;
1286     }
1287
1288     TRACE("(%p) : dirtyfied(%d)\n", This, This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);
1289
1290     if (This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE)) {
1291         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
1292         goto unlock_end;
1293     }
1294
1295     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1296     if(swapchain || (myDevice->render_targets && iface == myDevice->render_targets[0])) {
1297         if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1298
1299         if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
1300             static BOOL warned = FALSE;
1301             if(!warned) {
1302                 ERR("The application tries to write to the render target, but render target locking is disabled\n");
1303                 warned = TRUE;
1304             }
1305             goto unlock_end;
1306         }
1307
1308         if(This->dirtyRect.left   == 0 &&
1309            This->dirtyRect.top    == 0 &&
1310            This->dirtyRect.right  == This->currentDesc.Width &&
1311            This->dirtyRect.bottom == This->currentDesc.Height) {
1312             fullsurface = TRUE;
1313         } else {
1314             /* TODO: Proper partial rectangle tracking */
1315             fullsurface = FALSE;
1316             This->Flags |= SFLAG_INSYSMEM;
1317         }
1318
1319         switch(wined3d_settings.rendertargetlock_mode) {
1320             case RTL_READTEX:
1321             case RTL_TEXTEX:
1322                 ActivateContext(myDevice, iface, CTXUSAGE_BLIT);
1323                 IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* partial texture loading not supported yet */);
1324                 /* drop through */
1325
1326             case RTL_AUTO:
1327             case RTL_READDRAW:
1328             case RTL_TEXDRAW:
1329                 IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, fullsurface ? NULL : &This->dirtyRect);
1330                 break;
1331         }
1332
1333         if(!fullsurface) {
1334             /* Partial rectangle tracking is not commonly implemented, it is only done for render targets. Overwrite
1335              * the flags to bring them back into a sane state. INSYSMEM was set before to tell LoadLocation where
1336              * to read the rectangle from. Indrawable is set because all modifications from the partial sysmem copy
1337              * are written back to the drawable, thus the surface is merged again in the drawable. The sysmem copy is
1338              * not fully up to date because only a subrectangle was read in LockRect.
1339              */
1340             This->Flags &= ~SFLAG_INSYSMEM;
1341             This->Flags |= SFLAG_INDRAWABLE;
1342         }
1343
1344         This->dirtyRect.left   = This->currentDesc.Width;
1345         This->dirtyRect.top    = This->currentDesc.Height;
1346         This->dirtyRect.right  = 0;
1347         This->dirtyRect.bottom = 0;
1348     } else if(iface == myDevice->stencilBufferTarget) {
1349         FIXME("Depth Stencil buffer locking is not implemented\n");
1350     } else {
1351         /* The rest should be a normal texture */
1352         IWineD3DBaseTextureImpl *impl;
1353         /* Check if the texture is bound, if yes dirtify the sampler to force a re-upload of the texture
1354          * Can't load the texture here because PreLoad may destroy and recreate the gl texture, so sampler
1355          * states need resetting
1356          */
1357         if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) {
1358             if(impl->baseTexture.bindCount) {
1359                 IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler));
1360             }
1361             IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl);
1362         }
1363     }
1364
1365     unlock_end:
1366     This->Flags &= ~SFLAG_LOCKED;
1367     memset(&This->lockedRect, 0, sizeof(RECT));
1368
1369     /* Overlays have to be redrawn manually after changes with the GL implementation */
1370     if(This->overlay_dest) {
1371         IWineD3DSurface_DrawOverlay(iface);
1372     }
1373     return WINED3D_OK;
1374 }
1375
1376 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
1377     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1378     WINED3DLOCKED_RECT lock;
1379     HRESULT hr;
1380     RGBQUAD col[256];
1381
1382     TRACE("(%p)->(%p)\n",This,pHDC);
1383
1384     if(This->Flags & SFLAG_USERPTR) {
1385         ERR("Not supported on surfaces with an application-provided surfaces\n");
1386         return WINEDDERR_NODC;
1387     }
1388
1389     /* Give more detailed info for ddraw */
1390     if (This->Flags & SFLAG_DCINUSE)
1391         return WINEDDERR_DCALREADYCREATED;
1392
1393     /* Can't GetDC if the surface is locked */
1394     if (This->Flags & SFLAG_LOCKED)
1395         return WINED3DERR_INVALIDCALL;
1396
1397     /* According to Direct3D9 docs, only these formats are supported */
1398     if (((IWineD3DImpl *)This->resource.wineD3DDevice->wineD3D)->dxVersion > 7) {
1399         if (This->resource.format != WINED3DFMT_R5G6B5 &&
1400             This->resource.format != WINED3DFMT_X1R5G5B5 &&
1401             This->resource.format != WINED3DFMT_R8G8B8 &&
1402             This->resource.format != WINED3DFMT_X8R8G8B8) return WINED3DERR_INVALIDCALL;
1403     }
1404
1405     memset(&lock, 0, sizeof(lock)); /* To be sure */
1406
1407     /* Create a DIB section if there isn't a hdc yet */
1408     if(!This->hDC) {
1409         IWineD3DBaseSurfaceImpl_CreateDIBSection(iface);
1410         if(This->Flags & SFLAG_CLIENT) {
1411             IWineD3DSurface_PreLoad(iface);
1412         }
1413
1414         /* Use the dib section from now on if we are not using a PBO */
1415         if(!(This->Flags & SFLAG_PBO))
1416             This->resource.allocatedMemory = This->dib.bitmap_data;
1417     }
1418
1419     /* Lock the surface */
1420     hr = IWineD3DSurface_LockRect(iface,
1421                                   &lock,
1422                                   NULL,
1423                                   0);
1424
1425     if(This->Flags & SFLAG_PBO) {
1426         /* Sync the DIB with the PBO. This can't be done earlier because LockRect activates the allocatedMemory */
1427         memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->dib.bitmap_size);
1428     }
1429
1430     if(FAILED(hr)) {
1431         ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
1432         /* keep the dib section */
1433         return hr;
1434     }
1435
1436     if(This->resource.format == WINED3DFMT_P8 ||
1437         This->resource.format == WINED3DFMT_A8P8) {
1438         /* GetDC on palettized formats is unsupported in D3D9, and the method is missing in
1439             D3D8, so this should only be used for DX <=7 surfaces (with non-device palettes) */
1440         unsigned int n;
1441         PALETTEENTRY *pal = NULL;
1442
1443         if(This->palette) {
1444             pal = This->palette->palents;
1445         } else {
1446             IWineD3DSurfaceImpl *dds_primary;
1447             IWineD3DSwapChainImpl *swapchain;
1448             swapchain = (IWineD3DSwapChainImpl *)This->resource.wineD3DDevice->swapchains[0];
1449             dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer;
1450             if (dds_primary && dds_primary->palette)
1451                 pal = dds_primary->palette->palents;
1452         }
1453
1454         if (pal) {
1455             for (n=0; n<256; n++) {
1456                 col[n].rgbRed   = pal[n].peRed;
1457                 col[n].rgbGreen = pal[n].peGreen;
1458                 col[n].rgbBlue  = pal[n].peBlue;
1459                 col[n].rgbReserved = 0;
1460             }
1461             SetDIBColorTable(This->hDC, 0, 256, col);
1462         }
1463     }
1464
1465     *pHDC = This->hDC;
1466     TRACE("returning %p\n",*pHDC);
1467     This->Flags |= SFLAG_DCINUSE;
1468
1469     return WINED3D_OK;
1470 }
1471
1472 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1473     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1474
1475     TRACE("(%p)->(%p)\n",This,hDC);
1476
1477     if (!(This->Flags & SFLAG_DCINUSE))
1478         return WINED3DERR_INVALIDCALL;
1479
1480     if (This->hDC !=hDC) {
1481         WARN("Application tries to release an invalid DC(%p), surface dc is %p\n", hDC, This->hDC);
1482         return WINED3DERR_INVALIDCALL;
1483     }
1484
1485     if((This->Flags & SFLAG_PBO) && This->resource.allocatedMemory) {
1486         /* Copy the contents of the DIB over to the PBO */
1487         memcpy(This->resource.allocatedMemory, This->dib.bitmap_data, This->dib.bitmap_size);
1488     }
1489
1490     /* we locked first, so unlock now */
1491     IWineD3DSurface_UnlockRect(iface);
1492
1493     This->Flags &= ~SFLAG_DCINUSE;
1494
1495     return WINED3D_OK;
1496 }
1497
1498 /* ******************************************************
1499    IWineD3DSurface Internal (No mapping to directx api) parts follow
1500    ****************************************************** */
1501
1502 HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode) {
1503     BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & WINEDDSD_CKSRCBLT);
1504     const GlPixelFormatDesc *glDesc;
1505     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1506     getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc);
1507
1508     /* Default values: From the surface */
1509     *format = glDesc->glFormat;
1510     *type = glDesc->glType;
1511     *convert = NO_CONVERSION;
1512     *target_bpp = This->bytesPerPixel;
1513
1514     if(srgb_mode) {
1515         *internal = glDesc->glGammaInternal;
1516     } else if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
1517         *internal = glDesc->rtInternal;
1518     } else {
1519         *internal = glDesc->glInternal;
1520     }
1521
1522     /* Ok, now look if we have to do any conversion */
1523     switch(This->resource.format) {
1524         case WINED3DFMT_P8:
1525             /* ****************
1526                 Paletted Texture
1527                 **************** */
1528
1529              /* Use conversion when the paletted texture extension OR fragment shaders are available. When either
1530              * of the two is available make sure texturing is requested as neither of the two works in
1531              * conjunction with calls like glDraw-/glReadPixels. Further also use conversion in case of color keying.
1532              * Paletted textures can be emulated using shaders but only do that for 2D purposes e.g. situations
1533              * in which the main render target uses p8. Some games like GTA Vice City use P8 for texturing which
1534              * conflicts with this.
1535              */
1536             if( !(GL_SUPPORT(EXT_PALETTED_TEXTURE) ||
1537                   (GL_SUPPORT(ARB_FRAGMENT_PROGRAM) &&
1538                    device->render_targets &&
1539                    This == (IWineD3DSurfaceImpl*)device->render_targets[0])) ||
1540                 colorkey_active || !use_texturing ) {
1541                 *format = GL_RGBA;
1542                 *internal = GL_RGBA;
1543                 *type = GL_UNSIGNED_BYTE;
1544                 *target_bpp = 4;
1545                 if(colorkey_active) {
1546                     *convert = CONVERT_PALETTED_CK;
1547                 } else {
1548                     *convert = CONVERT_PALETTED;
1549                 }
1550             }
1551             else if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
1552                 *format = GL_ALPHA;
1553                 *internal = GL_RGBA;
1554                 *type = GL_UNSIGNED_BYTE;
1555                 *target_bpp = 1;
1556             }
1557
1558             break;
1559
1560         case WINED3DFMT_R3G3B2:
1561             /* **********************
1562                 GL_UNSIGNED_BYTE_3_3_2
1563                 ********************** */
1564             if (colorkey_active) {
1565                 /* This texture format will never be used.. So do not care about color keying
1566                     up until the point in time it will be needed :-) */
1567                 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1568             }
1569             break;
1570
1571         case WINED3DFMT_R5G6B5:
1572             if (colorkey_active) {
1573                 *convert = CONVERT_CK_565;
1574                 *format = GL_RGBA;
1575                 *internal = GL_RGBA;
1576                 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1577             }
1578             break;
1579
1580         case WINED3DFMT_X1R5G5B5:
1581             if (colorkey_active) {
1582                 *convert = CONVERT_CK_5551;
1583                 *format = GL_BGRA;
1584                 *internal = GL_RGBA;
1585                 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1586             }
1587             break;
1588
1589         case WINED3DFMT_R8G8B8:
1590             if (colorkey_active) {
1591                 *convert = CONVERT_CK_RGB24;
1592                 *format = GL_RGBA;
1593                 *internal = GL_RGBA;
1594                 *type = GL_UNSIGNED_INT_8_8_8_8;
1595                 *target_bpp = 4;
1596             }
1597             break;
1598
1599         case WINED3DFMT_X8R8G8B8:
1600             if (colorkey_active) {
1601                 *convert = CONVERT_RGB32_888;
1602                 *format = GL_RGBA;
1603                 *internal = GL_RGBA;
1604                 *type = GL_UNSIGNED_INT_8_8_8_8;
1605             }
1606             break;
1607
1608         case WINED3DFMT_V8U8:
1609             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
1610             else if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1611                 *format = GL_DUDV_ATI;
1612                 *internal = GL_DU8DV8_ATI;
1613                 *type = GL_BYTE;
1614                 /* No conversion - Just change the gl type */
1615                 break;
1616             }
1617             *convert = CONVERT_V8U8;
1618             *format = GL_BGR;
1619             *internal = GL_RGB8;
1620             *type = GL_UNSIGNED_BYTE;
1621             *target_bpp = 3;
1622             break;
1623
1624         case WINED3DFMT_L6V5U5:
1625             *convert = CONVERT_L6V5U5;
1626             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1627                 *target_bpp = 3;
1628                 /* Use format and types from table */
1629             } else {
1630                 /* Load it into unsigned R5G6B5, swap L and V channels, and revert that in the shader */
1631                 *target_bpp = 2;
1632                 *format = GL_RGB;
1633                 *internal = GL_RGB5;
1634                 *type = GL_UNSIGNED_SHORT_5_6_5;
1635             }
1636             break;
1637
1638         case WINED3DFMT_X8L8V8U8:
1639             *convert = CONVERT_X8L8V8U8;
1640             *target_bpp = 4;
1641             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1642                 /* Use formats from gl table. It is a bit unfortunate, but the conversion
1643                  * is needed to set the X format to 255 to get 1.0 for alpha when sampling
1644                  * the texture. OpenGL can't use GL_DSDT8_MAG8_NV as internal format with
1645                  * the needed type and format parameter, so the internal format contains a
1646                  * 4th component, which is returned as alpha
1647                  */
1648             } else {
1649                 /* Not supported by GL_ATI_envmap_bumpmap */
1650                 *format = GL_BGRA;
1651                 *internal = GL_RGB8;
1652                 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
1653             }
1654             break;
1655
1656         case WINED3DFMT_Q8W8V8U8:
1657             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
1658             *convert = CONVERT_Q8W8V8U8;
1659             *format = GL_BGRA;
1660             *internal = GL_RGBA8;
1661             *type = GL_UNSIGNED_BYTE;
1662             *target_bpp = 4;
1663             /* Not supported by GL_ATI_envmap_bumpmap */
1664             break;
1665
1666         case WINED3DFMT_V16U16:
1667             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
1668             *convert = CONVERT_V16U16;
1669             *format = GL_BGR;
1670             *internal = GL_RGB16_EXT;
1671             *type = GL_UNSIGNED_SHORT;
1672             *target_bpp = 6;
1673             /* What should I do here about GL_ATI_envmap_bumpmap?
1674              * Convert it or allow data loss by loading it into a 8 bit / channel texture?
1675              */
1676             break;
1677
1678         case WINED3DFMT_A4L4:
1679             /* A4L4 exists as an internal gl format, but for some reason there is not
1680              * format+type combination to load it. Thus convert it to A8L8, then load it
1681              * with A4L4 internal, but A8L8 format+type
1682              */
1683             *convert = CONVERT_A4L4;
1684             *format = GL_LUMINANCE_ALPHA;
1685             *internal = GL_LUMINANCE4_ALPHA4;
1686             *type = GL_UNSIGNED_BYTE;
1687             *target_bpp = 2;
1688             break;
1689
1690         case WINED3DFMT_R32F:
1691             /* Can be loaded in theory with fmt=GL_RED, type=GL_FLOAT, but this fails. The reason
1692              * is that D3D expects the undefined green, blue and alpha channels to return 1.0
1693              * when sampling, but OpenGL sets green and blue to 0.0 instead. Thus we have to inject
1694              * 1.0 instead.
1695              *
1696              * The alpha channel defaults to 1.0 in opengl, so nothing has to be done about it.
1697              */
1698             *convert = CONVERT_R32F;
1699             *format = GL_RGB;
1700             *internal = GL_RGB32F_ARB;
1701             *type = GL_FLOAT;
1702             *target_bpp = 12;
1703             break;
1704
1705         case WINED3DFMT_R16F:
1706             /* Similar to R32F */
1707             *convert = CONVERT_R16F;
1708             *format = GL_RGB;
1709             *internal = GL_RGB16F_ARB;
1710             *type = GL_HALF_FLOAT_ARB;
1711             *target_bpp = 6;
1712             break;
1713
1714         case WINED3DFMT_G16R16:
1715             *convert = CONVERT_G16R16;
1716             *format = GL_RGB;
1717             *internal = GL_RGB16_EXT;
1718             *type = GL_UNSIGNED_SHORT;
1719             *target_bpp = 6;
1720             break;
1721
1722         default:
1723             break;
1724     }
1725
1726     return WINED3D_OK;
1727 }
1728
1729 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *This) {
1730     BYTE *source, *dest;
1731     TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert,This);
1732
1733     switch (convert) {
1734         case NO_CONVERSION:
1735         {
1736             memcpy(dst, src, pitch * height);
1737             break;
1738         }
1739         case CONVERT_PALETTED:
1740         case CONVERT_PALETTED_CK:
1741         {
1742             IWineD3DPaletteImpl* pal = This->palette;
1743             BYTE table[256][4];
1744             unsigned int x, y;
1745
1746             if( pal == NULL) {
1747                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1748             }
1749
1750             d3dfmt_p8_init_palette(This, table, (convert == CONVERT_PALETTED_CK));
1751
1752             for (y = 0; y < height; y++)
1753             {
1754                 source = src + pitch * y;
1755                 dest = dst + outpitch * y;
1756                 /* This is an 1 bpp format, using the width here is fine */
1757                 for (x = 0; x < width; x++) {
1758                     BYTE color = *source++;
1759                     *dest++ = table[color][0];
1760                     *dest++ = table[color][1];
1761                     *dest++ = table[color][2];
1762                     *dest++ = table[color][3];
1763                 }
1764             }
1765         }
1766         break;
1767
1768         case CONVERT_CK_565:
1769         {
1770             /* Converting the 565 format in 5551 packed to emulate color-keying.
1771
1772               Note : in all these conversion, it would be best to average the averaging
1773                       pixels to get the color of the pixel that will be color-keyed to
1774                       prevent 'color bleeding'. This will be done later on if ever it is
1775                       too visible.
1776
1777               Note2: Nvidia documents say that their driver does not support alpha + color keying
1778                      on the same surface and disables color keying in such a case
1779             */
1780             unsigned int x, y;
1781             WORD *Source;
1782             WORD *Dest;
1783
1784             TRACE("Color keyed 565\n");
1785
1786             for (y = 0; y < height; y++) {
1787                 Source = (WORD *) (src + y * pitch);
1788                 Dest = (WORD *) (dst + y * outpitch);
1789                 for (x = 0; x < width; x++ ) {
1790                     WORD color = *Source++;
1791                     *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1792                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
1793                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
1794                         *Dest |= 0x0001;
1795                     }
1796                     Dest++;
1797                 }
1798             }
1799         }
1800         break;
1801
1802         case CONVERT_CK_5551:
1803         {
1804             /* Converting X1R5G5B5 format to R5G5B5A1 to emulate color-keying. */
1805             unsigned int x, y;
1806             WORD *Source;
1807             WORD *Dest;
1808             TRACE("Color keyed 5551\n");
1809             for (y = 0; y < height; y++) {
1810                 Source = (WORD *) (src + y * pitch);
1811                 Dest = (WORD *) (dst + y * outpitch);
1812                 for (x = 0; x < width; x++ ) {
1813                     WORD color = *Source++;
1814                     *Dest = color;
1815                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
1816                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
1817                         *Dest |= (1 << 15);
1818                     }
1819                     else {
1820                         *Dest &= ~(1 << 15);
1821                     }
1822                     Dest++;
1823                 }
1824             }
1825         }
1826         break;
1827
1828         case CONVERT_RGB32_888:
1829         {
1830             /* Converting X8R8G8B8 format to R8G8B8A8 with color-keying. */
1831             unsigned int x, y;
1832             for (y = 0; y < height; y++)
1833             {
1834                 source = src + pitch * y;
1835                 dest = dst + outpitch * y;
1836                 for (x = 0; x < width; x++) {
1837                     DWORD color = 0xffffff & *(DWORD*)source;
1838                     DWORD dstcolor = color << 8;
1839                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
1840                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
1841                         dstcolor |= 0xff;
1842                     }
1843                     *(DWORD*)dest = dstcolor;
1844                     source += 4;
1845                     dest += 4;
1846                 }
1847             }
1848         }
1849         break;
1850
1851         case CONVERT_V8U8:
1852         {
1853             unsigned int x, y;
1854             short *Source;
1855             unsigned char *Dest;
1856             for(y = 0; y < height; y++) {
1857                 Source = (short *) (src + y * pitch);
1858                 Dest = dst + y * outpitch;
1859                 for (x = 0; x < width; x++ ) {
1860                     long color = (*Source++);
1861                     /* B */ Dest[0] = 0xff;
1862                     /* G */ Dest[1] = (color >> 8) + 128; /* V */
1863                     /* R */ Dest[2] = (color) + 128;      /* U */
1864                     Dest += 3;
1865                 }
1866             }
1867             break;
1868         }
1869
1870         case CONVERT_V16U16:
1871         {
1872             unsigned int x, y;
1873             DWORD *Source;
1874             unsigned short *Dest;
1875             for(y = 0; y < height; y++) {
1876                 Source = (DWORD *) (src + y * pitch);
1877                 Dest = (unsigned short *) (dst + y * outpitch);
1878                 for (x = 0; x < width; x++ ) {
1879                     DWORD color = (*Source++);
1880                     /* B */ Dest[0] = 0xffff;
1881                     /* G */ Dest[1] = (color >> 16) + 32768; /* V */
1882                     /* R */ Dest[2] = (color      ) + 32768; /* U */
1883                     Dest += 3;
1884                 }
1885             }
1886             break;
1887         }
1888
1889         case CONVERT_Q8W8V8U8:
1890         {
1891             unsigned int x, y;
1892             DWORD *Source;
1893             unsigned char *Dest;
1894             for(y = 0; y < height; y++) {
1895                 Source = (DWORD *) (src + y * pitch);
1896                 Dest = dst + y * outpitch;
1897                 for (x = 0; x < width; x++ ) {
1898                     long color = (*Source++);
1899                     /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
1900                     /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
1901                     /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
1902                     /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
1903                     Dest += 4;
1904                 }
1905             }
1906             break;
1907         }
1908
1909         case CONVERT_L6V5U5:
1910         {
1911             unsigned int x, y;
1912             WORD *Source;
1913             unsigned char *Dest;
1914
1915             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1916                 /* This makes the gl surface bigger(24 bit instead of 16), but it works with
1917                  * fixed function and shaders without further conversion once the surface is
1918                  * loaded
1919                  */
1920                 for(y = 0; y < height; y++) {
1921                     Source = (WORD *) (src + y * pitch);
1922                     Dest = dst + y * outpitch;
1923                     for (x = 0; x < width; x++ ) {
1924                         short color = (*Source++);
1925                         unsigned char l = ((color >> 10) & 0xfc);
1926                                   char v = ((color >>  5) & 0x3e);
1927                                   char u = ((color      ) & 0x1f);
1928
1929                         /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign
1930                          * and doubles the positive range. Thus shift left only once, gl does the 2nd
1931                          * shift. GL reads a signed value and converts it into an unsigned value.
1932                          */
1933                         /* M */ Dest[2] = l << 1;
1934
1935                         /* Those are read as signed, but kept signed. Just left-shift 3 times to scale
1936                          * from 5 bit values to 8 bit values.
1937                          */
1938                         /* V */ Dest[1] = v << 3;
1939                         /* U */ Dest[0] = u << 3;
1940                         Dest += 3;
1941                     }
1942                 }
1943             } else {
1944                 for(y = 0; y < height; y++) {
1945                     unsigned short *Dest_s = (unsigned short *) (dst + y * outpitch);
1946                     Source = (WORD *) (src + y * pitch);
1947                     for (x = 0; x < width; x++ ) {
1948                         short color = (*Source++);
1949                         unsigned char l = ((color >> 10) & 0xfc);
1950                                  short v = ((color >>  5) & 0x3e);
1951                                  short u = ((color      ) & 0x1f);
1952                         short v_conv = v + 16;
1953                         short u_conv = u + 16;
1954
1955                         *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f);
1956                         Dest_s += 1;
1957                     }
1958                 }
1959             }
1960             break;
1961         }
1962
1963         case CONVERT_X8L8V8U8:
1964         {
1965             unsigned int x, y;
1966             DWORD *Source;
1967             unsigned char *Dest;
1968
1969             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1970                 /* This implementation works with the fixed function pipeline and shaders
1971                  * without further modification after converting the surface.
1972                  */
1973                 for(y = 0; y < height; y++) {
1974                     Source = (DWORD *) (src + y * pitch);
1975                     Dest = dst + y * outpitch;
1976                     for (x = 0; x < width; x++ ) {
1977                         long color = (*Source++);
1978                         /* L */ Dest[2] = ((color >> 16) & 0xff);   /* L */
1979                         /* V */ Dest[1] = ((color >> 8 ) & 0xff);   /* V */
1980                         /* U */ Dest[0] = (color         & 0xff);   /* U */
1981                         /* I */ Dest[3] = 255;                      /* X */
1982                         Dest += 4;
1983                     }
1984                 }
1985             } else {
1986                 /* Doesn't work correctly with the fixed function pipeline, but can work in
1987                  * shaders if the shader is adjusted. (There's no use for this format in gl's
1988                  * standard fixed function pipeline anyway).
1989                  */
1990                 for(y = 0; y < height; y++) {
1991                     Source = (DWORD *) (src + y * pitch);
1992                     Dest = dst + y * outpitch;
1993                     for (x = 0; x < width; x++ ) {
1994                         long color = (*Source++);
1995                         /* B */ Dest[0] = ((color >> 16) & 0xff);       /* L */
1996                         /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
1997                         /* R */ Dest[2] = (color         & 0xff) + 128;  /* U */
1998                         Dest += 4;
1999                     }
2000                 }
2001             }
2002             break;
2003         }
2004
2005         case CONVERT_A4L4:
2006         {
2007             unsigned int x, y;
2008             unsigned char *Source;
2009             unsigned char *Dest;
2010             for(y = 0; y < height; y++) {
2011                 Source = src + y * pitch;
2012                 Dest = dst + y * outpitch;
2013                 for (x = 0; x < width; x++ ) {
2014                     unsigned char color = (*Source++);
2015                     /* A */ Dest[1] = (color & 0xf0) << 0;
2016                     /* L */ Dest[0] = (color & 0x0f) << 4;
2017                     Dest += 2;
2018                 }
2019             }
2020             break;
2021         }
2022
2023         case CONVERT_R32F:
2024         {
2025             unsigned int x, y;
2026             float *Source;
2027             float *Dest;
2028             for(y = 0; y < height; y++) {
2029                 Source = (float *) (src + y * pitch);
2030                 Dest = (float *) (dst + y * outpitch);
2031                 for (x = 0; x < width; x++ ) {
2032                     float color = (*Source++);
2033                     Dest[0] = color;
2034                     Dest[1] = 1.0;
2035                     Dest[2] = 1.0;
2036                     Dest += 3;
2037                 }
2038             }
2039             break;
2040         }
2041
2042         case CONVERT_R16F:
2043         {
2044             unsigned int x, y;
2045             WORD *Source;
2046             WORD *Dest;
2047             WORD one = 0x3c00;
2048             for(y = 0; y < height; y++) {
2049                 Source = (WORD *) (src + y * pitch);
2050                 Dest = (WORD *) (dst + y * outpitch);
2051                 for (x = 0; x < width; x++ ) {
2052                     WORD color = (*Source++);
2053                     Dest[0] = color;
2054                     Dest[1] = one;
2055                     Dest[2] = one;
2056                     Dest += 3;
2057                 }
2058             }
2059             break;
2060         }
2061
2062         case CONVERT_G16R16:
2063         {
2064             unsigned int x, y;
2065             WORD *Source;
2066             WORD *Dest;
2067
2068             for(y = 0; y < height; y++) {
2069                 Source = (WORD *) (src + y * pitch);
2070                 Dest = (WORD *) (dst + y * outpitch);
2071                 for (x = 0; x < width; x++ ) {
2072                     WORD green = (*Source++);
2073                     WORD red = (*Source++);
2074                     Dest[0] = green;
2075                     Dest[1] = red;
2076                     Dest[2] = 0xffff;
2077                     Dest += 3;
2078                 }
2079             }
2080             break;
2081         }
2082
2083         default:
2084             ERR("Unsupported conversation type %d\n", convert);
2085     }
2086     return WINED3D_OK;
2087 }
2088
2089 static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey) {
2090     IWineD3DPaletteImpl* pal = This->palette;
2091     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2092     BOOL index_in_alpha = FALSE;
2093     int dxVersion = ( (IWineD3DImpl *) device->wineD3D)->dxVersion;
2094     int i;
2095
2096     /* Old games like StarCraft, C&C, Red Alert and others use P8 render targets.
2097     * Reading back the RGB output each lockrect (each frame as they lock the whole screen)
2098     * is slow. Further RGB->P8 conversion is not possible because palettes can have
2099     * duplicate entries. Store the color key in the unused alpha component to speed the
2100     * download up and to make conversion unneeded. */
2101     index_in_alpha = primary_render_target_is_p8(device);
2102
2103     if (pal == NULL) {
2104         /* In DirectDraw the palette is a property of the surface, there are no such things as device palettes. */
2105         if(dxVersion <= 7) {
2106             ERR("This code should never get entered for DirectDraw!, expect problems\n");
2107             if(index_in_alpha) {
2108                 /* Guarantees that memory representation remains correct after sysmem<->texture transfers even if
2109                    there's no palette at this time. */
2110                 for (i = 0; i < 256; i++) table[i][3] = i;
2111             }
2112         } else {
2113             /*  Direct3D >= 8 palette usage style: P8 textures use device palettes, palette entry format is A8R8G8B8,
2114                 alpha is stored in peFlags and may be used by the app if D3DPTEXTURECAPS_ALPHAPALETTE device
2115                 capability flag is present (wine does advertise this capability) */
2116             for (i = 0; i < 256; i++) {
2117                 table[i][0] = device->palettes[device->currentPalette][i].peRed;
2118                 table[i][1] = device->palettes[device->currentPalette][i].peGreen;
2119                 table[i][2] = device->palettes[device->currentPalette][i].peBlue;
2120                 table[i][3] = device->palettes[device->currentPalette][i].peFlags;
2121             }
2122         }
2123     } else {
2124         TRACE("Using surface palette %p\n", pal);
2125         /* Get the surface's palette */
2126         for (i = 0; i < 256; i++) {
2127             table[i][0] = pal->palents[i].peRed;
2128             table[i][1] = pal->palents[i].peGreen;
2129             table[i][2] = pal->palents[i].peBlue;
2130
2131             /* When index_in_alpha is the palette index is stored in the alpha component. In case of a readback
2132                we can then read GL_ALPHA. Color keying is handled in BltOverride using a GL_ALPHA_TEST using GL_NOT_EQUAL.
2133                In case of index_in_alpha the color key itself is passed to glAlphaFunc in other cases the alpha component
2134                of pixels that should be masked away is set to 0. */
2135             if(index_in_alpha) {
2136                 table[i][3] = i;
2137             } else if(colorkey && (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&  (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
2138                 table[i][3] = 0x00;
2139             } else if(pal->Flags & WINEDDPCAPS_ALPHA) {
2140                 table[i][3] = pal->palents[i].peFlags;
2141             } else {
2142                 table[i][3] = 0xFF;
2143             }
2144         }
2145     }
2146 }
2147
2148 const char *fragment_palette_conversion =
2149     "!!ARBfp1.0\n"
2150     "TEMP index;\n"
2151     "PARAM constants = { 0.996, 0.00195, 0, 0 };\n" /* { 255/256, 0.5/255*255/256, 0, 0 } */
2152     "TEX index, fragment.texcoord[0], texture[0], 2D;\n" /* The alpha-component contains the palette index */
2153     "MAD index.a, index.a, constants.x, constants.y;\n" /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */
2154     "TEX result.color, index.a, texture[1], 1D;\n" /* use the alpha-component as a index in the palette to get the final color */
2155     "END";
2156
2157 /* This function is used in case of 8bit paletted textures to upload the palette.
2158    It supports GL_EXT_paletted_texture and GL_ARB_fragment_program, support for other
2159    extensions like ATI_fragment_shaders is possible.
2160 */
2161 static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
2162     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2163     BYTE table[256][4];
2164     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2165
2166     d3dfmt_p8_init_palette(This, table, (convert == CONVERT_PALETTED_CK));
2167
2168     /* Try to use the paletted texture extension */
2169     if(GL_SUPPORT(EXT_PALETTED_TEXTURE))
2170     {
2171         TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n");
2172         GL_EXTCALL(glColorTableEXT(This->glDescription.target,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table));
2173     }
2174     else
2175     {
2176         /* Let a fragment shader do the color conversion by uploading the palette to a 1D texture.
2177          * The 8bit pixel data will be used as an index in this palette texture to retrieve the final color. */
2178         TRACE("Using fragment shaders for emulating 8-bit paletted texture support\n");
2179
2180         /* Create the fragment program if we don't have it */
2181         if(!device->paletteConversionShader)
2182         {
2183             glEnable(GL_FRAGMENT_PROGRAM_ARB);
2184             GL_EXTCALL(glGenProgramsARB(1, &device->paletteConversionShader));
2185             GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader));
2186             GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragment_palette_conversion), (const GLbyte *)fragment_palette_conversion));
2187             glDisable(GL_FRAGMENT_PROGRAM_ARB);
2188         }
2189
2190         glEnable(GL_FRAGMENT_PROGRAM_ARB);
2191         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader));
2192
2193         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1));
2194         glEnable(GL_TEXTURE_1D);
2195         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2196
2197         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2198         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Make sure we have discrete color levels. */
2199         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2200         glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table); /* Upload the palette */
2201
2202         /* Switch back to unit 0 in which the 2D texture will be stored. */
2203         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0));
2204
2205         /* Rebind the texture because it isn't bound anymore */
2206         glBindTexture(This->glDescription.target, This->glDescription.textureName);
2207     }
2208 }
2209
2210 BOOL palette9_changed(IWineD3DSurfaceImpl *This) {
2211     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2212
2213     if(This->palette || (This->resource.format != WINED3DFMT_P8 && This->resource.format != WINED3DFMT_A8P8)) {
2214         /* If a ddraw-style palette is attached assume no d3d9 palette change.
2215          * Also the palette isn't interesting if the surface format isn't P8 or A8P8
2216          */
2217         return FALSE;
2218     }
2219
2220     if(This->palette9) {
2221         if(memcmp(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256) == 0) {
2222             return FALSE;
2223         }
2224     } else {
2225         This->palette9 = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256);
2226     }
2227     memcpy(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256);
2228     return TRUE;
2229 }
2230
2231 static inline void clear_unused_channels(IWineD3DSurfaceImpl *This) {
2232     GLboolean oldwrite[4];
2233
2234     /* Some formats have only some color channels, and the others are 1.0.
2235      * since our rendering renders to all channels, and those pixel formats
2236      * are emulated by using a full texture with the other channels set to 1.0
2237      * manually, clear the unused channels.
2238      *
2239      * This could be done with hacking colorwriteenable to mask the colors,
2240      * but before drawing the buffer would have to be cleared too, so there's
2241      * no gain in that
2242      */
2243     switch(This->resource.format) {
2244         case WINED3DFMT_R16F:
2245         case WINED3DFMT_R32F:
2246             TRACE("R16F or R32F format, clearing green, blue and alpha to 1.0\n");
2247             /* Do not activate a context, the correct drawable is active already
2248              * though just the read buffer is set, make sure to have the correct draw
2249              * buffer too
2250              */
2251             glDrawBuffer(This->resource.wineD3DDevice->offscreenBuffer);
2252             glDisable(GL_SCISSOR_TEST);
2253             glGetBooleanv(GL_COLOR_WRITEMASK, oldwrite);
2254             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
2255             glClearColor(0.0, 1.0, 1.0, 1.0);
2256             glClear(GL_COLOR_BUFFER_BIT);
2257             glColorMask(oldwrite[0], oldwrite[1], oldwrite[2], oldwrite[3]);
2258             if(!This->resource.wineD3DDevice->render_offscreen) glDrawBuffer(GL_BACK);
2259             checkGLcall("Unused channel clear\n");
2260             break;
2261
2262         default: break;
2263     }
2264 }
2265
2266 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, BOOL srgb_mode) {
2267     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2268
2269     if (!(This->Flags & SFLAG_INTEXTURE)) {
2270         TRACE("Reloading because surface is dirty\n");
2271     } else if(/* Reload: gl texture has ck, now no ckey is set OR */
2272               ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & WINEDDSD_CKSRCBLT))) ||
2273               /* Reload: vice versa  OR */
2274               ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & WINEDDSD_CKSRCBLT)) ||
2275               /* Also reload: Color key is active AND the color key has changed */
2276               ((This->CKeyFlags & WINEDDSD_CKSRCBLT) && (
2277                 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
2278                 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
2279         TRACE("Reloading because of color keying\n");
2280         /* To perform the color key conversion we need a sysmem copy of
2281          * the surface. Make sure we have it
2282          */
2283
2284         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
2285         /* Make sure the texture is reloaded because of the color key change, this kills performance though :( */
2286         /* TODO: This is not necessarily needed with hw palettized texture support */
2287         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2288     } else {
2289         TRACE("surface is already in texture\n");
2290         return WINED3D_OK;
2291     }
2292
2293     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
2294      *  These resources are not bound by device size or format restrictions. Because of this,
2295      *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
2296      *  However, these resources can always be created, locked, and copied.
2297      */
2298     if (This->resource.pool == WINED3DPOOL_SCRATCH )
2299     {
2300         FIXME("(%p) Operation not supported for scratch textures\n",This);
2301         return WINED3DERR_INVALIDCALL;
2302     }
2303
2304     This->srgb = srgb_mode;
2305     IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* no partial locking for textures yet */);
2306
2307 #if 0
2308     {
2309         static unsigned int gen = 0;
2310         char buffer[4096];
2311         ++gen;
2312         if ((gen % 10) == 0) {
2313             snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
2314             IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
2315         }
2316         /*
2317          * debugging crash code
2318          if (gen == 250) {
2319          void** test = NULL;
2320          *test = 0;
2321          }
2322          */
2323     }
2324 #endif
2325
2326     if (!(This->Flags & SFLAG_DONOTFREE)) {
2327         HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
2328         This->resource.allocatedMemory = NULL;
2329         This->resource.heapMemory = NULL;
2330         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, FALSE);
2331     }
2332
2333     return WINED3D_OK;
2334 }
2335
2336 static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface) {
2337     /* TODO: check for locks */
2338     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2339     IWineD3DBaseTexture *baseTexture = NULL;
2340     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2341
2342     TRACE("(%p)Checking to see if the container is a base texture\n", This);
2343     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2344         TRACE("Passing to container\n");
2345         IWineD3DBaseTexture_BindTexture(baseTexture);
2346         IWineD3DBaseTexture_Release(baseTexture);
2347     } else {
2348         TRACE("(%p) : Binding surface\n", This);
2349
2350         if(!device->isInDraw) {
2351             ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
2352         }
2353
2354         ENTER_GL();
2355
2356         glEnable(This->glDescription.target);
2357
2358         if (!This->glDescription.level) {
2359             if (!This->glDescription.textureName) {
2360                 glGenTextures(1, &This->glDescription.textureName);
2361                 checkGLcall("glGenTextures");
2362                 TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
2363             }
2364             /* This is where we should be reducing the amount of GLMemoryUsed */
2365         } else if (This->glDescription.textureName) {
2366             /* Mipmap surfaces should have a base texture container */
2367             ERR("Mipmap surface has a glTexture bound to it!\n");
2368         }
2369
2370         glBindTexture(This->glDescription.target, This->glDescription.textureName);
2371         checkGLcall("glBindTexture");
2372
2373         LEAVE_GL();
2374     }
2375     return;
2376 }
2377
2378 #include <errno.h>
2379 #include <stdio.h>
2380 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
2381     FILE* f = NULL;
2382     UINT i, y;
2383     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2384     char *allocatedMemory;
2385     char *textureRow;
2386     IWineD3DSwapChain *swapChain = NULL;
2387     int width, height;
2388     GLuint tmpTexture = 0;
2389     DWORD color;
2390     /*FIXME:
2391     Textures may not be stored in ->allocatedgMemory and a GlTexture
2392     so we should lock the surface before saving a snapshot, or at least check that
2393     */
2394     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
2395     by calling GetTexImage and in compressed form by calling
2396     GetCompressedTexImageARB.  Queried compressed images can be saved and
2397     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
2398     texture images do not need to be processed by the GL and should
2399     significantly improve texture loading performance relative to uncompressed
2400     images. */
2401
2402 /* Setup the width and height to be the internal texture width and height. */
2403     width  = This->pow2Width;
2404     height = This->pow2Height;
2405 /* check to see if we're a 'virtual' texture, e.g. we're not a pbuffer of texture, we're a back buffer*/
2406     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
2407
2408     if (This->Flags & SFLAG_INDRAWABLE && !(This->Flags & SFLAG_INTEXTURE)) {
2409         /* if were not a real texture then read the back buffer into a real texture */
2410         /* we don't want to interfere with the back buffer so read the data into a temporary
2411          * texture and then save the data out of the temporary texture
2412          */
2413         GLint prevRead;
2414         ENTER_GL();
2415         TRACE("(%p) Reading render target into texture\n", This);
2416         glEnable(GL_TEXTURE_2D);
2417
2418         glGenTextures(1, &tmpTexture);
2419         glBindTexture(GL_TEXTURE_2D, tmpTexture);
2420
2421         glTexImage2D(GL_TEXTURE_2D,
2422                         0,
2423                         GL_RGBA,
2424                         width,
2425                         height,
2426                         0/*border*/,
2427                         GL_RGBA,
2428                         GL_UNSIGNED_INT_8_8_8_8_REV,
2429                         NULL);
2430
2431         glGetIntegerv(GL_READ_BUFFER, &prevRead);
2432         vcheckGLcall("glGetIntegerv");
2433         glReadBuffer(swapChain ? GL_BACK : This->resource.wineD3DDevice->offscreenBuffer);
2434         vcheckGLcall("glReadBuffer");
2435         glCopyTexImage2D(GL_TEXTURE_2D,
2436                             0,
2437                             GL_RGBA,
2438                             0,
2439                             0,
2440                             width,
2441                             height,
2442                             0);
2443
2444         checkGLcall("glCopyTexImage2D");
2445         glReadBuffer(prevRead);
2446         LEAVE_GL();
2447
2448     } else { /* bind the real texture, and make sure it up to date */
2449         IWineD3DSurface_PreLoad(iface);
2450     }
2451     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
2452     ENTER_GL();
2453     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
2454     glGetTexImage(GL_TEXTURE_2D,
2455                 This->glDescription.level,
2456                 GL_RGBA,
2457                 GL_UNSIGNED_INT_8_8_8_8_REV,
2458                 allocatedMemory);
2459     checkGLcall("glTexImage2D");
2460     if (tmpTexture) {
2461         glBindTexture(GL_TEXTURE_2D, 0);
2462         glDeleteTextures(1, &tmpTexture);
2463     }
2464     LEAVE_GL();
2465
2466     f = fopen(filename, "w+");
2467     if (NULL == f) {
2468         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
2469         return WINED3DERR_INVALIDCALL;
2470     }
2471 /* Save the data out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha channel */
2472     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
2473 /* TGA header */
2474     fputc(0,f);
2475     fputc(0,f);
2476     fputc(2,f);
2477     fputc(0,f);
2478     fputc(0,f);
2479     fputc(0,f);
2480     fputc(0,f);
2481     fputc(0,f);
2482     fputc(0,f);
2483     fputc(0,f);
2484     fputc(0,f);
2485     fputc(0,f);
2486 /* short width*/
2487     fwrite(&width,2,1,f);
2488 /* short height */
2489     fwrite(&height,2,1,f);
2490 /* format rgba */
2491     fputc(0x20,f);
2492     fputc(0x28,f);
2493 /* raw data */
2494     /* 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 */
2495     if(swapChain)
2496         textureRow = allocatedMemory + (width * (height - 1) *4);
2497     else
2498         textureRow = allocatedMemory;
2499     for (y = 0 ; y < height; y++) {
2500         for (i = 0; i < width;  i++) {
2501             color = *((DWORD*)textureRow);
2502             fputc((color >> 16) & 0xFF, f); /* B */
2503             fputc((color >>  8) & 0xFF, f); /* G */
2504             fputc((color >>  0) & 0xFF, f); /* R */
2505             fputc((color >> 24) & 0xFF, f); /* A */
2506             textureRow += 4;
2507         }
2508         /* take two rows of the pointer to the texture memory */
2509         if(swapChain)
2510             (textureRow-= width << 3);
2511
2512     }
2513     TRACE("Closing file\n");
2514     fclose(f);
2515
2516     if(swapChain) {
2517         IWineD3DSwapChain_Release(swapChain);
2518     }
2519     HeapFree(GetProcessHeap(), 0, allocatedMemory);
2520     return WINED3D_OK;
2521 }
2522
2523 /**
2524  *   Slightly inefficient way to handle multiple dirty rects but it works :)
2525  */
2526 HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
2527     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2528     IWineD3DBaseTexture *baseTexture = NULL;
2529
2530     if (!(This->Flags & SFLAG_INSYSMEM) && (This->Flags & SFLAG_INTEXTURE))
2531         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */);
2532
2533     IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2534     if (NULL != pDirtyRect) {
2535         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
2536         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
2537         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
2538         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
2539     } else {
2540         This->dirtyRect.left   = 0;
2541         This->dirtyRect.top    = 0;
2542         This->dirtyRect.right  = This->currentDesc.Width;
2543         This->dirtyRect.bottom = This->currentDesc.Height;
2544     }
2545     TRACE("(%p) : Dirty: yes, Rect:(%d,%d,%d,%d)\n", This, This->dirtyRect.left,
2546           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2547     /* if the container is a basetexture then mark it dirty. */
2548     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2549         TRACE("Passing to container\n");
2550         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
2551         IWineD3DBaseTexture_Release(baseTexture);
2552     }
2553     return WINED3D_OK;
2554 }
2555
2556 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
2557     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2558     HRESULT hr;
2559     const GlPixelFormatDesc *glDesc;
2560     getFormatDescEntry(format, &GLINFO_LOCATION, &glDesc);
2561
2562     TRACE("(%p) : Calling base function first\n", This);
2563     hr = IWineD3DBaseSurfaceImpl_SetFormat(iface, format);
2564     if(SUCCEEDED(hr)) {
2565         /* Setup some glformat defaults */
2566         This->glDescription.glFormat         = glDesc->glFormat;
2567         This->glDescription.glFormatInternal = glDesc->glInternal;
2568         This->glDescription.glType           = glDesc->glType;
2569
2570         This->Flags &= ~SFLAG_ALLOCATED;
2571         TRACE("(%p) : glFormat %d, glFotmatInternal %d, glType %d\n", This,
2572               This->glDescription.glFormat, This->glDescription.glFormatInternal, This->glDescription.glType);
2573     }
2574     return hr;
2575 }
2576
2577 HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2578     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2579
2580     if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2581         WARN("Surface is locked or the HDC is in use\n");
2582         return WINED3DERR_INVALIDCALL;
2583     }
2584
2585     if(Mem && Mem != This->resource.allocatedMemory) {
2586         void *release = NULL;
2587
2588         /* Do I have to copy the old surface content? */
2589         if(This->Flags & SFLAG_DIBSECTION) {
2590                 /* Release the DC. No need to hold the critical section for the update
2591                  * Thread because this thread runs only on front buffers, but this method
2592                  * fails for render targets in the check above.
2593                  */
2594                 SelectObject(This->hDC, This->dib.holdbitmap);
2595                 DeleteDC(This->hDC);
2596                 /* Release the DIB section */
2597                 DeleteObject(This->dib.DIBsection);
2598                 This->dib.bitmap_data = NULL;
2599                 This->resource.allocatedMemory = NULL;
2600                 This->hDC = NULL;
2601                 This->Flags &= ~SFLAG_DIBSECTION;
2602         } else if(!(This->Flags & SFLAG_USERPTR)) {
2603             release = This->resource.heapMemory;
2604             This->resource.heapMemory = NULL;
2605         }
2606         This->resource.allocatedMemory = Mem;
2607         This->Flags |= SFLAG_USERPTR | SFLAG_INSYSMEM;
2608
2609         /* Now the surface memory is most up do date. Invalidate drawable and texture */
2610         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2611
2612         /* For client textures opengl has to be notified */
2613         if(This->Flags & SFLAG_CLIENT) {
2614             This->Flags &= ~SFLAG_ALLOCATED;
2615             IWineD3DSurface_PreLoad(iface);
2616             /* And hope that the app behaves correctly and did not free the old surface memory before setting a new pointer */
2617         }
2618
2619         /* Now free the old memory if any */
2620         HeapFree(GetProcessHeap(), 0, release);
2621     } else if(This->Flags & SFLAG_USERPTR) {
2622         /* LockRect and GetDC will re-create the dib section and allocated memory */
2623         This->resource.allocatedMemory = NULL;
2624         /* HeapMemory should be NULL already */
2625         if(This->resource.heapMemory != NULL) ERR("User pointer surface has heap memory allocated\n");
2626         This->Flags &= ~SFLAG_USERPTR;
2627
2628         if(This->Flags & SFLAG_CLIENT) {
2629             This->Flags &= ~SFLAG_ALLOCATED;
2630             /* This respecifies an empty texture and opengl knows that the old memory is gone */
2631             IWineD3DSurface_PreLoad(iface);
2632         }
2633     }
2634     return WINED3D_OK;
2635 }
2636
2637 void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) {
2638
2639     /* Flip the surface contents */
2640     /* Flip the DC */
2641     {
2642         HDC tmp;
2643         tmp = front->hDC;
2644         front->hDC = back->hDC;
2645         back->hDC = tmp;
2646     }
2647
2648     /* Flip the DIBsection */
2649     {
2650         HBITMAP tmp;
2651         BOOL hasDib = front->Flags & SFLAG_DIBSECTION;
2652         tmp = front->dib.DIBsection;
2653         front->dib.DIBsection = back->dib.DIBsection;
2654         back->dib.DIBsection = tmp;
2655
2656         if(back->Flags & SFLAG_DIBSECTION) front->Flags |= SFLAG_DIBSECTION;
2657         else front->Flags &= ~SFLAG_DIBSECTION;
2658         if(hasDib) back->Flags |= SFLAG_DIBSECTION;
2659         else back->Flags &= ~SFLAG_DIBSECTION;
2660     }
2661
2662     /* Flip the surface data */
2663     {
2664         void* tmp;
2665
2666         tmp = front->dib.bitmap_data;
2667         front->dib.bitmap_data = back->dib.bitmap_data;
2668         back->dib.bitmap_data = tmp;
2669
2670         tmp = front->resource.allocatedMemory;
2671         front->resource.allocatedMemory = back->resource.allocatedMemory;
2672         back->resource.allocatedMemory = tmp;
2673
2674         tmp = front->resource.heapMemory;
2675         front->resource.heapMemory = back->resource.heapMemory;
2676         back->resource.heapMemory = tmp;
2677     }
2678
2679     /* Flip the PBO */
2680     {
2681         GLuint tmp_pbo = front->pbo;
2682         front->pbo = back->pbo;
2683         back->pbo = tmp_pbo;
2684     }
2685
2686     /* client_memory should not be different, but just in case */
2687     {
2688         BOOL tmp;
2689         tmp = front->dib.client_memory;
2690         front->dib.client_memory = back->dib.client_memory;
2691         back->dib.client_memory = tmp;
2692     }
2693
2694     /* Flip the opengl texture */
2695     {
2696         glDescriptor tmp_desc = back->glDescription;
2697         back->glDescription = front->glDescription;
2698         front->glDescription = tmp_desc;
2699     }
2700
2701     {
2702         DWORD tmp_flags = back->Flags;
2703         back->Flags = front->Flags;
2704         front->Flags = tmp_flags;
2705     }
2706 }
2707
2708 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2709     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2710     IWineD3DSwapChainImpl *swapchain = NULL;
2711     HRESULT hr;
2712     TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2713
2714     /* Flipping is only supported on RenderTargets and overlays*/
2715     if( !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_OVERLAY)) ) {
2716         WARN("Tried to flip a non-render target, non-overlay surface\n");
2717         return WINEDDERR_NOTFLIPPABLE;
2718     }
2719
2720     if(This->resource.usage & WINED3DUSAGE_OVERLAY) {
2721         flip_surface(This, (IWineD3DSurfaceImpl *) override);
2722
2723         /* Update the overlay if it is visible */
2724         if(This->overlay_dest) {
2725             return IWineD3DSurface_DrawOverlay((IWineD3DSurface *) This);
2726         } else {
2727             return WINED3D_OK;
2728         }
2729     }
2730
2731     if(override) {
2732         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
2733          * FIXME("(%p) Target override is not supported by now\n", This);
2734          * Additionally, it isn't really possible to support triple-buffering
2735          * properly on opengl at all
2736          */
2737     }
2738
2739     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain);
2740     if(!swapchain) {
2741         ERR("Flipped surface is not on a swapchain\n");
2742         return WINEDDERR_NOTFLIPPABLE;
2743     }
2744
2745     /* Just overwrite the swapchain presentation interval. This is ok because only ddraw apps can call Flip,
2746      * and only d3d8 and d3d9 apps specify the presentation interval
2747      */
2748     if((Flags & (WINEDDFLIP_NOVSYNC | WINEDDFLIP_INTERVAL2 | WINEDDFLIP_INTERVAL3 | WINEDDFLIP_INTERVAL4)) == 0) {
2749         /* Most common case first to avoid wasting time on all the other cases */
2750         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_ONE;
2751     } else if(Flags & WINEDDFLIP_NOVSYNC) {
2752         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
2753     } else if(Flags & WINEDDFLIP_INTERVAL2) {
2754         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_TWO;
2755     } else if(Flags & WINEDDFLIP_INTERVAL3) {
2756         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_THREE;
2757     } else {
2758         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_FOUR;
2759     }
2760
2761     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2762     hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0);
2763     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2764     return hr;
2765 }
2766
2767 /* Does a direct frame buffer -> texture copy. Stretching is done
2768  * with single pixel copy calls
2769  */
2770 static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter) {
2771     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2772     float xrel, yrel;
2773     UINT row;
2774     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2775
2776
2777     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2778     IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2779     ENTER_GL();
2780
2781     /* TODO: Do we need GL_TEXTURE_2D enabled fpr copyteximage? */
2782     glEnable(This->glDescription.target);
2783     checkGLcall("glEnable(This->glDescription.target)");
2784
2785     /* Bind the target texture */
2786     glBindTexture(This->glDescription.target, This->glDescription.textureName);
2787     checkGLcall("glBindTexture");
2788     if(!swapchain) {
2789         TRACE("Reading from an offscreen target\n");
2790         upsidedown = !upsidedown;
2791         glReadBuffer(myDevice->offscreenBuffer);
2792     } else {
2793         GLenum buffer = surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain);
2794         glReadBuffer(buffer);
2795     }
2796     checkGLcall("glReadBuffer");
2797
2798     xrel = (float) (srect->x2 - srect->x1) / (float) (drect->x2 - drect->x1);
2799     yrel = (float) (srect->y2 - srect->y1) / (float) (drect->y2 - drect->y1);
2800
2801     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2802         FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n");
2803
2804         if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) {
2805             ERR("Texture filtering not supported in direct blit\n");
2806         }
2807     } else if((Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) && ((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) {
2808         ERR("Texture filtering not supported in direct blit\n");
2809     }
2810
2811     if(upsidedown &&
2812        !((xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) &&
2813        !((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) {
2814         /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */
2815
2816         glCopyTexSubImage2D(This->glDescription.target,
2817                             This->glDescription.level,
2818                             drect->x1, drect->y1, /* xoffset, yoffset */
2819                             srect->x1, Src->currentDesc.Height - srect->y2,
2820                             drect->x2 - drect->x1, drect->y2 - drect->y1);
2821     } else {
2822         UINT yoffset = Src->currentDesc.Height - srect->y1 + drect->y1 - 1;
2823         /* I have to process this row by row to swap the image,
2824          * otherwise it would be upside down, so stretching in y direction
2825          * doesn't cost extra time
2826          *
2827          * However, stretching in x direction can be avoided if not necessary
2828          */
2829         for(row = drect->y1; row < drect->y2; row++) {
2830             if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2831                 /* Well, that stuff works, but it's very slow.
2832                  * find a better way instead
2833                  */
2834                 UINT col;
2835
2836                 for(col = drect->x1; col < drect->x2; col++) {
2837                     glCopyTexSubImage2D(This->glDescription.target,
2838                                         This->glDescription.level,
2839                                         drect->x1 + col, row, /* xoffset, yoffset */
2840                                         srect->x1 + col * xrel, yoffset - (int) (row * yrel),
2841                                         1, 1);
2842                 }
2843             } else {
2844                 glCopyTexSubImage2D(This->glDescription.target,
2845                                     This->glDescription.level,
2846                                     drect->x1, row, /* xoffset, yoffset */
2847                                     srect->x1, yoffset - (int) (row * yrel),
2848                                     drect->x2-drect->x1, 1);
2849             }
2850         }
2851     }
2852     vcheckGLcall("glCopyTexSubImage2D");
2853
2854     /* Leave the opengl state valid for blitting */
2855     glDisable(This->glDescription.target);
2856     checkGLcall("glDisable(This->glDescription.target)");
2857
2858     LEAVE_GL();
2859 }
2860
2861 /* Uses the hardware to stretch and flip the image */
2862 static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter) {
2863     GLuint src, backup = 0;
2864     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2865     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2866     float left, right, top, bottom; /* Texture coordinates */
2867     UINT fbwidth = Src->currentDesc.Width;
2868     UINT fbheight = Src->currentDesc.Height;
2869     GLenum drawBuffer = GL_BACK;
2870     GLenum texture_target;
2871     BOOL noBackBufferBackup;
2872
2873     TRACE("Using hwstretch blit\n");
2874     /* Activate the Proper context for reading from the source surface, set it up for blitting */
2875     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2876     IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2877
2878     noBackBufferBackup = !swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO;
2879     if(!noBackBufferBackup && Src->glDescription.textureName == 0) {
2880         /* Get it a description */
2881         IWineD3DSurface_PreLoad(SrcSurface);
2882     }
2883     ENTER_GL();
2884
2885     /* Try to use an aux buffer for drawing the rectangle. This way it doesn't need restoring.
2886      * This way we don't have to wait for the 2nd readback to finish to leave this function.
2887      */
2888     if(myDevice->activeContext->aux_buffers >= 2) {
2889         /* Got more than one aux buffer? Use the 2nd aux buffer */
2890         drawBuffer = GL_AUX1;
2891     } else if((swapchain || myDevice->offscreenBuffer == GL_BACK) && myDevice->activeContext->aux_buffers >= 1) {
2892         /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */
2893         drawBuffer = GL_AUX0;
2894     }
2895
2896     if(noBackBufferBackup) {
2897         glGenTextures(1, &backup);
2898         checkGLcall("glGenTextures\n");
2899         glBindTexture(GL_TEXTURE_2D, backup);
2900         checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)");
2901         texture_target = GL_TEXTURE_2D;
2902     } else {
2903         /* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If
2904          * we are reading from the back buffer, the backup can be used as source texture
2905          */
2906         texture_target = Src->glDescription.target;
2907         glBindTexture(texture_target, Src->glDescription.textureName);
2908         checkGLcall("glBindTexture(texture_target, Src->glDescription.textureName)");
2909         glEnable(texture_target);
2910         checkGLcall("glEnable(texture_target)");
2911
2912         /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
2913         Src->Flags &= ~SFLAG_INTEXTURE;
2914     }
2915
2916     if(swapchain) {
2917         glReadBuffer(surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain));
2918     } else {
2919         TRACE("Reading from an offscreen target\n");
2920         upsidedown = !upsidedown;
2921         glReadBuffer(myDevice->offscreenBuffer);
2922     }
2923
2924     /* TODO: Only back up the part that will be overwritten */
2925     glCopyTexSubImage2D(texture_target, 0,
2926                         0, 0 /* read offsets */,
2927                         0, 0,
2928                         fbwidth,
2929                         fbheight);
2930
2931     checkGLcall("glCopyTexSubImage2D");
2932
2933     /* No issue with overriding these - the sampler is dirty due to blit usage */
2934     glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER,
2935                     magLookup[Filter - WINED3DTEXF_NONE]);
2936     checkGLcall("glTexParameteri");
2937     glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER,
2938                     minMipLookup[Filter][WINED3DTEXF_NONE]);
2939     checkGLcall("glTexParameteri");
2940
2941     if(!swapchain || (IWineD3DSurface *) Src == swapchain->backBuffer[0]) {
2942         src = backup ? backup : Src->glDescription.textureName;
2943     } else {
2944         glReadBuffer(GL_FRONT);
2945         checkGLcall("glReadBuffer(GL_FRONT)");
2946
2947         glGenTextures(1, &src);
2948         checkGLcall("glGenTextures(1, &src)");
2949         glBindTexture(GL_TEXTURE_2D, src);
2950         checkGLcall("glBindTexture(GL_TEXTURE_2D, src)");
2951
2952         /* TODO: Only copy the part that will be read. Use srect->x1, srect->y2 as origin, but with the width watch
2953          * out for power of 2 sizes
2954          */
2955         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Src->pow2Width, Src->pow2Height, 0,
2956                     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2957         checkGLcall("glTexImage2D");
2958         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2959                             0, 0 /* read offsets */,
2960                             0, 0,
2961                             fbwidth,
2962                             fbheight);
2963
2964         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2965         checkGLcall("glTexParameteri");
2966         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2967         checkGLcall("glTexParameteri");
2968
2969         glReadBuffer(GL_BACK);
2970         checkGLcall("glReadBuffer(GL_BACK)");
2971
2972         if(texture_target != GL_TEXTURE_2D) {
2973             glDisable(texture_target);
2974             glEnable(GL_TEXTURE_2D);
2975             texture_target = GL_TEXTURE_2D;
2976         }
2977     }
2978     checkGLcall("glEnd and previous");
2979
2980     left = srect->x1;
2981     right = srect->x2;
2982
2983     if(upsidedown) {
2984         top = Src->currentDesc.Height - srect->y1;
2985         bottom = Src->currentDesc.Height - srect->y2;
2986     } else {
2987         top = Src->currentDesc.Height - srect->y2;
2988         bottom = Src->currentDesc.Height - srect->y1;
2989     }
2990
2991     if(Src->Flags & SFLAG_NORMCOORD) {
2992         left /= Src->pow2Width;
2993         right /= Src->pow2Width;
2994         top /= Src->pow2Height;
2995         bottom /= Src->pow2Height;
2996     }
2997
2998     /* draw the source texture stretched and upside down. The correct surface is bound already */
2999     glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
3000     glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
3001
3002     glDrawBuffer(drawBuffer);
3003     glReadBuffer(drawBuffer);
3004
3005     glBegin(GL_QUADS);
3006         /* bottom left */
3007         glTexCoord2f(left, bottom);
3008         glVertex2i(0, fbheight);
3009
3010         /* top left */
3011         glTexCoord2f(left, top);
3012         glVertex2i(0, fbheight - drect->y2 - drect->y1);
3013
3014         /* top right */
3015         glTexCoord2f(right, top);
3016         glVertex2i(drect->x2 - drect->x1, fbheight - drect->y2 - drect->y1);
3017
3018         /* bottom right */
3019         glTexCoord2f(right, bottom);
3020         glVertex2i(drect->x2 - drect->x1, fbheight);
3021     glEnd();
3022     checkGLcall("glEnd and previous");
3023
3024     if(texture_target != This->glDescription.target) {
3025         glDisable(texture_target);
3026         glEnable(This->glDescription.target);
3027         texture_target = This->glDescription.target;
3028     }
3029
3030     /* Now read the stretched and upside down image into the destination texture */
3031     glBindTexture(texture_target, This->glDescription.textureName);
3032     checkGLcall("glBindTexture");
3033     glCopyTexSubImage2D(texture_target,
3034                         0,
3035                         drect->x1, drect->y1, /* xoffset, yoffset */
3036                         0, 0, /* We blitted the image to the origin */
3037                         drect->x2 - drect->x1, drect->y2 - drect->y1);
3038     checkGLcall("glCopyTexSubImage2D");
3039
3040     if(drawBuffer == GL_BACK) {
3041         /* Write the back buffer backup back */
3042         if(backup) {
3043             if(texture_target != GL_TEXTURE_2D) {
3044                 glDisable(texture_target);
3045                 glEnable(GL_TEXTURE_2D);
3046                 texture_target = GL_TEXTURE_2D;
3047             }
3048             glBindTexture(GL_TEXTURE_2D, backup);
3049             checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)");
3050         } else {
3051             if(texture_target != Src->glDescription.target) {
3052                 glDisable(texture_target);
3053                 glEnable(Src->glDescription.target);
3054                 texture_target = Src->glDescription.target;
3055             }
3056             glBindTexture(Src->glDescription.target, Src->glDescription.textureName);
3057             checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)");
3058         }
3059
3060         glBegin(GL_QUADS);
3061             /* top left */
3062             glTexCoord2f(0.0, (float) fbheight / (float) Src->pow2Height);
3063             glVertex2i(0, 0);
3064
3065             /* bottom left */
3066             glTexCoord2f(0.0, 0.0);
3067             glVertex2i(0, fbheight);
3068
3069             /* bottom right */
3070             glTexCoord2f((float) fbwidth / (float) Src->pow2Width, 0.0);
3071             glVertex2i(fbwidth, Src->currentDesc.Height);
3072
3073             /* top right */
3074             glTexCoord2f((float) fbwidth / (float) Src->pow2Width, (float) fbheight / (float) Src->pow2Height);
3075             glVertex2i(fbwidth, 0);
3076         glEnd();
3077     } else {
3078         /* Restore the old draw buffer */
3079         glDrawBuffer(GL_BACK);
3080     }
3081     glDisable(texture_target);
3082     checkGLcall("glDisable(texture_target)");
3083
3084     /* Cleanup */
3085     if(src != Src->glDescription.textureName && src != backup) {
3086         glDeleteTextures(1, &src);
3087         checkGLcall("glDeleteTextures(1, &src)");
3088     }
3089     if(backup) {
3090         glDeleteTextures(1, &backup);
3091         checkGLcall("glDeleteTextures(1, &backup)");
3092     }
3093
3094     LEAVE_GL();
3095 }
3096
3097 /* Not called from the VTable */
3098 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) {
3099     WINED3DRECT rect;
3100     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3101     IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL;
3102     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3103
3104     TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
3105
3106     /* Get the swapchain. One of the surfaces has to be a primary surface */
3107     if(This->resource.pool == WINED3DPOOL_SYSTEMMEM) {
3108         WARN("Destination is in sysmem, rejecting gl blt\n");
3109         return WINED3DERR_INVALIDCALL;
3110     }
3111     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&dstSwapchain);
3112     if(dstSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) dstSwapchain);
3113     if(Src) {
3114         if(Src->resource.pool == WINED3DPOOL_SYSTEMMEM) {
3115             WARN("Src is in sysmem, rejecting gl blt\n");
3116             return WINED3DERR_INVALIDCALL;
3117         }
3118         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&srcSwapchain);
3119         if(srcSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) srcSwapchain);
3120     }
3121
3122     /* Early sort out of cases where no render target is used */
3123     if(!dstSwapchain && !srcSwapchain &&
3124         SrcSurface != myDevice->render_targets[0] && This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
3125         TRACE("No surface is render target, not using hardware blit. Src = %p, dst = %p\n", Src, This);
3126         return WINED3DERR_INVALIDCALL;
3127     }
3128
3129     /* No destination color keying supported */
3130     if(Flags & (WINEDDBLT_KEYDEST | WINEDDBLT_KEYDESTOVERRIDE)) {
3131         /* Can we support that with glBlendFunc if blitting to the frame buffer? */
3132         TRACE("Destination color key not supported in accelerated Blit, falling back to software\n");
3133         return WINED3DERR_INVALIDCALL;
3134     }
3135
3136     if (DestRect) {
3137         rect.x1 = DestRect->left;
3138         rect.y1 = DestRect->top;
3139         rect.x2 = DestRect->right;
3140         rect.y2 = DestRect->bottom;
3141     } else {
3142         rect.x1 = 0;
3143         rect.y1 = 0;
3144         rect.x2 = This->currentDesc.Width;
3145         rect.y2 = This->currentDesc.Height;
3146     }
3147
3148     /* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */
3149     if(dstSwapchain && dstSwapchain == srcSwapchain && dstSwapchain->backBuffer &&
3150        ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && SrcSurface == dstSwapchain->backBuffer[0]) {
3151         /* Half-life does a Blt from the back buffer to the front buffer,
3152          * Full surface size, no flags... Use present instead
3153          *
3154          * This path will only be entered for d3d7 and ddraw apps, because d3d8/9 offer no way to blit TO the front buffer
3155          */
3156
3157         /* Check rects - IWineD3DDevice_Present doesn't handle them */
3158         while(1)
3159         {
3160             RECT mySrcRect;
3161             TRACE("Looking if a Present can be done...\n");
3162             /* Source Rectangle must be full surface */
3163             if( SrcRect ) {
3164                 if(SrcRect->left != 0 || SrcRect->top != 0 ||
3165                    SrcRect->right != Src->currentDesc.Width || SrcRect->bottom != Src->currentDesc.Height) {
3166                     TRACE("No, Source rectangle doesn't match\n");
3167                     break;
3168                 }
3169             }
3170             mySrcRect.left = 0;
3171             mySrcRect.top = 0;
3172             mySrcRect.right = Src->currentDesc.Width;
3173             mySrcRect.bottom = Src->currentDesc.Height;
3174
3175             /* No stretching may occur */
3176             if(mySrcRect.right != rect.x2 - rect.x1 ||
3177                mySrcRect.bottom != rect.y2 - rect.y1) {
3178                 TRACE("No, stretching is done\n");
3179                 break;
3180             }
3181
3182             /* Destination must be full surface or match the clipping rectangle */
3183             if(This->clipper && ((IWineD3DClipperImpl *) This->clipper)->hWnd)
3184             {
3185                 RECT cliprect;
3186                 POINT pos[2];
3187                 GetClientRect(((IWineD3DClipperImpl *) This->clipper)->hWnd, &cliprect);
3188                 pos[0].x = rect.x1;
3189                 pos[0].y = rect.y1;
3190                 pos[1].x = rect.x2;
3191                 pos[1].y = rect.y2;
3192                 MapWindowPoints(GetDesktopWindow(), ((IWineD3DClipperImpl *) This->clipper)->hWnd,
3193                                 pos, 2);
3194
3195                 if(pos[0].x != cliprect.left  || pos[0].y != cliprect.top   ||
3196                    pos[1].x != cliprect.right || pos[1].y != cliprect.bottom)
3197                 {
3198                     TRACE("No, dest rectangle doesn't match(clipper)\n");
3199                     TRACE("Clip rect at (%d,%d)-(%d,%d)\n", cliprect.left, cliprect.top, cliprect.right, cliprect.bottom);
3200                     TRACE("Blt dest: (%d,%d)-(%d,%d)\n", rect.x1, rect.y1, rect.x2, rect.y2);
3201                     break;
3202                 }
3203             }
3204             else
3205             {
3206                 if(rect.x1 != 0 || rect.y1 != 0 ||
3207                    rect.x2 != This->currentDesc.Width || rect.y2 != This->currentDesc.Height) {
3208                     TRACE("No, dest rectangle doesn't match(surface size)\n");
3209                     break;
3210                 }
3211             }
3212
3213             TRACE("Yes\n");
3214
3215             /* These flags are unimportant for the flag check, remove them */
3216             if((Flags & ~(WINEDDBLT_DONOTWAIT | WINEDDBLT_WAIT)) == 0) {
3217                 WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect;
3218
3219                 /* The idea behind this is that a glReadPixels and a glDrawPixels call
3220                     * take very long, while a flip is fast.
3221                     * This applies to Half-Life, which does such Blts every time it finished
3222                     * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
3223                     * menu. This is also used by all apps when they do windowed rendering
3224                     *
3225                     * The problem is that flipping is not really the same as copying. After a
3226                     * Blt the front buffer is a copy of the back buffer, and the back buffer is
3227                     * untouched. Therefore it's necessary to override the swap effect
3228                     * and to set it back after the flip.
3229                     *
3230                     * Windowed Direct3D < 7 apps do the same. The D3D7 sdk demos are nice
3231                     * testcases.
3232                     */
3233
3234                 dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
3235                 dstSwapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
3236
3237                 TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
3238                 IWineD3DSwapChain_Present((IWineD3DSwapChain *) dstSwapchain, NULL, NULL, 0, NULL, 0);
3239
3240                 dstSwapchain->presentParms.SwapEffect = orig_swap;
3241
3242                 return WINED3D_OK;
3243             }
3244             break;
3245         }
3246
3247         TRACE("Unsupported blit between buffers on the same swapchain\n");
3248         return WINED3DERR_INVALIDCALL;
3249     } else if(dstSwapchain && dstSwapchain == srcSwapchain) {
3250         FIXME("Implement hardware blit between two surfaces on the same swapchain\n");
3251         return WINED3DERR_INVALIDCALL;
3252     } else if(dstSwapchain && srcSwapchain) {
3253         FIXME("Implement hardware blit between two different swapchains\n");
3254         return WINED3DERR_INVALIDCALL;
3255     } else if(dstSwapchain) {
3256         if(SrcSurface == myDevice->render_targets[0]) {
3257             TRACE("Blit from active render target to a swapchain\n");
3258             /* Handled with regular texture -> swapchain blit */
3259         }
3260     } else if(srcSwapchain && This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
3261         FIXME("Implement blit from a swapchain to the active render target\n");
3262         return WINED3DERR_INVALIDCALL;
3263     }
3264
3265     if((srcSwapchain || SrcSurface == myDevice->render_targets[0]) && !dstSwapchain) {
3266         /* Blit from render target to texture */
3267         WINED3DRECT srect;
3268         BOOL upsideDown, stretchx;
3269         BOOL paletteOverride = FALSE;
3270
3271         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3272             TRACE("Color keying not supported by frame buffer to texture blit\n");
3273             return WINED3DERR_INVALIDCALL;
3274             /* Destination color key is checked above */
3275         }
3276
3277         /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
3278          * glCopyTexSubImage is a bit picky about the parameters we pass to it
3279          */
3280         if(SrcRect) {
3281             if(SrcRect->top < SrcRect->bottom) {
3282                 srect.y1 = SrcRect->top;
3283                 srect.y2 = SrcRect->bottom;
3284                 upsideDown = FALSE;
3285             } else {
3286                 srect.y1 = SrcRect->bottom;
3287                 srect.y2 = SrcRect->top;
3288                 upsideDown = TRUE;
3289             }
3290             srect.x1 = SrcRect->left;
3291             srect.x2 = SrcRect->right;
3292         } else {
3293             srect.x1 = 0;
3294             srect.y1 = 0;
3295             srect.x2 = Src->currentDesc.Width;
3296             srect.y2 = Src->currentDesc.Height;
3297             upsideDown = FALSE;
3298         }
3299         if(rect.x1 > rect.x2) {
3300             UINT tmp = rect.x2;
3301             rect.x2 = rect.x1;
3302             rect.x1 = tmp;
3303             upsideDown = !upsideDown;
3304         }
3305
3306         if(rect.x2 - rect.x1 != srect.x2 - srect.x1) {
3307             stretchx = TRUE;
3308         } else {
3309             stretchx = FALSE;
3310         }
3311
3312         /* When blitting from a render target a texture, the texture isn't required to have a palette.
3313          * In this case grab the palette from the render target. */
3314         if((This->resource.format == WINED3DFMT_P8) && (This->palette == NULL)) {
3315             paletteOverride = TRUE;
3316             TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This);
3317             This->palette = Src->palette;
3318         }
3319
3320         /* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
3321          * flip the image nor scale it.
3322          *
3323          * -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
3324          * -> If the app wants a image width an unscaled width, copy it line per line
3325          * -> If the app wants a image that is scaled on the x axis, and the destination rectangle is smaller
3326          *    than the frame buffer, draw an upside down scaled image onto the fb, read it back and restore the
3327          *    back buffer. This is slower than reading line per line, thus not used for flipping
3328          * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
3329          *    pixel by pixel
3330          *
3331          * If EXT_framebuffer_blit is supported that can be used instead. Note that EXT_framebuffer_blit implies
3332          * FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering
3333          * backends.
3334          */
3335         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT)) {
3336             stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &srect,
3337                     (IWineD3DSurface *)This, &rect, Filter, upsideDown);
3338         } else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width ||
3339                                     rect.y2 - rect.y1 > Src->currentDesc.Height) {
3340             TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
3341             fb_copy_to_texture_direct(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, Filter);
3342         } else {
3343             TRACE("Using hardware stretching to flip / stretch the texture\n");
3344             fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, Filter);
3345         }
3346
3347         /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3348         if(paletteOverride)
3349             This->palette = NULL;
3350
3351         if(!(This->Flags & SFLAG_DONOTFREE)) {
3352             HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
3353             This->resource.allocatedMemory = NULL;
3354             This->resource.heapMemory = NULL;
3355         } else {
3356             This->Flags &= ~SFLAG_INSYSMEM;
3357         }
3358         /* The texture is now most up to date - If the surface is a render target and has a drawable, this
3359          * path is never entered
3360          */
3361         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INTEXTURE, TRUE);
3362
3363         return WINED3D_OK;
3364     } else if(Src) {
3365         /* Blit from offscreen surface to render target */
3366         float glTexCoord[4];
3367         DWORD oldCKeyFlags = Src->CKeyFlags;
3368         WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey;
3369         RECT SourceRectangle;
3370         BOOL paletteOverride = FALSE;
3371
3372         TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
3373
3374         if(SrcRect) {
3375             SourceRectangle.left = SrcRect->left;
3376             SourceRectangle.right = SrcRect->right;
3377             SourceRectangle.top = SrcRect->top;
3378             SourceRectangle.bottom = SrcRect->bottom;
3379         } else {
3380             SourceRectangle.left = 0;
3381             SourceRectangle.right = Src->currentDesc.Width;
3382             SourceRectangle.top = 0;
3383             SourceRectangle.bottom = Src->currentDesc.Height;
3384         }
3385
3386         /* When blitting from an offscreen surface to a rendertarget, the source
3387          * surface is not required to have a palette. Our rendering / conversion
3388          * code further down the road retrieves the palette from the surface, so
3389          * it must have a palette set. */
3390         if((Src->resource.format == WINED3DFMT_P8) && (Src->palette == NULL)) {
3391             paletteOverride = TRUE;
3392             TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This);
3393             Src->palette = This->palette;
3394         }
3395
3396         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) &&
3397             (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) == 0) {
3398             TRACE("Using stretch_rect_fbo\n");
3399             /* The source is always a texture, but never the currently active render target, and the texture
3400              * contents are never upside down
3401              */
3402             stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, (WINED3DRECT *) &SourceRectangle,
3403                               (IWineD3DSurface *)This, &rect, Filter, FALSE);
3404
3405             /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3406             if(paletteOverride)
3407                 Src->palette = NULL;
3408             return WINED3D_OK;
3409         }
3410
3411         if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
3412             /* Fall back to software */
3413             WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
3414                     SourceRectangle.left, SourceRectangle.top,
3415                     SourceRectangle.right, SourceRectangle.bottom);
3416             return WINED3DERR_INVALIDCALL;
3417         }
3418
3419         /* Color keying: Check if we have to do a color keyed blt,
3420          * and if not check if a color key is activated.
3421          *
3422          * Just modify the color keying parameters in the surface and restore them afterwards
3423          * The surface keeps track of the color key last used to load the opengl surface.
3424          * PreLoad will catch the change to the flags and color key and reload if necessary.
3425          */
3426         if(Flags & WINEDDBLT_KEYSRC) {
3427             /* Use color key from surface */
3428         } else if(Flags & WINEDDBLT_KEYSRCOVERRIDE) {
3429             /* Use color key from DDBltFx */
3430             Src->CKeyFlags |= WINEDDSD_CKSRCBLT;
3431             Src->SrcBltCKey = DDBltFx->ddckSrcColorkey;
3432         } else {
3433             /* Do not use color key */
3434             Src->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
3435         }
3436
3437         /* Now load the surface */
3438         IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
3439
3440         /* Activate the destination context, set it up for blitting */
3441         ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
3442
3443         if (dstSwapchain && (IWineD3DSurface *)This == dstSwapchain->frontBuffer) {
3444             RECT windowsize;
3445             POINT offset = {0,0};
3446             UINT h;
3447             ClientToScreen(dstSwapchain->win_handle, &offset);
3448             GetClientRect(dstSwapchain->win_handle, &windowsize);
3449             h = windowsize.bottom - windowsize.top;
3450             rect.x1 -= offset.x; rect.x2 -=offset.x;
3451             rect.y1 -= offset.y; rect.y2 -=offset.y;
3452             rect.y1 += This->currentDesc.Height - h; rect.y2 += This->currentDesc.Height - h;
3453         }
3454
3455         ENTER_GL();
3456         myDevice->blitter->set_shader((IWineD3DDevice *) myDevice, Src->resource.format,
3457                                        Src->glDescription.target, Src->pow2Width, Src->pow2Height);
3458
3459         /* Bind the texture */
3460         glBindTexture(Src->glDescription.target, Src->glDescription.textureName);
3461         checkGLcall("glBindTexture");
3462
3463         /* Filtering for StretchRect */
3464         glTexParameteri(Src->glDescription.target, GL_TEXTURE_MAG_FILTER,
3465                         magLookup[Filter - WINED3DTEXF_NONE]);
3466         checkGLcall("glTexParameteri");
3467         glTexParameteri(Src->glDescription.target, GL_TEXTURE_MIN_FILTER,
3468                         minMipLookup[Filter][WINED3DTEXF_NONE]);
3469         checkGLcall("glTexParameteri");
3470         glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_S, GL_CLAMP);
3471         glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_T, GL_CLAMP);
3472         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3473         checkGLcall("glTexEnvi");
3474
3475         /* This is for color keying */
3476         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3477             glEnable(GL_ALPHA_TEST);
3478             checkGLcall("glEnable GL_ALPHA_TEST");
3479
3480             /* When the primary render target uses P8, the alpha component contains the palette index.
3481              * Which means that the colorkey is one of the palette entries. In other cases pixels that
3482              * should be masked away have alpha set to 0. */
3483             if(primary_render_target_is_p8(myDevice))
3484                 glAlphaFunc(GL_NOTEQUAL, (float)Src->SrcBltCKey.dwColorSpaceLowValue / 256.0);
3485             else
3486                 glAlphaFunc(GL_NOTEQUAL, 0.0);
3487             checkGLcall("glAlphaFunc\n");
3488         } else {
3489             glDisable(GL_ALPHA_TEST);
3490             checkGLcall("glDisable GL_ALPHA_TEST");
3491         }
3492
3493         /* Draw a textured quad
3494          */
3495         glBegin(GL_QUADS);
3496
3497         glColor3d(1.0f, 1.0f, 1.0f);
3498         glTexCoord2f(glTexCoord[0], glTexCoord[2]);
3499         glVertex3f(rect.x1,
3500                     rect.y1,
3501                     0.0);
3502
3503         glTexCoord2f(glTexCoord[0], glTexCoord[3]);
3504         glVertex3f(rect.x1, rect.y2, 0.0);
3505
3506         glTexCoord2f(glTexCoord[1], glTexCoord[3]);
3507         glVertex3f(rect.x2,
3508                     rect.y2,
3509                     0.0);
3510
3511         glTexCoord2f(glTexCoord[1], glTexCoord[2]);
3512         glVertex3f(rect.x2,
3513                     rect.y1,
3514                     0.0);
3515         glEnd();
3516         checkGLcall("glEnd");
3517
3518         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3519             glDisable(GL_ALPHA_TEST);
3520             checkGLcall("glDisable(GL_ALPHA_TEST)");
3521         }
3522
3523         glBindTexture(Src->glDescription.target, 0);
3524         checkGLcall("glBindTexture(Src->glDescription.target, 0)");
3525         /* Leave the opengl state valid for blitting */
3526         myDevice->blitter->unset_shader((IWineD3DDevice *) myDevice);
3527
3528         /* Restore the color key parameters */
3529         Src->CKeyFlags = oldCKeyFlags;
3530         Src->SrcBltCKey = oldBltCKey;
3531
3532         /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3533         if(paletteOverride)
3534             Src->palette = NULL;
3535
3536         LEAVE_GL();
3537
3538         /* Flush in case the drawable is used by multiple GL contexts */
3539         if(dstSwapchain && (This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer || dstSwapchain->num_contexts >= 2))
3540             glFlush();
3541
3542         /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
3543         /* The surface is now in the drawable. On onscreen surfaces or without fbos the texture
3544          * is outdated now
3545          */
3546         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INDRAWABLE, TRUE);
3547
3548         return WINED3D_OK;
3549     } else {
3550         /* Source-Less Blit to render target */
3551         if (Flags & WINEDDBLT_COLORFILL) {
3552             /* This is easy to handle for the D3D Device... */
3553             DWORD color;
3554
3555             TRACE("Colorfill\n");
3556
3557             /* This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0] || dstSwapchain
3558                 must be true if we are here */
3559             if (This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0] &&
3560                     !(This == (IWineD3DSurfaceImpl*) dstSwapchain->frontBuffer ||
3561                       (dstSwapchain->backBuffer && This == (IWineD3DSurfaceImpl*) dstSwapchain->backBuffer[0]))) {
3562                 TRACE("Surface is higher back buffer, falling back to software\n");
3563                 return WINED3DERR_INVALIDCALL;
3564             }
3565
3566             /* The color as given in the Blt function is in the format of the frame-buffer...
3567              * 'clear' expect it in ARGB format => we need to do some conversion :-)
3568              */
3569             if (This->resource.format == WINED3DFMT_P8) {
3570                 DWORD alpha;
3571
3572                 if (primary_render_target_is_p8(myDevice)) alpha = DDBltFx->u5.dwFillColor << 24;
3573                 else alpha = 0xFF000000;
3574
3575                 if (This->palette) {
3576                     color = (alpha |
3577                             (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
3578                             (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
3579                             (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
3580                 } else {
3581                     color = alpha;
3582                 }
3583             }
3584             else if (This->resource.format == WINED3DFMT_R5G6B5) {
3585                 if (DDBltFx->u5.dwFillColor == 0xFFFF) {
3586                     color = 0xFFFFFFFF;
3587                 } else {
3588                     color = ((0xFF000000) |
3589                             ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
3590                             ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
3591                             ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
3592                 }
3593             }
3594             else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
3595                     (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
3596                 color = 0xFF000000 | DDBltFx->u5.dwFillColor;
3597             }
3598             else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
3599                 color = DDBltFx->u5.dwFillColor;
3600             }
3601             else {
3602                 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
3603                 return WINED3DERR_INVALIDCALL;
3604             }
3605
3606             TRACE("(%p) executing Render Target override, color = %x\n", This, color);
3607             IWineD3DDeviceImpl_ClearSurface(myDevice, This,
3608                                             1, /* Number of rectangles */
3609                                             &rect, WINED3DCLEAR_TARGET, color,
3610                                             0.0 /* Z */,
3611                                             0 /* Stencil */);
3612             return WINED3D_OK;
3613         }
3614     }
3615
3616     /* Default: Fall back to the generic blt. Not an error, a TRACE is enough */
3617     TRACE("Didn't find any usable render target setup for hw blit, falling back to software\n");
3618     return WINED3DERR_INVALIDCALL;
3619 }
3620
3621 static HRESULT WINAPI IWineD3DSurfaceImpl_BltZ(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, WINEDDBLTFX *DDBltFx)
3622 {
3623     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3624     float depth;
3625
3626     if (Flags & WINEDDBLT_DEPTHFILL) {
3627         switch(This->resource.format) {
3628             case WINED3DFMT_D16:
3629                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x0000ffff;
3630                 break;
3631             case WINED3DFMT_D15S1:
3632                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x0000fffe;
3633                 break;
3634             case WINED3DFMT_D24S8:
3635             case WINED3DFMT_D24X8:
3636                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x00ffffff;
3637                 break;
3638             case WINED3DFMT_D32:
3639                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0xffffffff;
3640                 break;
3641             default:
3642                 depth = 0.0;
3643                 ERR("Unexpected format for depth fill: %s\n", debug_d3dformat(This->resource.format));
3644         }
3645
3646         return IWineD3DDevice_Clear((IWineD3DDevice *) myDevice,
3647                                     DestRect == NULL ? 0 : 1,
3648                                     (WINED3DRECT *) DestRect,
3649                                     WINED3DCLEAR_ZBUFFER,
3650                                     0x00000000,
3651                                     depth,
3652                                     0x00000000);
3653     }
3654
3655     FIXME("(%p): Unsupp depthstencil blit\n", This);
3656     return WINED3DERR_INVALIDCALL;
3657 }
3658
3659 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) {
3660     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
3661     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3662     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3663     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
3664     TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
3665
3666     if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
3667     {
3668         WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
3669         return WINEDDERR_SURFACEBUSY;
3670     }
3671
3672     /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair,
3673      * except depth blits, which seem to work
3674      */
3675     if(iface == myDevice->stencilBufferTarget || (SrcSurface && SrcSurface == myDevice->stencilBufferTarget)) {
3676         if(myDevice->inScene && !(Flags & WINEDDBLT_DEPTHFILL)) {
3677             TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
3678             return WINED3DERR_INVALIDCALL;
3679         } else if(IWineD3DSurfaceImpl_BltZ(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) {
3680             TRACE("Z Blit override handled the blit\n");
3681             return WINED3D_OK;
3682         }
3683     }
3684
3685     /* Special cases for RenderTargets */
3686     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
3687         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
3688         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter) == WINED3D_OK) return WINED3D_OK;
3689     }
3690
3691     /* For the rest call the X11 surface implementation.
3692      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
3693      * other Blts are rather rare
3694      */
3695     return IWineD3DBaseSurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter);
3696 }
3697
3698 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
3699     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3700     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
3701     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3702     TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
3703
3704     if ( (This->Flags & SFLAG_LOCKED) || ((srcImpl != NULL) && (srcImpl->Flags & SFLAG_LOCKED)))
3705     {
3706         WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
3707         return WINEDDERR_SURFACEBUSY;
3708     }
3709
3710     if(myDevice->inScene &&
3711        (iface == myDevice->stencilBufferTarget ||
3712        (Source && Source == myDevice->stencilBufferTarget))) {
3713         TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
3714         return WINED3DERR_INVALIDCALL;
3715     }
3716
3717     /* Special cases for RenderTargets */
3718     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
3719         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
3720
3721         RECT SrcRect, DstRect;
3722         DWORD Flags=0;
3723
3724         if(rsrc) {
3725             SrcRect.left = rsrc->left;
3726             SrcRect.top= rsrc->top;
3727             SrcRect.bottom = rsrc->bottom;
3728             SrcRect.right = rsrc->right;
3729         } else {
3730             SrcRect.left = 0;
3731             SrcRect.top = 0;
3732             SrcRect.right = srcImpl->currentDesc.Width;
3733             SrcRect.bottom = srcImpl->currentDesc.Height;
3734         }
3735
3736         DstRect.left = dstx;
3737         DstRect.top=dsty;
3738         DstRect.right = dstx + SrcRect.right - SrcRect.left;
3739         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
3740
3741         /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
3742         if(trans & WINEDDBLTFAST_SRCCOLORKEY)
3743             Flags |= WINEDDBLT_KEYSRC;
3744         if(trans & WINEDDBLTFAST_DESTCOLORKEY)
3745             Flags |= WINEDDBLT_KEYDEST;
3746         if(trans & WINEDDBLTFAST_WAIT)
3747             Flags |= WINEDDBLT_WAIT;
3748         if(trans & WINEDDBLTFAST_DONOTWAIT)
3749             Flags |= WINEDDBLT_DONOTWAIT;
3750
3751         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL, WINED3DTEXF_POINT) == WINED3D_OK) return WINED3D_OK;
3752     }
3753
3754
3755     return IWineD3DBaseSurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
3756 }
3757
3758 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
3759     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3760     RGBQUAD col[256];
3761     IWineD3DPaletteImpl *pal = This->palette;
3762     unsigned int n;
3763     TRACE("(%p)\n", This);
3764
3765     if (!pal) return WINED3D_OK;
3766
3767     if(This->resource.format == WINED3DFMT_P8 ||
3768        This->resource.format == WINED3DFMT_A8P8)
3769     {
3770         int bpp;
3771         GLenum format, internal, type;
3772         CONVERT_TYPES convert;
3773
3774         /* Check if we are using a RTL mode which uses texturing for uploads */
3775         BOOL use_texture = (wined3d_settings.rendertargetlock_mode == RTL_READTEX || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX);
3776
3777         /* Check if we have hardware palette conversion if we have convert is set to NO_CONVERSION */
3778         d3dfmt_get_conv(This, TRUE, use_texture, &format, &internal, &type, &convert, &bpp, This->srgb);
3779
3780         if((This->resource.usage & WINED3DUSAGE_RENDERTARGET) && (convert == NO_CONVERSION))
3781         {
3782             /* Make sure the texture is up to date. This call doesn't do anything if the texture is already up to date. */
3783             IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL);
3784
3785             /* We want to force a palette refresh, so mark the drawable as not being up to date */
3786             IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE);
3787
3788             /* Re-upload the palette */
3789             d3dfmt_p8_upload_palette(iface, convert);
3790         } else {
3791             if(!(This->Flags & SFLAG_INSYSMEM)) {
3792                 TRACE("Palette changed with surface that does not have an up to date system memory copy\n");
3793                 IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
3794             }
3795             TRACE("Dirtifying surface\n");
3796             IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
3797         }
3798     }
3799
3800     if(This->Flags & SFLAG_DIBSECTION) {
3801         TRACE("(%p): Updating the hdc's palette\n", This);
3802         for (n=0; n<256; n++) {
3803             col[n].rgbRed   = pal->palents[n].peRed;
3804             col[n].rgbGreen = pal->palents[n].peGreen;
3805             col[n].rgbBlue  = pal->palents[n].peBlue;
3806             col[n].rgbReserved = 0;
3807         }
3808         SetDIBColorTable(This->hDC, 0, 256, col);
3809     }
3810
3811     /* Propagate the changes to the drawable when we have a palette. */
3812     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
3813         IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, NULL);
3814
3815     return WINED3D_OK;
3816 }
3817
3818 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
3819     /** Check against the maximum texture sizes supported by the video card **/
3820     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3821     unsigned int pow2Width, pow2Height;
3822     const GlPixelFormatDesc *glDesc;
3823
3824     getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc);
3825     /* Setup some glformat defaults */
3826     This->glDescription.glFormat         = glDesc->glFormat;
3827     This->glDescription.glFormatInternal = glDesc->glInternal;
3828     This->glDescription.glType           = glDesc->glType;
3829
3830     This->glDescription.textureName      = 0;
3831     This->glDescription.target           = GL_TEXTURE_2D;
3832
3833     /* Non-power2 support */
3834     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) {
3835         pow2Width = This->currentDesc.Width;
3836         pow2Height = This->currentDesc.Height;
3837     } else {
3838         /* Find the nearest pow2 match */
3839         pow2Width = pow2Height = 1;
3840         while (pow2Width < This->currentDesc.Width) pow2Width <<= 1;
3841         while (pow2Height < This->currentDesc.Height) pow2Height <<= 1;
3842     }
3843     This->pow2Width  = pow2Width;
3844     This->pow2Height = pow2Height;
3845
3846     if (pow2Width > This->currentDesc.Width || pow2Height > This->currentDesc.Height) {
3847         WINED3DFORMAT Format = This->resource.format;
3848         /** TODO: add support for non power two compressed textures **/
3849         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
3850             || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5
3851             || This->resource.format == WINED3DFMT_ATI2N) {
3852             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
3853                   This, This->currentDesc.Width, This->currentDesc.Height);
3854             return WINED3DERR_NOTAVAILABLE;
3855         }
3856     }
3857
3858     if(pow2Width != This->currentDesc.Width ||
3859        pow2Height != This->currentDesc.Height) {
3860         This->Flags |= SFLAG_NONPOW2;
3861     }
3862
3863     TRACE("%p\n", This);
3864     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
3865         /* one of three options
3866         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)
3867         2: Set the texture to the maximum size (bad idea)
3868         3:    WARN and return WINED3DERR_NOTAVAILABLE;
3869         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.
3870         */
3871         WARN("(%p) Creating an oversized surface\n", This);
3872         This->Flags |= SFLAG_OVERSIZE;
3873
3874         /* This will be initialized on the first blt */
3875         This->glRect.left = 0;
3876         This->glRect.top = 0;
3877         This->glRect.right = 0;
3878         This->glRect.bottom = 0;
3879     } else {
3880         /* Check this after the oversize check - do not make an oversized surface a texture_rectangle one.
3881            Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
3882            is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE
3883            doesn't work in combination with ARB_TEXTURE_RECTANGLE.
3884         */
3885         if(This->Flags & SFLAG_NONPOW2 && GL_SUPPORT(ARB_TEXTURE_RECTANGLE) &&
3886            !((This->resource.format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE) && (wined3d_settings.rendertargetlock_mode == RTL_READTEX || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX)))
3887         {
3888             This->glDescription.target = GL_TEXTURE_RECTANGLE_ARB;
3889             This->pow2Width  = This->currentDesc.Width;
3890             This->pow2Height = This->currentDesc.Height;
3891             This->Flags &= ~(SFLAG_NONPOW2 | SFLAG_NORMCOORD);
3892         }
3893
3894         /* No oversize, gl rect is the full texture size */
3895         This->Flags &= ~SFLAG_OVERSIZE;
3896         This->glRect.left = 0;
3897         This->glRect.top = 0;
3898         This->glRect.right = This->pow2Width;
3899         This->glRect.bottom = This->pow2Height;
3900     }
3901
3902     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
3903         switch(wined3d_settings.offscreen_rendering_mode) {
3904             case ORM_FBO:        This->get_drawable_size = get_drawable_size_fbo;        break;
3905             case ORM_PBUFFER:    This->get_drawable_size = get_drawable_size_pbuffer;    break;
3906             case ORM_BACKBUFFER: This->get_drawable_size = get_drawable_size_backbuffer; break;
3907         }
3908     }
3909
3910     This->Flags |= SFLAG_INSYSMEM;
3911
3912     return WINED3D_OK;
3913 }
3914
3915 void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location) {
3916     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
3917
3918     TRACE("(%p) New location %#x\n", This, location);
3919
3920     if (location & ~SFLAG_DS_LOCATIONS) {
3921         FIXME("(%p) Invalid location (%#x) specified\n", This, location);
3922     }
3923
3924     This->Flags &= ~SFLAG_DS_LOCATIONS;
3925     This->Flags |= location;
3926 }
3927
3928 void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) {
3929     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
3930     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
3931
3932     TRACE("(%p) New location %#x\n", This, location);
3933
3934     /* TODO: Make this work for modes other than FBO */
3935     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
3936
3937     if (This->Flags & location) {
3938         TRACE("(%p) Location (%#x) is already up to date\n", This, location);
3939         return;
3940     }
3941
3942     if (This->current_renderbuffer) {
3943         FIXME("(%p) Not supported with fixed up depth stencil\n", This);
3944         return;
3945     }
3946
3947     if (location == SFLAG_DS_OFFSCREEN) {
3948         if (This->Flags & SFLAG_DS_ONSCREEN) {
3949             GLint old_binding = 0;
3950
3951             TRACE("(%p) Copying onscreen depth buffer to depth texture\n", This);
3952
3953             ENTER_GL();
3954
3955             if (!device->depth_blt_texture) {
3956                 glGenTextures(1, &device->depth_blt_texture);
3957             }
3958
3959             /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
3960              * directly on the FBO texture. That's because we need to flip. */
3961             GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
3962             glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
3963             glBindTexture(GL_TEXTURE_2D, device->depth_blt_texture);
3964             glCopyTexImage2D(This->glDescription.target,
3965                     This->glDescription.level,
3966                     This->glDescription.glFormatInternal,
3967                     0,
3968                     0,
3969                     This->currentDesc.Width,
3970                     This->currentDesc.Height,
3971                     0);
3972             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3973             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3974             glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
3975             glBindTexture(GL_TEXTURE_2D, old_binding);
3976
3977             /* Setup the destination */
3978             if (!device->depth_blt_rb) {
3979                 GL_EXTCALL(glGenRenderbuffersEXT(1, &device->depth_blt_rb));
3980                 checkGLcall("glGenRenderbuffersEXT");
3981             }
3982             if (device->depth_blt_rb_w != This->currentDesc.Width
3983                     || device->depth_blt_rb_h != This->currentDesc.Height) {
3984                 GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, device->depth_blt_rb));
3985                 checkGLcall("glBindRenderbufferEXT");
3986                 GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, This->currentDesc.Width, This->currentDesc.Height));
3987                 checkGLcall("glRenderbufferStorageEXT");
3988                 device->depth_blt_rb_w = This->currentDesc.Width;
3989                 device->depth_blt_rb_h = This->currentDesc.Height;
3990             }
3991
3992             bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->dst_fbo);
3993             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, device->depth_blt_rb));
3994             checkGLcall("glFramebufferRenderbufferEXT");
3995             attach_depth_stencil_fbo(device, GL_FRAMEBUFFER_EXT, iface, FALSE);
3996
3997             /* Do the actual blit */
3998             depth_blt((IWineD3DDevice *)device, device->depth_blt_texture, This->currentDesc.Width, This->currentDesc.Height);
3999             checkGLcall("depth_blt");
4000
4001             if (device->render_offscreen) {
4002                 bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->fbo);
4003             } else {
4004                 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
4005                 checkGLcall("glBindFramebuffer()");
4006             }
4007
4008             LEAVE_GL();
4009         } else {
4010             FIXME("No up to date depth stencil location\n");
4011         }
4012     } else if (location == SFLAG_DS_ONSCREEN) {
4013         if (This->Flags & SFLAG_DS_OFFSCREEN) {
4014             TRACE("(%p) Copying depth texture to onscreen depth buffer\n", This);
4015
4016             ENTER_GL();
4017
4018             GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
4019             checkGLcall("glBindFramebuffer()");
4020             depth_blt((IWineD3DDevice *)device, This->glDescription.textureName, This->currentDesc.Width, This->currentDesc.Height);
4021             checkGLcall("depth_blt");
4022
4023             if (device->render_offscreen) {
4024                 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, device->activeContext->fbo));
4025                 checkGLcall("glBindFramebuffer()");
4026             }
4027
4028             LEAVE_GL();
4029         } else {
4030             FIXME("No up to date depth stencil location\n");
4031         }
4032     } else {
4033         ERR("(%p) Invalid location (%#x) specified\n", This, location);
4034     }
4035
4036     This->Flags |= location;
4037 }
4038
4039 static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DWORD flag, BOOL persistent) {
4040     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4041     IWineD3DBaseTexture *texture;
4042     IWineD3DSurfaceImpl *overlay;
4043
4044     TRACE("(%p)->(%s, %s)\n", iface,
4045           flag == SFLAG_INSYSMEM ? "SFLAG_INSYSMEM" : flag == SFLAG_INDRAWABLE ? "SFLAG_INDRAWABLE" : "SFLAG_INTEXTURE",
4046           persistent ? "TRUE" : "FALSE");
4047
4048     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4049         IWineD3DSwapChain *swapchain = NULL;
4050
4051         if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
4052             TRACE("Surface %p is an onscreen surface\n", iface);
4053
4054             IWineD3DSwapChain_Release(swapchain);
4055         } else {
4056             /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. */
4057             if (flag & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE)) flag |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
4058         }
4059     }
4060
4061     if(persistent) {
4062         if((This->Flags & SFLAG_INTEXTURE) && !(flag & SFLAG_INTEXTURE)) {
4063             if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
4064                 TRACE("Passing to container\n");
4065                 IWineD3DBaseTexture_SetDirty(texture, TRUE);
4066                 IWineD3DBaseTexture_Release(texture);
4067             }
4068         }
4069         This->Flags &= ~SFLAG_LOCATIONS;
4070         This->Flags |= flag;
4071
4072         /* Redraw emulated overlays, if any */
4073         if(flag & SFLAG_INDRAWABLE && !list_empty(&This->overlays)) {
4074             LIST_FOR_EACH_ENTRY(overlay, &This->overlays, IWineD3DSurfaceImpl, overlay_entry) {
4075                 IWineD3DSurface_DrawOverlay((IWineD3DSurface *) overlay);
4076             }
4077         }
4078     } else {
4079         if((This->Flags & SFLAG_INTEXTURE) && (flag & SFLAG_INTEXTURE)) {
4080             if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
4081                 TRACE("Passing to container\n");
4082                 IWineD3DBaseTexture_SetDirty(texture, TRUE);
4083                 IWineD3DBaseTexture_Release(texture);
4084             }
4085         }
4086         This->Flags &= ~flag;
4087     }
4088 }
4089
4090 struct coords {
4091     GLfloat x, y, z;
4092 };
4093
4094 static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) {
4095     struct coords coords[4];
4096     RECT rect;
4097     IWineD3DSwapChain *swapchain = NULL;
4098     IWineD3DBaseTexture *texture = NULL;
4099     HRESULT hr;
4100     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4101
4102     if(rect_in) {
4103         rect = *rect_in;
4104     } else {
4105         rect.left = 0;
4106         rect.top = 0;
4107         rect.right = This->currentDesc.Width;
4108         rect.bottom = This->currentDesc.Height;
4109     }
4110
4111     ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT);
4112     ENTER_GL();
4113
4114     if(This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB) {
4115         glEnable(GL_TEXTURE_RECTANGLE_ARB);
4116         checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
4117         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, This->glDescription.textureName);
4118         checkGLcall("GL_TEXTURE_RECTANGLE_ARB, This->glDescription.textureName)");
4119         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4120         checkGLcall("glTexParameteri");
4121         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4122         checkGLcall("glTexParameteri");
4123
4124         coords[0].x = rect.left;
4125         coords[0].z = 0;
4126
4127         coords[1].x = rect.left;
4128         coords[1].z = 0;
4129
4130         coords[2].x = rect.right;
4131         coords[2].z = 0;
4132
4133         coords[3].x = rect.right;
4134         coords[3].z = 0;
4135
4136         coords[0].y = rect.top;
4137         coords[1].y = rect.bottom;
4138         coords[2].y = rect.bottom;
4139         coords[3].y = rect.top;
4140     } else if(This->glDescription.target == GL_TEXTURE_2D) {
4141         glEnable(GL_TEXTURE_2D);
4142         checkGLcall("glEnable(GL_TEXTURE_2D)");
4143         glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
4144         checkGLcall("GL_TEXTURE_2D, This->glDescription.textureName)");
4145         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4146         checkGLcall("glTexParameteri");
4147         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4148         checkGLcall("glTexParameteri");
4149
4150         coords[0].x = (float)rect.left   / This->pow2Width;
4151         coords[0].z = 0;
4152
4153         coords[1].x = (float)rect.left   / This->pow2Width;
4154         coords[1].z = 0;
4155
4156         coords[2].x = (float)rect.right  / This->pow2Width;
4157         coords[2].z = 0;
4158
4159         coords[3].x = (float)rect.right  / This->pow2Width;
4160         coords[3].z = 0;
4161
4162         coords[0].y = (float)rect.top    / This->pow2Height;
4163         coords[1].y = (float)rect.bottom / This->pow2Height;
4164         coords[2].y = (float)rect.bottom / This->pow2Height;
4165         coords[3].y = (float)rect.top    / This->pow2Height;
4166     } else {
4167         /* Must be a cube map */
4168         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
4169         checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
4170         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, This->glDescription.textureName);
4171         checkGLcall("GL_TEXTURE_CUBE_MAP_ARB, This->glDescription.textureName)");
4172         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4173         checkGLcall("glTexParameteri");
4174         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4175         checkGLcall("glTexParameteri");
4176
4177         switch(This->glDescription.target) {
4178             case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4179                 coords[0].x =  1;   coords[0].y = -1;   coords[0].z =  1;
4180                 coords[1].x =  1;   coords[1].y =  1;   coords[1].z =  1;
4181                 coords[2].x =  1;   coords[2].y =  1;   coords[2].z = -1;
4182                 coords[3].x =  1;   coords[3].y = -1;   coords[3].z = -1;
4183                 break;
4184
4185             case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4186                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z =  1;
4187                 coords[1].x = -1;   coords[1].y =  1;   coords[1].z =  1;
4188                 coords[2].x = -1;   coords[2].y =  1;   coords[2].z = -1;
4189                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z = -1;
4190                 break;
4191
4192             case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4193                 coords[0].x = -1;   coords[0].y =  1;   coords[0].z =  1;
4194                 coords[1].x =  1;   coords[1].y =  1;   coords[1].z =  1;
4195                 coords[2].x =  1;   coords[2].y =  1;   coords[2].z = -1;
4196                 coords[3].x = -1;   coords[3].y =  1;   coords[3].z = -1;
4197                 break;
4198
4199             case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4200                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z =  1;
4201                 coords[1].x =  1;   coords[1].y = -1;   coords[1].z =  1;
4202                 coords[2].x =  1;   coords[2].y = -1;   coords[2].z = -1;
4203                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z = -1;
4204                 break;
4205
4206             case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4207                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z =  1;
4208                 coords[1].x =  1;   coords[1].y = -1;   coords[1].z =  1;
4209                 coords[2].x =  1;   coords[2].y = -1;   coords[2].z =  1;
4210                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z =  1;
4211                 break;
4212
4213             case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4214                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z = -1;
4215                 coords[1].x =  1;   coords[1].y = -1;   coords[1].z = -1;
4216                 coords[2].x =  1;   coords[2].y = -1;   coords[2].z = -1;
4217                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z = -1;
4218                 break;
4219
4220             default:
4221                 ERR("Unexpected texture target\n");
4222                 LEAVE_GL();
4223                 return;
4224         }
4225     }
4226
4227     glBegin(GL_QUADS);
4228     glTexCoord3fv(&coords[0].x);
4229     glVertex2i(rect.left, device->render_offscreen ? rect.bottom : rect.top);
4230
4231     glTexCoord3fv(&coords[1].x);
4232     glVertex2i(rect.left, device->render_offscreen ? rect.top : rect.bottom);
4233
4234     glTexCoord3fv(&coords[2].x);
4235     glVertex2i(rect.right, device->render_offscreen ? rect.top : rect.bottom);
4236
4237     glTexCoord3fv(&coords[3].x);
4238     glVertex2i(rect.right, device->render_offscreen ? rect.bottom : rect.top);
4239     glEnd();
4240     checkGLcall("glEnd");
4241
4242     if(This->glDescription.target != GL_TEXTURE_2D) {
4243         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
4244         checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
4245     } else {
4246         glDisable(GL_TEXTURE_2D);
4247         checkGLcall("glDisable(GL_TEXTURE_2D)");
4248     }
4249     LEAVE_GL();
4250
4251     hr = IWineD3DSurface_GetContainer((IWineD3DSurface*)This, &IID_IWineD3DSwapChain, (void **) &swapchain);
4252     if(hr == WINED3D_OK && swapchain) {
4253         /* Make sure to flush the buffers. This is needed in apps like Red Alert II and Tiberian SUN that use multiple WGL contexts. */
4254         if(((IWineD3DSwapChainImpl*)swapchain)->frontBuffer == (IWineD3DSurface*)This ||
4255            ((IWineD3DSwapChainImpl*)swapchain)->num_contexts >= 2)
4256             glFlush();
4257
4258         IWineD3DSwapChain_Release(swapchain);
4259     } else {
4260         /* We changed the filtering settings on the texture. Inform the container about this to get the filters
4261          * reset properly next draw
4262          */
4263         hr = IWineD3DSurface_GetContainer((IWineD3DSurface*)This, &IID_IWineD3DBaseTexture, (void **) &texture);
4264         if(hr == WINED3D_OK && texture) {
4265             ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
4266             ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
4267             ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE;
4268             IWineD3DBaseTexture_Release(texture);
4269         }
4270     }
4271 }
4272
4273 /*****************************************************************************
4274  * IWineD3DSurface::LoadLocation
4275  *
4276  * Copies the current surface data from wherever it is to the requested
4277  * location. The location is one of the surface flags, SFLAG_INSYSMEM,
4278  * SFLAG_INTEXTURE and SFLAG_INDRAWABLE. When the surface is current in
4279  * multiple locations, the gl texture is preferred over the drawable, which is
4280  * preferred over system memory. The PBO counts as system memory. If rect is
4281  * not NULL, only the specified rectangle is copied (only supported for
4282  * sysmem<->drawable copies at the moment). If rect is NULL, the destination
4283  * location is marked up to date after the copy.
4284  *
4285  * Parameters:
4286  *  flag: Surface location flag to be updated
4287  *  rect: rectangle to be copied
4288  *
4289  * Returns:
4290  *  WINED3D_OK on success
4291  *  WINED3DERR_DEVICELOST on an internal error
4292  *
4293  *****************************************************************************/
4294 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, DWORD flag, const RECT *rect) {
4295     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4296     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4297     IWineD3DSwapChain *swapchain = NULL;
4298     GLenum format, internal, type;
4299     CONVERT_TYPES convert;
4300     int bpp;
4301     int width, pitch, outpitch;
4302     BYTE *mem;
4303
4304     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4305         if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
4306             TRACE("Surface %p is an onscreen surface\n", iface);
4307
4308             IWineD3DSwapChain_Release(swapchain);
4309         } else {
4310             /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets.
4311              * Prefer SFLAG_INTEXTURE. */
4312             if (flag == SFLAG_INDRAWABLE) flag = SFLAG_INTEXTURE;
4313         }
4314     }
4315
4316     TRACE("(%p)->(%s, %p)\n", iface,
4317           flag == SFLAG_INSYSMEM ? "SFLAG_INSYSMEM" : flag == SFLAG_INDRAWABLE ? "SFLAG_INDRAWABLE" : "SFLAG_INTEXTURE",
4318           rect);
4319     if(rect) {
4320         TRACE("Rectangle: (%d,%d)-(%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom);
4321     }
4322
4323     if(This->Flags & flag) {
4324         TRACE("Location already up to date\n");
4325         return WINED3D_OK;
4326     }
4327
4328     if(!(This->Flags & SFLAG_LOCATIONS)) {
4329         ERR("Surface does not have any up to date location\n");
4330         This->Flags |= SFLAG_LOST;
4331         return WINED3DERR_DEVICELOST;
4332     }
4333
4334     if(flag == SFLAG_INSYSMEM) {
4335         surface_prepare_system_memory(This);
4336
4337         /* Download the surface to system memory */
4338         if(This->Flags & SFLAG_INTEXTURE) {
4339             if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4340             surface_bind_and_dirtify(This);
4341
4342             surface_download_data(This);
4343         } else {
4344             read_from_framebuffer(This, rect,
4345                                   This->resource.allocatedMemory,
4346                                   IWineD3DSurface_GetPitch(iface));
4347         }
4348     } else if(flag == SFLAG_INDRAWABLE) {
4349         if(This->Flags & SFLAG_INTEXTURE) {
4350             surface_blt_to_drawable(This, rect);
4351         } else {
4352             d3dfmt_get_conv(This, TRUE /* We need color keying */, FALSE /* We won't use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
4353
4354             /* The width is in 'length' not in bytes */
4355             width = This->currentDesc.Width;
4356             pitch = IWineD3DSurface_GetPitch(iface);
4357
4358             /* Don't use PBOs for converted surfaces. During PBO conversion we look at SFLAG_CONVERTED
4359              * but it isn't set (yet) in all cases it is getting called. */
4360             if((convert != NO_CONVERSION) && (This->Flags & SFLAG_PBO)) {
4361                 TRACE("Removing the pbo attached to surface %p\n", This);
4362                 surface_remove_pbo(This);
4363             }
4364
4365             if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
4366                 int height = This->currentDesc.Height;
4367
4368                 /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
4369                 outpitch = width * bpp;
4370                 outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
4371
4372                 mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
4373                 if(!mem) {
4374                     ERR("Out of memory %d, %d!\n", outpitch, height);
4375                     return WINED3DERR_OUTOFVIDEOMEMORY;
4376                 }
4377                 d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
4378
4379                 This->Flags |= SFLAG_CONVERTED;
4380             } else {
4381                 This->Flags &= ~SFLAG_CONVERTED;
4382                 mem = This->resource.allocatedMemory;
4383             }
4384
4385             flush_to_framebuffer_drawpixels(This, format, type, bpp, mem);
4386
4387             /* Don't delete PBO memory */
4388             if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO))
4389                 HeapFree(GetProcessHeap(), 0, mem);
4390         }
4391     } else /* if(flag == SFLAG_INTEXTURE) */ {
4392         if (This->Flags & SFLAG_INDRAWABLE) {
4393             read_from_framebuffer_texture(This);
4394         } else { /* Upload from system memory */
4395             d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
4396
4397             if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4398             surface_bind_and_dirtify(This);
4399             ENTER_GL();
4400
4401             /* The only place where LoadTexture() might get called when isInDraw=1
4402              * is ActivateContext where lastActiveRenderTarget is preloaded.
4403              */
4404             if(iface == device->lastActiveRenderTarget && device->isInDraw)
4405                 ERR("Reading back render target but SFLAG_INDRAWABLE not set\n");
4406
4407             /* Otherwise: System memory copy must be most up to date */
4408
4409             if(This->CKeyFlags & WINEDDSD_CKSRCBLT) {
4410                 This->Flags |= SFLAG_GLCKEY;
4411                 This->glCKey = This->SrcBltCKey;
4412             }
4413             else This->Flags &= ~SFLAG_GLCKEY;
4414
4415             /* The width is in 'length' not in bytes */
4416             width = This->currentDesc.Width;
4417             pitch = IWineD3DSurface_GetPitch(iface);
4418
4419             /* Don't use PBOs for converted surfaces. During PBO conversion we look at SFLAG_CONVERTED
4420              * but it isn't set (yet) in all cases it is getting called. */
4421             if((convert != NO_CONVERSION) && (This->Flags & SFLAG_PBO)) {
4422                 TRACE("Removing the pbo attached to surface %p\n", This);
4423                 surface_remove_pbo(This);
4424             }
4425
4426             if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
4427                 int height = This->currentDesc.Height;
4428
4429                 /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
4430                 outpitch = width * bpp;
4431                 outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
4432
4433                 mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
4434                 if(!mem) {
4435                     ERR("Out of memory %d, %d!\n", outpitch, height);
4436                     return WINED3DERR_OUTOFVIDEOMEMORY;
4437                 }
4438                 d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
4439
4440                 This->Flags |= SFLAG_CONVERTED;
4441             } else if( (This->resource.format == WINED3DFMT_P8) && (GL_SUPPORT(EXT_PALETTED_TEXTURE) || GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) ) {
4442                 d3dfmt_p8_upload_palette(iface, convert);
4443                 This->Flags &= ~SFLAG_CONVERTED;
4444                 mem = This->resource.allocatedMemory;
4445             } else {
4446                 This->Flags &= ~SFLAG_CONVERTED;
4447                 mem = This->resource.allocatedMemory;
4448             }
4449
4450             /* Make sure the correct pitch is used */
4451             glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
4452
4453             if ((This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
4454                 TRACE("non power of two support\n");
4455                 if(!(This->Flags & SFLAG_ALLOCATED)) {
4456                     surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
4457                 }
4458                 if (mem || (This->Flags & SFLAG_PBO)) {
4459                     surface_upload_data(This, internal, This->currentDesc.Width, This->currentDesc.Height, format, type, mem);
4460                 }
4461             } else {
4462                 /* When making the realloc conditional, keep in mind that GL_APPLE_client_storage may be in use, and This->resource.allocatedMemory
4463                  * changed. So also keep track of memory changes. In this case the texture has to be reallocated
4464                  */
4465                 if(!(This->Flags & SFLAG_ALLOCATED)) {
4466                     surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
4467                 }
4468                 if (mem || (This->Flags & SFLAG_PBO)) {
4469                     surface_upload_data(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
4470                 }
4471             }
4472
4473             /* Restore the default pitch */
4474             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
4475             LEAVE_GL();
4476
4477             /* Don't delete PBO memory */
4478             if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO))
4479                 HeapFree(GetProcessHeap(), 0, mem);
4480         }
4481     }
4482
4483     if(rect == NULL) {
4484         This->Flags |= flag;
4485     }
4486
4487     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !swapchain
4488             && (This->Flags & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE))) {
4489         /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. */
4490         This->Flags |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
4491     }
4492
4493     return WINED3D_OK;
4494 }
4495
4496 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
4497     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4498     IWineD3DSwapChain *swapchain = NULL;
4499
4500     /* Update the drawable size method */
4501     if(container) {
4502         IWineD3DBase_QueryInterface(container, &IID_IWineD3DSwapChain, (void **) &swapchain);
4503     }
4504     if(swapchain) {
4505         This->get_drawable_size = get_drawable_size_swapchain;
4506         IWineD3DSwapChain_Release(swapchain);
4507     } else if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
4508         switch(wined3d_settings.offscreen_rendering_mode) {
4509             case ORM_FBO:        This->get_drawable_size = get_drawable_size_fbo;        break;
4510             case ORM_PBUFFER:    This->get_drawable_size = get_drawable_size_pbuffer;    break;
4511             case ORM_BACKBUFFER: This->get_drawable_size = get_drawable_size_backbuffer; break;
4512         }
4513     }
4514
4515     return IWineD3DBaseSurfaceImpl_SetContainer(iface, container);
4516 }
4517
4518 static WINED3DSURFTYPE WINAPI IWineD3DSurfaceImpl_GetImplType(IWineD3DSurface *iface) {
4519     return SURFACE_OPENGL;
4520 }
4521
4522 static HRESULT WINAPI IWineD3DSurfaceImpl_DrawOverlay(IWineD3DSurface *iface) {
4523     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4524     HRESULT hr;
4525
4526     /* If there's no destination surface there is nothing to do */
4527     if(!This->overlay_dest) return WINED3D_OK;
4528
4529     /* Blt calls ModifyLocation on the dest surface, which in turn calls DrawOverlay to
4530      * update the overlay. Prevent an endless recursion
4531      */
4532     if(This->overlay_dest->Flags & SFLAG_INOVERLAYDRAW) {
4533         return WINED3D_OK;
4534     }
4535     This->overlay_dest->Flags |= SFLAG_INOVERLAYDRAW;
4536     hr = IWineD3DSurfaceImpl_Blt((IWineD3DSurface *) This->overlay_dest, &This->overlay_destrect,
4537                                  iface, &This->overlay_srcrect, WINEDDBLT_WAIT,
4538                                  NULL, WINED3DTEXF_LINEAR);
4539     This->overlay_dest->Flags &= ~SFLAG_INOVERLAYDRAW;
4540
4541     return hr;
4542 }
4543
4544 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
4545 {
4546     /* IUnknown */
4547     IWineD3DBaseSurfaceImpl_QueryInterface,
4548     IWineD3DBaseSurfaceImpl_AddRef,
4549     IWineD3DSurfaceImpl_Release,
4550     /* IWineD3DResource */
4551     IWineD3DBaseSurfaceImpl_GetParent,
4552     IWineD3DBaseSurfaceImpl_GetDevice,
4553     IWineD3DBaseSurfaceImpl_SetPrivateData,
4554     IWineD3DBaseSurfaceImpl_GetPrivateData,
4555     IWineD3DBaseSurfaceImpl_FreePrivateData,
4556     IWineD3DBaseSurfaceImpl_SetPriority,
4557     IWineD3DBaseSurfaceImpl_GetPriority,
4558     IWineD3DSurfaceImpl_PreLoad,
4559     IWineD3DSurfaceImpl_UnLoad,
4560     IWineD3DBaseSurfaceImpl_GetType,
4561     /* IWineD3DSurface */
4562     IWineD3DBaseSurfaceImpl_GetContainer,
4563     IWineD3DBaseSurfaceImpl_GetDesc,
4564     IWineD3DSurfaceImpl_LockRect,
4565     IWineD3DSurfaceImpl_UnlockRect,
4566     IWineD3DSurfaceImpl_GetDC,
4567     IWineD3DSurfaceImpl_ReleaseDC,
4568     IWineD3DSurfaceImpl_Flip,
4569     IWineD3DSurfaceImpl_Blt,
4570     IWineD3DBaseSurfaceImpl_GetBltStatus,
4571     IWineD3DBaseSurfaceImpl_GetFlipStatus,
4572     IWineD3DBaseSurfaceImpl_IsLost,
4573     IWineD3DBaseSurfaceImpl_Restore,
4574     IWineD3DSurfaceImpl_BltFast,
4575     IWineD3DBaseSurfaceImpl_GetPalette,
4576     IWineD3DBaseSurfaceImpl_SetPalette,
4577     IWineD3DSurfaceImpl_RealizePalette,
4578     IWineD3DBaseSurfaceImpl_SetColorKey,
4579     IWineD3DBaseSurfaceImpl_GetPitch,
4580     IWineD3DSurfaceImpl_SetMem,
4581     IWineD3DBaseSurfaceImpl_SetOverlayPosition,
4582     IWineD3DBaseSurfaceImpl_GetOverlayPosition,
4583     IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder,
4584     IWineD3DBaseSurfaceImpl_UpdateOverlay,
4585     IWineD3DBaseSurfaceImpl_SetClipper,
4586     IWineD3DBaseSurfaceImpl_GetClipper,
4587     /* Internal use: */
4588     IWineD3DSurfaceImpl_AddDirtyRect,
4589     IWineD3DSurfaceImpl_LoadTexture,
4590     IWineD3DSurfaceImpl_BindTexture,
4591     IWineD3DSurfaceImpl_SaveSnapshot,
4592     IWineD3DSurfaceImpl_SetContainer,
4593     IWineD3DSurfaceImpl_SetGlTextureDesc,
4594     IWineD3DSurfaceImpl_GetGlDesc,
4595     IWineD3DSurfaceImpl_GetData,
4596     IWineD3DSurfaceImpl_SetFormat,
4597     IWineD3DSurfaceImpl_PrivateSetup,
4598     IWineD3DSurfaceImpl_ModifyLocation,
4599     IWineD3DSurfaceImpl_LoadLocation,
4600     IWineD3DSurfaceImpl_GetImplType,
4601     IWineD3DSurfaceImpl_DrawOverlay
4602 };
4603 #undef GLINFO_LOCATION
4604
4605 #define GLINFO_LOCATION device->adapter->gl_info
4606 static HRESULT ffp_blit_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
4607 static void ffp_blit_free(IWineD3DDevice *iface) { }
4608
4609 static HRESULT ffp_blit_set(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height) {
4610     glEnable(textype);
4611     checkGLcall("glEnable(textype)");
4612     return WINED3D_OK;
4613 }
4614
4615 static void ffp_blit_unset(IWineD3DDevice *iface) {
4616     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface;
4617     glDisable(GL_TEXTURE_2D);
4618     checkGLcall("glDisable(GL_TEXTURE_2D)");
4619     if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
4620         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
4621         checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
4622     }
4623     if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
4624         glDisable(GL_TEXTURE_RECTANGLE_ARB);
4625         checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
4626     }
4627 }
4628
4629 static BOOL ffp_blit_conv_supported(WINED3DFORMAT fmt) {
4630     TRACE("Checking blit format support for format %s: [FAILED]\n", debug_d3dformat(fmt));
4631     return FALSE;
4632 }
4633
4634 const struct blit_shader ffp_blit =  {
4635     ffp_blit_alloc,
4636     ffp_blit_free,
4637     ffp_blit_set,
4638     ffp_blit_unset,
4639     ffp_blit_conv_supported
4640 };