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