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