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