diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 7feb7e3fe6f..fc095774aa8 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -549,10 +549,14 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Wid while (pow2Width < Width) pow2Width <<= 1; while (pow2Height < Height) pow2Height <<= 1; - if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) { - /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/ - FIXME("non-power-two textures unsupported\n"); - return D3DERR_NOTAVAILABLE; + if (pow2Width > Width || pow2Height > Height) { + /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/ + if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 + || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) { + FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n", + This, Width, Height); + return D3DERR_NOTAVAILABLE; + } } /** TODO: Check against the maximum texture sizes supported by the video card **/ @@ -565,9 +569,21 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Wid object->currentDesc.Level = Level; object->currentDesc.MultiSampleType = MultiSample; object->currentDesc.MultiSampleQuality = MultisampleQuality; + /* Internal data */ + object->pow2Width = pow2Width; + object->pow2Height = pow2Height; + object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE; object->discard = Discard; object->bytesPerPixel = D3DFmtGetBpp(This, Format); - + object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height; + + /** TODO: change this into a texture transform matrix so that it's processed in hardware **/ + + /* Precalculated scaling for 'faked' non power of two texture coords */ + object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width)); + object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height)); + TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY); + /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since * it is based around 4x4 pixel blocks it requires padding, so allocate enough * space! @@ -640,7 +656,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Wid return D3DERR_OUTOFVIDEOMEMORY; } - + /* mark the texture as dirty so that it get's loaded first time around*/ IWineD3DSurface_AddDirtyRect(*ppSurface, NULL); TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index a8dd9583c99..988893cd0fe 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -3,7 +3,8 @@ * * Copyright 2002-2004 Jason Edmeades * Copyright 2002-2004 Raphael Junqueira - * Copyright 2004 Christian Costa + * Copyright 2004 Christian Costa + * Copyright 2005 Oliver Stieber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -367,7 +368,7 @@ void primitiveDeclarationConvertToStridedData(IWineD3DDevice *iface, Direct3DVer TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]); data = ((IWineD3DVertexBufferImpl *)This->stateBlock->streamSource[element->Stream])->resource.allocatedMemory; } - stride = This->stateBlock->streamSource[element->Stream]; + stride = This->stateBlock->streamStride[element->Stream]; data += (BaseVertexIndex * stride); data += element->Offset; /* Why can't I just use a lookup table instead of a switch statment? */ @@ -1258,6 +1259,12 @@ void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd, } } + /* crude support for non-power2 textures */ + if(((IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->nonpow2){ + t *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorY; + s *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorX; + } + switch (coordsToUse) { /* Supply the provided texture coords */ case D3DTTFF_COUNT1: VTRACE(("tex:%d, s=%f\n", textureNo, s)); @@ -1637,6 +1644,7 @@ void drawPrimitive(IWineD3DDevice *iface, BOOL isLightingOn = FALSE; Direct3DVertexStridedData dataLocations; int useHW = FALSE; + BOOL nonPower2 = FALSE; /* set to true if any surfaces are non-power2 so that drawslow is used. */ if (This->stateBlock->vertexDecl == NULL) { /* Work out what the FVF should look like */ @@ -1738,6 +1746,14 @@ void drawPrimitive(IWineD3DDevice *iface, { /* Load up the texture now */ IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]); + if (IWineD3DResourceImpl_GetType((IWineD3DResource *)This->stateBlock->textures[i]) == D3DRTYPE_TEXTURE ) { + /* TODO: Is this right, as its cast all texture types to texture8... checkme */ + IWineD3DSurface *surface; + IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[i], 0, &surface); + if (((IWineD3DSurfaceImpl *)surface)->nonpow2) { + nonPower2 = TRUE; + } + } } } @@ -1764,6 +1780,7 @@ void drawPrimitive(IWineD3DDevice *iface, } else if ((dataLocations.u.s.pSize.lpData != NULL) || (dataLocations.u.s.diffuse.lpData != NULL) + || nonPower2 /*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) { /* Fixme, Ideally, only use the per-vertex code for software HAL diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 0b389077dc4..9a266749661 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -272,6 +272,9 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE This->lockedRect.bottom = pRect->bottom; } + if(This->nonpow2){ + TRACE("Locking non-power 2 texture\n"); + } if (0 == This->resource.usage) { /* classic surface */ @@ -678,8 +681,23 @@ HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) { HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, GLenum gl_target, GLenum gl_level) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; - if (This->inTexture) + if (This->inTexture) { + TRACE("Surface already in texture\n"); return D3D_OK; + } + if (This->Dirty == FALSE) { + TRACE("surface isn't dirty\n"); + return D3D_OK; + } + + This->Dirty = FALSE; + + /* Resources are placed in system RAM and do not need to be recreated when a device is lost. These resources are not bound by device size or format restrictions. Because of this, these resources cannot be accessed by the Direct3D device nor set as textures or render targets. However, these resources can always be created, locked, and copied. */ + if (This->resource.pool == D3DPOOL_SCRATCH || This->resource.pool == D3DPOOL_SYSTEMMEM) /*never store scratch or system mem textures in the video ram*/ + { + FIXME("(%p) Opperation not supported for scratch or SYSTEMMEM textures\n",This); + return D3DERR_INVALIDCALL; + } if (This->inPBuffer) { ENTER_GL(); @@ -791,32 +809,79 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, GLenum gl } } else { - TRACE("Calling glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n", - gl_target, - gl_level, - debug_d3dformat(This->resource.format), - D3DFmt2GLIntFmt(This->resource.wineD3DDevice, This->resource.format), - This->currentDesc.Width, - This->currentDesc.Height, - 0, - D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format), - D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format), - This->resource.allocatedMemory); + /* TODO: possibly use texture recrangle (though we probably more compatable without it) */ + if (This->nonpow2 == TRUE) { - ENTER_GL(); + TRACE("non power of two support\n"); + ENTER_GL(); + TRACE("(%p) Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n", This, + gl_target, + gl_level, + debug_d3dformat(This->resource.format), + D3DFmt2GLIntFmt(This->resource.wineD3DDevice, This->resource.format), + This->pow2Width, + This->pow2Height, + 0, + D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format), + D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format), + NULL); - glTexImage2D(gl_target, - gl_level, - D3DFmt2GLIntFmt(This->resource.wineD3DDevice, This->resource.format), - This->currentDesc.Width, - This->currentDesc.Height, - 0, - D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format), - D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format), - This->resource.allocatedMemory); - checkGLcall("glTexImage2D"); + glTexImage2D(gl_target, + gl_level, + D3DFmt2GLIntFmt(This->resource.wineD3DDevice, This->resource.format), + This->pow2Width, + This->pow2Height, + 0/*border*/, + D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format), + D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format), + NULL); - LEAVE_GL(); + checkGLcall("glTexImage2D"); + if (This->resource.allocatedMemory != NULL) { + TRACE("(%p) Calling glTexSubImage2D w(%d) h(%d) mem(%p)\n", This, This->currentDesc.Width, This->currentDesc.Height, This->resource.allocatedMemory); + /* And map the non-power two data into the top left corner */ + glTexSubImage2D( + gl_target, + gl_level, + 0 /* xoffset */, + 0 /* ysoffset */ , + This->currentDesc.Width, + This->currentDesc.Height, + D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format), + D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format), + This->resource.allocatedMemory + ); + checkGLcall("glTexSubImage2D"); + } + LEAVE_GL(); + + } else { + + TRACE("Calling 2 glTexImage2D %x i=%d, d3dfmt=%s, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n", + gl_target, + gl_level, + debug_d3dformat(This->resource.format), + D3DFmt2GLIntFmt(This->resource.wineD3DDevice, This->resource.format), + This->currentDesc.Width, + This->currentDesc.Height, + 0, + D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format), + D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format), + This->resource.allocatedMemory); + + ENTER_GL(); + glTexImage2D(gl_target, + gl_level, + D3DFmt2GLIntFmt(This->resource.wineD3DDevice, This->resource.format), + This->currentDesc.Width, + This->currentDesc.Height, + 0 /* border */, + D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format), + D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format), + This->resource.allocatedMemory); + checkGLcall("glTexImage2D"); + LEAVE_GL(); + } #if 0 { @@ -939,6 +1004,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) { */ extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) { IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; + IWineD3DBaseTexture *baseTexture = NULL; This->Dirty = TRUE; if (NULL != pDirtyRect) { This->dirtyRect.left = min(This->dirtyRect.left, pDirtyRect->left); @@ -953,6 +1019,12 @@ extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, C } TRACE("(%p) : Dirty?%d, Rect:(%ld,%ld,%ld,%ld)\n", This, This->Dirty, This->dirtyRect.left, This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom); + /* if the container is a basetexture then mark it dirty. */ + if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == D3D_OK) { + TRACE("Passing to conatiner\n"); + IWineD3DBaseTexture_SetDirty(baseTexture, TRUE); + IWineD3DBaseTexture_Release(baseTexture); + } return D3D_OK; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 45136973847..4690d5c75c9 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -622,7 +622,18 @@ struct IWineD3DSurfaceImpl UINT textureName; UINT bytesPerPixel; - + + /* TODO: move this off into a management class(maybe!) */ + BOOL nonpow2; + + UINT pow2Width; + UINT pow2Height; + UINT pow2Size; + + /* precalculated x and y scalings for texture coords */ + float pow2scalingFactorX; /* = (Width / pow2Width ) */ + float pow2scalingFactorY; /* = (Height / pow2Height) */ + BOOL lockable; BOOL discard; BOOL locked;