wined3d: Get rid of two dead render target lock mode options.
[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                 IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* partial texture loading not supported yet */);
1519                 /* drop through */
1520
1521             case RTL_AUTO:
1522             case RTL_READDRAW:
1523                 IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, fullsurface ? NULL : &This->dirtyRect);
1524                 break;
1525         }
1526
1527         if(!fullsurface) {
1528             /* Partial rectangle tracking is not commonly implemented, it is only done for render targets. Overwrite
1529              * the flags to bring them back into a sane state. INSYSMEM was set before to tell LoadLocation where
1530              * to read the rectangle from. Indrawable is set because all modifications from the partial sysmem copy
1531              * are written back to the drawable, thus the surface is merged again in the drawable. The sysmem copy is
1532              * not fully up to date because only a subrectangle was read in LockRect.
1533              */
1534             This->Flags &= ~SFLAG_INSYSMEM;
1535             This->Flags |= SFLAG_INDRAWABLE;
1536         }
1537
1538         This->dirtyRect.left   = This->currentDesc.Width;
1539         This->dirtyRect.top    = This->currentDesc.Height;
1540         This->dirtyRect.right  = 0;
1541         This->dirtyRect.bottom = 0;
1542     } else if(iface == myDevice->stencilBufferTarget) {
1543         FIXME("Depth Stencil buffer locking is not implemented\n");
1544     } else {
1545         /* The rest should be a normal texture */
1546         IWineD3DBaseTextureImpl *impl;
1547         /* Check if the texture is bound, if yes dirtify the sampler to force a re-upload of the texture
1548          * Can't load the texture here because PreLoad may destroy and recreate the gl texture, so sampler
1549          * states need resetting
1550          */
1551         if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) {
1552             if(impl->baseTexture.bindCount) {
1553                 IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler));
1554             }
1555             IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl);
1556         }
1557     }
1558
1559     unlock_end:
1560     This->Flags &= ~SFLAG_LOCKED;
1561     memset(&This->lockedRect, 0, sizeof(RECT));
1562
1563     /* Overlays have to be redrawn manually after changes with the GL implementation */
1564     if(This->overlay_dest) {
1565         IWineD3DSurface_DrawOverlay(iface);
1566     }
1567     return WINED3D_OK;
1568 }
1569
1570 static HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC)
1571 {
1572     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1573     WINED3DLOCKED_RECT lock;
1574     HRESULT hr;
1575     RGBQUAD col[256];
1576
1577     TRACE("(%p)->(%p)\n",This,pHDC);
1578
1579     if(This->Flags & SFLAG_USERPTR) {
1580         ERR("Not supported on surfaces with an application-provided surfaces\n");
1581         return WINEDDERR_NODC;
1582     }
1583
1584     /* Give more detailed info for ddraw */
1585     if (This->Flags & SFLAG_DCINUSE)
1586         return WINEDDERR_DCALREADYCREATED;
1587
1588     /* Can't GetDC if the surface is locked */
1589     if (This->Flags & SFLAG_LOCKED)
1590         return WINED3DERR_INVALIDCALL;
1591
1592     /* According to Direct3D9 docs, only these formats are supported */
1593     if (((IWineD3DImpl *)This->resource.wineD3DDevice->wineD3D)->dxVersion > 7) {
1594         if (This->resource.format_desc->format != WINED3DFMT_R5G6B5
1595                 && This->resource.format_desc->format != WINED3DFMT_X1R5G5B5
1596                 && This->resource.format_desc->format != WINED3DFMT_R8G8B8
1597                 && This->resource.format_desc->format != WINED3DFMT_X8R8G8B8)
1598             return WINED3DERR_INVALIDCALL;
1599     }
1600
1601     memset(&lock, 0, sizeof(lock)); /* To be sure */
1602
1603     /* Create a DIB section if there isn't a hdc yet */
1604     if(!This->hDC) {
1605         IWineD3DBaseSurfaceImpl_CreateDIBSection(iface);
1606         if(This->Flags & SFLAG_CLIENT) {
1607             surface_internal_preload(iface, SRGB_RGB);
1608         }
1609
1610         /* Use the dib section from now on if we are not using a PBO */
1611         if(!(This->Flags & SFLAG_PBO))
1612             This->resource.allocatedMemory = This->dib.bitmap_data;
1613     }
1614
1615     /* Lock the surface */
1616     hr = IWineD3DSurface_LockRect(iface,
1617                                   &lock,
1618                                   NULL,
1619                                   0);
1620
1621     if(This->Flags & SFLAG_PBO) {
1622         /* Sync the DIB with the PBO. This can't be done earlier because LockRect activates the allocatedMemory */
1623         memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->dib.bitmap_size);
1624     }
1625
1626     if(FAILED(hr)) {
1627         ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
1628         /* keep the dib section */
1629         return hr;
1630     }
1631
1632     if (This->resource.format_desc->format == WINED3DFMT_P8
1633             || This->resource.format_desc->format == WINED3DFMT_A8P8)
1634     {
1635         /* GetDC on palettized formats is unsupported in D3D9, and the method is missing in
1636             D3D8, so this should only be used for DX <=7 surfaces (with non-device palettes) */
1637         unsigned int n;
1638         const PALETTEENTRY *pal = NULL;
1639
1640         if(This->palette) {
1641             pal = This->palette->palents;
1642         } else {
1643             IWineD3DSurfaceImpl *dds_primary;
1644             IWineD3DSwapChainImpl *swapchain;
1645             swapchain = (IWineD3DSwapChainImpl *)This->resource.wineD3DDevice->swapchains[0];
1646             dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer;
1647             if (dds_primary && dds_primary->palette)
1648                 pal = dds_primary->palette->palents;
1649         }
1650
1651         if (pal) {
1652             for (n=0; n<256; n++) {
1653                 col[n].rgbRed   = pal[n].peRed;
1654                 col[n].rgbGreen = pal[n].peGreen;
1655                 col[n].rgbBlue  = pal[n].peBlue;
1656                 col[n].rgbReserved = 0;
1657             }
1658             SetDIBColorTable(This->hDC, 0, 256, col);
1659         }
1660     }
1661
1662     *pHDC = This->hDC;
1663     TRACE("returning %p\n",*pHDC);
1664     This->Flags |= SFLAG_DCINUSE;
1665
1666     return WINED3D_OK;
1667 }
1668
1669 static HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC)
1670 {
1671     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1672
1673     TRACE("(%p)->(%p)\n",This,hDC);
1674
1675     if (!(This->Flags & SFLAG_DCINUSE))
1676         return WINEDDERR_NODC;
1677
1678     if (This->hDC !=hDC) {
1679         WARN("Application tries to release an invalid DC(%p), surface dc is %p\n", hDC, This->hDC);
1680         return WINEDDERR_NODC;
1681     }
1682
1683     if((This->Flags & SFLAG_PBO) && This->resource.allocatedMemory) {
1684         /* Copy the contents of the DIB over to the PBO */
1685         memcpy(This->resource.allocatedMemory, This->dib.bitmap_data, This->dib.bitmap_size);
1686     }
1687
1688     /* we locked first, so unlock now */
1689     IWineD3DSurface_UnlockRect(iface);
1690
1691     This->Flags &= ~SFLAG_DCINUSE;
1692
1693     return WINED3D_OK;
1694 }
1695
1696 /* ******************************************************
1697    IWineD3DSurface Internal (No mapping to directx api) parts follow
1698    ****************************************************** */
1699
1700 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) {
1701     BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & WINEDDSD_CKSRCBLT);
1702     const struct GlPixelFormatDesc *glDesc = This->resource.format_desc;
1703     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1704
1705     /* Default values: From the surface */
1706     *format = glDesc->glFormat;
1707     *type = glDesc->glType;
1708     *convert = NO_CONVERSION;
1709     *target_bpp = glDesc->byte_count;
1710
1711     if(srgb_mode) {
1712         *internal = glDesc->glGammaInternal;
1713     }
1714     else if (This->resource.usage & WINED3DUSAGE_RENDERTARGET
1715             && !(This->Flags & SFLAG_SWAPCHAIN))
1716     {
1717         *internal = glDesc->rtInternal;
1718     } else {
1719         *internal = glDesc->glInternal;
1720     }
1721
1722     /* Ok, now look if we have to do any conversion */
1723     switch(This->resource.format_desc->format)
1724     {
1725         case WINED3DFMT_P8:
1726             /* ****************
1727                 Paletted Texture
1728                 **************** */
1729
1730              /* Use conversion when the paletted texture extension OR fragment shaders are available. When either
1731              * of the two is available make sure texturing is requested as neither of the two works in
1732              * conjunction with calls like glDraw-/glReadPixels. Further also use conversion in case of color keying.
1733              * Paletted textures can be emulated using shaders but only do that for 2D purposes e.g. situations
1734              * in which the main render target uses p8. Some games like GTA Vice City use P8 for texturing which
1735              * conflicts with this.
1736              */
1737             if( !(GL_SUPPORT(EXT_PALETTED_TEXTURE) ||
1738                   (GL_SUPPORT(ARB_FRAGMENT_PROGRAM) &&
1739                    device->render_targets &&
1740                    This == (IWineD3DSurfaceImpl*)device->render_targets[0])) ||
1741                 colorkey_active || !use_texturing ) {
1742                 *format = GL_RGBA;
1743                 *internal = GL_RGBA;
1744                 *type = GL_UNSIGNED_BYTE;
1745                 *target_bpp = 4;
1746                 if(colorkey_active) {
1747                     *convert = CONVERT_PALETTED_CK;
1748                 } else {
1749                     *convert = CONVERT_PALETTED;
1750                 }
1751             }
1752             else if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
1753                 *format = GL_ALPHA;
1754                 *type = GL_UNSIGNED_BYTE;
1755                 *target_bpp = 1;
1756             }
1757
1758             break;
1759
1760         case WINED3DFMT_R3G3B2:
1761             /* **********************
1762                 GL_UNSIGNED_BYTE_3_3_2
1763                 ********************** */
1764             if (colorkey_active) {
1765                 /* This texture format will never be used.. So do not care about color keying
1766                     up until the point in time it will be needed :-) */
1767                 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1768             }
1769             break;
1770
1771         case WINED3DFMT_R5G6B5:
1772             if (colorkey_active) {
1773                 *convert = CONVERT_CK_565;
1774                 *format = GL_RGBA;
1775                 *internal = GL_RGB5_A1;
1776                 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1777             }
1778             break;
1779
1780         case WINED3DFMT_X1R5G5B5:
1781             if (colorkey_active) {
1782                 *convert = CONVERT_CK_5551;
1783                 *format = GL_BGRA;
1784                 *internal = GL_RGB5_A1;
1785                 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1786             }
1787             break;
1788
1789         case WINED3DFMT_R8G8B8:
1790             if (colorkey_active) {
1791                 *convert = CONVERT_CK_RGB24;
1792                 *format = GL_RGBA;
1793                 *internal = GL_RGBA8;
1794                 *type = GL_UNSIGNED_INT_8_8_8_8;
1795                 *target_bpp = 4;
1796             }
1797             break;
1798
1799         case WINED3DFMT_X8R8G8B8:
1800             if (colorkey_active) {
1801                 *convert = CONVERT_RGB32_888;
1802                 *format = GL_RGBA;
1803                 *internal = GL_RGBA8;
1804                 *type = GL_UNSIGNED_INT_8_8_8_8;
1805             }
1806             break;
1807
1808         case WINED3DFMT_R8G8_SNORM:
1809             if (GL_SUPPORT(NV_TEXTURE_SHADER)) break;
1810             *convert = CONVERT_V8U8;
1811             *format = GL_BGR;
1812             *type = GL_UNSIGNED_BYTE;
1813             *target_bpp = 3;
1814             break;
1815
1816         case WINED3DFMT_L6V5U5:
1817             *convert = CONVERT_L6V5U5;
1818             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1819                 *target_bpp = 3;
1820                 /* Use format and types from table */
1821             } else {
1822                 /* Load it into unsigned R5G6B5, swap L and V channels, and revert that in the shader */
1823                 *target_bpp = 2;
1824                 *format = GL_RGB;
1825                 *type = GL_UNSIGNED_SHORT_5_6_5;
1826             }
1827             break;
1828
1829         case WINED3DFMT_X8L8V8U8:
1830             *convert = CONVERT_X8L8V8U8;
1831             *target_bpp = 4;
1832             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1833                 /* Use formats from gl table. It is a bit unfortunate, but the conversion
1834                  * is needed to set the X format to 255 to get 1.0 for alpha when sampling
1835                  * the texture. OpenGL can't use GL_DSDT8_MAG8_NV as internal format with
1836                  * the needed type and format parameter, so the internal format contains a
1837                  * 4th component, which is returned as alpha
1838                  */
1839             } else {
1840                 *format = GL_BGRA;
1841                 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
1842             }
1843             break;
1844
1845         case WINED3DFMT_R8G8B8A8_SNORM:
1846             if (GL_SUPPORT(NV_TEXTURE_SHADER)) break;
1847             *convert = CONVERT_Q8W8V8U8;
1848             *format = GL_BGRA;
1849             *type = GL_UNSIGNED_BYTE;
1850             *target_bpp = 4;
1851             break;
1852
1853         case WINED3DFMT_R16G16_SNORM:
1854             if (GL_SUPPORT(NV_TEXTURE_SHADER)) break;
1855             *convert = CONVERT_V16U16;
1856             *format = GL_BGR;
1857             *type = GL_UNSIGNED_SHORT;
1858             *target_bpp = 6;
1859             break;
1860
1861         case WINED3DFMT_A4L4:
1862             /* A4L4 exists as an internal gl format, but for some reason there is not
1863              * format+type combination to load it. Thus convert it to A8L8, then load it
1864              * with A4L4 internal, but A8L8 format+type
1865              */
1866             *convert = CONVERT_A4L4;
1867             *format = GL_LUMINANCE_ALPHA;
1868             *type = GL_UNSIGNED_BYTE;
1869             *target_bpp = 2;
1870             break;
1871
1872         case WINED3DFMT_R16G16_UNORM:
1873             *convert = CONVERT_G16R16;
1874             *format = GL_RGB;
1875             *type = GL_UNSIGNED_SHORT;
1876             *target_bpp = 6;
1877             break;
1878
1879         case WINED3DFMT_R16G16_FLOAT:
1880             *convert = CONVERT_R16G16F;
1881             *format = GL_RGB;
1882             *type = GL_HALF_FLOAT_ARB;
1883             *target_bpp = 6;
1884             break;
1885
1886         case WINED3DFMT_R32G32_FLOAT:
1887             *convert = CONVERT_R32G32F;
1888             *format = GL_RGB;
1889             *type = GL_FLOAT;
1890             *target_bpp = 12;
1891             break;
1892
1893         case WINED3DFMT_D15S1:
1894             if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL))
1895             {
1896                 *convert = CONVERT_D15S1;
1897                 *target_bpp = 4;
1898             }
1899             break;
1900
1901         case WINED3DFMT_D24X4S4:
1902             if (GL_SUPPORT(EXT_PACKED_DEPTH_STENCIL))
1903             {
1904                 *convert = CONVERT_D24X4S4;
1905             }
1906             break;
1907
1908         case WINED3DFMT_D24FS8:
1909             if (GL_SUPPORT(ARB_DEPTH_BUFFER_FLOAT))
1910             {
1911                 *convert = CONVERT_D24FS8;
1912                 *target_bpp = 8;
1913             }
1914             break;
1915
1916         default:
1917             break;
1918     }
1919
1920     return WINED3D_OK;
1921 }
1922
1923 static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey)
1924 {
1925     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1926     IWineD3DPaletteImpl *pal = This->palette;
1927     BOOL index_in_alpha = FALSE;
1928     unsigned int i;
1929
1930     /* Old games like StarCraft, C&C, Red Alert and others use P8 render targets.
1931      * Reading back the RGB output each lockrect (each frame as they lock the whole screen)
1932      * is slow. Further RGB->P8 conversion is not possible because palettes can have
1933      * duplicate entries. Store the color key in the unused alpha component to speed the
1934      * download up and to make conversion unneeded. */
1935     index_in_alpha = primary_render_target_is_p8(device);
1936
1937     if (!pal)
1938     {
1939         UINT dxVersion = ((IWineD3DImpl *)device->wineD3D)->dxVersion;
1940
1941         /* In DirectDraw the palette is a property of the surface, there are no such things as device palettes. */
1942         if (dxVersion <= 7)
1943         {
1944             ERR("This code should never get entered for DirectDraw!, expect problems\n");
1945             if (index_in_alpha)
1946             {
1947                 /* Guarantees that memory representation remains correct after sysmem<->texture transfers even if
1948                  * there's no palette at this time. */
1949                 for (i = 0; i < 256; i++) table[i][3] = i;
1950             }
1951         }
1952         else
1953         {
1954             /* Direct3D >= 8 palette usage style: P8 textures use device palettes, palette entry format is A8R8G8B8,
1955              * alpha is stored in peFlags and may be used by the app if D3DPTEXTURECAPS_ALPHAPALETTE device
1956              * capability flag is present (wine does advertise this capability) */
1957             for (i = 0; i < 256; ++i)
1958             {
1959                 table[i][0] = device->palettes[device->currentPalette][i].peRed;
1960                 table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1961                 table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1962                 table[i][3] = device->palettes[device->currentPalette][i].peFlags;
1963             }
1964         }
1965     }
1966     else
1967     {
1968         TRACE("Using surface palette %p\n", pal);
1969         /* Get the surface's palette */
1970         for (i = 0; i < 256; ++i)
1971         {
1972             table[i][0] = pal->palents[i].peRed;
1973             table[i][1] = pal->palents[i].peGreen;
1974             table[i][2] = pal->palents[i].peBlue;
1975
1976             /* When index_in_alpha is set the palette index is stored in the
1977              * alpha component. In case of a readback we can then read
1978              * GL_ALPHA. Color keying is handled in BltOverride using a
1979              * GL_ALPHA_TEST using GL_NOT_EQUAL. In case of index_in_alpha the
1980              * color key itself is passed to glAlphaFunc in other cases the
1981              * alpha component of pixels that should be masked away is set to 0. */
1982             if (index_in_alpha)
1983             {
1984                 table[i][3] = i;
1985             }
1986             else if (colorkey && (i >= This->SrcBltCKey.dwColorSpaceLowValue)
1987                     && (i <= This->SrcBltCKey.dwColorSpaceHighValue))
1988             {
1989                 table[i][3] = 0x00;
1990             }
1991             else if(pal->Flags & WINEDDPCAPS_ALPHA)
1992             {
1993                 table[i][3] = pal->palents[i].peFlags;
1994             }
1995             else
1996             {
1997                 table[i][3] = 0xFF;
1998             }
1999         }
2000     }
2001 }
2002
2003 static HRESULT d3dfmt_convert_surface(const BYTE *src, BYTE *dst, UINT pitch, UINT width,
2004         UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *This)
2005 {
2006     const BYTE *source;
2007     BYTE *dest;
2008     TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert,This);
2009
2010     switch (convert) {
2011         case NO_CONVERSION:
2012         {
2013             memcpy(dst, src, pitch * height);
2014             break;
2015         }
2016         case CONVERT_PALETTED:
2017         case CONVERT_PALETTED_CK:
2018         {
2019             IWineD3DPaletteImpl* pal = This->palette;
2020             BYTE table[256][4];
2021             unsigned int x, y;
2022
2023             if( pal == NULL) {
2024                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
2025             }
2026
2027             d3dfmt_p8_init_palette(This, table, (convert == CONVERT_PALETTED_CK));
2028
2029             for (y = 0; y < height; y++)
2030             {
2031                 source = src + pitch * y;
2032                 dest = dst + outpitch * y;
2033                 /* This is an 1 bpp format, using the width here is fine */
2034                 for (x = 0; x < width; x++) {
2035                     BYTE color = *source++;
2036                     *dest++ = table[color][0];
2037                     *dest++ = table[color][1];
2038                     *dest++ = table[color][2];
2039                     *dest++ = table[color][3];
2040                 }
2041             }
2042         }
2043         break;
2044
2045         case CONVERT_CK_565:
2046         {
2047             /* Converting the 565 format in 5551 packed to emulate color-keying.
2048
2049               Note : in all these conversion, it would be best to average the averaging
2050                       pixels to get the color of the pixel that will be color-keyed to
2051                       prevent 'color bleeding'. This will be done later on if ever it is
2052                       too visible.
2053
2054               Note2: Nvidia documents say that their driver does not support alpha + color keying
2055                      on the same surface and disables color keying in such a case
2056             */
2057             unsigned int x, y;
2058             const WORD *Source;
2059             WORD *Dest;
2060
2061             TRACE("Color keyed 565\n");
2062
2063             for (y = 0; y < height; y++) {
2064                 Source = (const WORD *)(src + y * pitch);
2065                 Dest = (WORD *) (dst + y * outpitch);
2066                 for (x = 0; x < width; x++ ) {
2067                     WORD color = *Source++;
2068                     *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
2069                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
2070                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
2071                         *Dest |= 0x0001;
2072                     }
2073                     Dest++;
2074                 }
2075             }
2076         }
2077         break;
2078
2079         case CONVERT_CK_5551:
2080         {
2081             /* Converting X1R5G5B5 format to R5G5B5A1 to emulate color-keying. */
2082             unsigned int x, y;
2083             const WORD *Source;
2084             WORD *Dest;
2085             TRACE("Color keyed 5551\n");
2086             for (y = 0; y < height; y++) {
2087                 Source = (const WORD *)(src + y * pitch);
2088                 Dest = (WORD *) (dst + y * outpitch);
2089                 for (x = 0; x < width; x++ ) {
2090                     WORD color = *Source++;
2091                     *Dest = color;
2092                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
2093                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
2094                         *Dest |= (1 << 15);
2095                     }
2096                     else {
2097                         *Dest &= ~(1 << 15);
2098                     }
2099                     Dest++;
2100                 }
2101             }
2102         }
2103         break;
2104
2105         case CONVERT_CK_RGB24:
2106         {
2107             /* Converting R8G8B8 format to R8G8B8A8 with color-keying. */
2108             unsigned int x, y;
2109             for (y = 0; y < height; y++)
2110             {
2111                 source = src + pitch * y;
2112                 dest = dst + outpitch * y;
2113                 for (x = 0; x < width; x++) {
2114                     DWORD color = ((DWORD)source[0] << 16) + ((DWORD)source[1] << 8) + (DWORD)source[2] ;
2115                     DWORD dstcolor = color << 8;
2116                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
2117                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
2118                         dstcolor |= 0xff;
2119                     }
2120                     *(DWORD*)dest = dstcolor;
2121                     source += 3;
2122                     dest += 4;
2123                 }
2124             }
2125         }
2126         break;
2127
2128         case CONVERT_RGB32_888:
2129         {
2130             /* Converting X8R8G8B8 format to R8G8B8A8 with color-keying. */
2131             unsigned int x, y;
2132             for (y = 0; y < height; y++)
2133             {
2134                 source = src + pitch * y;
2135                 dest = dst + outpitch * y;
2136                 for (x = 0; x < width; x++) {
2137                     DWORD color = 0xffffff & *(const DWORD*)source;
2138                     DWORD dstcolor = color << 8;
2139                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
2140                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
2141                         dstcolor |= 0xff;
2142                     }
2143                     *(DWORD*)dest = dstcolor;
2144                     source += 4;
2145                     dest += 4;
2146                 }
2147             }
2148         }
2149         break;
2150
2151         case CONVERT_V8U8:
2152         {
2153             unsigned int x, y;
2154             const short *Source;
2155             unsigned char *Dest;
2156             for(y = 0; y < height; y++) {
2157                 Source = (const short *)(src + y * pitch);
2158                 Dest = dst + y * outpitch;
2159                 for (x = 0; x < width; x++ ) {
2160                     long color = (*Source++);
2161                     /* B */ Dest[0] = 0xff;
2162                     /* G */ Dest[1] = (color >> 8) + 128; /* V */
2163                     /* R */ Dest[2] = (color) + 128;      /* U */
2164                     Dest += 3;
2165                 }
2166             }
2167             break;
2168         }
2169
2170         case CONVERT_V16U16:
2171         {
2172             unsigned int x, y;
2173             const DWORD *Source;
2174             unsigned short *Dest;
2175             for(y = 0; y < height; y++) {
2176                 Source = (const DWORD *)(src + y * pitch);
2177                 Dest = (unsigned short *) (dst + y * outpitch);
2178                 for (x = 0; x < width; x++ ) {
2179                     DWORD color = (*Source++);
2180                     /* B */ Dest[0] = 0xffff;
2181                     /* G */ Dest[1] = (color >> 16) + 32768; /* V */
2182                     /* R */ Dest[2] = (color      ) + 32768; /* U */
2183                     Dest += 3;
2184                 }
2185             }
2186             break;
2187         }
2188
2189         case CONVERT_Q8W8V8U8:
2190         {
2191             unsigned int x, y;
2192             const DWORD *Source;
2193             unsigned char *Dest;
2194             for(y = 0; y < height; y++) {
2195                 Source = (const DWORD *)(src + y * pitch);
2196                 Dest = dst + y * outpitch;
2197                 for (x = 0; x < width; x++ ) {
2198                     long color = (*Source++);
2199                     /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
2200                     /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
2201                     /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
2202                     /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
2203                     Dest += 4;
2204                 }
2205             }
2206             break;
2207         }
2208
2209         case CONVERT_L6V5U5:
2210         {
2211             unsigned int x, y;
2212             const WORD *Source;
2213             unsigned char *Dest;
2214
2215             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
2216                 /* This makes the gl surface bigger(24 bit instead of 16), but it works with
2217                  * fixed function and shaders without further conversion once the surface is
2218                  * loaded
2219                  */
2220                 for(y = 0; y < height; y++) {
2221                     Source = (const WORD *)(src + y * pitch);
2222                     Dest = dst + y * outpitch;
2223                     for (x = 0; x < width; x++ ) {
2224                         short color = (*Source++);
2225                         unsigned char l = ((color >> 10) & 0xfc);
2226                                   char v = ((color >>  5) & 0x3e);
2227                                   char u = ((color      ) & 0x1f);
2228
2229                         /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign
2230                          * and doubles the positive range. Thus shift left only once, gl does the 2nd
2231                          * shift. GL reads a signed value and converts it into an unsigned value.
2232                          */
2233                         /* M */ Dest[2] = l << 1;
2234
2235                         /* Those are read as signed, but kept signed. Just left-shift 3 times to scale
2236                          * from 5 bit values to 8 bit values.
2237                          */
2238                         /* V */ Dest[1] = v << 3;
2239                         /* U */ Dest[0] = u << 3;
2240                         Dest += 3;
2241                     }
2242                 }
2243             } else {
2244                 for(y = 0; y < height; y++) {
2245                     unsigned short *Dest_s = (unsigned short *) (dst + y * outpitch);
2246                     Source = (const WORD *)(src + y * pitch);
2247                     for (x = 0; x < width; x++ ) {
2248                         short color = (*Source++);
2249                         unsigned char l = ((color >> 10) & 0xfc);
2250                                  short v = ((color >>  5) & 0x3e);
2251                                  short u = ((color      ) & 0x1f);
2252                         short v_conv = v + 16;
2253                         short u_conv = u + 16;
2254
2255                         *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f);
2256                         Dest_s += 1;
2257                     }
2258                 }
2259             }
2260             break;
2261         }
2262
2263         case CONVERT_X8L8V8U8:
2264         {
2265             unsigned int x, y;
2266             const DWORD *Source;
2267             unsigned char *Dest;
2268
2269             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
2270                 /* This implementation works with the fixed function pipeline and shaders
2271                  * without further modification after converting the surface.
2272                  */
2273                 for(y = 0; y < height; y++) {
2274                     Source = (const DWORD *)(src + y * pitch);
2275                     Dest = dst + y * outpitch;
2276                     for (x = 0; x < width; x++ ) {
2277                         long color = (*Source++);
2278                         /* L */ Dest[2] = ((color >> 16) & 0xff);   /* L */
2279                         /* V */ Dest[1] = ((color >> 8 ) & 0xff);   /* V */
2280                         /* U */ Dest[0] = (color         & 0xff);   /* U */
2281                         /* I */ Dest[3] = 255;                      /* X */
2282                         Dest += 4;
2283                     }
2284                 }
2285             } else {
2286                 /* Doesn't work correctly with the fixed function pipeline, but can work in
2287                  * shaders if the shader is adjusted. (There's no use for this format in gl's
2288                  * standard fixed function pipeline anyway).
2289                  */
2290                 for(y = 0; y < height; y++) {
2291                     Source = (const DWORD *)(src + y * pitch);
2292                     Dest = dst + y * outpitch;
2293                     for (x = 0; x < width; x++ ) {
2294                         long color = (*Source++);
2295                         /* B */ Dest[0] = ((color >> 16) & 0xff);       /* L */
2296                         /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
2297                         /* R */ Dest[2] = (color         & 0xff) + 128;  /* U */
2298                         Dest += 4;
2299                     }
2300                 }
2301             }
2302             break;
2303         }
2304
2305         case CONVERT_A4L4:
2306         {
2307             unsigned int x, y;
2308             const unsigned char *Source;
2309             unsigned char *Dest;
2310             for(y = 0; y < height; y++) {
2311                 Source = src + y * pitch;
2312                 Dest = dst + y * outpitch;
2313                 for (x = 0; x < width; x++ ) {
2314                     unsigned char color = (*Source++);
2315                     /* A */ Dest[1] = (color & 0xf0) << 0;
2316                     /* L */ Dest[0] = (color & 0x0f) << 4;
2317                     Dest += 2;
2318                 }
2319             }
2320             break;
2321         }
2322
2323         case CONVERT_G16R16:
2324         case CONVERT_R16G16F:
2325         {
2326             unsigned int x, y;
2327             const WORD *Source;
2328             WORD *Dest;
2329
2330             for(y = 0; y < height; y++) {
2331                 Source = (const WORD *)(src + y * pitch);
2332                 Dest = (WORD *) (dst + y * outpitch);
2333                 for (x = 0; x < width; x++ ) {
2334                     WORD green = (*Source++);
2335                     WORD red = (*Source++);
2336                     Dest[0] = green;
2337                     Dest[1] = red;
2338                     /* Strictly speaking not correct for R16G16F, but it doesn't matter because the
2339                      * shader overwrites it anyway
2340                      */
2341                     Dest[2] = 0xffff;
2342                     Dest += 3;
2343                 }
2344             }
2345             break;
2346         }
2347
2348         case CONVERT_R32G32F:
2349         {
2350             unsigned int x, y;
2351             const float *Source;
2352             float *Dest;
2353             for(y = 0; y < height; y++) {
2354                 Source = (const float *)(src + y * pitch);
2355                 Dest = (float *) (dst + y * outpitch);
2356                 for (x = 0; x < width; x++ ) {
2357                     float green = (*Source++);
2358                     float red = (*Source++);
2359                     Dest[0] = green;
2360                     Dest[1] = red;
2361                     Dest[2] = 1.0f;
2362                     Dest += 3;
2363                 }
2364             }
2365             break;
2366         }
2367
2368         case CONVERT_D15S1:
2369         {
2370             unsigned int x, y;
2371
2372             for (y = 0; y < height; ++y)
2373             {
2374                 const WORD *source = (const WORD *)(src + y * pitch);
2375                 DWORD *dest = (DWORD *)(dst + y * outpitch);
2376
2377                 for (x = 0; x < width; ++x)
2378                 {
2379                     /* The depth data is normalized, so needs to be scaled,
2380                      * the stencil data isn't.  Scale depth data by
2381                      *      (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */
2382                     WORD d15 = source[x] >> 1;
2383                     DWORD d24 = (d15 << 9) + (d15 >> 6);
2384                     dest[x] = (d24 << 8) | (source[x] & 0x1);
2385                 }
2386             }
2387             break;
2388         }
2389
2390         case CONVERT_D24X4S4:
2391         {
2392             unsigned int x, y;
2393
2394             for (y = 0; y < height; ++y)
2395             {
2396                 const DWORD *source = (const DWORD *)(src + y * pitch);
2397                 DWORD *dest = (DWORD *)(dst + y * outpitch);
2398
2399                 for (x = 0; x < width; ++x)
2400                 {
2401                     /* Just need to clear out the X4 part. */
2402                     dest[x] = source[x] & ~0xf0;
2403                 }
2404             }
2405             break;
2406         }
2407
2408         case CONVERT_D24FS8:
2409         {
2410             unsigned int x, y;
2411
2412             for (y = 0; y < height; ++y)
2413             {
2414                 const DWORD *source = (const DWORD *)(src + y * pitch);
2415                 float *dest_f = (float *)(dst + y * outpitch);
2416                 DWORD *dest_s = (DWORD *)(dst + y * outpitch);
2417
2418                 for (x = 0; x < width; ++x)
2419                 {
2420                     dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8);
2421                     dest_s[x * 2 + 1] = source[x] & 0xff;
2422                 }
2423             }
2424             break;
2425         }
2426
2427         default:
2428             ERR("Unsupported conversion type %#x.\n", convert);
2429     }
2430     return WINED3D_OK;
2431 }
2432
2433 /* This function is used in case of 8bit paletted textures to upload the palette.
2434    It supports GL_EXT_paletted_texture and GL_ARB_fragment_program, support for other
2435    extensions like ATI_fragment_shaders is possible.
2436 */
2437 /* Context activation is done by the caller. */
2438 static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
2439     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2440     BYTE table[256][4];
2441     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2442
2443     d3dfmt_p8_init_palette(This, table, (convert == CONVERT_PALETTED_CK));
2444
2445     /* Try to use the paletted texture extension */
2446     if(GL_SUPPORT(EXT_PALETTED_TEXTURE))
2447     {
2448         TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n");
2449         ENTER_GL();
2450         GL_EXTCALL(glColorTableEXT(This->texture_target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, table));
2451         LEAVE_GL();
2452     }
2453     else
2454     {
2455         /* Let a fragment shader do the color conversion by uploading the palette to a 1D texture.
2456          * The 8bit pixel data will be used as an index in this palette texture to retrieve the final color. */
2457         TRACE("Using fragment shaders for emulating 8-bit paletted texture support\n");
2458
2459         ENTER_GL();
2460
2461         /* Create the fragment program if we don't have it */
2462         if(!device->paletteConversionShader)
2463         {
2464             const char *fragment_palette_conversion =
2465                 "!!ARBfp1.0\n"
2466                 "TEMP index;\n"
2467                 /* { 255/256, 0.5/255*255/256, 0, 0 } */
2468                 "PARAM constants = { 0.996, 0.00195, 0, 0 };\n"
2469                 /* The alpha-component contains the palette index */
2470                 "TEX index, fragment.texcoord[0], texture[0], 2D;\n"
2471                 /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */
2472                 "MAD index.a, index.a, constants.x, constants.y;\n"
2473                 /* Use the alpha-component as an index in the palette to get the final color */
2474                 "TEX result.color, index.a, texture[1], 1D;\n"
2475                 "END";
2476
2477             glEnable(GL_FRAGMENT_PROGRAM_ARB);
2478             GL_EXTCALL(glGenProgramsARB(1, &device->paletteConversionShader));
2479             GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader));
2480             GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragment_palette_conversion), fragment_palette_conversion));
2481             glDisable(GL_FRAGMENT_PROGRAM_ARB);
2482         }
2483
2484         glEnable(GL_FRAGMENT_PROGRAM_ARB);
2485         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader));
2486
2487         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1));
2488         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2489
2490         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2491         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Make sure we have discrete color levels. */
2492         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2493         glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table); /* Upload the palette */
2494
2495         /* Switch back to unit 0 in which the 2D texture will be stored. */
2496         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0));
2497
2498         /* Rebind the texture because it isn't bound anymore */
2499         glBindTexture(This->texture_target, This->texture_name);
2500
2501         LEAVE_GL();
2502     }
2503 }
2504
2505 BOOL palette9_changed(IWineD3DSurfaceImpl *This) {
2506     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2507
2508     if (This->palette || (This->resource.format_desc->format != WINED3DFMT_P8
2509             && This->resource.format_desc->format != WINED3DFMT_A8P8))
2510     {
2511         /* If a ddraw-style palette is attached assume no d3d9 palette change.
2512          * Also the palette isn't interesting if the surface format isn't P8 or A8P8
2513          */
2514         return FALSE;
2515     }
2516
2517     if(This->palette9) {
2518         if(memcmp(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256) == 0) {
2519             return FALSE;
2520         }
2521     } else {
2522         This->palette9 = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256);
2523     }
2524     memcpy(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256);
2525     return TRUE;
2526 }
2527
2528 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, BOOL srgb_mode) {
2529     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2530     DWORD flag = srgb_mode ? SFLAG_INSRGBTEX : SFLAG_INTEXTURE;
2531
2532     if (!(This->Flags & flag)) {
2533         TRACE("Reloading because surface is dirty\n");
2534     } else if(/* Reload: gl texture has ck, now no ckey is set OR */
2535               ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & WINEDDSD_CKSRCBLT))) ||
2536               /* Reload: vice versa  OR */
2537               ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & WINEDDSD_CKSRCBLT)) ||
2538               /* Also reload: Color key is active AND the color key has changed */
2539               ((This->CKeyFlags & WINEDDSD_CKSRCBLT) && (
2540                 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
2541                 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
2542         TRACE("Reloading because of color keying\n");
2543         /* To perform the color key conversion we need a sysmem copy of
2544          * the surface. Make sure we have it
2545          */
2546
2547         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
2548         /* Make sure the texture is reloaded because of the color key change, this kills performance though :( */
2549         /* TODO: This is not necessarily needed with hw palettized texture support */
2550         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2551     } else {
2552         TRACE("surface is already in texture\n");
2553         return WINED3D_OK;
2554     }
2555
2556     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
2557      *  These resources are not bound by device size or format restrictions. Because of this,
2558      *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
2559      *  However, these resources can always be created, locked, and copied.
2560      */
2561     if (This->resource.pool == WINED3DPOOL_SCRATCH )
2562     {
2563         FIXME("(%p) Operation not supported for scratch textures\n",This);
2564         return WINED3DERR_INVALIDCALL;
2565     }
2566
2567     IWineD3DSurface_LoadLocation(iface, flag, NULL /* no partial locking for textures yet */);
2568
2569 #if 0
2570     {
2571         static unsigned int gen = 0;
2572         char buffer[4096];
2573         ++gen;
2574         if ((gen % 10) == 0) {
2575             snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm",
2576                     This, This->texture_target, This->texture_level, gen);
2577             IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
2578         }
2579         /*
2580          * debugging crash code
2581          if (gen == 250) {
2582          void** test = NULL;
2583          *test = 0;
2584          }
2585          */
2586     }
2587 #endif
2588
2589     if (!(This->Flags & SFLAG_DONOTFREE)) {
2590         HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
2591         This->resource.allocatedMemory = NULL;
2592         This->resource.heapMemory = NULL;
2593         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, FALSE);
2594     }
2595
2596     return WINED3D_OK;
2597 }
2598
2599 /* Context activation is done by the caller. */
2600 static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface, BOOL srgb) {
2601     /* TODO: check for locks */
2602     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2603     IWineD3DBaseTexture *baseTexture = NULL;
2604     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2605
2606     TRACE("(%p)Checking to see if the container is a base texture\n", This);
2607     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2608         TRACE("Passing to container\n");
2609         IWineD3DBaseTexture_BindTexture(baseTexture, srgb);
2610         IWineD3DBaseTexture_Release(baseTexture);
2611     } else {
2612         GLuint *name;
2613         TRACE("(%p) : Binding surface\n", This);
2614
2615         name = srgb ? &This->texture_name_srgb : &This->texture_name;
2616         if(!device->isInDraw) {
2617             ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD);
2618         }
2619
2620         ENTER_GL();
2621
2622         if (!This->texture_level)
2623         {
2624             if (!*name) {
2625                 glGenTextures(1, name);
2626                 checkGLcall("glGenTextures");
2627                 TRACE("Surface %p given name %d\n", This, *name);
2628
2629                 glBindTexture(This->texture_target, *name);
2630                 checkGLcall("glBindTexture");
2631                 glTexParameteri(This->texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2632                 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)");
2633                 glTexParameteri(This->texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2634                 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)");
2635                 glTexParameteri(This->texture_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
2636                 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)");
2637                 glTexParameteri(This->texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2638                 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MIN_FILTER, GL_NEAREST)");
2639                 glTexParameteri(This->texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2640                 checkGLcall("glTexParameteri(dimension, GL_TEXTURE_MAG_FILTER, GL_NEAREST)");
2641             }
2642             /* This is where we should be reducing the amount of GLMemoryUsed */
2643         } else if (*name) {
2644             /* Mipmap surfaces should have a base texture container */
2645             ERR("Mipmap surface has a glTexture bound to it!\n");
2646         }
2647
2648         glBindTexture(This->texture_target, *name);
2649         checkGLcall("glBindTexture");
2650
2651         LEAVE_GL();
2652     }
2653     return;
2654 }
2655
2656 #include <errno.h>
2657 #include <stdio.h>
2658 static HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename)
2659 {
2660     FILE* f = NULL;
2661     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2662     char *allocatedMemory;
2663     const char *textureRow;
2664     IWineD3DSwapChain *swapChain = NULL;
2665     int width, height, i, y;
2666     GLuint tmpTexture = 0;
2667     DWORD color;
2668     /*FIXME:
2669     Textures may not be stored in ->allocatedgMemory and a GlTexture
2670     so we should lock the surface before saving a snapshot, or at least check that
2671     */
2672     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
2673     by calling GetTexImage and in compressed form by calling
2674     GetCompressedTexImageARB.  Queried compressed images can be saved and
2675     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
2676     texture images do not need to be processed by the GL and should
2677     significantly improve texture loading performance relative to uncompressed
2678     images. */
2679
2680 /* Setup the width and height to be the internal texture width and height. */
2681     width  = This->pow2Width;
2682     height = This->pow2Height;
2683 /* check to see if we're a 'virtual' texture, e.g. we're not a pbuffer of texture, we're a back buffer*/
2684     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
2685
2686     if (This->Flags & SFLAG_INDRAWABLE && !(This->Flags & SFLAG_INTEXTURE)) {
2687         /* if were not a real texture then read the back buffer into a real texture */
2688         /* we don't want to interfere with the back buffer so read the data into a temporary
2689          * texture and then save the data out of the temporary texture
2690          */
2691         GLint prevRead;
2692         ENTER_GL();
2693         TRACE("(%p) Reading render target into texture\n", This);
2694
2695         glGenTextures(1, &tmpTexture);
2696         glBindTexture(GL_TEXTURE_2D, tmpTexture);
2697
2698         glTexImage2D(GL_TEXTURE_2D,
2699                         0,
2700                         GL_RGBA,
2701                         width,
2702                         height,
2703                         0/*border*/,
2704                         GL_RGBA,
2705                         GL_UNSIGNED_INT_8_8_8_8_REV,
2706                         NULL);
2707
2708         glGetIntegerv(GL_READ_BUFFER, &prevRead);
2709         checkGLcall("glGetIntegerv");
2710         glReadBuffer(swapChain ? GL_BACK : This->resource.wineD3DDevice->offscreenBuffer);
2711         checkGLcall("glReadBuffer");
2712         glCopyTexImage2D(GL_TEXTURE_2D,
2713                             0,
2714                             GL_RGBA,
2715                             0,
2716                             0,
2717                             width,
2718                             height,
2719                             0);
2720
2721         checkGLcall("glCopyTexImage2D");
2722         glReadBuffer(prevRead);
2723         LEAVE_GL();
2724
2725     } else { /* bind the real texture, and make sure it up to date */
2726         surface_internal_preload(iface, SRGB_RGB);
2727         surface_bind_and_dirtify(This, FALSE);
2728     }
2729     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
2730     ENTER_GL();
2731     FIXME("Saving texture level %d width %d height %d\n", This->texture_level, width, height);
2732     glGetTexImage(GL_TEXTURE_2D, This->texture_level, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, allocatedMemory);
2733     checkGLcall("glTexImage2D");
2734     if (tmpTexture) {
2735         glBindTexture(GL_TEXTURE_2D, 0);
2736         glDeleteTextures(1, &tmpTexture);
2737     }
2738     LEAVE_GL();
2739
2740     f = fopen(filename, "w+");
2741     if (NULL == f) {
2742         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
2743         return WINED3DERR_INVALIDCALL;
2744     }
2745 /* Save the data out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha channel */
2746     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format_desc->format));
2747 /* TGA header */
2748     fputc(0,f);
2749     fputc(0,f);
2750     fputc(2,f);
2751     fputc(0,f);
2752     fputc(0,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 /* short width*/
2761     fwrite(&width,2,1,f);
2762 /* short height */
2763     fwrite(&height,2,1,f);
2764 /* format rgba */
2765     fputc(0x20,f);
2766     fputc(0x28,f);
2767 /* raw data */
2768     /* 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 */
2769     if(swapChain)
2770         textureRow = allocatedMemory + (width * (height - 1) *4);
2771     else
2772         textureRow = allocatedMemory;
2773     for (y = 0 ; y < height; y++) {
2774         for (i = 0; i < width;  i++) {
2775             color = *((const DWORD*)textureRow);
2776             fputc((color >> 16) & 0xFF, f); /* B */
2777             fputc((color >>  8) & 0xFF, f); /* G */
2778             fputc((color >>  0) & 0xFF, f); /* R */
2779             fputc((color >> 24) & 0xFF, f); /* A */
2780             textureRow += 4;
2781         }
2782         /* take two rows of the pointer to the texture memory */
2783         if(swapChain)
2784             (textureRow-= width << 3);
2785
2786     }
2787     TRACE("Closing file\n");
2788     fclose(f);
2789
2790     if(swapChain) {
2791         IWineD3DSwapChain_Release(swapChain);
2792     }
2793     HeapFree(GetProcessHeap(), 0, allocatedMemory);
2794     return WINED3D_OK;
2795 }
2796
2797 static HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
2798     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2799     HRESULT hr;
2800
2801     TRACE("(%p) : Calling base function first\n", This);
2802     hr = IWineD3DBaseSurfaceImpl_SetFormat(iface, format);
2803     if(SUCCEEDED(hr)) {
2804         This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED);
2805         TRACE("(%p) : glFormat %d, glFormatInternal %d, glType %d\n", This, This->resource.format_desc->glFormat,
2806                 This->resource.format_desc->glInternal, This->resource.format_desc->glType);
2807     }
2808     return hr;
2809 }
2810
2811 static HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2812     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2813
2814     if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2815         WARN("Surface is locked or the HDC is in use\n");
2816         return WINED3DERR_INVALIDCALL;
2817     }
2818
2819     if(Mem && Mem != This->resource.allocatedMemory) {
2820         void *release = NULL;
2821
2822         /* Do I have to copy the old surface content? */
2823         if(This->Flags & SFLAG_DIBSECTION) {
2824                 /* Release the DC. No need to hold the critical section for the update
2825                  * Thread because this thread runs only on front buffers, but this method
2826                  * fails for render targets in the check above.
2827                  */
2828                 SelectObject(This->hDC, This->dib.holdbitmap);
2829                 DeleteDC(This->hDC);
2830                 /* Release the DIB section */
2831                 DeleteObject(This->dib.DIBsection);
2832                 This->dib.bitmap_data = NULL;
2833                 This->resource.allocatedMemory = NULL;
2834                 This->hDC = NULL;
2835                 This->Flags &= ~SFLAG_DIBSECTION;
2836         } else if(!(This->Flags & SFLAG_USERPTR)) {
2837             release = This->resource.heapMemory;
2838             This->resource.heapMemory = NULL;
2839         }
2840         This->resource.allocatedMemory = Mem;
2841         This->Flags |= SFLAG_USERPTR | SFLAG_INSYSMEM;
2842
2843         /* Now the surface memory is most up do date. Invalidate drawable and texture */
2844         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2845
2846         /* For client textures opengl has to be notified */
2847         if(This->Flags & SFLAG_CLIENT) {
2848             DWORD oldFlags = This->Flags;
2849             This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED);
2850             if(oldFlags & SFLAG_ALLOCATED) surface_internal_preload(iface, SRGB_RGB);
2851             if(oldFlags & SFLAG_SRGBALLOCATED) surface_internal_preload(iface, SRGB_SRGB);
2852             /* And hope that the app behaves correctly and did not free the old surface memory before setting a new pointer */
2853         }
2854
2855         /* Now free the old memory if any */
2856         HeapFree(GetProcessHeap(), 0, release);
2857     } else if(This->Flags & SFLAG_USERPTR) {
2858         /* LockRect and GetDC will re-create the dib section and allocated memory */
2859         This->resource.allocatedMemory = NULL;
2860         /* HeapMemory should be NULL already */
2861         if(This->resource.heapMemory != NULL) ERR("User pointer surface has heap memory allocated\n");
2862         This->Flags &= ~SFLAG_USERPTR;
2863
2864         if(This->Flags & SFLAG_CLIENT) {
2865             DWORD oldFlags = This->Flags;
2866             This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED);
2867             /* This respecifies an empty texture and opengl knows that the old memory is gone */
2868             if(oldFlags & SFLAG_ALLOCATED) surface_internal_preload(iface, SRGB_RGB);
2869             if(oldFlags & SFLAG_SRGBALLOCATED) surface_internal_preload(iface, SRGB_SRGB);
2870         }
2871     }
2872     return WINED3D_OK;
2873 }
2874
2875 void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) {
2876
2877     /* Flip the surface contents */
2878     /* Flip the DC */
2879     {
2880         HDC tmp;
2881         tmp = front->hDC;
2882         front->hDC = back->hDC;
2883         back->hDC = tmp;
2884     }
2885
2886     /* Flip the DIBsection */
2887     {
2888         HBITMAP tmp;
2889         BOOL hasDib = front->Flags & SFLAG_DIBSECTION;
2890         tmp = front->dib.DIBsection;
2891         front->dib.DIBsection = back->dib.DIBsection;
2892         back->dib.DIBsection = tmp;
2893
2894         if(back->Flags & SFLAG_DIBSECTION) front->Flags |= SFLAG_DIBSECTION;
2895         else front->Flags &= ~SFLAG_DIBSECTION;
2896         if(hasDib) back->Flags |= SFLAG_DIBSECTION;
2897         else back->Flags &= ~SFLAG_DIBSECTION;
2898     }
2899
2900     /* Flip the surface data */
2901     {
2902         void* tmp;
2903
2904         tmp = front->dib.bitmap_data;
2905         front->dib.bitmap_data = back->dib.bitmap_data;
2906         back->dib.bitmap_data = tmp;
2907
2908         tmp = front->resource.allocatedMemory;
2909         front->resource.allocatedMemory = back->resource.allocatedMemory;
2910         back->resource.allocatedMemory = tmp;
2911
2912         tmp = front->resource.heapMemory;
2913         front->resource.heapMemory = back->resource.heapMemory;
2914         back->resource.heapMemory = tmp;
2915     }
2916
2917     /* Flip the PBO */
2918     {
2919         GLuint tmp_pbo = front->pbo;
2920         front->pbo = back->pbo;
2921         back->pbo = tmp_pbo;
2922     }
2923
2924     /* client_memory should not be different, but just in case */
2925     {
2926         BOOL tmp;
2927         tmp = front->dib.client_memory;
2928         front->dib.client_memory = back->dib.client_memory;
2929         back->dib.client_memory = tmp;
2930     }
2931
2932     /* Flip the opengl texture */
2933     {
2934         GLuint tmp;
2935
2936         tmp = back->texture_name;
2937         back->texture_name = front->texture_name;
2938         front->texture_name = tmp;
2939
2940         tmp = back->texture_name_srgb;
2941         back->texture_name_srgb = front->texture_name_srgb;
2942         front->texture_name_srgb = tmp;
2943     }
2944
2945     {
2946         DWORD tmp_flags = back->Flags;
2947         back->Flags = front->Flags;
2948         front->Flags = tmp_flags;
2949     }
2950 }
2951
2952 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2953     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2954     IWineD3DSwapChainImpl *swapchain = NULL;
2955     HRESULT hr;
2956     TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2957
2958     /* Flipping is only supported on RenderTargets and overlays*/
2959     if( !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_OVERLAY)) ) {
2960         WARN("Tried to flip a non-render target, non-overlay surface\n");
2961         return WINEDDERR_NOTFLIPPABLE;
2962     }
2963
2964     if(This->resource.usage & WINED3DUSAGE_OVERLAY) {
2965         flip_surface(This, (IWineD3DSurfaceImpl *) override);
2966
2967         /* Update the overlay if it is visible */
2968         if(This->overlay_dest) {
2969             return IWineD3DSurface_DrawOverlay((IWineD3DSurface *) This);
2970         } else {
2971             return WINED3D_OK;
2972         }
2973     }
2974
2975     if(override) {
2976         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
2977          * FIXME("(%p) Target override is not supported by now\n", This);
2978          * Additionally, it isn't really possible to support triple-buffering
2979          * properly on opengl at all
2980          */
2981     }
2982
2983     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain);
2984     if(!swapchain) {
2985         ERR("Flipped surface is not on a swapchain\n");
2986         return WINEDDERR_NOTFLIPPABLE;
2987     }
2988
2989     /* Just overwrite the swapchain presentation interval. This is ok because only ddraw apps can call Flip,
2990      * and only d3d8 and d3d9 apps specify the presentation interval
2991      */
2992     if((Flags & (WINEDDFLIP_NOVSYNC | WINEDDFLIP_INTERVAL2 | WINEDDFLIP_INTERVAL3 | WINEDDFLIP_INTERVAL4)) == 0) {
2993         /* Most common case first to avoid wasting time on all the other cases */
2994         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_ONE;
2995     } else if(Flags & WINEDDFLIP_NOVSYNC) {
2996         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
2997     } else if(Flags & WINEDDFLIP_INTERVAL2) {
2998         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_TWO;
2999     } else if(Flags & WINEDDFLIP_INTERVAL3) {
3000         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_THREE;
3001     } else {
3002         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_FOUR;
3003     }
3004
3005     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
3006     hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0);
3007     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
3008     return hr;
3009 }
3010
3011 /* Does a direct frame buffer -> texture copy. Stretching is done
3012  * with single pixel copy calls
3013  */
3014 static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface,
3015         IWineD3DSwapChainImpl *swapchain, const WINED3DRECT *srect, const WINED3DRECT *drect,
3016         BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter)
3017 {
3018     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3019     float xrel, yrel;
3020     UINT row;
3021     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3022
3023
3024     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
3025     surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB);
3026     ENTER_GL();
3027
3028     /* Bind the target texture */
3029     glBindTexture(This->texture_target, This->texture_name);
3030     checkGLcall("glBindTexture");
3031     if(!swapchain) {
3032         TRACE("Reading from an offscreen target\n");
3033         upsidedown = !upsidedown;
3034         glReadBuffer(myDevice->offscreenBuffer);
3035     } else {
3036         GLenum buffer = surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain);
3037         glReadBuffer(buffer);
3038     }
3039     checkGLcall("glReadBuffer");
3040
3041     xrel = (float) (srect->x2 - srect->x1) / (float) (drect->x2 - drect->x1);
3042     yrel = (float) (srect->y2 - srect->y1) / (float) (drect->y2 - drect->y1);
3043
3044     if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
3045     {
3046         FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n");
3047
3048         if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) {
3049             ERR("Texture filtering not supported in direct blit\n");
3050         }
3051     }
3052     else if ((Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT)
3053             && ((yrel - 1.0f < -eps) || (yrel - 1.0f > eps)))
3054     {
3055         ERR("Texture filtering not supported in direct blit\n");
3056     }
3057
3058     if (upsidedown
3059             && !((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
3060             && !((yrel - 1.0f < -eps) || (yrel - 1.0f > eps)))
3061     {
3062         /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */
3063
3064         glCopyTexSubImage2D(This->texture_target, This->texture_level,
3065                 drect->x1 /*xoffset */, drect->y1 /* y offset */,
3066                 srect->x1, Src->currentDesc.Height - srect->y2,
3067                 drect->x2 - drect->x1, drect->y2 - drect->y1);
3068     } else {
3069         UINT yoffset = Src->currentDesc.Height - srect->y1 + drect->y1 - 1;
3070         /* I have to process this row by row to swap the image,
3071          * otherwise it would be upside down, so stretching in y direction
3072          * doesn't cost extra time
3073          *
3074          * However, stretching in x direction can be avoided if not necessary
3075          */
3076         for(row = drect->y1; row < drect->y2; row++) {
3077             if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
3078             {
3079                 /* Well, that stuff works, but it's very slow.
3080                  * find a better way instead
3081                  */
3082                 UINT col;
3083
3084                 for(col = drect->x1; col < drect->x2; col++) {
3085                     glCopyTexSubImage2D(This->texture_target, This->texture_level,
3086                             drect->x1 + col /* x offset */, row /* y offset */,
3087                             srect->x1 + col * xrel, yoffset - (int) (row * yrel), 1, 1);
3088                 }
3089             } else {
3090                 glCopyTexSubImage2D(This->texture_target, This->texture_level,
3091                         drect->x1 /* x offset */, row /* y offset */,
3092                         srect->x1, yoffset - (int) (row * yrel), drect->x2-drect->x1, 1);
3093             }
3094         }
3095     }
3096     checkGLcall("glCopyTexSubImage2D");
3097
3098     LEAVE_GL();
3099 }
3100
3101 /* Uses the hardware to stretch and flip the image */
3102 static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface,
3103         IWineD3DSwapChainImpl *swapchain, const WINED3DRECT *srect, const WINED3DRECT *drect,
3104         BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter)
3105 {
3106     GLuint src, backup = 0;
3107     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3108     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3109     float left, right, top, bottom; /* Texture coordinates */
3110     UINT fbwidth = Src->currentDesc.Width;
3111     UINT fbheight = Src->currentDesc.Height;
3112     struct wined3d_context *context;
3113     GLenum drawBuffer = GL_BACK;
3114     GLenum texture_target;
3115     BOOL noBackBufferBackup;
3116
3117     TRACE("Using hwstretch blit\n");
3118     /* Activate the Proper context for reading from the source surface, set it up for blitting */
3119     context = ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
3120     surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB);
3121
3122     noBackBufferBackup = !swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO;
3123     if (!noBackBufferBackup && !Src->texture_name)
3124     {
3125         /* Get it a description */
3126         surface_internal_preload(SrcSurface, SRGB_RGB);
3127     }
3128     ENTER_GL();
3129
3130     /* Try to use an aux buffer for drawing the rectangle. This way it doesn't need restoring.
3131      * This way we don't have to wait for the 2nd readback to finish to leave this function.
3132      */
3133     if (context->aux_buffers >= 2)
3134     {
3135         /* Got more than one aux buffer? Use the 2nd aux buffer */
3136         drawBuffer = GL_AUX1;
3137     }
3138     else if ((swapchain || myDevice->offscreenBuffer == GL_BACK) && context->aux_buffers >= 1)
3139     {
3140         /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */
3141         drawBuffer = GL_AUX0;
3142     }
3143
3144     if(noBackBufferBackup) {
3145         glGenTextures(1, &backup);
3146         checkGLcall("glGenTextures");
3147         glBindTexture(GL_TEXTURE_2D, backup);
3148         checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)");
3149         texture_target = GL_TEXTURE_2D;
3150     } else {
3151         /* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If
3152          * we are reading from the back buffer, the backup can be used as source texture
3153          */
3154         texture_target = Src->texture_target;
3155         glBindTexture(texture_target, Src->texture_name);
3156         checkGLcall("glBindTexture(texture_target, Src->texture_name)");
3157         glEnable(texture_target);
3158         checkGLcall("glEnable(texture_target)");
3159
3160         /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
3161         Src->Flags &= ~SFLAG_INTEXTURE;
3162     }
3163
3164     if(swapchain) {
3165         glReadBuffer(surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain));
3166     } else {
3167         TRACE("Reading from an offscreen target\n");
3168         upsidedown = !upsidedown;
3169         glReadBuffer(myDevice->offscreenBuffer);
3170     }
3171
3172     /* TODO: Only back up the part that will be overwritten */
3173     glCopyTexSubImage2D(texture_target, 0,
3174                         0, 0 /* read offsets */,
3175                         0, 0,
3176                         fbwidth,
3177                         fbheight);
3178
3179     checkGLcall("glCopyTexSubImage2D");
3180
3181     /* No issue with overriding these - the sampler is dirty due to blit usage */
3182     glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER,
3183             wined3d_gl_mag_filter(magLookup, Filter));
3184     checkGLcall("glTexParameteri");
3185     glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER,
3186             wined3d_gl_min_mip_filter(minMipLookup, Filter, WINED3DTEXF_NONE));
3187     checkGLcall("glTexParameteri");
3188
3189     if(!swapchain || (IWineD3DSurface *) Src == swapchain->backBuffer[0]) {
3190         src = backup ? backup : Src->texture_name;
3191     } else {
3192         glReadBuffer(GL_FRONT);
3193         checkGLcall("glReadBuffer(GL_FRONT)");
3194
3195         glGenTextures(1, &src);
3196         checkGLcall("glGenTextures(1, &src)");
3197         glBindTexture(GL_TEXTURE_2D, src);
3198         checkGLcall("glBindTexture(GL_TEXTURE_2D, src)");
3199
3200         /* TODO: Only copy the part that will be read. Use srect->x1, srect->y2 as origin, but with the width watch
3201          * out for power of 2 sizes
3202          */
3203         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Src->pow2Width, Src->pow2Height, 0,
3204                     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
3205         checkGLcall("glTexImage2D");
3206         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3207                             0, 0 /* read offsets */,
3208                             0, 0,
3209                             fbwidth,
3210                             fbheight);
3211
3212         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3213         checkGLcall("glTexParameteri");
3214         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3215         checkGLcall("glTexParameteri");
3216
3217         glReadBuffer(GL_BACK);
3218         checkGLcall("glReadBuffer(GL_BACK)");
3219
3220         if(texture_target != GL_TEXTURE_2D) {
3221             glDisable(texture_target);
3222             glEnable(GL_TEXTURE_2D);
3223             texture_target = GL_TEXTURE_2D;
3224         }
3225     }
3226     checkGLcall("glEnd and previous");
3227
3228     left = srect->x1;
3229     right = srect->x2;
3230
3231     if(upsidedown) {
3232         top = Src->currentDesc.Height - srect->y1;
3233         bottom = Src->currentDesc.Height - srect->y2;
3234     } else {
3235         top = Src->currentDesc.Height - srect->y2;
3236         bottom = Src->currentDesc.Height - srect->y1;
3237     }
3238
3239     if(Src->Flags & SFLAG_NORMCOORD) {
3240         left /= Src->pow2Width;
3241         right /= Src->pow2Width;
3242         top /= Src->pow2Height;
3243         bottom /= Src->pow2Height;
3244     }
3245
3246     /* draw the source texture stretched and upside down. The correct surface is bound already */
3247     glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
3248     glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
3249
3250     glDrawBuffer(drawBuffer);
3251     glReadBuffer(drawBuffer);
3252
3253     glBegin(GL_QUADS);
3254         /* bottom left */
3255         glTexCoord2f(left, bottom);
3256         glVertex2i(0, fbheight);
3257
3258         /* top left */
3259         glTexCoord2f(left, top);
3260         glVertex2i(0, fbheight - drect->y2 - drect->y1);
3261
3262         /* top right */
3263         glTexCoord2f(right, top);
3264         glVertex2i(drect->x2 - drect->x1, fbheight - drect->y2 - drect->y1);
3265
3266         /* bottom right */
3267         glTexCoord2f(right, bottom);
3268         glVertex2i(drect->x2 - drect->x1, fbheight);
3269     glEnd();
3270     checkGLcall("glEnd and previous");
3271
3272     if (texture_target != This->texture_target)
3273     {
3274         glDisable(texture_target);
3275         glEnable(This->texture_target);
3276         texture_target = This->texture_target;
3277     }
3278
3279     /* Now read the stretched and upside down image into the destination texture */
3280     glBindTexture(texture_target, This->texture_name);
3281     checkGLcall("glBindTexture");
3282     glCopyTexSubImage2D(texture_target,
3283                         0,
3284                         drect->x1, drect->y1, /* xoffset, yoffset */
3285                         0, 0, /* We blitted the image to the origin */
3286                         drect->x2 - drect->x1, drect->y2 - drect->y1);
3287     checkGLcall("glCopyTexSubImage2D");
3288
3289     if(drawBuffer == GL_BACK) {
3290         /* Write the back buffer backup back */
3291         if(backup) {
3292             if(texture_target != GL_TEXTURE_2D) {
3293                 glDisable(texture_target);
3294                 glEnable(GL_TEXTURE_2D);
3295                 texture_target = GL_TEXTURE_2D;
3296             }
3297             glBindTexture(GL_TEXTURE_2D, backup);
3298             checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)");
3299         } else {
3300             if (texture_target != Src->texture_target)
3301             {
3302                 glDisable(texture_target);
3303                 glEnable(Src->texture_target);
3304                 texture_target = Src->texture_target;
3305             }
3306             glBindTexture(Src->texture_target, Src->texture_name);
3307             checkGLcall("glBindTexture(Src->texture_target, Src->texture_name)");
3308         }
3309
3310         glBegin(GL_QUADS);
3311             /* top left */
3312             glTexCoord2f(0.0f, (float)fbheight / (float)Src->pow2Height);
3313             glVertex2i(0, 0);
3314
3315             /* bottom left */
3316             glTexCoord2f(0.0f, 0.0f);
3317             glVertex2i(0, fbheight);
3318
3319             /* bottom right */
3320             glTexCoord2f((float)fbwidth / (float)Src->pow2Width, 0.0f);
3321             glVertex2i(fbwidth, Src->currentDesc.Height);
3322
3323             /* top right */
3324             glTexCoord2f((float) fbwidth / (float) Src->pow2Width, (float) fbheight / (float) Src->pow2Height);
3325             glVertex2i(fbwidth, 0);
3326         glEnd();
3327     } else {
3328         /* Restore the old draw buffer */
3329         glDrawBuffer(GL_BACK);
3330     }
3331     glDisable(texture_target);
3332     checkGLcall("glDisable(texture_target)");
3333
3334     /* Cleanup */
3335     if (src != Src->texture_name && src != backup)
3336     {
3337         glDeleteTextures(1, &src);
3338         checkGLcall("glDeleteTextures(1, &src)");
3339     }
3340     if(backup) {
3341         glDeleteTextures(1, &backup);
3342         checkGLcall("glDeleteTextures(1, &backup)");
3343     }
3344
3345     LEAVE_GL();
3346 }
3347
3348 /* Not called from the VTable */
3349 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const RECT *DestRect,
3350         IWineD3DSurface *SrcSurface, const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx,
3351         WINED3DTEXTUREFILTERTYPE Filter)
3352 {
3353     WINED3DRECT rect;
3354     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3355     IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL;
3356     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3357
3358     TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
3359
3360     /* Get the swapchain. One of the surfaces has to be a primary surface */
3361     if(This->resource.pool == WINED3DPOOL_SYSTEMMEM) {
3362         WARN("Destination is in sysmem, rejecting gl blt\n");
3363         return WINED3DERR_INVALIDCALL;
3364     }
3365     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&dstSwapchain);
3366     if(dstSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) dstSwapchain);
3367     if(Src) {
3368         if(Src->resource.pool == WINED3DPOOL_SYSTEMMEM) {
3369             WARN("Src is in sysmem, rejecting gl blt\n");
3370             return WINED3DERR_INVALIDCALL;
3371         }
3372         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&srcSwapchain);
3373         if(srcSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) srcSwapchain);
3374     }
3375
3376     /* Early sort out of cases where no render target is used */
3377     if(!dstSwapchain && !srcSwapchain &&
3378         SrcSurface != myDevice->render_targets[0] && This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
3379         TRACE("No surface is render target, not using hardware blit. Src = %p, dst = %p\n", Src, This);
3380         return WINED3DERR_INVALIDCALL;
3381     }
3382
3383     /* No destination color keying supported */
3384     if(Flags & (WINEDDBLT_KEYDEST | WINEDDBLT_KEYDESTOVERRIDE)) {
3385         /* Can we support that with glBlendFunc if blitting to the frame buffer? */
3386         TRACE("Destination color key not supported in accelerated Blit, falling back to software\n");
3387         return WINED3DERR_INVALIDCALL;
3388     }
3389
3390     if (DestRect) {
3391         rect.x1 = DestRect->left;
3392         rect.y1 = DestRect->top;
3393         rect.x2 = DestRect->right;
3394         rect.y2 = DestRect->bottom;
3395     } else {
3396         rect.x1 = 0;
3397         rect.y1 = 0;
3398         rect.x2 = This->currentDesc.Width;
3399         rect.y2 = This->currentDesc.Height;
3400     }
3401
3402     /* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */
3403     if(dstSwapchain && dstSwapchain == srcSwapchain && dstSwapchain->backBuffer &&
3404        ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && SrcSurface == dstSwapchain->backBuffer[0]) {
3405         /* Half-life does a Blt from the back buffer to the front buffer,
3406          * Full surface size, no flags... Use present instead
3407          *
3408          * This path will only be entered for d3d7 and ddraw apps, because d3d8/9 offer no way to blit TO the front buffer
3409          */
3410
3411         /* Check rects - IWineD3DDevice_Present doesn't handle them */
3412         while(1)
3413         {
3414             RECT mySrcRect;
3415             TRACE("Looking if a Present can be done...\n");
3416             /* Source Rectangle must be full surface */
3417             if( SrcRect ) {
3418                 if(SrcRect->left != 0 || SrcRect->top != 0 ||
3419                    SrcRect->right != Src->currentDesc.Width || SrcRect->bottom != Src->currentDesc.Height) {
3420                     TRACE("No, Source rectangle doesn't match\n");
3421                     break;
3422                 }
3423             }
3424             mySrcRect.left = 0;
3425             mySrcRect.top = 0;
3426             mySrcRect.right = Src->currentDesc.Width;
3427             mySrcRect.bottom = Src->currentDesc.Height;
3428
3429             /* No stretching may occur */
3430             if(mySrcRect.right != rect.x2 - rect.x1 ||
3431                mySrcRect.bottom != rect.y2 - rect.y1) {
3432                 TRACE("No, stretching is done\n");
3433                 break;
3434             }
3435
3436             /* Destination must be full surface or match the clipping rectangle */
3437             if(This->clipper && ((IWineD3DClipperImpl *) This->clipper)->hWnd)
3438             {
3439                 RECT cliprect;
3440                 POINT pos[2];
3441                 GetClientRect(((IWineD3DClipperImpl *) This->clipper)->hWnd, &cliprect);
3442                 pos[0].x = rect.x1;
3443                 pos[0].y = rect.y1;
3444                 pos[1].x = rect.x2;
3445                 pos[1].y = rect.y2;
3446                 MapWindowPoints(GetDesktopWindow(), ((IWineD3DClipperImpl *) This->clipper)->hWnd,
3447                                 pos, 2);
3448
3449                 if(pos[0].x != cliprect.left  || pos[0].y != cliprect.top   ||
3450                    pos[1].x != cliprect.right || pos[1].y != cliprect.bottom)
3451                 {
3452                     TRACE("No, dest rectangle doesn't match(clipper)\n");
3453                     TRACE("Clip rect at (%d,%d)-(%d,%d)\n", cliprect.left, cliprect.top, cliprect.right, cliprect.bottom);
3454                     TRACE("Blt dest: (%d,%d)-(%d,%d)\n", rect.x1, rect.y1, rect.x2, rect.y2);
3455                     break;
3456                 }
3457             }
3458             else
3459             {
3460                 if(rect.x1 != 0 || rect.y1 != 0 ||
3461                    rect.x2 != This->currentDesc.Width || rect.y2 != This->currentDesc.Height) {
3462                     TRACE("No, dest rectangle doesn't match(surface size)\n");
3463                     break;
3464                 }
3465             }
3466
3467             TRACE("Yes\n");
3468
3469             /* These flags are unimportant for the flag check, remove them */
3470             if((Flags & ~(WINEDDBLT_DONOTWAIT | WINEDDBLT_WAIT)) == 0) {
3471                 WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect;
3472
3473                 /* The idea behind this is that a glReadPixels and a glDrawPixels call
3474                     * take very long, while a flip is fast.
3475                     * This applies to Half-Life, which does such Blts every time it finished
3476                     * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
3477                     * menu. This is also used by all apps when they do windowed rendering
3478                     *
3479                     * The problem is that flipping is not really the same as copying. After a
3480                     * Blt the front buffer is a copy of the back buffer, and the back buffer is
3481                     * untouched. Therefore it's necessary to override the swap effect
3482                     * and to set it back after the flip.
3483                     *
3484                     * Windowed Direct3D < 7 apps do the same. The D3D7 sdk demos are nice
3485                     * testcases.
3486                     */
3487
3488                 dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
3489                 dstSwapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
3490
3491                 TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
3492                 IWineD3DSwapChain_Present((IWineD3DSwapChain *) dstSwapchain, NULL, NULL, 0, NULL, 0);
3493
3494                 dstSwapchain->presentParms.SwapEffect = orig_swap;
3495
3496                 return WINED3D_OK;
3497             }
3498             break;
3499         }
3500
3501         TRACE("Unsupported blit between buffers on the same swapchain\n");
3502         return WINED3DERR_INVALIDCALL;
3503     } else if(dstSwapchain && dstSwapchain == srcSwapchain) {
3504         FIXME("Implement hardware blit between two surfaces on the same swapchain\n");
3505         return WINED3DERR_INVALIDCALL;
3506     } else if(dstSwapchain && srcSwapchain) {
3507         FIXME("Implement hardware blit between two different swapchains\n");
3508         return WINED3DERR_INVALIDCALL;
3509     } else if(dstSwapchain) {
3510         if(SrcSurface == myDevice->render_targets[0]) {
3511             TRACE("Blit from active render target to a swapchain\n");
3512             /* Handled with regular texture -> swapchain blit */
3513         }
3514     } else if(srcSwapchain && This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
3515         FIXME("Implement blit from a swapchain to the active render target\n");
3516         return WINED3DERR_INVALIDCALL;
3517     }
3518
3519     if((srcSwapchain || SrcSurface == myDevice->render_targets[0]) && !dstSwapchain) {
3520         /* Blit from render target to texture */
3521         WINED3DRECT srect;
3522         BOOL upsideDown, stretchx;
3523         BOOL paletteOverride = FALSE;
3524
3525         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3526             TRACE("Color keying not supported by frame buffer to texture blit\n");
3527             return WINED3DERR_INVALIDCALL;
3528             /* Destination color key is checked above */
3529         }
3530
3531         /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
3532          * glCopyTexSubImage is a bit picky about the parameters we pass to it
3533          */
3534         if(SrcRect) {
3535             if(SrcRect->top < SrcRect->bottom) {
3536                 srect.y1 = SrcRect->top;
3537                 srect.y2 = SrcRect->bottom;
3538                 upsideDown = FALSE;
3539             } else {
3540                 srect.y1 = SrcRect->bottom;
3541                 srect.y2 = SrcRect->top;
3542                 upsideDown = TRUE;
3543             }
3544             srect.x1 = SrcRect->left;
3545             srect.x2 = SrcRect->right;
3546         } else {
3547             srect.x1 = 0;
3548             srect.y1 = 0;
3549             srect.x2 = Src->currentDesc.Width;
3550             srect.y2 = Src->currentDesc.Height;
3551             upsideDown = FALSE;
3552         }
3553         if(rect.x1 > rect.x2) {
3554             UINT tmp = rect.x2;
3555             rect.x2 = rect.x1;
3556             rect.x1 = tmp;
3557             upsideDown = !upsideDown;
3558         }
3559
3560         if(rect.x2 - rect.x1 != srect.x2 - srect.x1) {
3561             stretchx = TRUE;
3562         } else {
3563             stretchx = FALSE;
3564         }
3565
3566         /* When blitting from a render target a texture, the texture isn't required to have a palette.
3567          * In this case grab the palette from the render target. */
3568         if ((This->resource.format_desc->format == WINED3DFMT_P8) && (This->palette == NULL))
3569         {
3570             paletteOverride = TRUE;
3571             TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This);
3572             This->palette = Src->palette;
3573         }
3574
3575         /* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
3576          * flip the image nor scale it.
3577          *
3578          * -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
3579          * -> If the app wants a image width an unscaled width, copy it line per line
3580          * -> If the app wants a image that is scaled on the x axis, and the destination rectangle is smaller
3581          *    than the frame buffer, draw an upside down scaled image onto the fb, read it back and restore the
3582          *    back buffer. This is slower than reading line per line, thus not used for flipping
3583          * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
3584          *    pixel by pixel
3585          *
3586          * If EXT_framebuffer_blit is supported that can be used instead. Note that EXT_framebuffer_blit implies
3587          * FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering
3588          * backends.
3589          */
3590         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT)
3591                 && surface_can_stretch_rect(Src, This))
3592         {
3593             stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &srect,
3594                     (IWineD3DSurface *)This, &rect, Filter, upsideDown);
3595         } else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width ||
3596                                     rect.y2 - rect.y1 > Src->currentDesc.Height) {
3597             TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
3598             fb_copy_to_texture_direct(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, Filter);
3599         } else {
3600             TRACE("Using hardware stretching to flip / stretch the texture\n");
3601             fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, Filter);
3602         }
3603
3604         /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3605         if(paletteOverride)
3606             This->palette = NULL;
3607
3608         if(!(This->Flags & SFLAG_DONOTFREE)) {
3609             HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
3610             This->resource.allocatedMemory = NULL;
3611             This->resource.heapMemory = NULL;
3612         } else {
3613             This->Flags &= ~SFLAG_INSYSMEM;
3614         }
3615         /* The texture is now most up to date - If the surface is a render target and has a drawable, this
3616          * path is never entered
3617          */
3618         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INTEXTURE, TRUE);
3619
3620         return WINED3D_OK;
3621     } else if(Src) {
3622         /* Blit from offscreen surface to render target */
3623         float glTexCoord[4];
3624         DWORD oldCKeyFlags = Src->CKeyFlags;
3625         WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey;
3626         RECT SourceRectangle;
3627         BOOL paletteOverride = FALSE;
3628
3629         TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
3630
3631         if(SrcRect) {
3632             SourceRectangle.left = SrcRect->left;
3633             SourceRectangle.right = SrcRect->right;
3634             SourceRectangle.top = SrcRect->top;
3635             SourceRectangle.bottom = SrcRect->bottom;
3636         } else {
3637             SourceRectangle.left = 0;
3638             SourceRectangle.right = Src->currentDesc.Width;
3639             SourceRectangle.top = 0;
3640             SourceRectangle.bottom = Src->currentDesc.Height;
3641         }
3642
3643         /* When blitting from an offscreen surface to a rendertarget, the source
3644          * surface is not required to have a palette. Our rendering / conversion
3645          * code further down the road retrieves the palette from the surface, so
3646          * it must have a palette set. */
3647         if ((Src->resource.format_desc->format == WINED3DFMT_P8) && (Src->palette == NULL))
3648         {
3649             paletteOverride = TRUE;
3650             TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This);
3651             Src->palette = This->palette;
3652         }
3653
3654         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT)
3655                 && !(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE))
3656                 && surface_can_stretch_rect(Src, This))
3657         {
3658             TRACE("Using stretch_rect_fbo\n");
3659             /* The source is always a texture, but never the currently active render target, and the texture
3660              * contents are never upside down
3661              */
3662             stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, (WINED3DRECT *) &SourceRectangle,
3663                               (IWineD3DSurface *)This, &rect, Filter, FALSE);
3664
3665             /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3666             if(paletteOverride)
3667                 Src->palette = NULL;
3668             return WINED3D_OK;
3669         }
3670
3671         if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
3672             /* Fall back to software */
3673             WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
3674                     SourceRectangle.left, SourceRectangle.top,
3675                     SourceRectangle.right, SourceRectangle.bottom);
3676             return WINED3DERR_INVALIDCALL;
3677         }
3678
3679         /* Color keying: Check if we have to do a color keyed blt,
3680          * and if not check if a color key is activated.
3681          *
3682          * Just modify the color keying parameters in the surface and restore them afterwards
3683          * The surface keeps track of the color key last used to load the opengl surface.
3684          * PreLoad will catch the change to the flags and color key and reload if necessary.
3685          */
3686         if(Flags & WINEDDBLT_KEYSRC) {
3687             /* Use color key from surface */
3688         } else if(Flags & WINEDDBLT_KEYSRCOVERRIDE) {
3689             /* Use color key from DDBltFx */
3690             Src->CKeyFlags |= WINEDDSD_CKSRCBLT;
3691             Src->SrcBltCKey = DDBltFx->ddckSrcColorkey;
3692         } else {
3693             /* Do not use color key */
3694             Src->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
3695         }
3696
3697         /* Now load the surface */
3698         surface_internal_preload((IWineD3DSurface *) Src, SRGB_RGB);
3699
3700         /* Activate the destination context, set it up for blitting */
3701         ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
3702
3703         /* The coordinates of the ddraw front buffer are always fullscreen ('screen coordinates',
3704          * while OpenGL coordinates are window relative.
3705          * Also beware of the origin difference(top left vs bottom left).
3706          * Also beware that the front buffer's surface size is screen width x screen height,
3707          * whereas the real gl drawable size is the size of the window.
3708          */
3709         if (dstSwapchain && (IWineD3DSurface *)This == dstSwapchain->frontBuffer) {
3710             RECT windowsize;
3711             POINT offset = {0,0};
3712             UINT h;
3713             ClientToScreen(dstSwapchain->win_handle, &offset);
3714             GetClientRect(dstSwapchain->win_handle, &windowsize);
3715             h = windowsize.bottom - windowsize.top;
3716             rect.x1 -= offset.x; rect.x2 -=offset.x;
3717             rect.y1 -= offset.y; rect.y2 -=offset.y;
3718             rect.y1 += This->currentDesc.Height - h; rect.y2 += This->currentDesc.Height - h;
3719         }
3720
3721         if (!is_identity_fixup(This->resource.format_desc->color_fixup))
3722         {
3723             FIXME("Destination format %s has a fixup, this is not supported.\n",
3724                     debug_d3dformat(This->resource.format_desc->format));
3725             dump_color_fixup_desc(This->resource.format_desc->color_fixup);
3726         }
3727
3728         if (!myDevice->blitter->color_fixup_supported(Src->resource.format_desc->color_fixup))
3729         {
3730             FIXME("Source format %s has an unsupported fixup:\n",
3731                     debug_d3dformat(Src->resource.format_desc->format));
3732             dump_color_fixup_desc(Src->resource.format_desc->color_fixup);
3733         }
3734
3735         myDevice->blitter->set_shader((IWineD3DDevice *) myDevice, Src->resource.format_desc,
3736                 Src->texture_target, Src->pow2Width, Src->pow2Height);
3737
3738         ENTER_GL();
3739
3740         /* Bind the texture */
3741         glBindTexture(Src->texture_target, Src->texture_name);
3742         checkGLcall("glBindTexture");
3743
3744         /* Filtering for StretchRect */
3745         glTexParameteri(Src->texture_target, GL_TEXTURE_MAG_FILTER,
3746                 wined3d_gl_mag_filter(magLookup, Filter));
3747         checkGLcall("glTexParameteri");
3748         glTexParameteri(Src->texture_target, GL_TEXTURE_MIN_FILTER,
3749                 wined3d_gl_min_mip_filter(minMipLookup, Filter, WINED3DTEXF_NONE));
3750         checkGLcall("glTexParameteri");
3751         glTexParameteri(Src->texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
3752         glTexParameteri(Src->texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
3753         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3754         checkGLcall("glTexEnvi");
3755
3756         /* This is for color keying */
3757         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3758             glEnable(GL_ALPHA_TEST);
3759             checkGLcall("glEnable GL_ALPHA_TEST");
3760
3761             /* When the primary render target uses P8, the alpha component contains the palette index.
3762              * Which means that the colorkey is one of the palette entries. In other cases pixels that
3763              * should be masked away have alpha set to 0. */
3764             if(primary_render_target_is_p8(myDevice))
3765                 glAlphaFunc(GL_NOTEQUAL, (float)Src->SrcBltCKey.dwColorSpaceLowValue / 256.0f);
3766             else
3767                 glAlphaFunc(GL_NOTEQUAL, 0.0f);
3768             checkGLcall("glAlphaFunc");
3769         } else {
3770             glDisable(GL_ALPHA_TEST);
3771             checkGLcall("glDisable GL_ALPHA_TEST");
3772         }
3773
3774         /* Draw a textured quad
3775          */
3776         glBegin(GL_QUADS);
3777
3778         glColor3f(1.0f, 1.0f, 1.0f);
3779         glTexCoord2f(glTexCoord[0], glTexCoord[2]);
3780         glVertex3f(rect.x1, rect.y1, 0.0f);
3781
3782         glTexCoord2f(glTexCoord[0], glTexCoord[3]);
3783         glVertex3f(rect.x1, rect.y2, 0.0f);
3784
3785         glTexCoord2f(glTexCoord[1], glTexCoord[3]);
3786         glVertex3f(rect.x2, rect.y2, 0.0f);
3787
3788         glTexCoord2f(glTexCoord[1], glTexCoord[2]);
3789         glVertex3f(rect.x2, rect.y1, 0.0f);
3790
3791         glEnd();
3792         checkGLcall("glEnd");
3793
3794         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3795             glDisable(GL_ALPHA_TEST);
3796             checkGLcall("glDisable(GL_ALPHA_TEST)");
3797         }
3798
3799         glBindTexture(Src->texture_target, 0);
3800         checkGLcall("glBindTexture(Src->texture_target, 0)");
3801
3802         /* Restore the color key parameters */
3803         Src->CKeyFlags = oldCKeyFlags;
3804         Src->SrcBltCKey = oldBltCKey;
3805
3806         /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3807         if(paletteOverride)
3808             Src->palette = NULL;
3809
3810         LEAVE_GL();
3811
3812         /* Leave the opengl state valid for blitting */
3813         myDevice->blitter->unset_shader((IWineD3DDevice *) myDevice);
3814
3815         /* Flush in case the drawable is used by multiple GL contexts */
3816         if(dstSwapchain && (This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer || dstSwapchain->num_contexts >= 2))
3817             glFlush();
3818
3819         /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
3820         /* The surface is now in the drawable. On onscreen surfaces or without fbos the texture
3821          * is outdated now
3822          */
3823         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INDRAWABLE, TRUE);
3824
3825         return WINED3D_OK;
3826     } else {
3827         /* Source-Less Blit to render target */
3828         if (Flags & WINEDDBLT_COLORFILL) {
3829             /* This is easy to handle for the D3D Device... */
3830             DWORD color;
3831
3832             TRACE("Colorfill\n");
3833
3834             /* This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0] || dstSwapchain
3835                 must be true if we are here */
3836             if (This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0] &&
3837                     !(This == (IWineD3DSurfaceImpl*) dstSwapchain->frontBuffer ||
3838                       (dstSwapchain->backBuffer && This == (IWineD3DSurfaceImpl*) dstSwapchain->backBuffer[0]))) {
3839                 TRACE("Surface is higher back buffer, falling back to software\n");
3840                 return WINED3DERR_INVALIDCALL;
3841             }
3842
3843             /* The color as given in the Blt function is in the format of the frame-buffer...
3844              * 'clear' expect it in ARGB format => we need to do some conversion :-)
3845              */
3846             if (This->resource.format_desc->format == WINED3DFMT_P8)
3847             {
3848                 DWORD alpha;
3849
3850                 if (primary_render_target_is_p8(myDevice)) alpha = DDBltFx->u5.dwFillColor << 24;
3851                 else alpha = 0xFF000000;
3852
3853                 if (This->palette) {
3854                     color = (alpha |
3855                             (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
3856                             (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
3857                             (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
3858                 } else {
3859                     color = alpha;
3860                 }
3861             }
3862             else if (This->resource.format_desc->format == WINED3DFMT_R5G6B5)
3863             {
3864                 if (DDBltFx->u5.dwFillColor == 0xFFFF) {
3865                     color = 0xFFFFFFFF;
3866                 } else {
3867                     color = ((0xFF000000) |
3868                             ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
3869                             ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
3870                             ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
3871                 }
3872             }
3873             else if ((This->resource.format_desc->format == WINED3DFMT_R8G8B8)
3874                     || (This->resource.format_desc->format == WINED3DFMT_X8R8G8B8))
3875             {
3876                 color = 0xFF000000 | DDBltFx->u5.dwFillColor;
3877             }
3878             else if (This->resource.format_desc->format == WINED3DFMT_A8R8G8B8)
3879             {
3880                 color = DDBltFx->u5.dwFillColor;
3881             }
3882             else {
3883                 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
3884                 return WINED3DERR_INVALIDCALL;
3885             }
3886
3887             TRACE("(%p) executing Render Target override, color = %x\n", This, color);
3888             IWineD3DDeviceImpl_ClearSurface(myDevice, This, 1 /* Number of rectangles */,
3889                     &rect, WINED3DCLEAR_TARGET, color, 0.0f /* Z */, 0 /* Stencil */);
3890             return WINED3D_OK;
3891         }
3892     }
3893
3894     /* Default: Fall back to the generic blt. Not an error, a TRACE is enough */
3895     TRACE("Didn't find any usable render target setup for hw blit, falling back to software\n");
3896     return WINED3DERR_INVALIDCALL;
3897 }
3898
3899 static HRESULT IWineD3DSurfaceImpl_BltZ(IWineD3DSurfaceImpl *This, const RECT *DestRect,
3900         IWineD3DSurface *SrcSurface, const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx)
3901 {
3902     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3903     float depth;
3904
3905     if (Flags & WINEDDBLT_DEPTHFILL) {
3906         switch(This->resource.format_desc->format)
3907         {
3908             case WINED3DFMT_D16_UNORM:
3909                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x0000ffff;
3910                 break;
3911             case WINED3DFMT_D15S1:
3912                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x0000fffe;
3913                 break;
3914             case WINED3DFMT_D24S8:
3915             case WINED3DFMT_D24X8:
3916                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x00ffffff;
3917                 break;
3918             case WINED3DFMT_D32:
3919                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0xffffffff;
3920                 break;
3921             default:
3922                 depth = 0.0f;
3923                 ERR("Unexpected format for depth fill: %s\n", debug_d3dformat(This->resource.format_desc->format));
3924         }
3925
3926         return IWineD3DDevice_Clear((IWineD3DDevice *) myDevice,
3927                                     DestRect == NULL ? 0 : 1,
3928                                     (const WINED3DRECT *)DestRect,
3929                                     WINED3DCLEAR_ZBUFFER,
3930                                     0x00000000,
3931                                     depth,
3932                                     0x00000000);
3933     }
3934
3935     FIXME("(%p): Unsupp depthstencil blit\n", This);
3936     return WINED3DERR_INVALIDCALL;
3937 }
3938
3939 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, const RECT *DestRect, IWineD3DSurface *SrcSurface,
3940         const RECT *SrcRect, DWORD Flags, const WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) {
3941     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
3942     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3943     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3944     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
3945     TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
3946
3947     if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
3948     {
3949         WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
3950         return WINEDDERR_SURFACEBUSY;
3951     }
3952
3953     /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair,
3954      * except depth blits, which seem to work
3955      */
3956     if(iface == myDevice->stencilBufferTarget || (SrcSurface && SrcSurface == myDevice->stencilBufferTarget)) {
3957         if(myDevice->inScene && !(Flags & WINEDDBLT_DEPTHFILL)) {
3958             TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
3959             return WINED3DERR_INVALIDCALL;
3960         } else if(IWineD3DSurfaceImpl_BltZ(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) {
3961             TRACE("Z Blit override handled the blit\n");
3962             return WINED3D_OK;
3963         }
3964     }
3965
3966     /* Special cases for RenderTargets */
3967     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
3968         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
3969         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter) == WINED3D_OK) return WINED3D_OK;
3970     }
3971
3972     /* For the rest call the X11 surface implementation.
3973      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
3974      * other Blts are rather rare
3975      */
3976     return IWineD3DBaseSurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter);
3977 }
3978
3979 static HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty,
3980         IWineD3DSurface *Source, const RECT *rsrc, DWORD trans)
3981 {
3982     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3983     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
3984     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3985     TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
3986
3987     if ( (This->Flags & SFLAG_LOCKED) || ((srcImpl != NULL) && (srcImpl->Flags & SFLAG_LOCKED)))
3988     {
3989         WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
3990         return WINEDDERR_SURFACEBUSY;
3991     }
3992
3993     if(myDevice->inScene &&
3994        (iface == myDevice->stencilBufferTarget ||
3995        (Source && Source == myDevice->stencilBufferTarget))) {
3996         TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
3997         return WINED3DERR_INVALIDCALL;
3998     }
3999
4000     /* Special cases for RenderTargets */
4001     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
4002         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
4003
4004         RECT SrcRect, DstRect;
4005         DWORD Flags=0;
4006
4007         if(rsrc) {
4008             SrcRect.left = rsrc->left;
4009             SrcRect.top= rsrc->top;
4010             SrcRect.bottom = rsrc->bottom;
4011             SrcRect.right = rsrc->right;
4012         } else {
4013             SrcRect.left = 0;
4014             SrcRect.top = 0;
4015             SrcRect.right = srcImpl->currentDesc.Width;
4016             SrcRect.bottom = srcImpl->currentDesc.Height;
4017         }
4018
4019         DstRect.left = dstx;
4020         DstRect.top=dsty;
4021         DstRect.right = dstx + SrcRect.right - SrcRect.left;
4022         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
4023
4024         /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
4025         if(trans & WINEDDBLTFAST_SRCCOLORKEY)
4026             Flags |= WINEDDBLT_KEYSRC;
4027         if(trans & WINEDDBLTFAST_DESTCOLORKEY)
4028             Flags |= WINEDDBLT_KEYDEST;
4029         if(trans & WINEDDBLTFAST_WAIT)
4030             Flags |= WINEDDBLT_WAIT;
4031         if(trans & WINEDDBLTFAST_DONOTWAIT)
4032             Flags |= WINEDDBLT_DONOTWAIT;
4033
4034         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL, WINED3DTEXF_POINT) == WINED3D_OK) return WINED3D_OK;
4035     }
4036
4037
4038     return IWineD3DBaseSurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
4039 }
4040
4041 static HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface)
4042 {
4043     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4044     RGBQUAD col[256];
4045     IWineD3DPaletteImpl *pal = This->palette;
4046     unsigned int n;
4047     TRACE("(%p)\n", This);
4048
4049     if (!pal) return WINED3D_OK;
4050
4051     if (This->resource.format_desc->format == WINED3DFMT_P8
4052             || This->resource.format_desc->format == WINED3DFMT_A8P8)
4053     {
4054         int bpp;
4055         GLenum format, internal, type;
4056         CONVERT_TYPES convert;
4057
4058         /* Check if we are using a RTL mode which uses texturing for uploads */
4059         BOOL use_texture = (wined3d_settings.rendertargetlock_mode == RTL_READTEX);
4060
4061         /* Check if we have hardware palette conversion if we have convert is set to NO_CONVERSION */
4062         d3dfmt_get_conv(This, TRUE, use_texture, &format, &internal, &type, &convert, &bpp, FALSE);
4063
4064         if((This->resource.usage & WINED3DUSAGE_RENDERTARGET) && (convert == NO_CONVERSION))
4065         {
4066             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4067
4068             /* Make sure the texture is up to date. This call doesn't do anything if the texture is already up to date. */
4069             IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL);
4070
4071             /* We want to force a palette refresh, so mark the drawable as not being up to date */
4072             IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE);
4073
4074             /* Re-upload the palette */
4075             ActivateContext(device, NULL, CTXUSAGE_RESOURCELOAD);
4076             d3dfmt_p8_upload_palette(iface, convert);
4077         } else {
4078             if(!(This->Flags & SFLAG_INSYSMEM)) {
4079                 TRACE("Palette changed with surface that does not have an up to date system memory copy\n");
4080                 IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
4081             }
4082             TRACE("Dirtifying surface\n");
4083             IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
4084         }
4085     }
4086
4087     if(This->Flags & SFLAG_DIBSECTION) {
4088         TRACE("(%p): Updating the hdc's palette\n", This);
4089         for (n=0; n<256; n++) {
4090             col[n].rgbRed   = pal->palents[n].peRed;
4091             col[n].rgbGreen = pal->palents[n].peGreen;
4092             col[n].rgbBlue  = pal->palents[n].peBlue;
4093             col[n].rgbReserved = 0;
4094         }
4095         SetDIBColorTable(This->hDC, 0, 256, col);
4096     }
4097
4098     /* Propagate the changes to the drawable when we have a palette. */
4099     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
4100         IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, NULL);
4101
4102     return WINED3D_OK;
4103 }
4104
4105 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
4106     /** Check against the maximum texture sizes supported by the video card **/
4107     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4108     unsigned int pow2Width, pow2Height;
4109
4110     This->texture_name = 0;
4111     This->texture_target = GL_TEXTURE_2D;
4112
4113     /* Non-power2 support */
4114     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) {
4115         pow2Width = This->currentDesc.Width;
4116         pow2Height = This->currentDesc.Height;
4117     } else {
4118         /* Find the nearest pow2 match */
4119         pow2Width = pow2Height = 1;
4120         while (pow2Width < This->currentDesc.Width) pow2Width <<= 1;
4121         while (pow2Height < This->currentDesc.Height) pow2Height <<= 1;
4122     }
4123     This->pow2Width  = pow2Width;
4124     This->pow2Height = pow2Height;
4125
4126     if (pow2Width > This->currentDesc.Width || pow2Height > This->currentDesc.Height) {
4127         /** TODO: add support for non power two compressed textures **/
4128         if (This->resource.format_desc->Flags & WINED3DFMT_FLAG_COMPRESSED)
4129         {
4130             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
4131                   This, This->currentDesc.Width, This->currentDesc.Height);
4132             return WINED3DERR_NOTAVAILABLE;
4133         }
4134     }
4135
4136     if(pow2Width != This->currentDesc.Width ||
4137        pow2Height != This->currentDesc.Height) {
4138         This->Flags |= SFLAG_NONPOW2;
4139     }
4140
4141     TRACE("%p\n", This);
4142     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
4143         /* one of three options
4144         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)
4145         2: Set the texture to the maximum size (bad idea)
4146         3:    WARN and return WINED3DERR_NOTAVAILABLE;
4147         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.
4148         */
4149         WARN("(%p) Creating an oversized surface: %ux%u (texture is %ux%u)\n",
4150              This, This->pow2Width, This->pow2Height, This->currentDesc.Width, This->currentDesc.Height);
4151         This->Flags |= SFLAG_OVERSIZE;
4152
4153         /* This will be initialized on the first blt */
4154         This->glRect.left = 0;
4155         This->glRect.top = 0;
4156         This->glRect.right = 0;
4157         This->glRect.bottom = 0;
4158     } else {
4159         /* Check this after the oversize check - do not make an oversized surface a texture_rectangle one.
4160            Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
4161            is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE
4162            doesn't work in combination with ARB_TEXTURE_RECTANGLE.
4163         */
4164         if(This->Flags & SFLAG_NONPOW2 && GL_SUPPORT(ARB_TEXTURE_RECTANGLE)
4165                 && !((This->resource.format_desc->format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE)
4166                 && (wined3d_settings.rendertargetlock_mode == RTL_READTEX)))
4167         {
4168             This->texture_target = GL_TEXTURE_RECTANGLE_ARB;
4169             This->pow2Width  = This->currentDesc.Width;
4170             This->pow2Height = This->currentDesc.Height;
4171             This->Flags &= ~(SFLAG_NONPOW2 | SFLAG_NORMCOORD);
4172         }
4173
4174         /* No oversize, gl rect is the full texture size */
4175         This->Flags &= ~SFLAG_OVERSIZE;
4176         This->glRect.left = 0;
4177         This->glRect.top = 0;
4178         This->glRect.right = This->pow2Width;
4179         This->glRect.bottom = This->pow2Height;
4180     }
4181
4182     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
4183         switch(wined3d_settings.offscreen_rendering_mode) {
4184             case ORM_FBO:        This->get_drawable_size = get_drawable_size_fbo;        break;
4185             case ORM_PBUFFER:    This->get_drawable_size = get_drawable_size_pbuffer;    break;
4186             case ORM_BACKBUFFER: This->get_drawable_size = get_drawable_size_backbuffer; break;
4187         }
4188     }
4189
4190     This->Flags |= SFLAG_INSYSMEM;
4191
4192     return WINED3D_OK;
4193 }
4194
4195 struct depth_blt_info
4196 {
4197     GLenum binding;
4198     GLenum bind_target;
4199     enum tex_types tex_type;
4200     GLfloat coords[4][3];
4201 };
4202
4203 static void surface_get_depth_blt_info(GLenum target, GLsizei w, GLsizei h, struct depth_blt_info *info)
4204 {
4205     GLfloat (*coords)[3] = info->coords;
4206
4207     switch (target)
4208     {
4209         default:
4210             FIXME("Unsupported texture target %#x\n", target);
4211             /* Fall back to GL_TEXTURE_2D */
4212         case GL_TEXTURE_2D:
4213             info->binding = GL_TEXTURE_BINDING_2D;
4214             info->bind_target = GL_TEXTURE_2D;
4215             info->tex_type = tex_2d;
4216             coords[0][0] = 0.0f;    coords[0][1] = 1.0f;    coords[0][2] = 0.0f;
4217             coords[1][0] = 1.0f;    coords[1][1] = 1.0f;    coords[1][2] = 0.0f;
4218             coords[2][0] = 0.0f;    coords[2][1] = 0.0f;    coords[2][2] = 0.0f;
4219             coords[3][0] = 1.0f;    coords[3][1] = 0.0f;    coords[3][2] = 0.0f;
4220             break;
4221
4222         case GL_TEXTURE_RECTANGLE_ARB:
4223             info->binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
4224             info->bind_target = GL_TEXTURE_RECTANGLE_ARB;
4225             info->tex_type = tex_rect;
4226             coords[0][0] = 0.0f;    coords[0][1] = h;       coords[0][2] = 0.0f;
4227             coords[1][0] = w;       coords[1][1] = h;       coords[1][2] = 0.0f;
4228             coords[2][0] = 0.0f;    coords[2][1] = 0.0f;    coords[2][2] = 0.0f;
4229             coords[3][0] = w;       coords[3][1] = 0.0f;    coords[3][2] = 0.0f;
4230             break;
4231
4232         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4233             info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
4234             info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4235             info->tex_type = tex_cube;
4236             coords[0][0] =  1.0f;   coords[0][1] = -1.0f;   coords[0][2] =  1.0f;
4237             coords[1][0] =  1.0f;   coords[1][1] = -1.0f;   coords[1][2] = -1.0f;
4238             coords[2][0] =  1.0f;   coords[2][1] =  1.0f;   coords[2][2] =  1.0f;
4239             coords[3][0] =  1.0f;   coords[3][1] =  1.0f;   coords[3][2] = -1.0f;
4240
4241         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4242             info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
4243             info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4244             info->tex_type = tex_cube;
4245             coords[0][0] = -1.0f;   coords[0][1] = -1.0f;   coords[0][2] = -1.0f;
4246             coords[1][0] = -1.0f;   coords[1][1] = -1.0f;   coords[1][2] =  1.0f;
4247             coords[2][0] = -1.0f;   coords[2][1] =  1.0f;   coords[2][2] = -1.0f;
4248             coords[3][0] = -1.0f;   coords[3][1] =  1.0f;   coords[3][2] =  1.0f;
4249
4250         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4251             info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
4252             info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4253             info->tex_type = tex_cube;
4254             coords[0][0] = -1.0f;   coords[0][1] =  1.0f;   coords[0][2] =  1.0f;
4255             coords[1][0] =  1.0f;   coords[1][1] =  1.0f;   coords[1][2] =  1.0f;
4256             coords[2][0] = -1.0f;   coords[2][1] =  1.0f;   coords[2][2] = -1.0f;
4257             coords[3][0] =  1.0f;   coords[3][1] =  1.0f;   coords[3][2] = -1.0f;
4258
4259         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4260             info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
4261             info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4262             info->tex_type = tex_cube;
4263             coords[0][0] = -1.0f;   coords[0][1] = -1.0f;   coords[0][2] = -1.0f;
4264             coords[1][0] =  1.0f;   coords[1][1] = -1.0f;   coords[1][2] = -1.0f;
4265             coords[2][0] = -1.0f;   coords[2][1] = -1.0f;   coords[2][2] =  1.0f;
4266             coords[3][0] =  1.0f;   coords[3][1] = -1.0f;   coords[3][2] =  1.0f;
4267
4268         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4269             info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
4270             info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4271             info->tex_type = tex_cube;
4272             coords[0][0] = -1.0f;   coords[0][1] = -1.0f;   coords[0][2] =  1.0f;
4273             coords[1][0] =  1.0f;   coords[1][1] = -1.0f;   coords[1][2] =  1.0f;
4274             coords[2][0] = -1.0f;   coords[2][1] =  1.0f;   coords[2][2] =  1.0f;
4275             coords[3][0] =  1.0f;   coords[3][1] =  1.0f;   coords[3][2] =  1.0f;
4276
4277         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4278             info->binding = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
4279             info->bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4280             info->tex_type = tex_cube;
4281             coords[0][0] =  1.0f;   coords[0][1] = -1.0f;   coords[0][2] = -1.0f;
4282             coords[1][0] = -1.0f;   coords[1][1] = -1.0f;   coords[1][2] = -1.0f;
4283             coords[2][0] =  1.0f;   coords[2][1] =  1.0f;   coords[2][2] = -1.0f;
4284             coords[3][0] = -1.0f;   coords[3][1] =  1.0f;   coords[3][2] = -1.0f;
4285     }
4286 }
4287
4288 /* GL locking is done by the caller */
4289 static void surface_depth_blt(IWineD3DSurfaceImpl *This, GLuint texture, GLsizei w, GLsizei h, GLenum target)
4290 {
4291     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4292     struct depth_blt_info info;
4293     GLint old_binding = 0;
4294
4295     glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_VIEWPORT_BIT);
4296
4297     glDisable(GL_CULL_FACE);
4298     glDisable(GL_BLEND);
4299     glDisable(GL_ALPHA_TEST);
4300     glDisable(GL_SCISSOR_TEST);
4301     glDisable(GL_STENCIL_TEST);
4302     glEnable(GL_DEPTH_TEST);
4303     glDepthFunc(GL_ALWAYS);
4304     glDepthMask(GL_TRUE);
4305     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
4306     glViewport(0, 0, w, h);
4307
4308     surface_get_depth_blt_info(target, w, h, &info);
4309     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4310     glGetIntegerv(info.binding, &old_binding);
4311     glBindTexture(info.bind_target, texture);
4312
4313     device->shader_backend->shader_select_depth_blt((IWineD3DDevice *)device, info.tex_type);
4314
4315     glBegin(GL_TRIANGLE_STRIP);
4316     glTexCoord3fv(info.coords[0]);
4317     glVertex2f(-1.0f, -1.0f);
4318     glTexCoord3fv(info.coords[1]);
4319     glVertex2f(1.0f, -1.0f);
4320     glTexCoord3fv(info.coords[2]);
4321     glVertex2f(-1.0f, 1.0f);
4322     glTexCoord3fv(info.coords[3]);
4323     glVertex2f(1.0f, 1.0f);
4324     glEnd();
4325
4326     glBindTexture(info.bind_target, old_binding);
4327
4328     glPopAttrib();
4329
4330     device->shader_backend->shader_deselect_depth_blt((IWineD3DDevice *)device);
4331 }
4332
4333 void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location) {
4334     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
4335
4336     TRACE("(%p) New location %#x\n", This, location);
4337
4338     if (location & ~SFLAG_DS_LOCATIONS) {
4339         FIXME("(%p) Invalid location (%#x) specified\n", This, location);
4340     }
4341
4342     This->Flags &= ~SFLAG_DS_LOCATIONS;
4343     This->Flags |= location;
4344 }
4345
4346 /* Context activation is done by the caller. */
4347 void surface_load_ds_location(IWineD3DSurface *iface, struct wined3d_context *context, DWORD location)
4348 {
4349     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
4350     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4351
4352     TRACE("(%p) New location %#x\n", This, location);
4353
4354     /* TODO: Make this work for modes other than FBO */
4355     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
4356
4357     if (This->Flags & location) {
4358         TRACE("(%p) Location (%#x) is already up to date\n", This, location);
4359         return;
4360     }
4361
4362     if (This->current_renderbuffer) {
4363         FIXME("(%p) Not supported with fixed up depth stencil\n", This);
4364         return;
4365     }
4366
4367     if (location == SFLAG_DS_OFFSCREEN) {
4368         if (This->Flags & SFLAG_DS_ONSCREEN) {
4369             GLint old_binding = 0;
4370             GLenum bind_target;
4371
4372             TRACE("(%p) Copying onscreen depth buffer to depth texture\n", This);
4373
4374             ENTER_GL();
4375
4376             if (!device->depth_blt_texture) {
4377                 glGenTextures(1, &device->depth_blt_texture);
4378             }
4379
4380             /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
4381              * directly on the FBO texture. That's because we need to flip. */
4382             context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL);
4383             if (This->texture_target == GL_TEXTURE_RECTANGLE_ARB)
4384             {
4385                 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
4386                 bind_target = GL_TEXTURE_RECTANGLE_ARB;
4387             } else {
4388                 glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
4389                 bind_target = GL_TEXTURE_2D;
4390             }
4391             glBindTexture(bind_target, device->depth_blt_texture);
4392             glCopyTexImage2D(bind_target, This->texture_level, This->resource.format_desc->glInternal,
4393                     0, 0, This->currentDesc.Width, This->currentDesc.Height, 0);
4394             glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4395             glTexParameteri(bind_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4396             glTexParameteri(bind_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4397             glTexParameteri(bind_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4398             glTexParameteri(bind_target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4399             glTexParameteri(bind_target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
4400             glBindTexture(bind_target, old_binding);
4401
4402             /* Setup the destination */
4403             if (!device->depth_blt_rb) {
4404                 GL_EXTCALL(glGenRenderbuffersEXT(1, &device->depth_blt_rb));
4405                 checkGLcall("glGenRenderbuffersEXT");
4406             }
4407             if (device->depth_blt_rb_w != This->currentDesc.Width
4408                     || device->depth_blt_rb_h != This->currentDesc.Height) {
4409                 GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, device->depth_blt_rb));
4410                 checkGLcall("glBindRenderbufferEXT");
4411                 GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, This->currentDesc.Width, This->currentDesc.Height));
4412                 checkGLcall("glRenderbufferStorageEXT");
4413                 device->depth_blt_rb_w = This->currentDesc.Width;
4414                 device->depth_blt_rb_h = This->currentDesc.Height;
4415             }
4416
4417             context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->dst_fbo);
4418             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, device->depth_blt_rb));
4419             checkGLcall("glFramebufferRenderbufferEXT");
4420             context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER_EXT, iface, FALSE);
4421
4422             /* Do the actual blit */
4423             surface_depth_blt(This, device->depth_blt_texture, This->currentDesc.Width, This->currentDesc.Height, bind_target);
4424             checkGLcall("depth_blt");
4425
4426             if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->current_fbo->id);
4427             else context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL);
4428
4429             LEAVE_GL();
4430         } else {
4431             FIXME("No up to date depth stencil location\n");
4432         }
4433     } else if (location == SFLAG_DS_ONSCREEN) {
4434         if (This->Flags & SFLAG_DS_OFFSCREEN) {
4435             TRACE("(%p) Copying depth texture to onscreen depth buffer\n", This);
4436
4437             ENTER_GL();
4438
4439             context_bind_fbo(context, GL_FRAMEBUFFER_EXT, NULL);
4440             surface_depth_blt(This, This->texture_name, This->currentDesc.Width,
4441                     This->currentDesc.Height, This->texture_target);
4442             checkGLcall("depth_blt");
4443
4444             if (context->current_fbo) context_bind_fbo(context, GL_FRAMEBUFFER_EXT, &context->current_fbo->id);
4445
4446             LEAVE_GL();
4447         } else {
4448             FIXME("No up to date depth stencil location\n");
4449         }
4450     } else {
4451         ERR("(%p) Invalid location (%#x) specified\n", This, location);
4452     }
4453
4454     This->Flags |= location;
4455 }
4456
4457 static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DWORD flag, BOOL persistent) {
4458     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4459     IWineD3DBaseTexture *texture;
4460     IWineD3DSurfaceImpl *overlay;
4461
4462     TRACE("(%p)->(%s, %s)\n", iface, debug_surflocation(flag),
4463           persistent ? "TRUE" : "FALSE");
4464
4465     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4466         if (This->Flags & SFLAG_SWAPCHAIN)
4467         {
4468             TRACE("Surface %p is an onscreen surface\n", iface);
4469         } else {
4470             /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. */
4471             if (flag & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE)) flag |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
4472         }
4473     }
4474
4475     if(persistent) {
4476         if(((This->Flags & SFLAG_INTEXTURE) && !(flag & SFLAG_INTEXTURE)) ||
4477            ((This->Flags & SFLAG_INSRGBTEX) && !(flag & SFLAG_INSRGBTEX))) {
4478             if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
4479                 TRACE("Passing to container\n");
4480                 IWineD3DBaseTexture_SetDirty(texture, TRUE);
4481                 IWineD3DBaseTexture_Release(texture);
4482             }
4483         }
4484         This->Flags &= ~SFLAG_LOCATIONS;
4485         This->Flags |= flag;
4486
4487         /* Redraw emulated overlays, if any */
4488         if(flag & SFLAG_INDRAWABLE && !list_empty(&This->overlays)) {
4489             LIST_FOR_EACH_ENTRY(overlay, &This->overlays, IWineD3DSurfaceImpl, overlay_entry) {
4490                 IWineD3DSurface_DrawOverlay((IWineD3DSurface *) overlay);
4491             }
4492         }
4493     } else {
4494         if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) && (flag & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX))) {
4495             if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
4496                 TRACE("Passing to container\n");
4497                 IWineD3DBaseTexture_SetDirty(texture, TRUE);
4498                 IWineD3DBaseTexture_Release(texture);
4499             }
4500         }
4501         This->Flags &= ~flag;
4502     }
4503
4504     if(!(This->Flags & SFLAG_LOCATIONS)) {
4505         ERR("%p: Surface does not have any up to date location\n", This);
4506     }
4507 }
4508
4509 struct coords {
4510     GLfloat x, y, z;
4511 };
4512
4513 struct float_rect
4514 {
4515     float l;
4516     float t;
4517     float r;
4518     float b;
4519 };
4520
4521 static inline void cube_coords_float(const RECT *r, UINT w, UINT h, struct float_rect *f)
4522 {
4523     f->l = ((r->left * 2.0f) / w) - 1.0f;
4524     f->t = ((r->top * 2.0f) / h) - 1.0f;
4525     f->r = ((r->right * 2.0f) / w) - 1.0f;
4526     f->b = ((r->bottom * 2.0f) / h) - 1.0f;
4527 }
4528
4529 static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in)
4530 {
4531     const struct wined3d_context *context;
4532     struct coords coords[4];
4533     RECT rect;
4534     IWineD3DSwapChain *swapchain;
4535     IWineD3DBaseTexture *texture;
4536     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4537     GLenum bind_target;
4538     struct float_rect f;
4539
4540     if(rect_in) {
4541         rect = *rect_in;
4542     } else {
4543         rect.left = 0;
4544         rect.top = 0;
4545         rect.right = This->currentDesc.Width;
4546         rect.bottom = This->currentDesc.Height;
4547     }
4548
4549     switch (This->texture_target)
4550     {
4551         case GL_TEXTURE_2D:
4552             bind_target = GL_TEXTURE_2D;
4553
4554             coords[0].x = (float)rect.left / This->pow2Width;
4555             coords[0].y = (float)rect.top / This->pow2Height;
4556             coords[0].z = 0;
4557
4558             coords[1].x = (float)rect.left / This->pow2Width;
4559             coords[1].y = (float)rect.bottom / This->pow2Height;
4560             coords[1].z = 0;
4561
4562             coords[2].x = (float)rect.right / This->pow2Width;
4563             coords[2].y = (float)rect.bottom / This->pow2Height;
4564             coords[2].z = 0;
4565
4566             coords[3].x = (float)rect.right / This->pow2Width;
4567             coords[3].y = (float)rect.top / This->pow2Height;
4568             coords[3].z = 0;
4569             break;
4570
4571         case GL_TEXTURE_RECTANGLE_ARB:
4572             bind_target = GL_TEXTURE_RECTANGLE_ARB;
4573             coords[0].x = rect.left;    coords[0].y = rect.top;     coords[0].z = 0;
4574             coords[1].x = rect.left;    coords[1].y = rect.bottom;  coords[1].z = 0;
4575             coords[2].x = rect.right;   coords[2].y = rect.bottom;  coords[2].z = 0;
4576             coords[3].x = rect.right;   coords[3].y = rect.top;     coords[3].z = 0;
4577             break;
4578
4579         case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4580             bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4581             cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f);
4582             coords[0].x =    1; coords[0].y = -f.t; coords[0].z = -f.l;
4583             coords[1].x =    1; coords[1].y = -f.b; coords[1].z = -f.l;
4584             coords[2].x =    1; coords[2].y = -f.b; coords[2].z = -f.r;
4585             coords[3].x =    1; coords[3].y = -f.t; coords[3].z = -f.r;
4586             break;
4587
4588         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4589             bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4590             cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f);
4591             coords[0].x =   -1; coords[0].y = -f.t; coords[0].z =  f.l;
4592             coords[1].x =   -1; coords[1].y = -f.b; coords[1].z =  f.l;
4593             coords[2].x =   -1; coords[2].y = -f.b; coords[2].z =  f.r;
4594             coords[3].x =   -1; coords[3].y = -f.t; coords[3].z =  f.r;
4595             break;
4596
4597         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4598             bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4599             cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f);
4600             coords[0].x =  f.l; coords[0].y =    1; coords[0].z =  f.t;
4601             coords[1].x =  f.l; coords[1].y =    1; coords[1].z =  f.b;
4602             coords[2].x =  f.r; coords[2].y =    1; coords[2].z =  f.b;
4603             coords[3].x =  f.r; coords[3].y =    1; coords[3].z =  f.t;
4604             break;
4605
4606         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4607             bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4608             cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f);
4609             coords[0].x =  f.l; coords[0].y =   -1; coords[0].z = -f.t;
4610             coords[1].x =  f.l; coords[1].y =   -1; coords[1].z = -f.b;
4611             coords[2].x =  f.r; coords[2].y =   -1; coords[2].z = -f.b;
4612             coords[3].x =  f.r; coords[3].y =   -1; coords[3].z = -f.t;
4613             break;
4614
4615         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4616             bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4617             cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f);
4618             coords[0].x =  f.l; coords[0].y = -f.t; coords[0].z =    1;
4619             coords[1].x =  f.l; coords[1].y = -f.b; coords[1].z =    1;
4620             coords[2].x =  f.r; coords[2].y = -f.b; coords[2].z =    1;
4621             coords[3].x =  f.r; coords[3].y = -f.t; coords[3].z =    1;
4622             break;
4623
4624         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4625             bind_target = GL_TEXTURE_CUBE_MAP_ARB;
4626             cube_coords_float(&rect, This->pow2Width, This->pow2Height, &f);
4627             coords[0].x = -f.l; coords[0].y = -f.t; coords[0].z =   -1;
4628             coords[1].x = -f.l; coords[1].y = -f.b; coords[1].z =   -1;
4629             coords[2].x = -f.r; coords[2].y = -f.b; coords[2].z =   -1;
4630             coords[3].x = -f.r; coords[3].y = -f.t; coords[3].z =   -1;
4631             break;
4632
4633         default:
4634             ERR("Unexpected texture target %#x\n", This->texture_target);
4635             return;
4636     }
4637
4638     context = ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT);
4639
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 (context->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 };