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