2 * IWineD3DSurface Implementation
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 Stefan Dösinger for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/port.h"
29 #include "wined3d_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
50 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf);
52 static void surface_download_data(IWineD3DSurfaceImpl *This) {
53 if (This->resource.format == WINED3DFMT_DXT1 ||
54 This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
55 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
56 if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* We can assume this as the texture would not have been created otherwise */
57 FIXME("(%p) : Attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
59 TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
60 This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
64 GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory));
65 checkGLcall("glGetCompressedTexImageARB()");
70 TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
71 This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
75 glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat,
76 This->glDescription.glType, This->resource.allocatedMemory);
77 checkGLcall("glGetTexImage()");
81 if (wined3d_settings.nonpower2_mode == NP2_REPACK) {
83 * Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
84 * the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
85 * repack the texture so that the bpp * width pitch can be used instead of bpp * pow2width.
89 * instead of boxing the texture :
90 * |<-texture width ->| -->pow2width| /\
91 * |111111111111111111| | |
92 * |222 Texture 222222| boxed empty | texture height
93 * |3333 Data 33333333| | |
94 * |444444444444444444| | \/
95 * ----------------------------------- |
96 * | boxed empty | boxed empty | pow2height
98 * -----------------------------------
101 * we're repacking the data to the expected texture width
103 * |<-texture width ->| -->pow2width| /\
104 * |111111111111111111222222222222222| |
105 * |222333333333333333333444444444444| texture height
109 * | empty | pow2height
111 * -----------------------------------
115 * |<-texture width ->| /\
116 * |111111111111111111|
117 * |222222222222222222|texture height
118 * |333333333333333333|
119 * |444444444444444444| \/
120 * --------------------
122 * this also means that any references to allocatedMemory should work with the data as if were a
123 * standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
125 * internally the texture is still stored in a boxed format so any references to textureName will
126 * get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
129 if (This->Flags & SFLAG_NONPOW2) {
130 LPBYTE src_data, dst_data;
131 int src_pitch = This->bytesPerPixel * This->pow2Width;
132 int dst_pitch = This->bytesPerPixel * This->currentDesc.Width;
135 src_data = dst_data = This->resource.allocatedMemory;
136 FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, src_pitch, dst_pitch);
137 for (y = 1 ; y < This->currentDesc.Height; y++) {
138 /* skip the first row */
139 src_data += src_pitch;
140 dst_data += dst_pitch;
141 memcpy(dst_data, src_data, dst_pitch);
148 static void surface_upload_data(IWineD3DSurfaceImpl *This, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) {
149 if (This->resource.format == WINED3DFMT_DXT1 ||
150 This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
151 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
152 if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
153 FIXME("Using DXT1/3/5 without advertized support\n");
155 TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d, data %p\n", This, width, height, data);
157 GL_EXTCALL(glCompressedTexSubImage2DARB(This->glDescription.target, This->glDescription.level, 0, 0, width, height,
158 This->glDescription.glFormatInternal, This->resource.size, data));
159 checkGLcall("glCompressedTexSubImage2D");
163 TRACE("(%p) : Calling glTexSubImage2D w %d, h %d, data, %p\n", This, width, height, data);
165 glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, data);
166 checkGLcall("glTexSubImage2D");
171 static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) {
172 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,
173 This->glDescription.target, This->glDescription.level, debug_d3dformat(This->resource.format), internal, width, height, format, type);
177 glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type, NULL);
178 checkGLcall("glTexImage2D");
183 /* *******************************************
184 IWineD3DSurface IUnknown parts follow
185 ******************************************* */
186 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
188 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
189 /* Warn ,but be nice about things */
190 TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
192 ERR("Probably FIXME: Calling query interface with NULL riid\n");
194 if (IsEqualGUID(riid, &IID_IUnknown)
195 || IsEqualGUID(riid, &IID_IWineD3DBase)
196 || IsEqualGUID(riid, &IID_IWineD3DResource)
197 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
198 IUnknown_AddRef((IUnknown*)iface);
203 return E_NOINTERFACE;
206 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
207 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
208 ULONG ref = InterlockedIncrement(&This->resource.ref);
209 TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
213 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
214 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
215 ULONG ref = InterlockedDecrement(&This->resource.ref);
216 TRACE("(%p) : Releasing from %d\n", This, ref + 1);
218 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
219 TRACE("(%p) : cleaning up\n", This);
220 if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
222 TRACE("Deleting texture %d\n", This->glDescription.textureName);
223 glDeleteTextures(1, &This->glDescription.textureName);
227 if(This->Flags & SFLAG_DIBSECTION) {
229 SelectObject(This->hDC, This->dib.holdbitmap);
231 /* Release the DIB section */
232 DeleteObject(This->dib.DIBsection);
233 This->dib.bitmap_data = NULL;
234 This->resource.allocatedMemory = NULL;
236 if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL);
238 IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
239 if(iface == device->ddraw_primary)
240 device->ddraw_primary = NULL;
242 TRACE("(%p) Released\n", This);
243 HeapFree(GetProcessHeap(), 0, This);
249 /* ****************************************************
250 IWineD3DSurface IWineD3DResource parts follow
251 **************************************************** */
252 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
253 return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
256 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
257 return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
260 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
261 return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
264 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
265 return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
268 DWORD WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
269 return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
272 DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
273 return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
276 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
277 /* TODO: re-write the way textures and managed,
278 * use a 'opengl context manager' to manage RenderTarget surfaces
279 ** *********************************************************/
281 /* TODO: check for locks */
282 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
283 IWineD3DBaseTexture *baseTexture = NULL;
284 TRACE("(%p)Checking to see if the container is a base texture\n", This);
285 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
286 TRACE("Passing to conatiner\n");
287 IWineD3DBaseTexture_PreLoad(baseTexture);
288 IWineD3DBaseTexture_Release(baseTexture);
290 TRACE("(%p) : About to load surface\n", This);
292 #if 0 /* TODO: context manager support */
293 IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
295 glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
296 if (!This->glDescription.level) {
297 if (!This->glDescription.textureName) {
298 glGenTextures(1, &This->glDescription.textureName);
299 checkGLcall("glGenTextures");
300 TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
302 glBindTexture(This->glDescription.target, This->glDescription.textureName);
303 checkGLcall("glBindTexture");
304 IWineD3DSurface_LoadTexture(iface);
305 /* This is where we should be reducing the amount of GLMemoryUsed */
306 } else if (This->glDescription.textureName) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
307 /* assume this is a coding error not a real error for now */
308 FIXME("Mipmap surface has a glTexture bound to it!\n");
310 if (This->resource.pool == WINED3DPOOL_DEFAULT) {
311 /* Tell opengl to try and keep this texture in video ram (well mostly) */
314 glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
316 /* TODO: disable texture support, if it wastn't enabled when we entered. */
317 #if 0 /* TODO: context manager support */
318 IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
319 /* we don't care when the state is disabled(if atall) */);
326 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
327 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
328 return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
331 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
332 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
333 return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
336 /* ******************************************************
337 IWineD3DSurface IWineD3DSurface parts follow
338 ****************************************************** */
340 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
341 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
342 IWineD3DBase *container = 0;
344 TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
347 ERR("Called without a valid ppContainer.\n");
351 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
352 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
353 * GetContainer will return the Direct3D device used to create the surface.
355 if (This->container) {
356 container = This->container;
358 container = (IWineD3DBase *)This->resource.wineD3DDevice;
361 TRACE("Relaying to QueryInterface\n");
362 return IUnknown_QueryInterface(container, riid, ppContainer);
365 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
366 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
368 TRACE("(%p) : copying into %p\n", This, pDesc);
369 if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format;
370 if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType;
371 if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage;
372 if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool;
373 if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */
374 if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
375 if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
376 if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width;
377 if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height;
381 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
382 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
383 TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
384 if (This->glDescription.textureName == 0 && textureName != 0) {
385 This->Flags |= SFLAG_DIRTY;
386 IWineD3DSurface_AddDirtyRect(iface, NULL);
388 This->glDescription.textureName = textureName;
389 This->glDescription.target = target;
392 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
393 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
394 TRACE("(%p) : returning %p\n", This, &This->glDescription);
395 *glDescription = &This->glDescription;
398 /* TODO: think about moving this down to resource? */
399 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
400 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
401 /* 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 futture */
402 if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
403 FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
405 return (CONST void*)(This->resource.allocatedMemory);
408 static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) {
414 switch(This->resource.format)
418 /* GL can't return palettized data, so read ARGB pixels into a
419 * separate block of memory and convert them into palettized format
420 * in software. Slow, but if the app means to use palettized render
421 * targets and locks it...
423 * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
424 * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
425 * for the color channels when palettizing the colors.
428 type = GL_UNSIGNED_BYTE;
430 mem = HeapAlloc(GetProcessHeap(), 0, (rect->bottom - rect->top) * pitch);
432 ERR("Out of memory\n");
440 fmt = This->glDescription.glFormat;
441 type = This->glDescription.glType;
444 if (rect->left == 0 &&
445 rect->right == This->currentDesc.Width ) {
446 BYTE *row, *top, *bottom;
449 glReadPixels(0, rect->top,
450 This->currentDesc.Width,
451 rect->bottom - rect->top,
456 /* glReadPixels returns the image upside down, and there is no way to prevent this.
457 Flip the lines in software */
458 row = HeapAlloc(GetProcessHeap(), 0, pitch);
460 ERR("Out of memory\n");
464 bottom = ((BYTE *) mem) + pitch * ( rect->bottom - rect->top - 1);
465 for(i = 0; i < (rect->bottom - rect->top) / 2; i++) {
466 memcpy(row, top, pitch);
467 memcpy(top, bottom, pitch);
468 memcpy(bottom, row, pitch);
472 HeapFree(GetProcessHeap(), 0, row);
474 if(This->lockedRect.top == 0 && This->lockedRect.bottom == This->currentDesc.Height) {
475 This->Flags &= ~SFLAG_GLDIRTY;
478 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
479 glReadPixels(rect->left,
480 rect->bottom - j - 1,
481 rect->right - rect->left,
485 (char *)mem + (pitch * (j-rect->top)));
489 vcheckGLcall("glReadPixels");
491 if(This->resource.format == WINED3DFMT_P8) {
493 DWORD width = pitch / 3;
496 pal = This->palette->palents;
498 pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
501 for(y = rect->top; y < rect->bottom; y++) {
502 for(x = rect->left; x < rect->right; x++) {
503 /* start lines pixels */
504 BYTE *blue = (BYTE *) ((BYTE *) mem) + y * pitch + x * (sizeof(BYTE) * 3);
505 BYTE *green = blue + 1;
506 BYTE *red = green + 1;
508 for(c = 0; c < 256; c++) {
509 if(*red == pal[c].peRed &&
510 *green == pal[c].peGreen &&
511 *blue == pal[c].peBlue)
513 *((BYTE *) dest + y * width + x) = c;
519 HeapFree(GetProcessHeap(), 0, mem);
523 static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
524 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
525 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
526 IWineD3DSwapChainImpl *swapchain = NULL;
527 static UINT messages = 0; /* holds flags to disable fixme messages */
528 BOOL backbuf = FALSE;
530 /* fixme: should we really lock as such? */
531 if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INPBUFFER)) ==
532 (SFLAG_INTEXTURE | SFLAG_INPBUFFER) ) {
533 FIXME("Warning: Surface is in texture memory or pbuffer\n");
534 This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INPBUFFER);
537 if (!(This->Flags & SFLAG_LOCKABLE)) {
538 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
539 texture regions, and since the destination is an unlockable region we need
541 TRACE("Warning: trying to lock unlockable surf@%p\n", This);
542 /*return WINED3DERR_INVALIDCALL; */
545 if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
546 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
548 if (swapchain != NULL || iface == myDevice->render_targets[0] || iface == myDevice->depthStencilBuffer) {
549 if(swapchain != NULL) {
551 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
552 if(iface == swapchain->backBuffer[i]) {
559 TRACE("(%p, backBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
560 } else if (swapchain != NULL && iface == swapchain->frontBuffer) {
561 TRACE("(%p, frontBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
562 } else if (iface == myDevice->render_targets[0]) {
563 TRACE("(%p, renderTarget) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
564 } else if (iface == myDevice->depthStencilBuffer) {
565 TRACE("(%p, stencilBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
568 if (NULL != swapchain) {
569 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
574 TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
577 pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
580 pLockedRect->pBits = This->resource.allocatedMemory;
581 This->lockedRect.left = 0;
582 This->lockedRect.top = 0;
583 This->lockedRect.right = This->currentDesc.Width;
584 This->lockedRect.bottom = This->currentDesc.Height;
585 TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n", &This->lockedRect, This->lockedRect.left, This->lockedRect.top, This->lockedRect.right, This->lockedRect.bottom);
587 TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
589 if ((pRect->top < 0) ||
591 (pRect->left >= pRect->right) ||
592 (pRect->top >= pRect->bottom) ||
593 (pRect->right > This->currentDesc.Width) ||
594 (pRect->bottom > This->currentDesc.Height))
596 WARN(" Invalid values in pRect !!!\n");
597 return D3DERR_INVALIDCALL;
600 if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
601 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
603 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
605 This->lockedRect.left = pRect->left;
606 This->lockedRect.top = pRect->top;
607 This->lockedRect.right = pRect->right;
608 This->lockedRect.bottom = pRect->bottom;
611 if (This->Flags & SFLAG_NONPOW2) {
612 TRACE("Locking non-power 2 texture\n");
615 if (0 == This->resource.usage || This->resource.usage & WINED3DUSAGE_DYNAMIC) {
616 /* classic surface TODO: non 2d surfaces?
617 These resources may be POOL_SYSTEMMEM, so they must not access the device */
618 TRACE("locking an ordinarary surface\n");
619 /* Check to see if memory has already been allocated from the surface*/
620 if ((NULL == This->resource.allocatedMemory) ||
621 (This->Flags & SFLAG_GLDIRTY) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
622 /* Non-system memory surfaces */
624 This->Flags &= ~SFLAG_GLDIRTY;
626 /*Surface has no memory currently allocated to it!*/
627 TRACE("(%p) Locking rect\n" , This);
628 if(!This->resource.allocatedMemory) {
629 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
631 if (0 != This->glDescription.textureName) {
632 /* Now I have to copy thing bits back */
633 This->Flags |= SFLAG_ACTIVELOCK; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
634 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
636 /* Make sure that the texture is loaded */
637 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
639 surface_download_data(This);
641 } else { /* Nothing to do */
642 TRACE("Memory %p already allocted for texture\n", This->resource.allocatedMemory);
646 pLockedRect->pBits = This->resource.allocatedMemory;
648 if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
649 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
651 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
655 } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage ){ /* render surfaces */
656 if((!(Flags&WINED3DLOCK_DISCARD) && (This->Flags & SFLAG_GLDIRTY)) || !This->resource.allocatedMemory) {
659 BOOL notInContext = FALSE;
660 IWineD3DSwapChainImpl *targetSwapChain = NULL;
666 * for render->surface copy begin to begin of allocatedMemory
667 * unlock can be more easy
670 TRACE("locking a render target\n");
672 if (This->resource.allocatedMemory == NULL)
673 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
675 This->Flags |= SFLAG_ACTIVELOCK; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
676 pLockedRect->pBits = This->resource.allocatedMemory;
679 vcheckGLcall("glFlush");
680 glGetIntegerv(GL_READ_BUFFER, &prev_read);
681 vcheckGLcall("glIntegerv");
682 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
683 vcheckGLcall("glIntegerv");
685 /* Here's what we have to do:
686 See if the swapchain has the same context as the renderTarget or the surface is the render target.
687 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
688 and use the front back buffer as required.
689 if not, we need to switch contexts and then switchback at the end.
691 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
692 IWineD3DSurface_GetContainer(myDevice->render_targets[0], &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
694 /* NOTE: In a shared context environment the renderTarget will use the same context as the implicit swapchain (we're not in a shared environment yet! */
695 if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->render_targets[0]) {
696 if (swapchain && iface == swapchain->frontBuffer) {
697 TRACE("locking front\n");
698 glReadBuffer(GL_FRONT);
700 else if (iface == myDevice->render_targets[0] || backbuf) {
701 TRACE("locking back buffer\n");
702 glReadBuffer(GL_BACK);
703 } else if (iface == myDevice->depthStencilBuffer) {
704 FIXME("Stencil Buffer lock unsupported for now\n");
706 FIXME("(%p) Shouldn't have got here!\n", This);
707 glReadBuffer(GL_BACK);
709 } else if (swapchain != NULL) {
710 IWineD3DSwapChainImpl *implSwapChain;
711 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
712 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
713 /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
715 glReadBuffer(GL_BACK);
716 } else if (iface == swapchain->frontBuffer) {
717 glReadBuffer(GL_FRONT);
718 } else if (iface == myDevice->depthStencilBuffer) {
719 FIXME("Stencil Buffer lock unsupported for now\n");
721 FIXME("Should have got here!\n");
722 glReadBuffer(GL_BACK);
725 /* We need to switch contexts to be able to read the buffer!!! */
726 FIXME("The buffer requested isn't in the current openGL context\n");
728 /* TODO: check the contexts, to see if were shared with the current context */
730 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
732 if (swapchain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
733 if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
735 /** the depth stencil in openGL has a format of GL_FLOAT
736 * which should be good for WINED3DFMT_D16_LOCKABLE
738 * it is unclear what format the stencil buffer is in except.
739 * 'Each index is converted to fixed point...
740 * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
741 * mappings in the table GL_PIXEL_MAP_S_TO_S.
742 * glReadPixels(This->lockedRect.left,
743 * This->lockedRect.bottom - j - 1,
744 * This->lockedRect.right - This->lockedRect.left,
746 * GL_DEPTH_COMPONENT,
748 * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
749 *****************************************/
750 if (!notInContext) { /* Only read the buffer if it's in the current context */
751 switch(wined3d_settings.rendertargetlock_mode) {
755 read_from_framebuffer(This, &This->lockedRect, pLockedRect->pBits, pLockedRect->Pitch);
760 read_from_framebuffer(This, &This->lockedRect, pLockedRect->pBits, pLockedRect->Pitch);
761 FIXME("Reading from render target with a texture isn't implemented yet, falling back to framebuffer reading\n");
766 static BOOL warned = FALSE;
768 ERR("Application tries to lock the render target, but render target locking is disabled\n");
775 TRACE("Resetting buffer\n");
777 glReadBuffer(prev_read);
778 vcheckGLcall("glReadBuffer");
782 } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
785 FIXME("TODO stencil depth surface locking surf%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
788 glReadPixels(This->lockedRect.left,
789 This->lockedRect.bottom - j - 1,
790 This->lockedRect.right - This->lockedRect.left,
792 GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
799 FIXME("unsupported locking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
802 if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
805 IWineD3DBaseTexture *pBaseTexture;
808 * as seen in msdn docs
810 IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
812 /** Dirtify Container if needed */
813 if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
814 TRACE("Making container dirty\n");
815 IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
816 IWineD3DBaseTexture_Release(pBaseTexture);
818 TRACE("Surface is standalone, no need to dirty the container\n");
822 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Flags & SFLAG_DIRTY ? 0 : 1);
824 This->Flags |= SFLAG_LOCKED;
828 static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) {
830 GLint prev_rasterpos[4];
832 BOOL storechanged = FALSE;
836 glDisable(GL_TEXTURE_2D);
837 vcheckGLcall("glDisable(GL_TEXTURE_2D)");
838 glDisable(GL_TEXTURE_1D);
839 vcheckGLcall("glDisable(GL_TEXTURE_1D)");
842 vcheckGLcall("glFlush");
843 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
844 vcheckGLcall("glIntegerv");
845 glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
846 vcheckGLcall("glIntegerv");
847 glPixelZoom(1.0, -1.0);
848 vcheckGLcall("glPixelZoom");
850 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
851 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
852 glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
854 glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
855 vcheckGLcall("glRasterPos2f");
857 /* Some drivers(radeon dri, others?) don't like exceptions during
858 * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
859 * after ReleaseDC. Reading it will cause an exception, which x11drv will
860 * catch to put the dib section in InSync mode, which leads to a crash
861 * and a blocked x server on my radeon card.
863 * The following lines read the dib section so it is put in inSync mode
864 * before glDrawPixels is called and the crash is prevented. There won't
865 * be any interfering gdi accesses, because UnlockRect is called from
866 * ReleaseDC, and the app won't use the dc any more afterwards.
868 if(This->Flags & SFLAG_DIBSECTION) {
870 read = This->resource.allocatedMemory[0];
873 switch (This->resource.format) {
874 /* No special care needed */
875 case WINED3DFMT_A4R4G4B4:
876 case WINED3DFMT_R5G6B5:
877 case WINED3DFMT_A1R5G5B5:
878 case WINED3DFMT_R8G8B8:
879 type = This->glDescription.glType;
880 fmt = This->glDescription.glFormat;
881 mem = This->resource.allocatedMemory;
884 case WINED3DFMT_X4R4G4B4:
887 unsigned short *data;
888 data = (unsigned short *)This->resource.allocatedMemory;
889 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
895 type = This->glDescription.glType;
896 fmt = This->glDescription.glFormat;
897 mem = This->resource.allocatedMemory;
901 case WINED3DFMT_X1R5G5B5:
904 unsigned short *data;
905 data = (unsigned short *)This->resource.allocatedMemory;
906 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
912 type = This->glDescription.glType;
913 fmt = This->glDescription.glFormat;
914 mem = This->resource.allocatedMemory;
918 case WINED3DFMT_X8R8G8B8:
920 /* make sure the X byte is set to alpha on, since it
921 could be any random value. This fixes the intro movie in Pirates! */
924 data = (unsigned int *)This->resource.allocatedMemory;
925 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
934 case WINED3DFMT_A8R8G8B8:
936 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
937 vcheckGLcall("glPixelStorei");
939 type = This->glDescription.glType;
940 fmt = This->glDescription.glFormat;
941 mem = This->resource.allocatedMemory;
945 case WINED3DFMT_A2R10G10B10:
947 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
948 vcheckGLcall("glPixelStorei");
950 type = This->glDescription.glType;
951 fmt = This->glDescription.glFormat;
952 mem = This->resource.allocatedMemory;
958 UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This); /* target is argb, 4 byte */
959 int height = This->glRect.bottom - This->glRect.top;
960 type = GL_UNSIGNED_BYTE;
963 mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * sizeof(DWORD));
965 ERR("Out of memory\n");
968 d3dfmt_convert_surface(This->resource.allocatedMemory,
980 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
983 type = This->glDescription.glType;
984 fmt = This->glDescription.glFormat;
985 mem = This->resource.allocatedMemory;
988 glDrawPixels(This->lockedRect.right - This->lockedRect.left,
989 (This->lockedRect.bottom - This->lockedRect.top)-1,
992 checkGLcall("glDrawPixels");
993 glPixelZoom(1.0,1.0);
994 vcheckGLcall("glPixelZoom");
996 glRasterPos3iv(&prev_rasterpos[0]);
997 vcheckGLcall("glRasterPos3iv");
999 /* Reset to previous pack row length */
1000 glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
1001 vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
1003 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1004 vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES");
1007 if(mem != This->resource.allocatedMemory) HeapFree(GetProcessHeap(), 0, mem);
1011 static void flush_to_framebuffer_texture(IWineD3DSurface *iface) {
1012 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1013 float glTexCoord[4];
1015 glTexCoord[0] = 0.0; /* left */
1016 glTexCoord[1] = (float) This->currentDesc.Width / (float) This->pow2Width; /* right */
1017 glTexCoord[2] = 0.0; /* top */
1018 glTexCoord[3] = (float) This->currentDesc.Height / (float) This->pow2Height; /* bottom */
1020 IWineD3DSurface_PreLoad(iface);
1024 /* Disable some fancy graphics effects */
1025 glDisable(GL_LIGHTING);
1026 checkGLcall("glDisable GL_LIGHTING");
1027 glDisable(GL_DEPTH_TEST);
1028 checkGLcall("glDisable GL_DEPTH_TEST");
1030 checkGLcall("glDisable GL_FOG");
1031 glDisable(GL_CULL_FACE);
1032 checkGLcall("glDisable GL_CULL_FACE");
1033 glDisable(GL_BLEND);
1034 checkGLcall("glDisable GL_BLEND");
1035 glDisable(GL_STENCIL_TEST);
1036 checkGLcall("glDisable GL_STENCIL_TEST");
1038 glEnable(GL_TEXTURE_2D);
1039 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
1040 checkGLcall("glEnable glBindTexture");
1042 /* No filtering for blts */
1043 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1044 checkGLcall("glTexParameteri");
1045 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1046 checkGLcall("glTexParameteri");
1048 /* Start drawing a quad */
1051 glColor3d(1.0f, 1.0f, 1.0f);
1052 glTexCoord2f(glTexCoord[0], glTexCoord[2]);
1053 glVertex3f(0, 0, 0.0);
1055 glTexCoord2f(glTexCoord[0], glTexCoord[3]);
1056 glVertex3f(0, This->currentDesc.Height, 0.0);
1058 glTexCoord2f(glTexCoord[1], glTexCoord[3]);
1059 glVertex3d(This->currentDesc.Width, This->currentDesc.Height, 0.0);
1061 glTexCoord2f(glTexCoord[1], glTexCoord[2]);
1062 glVertex3f(This->currentDesc.Width, 0, 0.0);
1065 checkGLcall("glEnd");
1067 /* Unbind the texture */
1068 glBindTexture(GL_TEXTURE_2D, 0);
1069 checkGLcall("glEnable glBindTexture");
1074 static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
1075 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1076 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
1077 const char *buffername = "";
1078 IWineD3DSwapChainImpl *swapchain = NULL;
1079 BOOL backbuf = FALSE;
1081 if (!(This->Flags & SFLAG_LOCKED)) {
1082 WARN("trying to Unlock an unlocked surf@%p\n", This);
1083 return WINED3DERR_INVALIDCALL;
1086 if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
1087 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1091 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
1092 if(iface == swapchain->backBuffer[i]) {
1100 buffername = "backBuffer";
1101 } else if ((swapchain != NULL) && iface == swapchain->frontBuffer) {
1102 buffername = "frontBuffer";
1103 } else if (iface == myDevice->depthStencilBuffer) {
1104 buffername = "depthStencilBuffer";
1105 } else if (iface == myDevice->render_targets[0]) {
1106 buffername = "renderTarget";
1110 if (swapchain != NULL) {
1111 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
1114 TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Flags & SFLAG_DIRTY ? 1 : 0);
1116 if (!(This->Flags & SFLAG_DIRTY)) {
1117 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
1121 if (0 == This->resource.usage) { /* classic surface */
1122 IWineD3DBaseTextureImpl *impl;
1123 /* Check if the texture is bound, if yes dirtify the sampler to force a re-upload of the texture
1124 * Can't load the texture here because PreLoad may destroy and recreate the gl texture, so sampler
1125 * states need resetting
1127 if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) {
1128 if(impl->baseTexture.bindCount) {
1129 IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler));
1131 IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl);
1133 } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
1135 /****************************
1136 * TODO: Render targets are 'special' and
1137 * ?some? locking needs to be passed onto the context manager
1138 * so that it becomes possible to use auxiliary buffers, pbuffers
1139 * render-to-texture, shared, cached contexts etc...
1140 * ****************************/
1141 IWineD3DSwapChainImpl *implSwapChain;
1142 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
1144 if ((backbuf || iface == implSwapChain->frontBuffer || iface == myDevice->render_targets[0]) && wined3d_settings.rendertargetlock_mode != RTL_DISABLE) {
1149 /* glDrawPixels transforms the raster position as though it was a vertex -
1150 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
1151 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
1152 d3ddevice_set_ortho(This->resource.wineD3DDevice);
1153 IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
1155 if (iface == implSwapChain->frontBuffer) {
1156 glDrawBuffer(GL_FRONT);
1157 checkGLcall("glDrawBuffer GL_FRONT");
1158 } else if (backbuf || iface == myDevice->render_targets[0]) {
1159 glDrawBuffer(GL_BACK);
1160 checkGLcall("glDrawBuffer GL_BACK");
1163 /* Disable higher textures before calling glDrawPixels */
1164 for(tex = 1; tex < GL_LIMITS(samplers); tex++) {
1165 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1166 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + tex));
1167 checkGLcall("glActiveTextureARB");
1169 IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(tex));
1170 glDisable(GL_TEXTURE_2D);
1171 checkGLcall("glDisable GL_TEXTURE_2D");
1172 glDisable(GL_TEXTURE_1D);
1173 checkGLcall("glDisable GL_TEXTURE_1D");
1175 /* Activate texture 0, but don't disable it necessarily */
1176 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1177 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
1178 checkGLcall("glActiveTextureARB");
1180 IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0));
1182 /* And back buffers are not blended. Disable the depth test,
1183 that helps performance */
1184 glDisable(GL_BLEND);
1185 glDisable(GL_DEPTH_TEST);
1188 switch(wined3d_settings.rendertargetlock_mode) {
1192 flush_to_framebuffer_drawpixels(This);
1197 flush_to_framebuffer_texture(iface);
1202 static BOOL warned = FALSE;
1204 ERR("The application tries to write to the render target, but render target locking is disabled\n");
1211 if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
1212 glDrawBuffer(GL_BACK);
1213 vcheckGLcall("glDrawBuffer");
1215 if(myDevice->stateBlock->renderState[WINED3DRS_ZENABLE] == WINED3DZB_TRUE ||
1216 myDevice->stateBlock->renderState[WINED3DRS_ZENABLE] == WINED3DZB_USEW) glEnable(GL_DEPTH_TEST);
1217 if (myDevice->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
1218 if (myDevice->stateBlock->renderState[WINED3DRS_FOGENABLE]) glEnable(GL_FOG);
1222 /** restore clean dirty state */
1223 IWineD3DSurface_CleanDirtyRect(iface);
1225 } else if(wined3d_settings.rendertargetlock_mode != RTL_DISABLE) {
1226 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1228 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
1230 } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
1232 if (iface == myDevice->depthStencilBuffer) {
1233 FIXME("TODO stencil depth surface unlocking surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1235 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1239 FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1243 This->Flags &= ~SFLAG_LOCKED;
1244 memset(&This->lockedRect, 0, sizeof(RECT));
1248 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
1249 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1250 WINED3DLOCKED_RECT lock;
1257 const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1259 TRACE("(%p)->(%p)\n",This,pHDC);
1261 if(This->Flags & SFLAG_USERPTR) {
1262 ERR("Not supported on surfaces with an application-provided surfaces\n");
1266 /* Give more detailed info for ddraw */
1267 if (This->Flags & SFLAG_DCINUSE)
1268 return DDERR_DCALREADYCREATED;
1270 /* Can't GetDC if the surface is locked */
1271 if (This->Flags & SFLAG_LOCKED)
1272 return WINED3DERR_INVALIDCALL;
1274 memset(&lock, 0, sizeof(lock)); /* To be sure */
1276 /* Create a DIB section if there isn't a hdc yet */
1279 SYSTEM_INFO sysInfo;
1281 if(This->Flags & SFLAG_ACTIVELOCK) {
1282 ERR("Creating a DIB section while a lock is active. Uncertain consequences\n");
1285 switch (This->bytesPerPixel) {
1288 /* Allocate extra space to store the RGB bit masks. */
1289 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
1293 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
1297 /* Allocate extra space for a palette. */
1298 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1299 sizeof(BITMAPINFOHEADER)
1301 * (1 << (This->bytesPerPixel * 8)));
1306 return E_OUTOFMEMORY;
1308 /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
1309 * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
1310 * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
1311 * add an extra line to the dib section
1313 GetSystemInfo(&sysInfo);
1314 if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) {
1316 TRACE("Adding an extra line to the dib section\n");
1319 b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1320 if( (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
1321 b_info->bmiHeader.biWidth = This->currentDesc.Width;
1322 b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
1323 b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
1324 /* Use the full pow2 image size(assigned below) because LockRect
1325 * will need it for a full glGetTexImage call
1328 b_info->bmiHeader.biWidth = This->pow2Width;
1329 b_info->bmiHeader.biHeight = -This->pow2Height -extraline;
1330 b_info->bmiHeader.biSizeImage = This->resource.size + extraline * IWineD3DSurface_GetPitch(iface);
1332 b_info->bmiHeader.biPlanes = 1;
1333 b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
1335 b_info->bmiHeader.biXPelsPerMeter = 0;
1336 b_info->bmiHeader.biYPelsPerMeter = 0;
1337 b_info->bmiHeader.biClrUsed = 0;
1338 b_info->bmiHeader.biClrImportant = 0;
1340 /* Get the bit masks */
1341 masks = (DWORD *) &(b_info->bmiColors);
1342 switch (This->resource.format) {
1343 case WINED3DFMT_R8G8B8:
1344 usage = DIB_RGB_COLORS;
1345 b_info->bmiHeader.biCompression = BI_RGB;
1348 case WINED3DFMT_X1R5G5B5:
1349 case WINED3DFMT_A1R5G5B5:
1350 case WINED3DFMT_A4R4G4B4:
1351 case WINED3DFMT_X4R4G4B4:
1352 case WINED3DFMT_R3G3B2:
1353 case WINED3DFMT_A8R3G3B2:
1354 case WINED3DFMT_A2B10G10R10:
1355 case WINED3DFMT_A8B8G8R8:
1356 case WINED3DFMT_X8B8G8R8:
1357 case WINED3DFMT_A2R10G10B10:
1358 case WINED3DFMT_R5G6B5:
1359 case WINED3DFMT_A16B16G16R16:
1361 b_info->bmiHeader.biCompression = BI_BITFIELDS;
1362 masks[0] = formatEntry->redMask;
1363 masks[1] = formatEntry->greenMask;
1364 masks[2] = formatEntry->blueMask;
1368 /* Don't know palette */
1369 b_info->bmiHeader.biCompression = BI_RGB;
1376 HeapFree(GetProcessHeap(), 0, b_info);
1377 return HRESULT_FROM_WIN32(GetLastError());
1380 TRACE("Creating a DIB section with size %dx%dx%d, size=%d\n", b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
1381 This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
1384 if (!This->dib.DIBsection) {
1385 ERR("CreateDIBSection failed!\n");
1386 HeapFree(GetProcessHeap(), 0, b_info);
1387 return HRESULT_FROM_WIN32(GetLastError());
1390 TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
1392 /* copy the existing surface to the dib section */
1393 if(This->resource.allocatedMemory) {
1394 memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, b_info->bmiHeader.biSizeImage);
1395 /* We won't need that any more */
1396 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1398 /* This is to make LockRect read the gl Texture although memory is allocated */
1399 This->Flags |= SFLAG_GLDIRTY;
1402 HeapFree(GetProcessHeap(), 0, b_info);
1404 /* Use the dib section from now on */
1405 This->resource.allocatedMemory = This->dib.bitmap_data;
1407 /* Now allocate a HDC */
1408 This->hDC = CreateCompatibleDC(0);
1409 This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
1410 TRACE("using wined3d palette %p\n", This->palette);
1411 SelectPalette(This->hDC,
1412 This->palette ? This->palette->hpal : 0,
1415 This->Flags |= SFLAG_DIBSECTION;
1418 /* Lock the surface */
1419 hr = IWineD3DSurface_LockRect(iface,
1424 ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
1425 /* keep the dib section */
1429 if(This->resource.format == WINED3DFMT_P8 ||
1430 This->resource.format == WINED3DFMT_A8P8) {
1433 PALETTEENTRY ent[256];
1435 GetPaletteEntries(This->palette->hpal, 0, 256, ent);
1436 for (n=0; n<256; n++) {
1437 col[n].rgbRed = ent[n].peRed;
1438 col[n].rgbGreen = ent[n].peGreen;
1439 col[n].rgbBlue = ent[n].peBlue;
1440 col[n].rgbReserved = 0;
1443 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1445 for (n=0; n<256; n++) {
1446 col[n].rgbRed = device->palettes[device->currentPalette][n].peRed;
1447 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1448 col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue;
1449 col[n].rgbReserved = 0;
1453 SetDIBColorTable(This->hDC, 0, 256, col);
1457 TRACE("returning %p\n",*pHDC);
1458 This->Flags |= SFLAG_DCINUSE;
1463 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1464 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1466 TRACE("(%p)->(%p)\n",This,hDC);
1468 if (!(This->Flags & SFLAG_DCINUSE))
1469 return D3DERR_INVALIDCALL;
1471 /* we locked first, so unlock now */
1472 IWineD3DSurface_UnlockRect(iface);
1474 This->Flags &= ~SFLAG_DCINUSE;
1479 /* ******************************************************
1480 IWineD3DSurface Internal (No mapping to directx api) parts follow
1481 ****************************************************** */
1483 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) {
1484 BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & DDSD_CKSRCBLT);
1485 const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1487 /* Default values: From the surface */
1488 *format = formatEntry->glFormat;
1489 *internal = formatEntry->glInternal;
1490 *type = formatEntry->glType;
1491 *convert = NO_CONVERSION;
1492 *target_bpp = This->bytesPerPixel;
1494 /* Ok, now look if we have to do any conversion */
1495 switch(This->resource.format) {
1500 /* Use conversion when the paletted texture extension is not available, or when it is available make sure it is used
1501 * for texturing as it won't work for calls like glDraw-/glReadPixels and further also use conversion in case of color keying.
1503 if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) || colorkey_active || (!use_texturing && GL_SUPPORT(EXT_PALETTED_TEXTURE)) ) {
1505 *internal = GL_RGBA;
1506 *type = GL_UNSIGNED_BYTE;
1508 if(colorkey_active) {
1509 *convert = CONVERT_PALETTED_CK;
1511 *convert = CONVERT_PALETTED;
1517 case WINED3DFMT_R3G3B2:
1518 /* **********************
1519 GL_UNSIGNED_BYTE_3_3_2
1520 ********************** */
1521 if (colorkey_active) {
1522 /* This texture format will never be used.. So do not care about color keying
1523 up until the point in time it will be needed :-) */
1524 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1528 case WINED3DFMT_R5G6B5:
1529 if (colorkey_active) {
1530 *convert = CONVERT_CK_565;
1532 *internal = GL_RGBA;
1533 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1537 case WINED3DFMT_R8G8B8:
1538 if (colorkey_active) {
1539 *convert = CONVERT_CK_RGB24;
1541 *internal = GL_RGBA;
1542 *type = GL_UNSIGNED_INT_8_8_8_8;
1547 case WINED3DFMT_X8R8G8B8:
1548 if (colorkey_active) {
1549 *convert = CONVERT_RGB32_888;
1551 *internal = GL_RGBA;
1552 *type = GL_UNSIGNED_INT_8_8_8_8;
1563 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) {
1564 BYTE *source, *dest;
1565 TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert, surf);
1570 memcpy(dst, src, pitch * height);
1573 case CONVERT_PALETTED:
1574 case CONVERT_PALETTED_CK:
1576 IWineD3DPaletteImpl* pal = surf->palette;
1582 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1586 /* Still no palette? Use the device's palette */
1587 /* Get the surface's palette */
1588 for (i = 0; i < 256; i++) {
1589 IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice;
1591 table[i][0] = device->palettes[device->currentPalette][i].peRed;
1592 table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1593 table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1594 if ((convert == CONVERT_PALETTED_CK) &&
1595 (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1596 (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1597 /* We should maybe here put a more 'neutral' color than the standard bright purple
1598 one often used by application to prevent the nice purple borders when bi-linear
1606 TRACE("Using surface palette %p\n", pal);
1607 /* Get the surface's palette */
1608 for (i = 0; i < 256; i++) {
1609 table[i][0] = pal->palents[i].peRed;
1610 table[i][1] = pal->palents[i].peGreen;
1611 table[i][2] = pal->palents[i].peBlue;
1612 if ((convert == CONVERT_PALETTED_CK) &&
1613 (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1614 (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1615 /* We should maybe here put a more 'neutral' color than the standard bright purple
1616 one often used by application to prevent the nice purple borders when bi-linear
1625 for (y = 0; y < height; y++)
1627 source = src + pitch * y;
1628 dest = dst + outpitch * y;
1629 /* This is an 1 bpp format, using the width here is fine */
1630 for (x = 0; x < width; x++) {
1631 BYTE color = *source++;
1632 *dest++ = table[color][0];
1633 *dest++ = table[color][1];
1634 *dest++ = table[color][2];
1635 *dest++ = table[color][3];
1641 case CONVERT_CK_565:
1643 /* Converting the 565 format in 5551 packed to emulate color-keying.
1645 Note : in all these conversion, it would be best to average the averaging
1646 pixels to get the color of the pixel that will be color-keyed to
1647 prevent 'color bleeding'. This will be done later on if ever it is
1650 Note2: Nvidia documents say that their driver does not support alpha + color keying
1651 on the same surface and disables color keying in such a case
1657 TRACE("Color keyed 565\n");
1659 for (y = 0; y < height; y++) {
1660 Source = (WORD *) (src + y * pitch);
1661 Dest = (WORD *) (dst + y * outpitch);
1662 for (x = 0; x < width; x++ ) {
1663 WORD color = *Source++;
1664 *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1665 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1666 (color > surf->SrcBltCKey.dwColorSpaceHighValue)) {
1676 ERR("Unsupported conversation type %d\n", convert);
1681 /* This function is used in case of 8bit paletted textures to upload the palette.
1682 For now it only supports GL_EXT_paletted_texture extension but support for other
1683 extensions like ARB_fragment_program and ATI_fragment_shaders will be added as well.
1685 void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
1686 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1687 IWineD3DPaletteImpl* pal = This->palette;
1692 /* Still no palette? Use the device's palette */
1693 /* Get the surface's palette */
1694 for (i = 0; i < 256; i++) {
1695 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1697 table[i][0] = device->palettes[device->currentPalette][i].peRed;
1698 table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1699 table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1700 if ((convert == CONVERT_PALETTED_CK) &&
1701 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1702 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1703 /* We should maybe here put a more 'neutral' color than the standard bright purple
1704 one often used by application to prevent the nice purple borders when bi-linear
1712 TRACE("Using surface palette %p\n", pal);
1713 /* Get the surface's palette */
1714 for (i = 0; i < 256; i++) {
1715 table[i][0] = pal->palents[i].peRed;
1716 table[i][1] = pal->palents[i].peGreen;
1717 table[i][2] = pal->palents[i].peBlue;
1718 if ((convert == CONVERT_PALETTED_CK) &&
1719 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1720 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1721 /* We should maybe here put a more 'neutral' color than the standard bright purple
1722 one often used by application to prevent the nice purple borders when bi-linear
1730 GL_EXTCALL(glColorTableEXT(GL_TEXTURE_2D,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table));
1733 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1734 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1735 GLenum format, internal, type;
1736 CONVERT_TYPES convert;
1738 int width, pitch, outpitch;
1741 if (This->Flags & SFLAG_INTEXTURE) {
1742 TRACE("Surface already in texture\n");
1745 if (This->Flags & SFLAG_DIRTY) {
1746 TRACE("Reloading because surface is dirty\n");
1747 } else if(/* Reload: gl texture has ck, now no ckey is set OR */
1748 ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & DDSD_CKSRCBLT))) ||
1749 /* Reload: vice versa OR */
1750 ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & DDSD_CKSRCBLT)) ||
1751 /* Also reload: Color key is active AND the color key has changed */
1752 ((This->CKeyFlags & DDSD_CKSRCBLT) && (
1753 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
1754 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
1755 TRACE("Reloading because of color keying\n");
1757 TRACE("surface isn't dirty\n");
1761 This->Flags &= ~SFLAG_DIRTY;
1763 /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1764 * These resources are not bound by device size or format restrictions. Because of this,
1765 * these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1766 * However, these resources can always be created, locked, and copied.
1768 if (This->resource.pool == WINED3DPOOL_SCRATCH && !(This->Flags & SFLAG_FORCELOAD) )
1770 FIXME("(%p) Operation not supported for scratch textures\n",This);
1771 return WINED3DERR_INVALIDCALL;
1774 if (This->Flags & SFLAG_INPBUFFER) {
1775 if (This->glDescription.level != 0)
1776 FIXME("Surface in texture is only supported for level 0\n");
1777 else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1778 This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1779 This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1780 This->resource.format == WINED3DFMT_DXT5)
1781 FIXME("Format %d not supported\n", This->resource.format);
1787 glGetIntegerv(GL_READ_BUFFER, &prevRead);
1788 vcheckGLcall("glGetIntegerv");
1789 glReadBuffer(GL_BACK);
1790 vcheckGLcall("glReadBuffer");
1792 glCopyTexImage2D(This->glDescription.target,
1793 This->glDescription.level,
1794 This->glDescription.glFormatInternal,
1797 This->currentDesc.Width,
1798 This->currentDesc.Height,
1801 checkGLcall("glCopyTexImage2D");
1802 glReadBuffer(prevRead);
1803 vcheckGLcall("glReadBuffer");
1807 TRACE("Updating target %d\n", This->glDescription.target);
1808 This->Flags |= SFLAG_INTEXTURE;
1813 if(This->CKeyFlags & DDSD_CKSRCBLT) {
1814 This->Flags |= SFLAG_GLCKEY;
1815 This->glCKey = This->SrcBltCKey;
1817 else This->Flags &= ~SFLAG_GLCKEY;
1819 d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp);
1821 /* The width is in 'length' not in bytes */
1822 if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)
1823 width = This->currentDesc.Width;
1825 width = This->pow2Width;
1827 pitch = IWineD3DSurface_GetPitch(iface);
1829 if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
1830 int height = This->glRect.bottom - This->glRect.top;
1832 /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
1833 outpitch = width * bpp;
1834 outpitch = (outpitch + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1836 mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
1838 ERR("Out of memory %d, %d!\n", outpitch, height);
1839 return WINED3DERR_OUTOFVIDEOMEMORY;
1841 d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
1843 This->Flags |= SFLAG_CONVERTED;
1844 } else if (This->resource.format == WINED3DFMT_P8 && GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
1845 d3dfmt_p8_upload_palette(iface, convert);
1846 This->Flags &= ~SFLAG_CONVERTED;
1847 mem = This->resource.allocatedMemory;
1849 This->Flags &= ~SFLAG_CONVERTED;
1850 mem = This->resource.allocatedMemory;
1853 /* Make sure the correct pitch is used */
1854 glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
1856 if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
1857 TRACE("non power of two support\n");
1858 surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
1860 surface_upload_data(This, This->pow2Width, This->pow2Height, format, type, mem);
1863 surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
1865 surface_upload_data(This, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
1869 /* Restore the default pitch */
1870 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1872 if (mem != This->resource.allocatedMemory)
1873 HeapFree(GetProcessHeap(), 0, mem);
1877 static unsigned int gen = 0;
1880 if ((gen % 10) == 0) {
1881 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1882 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1885 * debugging crash code
1894 if (!(This->Flags & SFLAG_DONOTFREE)) {
1895 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1896 This->resource.allocatedMemory = NULL;
1904 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1907 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1908 char *allocatedMemory;
1910 IWineD3DSwapChain *swapChain = NULL;
1912 GLuint tmpTexture = 0;
1915 Textures my not be stored in ->allocatedgMemory and a GlTexture
1916 so we should lock the surface before saving a snapshot, or at least check that
1918 /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1919 by calling GetTexImage and in compressed form by calling
1920 GetCompressedTexImageARB. Queried compressed images can be saved and
1921 later reused by calling CompressedTexImage[123]DARB. Pre-compressed
1922 texture images do not need to be processed by the GL and should
1923 significantly improve texture loading performance relative to uncompressed
1926 /* Setup the width and height to be the internal texture width and height. */
1927 width = This->pow2Width;
1928 height = This->pow2Height;
1929 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1930 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1932 if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1933 /* we don't want to interfere with the back buffer so read the data into a temporary texture and then save the data out of the temporary texture */
1936 FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1937 glEnable(GL_TEXTURE_2D);
1939 glGenTextures(1, &tmpTexture);
1940 glBindTexture(GL_TEXTURE_2D, tmpTexture);
1942 glTexImage2D(GL_TEXTURE_2D,
1949 GL_UNSIGNED_INT_8_8_8_8_REV,
1952 glGetIntegerv(GL_READ_BUFFER, &prevRead);
1953 vcheckGLcall("glGetIntegerv");
1954 glReadBuffer(GL_BACK);
1955 vcheckGLcall("glReadBuffer");
1956 glCopyTexImage2D(GL_TEXTURE_2D,
1965 checkGLcall("glCopyTexImage2D");
1966 glReadBuffer(prevRead);
1969 } else { /* bind the real texture */
1970 IWineD3DSurface_PreLoad(iface);
1972 allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4);
1974 FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1975 glGetTexImage(GL_TEXTURE_2D,
1976 This->glDescription.level,
1978 GL_UNSIGNED_INT_8_8_8_8_REV,
1980 checkGLcall("glTexImage2D");
1982 glBindTexture(GL_TEXTURE_2D, 0);
1983 glDeleteTextures(1, &tmpTexture);
1987 f = fopen(filename, "w+");
1989 ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1990 return WINED3DERR_INVALIDCALL;
1992 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1993 TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
2008 fwrite(&width,2,1,f);
2010 fwrite(&height,2,1,f);
2015 /* 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*/
2017 textureRow = allocatedMemory + (width * (height - 1) *4);
2019 textureRow = allocatedMemory;
2020 for (y = 0 ; y < height; y++) {
2021 for (i = 0; i < width; i++) {
2022 color = *((DWORD*)textureRow);
2023 fputc((color >> 16) & 0xFF, f); /* B */
2024 fputc((color >> 8) & 0xFF, f); /* G */
2025 fputc((color >> 0) & 0xFF, f); /* R */
2026 fputc((color >> 24) & 0xFF, f); /* A */
2029 /* take two rows of the pointer to the texture memory */
2031 (textureRow-= width << 3);
2034 TRACE("Closing file\n");
2038 IWineD3DSwapChain_Release(swapChain);
2040 HeapFree(GetProcessHeap(), 0, allocatedMemory);
2044 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
2045 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2046 This->Flags &= ~SFLAG_DIRTY;
2047 This->dirtyRect.left = This->currentDesc.Width;
2048 This->dirtyRect.top = This->currentDesc.Height;
2049 This->dirtyRect.right = 0;
2050 This->dirtyRect.bottom = 0;
2051 TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
2052 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2057 * Slightly inefficient way to handle multiple dirty rects but it works :)
2059 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
2060 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2061 IWineD3DBaseTexture *baseTexture = NULL;
2062 This->Flags |= SFLAG_DIRTY;
2063 if (NULL != pDirtyRect) {
2064 This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
2065 This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
2066 This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
2067 This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
2069 This->dirtyRect.left = 0;
2070 This->dirtyRect.top = 0;
2071 This->dirtyRect.right = This->currentDesc.Width;
2072 This->dirtyRect.bottom = This->currentDesc.Height;
2074 TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
2075 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2076 /* if the container is a basetexture then mark it dirty. */
2077 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2078 TRACE("Passing to conatiner\n");
2079 IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
2080 IWineD3DBaseTexture_Release(baseTexture);
2085 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
2086 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2088 TRACE("This %p, container %p\n", This, container);
2090 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
2092 TRACE("Setting container to %p from %p\n", container, This->container);
2093 This->container = container;
2098 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
2099 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2100 const PixelFormatDesc *formatEntry = getFormatDescEntry(format);
2102 if (This->resource.format != WINED3DFMT_UNKNOWN) {
2103 FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
2104 return WINED3DERR_INVALIDCALL;
2107 TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
2108 if (format == WINED3DFMT_UNKNOWN) {
2109 This->resource.size = 0;
2110 } else if (format == WINED3DFMT_DXT1) {
2111 /* DXT1 is half byte per pixel */
2112 This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4)) >> 1;
2114 } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
2115 format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
2116 This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4));
2118 This->resource.size = ((This->pow2Width * formatEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
2119 This->resource.size *= This->pow2Height;
2123 /* Setup some glformat defaults */
2124 This->glDescription.glFormat = formatEntry->glFormat;
2125 This->glDescription.glFormatInternal = formatEntry->glInternal;
2126 This->glDescription.glType = formatEntry->glType;
2128 if (format != WINED3DFMT_UNKNOWN) {
2129 This->bytesPerPixel = formatEntry->bpp;
2130 This->pow2Size = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
2132 This->bytesPerPixel = 0;
2136 This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
2138 This->resource.format = format;
2140 TRACE("(%p) : Size %d, pow2Size %d, bytesPerPixel %d, glFormat %d, glFotmatInternal %d, glType %d\n", This, This->resource.size, This->pow2Size, This->bytesPerPixel, This->glDescription.glFormat, This->glDescription.glFormatInternal, This->glDescription.glType);
2145 HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2146 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2148 /* Render targets depend on their hdc, and we can't create a hdc on a user pointer */
2149 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2150 ERR("Not supported on render targets\n");
2151 return WINED3DERR_INVALIDCALL;
2154 if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2155 WARN("Surface is locked or the HDC is in use\n");
2156 return WINED3DERR_INVALIDCALL;
2159 if(Mem && Mem != This->resource.allocatedMemory) {
2161 /* Do I have to copy the old surface content? */
2162 if(This->Flags & SFLAG_DIBSECTION) {
2163 /* Release the DC. No need to hold the critical section for the update
2164 * Thread because this thread runs only on front buffers, but this method
2165 * fails for render targets in the check above.
2167 SelectObject(This->hDC, This->dib.holdbitmap);
2168 DeleteDC(This->hDC);
2169 /* Release the DIB section */
2170 DeleteObject(This->dib.DIBsection);
2171 This->dib.bitmap_data = NULL;
2172 This->resource.allocatedMemory = NULL;
2174 This->Flags &= ~SFLAG_DIBSECTION;
2175 } else if(!(This->Flags & SFLAG_USERPTR)) {
2176 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2178 This->resource.allocatedMemory = Mem;
2179 This->Flags |= SFLAG_USERPTR;
2180 } else if(This->Flags & SFLAG_USERPTR) {
2181 /* Lockrect and GetDC will re-create the dib section and allocated memory */
2182 This->resource.allocatedMemory = NULL;
2183 This->Flags &= ~SFLAG_USERPTR;
2188 /* TODO: replace this function with context management routines */
2189 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL inTexture) {
2190 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2193 This->Flags |= SFLAG_INPBUFFER;
2195 This->Flags &= ~SFLAG_INPBUFFER;
2199 This->Flags |= SFLAG_INTEXTURE;
2201 This->Flags &= ~SFLAG_INTEXTURE;
2207 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2208 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2209 IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
2210 TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2212 /* Flipping is only supported on RenderTargets */
2213 if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
2216 /* DDraw sets this for the X11 surfaces, so don't confuse the user
2217 * FIXME("(%p) Target override is not supported by now\n", This);
2218 * Additionally, it isn't really possible to support triple-buffering
2219 * properly on opengl at all
2223 /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2224 return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
2227 /* Not called from the VTable */
2228 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2230 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2231 IWineD3DSwapChainImpl *swapchain = NULL;
2232 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2235 TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2237 /* Get the swapchain. One of the surfaces has to be a primary surface */
2238 IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
2239 if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2241 IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&swapchain);
2242 if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2243 else return WINED3DERR_INVALIDCALL;
2249 rect.x1 = DestRect->left;
2250 rect.y1 = DestRect->top;
2251 rect.x2 = DestRect->right;
2252 rect.y2 = DestRect->bottom;
2256 rect.x2 = This->currentDesc.Width;
2257 rect.y2 = This->currentDesc.Height;
2260 /* Half-life does a Blt from the back buffer to the front buffer,
2261 * Full surface size, no flags... Use present instead
2265 /* First, check if we can do a Flip */
2267 /* Check rects - IWineD3DDevice_Present doesn't handle them */
2269 if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
2270 (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
2277 /* Check the Destination rect and the surface sizes */
2279 (rect.x1 == 0) && (rect.y1 == 0) &&
2280 (rect.x2 == This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
2281 (This->currentDesc.Width == Src->currentDesc.Width) &&
2282 (This->currentDesc.Height == Src->currentDesc.Height)) {
2283 /* These flags are unimportant for the flag check, remove them */
2285 if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
2286 if( swapchain->backBuffer && ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer[0]) ) {
2288 D3DSWAPEFFECT orig_swap = swapchain->presentParms.SwapEffect;
2290 /* The idea behind this is that a glReadPixels and a glDrawPixels call
2291 * take very long, while a flip is fast.
2292 * This applies to Half-Life, which does such Blts every time it finished
2293 * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2294 * menu. This is also used by all apps when they do windowed rendering
2296 * The problem is that flipping is not really the same as copying. After a
2297 * Blt the front buffer is a copy of the back buffer, and the back buffer is
2298 * untouched. Therefore it's necessary to override the swap effect
2299 * and to set it back after the flip.
2302 swapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
2304 TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2305 IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
2306 NULL, NULL, 0, NULL);
2308 swapchain->presentParms.SwapEffect = orig_swap;
2315 /* Blt from texture to rendertarget? */
2316 if( ( ( (IWineD3DSurface *) This == swapchain->frontBuffer) ||
2317 ( swapchain->backBuffer && (IWineD3DSurface *) This == swapchain->backBuffer[0]) )
2319 ( ( (IWineD3DSurface *) Src != swapchain->frontBuffer) &&
2320 ( swapchain->backBuffer && (IWineD3DSurface *) Src != swapchain->backBuffer[0]) ) ) {
2321 float glTexCoord[4];
2323 DDCOLORKEY oldBltCKey = {0,0};
2324 GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha;
2325 GLint oldStencil, oldNVRegisterCombiners = 0;
2328 RECT SourceRectangle;
2331 TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
2334 SourceRectangle.left = SrcRect->left;
2335 SourceRectangle.right = SrcRect->right;
2336 SourceRectangle.top = SrcRect->top;
2337 SourceRectangle.bottom = SrcRect->bottom;
2339 SourceRectangle.left = 0;
2340 SourceRectangle.right = Src->currentDesc.Width;
2341 SourceRectangle.top = 0;
2342 SourceRectangle.bottom = Src->currentDesc.Height;
2345 if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
2346 /* Fall back to software */
2347 WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
2348 SourceRectangle.left, SourceRectangle.top,
2349 SourceRectangle.right, SourceRectangle.bottom);
2350 return WINED3DERR_INVALIDCALL;
2353 /* Color keying: Check if we have to do a color keyed blt,
2354 * and if not check if a color key is activated.
2356 oldCKey = Src->CKeyFlags;
2357 if(!(Flags & DDBLT_KEYSRC) &&
2358 Src->CKeyFlags & DDSD_CKSRCBLT) {
2359 /* Ok, the surface has a color key, but we shall not use it -
2360 * Deactivate it for now, LoadTexture will catch this
2362 Src->CKeyFlags &= ~DDSD_CKSRCBLT;
2366 if(Flags & DDBLT_KEYDEST) {
2367 oldBltCKey = This->SrcBltCKey;
2368 /* Temporary replace the source color key with the destination one. We do this because the color conversion code which
2369 * is in the end called from LoadTexture works with the source color. At the end of this function we restore the color key.
2371 This->SrcBltCKey = This->DestBltCKey;
2372 } else if (Flags & DDBLT_KEYSRC)
2373 oldBltCKey = This->SrcBltCKey;
2375 /* Now load the surface */
2376 IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
2380 /* Save all the old stuff until we have a proper opengl state manager */
2381 oldLight = glIsEnabled(GL_LIGHTING);
2382 oldFog = glIsEnabled(GL_FOG);
2383 oldDepth = glIsEnabled(GL_DEPTH_TEST);
2384 oldBlend = glIsEnabled(GL_BLEND);
2385 oldCull = glIsEnabled(GL_CULL_FACE);
2386 oldAlpha = glIsEnabled(GL_ALPHA_TEST);
2387 oldStencil = glIsEnabled(GL_STENCIL_TEST);
2389 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2390 oldNVRegisterCombiners = glIsEnabled(GL_REGISTER_COMBINERS_NV);
2393 glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphafunc);
2394 checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC");
2395 glGetFloatv(GL_ALPHA_TEST_REF, &alpharef);
2396 checkGLcall("glGetFloatv GL_ALPHA_TEST_REF");
2398 glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
2399 if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer) {
2400 TRACE("Drawing to front buffer\n");
2401 glDrawBuffer(GL_FRONT);
2402 checkGLcall("glDrawBuffer GL_FRONT");
2405 /* Unbind the old texture */
2406 glBindTexture(GL_TEXTURE_2D, 0);
2407 IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0));
2409 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2410 /* We use texture unit 0 for blts */
2411 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
2412 checkGLcall("glActiveTextureARB");
2414 WARN("Multi-texturing is unsupported in the local OpenGL implementation\n");
2417 /* Disable some fancy graphics effects */
2418 glDisable(GL_LIGHTING);
2419 checkGLcall("glDisable GL_LIGHTING");
2420 glDisable(GL_DEPTH_TEST);
2421 checkGLcall("glDisable GL_DEPTH_TEST");
2423 checkGLcall("glDisable GL_FOG");
2424 glDisable(GL_BLEND);
2425 checkGLcall("glDisable GL_BLEND");
2426 glDisable(GL_CULL_FACE);
2427 checkGLcall("glDisable GL_CULL_FACE");
2428 glDisable(GL_STENCIL_TEST);
2429 checkGLcall("glDisable GL_STENCIL_TEST");
2430 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2431 glDisable(GL_REGISTER_COMBINERS_NV);
2432 checkGLcall("glDisable GL_REGISTER_COMBINERS_NV");
2435 /* Ok, we need 2d textures, but not 1D or 3D */
2436 glDisable(GL_TEXTURE_1D);
2437 checkGLcall("glDisable GL_TEXTURE_1D");
2438 glEnable(GL_TEXTURE_2D);
2439 checkGLcall("glEnable GL_TEXTURE_2D");
2440 glDisable(GL_TEXTURE_3D);
2441 checkGLcall("glDisable GL_TEXTURE_3D");
2443 /* Bind the texture */
2444 glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2445 checkGLcall("glBindTexture");
2447 glEnable(GL_SCISSOR_TEST);
2449 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2451 /* No filtering for blts */
2452 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2454 checkGLcall("glTexParameteri");
2455 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2457 checkGLcall("glTexParameteri");
2458 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2460 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2461 checkGLcall("glTexEnvi");
2463 /* This is for color keying */
2464 if(Flags & DDBLT_KEYSRC) {
2465 glEnable(GL_ALPHA_TEST);
2466 checkGLcall("glEnable GL_ALPHA_TEST");
2467 glAlphaFunc(GL_NOTEQUAL, 0.0);
2468 checkGLcall("glAlphaFunc\n");
2470 glDisable(GL_ALPHA_TEST);
2471 checkGLcall("glDisable GL_ALPHA_TEST");
2474 /* Draw a textured quad
2476 d3ddevice_set_ortho(This->resource.wineD3DDevice);
2477 IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL);
2481 glColor3d(1.0f, 1.0f, 1.0f);
2482 glTexCoord2f(glTexCoord[0], glTexCoord[2]);
2487 glTexCoord2f(glTexCoord[0], glTexCoord[3]);
2488 glVertex3f(rect.x1, rect.y2, 0.0);
2490 glTexCoord2f(glTexCoord[1], glTexCoord[3]);
2495 glTexCoord2f(glTexCoord[1], glTexCoord[2]);
2500 checkGLcall("glEnd");
2502 /* Unbind the texture */
2503 glBindTexture(GL_TEXTURE_2D, 0);
2504 checkGLcall("glEnable glBindTexture");
2506 /* Restore the old settings */
2508 glEnable(GL_LIGHTING);
2509 checkGLcall("glEnable GL_LIGHTING");
2513 checkGLcall("glEnable GL_FOG");
2516 glEnable(GL_DEPTH_TEST);
2517 checkGLcall("glEnable GL_DEPTH_TEST");
2521 checkGLcall("glEnable GL_BLEND");
2524 glEnable(GL_CULL_FACE);
2525 checkGLcall("glEnable GL_CULL_FACE");
2528 glEnable(GL_STENCIL_TEST);
2529 checkGLcall("glEnable GL_STENCIL_TEST");
2532 glDisable(GL_ALPHA_TEST);
2533 checkGLcall("glDisable GL_ALPHA_TEST");
2535 glEnable(GL_ALPHA_TEST);
2536 checkGLcall("glEnable GL_ALPHA_TEST");
2538 if (GL_SUPPORT(NV_REGISTER_COMBINERS) && oldNVRegisterCombiners) {
2539 glEnable(GL_REGISTER_COMBINERS_NV);
2540 checkGLcall("glEnable GL_REGISTER_COMBINERS_NV");
2543 glAlphaFunc(alphafunc, alpharef);
2544 checkGLcall("glAlphaFunc\n");
2546 if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer && oldDraw == GL_BACK) {
2547 glDrawBuffer(oldDraw);
2550 /* Restore the color key flags */
2551 if(oldCKey != Src->CKeyFlags) {
2552 Src->CKeyFlags = oldCKey;
2555 /* Restore the old color key */
2556 if (Flags & (DDBLT_KEYSRC | DDBLT_KEYDEST))
2557 This->SrcBltCKey = oldBltCKey;
2561 /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2562 This->Flags |= SFLAG_GLDIRTY;
2568 /* Blt from rendertarget to texture? */
2569 if( (SrcSurface == swapchain->frontBuffer) ||
2570 (swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) ) {
2571 if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
2572 ( swapchain->backBuffer && (IWineD3DSurface *) This != swapchain->backBuffer[0]) ) {
2577 TRACE("Blt from rendertarget to texture\n");
2579 /* Call preload for the surface to make sure it isn't dirty */
2580 IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2583 srect.x1 = SrcRect->left;
2584 srect.y1 = SrcRect->top;
2585 srect.x2 = SrcRect->right;
2586 srect.y2 = SrcRect->bottom;
2590 srect.x2 = Src->currentDesc.Width;
2591 srect.y2 = Src->currentDesc.Height;
2596 /* Bind the target texture */
2597 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2598 checkGLcall("glBindTexture");
2599 if(swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) {
2600 glReadBuffer(GL_BACK);
2602 glReadBuffer(GL_FRONT);
2604 checkGLcall("glReadBuffer");
2606 xrel = (float) (srect.x2 - srect.x1) / (float) (rect.x2 - rect.x1);
2607 yrel = (float) (srect.y2 - srect.y1) / (float) (rect.y2 - rect.y1);
2609 /* I have to process this row by row to swap the image,
2610 * otherwise it would be upside down, so streching in y direction
2611 * doesn't cost extra time
2613 * However, streching in x direction can be avoided if not necessary
2615 for(row = rect.y1; row < rect.y2; row++) {
2616 if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2617 /* Well, that stuff works, but it's very slow.
2618 * find a better way instead
2621 for(col = rect.x1; col < rect.x2; col++) {
2622 glCopyTexSubImage2D(GL_TEXTURE_2D,
2624 rect.x1 + col, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2625 srect.x1 + col * xrel, Src->currentDesc.Height - srect.y2 + row * yrel,
2629 glCopyTexSubImage2D(GL_TEXTURE_2D,
2631 rect.x1, rect.y2 + rect.y1 - row - 1, /* xoffset, yoffset */
2632 srect.x1, row - rect.y1,
2633 rect.x2-rect.x1, 1);
2637 vcheckGLcall("glCopyTexSubImage2D");
2640 if(!(This->Flags & SFLAG_DONOTFREE)) {
2641 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2642 This->resource.allocatedMemory = NULL;
2644 This->Flags |= SFLAG_GLDIRTY;
2652 if (Flags & DDBLT_COLORFILL) {
2653 /* This is easy to handle for the D3D Device... */
2655 IWineD3DSwapChainImpl *implSwapChain;
2657 TRACE("Colorfill\n");
2659 /* The color as given in the Blt function is in the format of the frame-buffer...
2660 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2662 if (This->resource.format == WINED3DFMT_P8) {
2663 if (This->palette) {
2664 color = ((0xFF000000) |
2665 (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2666 (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2667 (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2672 else if (This->resource.format == WINED3DFMT_R5G6B5) {
2673 if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2676 color = ((0xFF000000) |
2677 ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2678 ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2679 ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2682 else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2683 (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2684 color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2686 else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2687 color = DDBltFx->u5.dwFillColor;
2690 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2691 return WINED3DERR_INVALIDCALL;
2694 TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2695 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
2696 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
2697 if(implSwapChain->backBuffer && This == (IWineD3DSurfaceImpl*) implSwapChain->backBuffer[0]) {
2698 glDrawBuffer(GL_BACK);
2699 checkGLcall("glDrawBuffer(GL_BACK)");
2701 else if (This == (IWineD3DSurfaceImpl*) implSwapChain->frontBuffer) {
2702 glDrawBuffer(GL_FRONT);
2703 checkGLcall("glDrawBuffer(GL_FRONT)");
2706 ERR("Wrong surface type for BLT override(not on swapchain) !\n");
2707 return WINED3DERR_INVALIDCALL;
2710 TRACE("(%p) executing Render Target override, color = %x\n", This, color);
2712 IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2713 1 /* Number of rectangles */,
2715 WINED3DCLEAR_TARGET,
2720 /* Restore the original draw buffer */
2721 if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
2722 glDrawBuffer(GL_BACK);
2723 vcheckGLcall("glDrawBuffer");
2729 /* Default: Fall back to the generic blt */
2730 return WINED3DERR_INVALIDCALL;
2733 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2734 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2735 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2736 TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2737 TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
2739 /* Special cases for RenderTargets */
2740 if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2741 ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2742 if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2745 /* For the rest call the X11 surface implementation.
2746 * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2747 * other Blts are rather rare
2749 return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2752 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2753 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2754 TRACE("(%p)->(%x)\n", This, Flags);
2759 case DDGBS_ISBLTDONE:
2763 return DDERR_INVALIDPARAMS;
2767 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2768 /* XXX: DDERR_INVALIDSURFACETYPE */
2770 TRACE("(%p)->(%08x)\n",iface,Flags);
2773 case DDGFS_ISFLIPDONE:
2777 return DDERR_INVALIDPARAMS;
2781 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2782 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2783 TRACE("(%p)\n", This);
2785 return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2788 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2789 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2790 TRACE("(%p)\n", This);
2792 /* So far we don't lose anything :) */
2793 This->Flags &= ~SFLAG_LOST;
2797 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2798 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2799 IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2800 TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
2802 /* Special cases for RenderTargets */
2803 if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2804 ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2806 RECT SrcRect, DstRect;
2810 SrcRect.left = rsrc->left;
2811 SrcRect.top= rsrc->top;
2812 SrcRect.bottom = rsrc->bottom;
2813 SrcRect.right = rsrc->right;
2817 SrcRect.right = srcImpl->currentDesc.Width;
2818 SrcRect.bottom = srcImpl->currentDesc.Height;
2821 DstRect.left = dstx;
2823 DstRect.right = dstx + SrcRect.right - SrcRect.left;
2824 DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2826 /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
2827 if(trans & DDBLTFAST_SRCCOLORKEY)
2828 Flags |= DDBLT_KEYSRC;
2829 if(trans & DDBLTFAST_DESTCOLORKEY)
2830 Flags |= DDBLT_KEYDEST;
2831 if(trans & DDBLTFAST_WAIT)
2832 Flags |= DDBLT_WAIT;
2833 if(trans & DDBLTFAST_DONOTWAIT)
2834 Flags |= DDBLT_DONOTWAIT;
2836 if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL) == WINED3D_OK) return WINED3D_OK;
2840 return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2843 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2844 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2845 TRACE("(%p)->(%p)\n", This, Pal);
2847 *Pal = (IWineD3DPalette *) This->palette;
2851 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2852 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2854 IWineD3DPaletteImpl *pal = This->palette;
2856 TRACE("(%p)\n", This);
2858 if(This->resource.format == WINED3DFMT_P8 ||
2859 This->resource.format == WINED3DFMT_A8P8)
2861 TRACE("Dirtifying surface\n");
2862 This->Flags |= SFLAG_DIRTY;
2865 if(This->Flags & SFLAG_DIBSECTION) {
2866 TRACE("(%p): Updating the hdc's palette\n", This);
2867 for (n=0; n<256; n++) {
2869 col[n].rgbRed = pal->palents[n].peRed;
2870 col[n].rgbGreen = pal->palents[n].peGreen;
2871 col[n].rgbBlue = pal->palents[n].peBlue;
2873 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2874 /* Use the default device palette */
2875 col[n].rgbRed = device->palettes[device->currentPalette][n].peRed;
2876 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
2877 col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue;
2879 col[n].rgbReserved = 0;
2881 SetDIBColorTable(This->hDC, 0, 256, col);
2887 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
2888 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2889 IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
2890 TRACE("(%p)->(%p)\n", This, Pal);
2892 if(This->palette != NULL)
2893 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
2894 This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
2896 if(PalImpl != NULL) {
2897 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2898 /* Set the device's main palette if the palette
2899 * wasn't a primary palette before
2901 if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
2902 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2905 for(i=0; i < 256; i++) {
2906 device->palettes[device->currentPalette][i] = PalImpl->palents[i];
2910 (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
2913 This->palette = PalImpl;
2915 return IWineD3DSurface_RealizePalette(iface);
2918 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
2919 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2920 TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
2922 if ((Flags & DDCKEY_COLORSPACE) != 0) {
2923 FIXME(" colorkey value not supported (%08x) !\n", Flags);
2924 return DDERR_INVALIDPARAMS;
2927 /* Dirtify the surface, but only if a key was changed */
2929 switch (Flags & ~DDCKEY_COLORSPACE) {
2930 case DDCKEY_DESTBLT:
2931 This->DestBltCKey = *CKey;
2932 This->CKeyFlags |= DDSD_CKDESTBLT;
2935 case DDCKEY_DESTOVERLAY:
2936 This->DestOverlayCKey = *CKey;
2937 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
2940 case DDCKEY_SRCOVERLAY:
2941 This->SrcOverlayCKey = *CKey;
2942 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
2946 This->SrcBltCKey = *CKey;
2947 This->CKeyFlags |= DDSD_CKSRCBLT;
2952 switch (Flags & ~DDCKEY_COLORSPACE) {
2953 case DDCKEY_DESTBLT:
2954 This->CKeyFlags &= ~DDSD_CKDESTBLT;
2957 case DDCKEY_DESTOVERLAY:
2958 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
2961 case DDCKEY_SRCOVERLAY:
2962 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
2966 This->CKeyFlags &= ~DDSD_CKSRCBLT;
2974 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
2975 /** Check against the maximum texture sizes supported by the video card **/
2976 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2978 TRACE("%p\n", This);
2979 if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
2980 /* one of three options
2981 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)
2982 2: Set the texture to the maxium size (bad idea)
2983 3: WARN and return WINED3DERR_NOTAVAILABLE;
2984 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.
2986 WARN("(%p) Creating an oversized surface\n", This);
2987 This->Flags |= SFLAG_OVERSIZE;
2989 /* This will be initialized on the first blt */
2990 This->glRect.left = 0;
2991 This->glRect.top = 0;
2992 This->glRect.right = 0;
2993 This->glRect.bottom = 0;
2995 /* No oversize, gl rect is the full texture size */
2996 This->Flags &= ~SFLAG_OVERSIZE;
2997 This->glRect.left = 0;
2998 This->glRect.top = 0;
2999 This->glRect.right = This->pow2Width;
3000 This->glRect.bottom = This->pow2Height;
3006 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
3007 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3009 TRACE("(%p)\n", This);
3011 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
3012 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
3013 ie pitch = (width/4) * bytes per block */
3014 if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
3015 ret = ((This->currentDesc.Width + 3) >> 2) << 3;
3016 else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
3017 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
3018 ret = ((This->currentDesc.Width + 3) >> 2) << 4;
3020 if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
3021 /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
3022 ret = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
3024 ret = This->bytesPerPixel * This->pow2Width;
3026 /* Surfaces are 32 bit aligned */
3027 ret = (ret + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
3029 TRACE("(%p) Returning %d\n", This, ret);
3033 HRESULT WINAPI IWineD3DSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
3034 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3036 FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y);
3038 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3040 TRACE("(%p): Not an overlay surface\n", This);
3041 return DDERR_NOTAOVERLAYSURFACE;
3047 HRESULT WINAPI IWineD3DSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
3048 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3050 FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y);
3052 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3054 TRACE("(%p): Not an overlay surface\n", This);
3055 return DDERR_NOTAOVERLAYSURFACE;
3061 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
3062 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3063 IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
3065 FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
3067 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3069 TRACE("(%p): Not an overlay surface\n", This);
3070 return DDERR_NOTAOVERLAYSURFACE;
3076 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX) {
3077 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3078 IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
3079 FIXME("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
3081 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3083 TRACE("(%p): Not an overlay surface\n", This);
3084 return DDERR_NOTAOVERLAYSURFACE;
3090 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
3093 IWineD3DSurfaceImpl_QueryInterface,
3094 IWineD3DSurfaceImpl_AddRef,
3095 IWineD3DSurfaceImpl_Release,
3096 /* IWineD3DResource */
3097 IWineD3DSurfaceImpl_GetParent,
3098 IWineD3DSurfaceImpl_GetDevice,
3099 IWineD3DSurfaceImpl_SetPrivateData,
3100 IWineD3DSurfaceImpl_GetPrivateData,
3101 IWineD3DSurfaceImpl_FreePrivateData,
3102 IWineD3DSurfaceImpl_SetPriority,
3103 IWineD3DSurfaceImpl_GetPriority,
3104 IWineD3DSurfaceImpl_PreLoad,
3105 IWineD3DSurfaceImpl_GetType,
3106 /* IWineD3DSurface */
3107 IWineD3DSurfaceImpl_GetContainer,
3108 IWineD3DSurfaceImpl_GetDesc,
3109 IWineD3DSurfaceImpl_LockRect,
3110 IWineD3DSurfaceImpl_UnlockRect,
3111 IWineD3DSurfaceImpl_GetDC,
3112 IWineD3DSurfaceImpl_ReleaseDC,
3113 IWineD3DSurfaceImpl_Flip,
3114 IWineD3DSurfaceImpl_Blt,
3115 IWineD3DSurfaceImpl_GetBltStatus,
3116 IWineD3DSurfaceImpl_GetFlipStatus,
3117 IWineD3DSurfaceImpl_IsLost,
3118 IWineD3DSurfaceImpl_Restore,
3119 IWineD3DSurfaceImpl_BltFast,
3120 IWineD3DSurfaceImpl_GetPalette,
3121 IWineD3DSurfaceImpl_SetPalette,
3122 IWineD3DSurfaceImpl_RealizePalette,
3123 IWineD3DSurfaceImpl_SetColorKey,
3124 IWineD3DSurfaceImpl_GetPitch,
3125 IWineD3DSurfaceImpl_SetMem,
3126 IWineD3DSurfaceImpl_SetOverlayPosition,
3127 IWineD3DSurfaceImpl_GetOverlayPosition,
3128 IWineD3DSurfaceImpl_UpdateOverlayZOrder,
3129 IWineD3DSurfaceImpl_UpdateOverlay,
3131 IWineD3DSurfaceImpl_CleanDirtyRect,
3132 IWineD3DSurfaceImpl_AddDirtyRect,
3133 IWineD3DSurfaceImpl_LoadTexture,
3134 IWineD3DSurfaceImpl_SaveSnapshot,
3135 IWineD3DSurfaceImpl_SetContainer,
3136 IWineD3DSurfaceImpl_SetPBufferState,
3137 IWineD3DSurfaceImpl_SetGlTextureDesc,
3138 IWineD3DSurfaceImpl_GetGlDesc,
3139 IWineD3DSurfaceImpl_GetData,
3140 IWineD3DSurfaceImpl_SetFormat,
3141 IWineD3DSurfaceImpl_PrivateSetup