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