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