Implement UpdateTexture and UpdateSurface in wined3d.

Allow NULL members of WINED3DSURFACE_DESC to be set to Surface_GetDesc
so that the whole structure doesn't have to be filled just to get back
one value.
This commit is contained in:
Oliver Stieber 2005-07-12 17:02:47 +00:00 committed by Alexandre Julliard
parent e502d4dda3
commit 9f7e794ca6
3 changed files with 231 additions and 31 deletions

View File

@ -4618,10 +4618,52 @@ HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface,
return D3D_OK;
}
/* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
TRACE("(%p) : stub\n", This);
D3DRESOURCETYPE sourceType;
D3DRESOURCETYPE destinationType;
IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
int i;
sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
return D3DERR_INVALIDCALL;
}
TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
/** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
think about moving the code into texture, and adding a member to base texture to occomplish this **/
/* Make sure that the destination texture is loaded */
IWineD3DBaseTexture_PreLoad(pDestinationTexture);
TRACE("Loading source texture\n");
if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
}
if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
return D3DERR_INVALIDCALL;
}
/** TODO: check that both textures have the same number of levels **/
#if 0
if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
return D3DERR_INVALIDCALL;
#endif
/** TODO: move this code into baseTexture? device should never touch impl*'s **/
for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
}
return D3D_OK;
}
@ -4731,10 +4773,169 @@ float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
FIXME("(%p) : stub\n", This);
return D3D_OK;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
/** TODO: remove casts to IWineD3DSurfaceImpl
* NOTE: move code to surface to accomplish this
****************************************/
IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
int srcWidth, srcHeight, srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
WINED3DFORMAT destFormat, srcFormat;
UINT destSize;
int destLeft, destTop;
D3DPOOL srcPool, destPool;
int offset = 0;
int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
glDescriptor *glDescription = NULL;
GLenum textureDimensions = GL_TEXTURE_2D;
IWineD3DBaseTexture *baseTexture;
WINED3DSURFACE_DESC winedesc;
memset(&winedesc, 0, sizeof(winedesc));
winedesc.Width = &srcSurfaceWidth;
winedesc.Height = &srcSurfaceHeight;
winedesc.Pool = &srcPool;
winedesc.Format = &srcFormat;
IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
winedesc.Width = &destSurfaceWidth;
winedesc.Height = &destSurfaceHeight;
winedesc.Pool = &destPool;
winedesc.Format = &destFormat;
winedesc.Size = &destSize;
IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
return D3DERR_INVALIDCALL;
}
/* TODO: change this to use bindTexture */
/* Make sure the surface is loaded and upto date */
IWineD3DSurface_PreLoad(pDestinationSurface);
IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
ENTER_GL();
/* this needs to be done in lines if the sourceRect != the sourceWidth */
srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
destLeft = pDestPoint ? pDestPoint->x : 0;
destTop = pDestPoint ? pDestPoint->y : 0;
/* This function doesn't support compressed textures
the pitch is just bytesPerPixel * width */
if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
/* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
}
/* TODO DXT formats */
if(pSourceRect != NULL && pSourceRect->top != 0){
offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
}
TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
,This
,glDescription->level
,destLeft
,destTop
,srcWidth
,srcHeight
,glDescription->glFormat
,glDescription->glType
,IWineD3DSurface_GetData(pSourceSurface)
);
/* Sanity check */
if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
/* need to lock the surface to get the data */
FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
}
/* TODO: Cube and volume support */
if(rowoffset != 0){
/* not a whole row so we have to do it a line at a time */
int j;
/* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
for(j = destTop ; j < (srcHeight + destTop) ; j++){
glTexSubImage2D(glDescription->target
,glDescription->level
,destLeft
,j
,srcWidth
,1
,glDescription->glFormat
,glDescription->glType
,data/* could be quicker using */
);
data += rowoffset;
}
} else { /* Full width, so just write out the whole texture */
if (WINED3DFMT_DXT1 == destFormat ||
WINED3DFMT_DXT3 == destFormat ||
WINED3DFMT_DXT5 == destFormat) {
if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
/* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
FIXME("Updating part of a compressed texture is not supported at the moment\n");
} if (destFormat != srcFormat) {
FIXME("Updating mixed format compressed texture is not curretly support\n");
} else {
GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
glDescription->level,
glDescription->glFormatInternal,
srcWidth,
srcHeight,
0,
destSize,
IWineD3DSurface_GetData(pSourceSurface));
}
} else {
FIXME("Attempting to update a DXT compressed texture without hardware support\n");
}
} else {
/* some applications can not handle odd pitches returned by soft non-power2, so we have
to repack the data from pow2Width/Height to expected Width,Height, this makes the
data returned by GetData non-power2 width/height with hardware non-power2
pow2Width/height are set to surface width height, repacking isn't needed so it
doesn't matter which function gets called. */
glTexSubImage2D(glDescription->target
,glDescription->level
,destLeft
,destTop
,srcWidth
,srcHeight
,glDescription->glFormat
,glDescription->glType
,IWineD3DSurface_GetData(pSourceSurface)
);
}
}
checkGLcall("glTexSubImage2D");
/* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
* GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
* surface bigger than it needs to be hmm.. */
if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
IWineD3DBaseTexture_Release(baseTexture);
}
glDisable(textureDimensions); /* This needs to be managed better.... */
LEAVE_GL();
return D3D_OK;
}
/* Implementation details at http://developer.nvidia.com/attach/6494

View File

@ -1741,11 +1741,12 @@ void drawPrimitive(IWineD3DDevice *iface,
/* And re-upload any dirty textures */
for (i=0; i<GL_LIMITS(textures); i++) {
if ((This->stateBlock->textures[i] != NULL) &&
(IWineD3DBaseTexture_GetDirty(This->stateBlock->textures[i])))
{
/* Load up the texture now */
IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
if (This->stateBlock->textures[i] != NULL) {
if (IWineD3DBaseTexture_GetDirty(This->stateBlock->textures[i])) {
/* 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;
@ -1753,8 +1754,8 @@ void drawPrimitive(IWineD3DDevice *iface,
if (((IWineD3DSurfaceImpl *)surface)->nonpow2) {
nonPower2 = TRUE;
}
}
}
}
}
}
/* Now draw the graphics to the screen */

View File

@ -190,15 +190,15 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFAC
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
TRACE("(%p) : copying into %p\n", This, pDesc);
*(pDesc->Format) = This->resource.format;
*(pDesc->Type) = This->resource.resourceType;
*(pDesc->Usage) = This->resource.usage;
*(pDesc->Pool) = This->resource.pool;
*(pDesc->Size) = This->resource.size; /* dx8 only */
*(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
*(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
*(pDesc->Width) = This->currentDesc.Width;
*(pDesc->Height) = This->currentDesc.Height;
if(pDesc->Format != NULL) *(pDesc->Format) = This->resource.format;
if(pDesc->Type != NULL) *(pDesc->Type) = This->resource.resourceType;
if(pDesc->Usage != NULL) *(pDesc->Usage) = This->resource.usage;
if(pDesc->Pool != NULL) *(pDesc->Pool) = This->resource.pool;
if(pDesc->Size != NULL) *(pDesc->Size) = This->resource.size; /* dx8 only */
if(pDesc->MultiSampleType != NULL) *(pDesc->MultiSampleType) = This->currentDesc.MultiSampleType;
if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
if(pDesc->Width != NULL) *(pDesc->Width) = This->currentDesc.Width;
if(pDesc->Height != NULL) *(pDesc->Height) = This->currentDesc.Height;
return D3D_OK;
}
@ -406,8 +406,6 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
*****************************************/
if (!notInContext) { /* Only read the buffer if it's in the current context */
long j;
GLenum format = D3DFmt2GLFmt(myDevice, This->resource.format);
GLenum type = D3DFmt2GLType(myDevice, This->resource.format);
#if 0
/* Bizarly it takes 120 millseconds to get an 800x600 region a line at a time, but only 10 to get the whole lot every time,
* This is on an ATI9600, and may be format dependent, anyhow this hack makes this demo dx9_2d_demo_game
@ -422,16 +420,16 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
glReadPixels(0, 0,
This->currentDesc.Width,
This->currentDesc.Height,
format,
type,
This->glDescription.glFormat,
This->glDescription.glType,
(char *)pLockedRect->pBits);
}else if (This->lockedRect.left ==0 && This->lockedRect.right == This->currentDesc.Width) {
glReadPixels(0,
This->lockedRect.top,
This->currentDesc.Width,
This->currentDesc.Height,
format,
type,
This->glDescription.glFormat,
This->glDescription.glType,
(char *)pLockedRect->pBits);
} else{
@ -440,8 +438,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
This->lockedRect.bottom - j - 1,
This->lockedRect.right - This->lockedRect.left,
1,
format,
type,
This->glDescription.glFormat,
This->glDescription.glType,
(char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
}
@ -873,8 +871,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
This->pow2Width,
This->pow2Height,
0/*border*/,
D3DFmt2GLFmt(This->resource.wineD3DDevice, This->resource.format),
D3DFmt2GLType(This->resource.wineD3DDevice, This->resource.format),
This->glDescription.glFormat,
This->glDescription.glType,
NULL);
checkGLcall("glTexImage2D");