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