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