Implemented basic non-power 2 texture in wined3d.

Also fixed a typo in drawprim that was causing vertex declarations to
crash.
This commit is contained in:
Oliver Stieber 2005-07-11 14:25:54 +00:00 committed by Alexandre Julliard
parent 8ad8969fd5
commit 520c2f0870
4 changed files with 149 additions and 33 deletions

View File

@ -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),

View File

@ -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

View File

@ -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;
}

View File

@ -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;