2 * IWineD3DSurface Implementation
4 * Copyright 1998 Lionel Ulmer
5 * Copyright 2000-2001 TransGaming Technologies Inc.
6 * Copyright 2002-2005 Jason Edmeades
7 * Copyright 2002-2003 Raphael Junqueira
8 * Copyright 2004 Christian Costa
9 * Copyright 2005 Oliver Stieber
10 * Copyright 2006 Stefan Dösinger for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/port.h"
29 #include "wined3d_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
50 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf);
52 static void surface_download_data(IWineD3DSurfaceImpl *This) {
53 if (This->resource.format == WINED3DFMT_DXT1 ||
54 This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
55 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
56 if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* We can assume this as the texture would not have been created otherwise */
57 FIXME("(%p) : Attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
59 TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
60 This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
64 GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory));
65 checkGLcall("glGetCompressedTexImageARB()");
70 TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
71 This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
75 glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat,
76 This->glDescription.glType, This->resource.allocatedMemory);
77 checkGLcall("glGetTexImage()");
81 if (wined3d_settings.nonpower2_mode == NP2_REPACK) {
83 * Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
84 * the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
85 * repack the texture so that the bpp * width pitch can be used instead of bpp * pow2width.
89 * instead of boxing the texture :
90 * |<-texture width ->| -->pow2width| /\
91 * |111111111111111111| | |
92 * |222 Texture 222222| boxed empty | texture height
93 * |3333 Data 33333333| | |
94 * |444444444444444444| | \/
95 * ----------------------------------- |
96 * | boxed empty | boxed empty | pow2height
98 * -----------------------------------
101 * we're repacking the data to the expected texture width
103 * |<-texture width ->| -->pow2width| /\
104 * |111111111111111111222222222222222| |
105 * |222333333333333333333444444444444| texture height
109 * | empty | pow2height
111 * -----------------------------------
115 * |<-texture width ->| /\
116 * |111111111111111111|
117 * |222222222222222222|texture height
118 * |333333333333333333|
119 * |444444444444444444| \/
120 * --------------------
122 * this also means that any references to allocatedMemory should work with the data as if were a
123 * standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
125 * internally the texture is still stored in a boxed format so any references to textureName will
126 * get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
129 if (This->Flags & SFLAG_NONPOW2) {
130 LPBYTE src_data, dst_data;
131 int src_pitch = This->bytesPerPixel * This->pow2Width;
132 int dst_pitch = This->bytesPerPixel * This->currentDesc.Width;
135 src_data = dst_data = This->resource.allocatedMemory;
136 FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, src_pitch, dst_pitch);
137 for (y = 1 ; y < This->currentDesc.Height; y++) {
138 /* skip the first row */
139 src_data += src_pitch;
140 dst_data += dst_pitch;
141 memcpy(dst_data, src_data, dst_pitch);
148 static void surface_upload_data(IWineD3DSurfaceImpl *This, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) {
149 if (This->resource.format == WINED3DFMT_DXT1 ||
150 This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
151 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
152 if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
153 FIXME("Using DXT1/3/5 without advertized support\n");
155 TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d, data %p\n", This, width, height, data);
157 GL_EXTCALL(glCompressedTexSubImage2DARB(This->glDescription.target, This->glDescription.level, 0, 0, width, height,
158 This->glDescription.glFormatInternal, This->resource.size, data));
159 checkGLcall("glCompressedTexSubImage2D");
163 TRACE("(%p) : Calling glTexSubImage2D w %d, h %d, data, %p\n", This, width, height, data);
165 glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, data);
166 checkGLcall("glTexSubImage2D");
171 static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) {
172 TRACE("(%p) : Creating surface (target %#x) level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n", This,
173 This->glDescription.target, This->glDescription.level, debug_d3dformat(This->resource.format), internal, width, height, format, type);
177 glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type, NULL);
178 checkGLcall("glTexImage2D");
183 /* *******************************************
184 IWineD3DSurface IUnknown parts follow
185 ******************************************* */
186 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
188 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
189 /* Warn ,but be nice about things */
190 TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
192 ERR("Probably FIXME: Calling query interface with NULL riid\n");
194 if (IsEqualGUID(riid, &IID_IUnknown)
195 || IsEqualGUID(riid, &IID_IWineD3DBase)
196 || IsEqualGUID(riid, &IID_IWineD3DResource)
197 || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
198 IUnknown_AddRef((IUnknown*)iface);
203 return E_NOINTERFACE;
206 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
207 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
208 ULONG ref = InterlockedIncrement(&This->resource.ref);
209 TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
213 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
214 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
215 ULONG ref = InterlockedDecrement(&This->resource.ref);
216 TRACE("(%p) : Releasing from %d\n", This, ref + 1);
218 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
219 TRACE("(%p) : cleaning up\n", This);
220 if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
222 TRACE("Deleting texture %d\n", This->glDescription.textureName);
223 glDeleteTextures(1, &This->glDescription.textureName);
227 if(This->Flags & SFLAG_DIBSECTION) {
229 SelectObject(This->hDC, This->dib.holdbitmap);
231 /* Release the DIB section */
232 DeleteObject(This->dib.DIBsection);
233 This->dib.bitmap_data = NULL;
234 This->resource.allocatedMemory = NULL;
236 if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL);
238 IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
239 if(iface == device->ddraw_primary)
240 device->ddraw_primary = NULL;
242 TRACE("(%p) Released\n", This);
243 HeapFree(GetProcessHeap(), 0, This);
249 /* ****************************************************
250 IWineD3DSurface IWineD3DResource parts follow
251 **************************************************** */
252 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
253 return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
256 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
257 return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
260 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
261 return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
264 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
265 return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
268 DWORD WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
269 return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
272 DWORD WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
273 return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
276 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
277 /* TODO: re-write the way textures and managed,
278 * use a 'opengl context manager' to manage RenderTarget surfaces
279 ** *********************************************************/
281 /* TODO: check for locks */
282 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
283 IWineD3DBaseTexture *baseTexture = NULL;
284 TRACE("(%p)Checking to see if the container is a base texture\n", This);
285 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
286 TRACE("Passing to conatiner\n");
287 IWineD3DBaseTexture_PreLoad(baseTexture);
288 IWineD3DBaseTexture_Release(baseTexture);
290 TRACE("(%p) : About to load surface\n", This);
292 #if 0 /* TODO: context manager support */
293 IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
295 glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
296 if (!This->glDescription.level) {
297 if (!This->glDescription.textureName) {
298 glGenTextures(1, &This->glDescription.textureName);
299 checkGLcall("glGenTextures");
300 TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
302 glBindTexture(This->glDescription.target, This->glDescription.textureName);
303 checkGLcall("glBindTexture");
304 IWineD3DSurface_LoadTexture(iface);
305 /* This is where we should be reducing the amount of GLMemoryUsed */
306 } else if (This->glDescription.textureName) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
307 /* assume this is a coding error not a real error for now */
308 FIXME("Mipmap surface has a glTexture bound to it!\n");
310 if (This->resource.pool == WINED3DPOOL_DEFAULT) {
311 /* Tell opengl to try and keep this texture in video ram (well mostly) */
314 glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
316 /* TODO: disable texture support, if it wastn't enabled when we entered. */
317 #if 0 /* TODO: context manager support */
318 IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
319 /* we don't care when the state is disabled(if atall) */);
326 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
327 TRACE("(%p) : calling resourceimpl_GetType\n", iface);
328 return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
331 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
332 TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
333 return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
336 /* ******************************************************
337 IWineD3DSurface IWineD3DSurface parts follow
338 ****************************************************** */
340 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainerParent(IWineD3DSurface* iface, IUnknown **ppContainerParent) {
341 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
343 TRACE("(%p) : ppContainerParent %p)\n", This, ppContainerParent);
345 if (!ppContainerParent) {
346 ERR("(%p) : Called without a valid ppContainerParent.\n", This);
349 if (This->container) {
350 IWineD3DBase_GetParent(This->container, ppContainerParent);
351 if (!ppContainerParent) {
352 /* WineD3D objects should always have a parent */
353 ERR("(%p) : GetParent returned NULL\n", This);
355 IUnknown_Release(*ppContainerParent); /* GetParent adds a reference; we want just the pointer */
357 *ppContainerParent = NULL;
363 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
364 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
365 IWineD3DBase *container = 0;
367 TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
370 ERR("Called without a valid ppContainer.\n");
374 * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
375 * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
376 * GetContainer will return the Direct3D device used to create the surface.
378 if (This->container) {
379 container = This->container;
381 container = (IWineD3DBase *)This->resource.wineD3DDevice;
384 TRACE("Relaying to QueryInterface\n");
385 return IUnknown_QueryInterface(container, riid, ppContainer);
388 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
389 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
391 TRACE("(%p) : copying into %p\n", This, pDesc);
392 if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format;
393 if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType;
394 if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage;
395 if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool;
396 if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */
397 if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
398 if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
399 if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width;
400 if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height;
404 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
405 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
406 TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
407 if (This->glDescription.textureName == 0 && textureName != 0) {
408 This->Flags |= SFLAG_DIRTY;
409 IWineD3DSurface_AddDirtyRect(iface, NULL);
411 This->glDescription.textureName = textureName;
412 This->glDescription.target = target;
415 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
416 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
417 TRACE("(%p) : returning %p\n", This, &This->glDescription);
418 *glDescription = &This->glDescription;
421 /* TODO: think about moving this down to resource? */
422 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
423 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
424 /* 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 */
425 if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
426 FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
428 return (CONST void*)(This->resource.allocatedMemory);
431 static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) {
437 switch(This->resource.format)
441 /* GL can't return palettized data, so read ARGB pixels into a
442 * separate block of memory and convert them into palettized format
443 * in software. Slow, but if the app means to use palettized render
444 * targets and locks it...
446 * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
447 * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
448 * for the color channels when palettizing the colors.
451 type = GL_UNSIGNED_BYTE;
453 mem = HeapAlloc(GetProcessHeap(), 0, (rect->bottom - rect->top) * pitch);
455 ERR("Out of memory\n");
463 fmt = This->glDescription.glFormat;
464 type = This->glDescription.glType;
467 if (rect->left == 0 &&
468 rect->right == This->currentDesc.Width ) {
469 BYTE *row, *top, *bottom;
472 glReadPixels(0, rect->top,
473 This->currentDesc.Width,
474 rect->bottom - rect->top,
479 /* glReadPixels returns the image upside down, and there is no way to prevent this.
480 Flip the lines in software */
481 row = HeapAlloc(GetProcessHeap(), 0, pitch);
483 ERR("Out of memory\n");
487 bottom = ((BYTE *) mem) + pitch * ( rect->bottom - rect->top - 1);
488 for(i = 0; i < (rect->bottom - rect->top) / 2; i++) {
489 memcpy(row, top, pitch);
490 memcpy(top, bottom, pitch);
491 memcpy(bottom, row, pitch);
495 HeapFree(GetProcessHeap(), 0, row);
497 if(This->lockedRect.top == 0 && This->lockedRect.bottom == This->currentDesc.Height) {
498 This->Flags &= ~SFLAG_GLDIRTY;
501 for (j = This->lockedRect.top; j < This->lockedRect.bottom - This->lockedRect.top; ++j) {
502 glReadPixels(rect->left,
503 rect->bottom - j - 1,
504 rect->right - rect->left,
508 (char *)mem + (pitch * (j-rect->top)));
512 vcheckGLcall("glReadPixels");
514 if(This->resource.format == WINED3DFMT_P8) {
516 DWORD width = pitch / 3;
519 pal = This->palette->palents;
521 pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
524 for(y = rect->top; y < rect->bottom; y++) {
525 for(x = rect->left; x < rect->right; x++) {
526 /* start lines pixels */
527 BYTE *blue = (BYTE *) ((BYTE *) mem) + y * pitch + x * (sizeof(BYTE) * 3);
528 BYTE *green = blue + 1;
529 BYTE *red = green + 1;
531 for(c = 0; c < 256; c++) {
532 if(*red == pal[c].peRed &&
533 *green == pal[c].peGreen &&
534 *blue == pal[c].peBlue)
536 *((BYTE *) dest + y * width + x) = c;
542 HeapFree(GetProcessHeap(), 0, mem);
546 static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
547 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
548 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
549 IWineD3DSwapChainImpl *swapchain = NULL;
550 static UINT messages = 0; /* holds flags to disable fixme messages */
551 BOOL backbuf = FALSE;
553 /* fixme: should we really lock as such? */
554 if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INPBUFFER)) ==
555 (SFLAG_INTEXTURE | SFLAG_INPBUFFER) ) {
556 FIXME("Warning: Surface is in texture memory or pbuffer\n");
557 This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INPBUFFER);
560 if (!(This->Flags & SFLAG_LOCKABLE)) {
561 /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
562 texture regions, and since the destination is an unlockable region we need
564 TRACE("Warning: trying to lock unlockable surf@%p\n", This);
565 /*return WINED3DERR_INVALIDCALL; */
568 if (This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
569 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
571 if (swapchain != NULL || iface == myDevice->renderTarget || iface == myDevice->depthStencilBuffer) {
572 if(swapchain != NULL) {
574 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
575 if(iface == swapchain->backBuffer[i]) {
582 TRACE("(%p, backBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
583 } else if (swapchain != NULL && iface == swapchain->frontBuffer) {
584 TRACE("(%p, frontBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
585 } else if (iface == myDevice->renderTarget) {
586 TRACE("(%p, renderTarget) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
587 } else if (iface == myDevice->depthStencilBuffer) {
588 TRACE("(%p, stencilBuffer) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
591 if (NULL != swapchain) {
592 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
597 TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
600 pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
603 pLockedRect->pBits = This->resource.allocatedMemory;
604 This->lockedRect.left = 0;
605 This->lockedRect.top = 0;
606 This->lockedRect.right = This->currentDesc.Width;
607 This->lockedRect.bottom = This->currentDesc.Height;
608 TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n", &This->lockedRect, This->lockedRect.left, This->lockedRect.top, This->lockedRect.right, This->lockedRect.bottom);
610 TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
612 if ((pRect->top < 0) ||
614 (pRect->left >= pRect->right) ||
615 (pRect->top >= pRect->bottom) ||
616 (pRect->right > This->currentDesc.Width) ||
617 (pRect->bottom > This->currentDesc.Height))
619 WARN(" Invalid values in pRect !!!\n");
620 return D3DERR_INVALIDCALL;
623 if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
624 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
626 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
628 This->lockedRect.left = pRect->left;
629 This->lockedRect.top = pRect->top;
630 This->lockedRect.right = pRect->right;
631 This->lockedRect.bottom = pRect->bottom;
634 if (This->Flags & SFLAG_NONPOW2) {
635 TRACE("Locking non-power 2 texture\n");
638 if (0 == This->resource.usage || This->resource.usage & WINED3DUSAGE_DYNAMIC) {
639 /* classic surface TODO: non 2d surfaces?
640 These resources may be POOL_SYSTEMMEM, so they must not access the device */
641 TRACE("locking an ordinarary surface\n");
642 /* Check to see if memory has already been allocated from the surface*/
643 if ((NULL == This->resource.allocatedMemory) ||
644 (This->Flags & SFLAG_GLDIRTY) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
645 /* Non-system memory surfaces */
647 This->Flags &= ~SFLAG_GLDIRTY;
649 /*Surface has no memory currently allocated to it!*/
650 TRACE("(%p) Locking rect\n" , This);
651 if(!This->resource.allocatedMemory) {
652 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->pow2Size);
654 if (0 != This->glDescription.textureName) {
655 /* Now I have to copy thing bits back */
656 This->Flags |= SFLAG_ACTIVELOCK; /* When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory */
657 /* TODO: make activeLock a bit more intelligent, maybe implement a method to purge the texture memory. */
659 /* Make sure that the texture is loaded */
660 IWineD3DSurface_PreLoad(iface); /* Make sure there is a texture to bind! */
662 surface_download_data(This);
664 } else { /* Nothing to do */
665 TRACE("Memory %p already allocted for texture\n", This->resource.allocatedMemory);
669 pLockedRect->pBits = This->resource.allocatedMemory;
671 if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
672 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
674 pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
678 } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage ){ /* render surfaces */
679 if((!(Flags&WINED3DLOCK_DISCARD) && (This->Flags & SFLAG_GLDIRTY)) || !This->resource.allocatedMemory) {
682 BOOL notInContext = FALSE;
683 IWineD3DSwapChainImpl *targetSwapChain = NULL;
689 * for render->surface copy begin to begin of allocatedMemory
690 * unlock can be more easy
693 TRACE("locking a render target\n");
695 if (This->resource.allocatedMemory == NULL)
696 This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 ,This->resource.size);
698 This->Flags |= SFLAG_ACTIVELOCK; /*When this flag is set to true, loading the surface again won't free THis->resource.allocatedMemory*/
699 pLockedRect->pBits = This->resource.allocatedMemory;
702 vcheckGLcall("glFlush");
703 glGetIntegerv(GL_READ_BUFFER, &prev_read);
704 vcheckGLcall("glIntegerv");
705 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
706 vcheckGLcall("glIntegerv");
708 /* Here's what we have to do:
709 See if the swapchain has the same context as the renderTarget or the surface is the render target.
710 Otherwise, see if were sharing a context with the implicit swapchain (because we're using a shared context model!)
711 and use the front back buffer as required.
712 if not, we need to switch contexts and then switchback at the end.
714 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
715 IWineD3DSurface_GetContainer(myDevice->renderTarget, &IID_IWineD3DSwapChain, (void **)&targetSwapChain);
717 /* 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! */
718 if ((swapchain == targetSwapChain && targetSwapChain != NULL) || iface == myDevice->renderTarget) {
719 if (swapchain && iface == swapchain->frontBuffer) {
720 TRACE("locking front\n");
721 glReadBuffer(GL_FRONT);
723 else if (iface == myDevice->renderTarget || backbuf) {
724 TRACE("locking back buffer\n");
725 glReadBuffer(GL_BACK);
726 } else if (iface == myDevice->depthStencilBuffer) {
727 FIXME("Stencil Buffer lock unsupported for now\n");
729 FIXME("(%p) Shouldn't have got here!\n", This);
730 glReadBuffer(GL_BACK);
732 } else if (swapchain != NULL) {
733 IWineD3DSwapChainImpl *implSwapChain;
734 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
735 if (swapchain->glCtx == implSwapChain->render_ctx && swapchain->drawable == implSwapChain->win) {
736 /* This will fail for the implicit swapchain, which is why there needs to be a context manager */
738 glReadBuffer(GL_BACK);
739 } else if (iface == swapchain->frontBuffer) {
740 glReadBuffer(GL_FRONT);
741 } else if (iface == myDevice->depthStencilBuffer) {
742 FIXME("Stencil Buffer lock unsupported for now\n");
744 FIXME("Should have got here!\n");
745 glReadBuffer(GL_BACK);
748 /* We need to switch contexts to be able to read the buffer!!! */
749 FIXME("The buffer requested isn't in the current openGL context\n");
751 /* TODO: check the contexts, to see if were shared with the current context */
753 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
755 if (swapchain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
756 if (targetSwapChain != NULL) IWineD3DSwapChain_Release((IWineD3DSwapChain *)targetSwapChain);
758 /** the depth stencil in openGL has a format of GL_FLOAT
759 * which should be good for WINED3DFMT_D16_LOCKABLE
761 * it is unclear what format the stencil buffer is in except.
762 * 'Each index is converted to fixed point...
763 * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
764 * mappings in the table GL_PIXEL_MAP_S_TO_S.
765 * glReadPixels(This->lockedRect.left,
766 * This->lockedRect.bottom - j - 1,
767 * This->lockedRect.right - This->lockedRect.left,
769 * GL_DEPTH_COMPONENT,
771 * (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
772 *****************************************/
773 if (!notInContext) { /* Only read the buffer if it's in the current context */
774 switch(wined3d_settings.rendertargetlock_mode) {
778 read_from_framebuffer(This, &This->lockedRect, pLockedRect->pBits, pLockedRect->Pitch);
783 read_from_framebuffer(This, &This->lockedRect, pLockedRect->pBits, pLockedRect->Pitch);
784 FIXME("Reading from render target with a texture isn't implemented yet, falling back to framebuffer reading\n");
789 static BOOL warned = FALSE;
791 ERR("Application tries to lock the render target, but render target locking is disabled\n");
798 TRACE("Resetting buffer\n");
800 glReadBuffer(prev_read);
801 vcheckGLcall("glReadBuffer");
805 } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
808 FIXME("TODO stencil depth surface locking surf%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
811 glReadPixels(This->lockedRect.left,
812 This->lockedRect.bottom - j - 1,
813 This->lockedRect.right - This->lockedRect.left,
815 GL_STENCIL_INDEX or GL_DEPTH_COMPONENT
822 FIXME("unsupported locking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
825 if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
828 IWineD3DBaseTexture *pBaseTexture;
831 * as seen in msdn docs
833 IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
835 /** Dirtify Container if needed */
836 if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
837 TRACE("Making container dirty\n");
838 IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
839 IWineD3DBaseTexture_Release(pBaseTexture);
841 TRACE("Surface is standalone, no need to dirty the container\n");
845 TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Flags & SFLAG_DIRTY ? 0 : 1);
847 This->Flags |= SFLAG_LOCKED;
851 static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) {
853 GLint prev_rasterpos[4];
855 BOOL storechanged = FALSE;
859 glDisable(GL_TEXTURE_2D);
860 vcheckGLcall("glDisable(GL_TEXTURE_2D)");
861 glDisable(GL_TEXTURE_1D);
862 vcheckGLcall("glDisable(GL_TEXTURE_1D)");
865 vcheckGLcall("glFlush");
866 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
867 vcheckGLcall("glIntegerv");
868 glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
869 vcheckGLcall("glIntegerv");
870 glPixelZoom(1.0, -1.0);
871 vcheckGLcall("glPixelZoom");
873 /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
874 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
875 glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
877 glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
878 vcheckGLcall("glRasterPos2f");
880 /* Some drivers(radeon dri, others?) don't like exceptions during
881 * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
882 * after ReleaseDC. Reading it will cause an exception, which x11drv will
883 * catch to put the dib section in InSync mode, which leads to a crash
884 * and a blocked x server on my radeon card.
886 * The following lines read the dib section so it is put in inSync mode
887 * before glDrawPixels is called and the crash is prevented. There won't
888 * be any interfering gdi accesses, because UnlockRect is called from
889 * ReleaseDC, and the app won't use the dc any more afterwards.
891 if(This->Flags & SFLAG_DIBSECTION) {
893 read = This->resource.allocatedMemory[0];
896 switch (This->resource.format) {
897 /* No special care needed */
898 case WINED3DFMT_A4R4G4B4:
899 case WINED3DFMT_R5G6B5:
900 case WINED3DFMT_A1R5G5B5:
901 case WINED3DFMT_R8G8B8:
902 type = This->glDescription.glType;
903 fmt = This->glDescription.glFormat;
904 mem = This->resource.allocatedMemory;
907 case WINED3DFMT_X4R4G4B4:
910 unsigned short *data;
911 data = (unsigned short *)This->resource.allocatedMemory;
912 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
918 type = This->glDescription.glType;
919 fmt = This->glDescription.glFormat;
920 mem = This->resource.allocatedMemory;
924 case WINED3DFMT_X1R5G5B5:
927 unsigned short *data;
928 data = (unsigned short *)This->resource.allocatedMemory;
929 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
935 type = This->glDescription.glType;
936 fmt = This->glDescription.glFormat;
937 mem = This->resource.allocatedMemory;
941 case WINED3DFMT_X8R8G8B8:
943 /* make sure the X byte is set to alpha on, since it
944 could be any random value. This fixes the intro movie in Pirates! */
947 data = (unsigned int *)This->resource.allocatedMemory;
948 size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
957 case WINED3DFMT_A8R8G8B8:
959 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
960 vcheckGLcall("glPixelStorei");
962 type = This->glDescription.glType;
963 fmt = This->glDescription.glFormat;
964 mem = This->resource.allocatedMemory;
968 case WINED3DFMT_A2R10G10B10:
970 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
971 vcheckGLcall("glPixelStorei");
973 type = This->glDescription.glType;
974 fmt = This->glDescription.glFormat;
975 mem = This->resource.allocatedMemory;
981 UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This); /* target is argb, 4 byte */
982 int height = This->glRect.bottom - This->glRect.top;
983 type = GL_UNSIGNED_BYTE;
986 mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * sizeof(DWORD));
988 ERR("Out of memory\n");
991 d3dfmt_convert_surface(This->resource.allocatedMemory,
1003 FIXME("Unsupported Format %u in locking func\n", This->resource.format);
1006 type = This->glDescription.glType;
1007 fmt = This->glDescription.glFormat;
1008 mem = This->resource.allocatedMemory;
1011 glDrawPixels(This->lockedRect.right - This->lockedRect.left,
1012 (This->lockedRect.bottom - This->lockedRect.top)-1,
1015 checkGLcall("glDrawPixels");
1016 glPixelZoom(1.0,1.0);
1017 vcheckGLcall("glPixelZoom");
1019 glRasterPos3iv(&prev_rasterpos[0]);
1020 vcheckGLcall("glRasterPos3iv");
1022 /* Reset to previous pack row length */
1023 glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
1024 vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
1026 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1027 vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES");
1030 if(mem != This->resource.allocatedMemory) HeapFree(GetProcessHeap(), 0, mem);
1034 static void flush_to_framebuffer_texture(IWineD3DSurface *iface) {
1035 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1036 float glTexCoord[4];
1038 glTexCoord[0] = 0.0; /* left */
1039 glTexCoord[1] = (float) This->currentDesc.Width / (float) This->pow2Width; /* right */
1040 glTexCoord[2] = 0.0; /* top */
1041 glTexCoord[3] = (float) This->currentDesc.Height / (float) This->pow2Height; /* bottom */
1043 IWineD3DSurface_PreLoad(iface);
1047 /* Disable some fancy graphics effects */
1048 glDisable(GL_LIGHTING);
1049 checkGLcall("glDisable GL_LIGHTING");
1050 glDisable(GL_DEPTH_TEST);
1051 checkGLcall("glDisable GL_DEPTH_TEST");
1053 checkGLcall("glDisable GL_FOG");
1054 glDisable(GL_CULL_FACE);
1055 checkGLcall("glDisable GL_CULL_FACE");
1056 glDisable(GL_BLEND);
1057 checkGLcall("glDisable GL_BLEND");
1058 glDisable(GL_STENCIL_TEST);
1059 checkGLcall("glDisable GL_STENCIL_TEST");
1061 glEnable(GL_TEXTURE_2D);
1062 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
1063 checkGLcall("glEnable glBindTexture");
1065 /* No filtering for blts */
1066 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1067 checkGLcall("glTexParameteri");
1068 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1069 checkGLcall("glTexParameteri");
1071 /* Start drawing a quad */
1074 glColor3d(1.0f, 1.0f, 1.0f);
1075 glTexCoord2f(glTexCoord[0], glTexCoord[2]);
1076 glVertex3f(0, 0, 0.0);
1078 glTexCoord2f(glTexCoord[0], glTexCoord[3]);
1079 glVertex3f(0, This->currentDesc.Height, 0.0);
1081 glTexCoord2f(glTexCoord[1], glTexCoord[3]);
1082 glVertex3d(This->currentDesc.Width, This->currentDesc.Height, 0.0);
1084 glTexCoord2f(glTexCoord[1], glTexCoord[2]);
1085 glVertex3f(This->currentDesc.Width, 0, 0.0);
1088 checkGLcall("glEnd");
1090 /* Unbind the texture */
1091 glBindTexture(GL_TEXTURE_2D, 0);
1092 checkGLcall("glEnable glBindTexture");
1097 static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
1098 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1099 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
1100 const char *buffername = "";
1101 IWineD3DSwapChainImpl *swapchain = NULL;
1102 BOOL backbuf = FALSE;
1104 if (!(This->Flags & SFLAG_LOCKED)) {
1105 WARN("trying to Unlock an unlocked surf@%p\n", This);
1106 return WINED3DERR_INVALIDCALL;
1109 if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) {
1110 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1114 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
1115 if(iface == swapchain->backBuffer[i]) {
1123 buffername = "backBuffer";
1124 } else if ((swapchain != NULL) && iface == swapchain->frontBuffer) {
1125 buffername = "frontBuffer";
1126 } else if (iface == myDevice->depthStencilBuffer) {
1127 buffername = "depthStencilBuffer";
1128 } else if (iface == myDevice->renderTarget) {
1129 buffername = "renderTarget";
1133 if (swapchain != NULL) {
1134 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
1137 TRACE("(%p %s) : dirtyfied(%d)\n", This, buffername, This->Flags & SFLAG_DIRTY ? 1 : 0);
1139 if (!(This->Flags & SFLAG_DIRTY)) {
1140 TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
1144 if (0 == This->resource.usage) { /* classic surface */
1147 * waiting to reload the surface via IDirect3DDevice8::UpdateTexture
1149 } else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
1151 /****************************
1152 * TODO: Render targets are 'special' and
1153 * ?some? locking needs to be passed onto the context manager
1154 * so that it becomes possible to use auxiliary buffers, pbuffers
1155 * render-to-texture, shared, cached contexts etc...
1156 * ****************************/
1157 IWineD3DSwapChainImpl *implSwapChain;
1158 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
1160 if (backbuf || iface == implSwapChain->frontBuffer || iface == myDevice->renderTarget) {
1165 /* glDrawPixels transforms the raster position as though it was a vertex -
1166 we want to draw at screen position 0,0 - Set up ortho (rhw) mode as
1167 per drawprim (and leave set - it will sort itself out due to last_was_rhw */
1168 d3ddevice_set_ortho(This->resource.wineD3DDevice);
1170 if (iface == implSwapChain->frontBuffer) {
1171 glDrawBuffer(GL_FRONT);
1172 checkGLcall("glDrawBuffer GL_FRONT");
1173 } else if (backbuf || iface == myDevice->renderTarget) {
1174 glDrawBuffer(GL_BACK);
1175 checkGLcall("glDrawBuffer GL_BACK");
1178 /* Disable higher textures before calling glDrawPixels */
1179 for(tex = 1; tex < GL_LIMITS(samplers); tex++) {
1180 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1181 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + tex));
1182 checkGLcall("glActiveTextureARB");
1184 glDisable(GL_TEXTURE_2D);
1185 checkGLcall("glDisable GL_TEXTURE_2D");
1186 glDisable(GL_TEXTURE_1D);
1187 checkGLcall("glDisable GL_TEXTURE_1D");
1189 /* Activate texture 0, but don't disable it necessarily */
1190 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1191 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
1192 checkGLcall("glActiveTextureARB");
1195 /* And back buffers are not blended. Disable the depth test,
1196 that helps performance */
1197 glDisable(GL_BLEND);
1198 glDisable(GL_DEPTH_TEST);
1201 switch(wined3d_settings.rendertargetlock_mode) {
1205 flush_to_framebuffer_drawpixels(This);
1210 flush_to_framebuffer_texture(iface);
1215 static BOOL warned = FALSE;
1217 ERR("The application tries to write to the render target, but render target locking is disabled\n");
1224 if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
1225 glDrawBuffer(GL_BACK);
1226 vcheckGLcall("glDrawBuffer");
1228 if(myDevice->stateBlock->renderState[WINED3DRS_ZENABLE] == WINED3DZB_TRUE ||
1229 myDevice->stateBlock->renderState[WINED3DRS_ZENABLE] == WINED3DZB_USEW) glEnable(GL_DEPTH_TEST);
1230 if (myDevice->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND);
1231 if (myDevice->stateBlock->renderState[WINED3DRS_FOGENABLE]) glEnable(GL_FOG);
1235 /** restore clean dirty state */
1236 IWineD3DSurface_CleanDirtyRect(iface);
1239 FIXME("unsupported unlocking to Rendering surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1241 IWineD3DSwapChain_Release((IWineD3DSwapChain *)implSwapChain);
1243 } else if (WINED3DUSAGE_DEPTHSTENCIL & This->resource.usage) { /* stencil surfaces */
1245 if (iface == myDevice->depthStencilBuffer) {
1246 FIXME("TODO stencil depth surface unlocking surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1248 FIXME("unsupported unlocking to StencilDepth surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1252 FIXME("unsupported unlocking to surface surf@%p usage(%s)\n", This, debug_d3dusage(This->resource.usage));
1256 This->Flags &= ~SFLAG_LOCKED;
1257 memset(&This->lockedRect, 0, sizeof(RECT));
1261 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
1262 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1263 WINED3DLOCKED_RECT lock;
1270 const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1272 TRACE("(%p)->(%p)\n",This,pHDC);
1274 if(This->Flags & SFLAG_USERPTR) {
1275 ERR("Not supported on surfaces with an application-provided surfaces\n");
1279 /* Give more detailed info for ddraw */
1280 if (This->Flags & SFLAG_DCINUSE)
1281 return DDERR_DCALREADYCREATED;
1283 /* Can't GetDC if the surface is locked */
1284 if (This->Flags & SFLAG_LOCKED)
1285 return WINED3DERR_INVALIDCALL;
1287 memset(&lock, 0, sizeof(lock)); /* To be sure */
1289 /* Create a DIB section if there isn't a hdc yet */
1292 SYSTEM_INFO sysInfo;
1294 if(This->Flags & SFLAG_ACTIVELOCK) {
1295 ERR("Creating a DIB section while a lock is active. Uncertain consequences\n");
1298 switch (This->bytesPerPixel) {
1301 /* Allocate extra space to store the RGB bit masks. */
1302 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
1306 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
1310 /* Allocate extra space for a palette. */
1311 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1312 sizeof(BITMAPINFOHEADER)
1314 * (1 << (This->bytesPerPixel * 8)));
1319 return E_OUTOFMEMORY;
1321 /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
1322 * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
1323 * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
1324 * add an extra line to the dib section
1326 GetSystemInfo(&sysInfo);
1327 if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) {
1329 TRACE("Adding an extra line to the dib section\n");
1332 b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1333 if( (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
1334 b_info->bmiHeader.biWidth = This->currentDesc.Width;
1335 b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
1336 b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
1337 /* Use the full pow2 image size(assigned below) because LockRect
1338 * will need it for a full glGetTexImage call
1341 b_info->bmiHeader.biWidth = This->pow2Width;
1342 b_info->bmiHeader.biHeight = -This->pow2Height -extraline;
1343 b_info->bmiHeader.biSizeImage = This->resource.size + extraline * IWineD3DSurface_GetPitch(iface);
1345 b_info->bmiHeader.biPlanes = 1;
1346 b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
1348 b_info->bmiHeader.biXPelsPerMeter = 0;
1349 b_info->bmiHeader.biYPelsPerMeter = 0;
1350 b_info->bmiHeader.biClrUsed = 0;
1351 b_info->bmiHeader.biClrImportant = 0;
1353 /* Get the bit masks */
1354 masks = (DWORD *) &(b_info->bmiColors);
1355 switch (This->resource.format) {
1356 case WINED3DFMT_R8G8B8:
1357 usage = DIB_RGB_COLORS;
1358 b_info->bmiHeader.biCompression = BI_RGB;
1361 case WINED3DFMT_X1R5G5B5:
1362 case WINED3DFMT_A1R5G5B5:
1363 case WINED3DFMT_A4R4G4B4:
1364 case WINED3DFMT_X4R4G4B4:
1365 case WINED3DFMT_R3G3B2:
1366 case WINED3DFMT_A8R3G3B2:
1367 case WINED3DFMT_A2B10G10R10:
1368 case WINED3DFMT_A8B8G8R8:
1369 case WINED3DFMT_X8B8G8R8:
1370 case WINED3DFMT_A2R10G10B10:
1371 case WINED3DFMT_R5G6B5:
1372 case WINED3DFMT_A16B16G16R16:
1374 b_info->bmiHeader.biCompression = BI_BITFIELDS;
1375 masks[0] = formatEntry->redMask;
1376 masks[1] = formatEntry->greenMask;
1377 masks[2] = formatEntry->blueMask;
1381 /* Don't know palette */
1382 b_info->bmiHeader.biCompression = BI_RGB;
1387 ddc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1389 HeapFree(GetProcessHeap(), 0, b_info);
1390 return HRESULT_FROM_WIN32(GetLastError());
1393 TRACE("Creating a DIB section with size %dx%dx%d, size=%d\n", b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
1394 This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
1397 if (!This->dib.DIBsection) {
1398 ERR("CreateDIBSection failed!\n");
1399 HeapFree(GetProcessHeap(), 0, b_info);
1400 return HRESULT_FROM_WIN32(GetLastError());
1403 TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
1405 /* copy the existing surface to the dib section */
1406 if(This->resource.allocatedMemory) {
1407 memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, b_info->bmiHeader.biSizeImage);
1408 /* We won't need that any more */
1409 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1411 /* This is to make LockRect read the gl Texture although memory is allocated */
1412 This->Flags |= SFLAG_GLDIRTY;
1415 HeapFree(GetProcessHeap(), 0, b_info);
1417 /* Use the dib section from now on */
1418 This->resource.allocatedMemory = This->dib.bitmap_data;
1420 /* Now allocate a HDC */
1421 This->hDC = CreateCompatibleDC(0);
1422 This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
1423 TRACE("using wined3d palette %p\n", This->palette);
1424 SelectPalette(This->hDC,
1425 This->palette ? This->palette->hpal : 0,
1428 This->Flags |= SFLAG_DIBSECTION;
1431 /* Lock the surface */
1432 hr = IWineD3DSurface_LockRect(iface,
1437 ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
1438 /* keep the dib section */
1442 if(This->resource.format == WINED3DFMT_P8 ||
1443 This->resource.format == WINED3DFMT_A8P8) {
1446 PALETTEENTRY ent[256];
1448 GetPaletteEntries(This->palette->hpal, 0, 256, ent);
1449 for (n=0; n<256; n++) {
1450 col[n].rgbRed = ent[n].peRed;
1451 col[n].rgbGreen = ent[n].peGreen;
1452 col[n].rgbBlue = ent[n].peBlue;
1453 col[n].rgbReserved = 0;
1456 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1458 for (n=0; n<256; n++) {
1459 col[n].rgbRed = device->palettes[device->currentPalette][n].peRed;
1460 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1461 col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue;
1462 col[n].rgbReserved = 0;
1466 SetDIBColorTable(This->hDC, 0, 256, col);
1470 TRACE("returning %p\n",*pHDC);
1471 This->Flags |= SFLAG_DCINUSE;
1476 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1477 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1479 TRACE("(%p)->(%p)\n",This,hDC);
1481 if (!(This->Flags & SFLAG_DCINUSE))
1482 return D3DERR_INVALIDCALL;
1484 /* we locked first, so unlock now */
1485 IWineD3DSurface_UnlockRect(iface);
1487 This->Flags &= ~SFLAG_DCINUSE;
1492 /* ******************************************************
1493 IWineD3DSurface Internal (No mapping to directx api) parts follow
1494 ****************************************************** */
1496 HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp) {
1497 BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & DDSD_CKSRCBLT);
1498 const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1500 /* Default values: From the surface */
1501 *format = formatEntry->glFormat;
1502 *internal = formatEntry->glInternal;
1503 *type = formatEntry->glType;
1504 *convert = NO_CONVERSION;
1505 *target_bpp = This->bytesPerPixel;
1507 /* Ok, now look if we have to do any conversion */
1508 switch(This->resource.format) {
1513 /* Use conversion when the paletted texture extension is not available, or when it is available make sure it is used
1514 * for texturing as it won't work for calls like glDraw-/glReadPixels and further also use conversion in case of color keying.
1516 if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) || colorkey_active || (!use_texturing && GL_SUPPORT(EXT_PALETTED_TEXTURE)) ) {
1518 *internal = GL_RGBA;
1519 *type = GL_UNSIGNED_BYTE;
1521 if(colorkey_active) {
1522 *convert = CONVERT_PALETTED_CK;
1524 *convert = CONVERT_PALETTED;
1530 case WINED3DFMT_R3G3B2:
1531 /* **********************
1532 GL_UNSIGNED_BYTE_3_3_2
1533 ********************** */
1534 if (colorkey_active) {
1535 /* This texture format will never be used.. So do not care about color keying
1536 up until the point in time it will be needed :-) */
1537 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1541 case WINED3DFMT_R5G6B5:
1542 if (colorkey_active) {
1543 *convert = CONVERT_CK_565;
1545 *internal = GL_RGBA;
1546 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1550 case WINED3DFMT_R8G8B8:
1551 if (colorkey_active) {
1552 *convert = CONVERT_CK_RGB24;
1554 *internal = GL_RGBA;
1555 *type = GL_UNSIGNED_INT_8_8_8_8;
1560 case WINED3DFMT_X8R8G8B8:
1561 if (colorkey_active) {
1562 *convert = CONVERT_RGB32_888;
1564 *internal = GL_RGBA;
1565 *type = GL_UNSIGNED_INT_8_8_8_8;
1576 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) {
1577 BYTE *source, *dest;
1578 TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert, surf);
1583 memcpy(dst, src, pitch * height);
1586 case CONVERT_PALETTED:
1587 case CONVERT_PALETTED_CK:
1589 IWineD3DPaletteImpl* pal = surf->palette;
1595 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1599 /* Still no palette? Use the device's palette */
1600 /* Get the surface's palette */
1601 for (i = 0; i < 256; i++) {
1602 IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice;
1604 table[i][0] = device->palettes[device->currentPalette][i].peRed;
1605 table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1606 table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1607 if ((convert == CONVERT_PALETTED_CK) &&
1608 (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1609 (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1610 /* We should maybe here put a more 'neutral' color than the standard bright purple
1611 one often used by application to prevent the nice purple borders when bi-linear
1619 TRACE("Using surface palette %p\n", pal);
1620 /* Get the surface's palette */
1621 for (i = 0; i < 256; i++) {
1622 table[i][0] = pal->palents[i].peRed;
1623 table[i][1] = pal->palents[i].peGreen;
1624 table[i][2] = pal->palents[i].peBlue;
1625 if ((convert == CONVERT_PALETTED_CK) &&
1626 (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1627 (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1628 /* We should maybe here put a more 'neutral' color than the standard bright purple
1629 one often used by application to prevent the nice purple borders when bi-linear
1638 for (y = 0; y < height; y++)
1640 source = src + pitch * y;
1641 dest = dst + outpitch * y;
1642 /* This is an 1 bpp format, using the width here is fine */
1643 for (x = 0; x < width; x++) {
1644 BYTE color = *source++;
1645 *dest++ = table[color][0];
1646 *dest++ = table[color][1];
1647 *dest++ = table[color][2];
1648 *dest++ = table[color][3];
1654 case CONVERT_CK_565:
1656 /* Converting the 565 format in 5551 packed to emulate color-keying.
1658 Note : in all these conversion, it would be best to average the averaging
1659 pixels to get the color of the pixel that will be color-keyed to
1660 prevent 'color bleeding'. This will be done later on if ever it is
1663 Note2: Nvidia documents say that their driver does not support alpha + color keying
1664 on the same surface and disables color keying in such a case
1670 TRACE("Color keyed 565\n");
1672 for (y = 0; y < height; y++) {
1673 Source = (WORD *) (src + y * pitch);
1674 Dest = (WORD *) (dst + y * outpitch);
1675 for (x = 0; x < width; x++ ) {
1676 WORD color = *Source++;
1677 *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1678 if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1679 (color > surf->SrcBltCKey.dwColorSpaceHighValue)) {
1689 ERR("Unsupported conversation type %d\n", convert);
1694 /* This function is used in case of 8bit paletted textures to upload the palette.
1695 For now it only supports GL_EXT_paletted_texture extension but support for other
1696 extensions like ARB_fragment_program and ATI_fragment_shaders will be added as well.
1698 void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
1699 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1700 IWineD3DPaletteImpl* pal = This->palette;
1705 /* Still no palette? Use the device's palette */
1706 /* Get the surface's palette */
1707 for (i = 0; i < 256; i++) {
1708 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1710 table[i][0] = device->palettes[device->currentPalette][i].peRed;
1711 table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1712 table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1713 if ((convert == CONVERT_PALETTED_CK) &&
1714 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1715 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1716 /* We should maybe here put a more 'neutral' color than the standard bright purple
1717 one often used by application to prevent the nice purple borders when bi-linear
1725 TRACE("Using surface palette %p\n", pal);
1726 /* Get the surface's palette */
1727 for (i = 0; i < 256; i++) {
1728 table[i][0] = pal->palents[i].peRed;
1729 table[i][1] = pal->palents[i].peGreen;
1730 table[i][2] = pal->palents[i].peBlue;
1731 if ((convert == CONVERT_PALETTED_CK) &&
1732 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1733 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1734 /* We should maybe here put a more 'neutral' color than the standard bright purple
1735 one often used by application to prevent the nice purple borders when bi-linear
1743 GL_EXTCALL(glColorTableEXT(GL_TEXTURE_2D,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table));
1746 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1747 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1748 GLenum format, internal, type;
1749 CONVERT_TYPES convert;
1751 int width, pitch, outpitch;
1754 if (This->Flags & SFLAG_INTEXTURE) {
1755 TRACE("Surface already in texture\n");
1758 if (This->Flags & SFLAG_DIRTY) {
1759 TRACE("Reloading because surface is dirty\n");
1760 } else if(/* Reload: gl texture has ck, now no ckey is set OR */
1761 ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & DDSD_CKSRCBLT))) ||
1762 /* Reload: vice versa OR */
1763 ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & DDSD_CKSRCBLT)) ||
1764 /* Also reload: Color key is active AND the color key has changed */
1765 ((This->CKeyFlags & DDSD_CKSRCBLT) && (
1766 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
1767 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
1768 TRACE("Reloading because of color keying\n");
1770 TRACE("surface isn't dirty\n");
1774 This->Flags &= ~SFLAG_DIRTY;
1776 /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1777 * These resources are not bound by device size or format restrictions. Because of this,
1778 * these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1779 * However, these resources can always be created, locked, and copied.
1781 if (This->resource.pool == WINED3DPOOL_SCRATCH && !(This->Flags & SFLAG_FORCELOAD) )
1783 FIXME("(%p) Operation not supported for scratch textures\n",This);
1784 return WINED3DERR_INVALIDCALL;
1787 if (This->Flags & SFLAG_INPBUFFER) {
1788 if (This->glDescription.level != 0)
1789 FIXME("Surface in texture is only supported for level 0\n");
1790 else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1791 This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1792 This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1793 This->resource.format == WINED3DFMT_DXT5)
1794 FIXME("Format %d not supported\n", This->resource.format);
1800 glGetIntegerv(GL_READ_BUFFER, &prevRead);
1801 vcheckGLcall("glGetIntegerv");
1802 glReadBuffer(GL_BACK);
1803 vcheckGLcall("glReadBuffer");
1805 glCopyTexImage2D(This->glDescription.target,
1806 This->glDescription.level,
1807 This->glDescription.glFormatInternal,
1810 This->currentDesc.Width,
1811 This->currentDesc.Height,
1814 checkGLcall("glCopyTexImage2D");
1815 glReadBuffer(prevRead);
1816 vcheckGLcall("glReadBuffer");
1820 TRACE("Updating target %d\n", This->glDescription.target);
1821 This->Flags |= SFLAG_INTEXTURE;
1826 if(This->CKeyFlags & DDSD_CKSRCBLT) {
1827 This->Flags |= SFLAG_GLCKEY;
1828 This->glCKey = This->SrcBltCKey;
1830 else This->Flags &= ~SFLAG_GLCKEY;
1832 d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp);
1834 /* The width is in 'length' not in bytes */
1835 if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)
1836 width = This->currentDesc.Width;
1838 width = This->pow2Width;
1840 pitch = IWineD3DSurface_GetPitch(iface);
1842 if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
1843 int height = This->glRect.bottom - This->glRect.top;
1845 /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
1846 outpitch = width * bpp;
1847 outpitch = (outpitch + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1849 mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
1851 ERR("Out of memory %d, %d!\n", outpitch, height);
1852 return WINED3DERR_OUTOFVIDEOMEMORY;
1854 d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
1856 This->Flags |= SFLAG_CONVERTED;
1857 } else if (This->resource.format == WINED3DFMT_P8 && GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
1858 d3dfmt_p8_upload_palette(iface, convert);
1859 This->Flags &= ~SFLAG_CONVERTED;
1860 mem = This->resource.allocatedMemory;
1862 This->Flags &= ~SFLAG_CONVERTED;
1863 mem = This->resource.allocatedMemory;
1866 /* Make sure the correct pitch is used */
1867 glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
1869 if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
1870 TRACE("non power of two support\n");
1871 surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
1873 surface_upload_data(This, This->pow2Width, This->pow2Height, format, type, mem);
1876 surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
1878 surface_upload_data(This, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
1882 /* Restore the default pitch */
1883 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1885 if (mem != This->resource.allocatedMemory)
1886 HeapFree(GetProcessHeap(), 0, mem);
1890 static unsigned int gen = 0;
1893 if ((gen % 10) == 0) {
1894 snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1895 IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1898 * debugging crash code
1907 if (!(This->Flags & SFLAG_DONOTFREE)) {
1908 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1909 This->resource.allocatedMemory = NULL;
1917 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1920 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1921 char *allocatedMemory;
1923 IWineD3DSwapChain *swapChain = NULL;
1925 GLuint tmpTexture = 0;
1928 Textures my not be stored in ->allocatedgMemory and a GlTexture
1929 so we should lock the surface before saving a snapshot, or at least check that
1931 /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1932 by calling GetTexImage and in compressed form by calling
1933 GetCompressedTexImageARB. Queried compressed images can be saved and
1934 later reused by calling CompressedTexImage[123]DARB. Pre-compressed
1935 texture images do not need to be processed by the GL and should
1936 significantly improve texture loading performance relative to uncompressed
1939 /* Setup the width and height to be the internal texture width and height. */
1940 width = This->pow2Width;
1941 height = This->pow2Height;
1942 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1943 IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1945 if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1946 /* 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 */
1949 FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1950 glEnable(GL_TEXTURE_2D);
1952 glGenTextures(1, &tmpTexture);
1953 glBindTexture(GL_TEXTURE_2D, tmpTexture);
1955 glTexImage2D(GL_TEXTURE_2D,
1962 GL_UNSIGNED_INT_8_8_8_8_REV,
1965 glGetIntegerv(GL_READ_BUFFER, &prevRead);
1966 vcheckGLcall("glGetIntegerv");
1967 glReadBuffer(GL_BACK);
1968 vcheckGLcall("glReadBuffer");
1969 glCopyTexImage2D(GL_TEXTURE_2D,
1978 checkGLcall("glCopyTexImage2D");
1979 glReadBuffer(prevRead);
1982 } else { /* bind the real texture */
1983 IWineD3DSurface_PreLoad(iface);
1985 allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4);
1987 FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1988 glGetTexImage(GL_TEXTURE_2D,
1989 This->glDescription.level,
1991 GL_UNSIGNED_INT_8_8_8_8_REV,
1993 checkGLcall("glTexImage2D");
1995 glBindTexture(GL_TEXTURE_2D, 0);
1996 glDeleteTextures(1, &tmpTexture);
2000 f = fopen(filename, "w+");
2002 ERR("opening of %s failed with: %s\n", filename, strerror(errno));
2003 return WINED3DERR_INVALIDCALL;
2005 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
2006 TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
2021 fwrite(&width,2,1,f);
2023 fwrite(&height,2,1,f);
2028 /* 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*/
2030 textureRow = allocatedMemory + (width * (height - 1) *4);
2032 textureRow = allocatedMemory;
2033 for (y = 0 ; y < height; y++) {
2034 for (i = 0; i < width; i++) {
2035 color = *((DWORD*)textureRow);
2036 fputc((color >> 16) & 0xFF, f); /* B */
2037 fputc((color >> 8) & 0xFF, f); /* G */
2038 fputc((color >> 0) & 0xFF, f); /* R */
2039 fputc((color >> 24) & 0xFF, f); /* A */
2042 /* take two rows of the pointer to the texture memory */
2044 (textureRow-= width << 3);
2047 TRACE("Closing file\n");
2051 IWineD3DSwapChain_Release(swapChain);
2053 HeapFree(GetProcessHeap(), 0, allocatedMemory);
2057 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
2058 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2059 This->Flags &= ~SFLAG_DIRTY;
2060 This->dirtyRect.left = This->currentDesc.Width;
2061 This->dirtyRect.top = This->currentDesc.Height;
2062 This->dirtyRect.right = 0;
2063 This->dirtyRect.bottom = 0;
2064 TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
2065 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2070 * Slightly inefficient way to handle multiple dirty rects but it works :)
2072 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
2073 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2074 IWineD3DBaseTexture *baseTexture = NULL;
2075 This->Flags |= SFLAG_DIRTY;
2076 if (NULL != pDirtyRect) {
2077 This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left);
2078 This->dirtyRect.top = min(This->dirtyRect.top, pDirtyRect->top);
2079 This->dirtyRect.right = max(This->dirtyRect.right, pDirtyRect->right);
2080 This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
2082 This->dirtyRect.left = 0;
2083 This->dirtyRect.top = 0;
2084 This->dirtyRect.right = This->currentDesc.Width;
2085 This->dirtyRect.bottom = This->currentDesc.Height;
2087 TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
2088 This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2089 /* if the container is a basetexture then mark it dirty. */
2090 if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2091 TRACE("Passing to conatiner\n");
2092 IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
2093 IWineD3DBaseTexture_Release(baseTexture);
2098 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
2099 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2101 TRACE("This %p, container %p\n", This, container);
2103 /* We can't keep a reference to the container, since the container already keeps a reference to us. */
2105 TRACE("Setting container to %p from %p\n", container, This->container);
2106 This->container = container;
2111 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
2112 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2113 const PixelFormatDesc *formatEntry = getFormatDescEntry(format);
2115 if (This->resource.format != WINED3DFMT_UNKNOWN) {
2116 FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
2117 return WINED3DERR_INVALIDCALL;
2120 TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
2121 if (format == WINED3DFMT_UNKNOWN) {
2122 This->resource.size = 0;
2123 } else if (format == WINED3DFMT_DXT1) {
2124 /* DXT1 is half byte per pixel */
2125 This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4)) >> 1;
2127 } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
2128 format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
2129 This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4));
2131 This->resource.size = ((This->pow2Width * formatEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
2132 This->resource.size *= This->pow2Height;
2136 /* Setup some glformat defaults */
2137 This->glDescription.glFormat = formatEntry->glFormat;
2138 This->glDescription.glFormatInternal = formatEntry->glInternal;
2139 This->glDescription.glType = formatEntry->glType;
2141 if (format != WINED3DFMT_UNKNOWN) {
2142 This->bytesPerPixel = formatEntry->bpp;
2143 This->pow2Size = (This->pow2Width * This->bytesPerPixel) * This->pow2Height;
2145 This->bytesPerPixel = 0;
2149 This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
2151 This->resource.format = format;
2153 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);
2158 HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2159 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2161 /* Render targets depend on their hdc, and we can't create a hdc on a user pointer */
2162 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2163 ERR("Not supported on render targets\n");
2164 return WINED3DERR_INVALIDCALL;
2167 if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2168 WARN("Surface is locked or the HDC is in use\n");
2169 return WINED3DERR_INVALIDCALL;
2172 if(Mem && Mem != This->resource.allocatedMemory) {
2174 /* Do I have to copy the old surface content? */
2175 if(This->Flags & SFLAG_DIBSECTION) {
2176 /* Release the DC. No need to hold the critical section for the update
2177 * Thread because this thread runs only on front buffers, but this method
2178 * fails for render targets in the check above.
2180 SelectObject(This->hDC, This->dib.holdbitmap);
2181 DeleteDC(This->hDC);
2182 /* Release the DIB section */
2183 DeleteObject(This->dib.DIBsection);
2184 This->dib.bitmap_data = NULL;
2185 This->resource.allocatedMemory = NULL;
2187 This->Flags &= ~SFLAG_DIBSECTION;
2188 } else if(!(This->Flags & SFLAG_USERPTR)) {
2189 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2191 This->resource.allocatedMemory = Mem;
2192 This->Flags |= SFLAG_USERPTR;
2193 } else if(This->Flags & SFLAG_USERPTR) {
2194 /* Lockrect and GetDC will re-create the dib section and allocated memory */
2195 This->resource.allocatedMemory = NULL;
2196 This->Flags &= ~SFLAG_USERPTR;
2201 /* TODO: replace this function with context management routines */
2202 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL inTexture) {
2203 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2206 This->Flags |= SFLAG_INPBUFFER;
2208 This->Flags &= ~SFLAG_INPBUFFER;
2212 This->Flags |= SFLAG_INTEXTURE;
2214 This->Flags &= ~SFLAG_INTEXTURE;
2220 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2221 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2222 IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
2223 TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2225 /* Flipping is only supported on RenderTargets */
2226 if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
2229 /* DDraw sets this for the X11 surfaces, so don't confuse the user
2230 * FIXME("(%p) Target override is not supported by now\n", This);
2231 * Additionally, it isn't really possible to support triple-buffering
2232 * properly on opengl at all
2236 /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2237 return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
2240 /* Not called from the VTable */
2241 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2243 IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2244 IWineD3DSwapChainImpl *swapchain = NULL;
2245 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2248 TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2250 /* Get the swapchain. One of the surfaces has to be a primary surface */
2251 IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
2252 if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2254 IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&swapchain);
2255 if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2256 else return WINED3DERR_INVALIDCALL;
2262 rect.x1 = DestRect->left;
2263 rect.y1 = DestRect->top;
2264 rect.x2 = DestRect->right;
2265 rect.y2 = DestRect->bottom;
2269 rect.x2 = This->currentDesc.Width;
2270 rect.y2 = This->currentDesc.Height;
2273 /* Half-life does a Blt from the back buffer to the front buffer,
2274 * Full surface size, no flags... Use present instead
2278 /* First, check if we can do a Flip */
2280 /* Check rects - IWineD3DDevice_Present doesn't handle them */
2282 if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
2283 (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
2290 /* Check the Destination rect and the surface sizes */
2292 (rect.x1 == 0) && (rect.y1 == 0) &&
2293 (rect.x2 == This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
2294 (This->currentDesc.Width == Src->currentDesc.Width) &&
2295 (This->currentDesc.Height == Src->currentDesc.Height)) {
2296 /* These flags are unimportant for the flag check, remove them */
2298 if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
2299 if( swapchain->backBuffer && ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer[0]) ) {
2301 D3DSWAPEFFECT orig_swap = swapchain->presentParms.SwapEffect;
2303 /* The idea behind this is that a glReadPixels and a glDrawPixels call
2304 * take very long, while a flip is fast.
2305 * This applies to Half-Life, which does such Blts every time it finished
2306 * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2307 * menu. This is also used by all apps when they do windowed rendering
2309 * The problem is that flipping is not really the same as copying. After a
2310 * Blt the front buffer is a copy of the back buffer, and the back buffer is
2311 * untouched. Therefore it's necessary to override the swap effect
2312 * and to set it back after the flip.
2315 swapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
2317 TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2318 IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
2319 NULL, NULL, 0, NULL);
2321 swapchain->presentParms.SwapEffect = orig_swap;
2328 /* Blt from texture to rendertarget? */
2329 if( ( ( (IWineD3DSurface *) This == swapchain->frontBuffer) ||
2330 ( swapchain->backBuffer && (IWineD3DSurface *) This == swapchain->backBuffer[0]) )
2332 ( ( (IWineD3DSurface *) Src != swapchain->frontBuffer) &&
2333 ( swapchain->backBuffer && (IWineD3DSurface *) Src != swapchain->backBuffer[0]) ) ) {
2334 float glTexCoord[4];
2336 DDCOLORKEY oldBltCKey = {0,0};
2337 GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha;
2338 GLint oldStencil, oldNVRegisterCombiners = 0;
2341 RECT SourceRectangle;
2344 TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
2347 SourceRectangle.left = SrcRect->left;
2348 SourceRectangle.right = SrcRect->right;
2349 SourceRectangle.top = SrcRect->top;
2350 SourceRectangle.bottom = SrcRect->bottom;
2352 SourceRectangle.left = 0;
2353 SourceRectangle.right = Src->currentDesc.Width;
2354 SourceRectangle.top = 0;
2355 SourceRectangle.bottom = Src->currentDesc.Height;
2358 if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
2359 /* Fall back to software */
2360 WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
2361 SourceRectangle.left, SourceRectangle.top,
2362 SourceRectangle.right, SourceRectangle.bottom);
2363 return WINED3DERR_INVALIDCALL;
2366 /* Color keying: Check if we have to do a color keyed blt,
2367 * and if not check if a color key is activated.
2369 oldCKey = Src->CKeyFlags;
2370 if(!(Flags & DDBLT_KEYSRC) &&
2371 Src->CKeyFlags & DDSD_CKSRCBLT) {
2372 /* Ok, the surface has a color key, but we shall not use it -
2373 * Deactivate it for now, LoadTexture will catch this
2375 Src->CKeyFlags &= ~DDSD_CKSRCBLT;
2379 if(Flags & DDBLT_KEYDEST) {
2380 oldBltCKey = This->SrcBltCKey;
2381 /* Temporary replace the source color key with the destination one. We do this because the color conversion code which
2382 * is in the end called from LoadTexture works with the source color. At the end of this function we restore the color key.
2384 This->SrcBltCKey = This->DestBltCKey;
2385 } else if (Flags & DDBLT_KEYSRC)
2386 oldBltCKey = This->SrcBltCKey;
2388 /* Now load the surface */
2389 IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
2393 /* Save all the old stuff until we have a proper opengl state manager */
2394 oldLight = glIsEnabled(GL_LIGHTING);
2395 oldFog = glIsEnabled(GL_FOG);
2396 oldDepth = glIsEnabled(GL_DEPTH_TEST);
2397 oldBlend = glIsEnabled(GL_BLEND);
2398 oldCull = glIsEnabled(GL_CULL_FACE);
2399 oldAlpha = glIsEnabled(GL_ALPHA_TEST);
2400 oldStencil = glIsEnabled(GL_STENCIL_TEST);
2402 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2403 oldNVRegisterCombiners = glIsEnabled(GL_REGISTER_COMBINERS_NV);
2406 glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphafunc);
2407 checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC");
2408 glGetFloatv(GL_ALPHA_TEST_REF, &alpharef);
2409 checkGLcall("glGetFloatv GL_ALPHA_TEST_REF");
2411 glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
2412 if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer) {
2413 TRACE("Drawing to front buffer\n");
2414 glDrawBuffer(GL_FRONT);
2415 checkGLcall("glDrawBuffer GL_FRONT");
2418 /* Unbind the old texture */
2419 glBindTexture(GL_TEXTURE_2D, 0);
2421 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2422 /* We use texture unit 0 for blts */
2423 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
2424 checkGLcall("glActiveTextureARB");
2426 WARN("Multi-texturing is unsupported in the local OpenGL implementation\n");
2429 /* Disable some fancy graphics effects */
2430 glDisable(GL_LIGHTING);
2431 checkGLcall("glDisable GL_LIGHTING");
2432 glDisable(GL_DEPTH_TEST);
2433 checkGLcall("glDisable GL_DEPTH_TEST");
2435 checkGLcall("glDisable GL_FOG");
2436 glDisable(GL_BLEND);
2437 checkGLcall("glDisable GL_BLEND");
2438 glDisable(GL_CULL_FACE);
2439 checkGLcall("glDisable GL_CULL_FACE");
2440 glDisable(GL_STENCIL_TEST);
2441 checkGLcall("glDisable GL_STENCIL_TEST");
2442 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2443 glDisable(GL_REGISTER_COMBINERS_NV);
2444 checkGLcall("glDisable GL_REGISTER_COMBINERS_NV");
2447 /* Ok, we need 2d textures, but not 1D or 3D */
2448 glDisable(GL_TEXTURE_1D);
2449 checkGLcall("glDisable GL_TEXTURE_1D");
2450 glEnable(GL_TEXTURE_2D);
2451 checkGLcall("glEnable GL_TEXTURE_2D");
2452 glDisable(GL_TEXTURE_3D);
2453 checkGLcall("glDisable GL_TEXTURE_3D");
2455 /* Bind the texture */
2456 glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2457 checkGLcall("glBindTexture");
2459 glEnable(GL_SCISSOR_TEST);
2461 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2463 /* No filtering for blts */
2464 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2466 checkGLcall("glTexParameteri");
2467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2469 checkGLcall("glTexParameteri");
2470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2471 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2472 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2473 checkGLcall("glTexEnvi");
2475 /* This is for color keying */
2476 if(Flags & DDBLT_KEYSRC) {
2477 glEnable(GL_ALPHA_TEST);
2478 checkGLcall("glEnable GL_ALPHA_TEST");
2479 glAlphaFunc(GL_NOTEQUAL, 0.0);
2480 checkGLcall("glAlphaFunc\n");
2482 glDisable(GL_ALPHA_TEST);
2483 checkGLcall("glDisable GL_ALPHA_TEST");
2486 /* Draw a textured quad
2488 d3ddevice_set_ortho(This->resource.wineD3DDevice);
2492 glColor3d(1.0f, 1.0f, 1.0f);
2493 glTexCoord2f(glTexCoord[0], glTexCoord[2]);
2498 glTexCoord2f(glTexCoord[0], glTexCoord[3]);
2499 glVertex3f(rect.x1, rect.y2, 0.0);
2501 glTexCoord2f(glTexCoord[1], glTexCoord[3]);
2506 glTexCoord2f(glTexCoord[1], glTexCoord[2]);
2511 checkGLcall("glEnd");
2513 /* Unbind the texture */
2514 glBindTexture(GL_TEXTURE_2D, 0);
2515 checkGLcall("glEnable glBindTexture");
2517 /* Restore the old settings */
2519 glEnable(GL_LIGHTING);
2520 checkGLcall("glEnable GL_LIGHTING");
2524 checkGLcall("glEnable GL_FOG");
2527 glEnable(GL_DEPTH_TEST);
2528 checkGLcall("glEnable GL_DEPTH_TEST");
2532 checkGLcall("glEnable GL_BLEND");
2535 glEnable(GL_CULL_FACE);
2536 checkGLcall("glEnable GL_CULL_FACE");
2539 glEnable(GL_STENCIL_TEST);
2540 checkGLcall("glEnable GL_STENCIL_TEST");
2543 glDisable(GL_ALPHA_TEST);
2544 checkGLcall("glDisable GL_ALPHA_TEST");
2546 glEnable(GL_ALPHA_TEST);
2547 checkGLcall("glEnable GL_ALPHA_TEST");
2549 if (GL_SUPPORT(NV_REGISTER_COMBINERS) && oldNVRegisterCombiners) {
2550 glEnable(GL_REGISTER_COMBINERS_NV);
2551 checkGLcall("glEnable GL_REGISTER_COMBINERS_NV");
2554 glAlphaFunc(alphafunc, alpharef);
2555 checkGLcall("glAlphaFunc\n");
2557 if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer && oldDraw == GL_BACK) {
2558 glDrawBuffer(oldDraw);
2561 /* Restore the color key flags */
2562 if(oldCKey != Src->CKeyFlags) {
2563 Src->CKeyFlags = oldCKey;
2566 /* Restore the old color key */
2567 if (Flags & (DDBLT_KEYSRC | DDBLT_KEYDEST))
2568 This->SrcBltCKey = oldBltCKey;
2572 /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2573 This->Flags |= SFLAG_GLDIRTY;
2579 /* Blt from rendertarget to texture? */
2580 if( (SrcSurface == swapchain->frontBuffer) ||
2581 (swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) ) {
2582 if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
2583 ( swapchain->backBuffer && (IWineD3DSurface *) This != swapchain->backBuffer[0]) ) {
2588 TRACE("Blt from rendertarget to texture\n");
2590 /* Call preload for the surface to make sure it isn't dirty */
2591 IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2594 srect.x1 = SrcRect->left;
2595 srect.y1 = SrcRect->top;
2596 srect.x2 = SrcRect->right;
2597 srect.y2 = SrcRect->bottom;
2601 srect.x2 = Src->currentDesc.Width;
2602 srect.y2 = Src->currentDesc.Height;
2607 /* Bind the target texture */
2608 glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2609 checkGLcall("glBindTexture");
2610 if(swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) {
2611 glReadBuffer(GL_BACK);
2613 glReadBuffer(GL_FRONT);
2615 checkGLcall("glReadBuffer");
2617 xrel = (float) (srect.x2 - srect.x1) / (float) (rect.x2 - rect.x1);
2618 yrel = (float) (srect.y2 - srect.y1) / (float) (rect.y2 - rect.y1);
2620 /* I have to process this row by row to swap the image,
2621 * otherwise it would be upside down, so streching in y direction
2622 * doesn't cost extra time
2624 * However, streching in x direction can be avoided if not necessary
2626 for(row = rect.y1; row < rect.y2; row++) {
2627 if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2628 /* Well, that stuff works, but it's very slow.
2629 * find a better way instead
2632 for(col = rect.x1; col < rect.x2; col++) {
2633 glCopyTexSubImage2D(GL_TEXTURE_2D,
2635 rect.x1 + col, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
2636 srect.x1 + col * xrel, Src->currentDesc.Height - srect.y2 + row * yrel,
2640 glCopyTexSubImage2D(GL_TEXTURE_2D,
2642 rect.x1, rect.y2 + rect.y1 - row - 1, /* xoffset, yoffset */
2643 srect.x1, row - rect.y1,
2644 rect.x2-rect.x1, 1);
2648 vcheckGLcall("glCopyTexSubImage2D");
2651 if(!(This->Flags & SFLAG_DONOTFREE)) {
2652 HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2653 This->resource.allocatedMemory = NULL;
2655 This->Flags |= SFLAG_GLDIRTY;
2663 if (Flags & DDBLT_COLORFILL) {
2664 /* This is easy to handle for the D3D Device... */
2666 IWineD3DSwapChainImpl *implSwapChain;
2668 TRACE("Colorfill\n");
2670 /* The color as given in the Blt function is in the format of the frame-buffer...
2671 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2673 if (This->resource.format == WINED3DFMT_P8) {
2674 if (This->palette) {
2675 color = ((0xFF000000) |
2676 (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2677 (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2678 (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2683 else if (This->resource.format == WINED3DFMT_R5G6B5) {
2684 if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2687 color = ((0xFF000000) |
2688 ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2689 ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2690 ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2693 else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2694 (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2695 color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2697 else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2698 color = DDBltFx->u5.dwFillColor;
2701 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2702 return WINED3DERR_INVALIDCALL;
2705 TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2706 IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
2707 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
2708 if(implSwapChain->backBuffer && This == (IWineD3DSurfaceImpl*) implSwapChain->backBuffer[0]) {
2709 glDrawBuffer(GL_BACK);
2710 checkGLcall("glDrawBuffer(GL_BACK)");
2712 else if (This == (IWineD3DSurfaceImpl*) implSwapChain->frontBuffer) {
2713 glDrawBuffer(GL_FRONT);
2714 checkGLcall("glDrawBuffer(GL_FRONT)");
2717 ERR("Wrong surface type for BLT override(not on swapchain) !\n");
2718 return WINED3DERR_INVALIDCALL;
2721 TRACE("(%p) executing Render Target override, color = %x\n", This, color);
2723 IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2724 1 /* Number of rectangles */,
2726 WINED3DCLEAR_TARGET,
2731 /* Restore the original draw buffer */
2732 if(implSwapChain->backBuffer && implSwapChain->backBuffer[0]) {
2733 glDrawBuffer(GL_BACK);
2734 vcheckGLcall("glDrawBuffer");
2740 /* Default: Fall back to the generic blt */
2741 return WINED3DERR_INVALIDCALL;
2744 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2745 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2746 IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2747 TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2748 TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
2750 /* Special cases for RenderTargets */
2751 if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2752 ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2753 if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2756 /* For the rest call the X11 surface implementation.
2757 * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2758 * other Blts are rather rare
2760 return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2763 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2764 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2765 TRACE("(%p)->(%x)\n", This, Flags);
2770 case DDGBS_ISBLTDONE:
2774 return DDERR_INVALIDPARAMS;
2778 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2779 /* XXX: DDERR_INVALIDSURFACETYPE */
2781 TRACE("(%p)->(%08x)\n",iface,Flags);
2784 case DDGFS_ISFLIPDONE:
2788 return DDERR_INVALIDPARAMS;
2792 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2793 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2794 TRACE("(%p)\n", This);
2796 return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2799 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2800 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2801 TRACE("(%p)\n", This);
2803 /* So far we don't lose anything :) */
2804 This->Flags &= ~SFLAG_LOST;
2808 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2809 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2810 IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2811 TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
2813 /* Special cases for RenderTargets */
2814 if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2815 ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2817 RECT SrcRect, DstRect;
2821 SrcRect.left = rsrc->left;
2822 SrcRect.top= rsrc->top;
2823 SrcRect.bottom = rsrc->bottom;
2824 SrcRect.right = rsrc->right;
2828 SrcRect.right = srcImpl->currentDesc.Width;
2829 SrcRect.bottom = srcImpl->currentDesc.Height;
2832 DstRect.left = dstx;
2834 DstRect.right = dstx + SrcRect.right - SrcRect.left;
2835 DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2837 /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
2838 if(trans & DDBLTFAST_SRCCOLORKEY)
2839 Flags |= DDBLT_KEYSRC;
2840 if(trans & DDBLTFAST_DESTCOLORKEY)
2841 Flags |= DDBLT_KEYDEST;
2842 if(trans & DDBLTFAST_WAIT)
2843 Flags |= DDBLT_WAIT;
2844 if(trans & DDBLTFAST_DONOTWAIT)
2845 Flags |= DDBLT_DONOTWAIT;
2847 if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL) == WINED3D_OK) return WINED3D_OK;
2851 return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2854 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2855 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2856 TRACE("(%p)->(%p)\n", This, Pal);
2858 *Pal = (IWineD3DPalette *) This->palette;
2862 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2863 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2865 IWineD3DPaletteImpl *pal = This->palette;
2867 TRACE("(%p)\n", This);
2869 if(This->resource.format == WINED3DFMT_P8 ||
2870 This->resource.format == WINED3DFMT_A8P8)
2872 TRACE("Dirtifying surface\n");
2873 This->Flags |= SFLAG_DIRTY;
2876 if(This->Flags & SFLAG_DIBSECTION) {
2877 TRACE("(%p): Updating the hdc's palette\n", This);
2878 for (n=0; n<256; n++) {
2880 col[n].rgbRed = pal->palents[n].peRed;
2881 col[n].rgbGreen = pal->palents[n].peGreen;
2882 col[n].rgbBlue = pal->palents[n].peBlue;
2884 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2885 /* Use the default device palette */
2886 col[n].rgbRed = device->palettes[device->currentPalette][n].peRed;
2887 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
2888 col[n].rgbBlue = device->palettes[device->currentPalette][n].peBlue;
2890 col[n].rgbReserved = 0;
2892 SetDIBColorTable(This->hDC, 0, 256, col);
2898 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
2899 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2900 IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
2901 TRACE("(%p)->(%p)\n", This, Pal);
2903 if(This->palette != NULL)
2904 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
2905 This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
2907 if(PalImpl != NULL) {
2908 if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2909 /* Set the device's main palette if the palette
2910 * wasn't a primary palette before
2912 if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
2913 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2916 for(i=0; i < 256; i++) {
2917 device->palettes[device->currentPalette][i] = PalImpl->palents[i];
2921 (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
2924 This->palette = PalImpl;
2926 return IWineD3DSurface_RealizePalette(iface);
2929 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
2930 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2931 TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
2933 if ((Flags & DDCKEY_COLORSPACE) != 0) {
2934 FIXME(" colorkey value not supported (%08x) !\n", Flags);
2935 return DDERR_INVALIDPARAMS;
2938 /* Dirtify the surface, but only if a key was changed */
2940 switch (Flags & ~DDCKEY_COLORSPACE) {
2941 case DDCKEY_DESTBLT:
2942 This->DestBltCKey = *CKey;
2943 This->CKeyFlags |= DDSD_CKDESTBLT;
2946 case DDCKEY_DESTOVERLAY:
2947 This->DestOverlayCKey = *CKey;
2948 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
2951 case DDCKEY_SRCOVERLAY:
2952 This->SrcOverlayCKey = *CKey;
2953 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
2957 This->SrcBltCKey = *CKey;
2958 This->CKeyFlags |= DDSD_CKSRCBLT;
2963 switch (Flags & ~DDCKEY_COLORSPACE) {
2964 case DDCKEY_DESTBLT:
2965 This->CKeyFlags &= ~DDSD_CKDESTBLT;
2968 case DDCKEY_DESTOVERLAY:
2969 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
2972 case DDCKEY_SRCOVERLAY:
2973 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
2977 This->CKeyFlags &= ~DDSD_CKSRCBLT;
2985 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
2986 /** Check against the maximum texture sizes supported by the video card **/
2987 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2989 TRACE("%p\n", This);
2990 if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
2991 /* one of three options
2992 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)
2993 2: Set the texture to the maxium size (bad idea)
2994 3: WARN and return WINED3DERR_NOTAVAILABLE;
2995 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.
2997 WARN("(%p) Creating an oversized surface\n", This);
2998 This->Flags |= SFLAG_OVERSIZE;
3000 /* This will be initialized on the first blt */
3001 This->glRect.left = 0;
3002 This->glRect.top = 0;
3003 This->glRect.right = 0;
3004 This->glRect.bottom = 0;
3006 /* No oversize, gl rect is the full texture size */
3007 This->Flags &= ~SFLAG_OVERSIZE;
3008 This->glRect.left = 0;
3009 This->glRect.top = 0;
3010 This->glRect.right = This->pow2Width;
3011 This->glRect.bottom = This->pow2Height;
3017 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
3018 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3020 TRACE("(%p)\n", This);
3022 /* DXTn formats don't have exact pitches as they are to the new row of blocks,
3023 where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
3024 ie pitch = (width/4) * bytes per block */
3025 if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
3026 ret = ((This->currentDesc.Width + 3) >> 2) << 3;
3027 else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
3028 This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
3029 ret = ((This->currentDesc.Width + 3) >> 2) << 4;
3031 if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
3032 /* Front and back buffers are always lockes/unlocked on currentDesc.Width */
3033 ret = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
3035 ret = This->bytesPerPixel * This->pow2Width;
3037 /* Surfaces are 32 bit aligned */
3038 ret = (ret + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
3040 TRACE("(%p) Returning %d\n", This, ret);
3044 HRESULT WINAPI IWineD3DSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
3045 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3047 FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y);
3049 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3051 TRACE("(%p): Not an overlay surface\n", This);
3052 return DDERR_NOTAOVERLAYSURFACE;
3058 HRESULT WINAPI IWineD3DSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
3059 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3061 FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y);
3063 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3065 TRACE("(%p): Not an overlay surface\n", This);
3066 return DDERR_NOTAOVERLAYSURFACE;
3072 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
3073 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3074 IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
3076 FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
3078 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3080 TRACE("(%p): Not an overlay surface\n", This);
3081 return DDERR_NOTAOVERLAYSURFACE;
3087 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX) {
3088 IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3089 IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
3090 FIXME("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
3092 if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3094 TRACE("(%p): Not an overlay surface\n", This);
3095 return DDERR_NOTAOVERLAYSURFACE;
3101 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
3104 IWineD3DSurfaceImpl_QueryInterface,
3105 IWineD3DSurfaceImpl_AddRef,
3106 IWineD3DSurfaceImpl_Release,
3107 /* IWineD3DResource */
3108 IWineD3DSurfaceImpl_GetParent,
3109 IWineD3DSurfaceImpl_GetDevice,
3110 IWineD3DSurfaceImpl_SetPrivateData,
3111 IWineD3DSurfaceImpl_GetPrivateData,
3112 IWineD3DSurfaceImpl_FreePrivateData,
3113 IWineD3DSurfaceImpl_SetPriority,
3114 IWineD3DSurfaceImpl_GetPriority,
3115 IWineD3DSurfaceImpl_PreLoad,
3116 IWineD3DSurfaceImpl_GetType,
3117 /* IWineD3DSurface */
3118 IWineD3DSurfaceImpl_GetContainerParent,
3119 IWineD3DSurfaceImpl_GetContainer,
3120 IWineD3DSurfaceImpl_GetDesc,
3121 IWineD3DSurfaceImpl_LockRect,
3122 IWineD3DSurfaceImpl_UnlockRect,
3123 IWineD3DSurfaceImpl_GetDC,
3124 IWineD3DSurfaceImpl_ReleaseDC,
3125 IWineD3DSurfaceImpl_Flip,
3126 IWineD3DSurfaceImpl_Blt,
3127 IWineD3DSurfaceImpl_GetBltStatus,
3128 IWineD3DSurfaceImpl_GetFlipStatus,
3129 IWineD3DSurfaceImpl_IsLost,
3130 IWineD3DSurfaceImpl_Restore,
3131 IWineD3DSurfaceImpl_BltFast,
3132 IWineD3DSurfaceImpl_GetPalette,
3133 IWineD3DSurfaceImpl_SetPalette,
3134 IWineD3DSurfaceImpl_RealizePalette,
3135 IWineD3DSurfaceImpl_SetColorKey,
3136 IWineD3DSurfaceImpl_GetPitch,
3137 IWineD3DSurfaceImpl_SetMem,
3138 IWineD3DSurfaceImpl_SetOverlayPosition,
3139 IWineD3DSurfaceImpl_GetOverlayPosition,
3140 IWineD3DSurfaceImpl_UpdateOverlayZOrder,
3141 IWineD3DSurfaceImpl_UpdateOverlay,
3143 IWineD3DSurfaceImpl_CleanDirtyRect,
3144 IWineD3DSurfaceImpl_AddDirtyRect,
3145 IWineD3DSurfaceImpl_LoadTexture,
3146 IWineD3DSurfaceImpl_SaveSnapshot,
3147 IWineD3DSurfaceImpl_SetContainer,
3148 IWineD3DSurfaceImpl_SetPBufferState,
3149 IWineD3DSurfaceImpl_SetGlTextureDesc,
3150 IWineD3DSurfaceImpl_GetGlDesc,
3151 IWineD3DSurfaceImpl_GetData,
3152 IWineD3DSurfaceImpl_SetFormat,
3153 IWineD3DSurfaceImpl_PrivateSetup