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