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