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