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