2 * IWineD3DSurface Implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2002-2003 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/port.h"
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
31 /* *******************************************
32 IWineD3DSurface IUnknown parts follow
33 ******************************************* */
34 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
36 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
37 /* Warn ,but be nice about things */
38 TRACE("(%p)->(%s,%p) \n", This,debugstr_guid(riid),ppobj);
40 ERR("Probably FIXME: Calling query interface with NULL riid\n");
42 if (IsEqualGUID(riid, &IID_IUnknown)
43 || IsEqualGUID(riid, &IID_IWineD3DResource)
44 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
45 IUnknown_AddRef((IUnknown*)iface);
52 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
53 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
54 ULONG ref = InterlockedIncrement(&This->resource.ref);
55 TRACE("(%p) : AddRef increasing from %ld\n", This,ref - 1);
59 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
60 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
61 ULONG ref = InterlockedDecrement(&This->resource.ref);
62 TRACE("(%p) : Releasing from %ld\n", This, ref + 1);
64 TRACE("(%p) : cleaning up\n", This);
65 if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
67 TRACE("Deleting texture %d\n", This->glDescription.textureName);
68 glDeleteTextures(1, &This->glDescription.textureName);
71 IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
73 TRACE("(%p) Released\n", This);
74 HeapFree(GetProcessHeap(), 0, This);
80 /* ****************************************************
81 IWineD3DSurface IWineD3DResource parts follow
82 **************************************************** */
83 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
84 return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
87 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
88 return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
91 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
92 return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
95 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
96 return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
99 DWORD WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
100 return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
103 DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
104 return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
107 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
108 /* TODO: re-write the way textures and managed,
109 * use a 'opengl context manager' to manage RenderTarget surfaces
110 ** *********************************************************/
112 /* TODO: check for locks */
113 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
114 IWineD3DBaseTexture *baseTexture = NULL;
115 TRACE("(%p)Checking to see if the container is a base texture\n", This);
116 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == D3D_OK) {
117 TRACE("Passing to conatiner\n");
118 IWineD3DBaseTexture_PreLoad(baseTexture);
119 IWineD3DBaseTexture_Release(baseTexture);
121 TRACE("(%p) : About to load surface\n", This);
123 #if 0 /* TODO: context manager support */
124 IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
126 glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
127 if (This->glDescription.level == 0 && This->glDescription.textureName == 0) {
128 glGenTextures(1, &This->glDescription.textureName);
129 checkGLcall("glGenTextures");
130 TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
131 glBindTexture(This->glDescription.target, This->glDescription.textureName);
132 checkGLcall("glBindTexture");
133 IWineD3DSurface_LoadTexture(iface);
134 /* This is where we should be reducing the amount of GLMemoryUsed */
136 if (This->glDescription.level == 0) {
137 glBindTexture(This->glDescription.target, This->glDescription.textureName);
138 checkGLcall("glBindTexture");
139 IWineD3DSurface_LoadTexture(iface);
140 } else if (This->glDescription.textureName != 0) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
141 /* assume this is a coding error not a real error for now */
142 FIXME("Mipmap surface has a glTexture bound to it!\n");
145 if (This->resource.pool == D3DPOOL_DEFAULT) {
146 /* Tell opengl to try and keep this texture in video ram (well mostly) */
149 glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
151 /* TODO: disable texture support, if it wastn't enabled when we entered. */
152 #if 0 /* TODO: context manager support */
153 IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
154 /* we don't care when the state is disabled(if atall) */);
161 D3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
162 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
163 return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
166 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
167 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
168 return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
171 /* ******************************************************
172 IWineD3DSurface IWineD3DSurface parts follow
173 ****************************************************** */
175 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
176 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
178 if (ppContainer == NULL) {
179 ERR("Get container called witout a null ppContainer\n");
180 return E_NOINTERFACE;
182 TRACE("(%p) : Relaying to queryInterface %p %p\n", This, ppContainer, *ppContainer);
184 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
185 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
186 * GetContainer will return the Direct3D device used to create the surface.
188 hr = IUnknown_QueryInterface(This->container, riid, ppContainer);
192 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
193 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
195 TRACE("(%p) : copying into %p\n", This, pDesc);
196 if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format;
197 if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType;
198 if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage;
199 if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool;
200 if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */
201 if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
202 if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
203 if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width;
204 if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height;
208 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
209 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
210 TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
211 if (This->glDescription.textureName == 0 && textureName != 0) {
213 IWineD3DSurface_AddDirtyRect(iface, NULL);
215 This->glDescription.textureName = textureName;
216 This->glDescription.target = target;
219 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
220 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
221 TRACE("(%p) : returning %p\n", This, &This->glDescription);
222 *glDescription = &This->glDescription;
225 /* TODO: think about moving this down to resource? */
226 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
227 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
228 /* 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 */
229 if (This->resource.pool != D3DPOOL_SYSTEMMEM) {
230 FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
232 return (CONST void*)(This->resource.allocatedMemory);
235 HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
236 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
237 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
238 IWineD3DSwapChainImpl *swapchain = NULL;
239 static UINT messages = 0; /* holds flags to disable fixme messages */
241 /* fixme: should we really lock as such? */
242 if (This->inTexture && This->inPBuffer) {
243 FIXME("Warning: Surface is in texture memory or pbuffer\n");
248 if (FALSE == This->lockable) {
249 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
250 texture regions, and since the destination is an unlockable region we need
252 TRACE("Warning: trying to lock unlockable surf@%p\n", This);
253 /*return D3DERR_INVALIDCALL; */
256 if (This->resource.usage & D3DUSAGE_RENDERTARGET) {
257 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
259 if (swapchain != NULL || iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
260 if (swapchain != NULL && iface == swapchain->backBuffer) {
261 TRACE("(%p, backBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
262 } else if (swapchain != NULL && iface == swapchain->frontBuffer) {
263 TRACE("(%p, frontBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
264 } else if (iface == myDevice->renderTarget) {
265 TRACE("(%p, renderTarget) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
266 } else if (iface == myDevice->depthStencilBuffer) {
267 TRACE("(%p, stencilBuffer) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
270 if (NULL != swapchain) {
271 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
276 TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
279 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
280 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
281 ie pitch = (width/4) * bytes per block */
282 if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
283 pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 3;
284 else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
285 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
286 pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 4;
288 pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
291 pLockedRect->pBits = This->resource.allocatedMemory;
292 This->lockedRect.left = 0;
293 This->lockedRect.top = 0;
294 This->lockedRect.right = This->currentDesc.Width;
295 This->lockedRect.bottom = This->currentDesc.Height;
296 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);
298 TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
300 if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
301 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
303 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
305 This->lockedRect.left = pRect->left;
306 This->lockedRect.top = pRect->top;
307 This->lockedRect.right = pRect->right;
308 This->lockedRect.bottom = pRect->bottom;
312 TRACE("Locking non-power 2 texture\n");
315 if (0 == This->resource.usage || This->resource.usage & D3DUSAGE_DYNAMIC) {
316 /* classic surface TODO: non 2d surfaces?
317 Thease resources may be POOL_SYSTEMMEM, so they must not access the device */
318 TRACE("locking an ordinarary surface\n");
319 /* Check to see if memory has already been allocated fro the sufrace*/
320 if (NULL == This->resource.allocatedMemory) { /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
321 /* Non-systemmemory surfaces */
323 /*Surface has no memory currently allocate to it!*/
324 TRACE("(%p) Locking rect\n" , This);
325 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
327 /*Now I have to copy thing bits back*/
328 This->activeLock = TRUE; /* When this flag is set to true, laoding the surface again won't free THis->resource.allocatedMemory */
329 /* TODO: make activeLock a bit more intelegent, maybe implement a method to purge the texture memory. */
332 /* Make sure that the texture is loaded */
333 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
335 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);
337 if (This->resource.format == WINED3DFMT_DXT1 ||
338 This->resource.format == WINED3DFMT_DXT2 ||
339 This->resource.format == WINED3DFMT_DXT3 ||
340 This->resource.format == WINED3DFMT_DXT4 ||
341 This->resource.format == WINED3DFMT_DXT5) {
342 TRACE("Locking a compressed texture\n");
343 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* we can assume this as the texture would not have been created otherwise */
344 GL_EXTCALL(glGetCompressedTexImageARB)(This->glDescription.target,
345 This->glDescription.level,
346 This->resource.allocatedMemory);
349 FIXME("(%p) attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
352 glGetTexImage(This->glDescription.target,
353 This->glDescription.level,
354 This->glDescription.glFormat,
355 This->glDescription.glType,
356 This->resource.allocatedMemory);
357 vcheckGLcall("glGetTexImage");
360 } else { /* Nothing to do */
361 TRACE("Memory %p already allocted for texture\n", This->resource.allocatedMemory);
365 pLockedRect->pBits = This->resource.allocatedMemory;
367 if (This->resource.format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */
368 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
370 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
374 } else if (D3DUSAGE_RENDERTARGET & This->resource.usage && !(Flags&D3DLOCK_DISCARD)) { /* render surfaces */
378 BOOL notInContext = FALSE;
379 IWineD3DSwapChainImpl *targetSwapChain = NULL;
385 * for render->surface copy begin to begin of allocatedMemory
386 * unlock can be more easy
389 TRACE("locking a render target\n");
391 if (This->resource.allocatedMemory == NULL)
392 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
394 This->activeLock = TRUE; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
395 pLockedRect->pBits = This->resource.allocatedMemory;
398 vcheckGLcall("glFlush");
399 glGetIntegerv(GL_READ_BUFFER, &prev_read);
400 vcheckGLcall("glIntegerv");
401 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
402 vcheckGLcall("glIntegerv");
404 /* Here's what we have to do:
405 See if the swapchain has the same context as the renderTarget or the surface is the render target.
406 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
407 and use the front back buffer as required.
408 if not, we need to switch contexts and then switchback at the end.
410 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
411 IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
413 /* 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! */
414 if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
415 if (iface == myDevice->renderTarget || iface == swapchain->backBuffer) {
416 TRACE("locking back buffer\n");
417 glReadBuffer(GL_BACK);
418 } else if (iface == swapchain->frontBuffer) {
419 TRACE("locking front\n");
420 glReadBuffer(GL_FRONT);
421 } else if (iface == myDevice->depthStencilBuffer) {
422 FIXME("Stencil Buffer lock unsupported for now\n");
424 FIXME("(%p) Shouldn't have got here!\n", This);
425 glReadBuffer(GL_BACK);
427 } else if (swapchain != NULL) {
428 IWineD3DSwapChainImpl *implSwapChain;
429 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
430 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
431 /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
432 if (iface == swapchain->backBuffer) {
433 glReadBuffer(GL_BACK);
434 } else if (iface == swapchain->frontBuffer) {
435 glReadBuffer(GL_FRONT);
436 } else if (iface == myDevice->depthStencilBuffer) {
437 FIXME("Stencil Buffer lock unsupported for now\n");
439 FIXME("Should have got here!\n");
440 glReadBuffer(GL_BACK);
443 /* We need to switch contexts to be able to read the buffer!!! */
444 FIXME("The buffer requested isn't in the current openGL context\n");
446 /* TODO: check the contexts, to see if were shared with the current context */
448 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
450 if (swapchain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
451 if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
454 /** the depth stencil in openGL has a format of GL_FLOAT
455 * which should be good for WINED3DFMT_D16_LOCKABLE
457 * it is unclear what format the stencil buffer is in except.
458 * 'Each index is converted to fixed point...
459 * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
460 * mappings in the table GL_PIXEL_MAP_S_TO_S.
461 * glReadPixels(This->lockedRect.left,
462 * This->lockedRect.bottom - j - 1,
463 * This->lockedRect.right - This->lockedRect.left,
465 * GL_DEPTH_COMPONENT,
467 * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
468 *****************************************/
469 if (!notInContext) { /* Only read the buffer if it's in the current context */
472 /* Bizarly it takes 120 millseconds to get an 800x600 region a line at a time, but only 10 to get the whole lot every time,
473 * This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
474 * run ten times faster!
475 * ************************************/
476 BOOL ati_performance_hack = FALSE;
477 ati_performance_hack = (This->lockedRect.bottom - This->lockedRect.top > 10) || (This->lockedRect.right - This->lockedRect.left > 10)? TRUE: FALSE;
479 if ((This->lockedRect.left == 0 && This->lockedRect.top == 0 &&
480 This->lockedRect.right == This->currentDesc.Width
481 && This->lockedRect.bottom == This->currentDesc.Height)) {
483 This->currentDesc.Width,
484 This->currentDesc.Height,
485 This->glDescription.glFormat,
486 This->glDescription.glType,
487 (char *)pLockedRect->pBits);
488 } else if (This->lockedRect.left == 0 && This->lockedRect.right == This->currentDesc.Width) {
490 This->lockedRect.top,
491 This->currentDesc.Width,
492 This->currentDesc.Height,
493 This->glDescription.glFormat,
494 This->glDescription.glType,
495 (char *)pLockedRect->pBits);
498 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
499 glReadPixels(This->lockedRect.left,
500 This->lockedRect.bottom - j - 1,
501 This->lockedRect.right - This->lockedRect.left,
503 This->glDescription.glFormat,
504 This->glDescription.glType,
505 (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
509 vcheckGLcall("glReadPixels");
510 TRACE("Resetting buffer\n");
511 glReadBuffer(prev_read);
512 vcheckGLcall("glReadBuffer");
516 } else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
519 FIXME("TODO stencil depth surface locking surf%p usage(%lu)\n", This, This->resource.usage);
522 glReadPixels(This->lockedRect.left,
523 This->lockedRect.bottom - j - 1,
524 This->lockedRect.right - This->lockedRect.left,
526 GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
533 FIXME("unsupported locking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
536 if (Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY)) {
539 IWineD3DBaseTexture *pBaseTexture;
542 * as seen in msdn docs
544 IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
546 /** Dirtify Container if needed */
547 if (D3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
548 TRACE("Making container dirty\n");
549 IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
550 IWineD3DBaseTexture_Release(pBaseTexture);
552 TRACE("Surface is standalone, no need to dirty the container\n");
556 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Dirty);
562 HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
564 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
565 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
566 const char *buffername = "";
567 IWineD3DSwapChainImpl *swapchain = NULL;
569 if (FALSE == This->locked) {
570 WARN("trying to Unlock an unlocked surf@%p\n", This);
571 return D3DERR_INVALIDCALL;
574 if (D3DUSAGE_RENDERTARGET & This->resource.usage) {
575 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
577 if ((swapchain != NULL) && iface == swapchain->backBuffer) {
578 buffername = "backBuffer";
579 } else if ((swapchain != NULL) && iface == swapchain->frontBuffer) {
580 buffername = "frontBuffer";
581 } else if (iface == myDevice->depthStencilBuffer) {
582 buffername = "depthStencilBuffer";
583 } else if (iface == myDevice->renderTarget) {
584 buffername = "renderTarget";
588 if (swapchain != NULL) {
589 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
592 TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Dirty);
594 if (FALSE == This->Dirty) {
595 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
599 if (0 == This->resource.usage) { /* classic surface */
602 * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
604 } else if (D3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
606 /****************************
607 * TODO: Render targets are 'special' and
608 * ?some? locking needs to be passed onto the context manager
609 * so that it becomes possible to use auxilary buffers, pbuffers
610 * render-to-texture, shared, cached contexts etc...
611 * ****************************/
612 IWineD3DSwapChainImpl *implSwapChain;
613 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
615 if (iface == implSwapChain->backBuffer || iface == implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
618 GLint prev_rasterpos[4];
623 vcheckGLcall("glFlush");
624 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
625 vcheckGLcall("glIntegerv");
626 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
627 vcheckGLcall("glIntegerv");
628 glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
629 vcheckGLcall("glIntegerv");
630 glPixelZoom(1.0, -1.0);
631 vcheckGLcall("glPixelZoom");
633 /* glDrawPixels transforms the raster position as though it was a vertex -
634 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
635 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
636 if (!myDevice->last_was_rhw) {
638 double X, Y, height, width, minZ, maxZ;
639 myDevice->last_was_rhw = TRUE;
641 /* Transformed already into viewport coordinates, so we do not need transform
642 matrices. Reset all matrices to identity and leave the default matrix in world
644 glMatrixMode(GL_MODELVIEW);
645 checkGLcall("glMatrixMode");
647 checkGLcall("glLoadIdentity");
649 glMatrixMode(GL_PROJECTION);
650 checkGLcall("glMatrixMode");
652 checkGLcall("glLoadIdentity");
654 /* Set up the viewport to be full viewport */
655 X = myDevice->stateBlock->viewport.X;
656 Y = myDevice->stateBlock->viewport.Y;
657 height = myDevice->stateBlock->viewport.Height;
658 width = myDevice->stateBlock->viewport.Width;
659 minZ = myDevice->stateBlock->viewport.MinZ;
660 maxZ = myDevice->stateBlock->viewport.MaxZ;
661 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
662 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
663 checkGLcall("glOrtho");
665 /* Window Coord 0 is the middle of the first pixel, so translate by half
666 a pixel (See comment above glTranslate below) */
667 glTranslatef(0.5, 0.5, 0);
668 checkGLcall("glTranslatef(0.5, 0.5, 0)");
671 if (iface == implSwapChain->backBuffer || iface == myDevice->renderTarget) {
672 glDrawBuffer(GL_BACK);
673 } else if (iface == implSwapChain->frontBuffer) {
674 glDrawBuffer(GL_FRONT);
677 vcheckGLcall("glDrawBuffer");
679 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
680 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
681 glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
683 /* And back buffers are not blended */
686 glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
687 vcheckGLcall("glRasterPos2f");
688 switch (This->resource.format) {
689 case WINED3DFMT_R5G6B5:
691 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
692 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, This->resource.allocatedMemory);
693 vcheckGLcall("glDrawPixels");
696 case WINED3DFMT_R8G8B8:
698 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
699 GL_RGB, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
700 vcheckGLcall("glDrawPixels");
703 case WINED3DFMT_X8R8G8B8: /* make sure the X byte is set to alpha on, since it
704 could be any random value this fixes the intro move in Pirates! */
708 data = (unsigned int *)This->resource.allocatedMemory;
709 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
716 case WINED3DFMT_A8R8G8B8:
718 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
719 vcheckGLcall("glPixelStorei");
720 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
721 GL_BGRA, GL_UNSIGNED_BYTE, This->resource.allocatedMemory);
722 vcheckGLcall("glDrawPixels");
723 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
724 vcheckGLcall("glPixelStorei");
727 case WINED3DFMT_A2R10G10B10:
729 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
730 vcheckGLcall("glPixelStorei");
731 glDrawPixels(This->lockedRect.right - This->lockedRect.left, (This->lockedRect.bottom - This->lockedRect.top)-1,
732 GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, This->resource.allocatedMemory);
733 vcheckGLcall("glDrawPixels");
734 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
735 vcheckGLcall("glPixelStorei");
739 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
742 glPixelZoom(1.0,1.0);
743 vcheckGLcall("glPixelZoom");
744 glDrawBuffer(prev_draw);
745 vcheckGLcall("glDrawBuffer");
746 glRasterPos3iv(&prev_rasterpos[0]);
747 vcheckGLcall("glRasterPos3iv");
749 /* Reset to previous pack row length / blending state */
750 glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
751 if (myDevice->stateBlock->renderState[D3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
755 /** restore clean dirty state */
756 IWineD3DSurface_CleanDirtyRect(iface);
759 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%lu)\n", This, This->resource.usage);
761 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
763 } else if (D3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
765 if (iface == myDevice->depthStencilBuffer) {
766 FIXME("TODO stencil depth surface unlocking surf@%p usage(%lu)\n", This, This->resource.usage);
768 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%lu)\n", This, This->resource.usage);
772 FIXME("unsupported unlocking to surface surf@%p usage(%lu)\n", This, This->resource.usage);
776 This->locked = FALSE;
777 memset(&This->lockedRect, 0, sizeof(RECT));
781 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
782 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
783 FIXME("No support for GetDC yet for surface %p\n", This);
784 return D3DERR_INVALIDCALL;
787 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
788 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
789 FIXME("No support for ReleaseDC yet for surface %p\n", This);
790 return D3DERR_INVALIDCALL;
793 /* ******************************************************
794 IWineD3DSurface Internal (No mapping to directx api) parts follow
795 ****************************************************** */
796 HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
797 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
799 if (This->inTexture) {
800 TRACE("Surface already in texture\n");
803 if (This->Dirty == FALSE) {
804 TRACE("surface isn't dirty\n");
810 /* Resources are placed in system RAM and do not need to be recreated when a device is lost. These resources are not bound by device size or format restrictions. Because of this, these resources cannot be accessed by the Direct3D device nor set as textures or render targets. However, these resources can always be created, locked, and copied. */
811 if (This->resource.pool == D3DPOOL_SCRATCH || This->resource.pool == D3DPOOL_SYSTEMMEM) /*never store scratch or system mem textures in the video ram*/
813 FIXME("(%p) Opperation not supported for scratch or SYSTEMMEM textures\n",This);
814 return D3DERR_INVALIDCALL;
817 if (This->inPBuffer) {
820 if (This->glDescription.level != 0)
821 FIXME("Surface in texture is only supported for level 0\n");
822 else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
823 This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
824 This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
825 This->resource.format == WINED3DFMT_DXT5)
826 FIXME("Format %d not supported\n", This->resource.format);
829 glGetIntegerv(GL_READ_BUFFER, &prevRead);
830 vcheckGLcall("glGetIntegerv");
831 glReadBuffer(GL_BACK);
832 vcheckGLcall("glReadBuffer");
834 glCopyTexImage2D(This->glDescription.target,
835 This->glDescription.level,
836 This->glDescription.glFormatInternal,
839 This->currentDesc.Width,
840 This->currentDesc.Height,
843 checkGLcall("glCopyTexImage2D");
844 glReadBuffer(prevRead);
845 vcheckGLcall("glReadBuffer");
846 TRACE("Updating target %d\n", This->glDescription.target);
847 This->inTexture = TRUE;
853 if ((This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) &&
854 !GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
856 * wanted a paletted texture and not really support it in HW
857 * so software emulation code begin
860 PALETTEENTRY* pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
861 VOID* surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->currentDesc.Width * This->currentDesc.Height * sizeof(DWORD));
862 BYTE* dst = (BYTE*) surface;
863 BYTE* src = (BYTE*) This->resource.allocatedMemory;
865 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
867 *dst++ = pal[color].peRed;
868 *dst++ = pal[color].peGreen;
869 *dst++ = pal[color].peBlue;
870 if (This->resource.format == WINED3DFMT_A8P8)
871 *dst++ = pal[color].peFlags;
878 TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
879 This->glDescription.target,
880 This->glDescription.level,
882 This->currentDesc.Width,
883 This->currentDesc.Height,
888 glTexImage2D(This->glDescription.target,
889 This->glDescription.level,
891 This->currentDesc.Width,
892 This->currentDesc.Height,
897 checkGLcall("glTexImage2D");
898 HeapFree(GetProcessHeap(), 0, surface);
905 /* TODO: Compressed non-power 2 support */
907 if (This->resource.format == WINED3DFMT_DXT1 ||
908 This->resource.format == WINED3DFMT_DXT2 ||
909 This->resource.format == WINED3DFMT_DXT3 ||
910 This->resource.format == WINED3DFMT_DXT4 ||
911 This->resource.format == WINED3DFMT_DXT5) {
912 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
913 TRACE("Calling glCompressedTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, sz=%d, Mem=%p\n",
914 This->glDescription.target,
915 This->glDescription.level,
916 This->glDescription.glFormatInternal,
917 This->currentDesc.Width,
918 This->currentDesc.Height,
921 This->resource.allocatedMemory);
925 GL_EXTCALL(glCompressedTexImage2DARB)(This->glDescription.target,
926 This->glDescription.level,
927 This->glDescription.glFormatInternal,
928 This->currentDesc.Width,
929 This->currentDesc.Height,
932 This->resource.allocatedMemory);
933 checkGLcall("glCommpressedTexTexImage2D");
937 if(This->activeLock == FALSE){
938 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
939 This->resource.allocatedMemory = NULL;
943 FIXME("Using DXT1/3/5 without advertized support\n");
947 /* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
948 if (This->nonpow2 == TRUE) {
950 TRACE("non power of two support\n");
952 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,
953 This->glDescription.target,
954 This->glDescription.level,
955 debug_d3dformat(This->resource.format),
956 This->glDescription.glFormatInternal,
960 This->glDescription.glFormat,
961 This->glDescription.glType,
964 glTexImage2D(This->glDescription.target,
965 This->glDescription.level,
966 This->glDescription.glFormatInternal,
970 This->glDescription.glFormat,
971 This->glDescription.glType,
974 checkGLcall("glTexImage2D");
975 if (This->resource.allocatedMemory != NULL) {
976 TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory);
977 /* And map the non-power two data into the top left corner */
979 This->glDescription.target,
980 This->glDescription.level,
983 This->currentDesc.Width,
984 This->currentDesc.Height,
985 This->glDescription.glFormat,
986 This->glDescription.glType,
987 This->resource.allocatedMemory
989 checkGLcall("glTexSubImage2D");
995 TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n",
996 This->glDescription.target,
997 This->glDescription.level,
998 debug_d3dformat(This->resource.format),
999 This->glDescription.glFormatInternal,
1000 This->currentDesc.Width,
1001 This->currentDesc.Height,
1003 This->glDescription.glFormat,
1004 This->glDescription.glType,
1005 This->resource.allocatedMemory);
1008 glTexImage2D(This->glDescription.target,
1009 This->glDescription.level,
1010 This->glDescription.glFormatInternal,
1011 This->currentDesc.Width,
1012 This->currentDesc.Height,
1014 This->glDescription.glFormat,
1015 This->glDescription.glType,
1016 This->resource.allocatedMemory);
1017 checkGLcall("glTexImage2D");
1023 static unsigned int gen = 0;
1026 if ((gen % 10) == 0) {
1027 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1028 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1031 * debugging crash code
1039 if(This->activeLock == FALSE){
1040 HeapFree(GetProcessHeap(),0,This->resource.allocatedMemory);
1041 This->resource.allocatedMemory = NULL;
1051 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1054 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1056 f = fopen(filename, "w+");
1058 ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1059 return D3DERR_INVALIDCALL;
1062 TRACE("opened %s with format %s\n", filename, debug_d3dformat(This->resource.format));
1064 fprintf(f, "P6\n%u %u\n255\n", This->currentDesc.Width, This->currentDesc.Height);
1065 switch (This->resource.format) {
1066 case WINED3DFMT_X8R8G8B8:
1067 case WINED3DFMT_A8R8G8B8:
1070 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1071 color = ((DWORD*) This->resource.allocatedMemory)[i];
1072 fputc((color >> 16) & 0xFF, f);
1073 fputc((color >> 8) & 0xFF, f);
1074 fputc((color >> 0) & 0xFF, f);
1078 case WINED3DFMT_R8G8B8:
1081 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1082 color = ((BYTE*) This->resource.allocatedMemory) + (3 * i);
1083 fputc((color[0]) & 0xFF, f);
1084 fputc((color[1]) & 0xFF, f);
1085 fputc((color[2]) & 0xFF, f);
1089 case WINED3DFMT_A1R5G5B5:
1092 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1093 color = ((WORD*) This->resource.allocatedMemory)[i];
1094 fputc(((color >> 10) & 0x1F) * 255 / 31, f);
1095 fputc(((color >> 5) & 0x1F) * 255 / 31, f);
1096 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
1100 case WINED3DFMT_A4R4G4B4:
1103 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1104 color = ((WORD*) This->resource.allocatedMemory)[i];
1105 fputc(((color >> 8) & 0x0F) * 255 / 15, f);
1106 fputc(((color >> 4) & 0x0F) * 255 / 15, f);
1107 fputc(((color >> 0) & 0x0F) * 255 / 15, f);
1112 case WINED3DFMT_R5G6B5:
1115 for (i = 0; i < This->currentDesc.Width * This->currentDesc.Height; i++) {
1116 color = ((WORD*) This->resource.allocatedMemory)[i];
1117 fputc(((color >> 11) & 0x1F) * 255 / 31, f);
1118 fputc(((color >> 5) & 0x3F) * 255 / 63, f);
1119 fputc(((color >> 0) & 0x1F) * 255 / 31, f);
1124 FIXME("Unimplemented dump mode format(%u,%s)\n", This->resource.format, debug_d3dformat(This->resource.format));
1130 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1131 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1132 This->Dirty = FALSE;
1133 This->dirtyRect.left = This->currentDesc.Width;
1134 This->dirtyRect.top = This->currentDesc.Height;
1135 This->dirtyRect.right = 0;
1136 This->dirtyRect.bottom = 0;
1137 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1138 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1143 * Slightly inefficient way to handle multiple dirty rects but it works :)
1145 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1146 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1147 IWineD3DBaseTexture *baseTexture = NULL;
1149 if (NULL != pDirtyRect) {
1150 This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
1151 This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
1152 This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
1153 This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1155 This->dirtyRect.left = 0;
1156 This->dirtyRect.top = 0;
1157 This->dirtyRect.right = This->currentDesc.Width;
1158 This->dirtyRect.bottom = This->currentDesc.Height;
1160 TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left,
1161 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1162 /* if the container is a basetexture then mark it dirty. */
1163 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == D3D_OK) {
1164 TRACE("Passing to conatiner\n");
1165 IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1166 IWineD3DBaseTexture_Release(baseTexture);
1171 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IUnknown *container) {
1172 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1173 TRACE("Setting container to %p from %p\n", container, This->container);
1174 This->container = container;
1178 /* TODO: replace this function with context management routines */
1179 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL inTexture) {
1180 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1182 This->inPBuffer = inPBuffer;
1183 This->inTexture = inTexture;
1187 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
1190 IWineD3DSurfaceImpl_QueryInterface,
1191 IWineD3DSurfaceImpl_AddRef,
1192 IWineD3DSurfaceImpl_Release,
1193 /* IWineD3DResource */
1194 IWineD3DSurfaceImpl_GetParent,
1195 IWineD3DSurfaceImpl_GetDevice,
1196 IWineD3DSurfaceImpl_SetPrivateData,
1197 IWineD3DSurfaceImpl_GetPrivateData,
1198 IWineD3DSurfaceImpl_FreePrivateData,
1199 IWineD3DSurfaceImpl_SetPriority,
1200 IWineD3DSurfaceImpl_GetPriority,
1201 IWineD3DSurfaceImpl_PreLoad,
1202 IWineD3DSurfaceImpl_GetType,
1203 /* IWineD3DSurface */
1204 IWineD3DSurfaceImpl_GetContainer,
1205 IWineD3DSurfaceImpl_GetDesc,
1206 IWineD3DSurfaceImpl_LockRect,
1207 IWineD3DSurfaceImpl_UnlockRect,
1208 IWineD3DSurfaceImpl_GetDC,
1209 IWineD3DSurfaceImpl_ReleaseDC,
1211 IWineD3DSurfaceImpl_CleanDirtyRect,
1212 IWineD3DSurfaceImpl_AddDirtyRect,
1213 IWineD3DSurfaceImpl_LoadTexture,
1214 IWineD3DSurfaceImpl_SaveSnapshot,
1215 IWineD3DSurfaceImpl_SetContainer,
1216 IWineD3DSurfaceImpl_SetPBufferState,
1217 IWineD3DSurfaceImpl_SetGlTextureDesc,
1218 IWineD3DSurfaceImpl_GetGlDesc,
1219 IWineD3DSurfaceImpl_GetData