WineD3D patch submission
Mirek Slugen(
thunder.m at email.cz
Sat Sep 22 05:01:50 CDT 2007
I tried this patch, everything works like before, can't find any
regression in apps like ET: QW, Oblivion, all nvidia D3D SDK tests,
3DMarks and others. Titan Quest looks beter, but there are still some
issues in menu, game is not working because of gdi32.dll functionality.
I create patch for actual git.
Mirek
Mitchell Wheeler napsal(a):
> Hi all,
>
> A week or so ago I tried to get a game working in WINE (Titan Quest),
> however it seems it really needs a proper DIB engine before it'll be
> playable.
>
> Anyways, in my attempt to get it working I fixed up some issues w/
> "IWineD3DDeviceImpl_UpdateSurface.c" in dlls/wined3d, not entirely sure
> how you guys do things around here so I thought i'd just post my changes
> to the function in this mailing list and you can do with it what you
> want. (Note: it actually has a few different methods of doing one
> thing, enclosed in macro blocks to toggle between them. Technically the
> first one should work (i think :\) once you guys properly implement
> surface locking/unlocking, and it's 'simplest', but the last one is the
> only one that actually works properly (using standard OpenGL calls).
>
> You'll probably have to clean up the code to meet your coding standards
> / etc, maybe remove the custom byte size calculation of compressed
> images, and some other things - but the functionality is there... i
> also fixed the existing code that didn't actually do what it was
> supposed to, heh.
>
> Regards,
> Mitchell Wheeler
>
> static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice
> *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect,
> IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
> IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
> /** TODO: remove casts to IWineD3DSurfaceImpl
> * NOTE: move code to surface to accomplish this
> ****************************************/
> IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl
> *)pSourceSurface;
> IWineD3DSurfaceImpl *pDestSurface =
> (IWineD3DSurfaceImpl*)pDestinationSurface;
> int srcWidth, srcHeight;
> unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth,
> destSurfaceHeight;
> WINED3DFORMAT destFormat, srcFormat;
> int srcLeft, srcTop, destLeft, destTop;
> WINED3DPOOL 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, *glSrcDescription = NULL;
> GLenum dummy;
> int bpp;
> UINT destByteSize = 0, srcByteSize = 0;
> int destPixelByteSize = 0, srcPixelByteSize = 0;
> CONVERT_TYPES convert = NO_CONVERSION;
>
> WINED3DSURFACE_DESC winedesc;
>
> TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n",
> This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
> memset(&winedesc, 0, sizeof(winedesc));
> winedesc.Width = &srcSurfaceWidth;
> winedesc.Height = &srcSurfaceHeight;
> winedesc.Pool = &srcPool;
> winedesc.Format = &srcFormat;
> winedesc.Size = &srcByteSize;
>
> IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
>
> winedesc.Width = &destSurfaceWidth;
> winedesc.Height = &destSurfaceHeight;
> winedesc.Pool = &destPool;
> winedesc.Format = &destFormat;
> winedesc.Size = &destByteSize;
>
> IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
>
> if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool !=
> WINED3DPOOL_DEFAULT){
> WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT,
> returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
> return WINED3DERR_INVALIDCALL;
> }
>
> /* This call loads the opengl surface directly, instead of copying
> the surface to the
> * destination's sysmem copy. If surface conversion is needed, use
> BltFast instead to
> * copy in sysmem and use regular surface loading.
> */
> d3dfmt_get_conv((IWineD3DSurfaceImpl *) pDestinationSurface, FALSE,
> TRUE,
> &dummy, &dummy, &dummy, &convert, &bpp, FALSE);
> if(convert != NO_CONVERSION) {
> return IWineD3DSurface_BltFast(pDestinationSurface,
> pDestPoint ? pDestPoint->x : 0,
> pDestPoint ? pDestPoint->y : 0,
> pSourceSurface, (RECT *)
> pSourceRect, 0);
> }
>
> if (destFormat == WINED3DFMT_UNKNOWN) {
> TRACE("(%p) : Converting destination surface from
> WINED3DFMT_UNKNOWN to the source format\n", This);
> IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
>
> /* Get the update surface description */
> IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
> }
>
> ActivateContext(This, This->lastActiveRenderTarget,
> CTXUSAGE_RESOURCELOAD);
>
> ENTER_GL();
>
> if (GL_SUPPORT(ARB_MULTITEXTURE)) {
> GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
> checkGLcall("glActiveTextureARB");
> }
>
> /* Make sure the surface is loaded and up to date */
> IWineD3DSurface_PreLoad(pDestinationSurface);
> IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
> IWineD3DSurface_GetGlDesc(pDestinationSurface, &glSrcDescription);
>
> /* this needs to be done in lines if the sourceRect != the
> sourceWidth */
> srcWidth = pSourceRect ? pSourceRect->right -
> pSourceRect->left : srcSurfaceWidth;
> srcHeight = pSourceRect ? pSourceRect->bottom -
> pSourceRect->top : srcSurfaceHeight;
> srcLeft = pSourceRect ? pSourceRect->left
> : 0;
> srcTop = pSourceRect ? pSourceRect->top
> : 0;
> destLeft = pDestPoint ? pDestPoint->x
> : 0;
> destTop = pDestPoint ? pDestPoint->y
> : 0;
>
> // Calculate the rowOffset / offset values, for copying
> #define ISDXTFORMAT(format) \
> (format == WINED3DFMT_DXT1 || format == WINED3DFMT_DXT2 ||
> format == WINED3DFMT_DXT3 || format == WINED3DFMT_DXT4 || format ==
> WINED3DFMT_DXT5)
>
> // Calculating this for our selves because I don't have faith in how
> surface->bytesPerPixel is calculated...
> destPixelByteSize = destByteSize / (int)(destSurfaceWidth *
> destSurfaceHeight);
> srcPixelByteSize = srcByteSize / (int)(srcSurfaceWidth *
> srcSurfaceHeight);
>
> if(pSourceRect != NULL)
> {
> // Irregular surface formats
> if (destFormat != srcFormat) {
> FIXME("Can not convert between surface pixel formats...");
>
> // Would require some relatively big code restructuring for
> rare occurances (that shouldn't even be supported?)
>
> return WINED3DERR_INVALIDCALL;
> }
> // Uniform surface formats
> else
> {
> if(srcWidth != srcSurfaceWidth || srcLeft > 0)
> {
> rowoffset = srcSurfaceWidth * srcPixelByteSize;
> offset += (srcLeft * srcPixelByteSize);
> }
>
> if(srcTop > 0)
> offset += srcTop * srcSurfaceWidth * srcPixelByteSize;
> }
>
> }
>
> /* 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) {
> // Compressed texture
> if (ISDXTFORMAT(destFormat))
> {
> if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC))
> {
> #if 0
> RECT rect;
> rect.left = destLeft;
> rect.top = destTop;
> rect.right = destLeft + srcWidth;
> rect.bottom = destTop + srcHeight;
>
> // Lock source/destination regions
> WINED3DLOCKED_RECT destRect, srcRect;
>
> printf("Locking surfaces...\n");
> if(
> FAILED(IWineD3DSurface_LockRect(pDestinationSurface, &destRect, &rect,
> 0)) ||
> FAILED(IWineD3DSurface_LockRect(pSourceSurface,
> &srcRect, pSourceRect, WINED3DLOCK_READONLY)))
> {
> // How should we handle this case? Just returning
> an invalid call for now...
> return WINED3DERR_INVALIDCALL;
> }
>
> printf("Surfaces locked, copying contents now... ");
> if(destFormat == WINED3DFMT_DXT1) {
> printf("DXT1\n");
> //memcpy(destRect.pBits, srcRect.pBits,
> srcRect.Pitch * (srcHeight / 2));
> //memcpy(destRect.pBits, srcRect.pBits,
> srcRect.Pitch * (srcHeight / 2));
> memcpy(destRect.pBits, srcRect.pBits,
> ceil(srcWidth/4) * ceil(srcHeight/4) * 8);
> } else {
> printf("DXT2-5\n");
> //memcpy(destRect.pBits, srcRect.pBits,
> srcRect.Pitch * (srcHeight / 4));
> memcpy(destRect.pBits, srcRect.pBits,
> ceil(srcWidth/4) * ceil(srcHeight/4) * 16);
> }
>
> // Unlock source/destination regions
> IWineD3DSurface_UnlockRect(pSourceSurface);
> IWineD3DSurface_UnlockRect(pDestinationSurface);
> printf("Unlocking surfaces...\n");
> #elif 0
> // Get pointers to the source/destination buffers
> unsigned char *dest_data = (unsigned
> char*)IWineD3DSurface_GetData(pDestinationSurface);
> const unsigned char *src_data = (unsigned
> char*)IWineD3DSurface_GetData(pSourceSurface);
>
> // Copy subsection of source buffer, in to destination
> buffer.
> unsigned char *dest_ptr = dest_data + offset;
> const unsigned char *src_ptr = src_data + offset;
>
> size_t i;
> for(i = 0; i < srcHeight; ++i) {
> memcpy(dest_ptr, src_ptr, srcWidth * srcPixelByteSize);
>
> dest_ptr += rowoffset;
> src_ptr += rowoffset;
> }
>
>
> // Upload destination buffer to server
> GL_EXTCALL(glCompressedTexImage2DARB(glDescription->target,
> glDescription->level,
>
> glDescription->glFormatInternal,
> srcWidth,
> srcHeight,
> 0,
> destByteSize,
> dest_data));
>
> checkGLcall("glCompressedTexImage2DARB");
> #elif 1
> int blocksize = 16;
> if(destFormat == WINED3DFMT_DXT1)
> blocksize = 8;
>
> #define max(a, b) (a > b? a : b)
> srcHeight = max(srcHeight, 4);
> srcWidth = max(srcWidth, 4);
> #undef max
>
> int data_size = (srcWidth / 4) * (srcHeight / 4) *
> blocksize;
> int row_size = data_size / srcHeight;
> int pixel_size = row_size / srcWidth;
> int stride = srcSurfaceWidth * pixel_size;
>
> unsigned char *temp_buffer = HeapAlloc(GetProcessHeap(),
> 0, data_size);
> unsigned char *temp_ptr = temp_buffer;
>
> // Debug info
> //printf(" > BytesTotal: %i | BytesPerPixel: %i |
> RowSize: %i\n", data_size, pixel_size, row_size);
> //printf(" > Source: %i -> %i, %i -> %i | Dest: %i,
> %i\n", srcLeft, srcWidth, srcTop, srcHeight, destLeft, destTop);
> //printf(" > Offset: %i\n", (int)((row_size * srcTop) +
> srcLeft * pixel_size));
>
> // Get pointers to the source buffer
> const unsigned char *src_data = (unsigned
> char*)IWineD3DSurface_GetData(pSourceSurface);
> src_data += (stride * srcTop) + srcLeft * pixel_size;
>
> size_t i;
> for(i = 0; i < srcHeight; ++i) {
> memcpy(temp_ptr, src_data, row_size);
> temp_ptr += row_size;
> src_data += stride;
> }
>
> GL_EXTCALL(glCompressedTexSubImage2DARB(
> glDescription->target,
> glDescription->level,
> destLeft,
> destTop,
> srcWidth,
> srcHeight,
> glDescription->glFormatInternal,
> data_size,
> temp_buffer
> ));
> //checkGLcall("glCompressedTexSubImage2DARB");
>
> HeapFree(GetProcessHeap(), 0, temp_buffer);
> #endif
> }
> else
> {
> FIXME("TODO: Need to update a DXT compressed texture
> without hardware support\n");
> }
> }
> // Uncompressed texture
> else
> {
> /* 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 */
> const unsigned char* data =((const 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 {
> // Compressed texture
> if (ISDXTFORMAT(destFormat))
> {
> if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC))
> {
> int blocksize = 16;
> if(destFormat == WINED3DFMT_DXT1)
> blocksize = 8;
>
> #define max(a, b) (a > b? a : b)
> int data_size = (max(srcWidth, 4) / 4) * (max(srcHeight,
> 4) / 4) * blocksize;
> #undef max
>
> //printf(" -> S = %i | CompressedTexImage2D(?, %i, %i,
> %i, %i, 0, %i, ?)\n", destByteSize, glDescription->level,
> glDescription->glFormatInternal, srcWidth, srcHeight, data_size);
>
> GL_EXTCALL(glCompressedTexSubImage2DARB(glDescription->target,
> glDescription->level,
> destLeft,
> destTop,
> srcWidth,
> srcHeight,
>
> glDescription->glFormatInternal,
> data_size,
>
> IWineD3DSurface_GetData(pSourceSurface)));
>
> checkGLcall("glCompressedTexImage2DARB");
> }
> else
> {
> FIXME("TODO: Need to update a DXT compressed texture
> without hardware support\n");
> }
> }
> // Uncompressed Texture
> else
> {
> glTexSubImage2D(
> glDescription->target,
> glDescription->level,
> destLeft,
> destTop,
> srcWidth,
> srcHeight,
> glDescription->glFormat,
> glDescription->glType,
> IWineD3DSurface_GetData(pSourceSurface)
> );
>
> checkGLcall("glTexSubImage2D");
> }
> }
>
> LEAVE_GL();
>
> ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags &= ~SFLAG_INSYSMEM;
> ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_INTEXTURE;
> IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
>
> return WINED3D_OK;
> }
>
>
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.diff
Type: text/x-patch
Size: 17700 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20070922/bbdac283/attachment-0001.bin
More information about the wine-devel
mailing list