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