d3d9: ATI1N support

Stefan Dösinger stefandoesinger at gmx.at
Sun Jun 7 21:18:17 CDT 2009


Nice that you found a way to support this format :-)

Can you separate the compressed data loading changes from the ATI1N  
specific changes? I will make regression testing easier if anything  
should break.

Do you have an app that needs this format? I think a test would be a  
good idea.

Am 07.06.2009 um 09:48 schrieb Frank Richter:

> ---
> dlls/wined3d/device.c       |    5 +-
> dlls/wined3d/directx.c      |    8 +++
> dlls/wined3d/surface.c      |  110
> ++++++++++++++++++++++++-------------------
> dlls/wined3d/surface_base.c |    6 +-
> dlls/wined3d/utils.c        |    6 ++
> include/wine/wined3d.idl    |    1 +
> 6 files changed, 82 insertions(+), 54 deletions(-)
>
>
> diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
> index f1dd938..a08f713 100644
> --- a/dlls/wined3d/device.c
> +++ b/dlls/wined3d/device.c
> @@ -920,10 +920,9 @@ static HRESULT WINAPI  
> IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface,
>     mul_4h = (Height + 3) & ~3;
>     if (WINED3DFMT_UNKNOWN == Format) {
>         Size = 0;
> -    } else if (Format == WINED3DFMT_DXT1) {
> -        /* DXT1 is half byte per pixel */
> +    } else if (Format == WINED3DFMT_DXT1 || Format ==  
> WINED3DFMT_ATI1N) {
> +        /* DXT1, ATI1N are half byte per pixel */
>         Size = (mul_4w * glDesc->byte_count * mul_4h) >> 1;
> -
>     } else if (Format == WINED3DFMT_DXT2 || Format ==  
> WINED3DFMT_DXT3 ||
>                Format == WINED3DFMT_DXT4 || Format ==  
> WINED3DFMT_DXT5 ||
>                Format == WINED3DFMT_ATI2N) {
> diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
> index 4a2a270..60045aa 100644
> --- a/dlls/wined3d/directx.c
> +++ b/dlls/wined3d/directx.c
> @@ -2467,6 +2467,14 @@ static BOOL CheckTextureCapability(struct  
> WineD3DAdapter *adapter,
>             return FALSE;
>
>         /* Vendor specific formats */
> +        case WINED3DFMT_ATI1N:
> +            if(GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
> +                TRACE_(d3d_caps)("[OK]\n");
> +                return TRUE;
> +            }
> +            TRACE_(d3d_caps)("[FAILED]\n");
> +            return FALSE;
> +
>         case WINED3DFMT_ATI2N:
>             if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) ||  
> GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
>                 shader_backend = select_shader_backend(adapter,  
> DeviceType);
> diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
> index 2f5554f..6469fa4 100644
> --- a/dlls/wined3d/surface.c
> +++ b/dlls/wined3d/surface.c
> @@ -132,6 +132,25 @@ static BOOL  
> primary_render_target_is_p8(IWineD3DDeviceImpl *device)
>     return FALSE;
> }
>
> +/* Download data for a compressed surface */
> +static void surface_download_data_compressed(IWineD3DSurfaceImpl  
> *This, const struct GlPixelFormatDesc *format_desc) {
> +    TRACE("(%p) : Calling glGetCompressedTexImageARB level %d,  
> format %#x, type %#x, data %p\n",
> +	    This, This->glDescription.level, format_desc->glFormat,  
> format_desc->glType,
> +	    This->resource.allocatedMemory);
> +
> +    if(This->Flags & SFLAG_PBO) {
> +	GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
> +	checkGLcall("glBindBufferARB");
> +	GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target,  
> This->glDescription.level, NULL));
> +	checkGLcall("glGetCompressedTexImageARB()");
> +	GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
> +	checkGLcall("glBindBufferARB");
> +    } else {
> +	GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target,  
> This->glDescription.level, This->resource.allocatedMemory));
> +	checkGLcall("glGetCompressedTexImageARB()");
> +    }
> +}
> +
> /* This call just downloads data, the caller is responsible for  
> activating the
>  * right context and binding the correct texture. */
> static void surface_download_data(IWineD3DSurfaceImpl *This) {
> @@ -145,31 +164,19 @@ static void  
> surface_download_data(IWineD3DSurfaceImpl *This) {
>     }
>
>     ENTER_GL();
> -
> -    if (format_desc->format == WINED3DFMT_DXT1 || format_desc- 
> >format == WINED3DFMT_DXT2
> -            || format_desc->format == WINED3DFMT_DXT3 ||  
> format_desc->format == WINED3DFMT_DXT4
> -            || format_desc->format == WINED3DFMT_DXT5 ||  
> format_desc->format == WINED3DFMT_ATI2N)
> -    {
> +
> +    if (format_desc->format == WINED3DFMT_DXT1 || format_desc- 
> >format == WINED3DFMT_DXT2
> +	    || format_desc->format == WINED3DFMT_DXT3 || format_desc- 
> >format == WINED3DFMT_DXT4
> +	    || format_desc->format == WINED3DFMT_DXT5) {
>         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* We can  
> assume this as the texture would not have been created otherwise */
>             FIXME("(%p) : Attempting to lock a compressed texture  
> when texture compression isn't supported by opengl\n", This);
>         } else {
> -            TRACE("(%p) : Calling glGetCompressedTexImageARB level  
> %d, format %#x, type %#x, data %p\n",
> -                    This, This->glDescription.level, format_desc- 
> >glFormat, format_desc->glType,
> -                    This->resource.allocatedMemory);
> -
> -            if(This->Flags & SFLAG_PBO) {
> -                 
> GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
> -                checkGLcall("glBindBufferARB");
> -                GL_EXTCALL(glGetCompressedTexImageARB(This- 
> >glDescription.target, This->glDescription.level, NULL));
> -                checkGLcall("glGetCompressedTexImageARB()");
> -                 
> GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
> -                checkGLcall("glBindBufferARB");
> -            } else {
> -                GL_EXTCALL(glGetCompressedTexImageARB(This- 
> >glDescription.target, This->glDescription.level, This- 
> >resource.allocatedMemory));
> -                checkGLcall("glGetCompressedTexImageARB()");
> -            }
> +	    surface_download_data_compressed(This, format_desc);
>         }
>         LEAVE_GL();
> +    } else if (format_desc->format == WINED3DFMT_ATI1N ||  
> format_desc->format == WINED3DFMT_ATI2N) {
> +	surface_download_data_compressed(This, format_desc);
> +        LEAVE_GL();
>     } else {
>         void *mem;
>         GLenum format = format_desc->glFormat;
> @@ -286,6 +293,35 @@ static void  
> surface_download_data(IWineD3DSurfaceImpl *This) {
>     This->Flags |= SFLAG_INSYSMEM;
> }
>
> +/* Upload data for a compressed surface */
> +static void surface_upload_data_compressed(IWineD3DSurfaceImpl  
> *This, const struct GlPixelFormatDesc *format_desc,
> +					   GLenum internal, GLsizei width, GLsizei height, const  
> GLvoid *data) {
> +    /* glCompressedTexSubImage2D for uploading and glTexImage2D for  
> allocating does not work well on some drivers(r200 dri, MacOS ATI  
> driver)
> +     * glCompressedTexImage2D does not accept NULL pointers. So for  
> compressed textures surface_allocate_surface does nothing, and this
> +     * function uses glCompressedTexImage2D instead of the SubImage  
> call
> +     */
> +    TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d,  
> data %p\n", This, width, height, data);
> +    ENTER_GL();
> +
> +    if(This->Flags & SFLAG_PBO) {
> +	GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
> +	checkGLcall("glBindBufferARB");
> +	TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo, data);
> +
> +	GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target,  
> This->glDescription.level, internal,
> +		width, height, 0 /* border */, This->resource.size, NULL));
> +	checkGLcall("glCompressedTexSubImage2D");
> +
> +	GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
> +	checkGLcall("glBindBufferARB");
> +    } else {
> +	GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target,  
> This->glDescription.level, internal,
> +		width, height, 0 /* border */, This->resource.size, data));
> +	checkGLcall("glCompressedTexSubImage2D");
> +    }
> +    LEAVE_GL();
> +}
> +
> /* This call just uploads data, the caller is responsible for  
> activating the
>  * right context and binding the correct texture. */
> static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum  
> internal, GLsizei width, GLsizei height, GLenum format, GLenum type,  
> const GLvoid *data) {
> @@ -293,38 +329,16 @@ static void  
> surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsi
>
>     if (format_desc->heightscale != 1.0 && format_desc->heightscale ! 
> = 0.0) height *= format_desc->heightscale;
>
> -    if (format_desc->format == WINED3DFMT_DXT1 || format_desc- 
> >format == WINED3DFMT_DXT2
> -            || format_desc->format == WINED3DFMT_DXT3 ||  
> format_desc->format == WINED3DFMT_DXT4
> -            || format_desc->format == WINED3DFMT_DXT5 ||  
> format_desc->format == WINED3DFMT_ATI2N)
> -    {
> +    if (format_desc->format == WINED3DFMT_DXT1 || format_desc- 
> >format == WINED3DFMT_DXT2
> +	    || format_desc->format == WINED3DFMT_DXT3 || format_desc- 
> >format == WINED3DFMT_DXT4
> +	    || format_desc->format == WINED3DFMT_DXT5) {
>         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
>             FIXME("Using DXT1/3/5 without advertized support\n");
>         } else {
> -            /* glCompressedTexSubImage2D for uploading and  
> glTexImage2D for allocating does not work well on some drivers(r200  
> dri, MacOS ATI driver)
> -             * glCompressedTexImage2D does not accept NULL  
> pointers. So for compressed textures surface_allocate_surface does  
> nothing, and this
> -             * function uses glCompressedTexImage2D instead of the  
> SubImage call
> -             */
> -            TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h  
> %d, data %p\n", This, width, height, data);
> -            ENTER_GL();
> -
> -            if(This->Flags & SFLAG_PBO) {
> -                 
> GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
> -                checkGLcall("glBindBufferARB");
> -                TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo,  
> data);
> -
> -                GL_EXTCALL(glCompressedTexImage2DARB(This- 
> >glDescription.target, This->glDescription.level, internal,
> -                        width, height, 0 /* border */, This- 
> >resource.size, NULL));
> -                checkGLcall("glCompressedTexSubImage2D");
> -
> -                 
> GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
> -                checkGLcall("glBindBufferARB");
> -            } else {
> -                GL_EXTCALL(glCompressedTexImage2DARB(This- 
> >glDescription.target, This->glDescription.level, internal,
> -                        width, height, 0 /* border */, This- 
> >resource.size, data));
> -                checkGLcall("glCompressedTexSubImage2D");
> -            }
> -            LEAVE_GL();
> +	    surface_upload_data_compressed(This, format_desc, internal,  
> width, height, data);
>         }
> +    } else if (format_desc->format == WINED3DFMT_ATI1N ||  
> format_desc->format == WINED3DFMT_ATI2N) {
> +	surface_upload_data_compressed(This, format_desc, internal, width,  
> height, data);
>     } else {
>         TRACE("(%p) : Calling glTexSubImage2D w %d,  h %d, data, %p 
> \n", This, width, height, data);
>         ENTER_GL();
> diff --git a/dlls/wined3d/surface_base.c b/dlls/wined3d/surface_base.c
> index d487f80..83cbd9d 100644
> --- a/dlls/wined3d/surface_base.c
> +++ b/dlls/wined3d/surface_base.c
> @@ -339,7 +339,7 @@ DWORD WINAPI  
> IWineD3DBaseSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
>     /* DXTn formats don't have exact pitches as they are to the new  
> row of blocks,
>     where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes  
> (dxt2/3/4/5)
>     ie pitch = (width/4) * bytes per  
> block                                  */
> -    if (format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
> +    if (format == WINED3DFMT_DXT1 || format == WINED3DFMT_ATI1N) /*  
> DXT1, ATI1N are 8 bytes per block */
>         ret = ((This->currentDesc.Width + 3) >> 2) << 3;
>     else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
>              format == WINED3DFMT_DXT4 || format ==  
> WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
> @@ -521,8 +521,8 @@ HRESULT WINAPI  
> IWineD3DBaseSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3D
>     TRACE("(%p) : Setting texture format to (%d,%s)\n", This,  
> format, debug_d3dformat(format));
>     if (format == WINED3DFMT_UNKNOWN) {
>         This->resource.size = 0;
> -    } else if (format == WINED3DFMT_DXT1) {
> -        /* DXT1 is half byte per pixel */
> +    } else if (format == WINED3DFMT_DXT1 || format ==  
> WINED3DFMT_ATI1N) {
> +        /* DXT1, ATI1N are half byte per pixel */
>         This->resource.size = ((max(This->pow2Width, 4) *  
> format_desc->byte_count) * max(This->pow2Height, 4)) >> 1;
>
>     } else if (format == WINED3DFMT_DXT2 || format ==  
> WINED3DFMT_DXT3 ||
> diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
> index f141a3b..822ce14 100644
> --- a/dlls/wined3d/utils.c
> +++ b/dlls/wined3d/utils.c
> @@ -129,6 +129,7 @@ static const struct StaticPixelFormatDesc  
> formats[] =
>     {WINED3DFMT_R32_UINT,           0x0,        0x0,         
> 0x0,        0x0,        4,      0,      0,      FALSE},
>     {WINED3DFMT_R16G16B16A16_SNORM, 0x0,        0x0,         
> 0x0,        0x0,        8,      0,      0,      FALSE},
>     /* Vendor-specific formats */
> +    {WINED3DFMT_ATI1N,              0x0,        0x0,         
> 0x0,        0x0,        1,      0,      0,      TRUE },
>     {WINED3DFMT_ATI2N,              0x0,        0x0,         
> 0x0,        0x0,        1,      0,      0,      TRUE },
>     {WINED3DFMT_NVHU,               0x0,        0x0,         
> 0x0,        0x0,        2,      0,      0,      TRUE },
>     {WINED3DFMT_NVHS,               0x0,        0x0,         
> 0x0,        0x0,        2,      0,      0,      TRUE },
> @@ -459,6 +460,10 @@ static const GlPixelFormatDescTemplate  
> gl_formats_template[] = {
>             WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL,
>             EXT_PACKED_DEPTH_STENCIL},
>     /* Vendor-specific formats */
> +    {WINED3DFMT_ATI1N,              GL_COMPRESSED_RED_RGTC1_EXT,  
> GL_COMPRESSED_RED_RGTC1_EXT,     0,
> +            GL_RED,                 GL_UNSIGNED_BYTE,
> +            0,
> +            EXT_TEXTURE_COMPRESSION_RGTC},
>     {WINED3DFMT_ATI2N,               
> GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI,  
> GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0,
>             GL_LUMINANCE_ALPHA,     GL_UNSIGNED_BYTE,
>             0,
> @@ -868,6 +873,7 @@ const char* debug_d3dformat(WINED3DFORMAT fmt) {
>     FMT_TO_STR(WINED3DFMT_D24FS8);
>     FMT_TO_STR(WINED3DFMT_VERTEXDATA);
>     FMT_TO_STR(WINED3DFMT_CxV8U8);
> +    FMT_TO_STR(WINED3DFMT_ATI1N);
>     FMT_TO_STR(WINED3DFMT_ATI2N);
>     FMT_TO_STR(WINED3DFMT_NVHU);
>     FMT_TO_STR(WINED3DFMT_NVHS);
> diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
> index 51d886c..6d087fd 100644
> --- a/include/wine/wined3d.idl
> +++ b/include/wine/wined3d.idl
> @@ -272,6 +272,7 @@ cpp_quote("#define WINED3DFMT_MULTI2_ARGB8  
> WINEMAKEFOURCC('M', 'E', 'T', '1')")
> cpp_quote("#define WINED3DFMT_G8R8_G8B8    WINEMAKEFOURCC('G', 'R',  
> 'G', 'B')")
> cpp_quote("#define WINED3DFMT_R8G8_B8G8    WINEMAKEFOURCC('R', 'G',  
> 'B', 'G')")
> /* Vendor specific formats */
> +cpp_quote("#define WINED3DFMT_ATI1N        WINEMAKEFOURCC('A', 'T',  
> 'I', '1')")
> cpp_quote("#define WINED3DFMT_ATI2N        WINEMAKEFOURCC('A', 'T',  
> 'I', '2')")
> cpp_quote("#define WINED3DFMT_NVHU         WINEMAKEFOURCC('N', 'V',  
> 'H', 'U')")
> cpp_quote("#define WINED3DFMT_NVHS         WINEMAKEFOURCC('N', 'V',  
> 'H', 'S')")
>
>




More information about the wine-devel mailing list