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
, unsigned long len
, CONVERT_TYPES convert
, IWineD3DSurfaceImpl
*surf
);
52 /* *******************************************
53 IWineD3DSurface IUnknown parts follow
54 ******************************************* */
55 HRESULT WINAPI
IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface
*iface
, REFIID riid
, LPVOID
*ppobj
)
57 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
58 /* Warn ,but be nice about things */
59 TRACE("(%p)->(%s,%p)\n", This
,debugstr_guid(riid
),ppobj
);
61 ERR("Probably FIXME: Calling query interface with NULL riid\n");
63 if (IsEqualGUID(riid
, &IID_IUnknown
)
64 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
65 || IsEqualGUID(riid
, &IID_IWineD3DResource
)
66 || IsEqualGUID(riid
, &IID_IWineD3DSurface
)) {
67 IUnknown_AddRef((IUnknown
*)iface
);
75 ULONG WINAPI
IWineD3DSurfaceImpl_AddRef(IWineD3DSurface
*iface
) {
76 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
77 ULONG ref
= InterlockedIncrement(&This
->resource
.ref
);
78 TRACE("(%p) : AddRef increasing from %ld\n", This
,ref
- 1);
82 ULONG WINAPI
IWineD3DSurfaceImpl_Release(IWineD3DSurface
*iface
) {
83 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
84 ULONG ref
= InterlockedDecrement(&This
->resource
.ref
);
85 TRACE("(%p) : Releasing from %ld\n", This
, ref
+ 1);
87 IWineD3DDeviceImpl
*device
= (IWineD3DDeviceImpl
*) This
->resource
.wineD3DDevice
;
88 TRACE("(%p) : cleaning up\n", This
);
89 if (This
->glDescription
.textureName
!= 0) { /* release the openGL texture.. */
91 TRACE("Deleting texture %d\n", This
->glDescription
.textureName
);
92 glDeleteTextures(1, &This
->glDescription
.textureName
);
96 if(This
->Flags
& SFLAG_DIBSECTION
) {
98 SelectObject(This
->hDC
, This
->dib
.holdbitmap
);
100 /* Release the DIB section */
101 DeleteObject(This
->dib
.DIBsection
);
102 This
->dib
.bitmap_data
= NULL
;
103 This
->resource
.allocatedMemory
= NULL
;
106 IWineD3DResourceImpl_CleanUp((IWineD3DResource
*)iface
);
107 if(iface
== device
->ddraw_primary
)
108 device
->ddraw_primary
= NULL
;
110 TRACE("(%p) Released\n", This
);
111 HeapFree(GetProcessHeap(), 0, This
);
117 /* ****************************************************
118 IWineD3DSurface IWineD3DResource parts follow
119 **************************************************** */
120 HRESULT WINAPI
IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface
*iface
, IWineD3DDevice
** ppDevice
) {
121 return IWineD3DResourceImpl_GetDevice((IWineD3DResource
*)iface
, ppDevice
);
124 HRESULT WINAPI
IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface
*iface
, REFGUID refguid
, CONST
void* pData
, DWORD SizeOfData
, DWORD Flags
) {
125 return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource
*)iface
, refguid
, pData
, SizeOfData
, Flags
);
128 HRESULT WINAPI
IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface
*iface
, REFGUID refguid
, void* pData
, DWORD
* pSizeOfData
) {
129 return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource
*)iface
, refguid
, pData
, pSizeOfData
);
132 HRESULT WINAPI
IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface
*iface
, REFGUID refguid
) {
133 return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource
*)iface
, refguid
);
136 DWORD WINAPI
IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface
*iface
, DWORD PriorityNew
) {
137 return IWineD3DResourceImpl_SetPriority((IWineD3DResource
*)iface
, PriorityNew
);
140 DWORD WINAPI
IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface
*iface
) {
141 return IWineD3DResourceImpl_GetPriority((IWineD3DResource
*)iface
);
144 void WINAPI
IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface
*iface
) {
145 /* TODO: re-write the way textures and managed,
146 * use a 'opengl context manager' to manage RenderTarget surfaces
147 ** *********************************************************/
149 /* TODO: check for locks */
150 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
151 IWineD3DBaseTexture
*baseTexture
= NULL
;
152 TRACE("(%p)Checking to see if the container is a base texture\n", This
);
153 if (IWineD3DSurface_GetContainer(iface
, &IID_IWineD3DBaseTexture
, (void **)&baseTexture
) == WINED3D_OK
) {
154 TRACE("Passing to conatiner\n");
155 IWineD3DBaseTexture_PreLoad(baseTexture
);
156 IWineD3DBaseTexture_Release(baseTexture
);
158 TRACE("(%p) : About to load surface\n", This
);
160 #if 0 /* TODO: context manager support */
161 IWineD3DContextManager_PushState(This
->contextManager
, GL_TEXTURE_2D
, ENABLED
, NOW
/* make sure the state is applied now */);
163 glEnable(This
->glDescription
.target
);/* make sure texture support is enabled in this context */
164 if (This
->glDescription
.level
== 0 && This
->glDescription
.textureName
== 0) {
165 glGenTextures(1, &This
->glDescription
.textureName
);
166 checkGLcall("glGenTextures");
167 TRACE("Surface %p given name %d\n", This
, This
->glDescription
.textureName
);
168 glBindTexture(This
->glDescription
.target
, This
->glDescription
.textureName
);
169 checkGLcall("glBindTexture");
170 IWineD3DSurface_LoadTexture(iface
);
171 /* This is where we should be reducing the amount of GLMemoryUsed */
173 if (This
->glDescription
.level
== 0) {
174 glBindTexture(This
->glDescription
.target
, This
->glDescription
.textureName
);
175 checkGLcall("glBindTexture");
176 IWineD3DSurface_LoadTexture(iface
);
177 } else if (This
->glDescription
.textureName
!= 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
178 /* assume this is a coding error not a real error for now */
179 FIXME("Mipmap surface has a glTexture bound to it!\n");
182 if (This
->resource
.pool
== WINED3DPOOL_DEFAULT
) {
183 /* Tell opengl to try and keep this texture in video ram (well mostly) */
186 glPrioritizeTextures(1, &This
->glDescription
.textureName
, &tmp
);
188 /* TODO: disable texture support, if it wastn't enabled when we entered. */
189 #if 0 /* TODO: context manager support */
190 IWineD3DContextManager_PopState(This
->contextManager
, GL_TEXTURE_2D
, DISABLED
,DELAYED
191 /* we don't care when the state is disabled(if atall) */);
198 WINED3DRESOURCETYPE WINAPI
IWineD3DSurfaceImpl_GetType(IWineD3DSurface
*iface
) {
199 TRACE("(%p) : calling resourceimpl_GetType\n", iface
);
200 return IWineD3DResourceImpl_GetType((IWineD3DResource
*)iface
);
203 HRESULT WINAPI
IWineD3DSurfaceImpl_GetParent(IWineD3DSurface
*iface
, IUnknown
**pParent
) {
204 TRACE("(%p) : calling resourceimpl_GetParent\n", iface
);
205 return IWineD3DResourceImpl_GetParent((IWineD3DResource
*)iface
, pParent
);
208 /* ******************************************************
209 IWineD3DSurface IWineD3DSurface parts follow
210 ****************************************************** */
212 HRESULT WINAPI
IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface
* iface
, IUnknown
**ppContainerParent
) {
213 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
215 TRACE("(%p) : ppContainerParent %p)\n", This
, ppContainerParent
);
217 if (!ppContainerParent
) {
218 ERR("(%p) : Called without a valid ppContainerParent.\n", This
);
221 if (This
->container
) {
222 IWineD3DBase_GetParent(This
->container
, ppContainerParent
);
223 if (!ppContainerParent
) {
224 /* WineD3D objects should always have a parent */
225 ERR("(%p) : GetParent returned NULL\n", This
);
227 IUnknown_Release(*ppContainerParent
); /* GetParent adds a reference; we want just the pointer */
229 *ppContainerParent
= NULL
;
235 HRESULT WINAPI
IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface
* iface
, REFIID riid
, void** ppContainer
) {
236 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
237 IWineD3DBase
*container
= 0;
239 TRACE("(This %p, riid %s, ppContainer %p)\n", This
, debugstr_guid(riid
), ppContainer
);
242 ERR("Called without a valid ppContainer.\n");
246 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
247 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
248 * GetContainer will return the Direct3D device used to create the surface.
250 if (This
->container
) {
251 container
= This
->container
;
253 container
= (IWineD3DBase
*)This
->resource
.wineD3DDevice
;
256 TRACE("Relaying to QueryInterface\n");
257 return IUnknown_QueryInterface(container
, riid
, ppContainer
);
260 HRESULT WINAPI
IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface
*iface
, WINED3DSURFACE_DESC
*pDesc
) {
261 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
263 TRACE("(%p) : copying into %p\n", This
, pDesc
);
264 if(pDesc
->Format
!= NULL
) *(pDesc
->Format
) = This
->resource
.format
;
265 if(pDesc
->Type
!= NULL
) *(pDesc
->Type
) = This
->resource
.resourceType
;
266 if(pDesc
->Usage
!= NULL
) *(pDesc
->Usage
) = This
->resource
.usage
;
267 if(pDesc
->Pool
!= NULL
) *(pDesc
->Pool
) = This
->resource
.pool
;
268 if(pDesc
->Size
!= NULL
) *(pDesc
->Size
) = This
->resource
.size
; /* dx8 only */
269 if(pDesc
->MultiSampleType
!= NULL
) *(pDesc
->MultiSampleType
) = This
->currentDesc
.MultiSampleType
;
270 if(pDesc
->MultiSampleQuality
!= NULL
) *(pDesc
->MultiSampleQuality
) = This
->currentDesc
.MultiSampleQuality
;
271 if(pDesc
->Width
!= NULL
) *(pDesc
->Width
) = This
->currentDesc
.Width
;
272 if(pDesc
->Height
!= NULL
) *(pDesc
->Height
) = This
->currentDesc
.Height
;
276 void WINAPI
IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface
*iface
, UINT textureName
, int target
) {
277 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
278 TRACE("(%p) : setting textureName %u, target %i\n", This
, textureName
, target
);
279 if (This
->glDescription
.textureName
== 0 && textureName
!= 0) {
280 This
->Flags
|= SFLAG_DIRTY
;
281 IWineD3DSurface_AddDirtyRect(iface
, NULL
);
283 This
->glDescription
.textureName
= textureName
;
284 This
->glDescription
.target
= target
;
287 void WINAPI
IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface
*iface
, glDescriptor
**glDescription
) {
288 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
289 TRACE("(%p) : returning %p\n", This
, &This
->glDescription
);
290 *glDescription
= &This
->glDescription
;
293 /* TODO: think about moving this down to resource? */
294 const void *WINAPI
IWineD3DSurfaceImpl_GetData(IWineD3DSurface
*iface
) {
295 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
296 /* 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 */
297 if (This
->resource
.pool
!= WINED3DPOOL_SYSTEMMEM
) {
298 FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface
);
300 return (CONST
void*)(This
->resource
.allocatedMemory
);
303 static void read_from_framebuffer(IWineD3DSurfaceImpl
*This
, CONST RECT
*rect
, void *dest
, UINT pitch
) {
309 switch(This
->resource
.format
)
313 /* GL can't return palettized data, so read ARGB pixels into a
314 * seperate block of memory and convert them into palettized format
315 * in software. Slow, but if the app means to use palettized render
316 * targets and lock it...
318 * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
319 * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
320 * for the color channels when palettizing the colors.
323 type
= GL_UNSIGNED_BYTE
;
325 mem
= HeapAlloc(GetProcessHeap(), 0, (rect
->bottom
- rect
->top
) * pitch
);
327 ERR("Out of memory\n");
335 fmt
= This
->glDescription
.glFormat
;
336 type
= This
->glDescription
.glType
;
339 if (rect
->left
== 0 &&
340 rect
->right
== This
->currentDesc
.Width
) {
341 BYTE
*row
, *top
, *bottom
;
344 glReadPixels(0, rect
->top
,
345 This
->currentDesc
.Width
,
346 rect
->bottom
- rect
->top
,
351 /* glReadPixels returns the image upside down, and there is no way to prevent this.
352 Flip the lines in software */
353 row
= HeapAlloc(GetProcessHeap(), 0, pitch
);
355 ERR("Out of memory\n");
359 bottom
= ((BYTE
*) mem
) + pitch
* ( rect
->bottom
- rect
->top
- 1);
360 for(i
= 0; i
< (rect
->bottom
- rect
->top
) / 2; i
++) {
361 memcpy(row
, top
, pitch
);
362 memcpy(top
, bottom
, pitch
);
363 memcpy(bottom
, row
, pitch
);
367 HeapFree(GetProcessHeap(), 0, row
);
369 if(This
->lockedRect
.top
== 0 && This
->lockedRect
.bottom
== This
->currentDesc
.Height
) {
370 This
->Flags
&= ~SFLAG_GLDIRTY
;
373 for (j
= This
->lockedRect
.top
; j
< This
->lockedRect
.bottom
- This
->lockedRect
.top
; ++j
) {
374 glReadPixels(rect
->left
,
375 rect
->bottom
- j
- 1,
376 rect
->right
- rect
->left
,
380 (char *)mem
+ (pitch
* (j
-rect
->top
)));
384 vcheckGLcall("glReadPixels");
386 if(This
->resource
.format
== WINED3DFMT_P8
) {
388 DWORD width
= pitch
/ 3;
391 pal
= This
->palette
->palents
;
393 pal
= This
->resource
.wineD3DDevice
->palettes
[This
->resource
.wineD3DDevice
->currentPalette
];
396 for(y
= rect
->top
; y
< rect
->bottom
; y
++) {
397 for(x
= rect
->left
; x
< rect
->right
; x
++) {
398 /* start lines pixels */
399 BYTE
*blue
= (BYTE
*) ((BYTE
*) mem
) + y
* pitch
+ x
* (sizeof(BYTE
) * 3);
400 BYTE
*green
= blue
+ 1;
401 BYTE
*red
= green
+ 1;
403 for(c
= 0; c
< 256; c
++) {
404 if(*red
== pal
[c
].peRed
&&
405 *green
== pal
[c
].peGreen
&&
406 *blue
== pal
[c
].peBlue
)
408 *((BYTE
*) dest
+ y
* width
+ x
) = c
;
414 HeapFree(GetProcessHeap(), 0, mem
);
418 static HRESULT WINAPI
IWineD3DSurfaceImpl_LockRect(IWineD3DSurface
*iface
, WINED3DLOCKED_RECT
* pLockedRect
, CONST RECT
* pRect
, DWORD Flags
) {
419 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
420 IWineD3DDeviceImpl
*myDevice
= This
->resource
.wineD3DDevice
;
421 IWineD3DSwapChainImpl
*swapchain
= NULL
;
422 static UINT messages
= 0; /* holds flags to disable fixme messages */
423 BOOL backbuf
= FALSE
;
425 /* fixme: should we really lock as such? */
426 if((This
->Flags
& (SFLAG_INTEXTURE
| SFLAG_INPBUFFER
)) ==
427 (SFLAG_INTEXTURE
| SFLAG_INPBUFFER
) ) {
428 FIXME("Warning: Surface is in texture memory or pbuffer\n");
429 This
->Flags
&= ~(SFLAG_INTEXTURE
| SFLAG_INPBUFFER
);
432 if (!(This
->Flags
& SFLAG_LOCKABLE
)) {
433 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
434 texture regions, and since the destination is an unlockable region we need
436 TRACE("Warning: trying to lock unlockable surf@%p\n", This
);
437 /*return WINED3DERR_INVALIDCALL; */
440 if (This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) {
441 IWineD3DSurface_GetContainer(iface
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
443 if (swapchain
!= NULL
|| iface
== myDevice
->renderTarget
|| iface
== myDevice
->depthStencilBuffer
) {
444 if(swapchain
!= NULL
) {
446 for(i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; i
++) {
447 if(iface
== swapchain
->backBuffer
[i
]) {
454 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
455 } else if (swapchain
!= NULL
&& iface
== swapchain
->frontBuffer
) {
456 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
457 } else if (iface
== myDevice
->renderTarget
) {
458 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
459 } else if (iface
== myDevice
->depthStencilBuffer
) {
460 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
463 if (NULL
!= swapchain
) {
464 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
469 TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This
, pRect
, Flags
, pLockedRect
, This
->resource
.allocatedMemory
);
472 pLockedRect
->Pitch
= IWineD3DSurface_GetPitch(iface
);
475 pLockedRect
->pBits
= This
->resource
.allocatedMemory
;
476 This
->lockedRect
.left
= 0;
477 This
->lockedRect
.top
= 0;
478 This
->lockedRect
.right
= This
->currentDesc
.Width
;
479 This
->lockedRect
.bottom
= This
->currentDesc
.Height
;
480 TRACE("Locked Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", &This
->lockedRect
, This
->lockedRect
.left
, This
->lockedRect
.top
, This
->lockedRect
.right
, This
->lockedRect
.bottom
);
482 TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect
, pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
484 if ((pRect
->top
< 0) ||
486 (pRect
->left
>= pRect
->right
) ||
487 (pRect
->top
>= pRect
->bottom
) ||
488 (pRect
->right
> This
->currentDesc
.Width
) ||
489 (pRect
->bottom
> This
->currentDesc
.Height
))
491 WARN(" Invalid values in pRect !!!\n");
492 return D3DERR_INVALIDCALL
;
495 if (This
->resource
.format
== WINED3DFMT_DXT1
) { /* DXT1 is half byte per pixel */
496 pLockedRect
->pBits
= This
->resource
.allocatedMemory
+ (pLockedRect
->Pitch
* pRect
->top
) + ((pRect
->left
* This
->bytesPerPixel
/ 2));
498 pLockedRect
->pBits
= This
->resource
.allocatedMemory
+ (pLockedRect
->Pitch
* pRect
->top
) + (pRect
->left
* This
->bytesPerPixel
);
500 This
->lockedRect
.left
= pRect
->left
;
501 This
->lockedRect
.top
= pRect
->top
;
502 This
->lockedRect
.right
= pRect
->right
;
503 This
->lockedRect
.bottom
= pRect
->bottom
;
506 if (This
->Flags
& SFLAG_NONPOW2
) {
507 TRACE("Locking non-power 2 texture\n");
510 if (0 == This
->resource
.usage
|| This
->resource
.usage
& WINED3DUSAGE_DYNAMIC
) {
511 /* classic surface TODO: non 2d surfaces?
512 These resources may be POOL_SYSTEMMEM, so they must not access the device */
513 TRACE("locking an ordinarary surface\n");
514 /* Check to see if memory has already been allocated from the surface*/
515 if ((NULL
== This
->resource
.allocatedMemory
) ||
516 (This
->Flags
& SFLAG_GLDIRTY
) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
517 /* Non-system memory surfaces */
519 This
->Flags
&= ~SFLAG_GLDIRTY
;
521 /*Surface has no memory currently allocated to it!*/
522 TRACE("(%p) Locking rect\n" , This
);
523 if(!This
->resource
.allocatedMemory
) {
524 This
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap() ,0 , This
->pow2Size
);
526 if (0 != This
->glDescription
.textureName
) {
527 /* Now I have to copy thing bits back */
528 This
->Flags
|= SFLAG_ACTIVELOCK
; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
529 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
532 /* Make sure that the texture is loaded */
533 IWineD3DSurface_PreLoad(iface
); /* Make sure there is a texture to bind! */
535 TRACE("(%p) glGetTexImage level(%d), fmt(%d), typ(%d), mem(%p)\n" , This
, This
->glDescription
.level
, This
->glDescription
.glFormat
, This
->glDescription
.glType
, This
->resource
.allocatedMemory
);
537 if (This
->resource
.format
== WINED3DFMT_DXT1
||
538 This
->resource
.format
== WINED3DFMT_DXT2
||
539 This
->resource
.format
== WINED3DFMT_DXT3
||
540 This
->resource
.format
== WINED3DFMT_DXT4
||
541 This
->resource
.format
== WINED3DFMT_DXT5
) {
542 TRACE("Locking a compressed texture\n");
543 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) { /* we can assume this as the texture would not have been created otherwise */
544 GL_EXTCALL(glGetCompressedTexImageARB
)(This
->glDescription
.target
,
545 This
->glDescription
.level
,
546 This
->resource
.allocatedMemory
);
549 FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This
);
552 glGetTexImage(This
->glDescription
.target
,
553 This
->glDescription
.level
,
554 This
->glDescription
.glFormat
,
555 This
->glDescription
.glType
,
556 This
->resource
.allocatedMemory
);
557 vcheckGLcall("glGetTexImage");
558 if (NP2_REPACK
== wined3d_settings
.nonpower2_mode
) {
559 /* some games (e.g. warhammer 40k) don't work with the odd pitchs properly, preventing
560 the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
561 repack the texture so that the bpp * width pitch can be used instead of the bpp * pow2width.
565 instead of boxing the texture :
566 |<-texture width ->| -->pow2width| /\
567 |111111111111111111| | |
568 |222 Texture 222222| boxed empty | texture height
569 |3333 Data 33333333| | |
570 |444444444444444444| | \/
571 ----------------------------------- |
572 | boxed empty | boxed empty | pow2height
574 -----------------------------------
577 were repacking the data to the expected texture width
579 |<-texture width ->| -->pow2width| /\
580 |111111111111111111222222222222222| |
581 |222333333333333333333444444444444| texture height
587 -----------------------------------
591 |<-texture width ->| /\
593 |222222222222222222|texture height
595 |444444444444444444| \/
598 this also means that any references to allocatedMemory should work with the data as if were a standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
600 internally the texture is still stored in a boxed format so any references to textureName will get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
602 if (This
->Flags
& SFLAG_NONPOW2
) {
604 int pitcha
= 0, pitchb
= 0;
606 pitcha
= This
->bytesPerPixel
* This
->currentDesc
.Width
;
607 pitchb
= This
->bytesPerPixel
* This
->pow2Width
;
608 datab
= dataa
= This
->resource
.allocatedMemory
;
609 FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This
, pitcha
, pitchb
);
610 for (y
= 1 ; y
< This
->currentDesc
.Height
; y
++) {
611 dataa
+= pitcha
; /* skip the first row */
613 memcpy(dataa
, datab
, pitcha
);
620 } else { /* Nothing to do */
621 TRACE("Memory %p already allocted for texture\n", This
->resource
.allocatedMemory
);
625 pLockedRect
->pBits
= This
->resource
.allocatedMemory
;
627 if (This
->resource
.format
== D3DFMT_DXT1
) { /* DXT1 is half byte per pixel */
628 pLockedRect
->pBits
= This
->resource
.allocatedMemory
+ (pLockedRect
->Pitch
* pRect
->top
) + ((pRect
->left
* This
->bytesPerPixel
/ 2));
630 pLockedRect
->pBits
= This
->resource
.allocatedMemory
+ (pLockedRect
->Pitch
* pRect
->top
) + (pRect
->left
* This
->bytesPerPixel
);
634 } else if (WINED3DUSAGE_RENDERTARGET
& This
->resource
.usage
){ /* render surfaces */
635 if((!(Flags
&WINED3DLOCK_DISCARD
) && (This
->Flags
& SFLAG_GLDIRTY
)) || !This
->resource
.allocatedMemory
) {
638 BOOL notInContext
= FALSE
;
639 IWineD3DSwapChainImpl
*targetSwapChain
= NULL
;
645 * for render->surface copy begin to begin of allocatedMemory
646 * unlock can be more easy
649 TRACE("locking a render target\n");
651 if (This
->resource
.allocatedMemory
== NULL
)
652 This
->resource
.allocatedMemory
= HeapAlloc(GetProcessHeap() ,0 ,This
->resource
.size
);
654 This
->Flags
|= SFLAG_ACTIVELOCK
; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
655 pLockedRect
->pBits
= This
->resource
.allocatedMemory
;
658 vcheckGLcall("glFlush");
659 glGetIntegerv(GL_READ_BUFFER
, &prev_read
);
660 vcheckGLcall("glIntegerv");
661 glGetIntegerv(GL_PACK_SWAP_BYTES
, &prev_store
);
662 vcheckGLcall("glIntegerv");
664 /* Here's what we have to do:
665 See if the swapchain has the same context as the renderTarget or the surface is the render target.
666 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
667 and use the front back buffer as required.
668 if not, we need to switch contexts and then switchback at the end.
670 IWineD3DSurface_GetContainer(iface
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
671 IWineD3DSurface_GetContainer(myDevice
->renderTarget
, &IID_IWineD3DSwapChain
, (void **)&targetSwapChain
);
673 /* 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! */
674 if ((swapchain
== targetSwapChain
&& targetSwapChain
!= NULL
) || iface
== myDevice
->renderTarget
) {
675 if (iface
== swapchain
->frontBuffer
) {
676 TRACE("locking front\n");
677 glReadBuffer(GL_FRONT
);
679 else if (iface
== myDevice
->renderTarget
|| backbuf
) {
680 TRACE("locking back buffer\n");
681 glReadBuffer(GL_BACK
);
682 } else if (iface
== myDevice
->depthStencilBuffer
) {
683 FIXME("Stencil Buffer lock unsupported for now\n");
685 FIXME("(%p) Shouldn't have got here!\n", This
);
686 glReadBuffer(GL_BACK
);
688 } else if (swapchain
!= NULL
) {
689 IWineD3DSwapChainImpl
*implSwapChain
;
690 IWineD3DDevice_GetSwapChain((IWineD3DDevice
*)myDevice
, 0, (IWineD3DSwapChain
**)&implSwapChain
);
691 if (swapchain
->glCtx
== implSwapChain
->render_ctx
&& swapchain
->drawable
== implSwapChain
->win
) {
692 /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
694 glReadBuffer(GL_BACK
);
695 } else if (iface
== swapchain
->frontBuffer
) {
696 glReadBuffer(GL_FRONT
);
697 } else if (iface
== myDevice
->depthStencilBuffer
) {
698 FIXME("Stencil Buffer lock unsupported for now\n");
700 FIXME("Should have got here!\n");
701 glReadBuffer(GL_BACK
);
704 /* We need to switch contexts to be able to read the buffer!!! */
705 FIXME("The buffer requested isn't in the current openGL context\n");
707 /* TODO: check the contexts, to see if were shared with the current context */
709 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)implSwapChain
);
711 if (swapchain
!= NULL
) IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
712 if (targetSwapChain
!= NULL
) IWineD3DSwapChain_Release((IWineD3DSwapChain
*)targetSwapChain
);
714 /** the depth stencil in openGL has a format of GL_FLOAT
715 * which should be good for WINED3DFMT_D16_LOCKABLE
717 * it is unclear what format the stencil buffer is in except.
718 * 'Each index is converted to fixed point...
719 * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
720 * mappings in the table GL_PIXEL_MAP_S_TO_S.
721 * glReadPixels(This->lockedRect.left,
722 * This->lockedRect.bottom - j - 1,
723 * This->lockedRect.right - This->lockedRect.left,
725 * GL_DEPTH_COMPONENT,
727 * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
728 *****************************************/
729 if (!notInContext
) { /* Only read the buffer if it's in the current context */
730 switch(wined3d_settings
.rendertargetlock_mode
) {
734 read_from_framebuffer(This
, &This
->lockedRect
, pLockedRect
->pBits
, pLockedRect
->Pitch
);
739 ERR("Reading from render target with a texture isn't implemented yet\n");
744 static BOOL warned
= FALSE
;
746 ERR("Application tries to lock the render target, but render target locking is disabled\n");
753 TRACE("Resetting buffer\n");
755 glReadBuffer(prev_read
);
756 vcheckGLcall("glReadBuffer");
760 } else if (WINED3DUSAGE_DEPTHSTENCIL
& This
->resource
.usage
) { /* stencil surfaces */
763 FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This
, This
->resource
.usage
);
766 glReadPixels(This->lockedRect.left,
767 This->lockedRect.bottom - j - 1,
768 This->lockedRect.right - This->lockedRect.left,
770 GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
777 FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This
, This
->resource
.usage
);
780 if (Flags
& (WINED3DLOCK_NO_DIRTY_UPDATE
| WINED3DLOCK_READONLY
)) {
783 IWineD3DBaseTexture
*pBaseTexture
;
786 * as seen in msdn docs
788 IWineD3DSurface_AddDirtyRect(iface
, &This
->lockedRect
);
790 /** Dirtify Container if needed */
791 if (WINED3D_OK
== IWineD3DSurface_GetContainer(iface
, &IID_IWineD3DBaseTexture
, (void **)&pBaseTexture
) && pBaseTexture
!= NULL
) {
792 TRACE("Making container dirty\n");
793 IWineD3DBaseTexture_SetDirty(pBaseTexture
, TRUE
);
794 IWineD3DBaseTexture_Release(pBaseTexture
);
796 TRACE("Surface is standalone, no need to dirty the container\n");
800 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect
->pBits
, pLockedRect
->Pitch
, This
->Flags
& SFLAG_DIRTY
? 0 : 1);
802 This
->Flags
|= SFLAG_LOCKED
;
806 static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl
*This
) {
808 GLint prev_rasterpos
[4];
810 BOOL storechanged
= FALSE
;
814 glDisable(GL_TEXTURE_2D
);
815 vcheckGLcall("glDisable(GL_TEXTURE_2D)");
816 glDisable(GL_TEXTURE_1D
);
817 vcheckGLcall("glDisable(GL_TEXTURE_1D)");
820 vcheckGLcall("glFlush");
821 glGetIntegerv(GL_PACK_SWAP_BYTES
, &prev_store
);
822 vcheckGLcall("glIntegerv");
823 glGetIntegerv(GL_CURRENT_RASTER_POSITION
, &prev_rasterpos
[0]);
824 vcheckGLcall("glIntegerv");
825 glPixelZoom(1.0, -1.0);
826 vcheckGLcall("glPixelZoom");
828 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
829 glGetIntegerv(GL_UNPACK_ROW_LENGTH
, &skipBytes
);
830 glPixelStorei(GL_UNPACK_ROW_LENGTH
, This
->currentDesc
.Width
);
832 glRasterPos3i(This
->lockedRect
.left
, This
->lockedRect
.top
, 1);
833 vcheckGLcall("glRasterPos2f");
835 /* Some drivers(radeon dri, others?) don't like exceptions during
836 * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
837 * after ReleaseDC. Reading it will cause an exception, which x11drv will
838 * catch to put the dib section in InSync mode, which leads to a crash
839 * and a blocked x server on my radeon card.
841 * The following lines read the dib section so it is put in inSync mode
842 * before glDrawPixels is called and the crash is prevented. There won't
843 * be any interfering gdi accesses, because UnlockRect is called from
844 * ReleaseDC, and the app won't use the dc any more afterwards.
846 if(This
->Flags
& SFLAG_DIBSECTION
) {
848 read
= This
->resource
.allocatedMemory
[0];
851 switch (This
->resource
.format
) {
852 /* No special care needed */
853 case WINED3DFMT_A4R4G4B4
:
854 case WINED3DFMT_R5G6B5
:
855 case WINED3DFMT_A1R5G5B5
:
856 case WINED3DFMT_R8G8B8
:
857 type
= This
->glDescription
.glType
;
858 fmt
= This
->glDescription
.glFormat
;
859 mem
= This
->resource
.allocatedMemory
;
862 case WINED3DFMT_X4R4G4B4
:
864 #if 0 /* Do we still need that? Those pixel formats have no alpha channel in gl any more */
866 unsigned short *data
;
867 data
= (unsigned short *)This
->resource
.allocatedMemory
;
868 size
= (This
->lockedRect
.bottom
- This
->lockedRect
.top
) * (This
->lockedRect
.right
- This
->lockedRect
.left
);
875 type
= This
->glDescription
.glType
;
876 fmt
= This
->glDescription
.glFormat
;
877 mem
= This
->resource
.allocatedMemory
;
881 case WINED3DFMT_X1R5G5B5
:
883 #if 0 /* Do we still need that? Those pixel formats have no alpha channel in gl any more */
885 unsigned short *data
;
886 data
= (unsigned short *)This
->resource
.allocatedMemory
;
887 size
= (This
->lockedRect
.bottom
- This
->lockedRect
.top
) * (This
->lockedRect
.right
- This
->lockedRect
.left
);
894 type
= This
->glDescription
.glType
;
895 fmt
= This
->glDescription
.glFormat
;
896 mem
= This
->resource
.allocatedMemory
;
900 case WINED3DFMT_X8R8G8B8
:
902 #if 0 /* Do we still need that? Those pixel formats have no alpha channel in gl any more */
903 /* make sure the X byte is set to alpha on, since it
904 could be any random value this fixes the intro move in Pirates! */
907 data
= (unsigned int *)This
->resource
.allocatedMemory
;
908 size
= (This
->lockedRect
.bottom
- This
->lockedRect
.top
) * (This
->lockedRect
.right
- This
->lockedRect
.left
);
917 case WINED3DFMT_A8R8G8B8
:
919 glPixelStorei(GL_PACK_SWAP_BYTES
, TRUE
);
920 vcheckGLcall("glPixelStorei");
922 type
= This
->glDescription
.glType
;
923 fmt
= This
->glDescription
.glFormat
;
924 mem
= This
->resource
.allocatedMemory
;
928 case WINED3DFMT_A2R10G10B10
:
930 glPixelStorei(GL_PACK_SWAP_BYTES
, TRUE
);
931 vcheckGLcall("glPixelStorei");
933 type
= This
->glDescription
.glType
;
934 fmt
= This
->glDescription
.glFormat
;
935 mem
= This
->resource
.allocatedMemory
;
941 UINT pitch
= IWineD3DSurface_GetPitch((IWineD3DSurface
*) This
); /* target is argb, 4 byte */
943 type
= GL_UNSIGNED_BYTE
;
946 mem
= HeapAlloc(GetProcessHeap(), 0, This
->resource
.size
* sizeof(DWORD
));
948 ERR("Out of memory\n");
951 for(row
= This
->dirtyRect
.top
; row
< This
->dirtyRect
.bottom
; row
++) {
952 d3dfmt_convert_surface(This
->resource
.allocatedMemory
+ row
* pitch
+ This
->lockedRect
.left
,
953 (BYTE
*) mem
+ row
* pitch
* 4 + This
->lockedRect
.left
* 4,
954 This
->lockedRect
.right
- This
->lockedRect
.left
,
955 CONVERT_PALETTED
, This
);
961 FIXME("Unsupported Format %u in locking func\n", This
->resource
.format
);
964 type
= This
->glDescription
.glType
;
965 fmt
= This
->glDescription
.glFormat
;
966 mem
= This
->resource
.allocatedMemory
;
969 glDrawPixels(This
->lockedRect
.right
- This
->lockedRect
.left
,
970 (This
->lockedRect
.bottom
- This
->lockedRect
.top
)-1,
973 checkGLcall("glDrawPixels");
974 glPixelZoom(1.0,1.0);
975 vcheckGLcall("glPixelZoom");
977 glRasterPos3iv(&prev_rasterpos
[0]);
978 vcheckGLcall("glRasterPos3iv");
980 /* Reset to previous pack row length */
981 glPixelStorei(GL_UNPACK_ROW_LENGTH
, skipBytes
);
982 vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
984 glPixelStorei(GL_PACK_SWAP_BYTES
, prev_store
);
985 vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES");
988 if(mem
!= This
->resource
.allocatedMemory
) HeapFree(GetProcessHeap(), 0, mem
);
992 static HRESULT WINAPI
IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface
*iface
) {
993 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
994 IWineD3DDeviceImpl
*myDevice
= This
->resource
.wineD3DDevice
;
995 const char *buffername
= "";
996 IWineD3DSwapChainImpl
*swapchain
= NULL
;
997 BOOL backbuf
= FALSE
;
999 if (!(This
->Flags
& SFLAG_LOCKED
)) {
1000 WARN("trying to Unlock an unlocked surf@%p\n", This
);
1001 return WINED3DERR_INVALIDCALL
;
1004 if (WINED3DUSAGE_RENDERTARGET
& This
->resource
.usage
) {
1005 IWineD3DSurface_GetContainer(iface
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
1009 for(i
= 0; i
< swapchain
->presentParms
.BackBufferCount
; i
++) {
1010 if(iface
== swapchain
->backBuffer
[i
]) {
1018 buffername
= "backBuffer";
1019 } else if ((swapchain
!= NULL
) && iface
== swapchain
->frontBuffer
) {
1020 buffername
= "frontBuffer";
1021 } else if (iface
== myDevice
->depthStencilBuffer
) {
1022 buffername
= "depthStencilBuffer";
1023 } else if (iface
== myDevice
->renderTarget
) {
1024 buffername
= "renderTarget";
1028 if (swapchain
!= NULL
) {
1029 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)swapchain
);
1032 TRACE("(%p %s) : dirtyfied(%d)\n", This
, buffername
, This
->Flags
& SFLAG_DIRTY
? 1 : 0);
1034 if (!(This
->Flags
& SFLAG_DIRTY
)) {
1035 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This
);
1039 if (0 == This
->resource
.usage
) { /* classic surface */
1042 * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
1044 } else if (WINED3DUSAGE_RENDERTARGET
& This
->resource
.usage
) { /* render surfaces */
1046 /****************************
1047 * TODO: Render targets are 'special' and
1048 * ?some? locking needs to be passed onto the context manager
1049 * so that it becomes possible to use auxiliary buffers, pbuffers
1050 * render-to-texture, shared, cached contexts etc...
1051 * ****************************/
1052 IWineD3DSwapChainImpl
*implSwapChain
;
1053 IWineD3DDevice_GetSwapChain((IWineD3DDevice
*)myDevice
, 0, (IWineD3DSwapChain
**)&implSwapChain
);
1055 if (backbuf
|| iface
== implSwapChain
->frontBuffer
|| iface
== myDevice
->renderTarget
) {
1060 /* glDrawPixels transforms the raster position as though it was a vertex -
1061 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
1062 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
1063 d3ddevice_set_ortho(This
->resource
.wineD3DDevice
);
1065 if (iface
== implSwapChain
->frontBuffer
) {
1066 glDrawBuffer(GL_FRONT
);
1067 checkGLcall("glDrawBuffer GL_FRONT");
1068 } else if (backbuf
|| iface
== myDevice
->renderTarget
) {
1069 glDrawBuffer(GL_BACK
);
1070 checkGLcall("glDrawBuffer GL_BACK");
1073 /* Disable higher textures before calling glDrawPixels */
1074 for(tex
= 1; tex
< GL_LIMITS(sampler_stages
); tex
++) {
1075 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
1076 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
+ tex
));
1077 checkGLcall("glActiveTextureARB");
1079 glDisable(GL_TEXTURE_2D
);
1080 checkGLcall("glDisable GL_TEXTURE_2D");
1081 glDisable(GL_TEXTURE_1D
);
1082 checkGLcall("glDisable GL_TEXTURE_1D");
1084 /* Activate texture 0, but don't disable it necessarilly */
1085 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
1086 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
1087 checkGLcall("glActiveTextureARB");
1090 /* And back buffers are not blended. Disable the depth test,
1091 that helps performance */
1092 glDisable(GL_BLEND
);
1093 glDisable(GL_DEPTH_TEST
);
1096 switch(wined3d_settings
.rendertargetlock_mode
) {
1100 flush_to_framebuffer_drawpixels(This
);
1105 ERR("Writing to the render target with textures is not implemented yet\n");
1110 static BOOL warned
= FALSE
;
1112 ERR("The application tries to write to the render target, but render target locking is disabled\n");
1119 if(implSwapChain
->backBuffer
&& implSwapChain
->backBuffer
[0]) {
1120 glDrawBuffer(GL_BACK
);
1121 vcheckGLcall("glDrawBuffer");
1123 if(myDevice
->stateBlock
->renderState
[D3DRS_ZENABLE
] == D3DZB_TRUE
||
1124 myDevice
->stateBlock
->renderState
[D3DRS_ZENABLE
] == D3DZB_USEW
) glEnable(GL_DEPTH_TEST
);
1125 if (myDevice
->stateBlock
->renderState
[D3DRS_ALPHABLENDENABLE
]) glEnable(GL_BLEND
);
1126 if (myDevice
->stateBlock
->renderState
[D3DRS_FOGENABLE
]) glEnable(GL_FOG
);
1130 /** restore clean dirty state */
1131 IWineD3DSurface_CleanDirtyRect(iface
);
1134 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This
, debug_d3dusage(This
->resource
.usage
));
1136 IWineD3DSwapChain_Release((IWineD3DSwapChain
*)implSwapChain
);
1138 } else if (WINED3DUSAGE_DEPTHSTENCIL
& This
->resource
.usage
) { /* stencil surfaces */
1140 if (iface
== myDevice
->depthStencilBuffer
) {
1141 FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This
, This
->resource
.usage
);
1143 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This
, This
->resource
.usage
);
1147 FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This
, debug_d3dusage(This
->resource
.usage
));
1151 This
->Flags
&= ~SFLAG_LOCKED
;
1152 memset(&This
->lockedRect
, 0, sizeof(RECT
));
1156 HRESULT WINAPI
IWineD3DSurfaceImpl_GetDC(IWineD3DSurface
*iface
, HDC
*pHDC
) {
1157 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1158 WINED3DLOCKED_RECT lock
;
1165 const PixelFormatDesc
*formatEntry
= getFormatDescEntry(This
->resource
.format
);
1167 TRACE("(%p)->(%p)\n",This
,pHDC
);
1169 /* Give more detailed info for ddraw */
1170 if (This
->Flags
& SFLAG_DCINUSE
)
1171 return DDERR_DCALREADYCREATED
;
1173 /* Can't GetDC if the surface is locked */
1174 if (This
->Flags
& SFLAG_LOCKED
)
1175 return WINED3DERR_INVALIDCALL
;
1177 memset(&lock
, 0, sizeof(lock
)); /* To be sure */
1179 /* Create a DIB section if there isn't a hdc yet */
1182 SYSTEM_INFO sysInfo
;
1184 if(This
->Flags
& SFLAG_ACTIVELOCK
) {
1185 ERR("Creating a DIB section while a lock is active. Uncertain consequences\n");
1188 switch (This
->bytesPerPixel
) {
1191 /* Allocate extra space to store the RGB bit masks. */
1192 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
) + 3 * sizeof(DWORD
));
1196 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
));
1200 /* Allocate extra space for a palette. */
1201 b_info
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1202 sizeof(BITMAPINFOHEADER
)
1204 * (1 << (This
->bytesPerPixel
* 8)));
1208 /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
1209 * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
1210 * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
1211 * add an extra line to the dib section
1213 GetSystemInfo(&sysInfo
);
1214 if( ((This
->resource
.size
+ 3) % sysInfo
.dwPageSize
) < 4) {
1216 TRACE("Adding an extra line to the dib section\n");
1219 b_info
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1220 if( (NP2_REPACK
== wined3d_settings
.nonpower2_mode
|| This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)) {
1221 b_info
->bmiHeader
.biWidth
= This
->currentDesc
.Width
;
1222 b_info
->bmiHeader
.biHeight
= -This
->currentDesc
.Height
-extraline
;
1223 b_info
->bmiHeader
.biSizeImage
= This
->currentDesc
.Width
* This
->currentDesc
.Height
* This
->bytesPerPixel
;
1224 /* Use the full pow2 image size(assigned below) because LockRect
1225 * will need it for a full glGetTexImage call
1228 b_info
->bmiHeader
.biWidth
= This
->pow2Width
;
1229 b_info
->bmiHeader
.biHeight
= -This
->pow2Height
-extraline
;
1230 b_info
->bmiHeader
.biSizeImage
= This
->resource
.size
;
1232 b_info
->bmiHeader
.biPlanes
= 1;
1233 b_info
->bmiHeader
.biBitCount
= This
->bytesPerPixel
* 8;
1235 b_info
->bmiHeader
.biXPelsPerMeter
= 0;
1236 b_info
->bmiHeader
.biYPelsPerMeter
= 0;
1237 b_info
->bmiHeader
.biClrUsed
= 0;
1238 b_info
->bmiHeader
.biClrImportant
= 0;
1240 /* Get the bit masks */
1241 masks
= (DWORD
*) &(b_info
->bmiColors
);
1242 switch (This
->resource
.format
) {
1243 case WINED3DFMT_R8G8B8
:
1244 usage
= DIB_RGB_COLORS
;
1245 b_info
->bmiHeader
.biCompression
= BI_RGB
;
1248 case WINED3DFMT_X1R5G5B5
:
1249 case WINED3DFMT_A1R5G5B5
:
1250 case WINED3DFMT_A4R4G4B4
:
1251 case WINED3DFMT_X4R4G4B4
:
1252 case WINED3DFMT_R3G3B2
:
1253 case WINED3DFMT_A8R3G3B2
:
1254 case WINED3DFMT_A2B10G10R10
:
1255 case WINED3DFMT_A8B8G8R8
:
1256 case WINED3DFMT_X8B8G8R8
:
1257 case WINED3DFMT_A2R10G10B10
:
1258 case WINED3DFMT_R5G6B5
:
1259 case WINED3DFMT_A16B16G16R16
:
1261 b_info
->bmiHeader
.biCompression
= BI_BITFIELDS
;
1262 masks
[0] = formatEntry
->redMask
;
1263 masks
[1] = formatEntry
->greenMask
;
1264 masks
[2] = formatEntry
->blueMask
;
1268 /* Don't know palette */
1269 b_info
->bmiHeader
.biCompression
= BI_RGB
;
1274 ddc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
1276 HeapFree(GetProcessHeap(), 0, b_info
);
1277 return HRESULT_FROM_WIN32(GetLastError());
1280 TRACE("Creating a DIB section with size %ldx%ldx%d, size=%ld\n", b_info
->bmiHeader
.biWidth
, b_info
->bmiHeader
.biHeight
, b_info
->bmiHeader
.biBitCount
, b_info
->bmiHeader
.biSizeImage
);
1281 This
->dib
.DIBsection
= CreateDIBSection(ddc
, b_info
, usage
, &This
->dib
.bitmap_data
, 0 /* Handle */, 0 /* Offset */);
1284 if (!This
->dib
.DIBsection
) {
1285 ERR("CreateDIBSection failed!\n");
1286 return HRESULT_FROM_WIN32(GetLastError());
1288 HeapFree(GetProcessHeap(), 0, b_info
);
1290 TRACE("DIBSection at : %p\n", This
->dib
.bitmap_data
);
1292 /* copy the existing surface to the dib section */
1293 if(This
->resource
.allocatedMemory
) {
1294 memcpy(This
->dib
.bitmap_data
, This
->resource
.allocatedMemory
, b_info
->bmiHeader
.biSizeImage
);
1295 /* We won't need that any more */
1296 HeapFree(GetProcessHeap(), 0, This
->resource
.allocatedMemory
);
1298 /* This is to make LockRect read the gl Texture although memory is allocated */
1299 This
->Flags
|= SFLAG_GLDIRTY
;
1302 /* Use the dib section from now on */
1303 This
->resource
.allocatedMemory
= This
->dib
.bitmap_data
;
1305 /* Now allocate a HDC */
1306 This
->hDC
= CreateCompatibleDC(0);
1307 This
->dib
.holdbitmap
= SelectObject(This
->hDC
, This
->dib
.DIBsection
);
1308 TRACE("using wined3d palette %p\n", This
->palette
);
1309 SelectPalette(This
->hDC
,
1310 This
->palette
? This
->palette
->hpal
: 0,
1313 This
->Flags
|= SFLAG_DIBSECTION
;
1316 /* Lock the surface */
1317 hr
= IWineD3DSurface_LockRect(iface
,
1322 ERR("IWineD3DSurface_LockRect failed with hr = %08lx\n", hr
);
1323 /* keep the dib section */
1327 if(This
->resource
.format
== WINED3DFMT_P8
||
1328 This
->resource
.format
== WINED3DFMT_A8P8
) {
1331 PALETTEENTRY ent
[256];
1333 GetPaletteEntries(This
->palette
->hpal
, 0, 256, ent
);
1334 for (n
=0; n
<256; n
++) {
1335 col
[n
].rgbRed
= ent
[n
].peRed
;
1336 col
[n
].rgbGreen
= ent
[n
].peGreen
;
1337 col
[n
].rgbBlue
= ent
[n
].peBlue
;
1338 col
[n
].rgbReserved
= 0;
1341 IWineD3DDeviceImpl
*device
= This
->resource
.wineD3DDevice
;
1343 for (n
=0; n
<256; n
++) {
1344 col
[n
].rgbRed
= device
->palettes
[device
->currentPalette
][n
].peRed
;
1345 col
[n
].rgbGreen
= device
->palettes
[device
->currentPalette
][n
].peGreen
;
1346 col
[n
].rgbBlue
= device
->palettes
[device
->currentPalette
][n
].peBlue
;
1347 col
[n
].rgbReserved
= 0;
1351 SetDIBColorTable(This
->hDC
, 0, 256, col
);
1355 TRACE("returning %p\n",*pHDC
);
1356 This
->Flags
|= SFLAG_DCINUSE
;
1361 HRESULT WINAPI
IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface
*iface
, HDC hDC
) {
1362 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1364 TRACE("(%p)->(%p)\n",This
,hDC
);
1366 if (!(This
->Flags
& SFLAG_DCINUSE
))
1367 return D3DERR_INVALIDCALL
;
1369 /* we locked first, so unlock now */
1370 IWineD3DSurface_UnlockRect(iface
);
1372 This
->Flags
&= ~SFLAG_DCINUSE
;
1377 /* ******************************************************
1378 IWineD3DSurface Internal (No mapping to directx api) parts follow
1379 ****************************************************** */
1381 HRESULT
d3dfmt_get_conv(IWineD3DSurfaceImpl
*This
, BOOL need_alpha_ck
, GLenum
*format
, GLenum
*internal
, GLenum
*type
, CONVERT_TYPES
*convert
, int *target_bpp
) {
1382 BOOL colorkey_active
= need_alpha_ck
&& (This
->CKeyFlags
& DDSD_CKSRCBLT
);
1383 const PixelFormatDesc
*formatEntry
= getFormatDescEntry(This
->resource
.format
);
1385 /* Default values: From the surface */
1386 *format
= formatEntry
->glFormat
;
1387 *internal
= formatEntry
->glInternal
;
1388 *type
= formatEntry
->glType
;
1389 *convert
= NO_CONVERSION
;
1390 *target_bpp
= This
->bytesPerPixel
;
1392 /* Ok, now look if we have to do any conversion */
1393 switch(This
->resource
.format
) {
1398 if(!GL_SUPPORT(EXT_PALETTED_TEXTURE
) || colorkey_active
) {
1400 *internal
= GL_RGBA
;
1401 *type
= GL_UNSIGNED_BYTE
;
1403 if(colorkey_active
) {
1404 *convert
= CONVERT_PALETTED
;
1406 *convert
= CONVERT_PALETTED_CK
;
1412 case WINED3DFMT_R3G3B2
:
1413 /* **********************
1414 GL_UNSIGNED_BYTE_3_3_2
1415 ********************** */
1416 if (colorkey_active
) {
1417 /* This texture format will never be used.. So do not care about color keying
1418 up until the point in time it will be needed :-) */
1419 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1423 case WINED3DFMT_R5G6B5
:
1424 if (colorkey_active
) {
1425 *convert
= CONVERT_CK_565
;
1427 *internal
= GL_RGBA
;
1428 *type
= GL_UNSIGNED_SHORT_5_5_5_1
;
1432 case WINED3DFMT_R8G8B8
:
1433 if (colorkey_active
) {
1434 *convert
= CONVERT_CK_RGB24
;
1436 *internal
= GL_RGBA
;
1437 *type
= GL_UNSIGNED_INT_8_8_8_8
;
1442 case WINED3DFMT_X8R8G8B8
:
1443 if (colorkey_active
) {
1444 *convert
= CONVERT_RGB32_888
;
1446 *internal
= GL_RGBA
;
1447 *type
= GL_UNSIGNED_INT_8_8_8_8
;
1451 /* Not sure if we should do color keying on Alpha-Enabled surfaces */
1452 case WINED3DFMT_A4R4G4B4
:
1453 if (colorkey_active
)
1455 *convert
= CONVERT_CK_4444_ARGB
;
1457 *internal
= GL_RGBA
;
1458 *type
= GL_UNSIGNED_SHORT_4_4_4_4
;
1462 case WINED3DFMT_A1R5G5B5
:
1463 if (colorkey_active
)
1465 *convert
= CONVERT_CK_1555
;
1468 case WINED3DFMT_A8R8G8B8
:
1469 if (colorkey_active
)
1471 *convert
= CONVERT_CK_8888_ARGB
;
1473 *internal
= GL_RGBA
;
1474 *type
= GL_UNSIGNED_INT_8_8_8_8
;
1485 HRESULT
d3dfmt_convert_surface(BYTE
*src
, BYTE
*dst
, unsigned long len
, CONVERT_TYPES convert
, IWineD3DSurfaceImpl
*surf
) {
1486 TRACE("(%p)->(%p),(%ld,%d,%p)\n", src
, dst
, len
, convert
, surf
);
1491 memcpy(dst
, src
, len
* surf
->bytesPerPixel
);
1494 case CONVERT_PALETTED
:
1495 case CONVERT_PALETTED_CK
:
1497 IWineD3DPaletteImpl
* pal
= surf
->palette
;
1503 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1507 /* Still no palette? Use the device's palette */
1508 /* Get the surface's palette */
1509 for (i
= 0; i
< 256; i
++) {
1510 IWineD3DDeviceImpl
*device
= surf
->resource
.wineD3DDevice
;
1512 table
[i
][0] = device
->palettes
[device
->currentPalette
][i
].peRed
;
1513 table
[i
][1] = device
->palettes
[device
->currentPalette
][i
].peGreen
;
1514 table
[i
][2] = device
->palettes
[device
->currentPalette
][i
].peBlue
;
1515 if ((convert
== CONVERT_PALETTED_CK
) &&
1516 (i
>= surf
->SrcBltCKey
.dwColorSpaceLowValue
) &&
1517 (i
<= surf
->SrcBltCKey
.dwColorSpaceHighValue
)) {
1518 /* We should maybe here put a more 'neutral' color than the standard bright purple
1519 one often used by application to prevent the nice purple borders when bi-linear
1527 TRACE("Using surface palette %p\n", pal
);
1528 /* Get the surface's palette */
1529 for (i
= 0; i
< 256; i
++) {
1530 table
[i
][0] = pal
->palents
[i
].peRed
;
1531 table
[i
][1] = pal
->palents
[i
].peGreen
;
1532 table
[i
][2] = pal
->palents
[i
].peBlue
;
1533 if ((convert
== CONVERT_PALETTED_CK
) &&
1534 (i
>= surf
->SrcBltCKey
.dwColorSpaceLowValue
) &&
1535 (i
<= surf
->SrcBltCKey
.dwColorSpaceHighValue
)) {
1536 /* We should maybe here put a more 'neutral' color than the standard bright purple
1537 one often used by application to prevent the nice purple borders when bi-linear
1546 for (x
= 0; x
< len
; x
++) {
1547 BYTE color
= *src
++;
1548 *dst
++ = table
[color
][0];
1549 *dst
++ = table
[color
][1];
1550 *dst
++ = table
[color
][2];
1551 *dst
++ = table
[color
][3];
1556 case CONVERT_CK_565
:
1558 /* Converting the 565 format in 5551 packed to emulate color-keying.
1560 Note : in all these conversion, it would be best to average the averaging
1561 pixels to get the color of the pixel that will be color-keyed to
1562 prevent 'color bleeding'. This will be done later on if ever it is
1565 Note2: when using color-keying + alpha, are the alpha bits part of the
1566 color-space or not ?
1569 WORD
*Source
= (WORD
*) src
;
1570 WORD
*Dest
= (WORD
*) dst
;
1572 TRACE("Color keyed 565\n");
1574 for (x
= 0; x
< len
; x
++ ) {
1575 WORD color
= *Source
++;
1576 *Dest
= ((color
& 0xFFC0) | ((color
& 0x1F) << 1));
1577 if ((color
< surf
->SrcBltCKey
.dwColorSpaceLowValue
) ||
1578 (color
> surf
->SrcBltCKey
.dwColorSpaceHighValue
)) {
1586 case CONVERT_CK_1555
:
1589 WORD
*Source
= (WORD
*) src
;
1590 WORD
*Dest
= (WORD
*) dst
;
1592 for (x
= 0; x
< len
* sizeof(WORD
); x
+=sizeof(WORD
)) {
1593 WORD color
= *Source
++;
1594 *Dest
= (color
& 0x7FFF);
1595 if ((color
< surf
->SrcBltCKey
.dwColorSpaceLowValue
) ||
1596 (color
> surf
->SrcBltCKey
.dwColorSpaceHighValue
))
1597 *Dest
|= (color
& 0x8000);
1603 case CONVERT_CK_4444_ARGB
:
1605 /* Move the four Alpha bits... */
1607 WORD
*Source
= (WORD
*) src
;
1608 WORD
*Dest
= (WORD
*) dst
;
1610 for (x
= 0; x
< len
; x
++) {
1611 WORD color
= *Source
++;
1612 *dst
= (color
& 0x0FFF) << 4;
1613 if ((color
< surf
->SrcBltCKey
.dwColorSpaceLowValue
) ||
1614 (color
> surf
->SrcBltCKey
.dwColorSpaceHighValue
))
1615 *Dest
|= (color
& 0xF000) >> 12;
1621 ERR("Unsupported conversation type %d\n", convert
);
1627 static HRESULT WINAPI
IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface
*iface
) {
1628 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1630 if (This
->Flags
& SFLAG_INTEXTURE
) {
1631 TRACE("Surface already in texture\n");
1634 if (!(This
->Flags
& SFLAG_DIRTY
)) {
1635 TRACE("surface isn't dirty\n");
1639 This
->Flags
&= ~SFLAG_DIRTY
;
1641 /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1642 * These resources are not bound by device size or format restrictions. Because of this,
1643 * these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1644 * However, these resources can always be created, locked, and copied.
1646 if (This
->resource
.pool
== WINED3DPOOL_SCRATCH
)
1648 FIXME("(%p) Operation not supported for scratch textures\n",This
);
1649 return WINED3DERR_INVALIDCALL
;
1652 if (This
->Flags
& SFLAG_INPBUFFER
) {
1655 if (This
->glDescription
.level
!= 0)
1656 FIXME("Surface in texture is only supported for level 0\n");
1657 else if (This
->resource
.format
== WINED3DFMT_P8
|| This
->resource
.format
== WINED3DFMT_A8P8
||
1658 This
->resource
.format
== WINED3DFMT_DXT1
|| This
->resource
.format
== WINED3DFMT_DXT2
||
1659 This
->resource
.format
== WINED3DFMT_DXT3
|| This
->resource
.format
== WINED3DFMT_DXT4
||
1660 This
->resource
.format
== WINED3DFMT_DXT5
)
1661 FIXME("Format %d not supported\n", This
->resource
.format
);
1664 glGetIntegerv(GL_READ_BUFFER
, &prevRead
);
1665 vcheckGLcall("glGetIntegerv");
1666 glReadBuffer(GL_BACK
);
1667 vcheckGLcall("glReadBuffer");
1669 glCopyTexImage2D(This
->glDescription
.target
,
1670 This
->glDescription
.level
,
1671 This
->glDescription
.glFormatInternal
,
1674 This
->currentDesc
.Width
,
1675 This
->currentDesc
.Height
,
1678 checkGLcall("glCopyTexImage2D");
1679 glReadBuffer(prevRead
);
1680 vcheckGLcall("glReadBuffer");
1681 TRACE("Updating target %d\n", This
->glDescription
.target
);
1682 This
->Flags
|= SFLAG_INTEXTURE
;
1688 /* TODO: Compressed non-power 2 support */
1690 if (This
->resource
.format
== WINED3DFMT_DXT1
||
1691 This
->resource
.format
== WINED3DFMT_DXT2
||
1692 This
->resource
.format
== WINED3DFMT_DXT3
||
1693 This
->resource
.format
== WINED3DFMT_DXT4
||
1694 This
->resource
.format
== WINED3DFMT_DXT5
) {
1695 if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
1696 FIXME("Using DXT1/3/5 without advertized support\n");
1697 } else if (This
->resource
.allocatedMemory
) {
1698 TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
1699 This
->glDescription
.target
,
1700 This
->glDescription
.level
,
1701 This
->glDescription
.glFormatInternal
,
1702 This
->currentDesc
.Width
,
1703 This
->currentDesc
.Height
,
1705 This
->resource
.size
,
1706 This
->resource
.allocatedMemory
);
1710 GL_EXTCALL(glCompressedTexImage2DARB
)(This
->glDescription
.target
,
1711 This
->glDescription
.level
,
1712 This
->glDescription
.glFormatInternal
,
1713 This
->currentDesc
.Width
,
1714 This
->currentDesc
.Height
,
1716 This
->resource
.size
,
1717 This
->resource
.allocatedMemory
);
1718 checkGLcall("glCommpressedTexImage2D");
1722 if(!(This
->Flags
& SFLAG_DONOTFREE
)){
1723 HeapFree(GetProcessHeap(), 0, This
->resource
.allocatedMemory
);
1724 This
->resource
.allocatedMemory
= NULL
;
1728 GLenum format
, internal
, type
;
1729 CONVERT_TYPES convert
;
1733 d3dfmt_get_conv(This
, TRUE
/* We need color keying */, &format
, &internal
, &type
, &convert
, &bpp
);
1735 if((convert
!= NO_CONVERSION
) &&
1736 This
->resource
.allocatedMemory
) {
1737 int width
= This
->glRect
.right
- This
->glRect
.left
;
1738 int height
= This
->glRect
.bottom
- This
->glRect
.top
;
1741 mem
= HeapAlloc(GetProcessHeap(), 0, width
* height
* bpp
);
1743 ERR("Out of memory %d, %d!\n", width
, height
);
1744 return WINED3DERR_OUTOFVIDEOMEMORY
;
1747 for(row
= This
->glRect
.top
; row
< This
->glRect
.bottom
; row
++) {
1748 BYTE
*cur
= This
->resource
.allocatedMemory
+ row
* This
->pow2Width
* This
->bytesPerPixel
;
1749 d3dfmt_convert_surface(cur
+ This
->glRect
.left
* This
->bytesPerPixel
,
1750 mem
+ row
* width
* bpp
,
1755 This
->Flags
|= SFLAG_CONVERTED
;
1757 This
->Flags
&= ~SFLAG_CONVERTED
;
1758 mem
= This
->resource
.allocatedMemory
;
1761 /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
1762 if (NP2_REPACK
== wined3d_settings
.nonpower2_mode
&& (This
->Flags
& SFLAG_NONPOW2
) && !(This
->Flags
& SFLAG_OVERSIZE
) ) {
1765 TRACE("non power of two support\n");
1767 TRACE("(%p) Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n", This
,
1768 This
->glDescription
.target
,
1769 This
->glDescription
.level
,
1770 debug_d3dformat(This
->resource
.format
),
1771 This
->glDescription
.glFormatInternal
,
1775 This
->glDescription
.glFormat
,
1776 This
->glDescription
.glType
,
1779 glTexImage2D(This
->glDescription
.target
,
1780 This
->glDescription
.level
,
1781 This
->glDescription
.glFormatInternal
,
1785 This
->glDescription
.glFormat
,
1786 This
->glDescription
.glType
,
1789 checkGLcall("glTexImage2D");
1790 if (This
->resource
.allocatedMemory
!= NULL
) {
1791 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This
, This
->currentDesc
.Width
, This
->currentDesc
.Height
, This
->resource
.allocatedMemory
);
1792 /* And map the non-power two data into the top left corner */
1794 This
->glDescription
.target
,
1795 This
->glDescription
.level
,
1798 This
->currentDesc
.Width
,
1799 This
->currentDesc
.Height
,
1800 This
->glDescription
.glFormat
,
1801 This
->glDescription
.glType
,
1802 This
->resource
.allocatedMemory
1804 checkGLcall("glTexSubImage2D");
1810 TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%ld, h=%ld,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
1811 This
->glDescription
.target
,
1812 This
->glDescription
.level
,
1813 debug_d3dformat(This
->resource
.format
),
1814 This
->glDescription
.glFormatInternal
,
1815 This
->glRect
.right
- This
->glRect
.left
,
1816 This
->glRect
.bottom
- This
->glRect
.top
,
1818 This
->glDescription
.glFormat
,
1819 This
->glDescription
.glType
,
1824 /* OK, create the texture */
1825 glTexImage2D(This
->glDescription
.target
,
1826 This
->glDescription
.level
,
1828 This
->glRect
.right
- This
->glRect
.left
,
1829 This
->glRect
.bottom
- This
->glRect
.top
,
1835 checkGLcall("glTexImage2D");
1839 if(mem
!= This
->resource
.allocatedMemory
)
1840 HeapFree(GetProcessHeap(), 0, mem
);
1844 static unsigned int gen
= 0;
1847 if ((gen
% 10) == 0) {
1848 snprintf(buffer
, sizeof(buffer
), "/tmp/surface%p_type%u_level%u_%u.ppm", This
, This
->glDescription
.target
, This
->glDescription
.level
, gen
);
1849 IWineD3DSurfaceImpl_SaveSnapshot(iface
, buffer
);
1852 * debugging crash code
1860 if(!(This
->Flags
& SFLAG_DONOTFREE
)){
1861 HeapFree(GetProcessHeap(),0,This
->resource
.allocatedMemory
);
1862 This
->resource
.allocatedMemory
= NULL
;
1872 HRESULT WINAPI
IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface
*iface
, const char* filename
) {
1875 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
1876 char *allocatedMemory
;
1878 IWineD3DSwapChain
*swapChain
= NULL
;
1883 Textures my not be stored in ->allocatedgMemory and a GlTexture
1884 so we should lock the surface before saving a snapshot, or at least check that
1886 /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1887 by calling GetTexImage and in compressed form by calling
1888 GetCompressedTexImageARB. Queried compressed images can be saved and
1889 later reused by calling CompressedTexImage[123]DARB. Pre-compressed
1890 texture images do not need to be processed by the GL and should
1891 significantly improve texture loading performance relative to uncompressed
1894 /* Setup the width and height to be the internal texture width and height. */
1895 width
= This
->pow2Width
;
1896 height
= This
->pow2Height
;
1897 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1898 IWineD3DSurface_GetContainer(iface
, &IID_IWineD3DSwapChain
, (void **)&swapChain
);
1900 if (swapChain
|| (This
->Flags
& SFLAG_INPBUFFER
)) { /* if were not a real texture then read the back buffer into a real texture*/
1901 /* 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 */
1904 FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This
);
1905 glEnable(GL_TEXTURE_2D
);
1907 glGenTextures(1, &tmpTexture
);
1908 glBindTexture(GL_TEXTURE_2D
, tmpTexture
);
1910 glTexImage2D(GL_TEXTURE_2D
,
1917 GL_UNSIGNED_INT_8_8_8_8_REV
,
1920 glGetIntegerv(GL_READ_BUFFER
, &prevRead
);
1921 vcheckGLcall("glGetIntegerv");
1922 glReadBuffer(GL_BACK
);
1923 vcheckGLcall("glReadBuffer");
1924 glCopyTexImage2D(GL_TEXTURE_2D
,
1933 checkGLcall("glCopyTexImage2D");
1934 glReadBuffer(prevRead
);
1937 } else { /* bind the real texture */
1938 IWineD3DSurface_PreLoad(iface
);
1940 allocatedMemory
= HeapAlloc(GetProcessHeap(), 0, width
* height
* 4);
1942 FIXME("Saving texture level %d width %d height %d\n", This
->glDescription
.level
, width
, height
);
1943 glGetTexImage(GL_TEXTURE_2D
,
1944 This
->glDescription
.level
,
1946 GL_UNSIGNED_INT_8_8_8_8_REV
,
1948 checkGLcall("glTexImage2D");
1950 glBindTexture(GL_TEXTURE_2D
, 0);
1951 glDeleteTextures(1, &tmpTexture
);
1955 f
= fopen(filename
, "w+");
1957 ERR("opening of %s failed with: %s\n", filename
, strerror(errno
));
1958 return WINED3DERR_INVALIDCALL
;
1960 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1961 TRACE("(%p) opened %s with format %s\n", This
, filename
, debug_d3dformat(This
->resource
.format
));
1976 fwrite(&width
,2,1,f
);
1978 fwrite(&height
,2,1,f
);
1983 /* 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*/
1985 textureRow
= allocatedMemory
+ (width
* (height
- 1) *4);
1987 textureRow
= allocatedMemory
;
1988 for (y
= 0 ; y
< height
; y
++) {
1989 for (i
= 0; i
< width
; i
++) {
1990 color
= *((DWORD
*)textureRow
);
1991 fputc((color
>> 16) & 0xFF, f
); /* B */
1992 fputc((color
>> 8) & 0xFF, f
); /* G */
1993 fputc((color
>> 0) & 0xFF, f
); /* R */
1994 fputc((color
>> 24) & 0xFF, f
); /* A */
1997 /* take two rows of the pointer to the texture memory */
1999 (textureRow
-= width
<< 3);
2002 TRACE("Closing file\n");
2006 IWineD3DSwapChain_Release(swapChain
);
2008 HeapFree(GetProcessHeap(), 0, allocatedMemory
);
2012 HRESULT WINAPI
IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface
*iface
) {
2013 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2014 This
->Flags
&= ~SFLAG_DIRTY
;
2015 This
->dirtyRect
.left
= This
->currentDesc
.Width
;
2016 This
->dirtyRect
.top
= This
->currentDesc
.Height
;
2017 This
->dirtyRect
.right
= 0;
2018 This
->dirtyRect
.bottom
= 0;
2019 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This
, This
->Flags
& SFLAG_DIRTY
? 1 : 0, This
->dirtyRect
.left
,
2020 This
->dirtyRect
.top
, This
->dirtyRect
.right
, This
->dirtyRect
.bottom
);
2025 * Slightly inefficient way to handle multiple dirty rects but it works :)
2027 extern HRESULT WINAPI
IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface
*iface
, CONST RECT
* pDirtyRect
) {
2028 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2029 IWineD3DBaseTexture
*baseTexture
= NULL
;
2030 This
->Flags
|= SFLAG_DIRTY
;
2031 if (NULL
!= pDirtyRect
) {
2032 This
->dirtyRect
.left
= min(This
->dirtyRect
.left
, pDirtyRect
->left
);
2033 This
->dirtyRect
.top
= min(This
->dirtyRect
.top
, pDirtyRect
->top
);
2034 This
->dirtyRect
.right
= max(This
->dirtyRect
.right
, pDirtyRect
->right
);
2035 This
->dirtyRect
.bottom
= max(This
->dirtyRect
.bottom
, pDirtyRect
->bottom
);
2037 This
->dirtyRect
.left
= 0;
2038 This
->dirtyRect
.top
= 0;
2039 This
->dirtyRect
.right
= This
->currentDesc
.Width
;
2040 This
->dirtyRect
.bottom
= This
->currentDesc
.Height
;
2042 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This
, This
->Flags
& SFLAG_DIRTY
, This
->dirtyRect
.left
,
2043 This
->dirtyRect
.top
, This
->dirtyRect
.right
, This
->dirtyRect
.bottom
);
2044 /* if the container is a basetexture then mark it dirty. */
2045 if (IWineD3DSurface_GetContainer(iface
, &IID_IWineD3DBaseTexture
, (void **)&baseTexture
) == WINED3D_OK
) {
2046 TRACE("Passing to conatiner\n");
2047 IWineD3DBaseTexture_SetDirty(baseTexture
, TRUE
);
2048 IWineD3DBaseTexture_Release(baseTexture
);
2053 HRESULT WINAPI
IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface
*iface
, IWineD3DBase
*container
) {
2054 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2056 TRACE("This %p, container %p\n", This
, container
);
2058 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
2060 TRACE("Setting container to %p from %p\n", container
, This
->container
);
2061 This
->container
= container
;
2066 HRESULT WINAPI
IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface
*iface
, WINED3DFORMAT format
) {
2067 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2068 const PixelFormatDesc
*formatEntry
= getFormatDescEntry(format
);
2070 if (This
->resource
.format
!= WINED3DFMT_UNKNOWN
) {
2071 FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This
);
2072 return WINED3DERR_INVALIDCALL
;
2075 TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This
, format
, debug_d3dformat(format
));
2076 if (format
== WINED3DFMT_UNKNOWN
) {
2077 This
->resource
.size
= 0;
2078 } else if (format
== WINED3DFMT_DXT1
) {
2079 /* DXT1 is half byte per pixel */
2080 This
->resource
.size
= ((max(This
->pow2Width
, 4) * formatEntry
->bpp
) * max(This
->pow2Height
, 4)) >> 1;
2082 } else if (format
== WINED3DFMT_DXT2
|| format
== WINED3DFMT_DXT3
||
2083 format
== WINED3DFMT_DXT4
|| format
== WINED3DFMT_DXT5
) {
2084 This
->resource
.size
= ((max(This
->pow2Width
, 4) * formatEntry
->bpp
) * max(This
->pow2Height
, 4));
2086 This
->resource
.size
= (This
->pow2Width
* formatEntry
->bpp
) * This
->pow2Height
;
2090 /* Setup some glformat defaults */
2091 This
->glDescription
.glFormat
= formatEntry
->glFormat
;
2092 This
->glDescription
.glFormatInternal
= formatEntry
->glInternal
;
2093 This
->glDescription
.glType
= formatEntry
->glType
;
2095 if (format
!= WINED3DFMT_UNKNOWN
) {
2096 This
->bytesPerPixel
= formatEntry
->bpp
;
2097 This
->pow2Size
= (This
->pow2Width
* This
->bytesPerPixel
) * This
->pow2Height
;
2099 This
->bytesPerPixel
= 0;
2103 This
->Flags
|= (WINED3DFMT_D16_LOCKABLE
== format
) ? SFLAG_LOCKABLE
: 0;
2105 This
->resource
.format
= format
;
2107 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
);
2112 /* TODO: replace this function with context management routines */
2113 HRESULT WINAPI
IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface
*iface
, BOOL inPBuffer
, BOOL inTexture
) {
2114 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2117 This
->Flags
|= SFLAG_INPBUFFER
;
2119 This
->Flags
&= ~SFLAG_INPBUFFER
;
2123 This
->Flags
|= SFLAG_INTEXTURE
;
2125 This
->Flags
&= ~SFLAG_INTEXTURE
;
2131 static HRESULT WINAPI
IWineD3DSurfaceImpl_Flip(IWineD3DSurface
*iface
, IWineD3DSurface
*override
, DWORD Flags
) {
2132 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2133 IWineD3DDevice
*D3D
= (IWineD3DDevice
*) This
->resource
.wineD3DDevice
;
2134 TRACE("(%p)->(%p,%lx)\n", This
, override
, Flags
);
2136 /* Flipping is only supported on RenderTargets */
2137 if( !(This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ) return DDERR_NOTFLIPPABLE
;
2140 /* DDraw sets this for the X11 surfaces, so don't confuse the user
2141 * FIXME("(%p) Target override is not supported by now\n", This);
2142 * Additionally, it isn't really possible to support triple-buffering
2143 * properly on opengl at all
2147 /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2148 return IWineD3DDevice_Present(D3D
, NULL
, NULL
, 0, NULL
);
2151 /* Not called from the VTable */
2152 static HRESULT
IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl
*This
, RECT
*DestRect
, IWineD3DSurface
*SrcSurface
, RECT
*SrcRect
, DWORD Flags
, DDBLTFX
*DDBltFx
) {
2154 IWineD3DDeviceImpl
*myDevice
= This
->resource
.wineD3DDevice
;
2155 IWineD3DSwapChainImpl
*swapchain
= NULL
;
2156 IWineD3DSurfaceImpl
*Src
= (IWineD3DSurfaceImpl
*) SrcSurface
;
2159 TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This
, DestRect
, SrcSurface
, SrcRect
, Flags
, DDBltFx
);
2161 /* Get the swapchain. One of the surfaces has to be a primary surface */
2162 IWineD3DSurface_GetContainer( (IWineD3DSurface
*) This
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
2163 if(swapchain
) IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
2165 IWineD3DSurface_GetContainer( (IWineD3DSurface
*) Src
, &IID_IWineD3DSwapChain
, (void **)&swapchain
);
2166 if(swapchain
) IWineD3DSwapChain_Release((IWineD3DSwapChain
*) swapchain
);
2167 else return WINED3DERR_INVALIDCALL
;
2173 rect
.x1
= DestRect
->left
;
2174 rect
.y1
= DestRect
->top
;
2175 rect
.x2
= DestRect
->right
;
2176 rect
.y2
= DestRect
->bottom
;
2180 rect
.x2
= This
->currentDesc
.Width
;
2181 rect
.y2
= This
->currentDesc
.Height
;
2184 /* Half-life does a Blt from the back buffer to the front buffer,
2185 * Full surface size, no flags... Use present instead
2189 /* First, check if we can do a Flip */
2191 /* Check rects - IWineD3DDevice_Present doesn't handle them */
2193 if( (SrcRect
->left
== 0) && (SrcRect
->top
== 0) &&
2194 (SrcRect
->right
== Src
->currentDesc
.Width
) && (SrcRect
->bottom
== Src
->currentDesc
.Height
) ) {
2201 /* Check the Destination rect and the surface sizes */
2203 (rect
.x1
== 0) && (rect
.y1
== 0) &&
2204 (rect
.x2
== This
->currentDesc
.Width
) && (rect
.y2
== This
->currentDesc
.Height
) &&
2205 (This
->currentDesc
.Width
== Src
->currentDesc
.Width
) &&
2206 (This
->currentDesc
.Height
== Src
->currentDesc
.Height
)) {
2207 /* These flags are unimportant for the flag check, remove them */
2209 if((Flags
& ~(DDBLT_DONOTWAIT
| DDBLT_WAIT
)) == 0) {
2210 if( swapchain
->backBuffer
&& ((IWineD3DSurface
*) This
== swapchain
->frontBuffer
) && ((IWineD3DSurface
*) Src
== swapchain
->backBuffer
[0]) ) {
2212 D3DSWAPEFFECT orig_swap
= swapchain
->presentParms
.SwapEffect
;
2214 /* The idea behind this is that a glReadPixels and a glDrawPixels call
2215 * take very long, while a flip is fast.
2216 * This applies to Half-Life, which does such Blts every time it finished
2217 * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2218 * menu. This is also used by all apps when they do windowed rendering
2220 * The problem is that flipping is not really the same as copying. After a
2221 * Blt the front buffer is a copy of the back buffer, and the back buffer is
2222 * untouched. Therefore it's necessary to override the swap effect
2223 * and to set it back after the flip.
2226 swapchain
->presentParms
.SwapEffect
= WINED3DSWAPEFFECT_COPY
;
2228 TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2229 IWineD3DDevice_Present((IWineD3DDevice
*) This
->resource
.wineD3DDevice
,
2230 NULL
, NULL
, 0, NULL
);
2232 swapchain
->presentParms
.SwapEffect
= orig_swap
;
2239 /* Blt from texture to rendertarget? */
2240 if( ( ( (IWineD3DSurface
*) This
== swapchain
->frontBuffer
) ||
2241 ( swapchain
->backBuffer
&& (IWineD3DSurface
*) This
== swapchain
->backBuffer
[0]) )
2243 ( ( (IWineD3DSurface
*) Src
!= swapchain
->frontBuffer
) &&
2244 ( swapchain
->backBuffer
&& (IWineD3DSurface
*) Src
!= swapchain
->backBuffer
[0]) ) ) {
2245 float glTexCoord
[4];
2247 GLint oldLight
, oldFog
, oldDepth
, oldBlend
, oldCull
, oldAlpha
;
2251 RECT SourceRectangle
;
2254 TRACE("Blt from surface %p to rendertarget %p\n", Src
, This
);
2257 SourceRectangle
.left
= SrcRect
->left
;
2258 SourceRectangle
.right
= SrcRect
->right
;
2259 SourceRectangle
.top
= SrcRect
->top
;
2260 SourceRectangle
.bottom
= SrcRect
->bottom
;
2262 SourceRectangle
.left
= 0;
2263 SourceRectangle
.right
= Src
->currentDesc
.Width
;
2264 SourceRectangle
.top
= 0;
2265 SourceRectangle
.bottom
= Src
->currentDesc
.Height
;
2268 if(!CalculateTexRect(Src
, &SourceRectangle
, glTexCoord
)) {
2269 /* Fall back to software */
2270 WARN("(%p) Source texture area (%ld,%ld)-(%ld,%ld) is too big\n", Src
,
2271 SourceRectangle
.left
, SourceRectangle
.top
,
2272 SourceRectangle
.right
, SourceRectangle
.bottom
);
2273 return WINED3DERR_INVALIDCALL
;
2276 /* Color keying: Check if we have to do a color keyed blt,
2277 * and if not check if a color key is activated.
2279 oldCKey
= Src
->CKeyFlags
;
2280 if(!(Flags
& DDBLT_KEYSRC
) &&
2281 Src
->CKeyFlags
& DDSD_CKSRCBLT
) {
2282 /* Ok, the surface has a color key, but we shall not use it -
2283 * Deactivate it for now and dirtify the surface to reload it
2285 Src
->CKeyFlags
&= ~DDSD_CKSRCBLT
;
2286 Src
->Flags
|= SFLAG_DIRTY
;
2289 /* Now load the surface */
2290 IWineD3DSurface_PreLoad((IWineD3DSurface
*) Src
);
2294 /* Save all the old stuff until we have a proper opengl state manager */
2295 oldLight
= glIsEnabled(GL_LIGHTING
);
2296 oldFog
= glIsEnabled(GL_FOG
);
2297 oldDepth
= glIsEnabled(GL_DEPTH_TEST
);
2298 oldBlend
= glIsEnabled(GL_BLEND
);
2299 oldCull
= glIsEnabled(GL_CULL_FACE
);
2300 oldAlpha
= glIsEnabled(GL_ALPHA_TEST
);
2301 oldStencil
= glIsEnabled(GL_STENCIL_TEST
);
2303 glGetIntegerv(GL_ALPHA_TEST_FUNC
, &alphafunc
);
2304 checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC");
2305 glGetFloatv(GL_ALPHA_TEST_REF
, &alpharef
);
2306 checkGLcall("glGetFloatv GL_ALPHA_TEST_REF");
2308 glGetIntegerv(GL_DRAW_BUFFER
, &oldDraw
);
2309 if(This
== (IWineD3DSurfaceImpl
*) swapchain
->frontBuffer
) {
2310 TRACE("Drawing to front buffer\n");
2311 glDrawBuffer(GL_FRONT
);
2312 checkGLcall("glDrawBuffer GL_FRONT");
2315 /* Unbind the old texture */
2316 glBindTexture(GL_TEXTURE_2D
, 0);
2318 if (GL_SUPPORT(ARB_MULTITEXTURE
)) {
2319 /* We use texture unit 0 for blts */
2320 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB
));
2321 checkGLcall("glActiveTextureARB");
2323 WARN("Multi-texturing is unsupported in the local OpenGL implementation\n");
2326 /* Disable some fancy graphics effects */
2327 glDisable(GL_LIGHTING
);
2328 checkGLcall("glDisable GL_LIGHTING");
2329 glDisable(GL_DEPTH_TEST
);
2330 checkGLcall("glDisable GL_DEPTH_TEST");
2332 checkGLcall("glDisable GL_FOG");
2333 glDisable(GL_BLEND
);
2334 checkGLcall("glDisable GL_BLEND");
2335 glDisable(GL_CULL_FACE
);
2336 checkGLcall("glDisable GL_CULL_FACE");
2337 glDisable(GL_STENCIL_TEST
);
2338 checkGLcall("glDisable GL_STENCIL_TEST");
2340 /* Ok, we need 2d textures, but not 1D or 3D */
2341 glDisable(GL_TEXTURE_1D
);
2342 checkGLcall("glDisable GL_TEXTURE_1D");
2343 glEnable(GL_TEXTURE_2D
);
2344 checkGLcall("glEnable GL_TEXTURE_2D");
2345 glDisable(GL_TEXTURE_3D
);
2346 checkGLcall("glDisable GL_TEXTURE_3D");
2348 /* Bind the texture */
2349 glBindTexture(GL_TEXTURE_2D
, Src
->glDescription
.textureName
);
2350 checkGLcall("glBindTexture");
2352 glEnable(GL_SCISSOR_TEST
);
2354 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
2356 /* No filtering for blts */
2357 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
,
2359 checkGLcall("glTexParameteri");
2360 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
2362 checkGLcall("glTexParameteri");
2363 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
2364 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
2365 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
2366 checkGLcall("glTexEnvi");
2368 /* This is for color keying */
2369 if(Flags
& DDBLT_KEYSRC
) {
2370 glEnable(GL_ALPHA_TEST
);
2371 checkGLcall("glEnable GL_ALPHA_TEST");
2372 glAlphaFunc(GL_NOTEQUAL
, 0.0);
2373 checkGLcall("glAlphaFunc\n");
2375 glDisable(GL_ALPHA_TEST
);
2376 checkGLcall("glDisable GL_ALPHA_TEST");
2379 /* Draw a textured quad
2381 d3ddevice_set_ortho(This
->resource
.wineD3DDevice
);
2385 glColor3d(1.0f
, 1.0f
, 1.0f
);
2386 glTexCoord2f(glTexCoord
[0], glTexCoord
[2]);
2391 glTexCoord2f(glTexCoord
[0], glTexCoord
[3]);
2392 glVertex3f(rect
.x1
, rect
.y2
, 0.0);
2394 glTexCoord2f(glTexCoord
[1], glTexCoord
[3]);
2399 glTexCoord2f(glTexCoord
[1], glTexCoord
[2]);
2404 checkGLcall("glEnd");
2406 /* Unbind the texture */
2407 glBindTexture(GL_TEXTURE_2D
, 0);
2408 checkGLcall("glEnable glBindTexture");
2410 /* Restore the old settings */
2412 glEnable(GL_LIGHTING
);
2413 checkGLcall("glEnable GL_LIGHTING");
2417 checkGLcall("glEnable GL_FOG");
2420 glEnable(GL_DEPTH_TEST
);
2421 checkGLcall("glEnable GL_DEPTH_TEST");
2425 checkGLcall("glEnable GL_BLEND");
2428 glEnable(GL_CULL_FACE
);
2429 checkGLcall("glEnable GL_CULL_FACE");
2432 glEnable(GL_STENCIL_TEST
);
2433 checkGLcall("glEnable GL_STENCIL_TEST");
2436 glDisable(GL_ALPHA_TEST
);
2437 checkGLcall("glDisable GL_ALPHA_TEST");
2439 glEnable(GL_ALPHA_TEST
);
2440 checkGLcall("glEnable GL_ALPHA_TEST");
2443 glAlphaFunc(alphafunc
, alpharef
);
2444 checkGLcall("glAlphaFunc\n");
2446 if(This
== (IWineD3DSurfaceImpl
*) swapchain
->frontBuffer
&& oldDraw
== GL_BACK
) {
2447 glDrawBuffer(oldDraw
);
2450 /* Restore the color key */
2451 if(oldCKey
!= Src
->CKeyFlags
) {
2452 Src
->CKeyFlags
= oldCKey
;
2453 Src
->Flags
|= SFLAG_DIRTY
;
2458 /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2459 This
->Flags
|= SFLAG_GLDIRTY
;
2465 /* Blt from rendertarget to texture? */
2466 if( (SrcSurface
== swapchain
->frontBuffer
) ||
2467 (swapchain
->backBuffer
&& SrcSurface
== swapchain
->backBuffer
[0]) ) {
2468 if( ( (IWineD3DSurface
*) This
!= swapchain
->frontBuffer
) &&
2469 ( swapchain
->backBuffer
&& (IWineD3DSurface
*) This
!= swapchain
->backBuffer
[0]) ) {
2474 TRACE("Blt from rendertarget to texture\n");
2476 /* Call preload for the surface to make sure it isn't dirty */
2477 IWineD3DSurface_PreLoad((IWineD3DSurface
*) This
);
2480 srect
.x1
= SrcRect
->left
;
2481 srect
.y1
= SrcRect
->top
;
2482 srect
.x2
= SrcRect
->right
;
2483 srect
.y2
= SrcRect
->bottom
;
2487 srect
.x2
= Src
->currentDesc
.Width
;
2488 srect
.y2
= Src
->currentDesc
.Height
;
2493 /* Bind the target texture */
2494 glBindTexture(GL_TEXTURE_2D
, This
->glDescription
.textureName
);
2495 checkGLcall("glBindTexture");
2496 if(swapchain
->backBuffer
&& SrcSurface
== swapchain
->backBuffer
[0]) {
2497 glReadBuffer(GL_BACK
);
2499 glReadBuffer(GL_FRONT
);
2501 checkGLcall("glReadBuffer");
2503 xrel
= (float) (srect
.x2
- srect
.x1
) / (float) (rect
.x2
- rect
.x1
);
2504 yrel
= (float) (srect
.y2
- srect
.y1
) / (float) (rect
.y2
- rect
.y1
);
2506 /* I have to process this row by row to swap the image,
2507 * otherwise it would be upside down, so streching in y direction
2508 * doesn't cost extra time
2510 * However, streching in x direction can be avoided if not necessary
2512 for(row
= rect
.y1
; row
< rect
.y2
; row
++) {
2513 if( (xrel
- 1.0 < -eps
) || (xrel
- 1.0 > eps
)) {
2514 /* Well, that stuff works, but it's very slow.
2515 * find a better way instead
2518 for(col
= rect
.x1
; col
< rect
.x2
; col
++) {
2519 glCopyTexSubImage2D(GL_TEXTURE_2D
,
2521 rect
.x1
+ col
, This
->currentDesc
.Height
- row
- 1, /* xoffset, yoffset */
2522 srect
.x1
+ col
* xrel
, Src
->currentDesc
.Height
- srect
.y2
+ row
* yrel
,
2526 glCopyTexSubImage2D(GL_TEXTURE_2D
,
2528 rect
.x1
, This
->currentDesc
.Height
- row
- 1, /* xoffset, yoffset */
2529 srect
.x1
, Src
->currentDesc
.Height
- srect
.y2
+ row
* yrel
,
2534 vcheckGLcall("glCopyTexSubImage2D");
2537 if(!(This
->Flags
& SFLAG_DONOTFREE
)) {
2538 HeapFree(GetProcessHeap(), 0, This
->resource
.allocatedMemory
);
2539 This
->resource
.allocatedMemory
= NULL
;
2541 This
->Flags
|= SFLAG_GLDIRTY
;
2549 if (Flags
& DDBLT_COLORFILL
) {
2550 /* This is easy to handle for the D3D Device... */
2552 IWineD3DSwapChainImpl
*implSwapChain
;
2554 TRACE("Colorfill\n");
2556 /* The color as given in the Blt function is in the format of the frame-buffer...
2557 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2559 if (This
->resource
.format
== WINED3DFMT_P8
) {
2560 if (This
->palette
) {
2561 color
= ((0xFF000000) |
2562 (This
->palette
->palents
[DDBltFx
->u5
.dwFillColor
].peRed
<< 16) |
2563 (This
->palette
->palents
[DDBltFx
->u5
.dwFillColor
].peGreen
<< 8) |
2564 (This
->palette
->palents
[DDBltFx
->u5
.dwFillColor
].peBlue
));
2569 else if (This
->resource
.format
== WINED3DFMT_R5G6B5
) {
2570 if (DDBltFx
->u5
.dwFillColor
== 0xFFFF) {
2573 color
= ((0xFF000000) |
2574 ((DDBltFx
->u5
.dwFillColor
& 0xF800) << 8) |
2575 ((DDBltFx
->u5
.dwFillColor
& 0x07E0) << 5) |
2576 ((DDBltFx
->u5
.dwFillColor
& 0x001F) << 3));
2579 else if ((This
->resource
.format
== WINED3DFMT_R8G8B8
) ||
2580 (This
->resource
.format
== WINED3DFMT_X8R8G8B8
) ) {
2581 color
= 0xFF000000 | DDBltFx
->u5
.dwFillColor
;
2583 else if (This
->resource
.format
== WINED3DFMT_A8R8G8B8
) {
2584 color
= DDBltFx
->u5
.dwFillColor
;
2587 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2588 return WINED3DERR_INVALIDCALL
;
2591 TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice
);
2592 IWineD3DDevice_GetSwapChain((IWineD3DDevice
*)myDevice
, 0, (IWineD3DSwapChain
**)&implSwapChain
);
2593 IWineD3DSwapChain_Release( (IWineD3DSwapChain
*) implSwapChain
);
2594 if(implSwapChain
->backBuffer
&& This
== (IWineD3DSurfaceImpl
*) implSwapChain
->backBuffer
[0]) {
2595 glDrawBuffer(GL_BACK
);
2596 checkGLcall("glDrawBuffer(GL_BACK)");
2598 else if (This
== (IWineD3DSurfaceImpl
*) implSwapChain
->frontBuffer
) {
2599 glDrawBuffer(GL_FRONT
);
2600 checkGLcall("glDrawBuffer(GL_FRONT)");
2603 ERR("Wrong surface type for BLT override(not on swapchain) !\n");
2604 return WINED3DERR_INVALIDCALL
;
2607 TRACE("(%p) executing Render Target override, color = %lx\n", This
, color
);
2609 IWineD3DDevice_Clear( (IWineD3DDevice
*) myDevice
,
2610 1 /* Number of rectangles */,
2617 /* Restore the original draw buffer */
2618 if(implSwapChain
->backBuffer
&& implSwapChain
->backBuffer
[0]) {
2619 glDrawBuffer(GL_BACK
);
2620 vcheckGLcall("glDrawBuffer");
2626 /* Default: Fall back to the generic blt */
2627 return WINED3DERR_INVALIDCALL
;
2630 static HRESULT WINAPI
IWineD3DSurfaceImpl_Blt(IWineD3DSurface
*iface
, RECT
*DestRect
, IWineD3DSurface
*SrcSurface
, RECT
*SrcRect
, DWORD Flags
, DDBLTFX
*DDBltFx
) {
2631 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2632 IWineD3DSurfaceImpl
*Src
= (IWineD3DSurfaceImpl
*) SrcSurface
;
2633 TRACE("(%p)->(%p,%p,%p,%lx,%p)\n", This
, DestRect
, SrcSurface
, SrcRect
, Flags
, DDBltFx
);
2634 TRACE("(%p): Usage is %08lx\n", This
, This
->resource
.usage
);
2636 /* Special cases for RenderTargets */
2637 if( (This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ||
2638 ( Src
&& (Src
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) )) {
2639 if(IWineD3DSurfaceImpl_BltOverride(This
, DestRect
, SrcSurface
, SrcRect
, Flags
, DDBltFx
) == WINED3D_OK
) return WINED3D_OK
;
2642 /* For the rest call the X11 surface implementation.
2643 * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2644 * other Blts are rather rare
2646 return IWineGDISurfaceImpl_Blt(iface
, DestRect
, SrcSurface
, SrcRect
, Flags
, DDBltFx
);
2649 HRESULT WINAPI
IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface
*iface
, DWORD Flags
) {
2650 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*)iface
;
2651 TRACE("(%p)->(%lx)\n", This
, Flags
);
2656 case DDGBS_ISBLTDONE
:
2660 return DDERR_INVALIDPARAMS
;
2664 HRESULT WINAPI
IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface
*iface
, DWORD Flags
) {
2665 /* XXX: DDERR_INVALIDSURFACETYPE */
2667 TRACE("(%p)->(%08lx)\n",iface
,Flags
);
2670 case DDGFS_ISFLIPDONE
:
2674 return DDERR_INVALIDPARAMS
;
2678 HRESULT WINAPI
IWineD3DSurfaceImpl_IsLost(IWineD3DSurface
*iface
) {
2679 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2680 TRACE("(%p)\n", This
);
2682 return This
->Flags
& SFLAG_LOST
? DDERR_SURFACELOST
: WINED3D_OK
;
2685 HRESULT WINAPI
IWineD3DSurfaceImpl_Restore(IWineD3DSurface
*iface
) {
2686 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2687 TRACE("(%p)\n", This
);
2689 /* So far we don't lose anything :) */
2690 This
->Flags
&= ~SFLAG_LOST
;
2694 HRESULT WINAPI
IWineD3DSurfaceImpl_BltFast(IWineD3DSurface
*iface
, DWORD dstx
, DWORD dsty
, IWineD3DSurface
*Source
, RECT
*rsrc
, DWORD trans
) {
2695 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2696 IWineD3DSurfaceImpl
*srcImpl
= (IWineD3DSurfaceImpl
*) Source
;
2697 TRACE("(%p)->(%ld, %ld, %p, %p, %08lx\n", iface
, dstx
, dsty
, Source
, rsrc
, trans
);
2699 /* Special cases for RenderTargets */
2700 if( (This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) ||
2701 ( srcImpl
&& (srcImpl
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) )) {
2703 RECT SrcRect
, DstRect
;
2706 SrcRect
.left
= rsrc
->left
;
2707 SrcRect
.top
= rsrc
->top
;
2708 SrcRect
.bottom
= rsrc
->bottom
;
2709 SrcRect
.right
= rsrc
->right
;
2713 SrcRect
.right
= srcImpl
->currentDesc
.Width
;
2714 SrcRect
.bottom
= srcImpl
->currentDesc
.Height
;
2717 DstRect
.left
= dstx
;
2719 DstRect
.right
= dstx
+ SrcRect
.right
- SrcRect
.left
;
2720 DstRect
.bottom
= dsty
+ SrcRect
.bottom
- SrcRect
.top
;
2722 if(IWineD3DSurfaceImpl_BltOverride(This
, &DstRect
, Source
, &SrcRect
, 0, NULL
) == WINED3D_OK
) return WINED3D_OK
;
2726 return IWineGDISurfaceImpl_BltFast(iface
, dstx
, dsty
, Source
, rsrc
, trans
);
2729 HRESULT WINAPI
IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface
*iface
, IWineD3DPalette
**Pal
) {
2730 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2731 TRACE("(%p)->(%p)\n", This
, Pal
);
2733 *Pal
= (IWineD3DPalette
*) This
->palette
;
2737 HRESULT WINAPI
IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface
*iface
) {
2738 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2740 IWineD3DPaletteImpl
*pal
= This
->palette
;
2742 TRACE("(%p)\n", This
);
2744 if(This
->resource
.format
== WINED3DFMT_P8
||
2745 This
->resource
.format
== WINED3DFMT_A8P8
)
2747 TRACE("Dirtifying surface\n");
2748 This
->Flags
|= SFLAG_DIRTY
;
2751 if(This
->Flags
& SFLAG_DIBSECTION
) {
2752 TRACE("(%p): Updating the hdc's palette\n", This
);
2753 for (n
=0; n
<256; n
++) {
2755 col
[n
].rgbRed
= pal
->palents
[n
].peRed
;
2756 col
[n
].rgbGreen
= pal
->palents
[n
].peGreen
;
2757 col
[n
].rgbBlue
= pal
->palents
[n
].peBlue
;
2759 IWineD3DDeviceImpl
*device
= This
->resource
.wineD3DDevice
;
2760 /* Use the default device palette */
2761 col
[n
].rgbRed
= device
->palettes
[device
->currentPalette
][n
].peRed
;
2762 col
[n
].rgbGreen
= device
->palettes
[device
->currentPalette
][n
].peGreen
;
2763 col
[n
].rgbBlue
= device
->palettes
[device
->currentPalette
][n
].peBlue
;
2765 col
[n
].rgbReserved
= 0;
2767 SetDIBColorTable(This
->hDC
, 0, 256, col
);
2773 HRESULT WINAPI
IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface
*iface
, IWineD3DPalette
*Pal
) {
2774 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2775 IWineD3DPaletteImpl
*PalImpl
= (IWineD3DPaletteImpl
*) Pal
;
2776 TRACE("(%p)->(%p)\n", This
, Pal
);
2778 if(This
->palette
!= NULL
)
2779 if(This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
)
2780 This
->palette
->Flags
&= ~DDPCAPS_PRIMARYSURFACE
;
2782 if(PalImpl
!= NULL
) {
2783 if(This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) {
2784 /* Set the device's main palette if the palette
2785 * wasn't a primary palette before
2787 if(!(PalImpl
->Flags
& DDPCAPS_PRIMARYSURFACE
)) {
2788 IWineD3DDeviceImpl
*device
= This
->resource
.wineD3DDevice
;
2791 for(i
=0; i
< 256; i
++) {
2792 device
->palettes
[device
->currentPalette
][i
] = PalImpl
->palents
[i
];
2796 (PalImpl
)->Flags
|= DDPCAPS_PRIMARYSURFACE
;
2799 This
->palette
= PalImpl
;
2801 return IWineD3DSurface_RealizePalette(iface
);
2804 HRESULT WINAPI
IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface
*iface
, DWORD Flags
, DDCOLORKEY
*CKey
) {
2805 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2806 BOOL dirtify
= FALSE
;
2807 TRACE("(%p)->(%08lx,%p)\n", This
, Flags
, CKey
);
2809 if ((Flags
& DDCKEY_COLORSPACE
) != 0) {
2810 FIXME(" colorkey value not supported (%08lx) !\n", Flags
);
2811 return DDERR_INVALIDPARAMS
;
2814 /* Dirtify the surface, but only if a key was changed */
2816 switch (Flags
& ~DDCKEY_COLORSPACE
) {
2817 case DDCKEY_DESTBLT
:
2818 if(!(This
->CKeyFlags
& DDSD_CKDESTBLT
)) {
2821 dirtify
= memcmp(&This
->DestBltCKey
, CKey
, sizeof(*CKey
) ) != 0;
2823 This
->DestBltCKey
= *CKey
;
2824 This
->CKeyFlags
|= DDSD_CKDESTBLT
;
2827 case DDCKEY_DESTOVERLAY
:
2828 if(!(This
->CKeyFlags
& DDSD_CKDESTOVERLAY
)) {
2831 dirtify
= memcmp(&This
->DestOverlayCKey
, CKey
, sizeof(*CKey
)) != 0;
2833 This
->DestOverlayCKey
= *CKey
;
2834 This
->CKeyFlags
|= DDSD_CKDESTOVERLAY
;
2837 case DDCKEY_SRCOVERLAY
:
2838 if(!(This
->CKeyFlags
& DDSD_CKSRCOVERLAY
)) {
2841 dirtify
= memcmp(&This
->SrcOverlayCKey
, CKey
, sizeof(*CKey
)) != 0;
2843 This
->SrcOverlayCKey
= *CKey
;
2844 This
->CKeyFlags
|= DDSD_CKSRCOVERLAY
;
2848 if(!(This
->CKeyFlags
& DDSD_CKSRCBLT
)) {
2851 dirtify
= memcmp(&This
->SrcBltCKey
, CKey
, sizeof(*CKey
)) != 0;
2853 This
->SrcBltCKey
= *CKey
;
2854 This
->CKeyFlags
|= DDSD_CKSRCBLT
;
2859 switch (Flags
& ~DDCKEY_COLORSPACE
) {
2860 case DDCKEY_DESTBLT
:
2861 dirtify
= This
->CKeyFlags
& DDSD_CKDESTBLT
;
2862 This
->CKeyFlags
&= ~DDSD_CKDESTBLT
;
2865 case DDCKEY_DESTOVERLAY
:
2866 dirtify
= This
->CKeyFlags
& DDSD_CKDESTOVERLAY
;
2867 This
->CKeyFlags
&= ~DDSD_CKDESTOVERLAY
;
2870 case DDCKEY_SRCOVERLAY
:
2871 dirtify
= This
->CKeyFlags
& DDSD_CKSRCOVERLAY
;
2872 This
->CKeyFlags
&= ~DDSD_CKSRCOVERLAY
;
2876 dirtify
= This
->CKeyFlags
& DDSD_CKSRCBLT
;
2877 This
->CKeyFlags
&= ~DDSD_CKSRCBLT
;
2883 TRACE("Color key changed, dirtifying surface\n");
2884 This
->Flags
|= SFLAG_DIRTY
;
2890 static HRESULT WINAPI
IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface
*iface
) {
2891 /** Check against the maximum texture sizes supported by the video card **/
2892 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2894 TRACE("%p\n", This
);
2895 if ((This
->pow2Width
> GL_LIMITS(texture_size
) || This
->pow2Height
> GL_LIMITS(texture_size
)) && !(This
->resource
.usage
& (WINED3DUSAGE_RENDERTARGET
| WINED3DUSAGE_DEPTHSTENCIL
))) {
2896 /* one of three options
2897 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)
2898 2: Set the texture to the maxium size (bad idea)
2899 3: WARN and return WINED3DERR_NOTAVAILABLE;
2900 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.
2902 WARN("(%p) Creating an oversized surface\n", This
);
2903 This
->Flags
|= SFLAG_OVERSIZE
;
2905 /* This will be initialized on the first blt */
2906 This
->glRect
.left
= 0;
2907 This
->glRect
.top
= 0;
2908 This
->glRect
.right
= 0;
2909 This
->glRect
.bottom
= 0;
2911 /* No oversize, gl rect is the full texture size */
2912 This
->Flags
&= ~SFLAG_OVERSIZE
;
2913 This
->glRect
.left
= 0;
2914 This
->glRect
.top
= 0;
2915 This
->glRect
.right
= This
->pow2Width
;
2916 This
->glRect
.bottom
= This
->pow2Height
;
2922 DWORD WINAPI
IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface
*iface
) {
2923 IWineD3DSurfaceImpl
*This
= (IWineD3DSurfaceImpl
*) iface
;
2925 TRACE("(%p)\n", This
);
2927 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
2928 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
2929 ie pitch = (width/4) * bytes per block */
2930 if (This
->resource
.format
== WINED3DFMT_DXT1
) /* DXT1 is 8 bytes per block */
2931 ret
= (This
->currentDesc
.Width
>> 2) << 3;
2932 else if (This
->resource
.format
== WINED3DFMT_DXT2
|| This
->resource
.format
== WINED3DFMT_DXT3
||
2933 This
->resource
.format
== WINED3DFMT_DXT4
|| This
->resource
.format
== WINED3DFMT_DXT5
) /* DXT2/3/4/5 is 16 bytes per block */
2934 ret
= (This
->currentDesc
.Width
>> 2) << 4;
2936 if (NP2_REPACK
== wined3d_settings
.nonpower2_mode
|| This
->resource
.usage
& WINED3DUSAGE_RENDERTARGET
) {
2937 /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
2938 ret
= This
->bytesPerPixel
* This
->currentDesc
.Width
; /* Bytes / row */
2940 ret
= This
->bytesPerPixel
* This
->pow2Width
;
2943 TRACE("(%p) Returning %ld\n", This
, ret
);
2947 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl
=
2950 IWineD3DSurfaceImpl_QueryInterface
,
2951 IWineD3DSurfaceImpl_AddRef
,
2952 IWineD3DSurfaceImpl_Release
,
2953 /* IWineD3DResource */
2954 IWineD3DSurfaceImpl_GetParent
,
2955 IWineD3DSurfaceImpl_GetDevice
,
2956 IWineD3DSurfaceImpl_SetPrivateData
,
2957 IWineD3DSurfaceImpl_GetPrivateData
,
2958 IWineD3DSurfaceImpl_FreePrivateData
,
2959 IWineD3DSurfaceImpl_SetPriority
,
2960 IWineD3DSurfaceImpl_GetPriority
,
2961 IWineD3DSurfaceImpl_PreLoad
,
2962 IWineD3DSurfaceImpl_GetType
,
2963 /* IWineD3DSurface */
2964 IWineD3DSurfaceImpl_GetContainerParent
,
2965 IWineD3DSurfaceImpl_GetContainer
,
2966 IWineD3DSurfaceImpl_GetDesc
,
2967 IWineD3DSurfaceImpl_LockRect
,
2968 IWineD3DSurfaceImpl_UnlockRect
,
2969 IWineD3DSurfaceImpl_GetDC
,
2970 IWineD3DSurfaceImpl_ReleaseDC
,
2971 IWineD3DSurfaceImpl_Flip
,
2972 IWineD3DSurfaceImpl_Blt
,
2973 IWineD3DSurfaceImpl_GetBltStatus
,
2974 IWineD3DSurfaceImpl_GetFlipStatus
,
2975 IWineD3DSurfaceImpl_IsLost
,
2976 IWineD3DSurfaceImpl_Restore
,
2977 IWineD3DSurfaceImpl_BltFast
,
2978 IWineD3DSurfaceImpl_GetPalette
,
2979 IWineD3DSurfaceImpl_SetPalette
,
2980 IWineD3DSurfaceImpl_RealizePalette
,
2981 IWineD3DSurfaceImpl_SetColorKey
,
2982 IWineD3DSurfaceImpl_GetPitch
,
2984 IWineD3DSurfaceImpl_CleanDirtyRect
,
2985 IWineD3DSurfaceImpl_AddDirtyRect
,
2986 IWineD3DSurfaceImpl_LoadTexture
,
2987 IWineD3DSurfaceImpl_SaveSnapshot
,
2988 IWineD3DSurfaceImpl_SetContainer
,
2989 IWineD3DSurfaceImpl_SetPBufferState
,
2990 IWineD3DSurfaceImpl_SetGlTextureDesc
,
2991 IWineD3DSurfaceImpl_GetGlDesc
,
2992 IWineD3DSurfaceImpl_GetData
,
2993 IWineD3DSurfaceImpl_SetFormat
,
2994 IWineD3DSurfaceImpl_PrivateSetup