示例#1
0
文件: texture.c 项目: mikekap/wine
/* Do not call while under the GL lock. */
static ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
    IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
    ULONG ref;
    TRACE("(%p) : Releasing from %d\n", This, This->resource.ref);
    ref = InterlockedDecrement(&This->resource.ref);
    if (!ref)
    {
        texture_cleanup(This);
        This->resource.parent_ops->wined3d_object_destroyed(This->resource.parent);
        HeapFree(GetProcessHeap(), 0, This);
    }
    return ref;
}
示例#2
0
文件: texture.c 项目: dvdhoo/wine
HRESULT texture_init(IWineD3DBaseTextureImpl *texture, UINT width, UINT height, UINT levels,
                     IWineD3DDeviceImpl *device, DWORD usage, enum wined3d_format_id format_id, WINED3DPOOL pool,
                     void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
    const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
    UINT pow2_width, pow2_height;
    UINT tmp_w, tmp_h;
    unsigned int i;
    HRESULT hr;

    /* TODO: It should only be possible to create textures for formats
     * that are reported as supported. */
    if (WINED3DFMT_UNKNOWN >= format_id)
    {
        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
        return WINED3DERR_INVALIDCALL;
    }

    /* Non-power2 support. */
    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
    {
        pow2_width = width;
        pow2_height = height;
    }
    else
    {
        /* Find the nearest pow2 match. */
        pow2_width = pow2_height = 1;
        while (pow2_width < width) pow2_width <<= 1;
        while (pow2_height < height) pow2_height <<= 1;

        if (pow2_width != width || pow2_height != height)
        {
            if (levels > 1)
            {
                WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support.\n");
                return WINED3DERR_INVALIDCALL;
            }
            levels = 1;
        }
    }

    /* Calculate levels for mip mapping. */
    if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
    {
        if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
        {
            WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n");
            return WINED3DERR_INVALIDCALL;
        }

        if (levels > 1)
        {
            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n");
            return WINED3DERR_INVALIDCALL;
        }

        levels = 1;
    }
    else if (!levels)
    {
        levels = wined3d_log2i(max(width, height)) + 1;
        TRACE("Calculated levels = %u.\n", levels);
    }

    texture->lpVtbl = &IWineD3DTexture_Vtbl;

    hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, &texture_ops,
                          1, levels, WINED3DRTYPE_TEXTURE, device, usage, format, pool,
                          parent, parent_ops, &texture_resource_ops);
    if (FAILED(hr))
    {
        WARN("Failed to initialize basetexture, returning %#x.\n", hr);
        return hr;
    }

    /* Precalculated scaling for 'faked' non power of two texture coords.
     * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
     * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE
     * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */
    if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT] && (width != pow2_width || height != pow2_height))
    {
        texture->baseTexture.pow2Matrix[0] = 1.0f;
        texture->baseTexture.pow2Matrix[5] = 1.0f;
        texture->baseTexture.pow2Matrix[10] = 1.0f;
        texture->baseTexture.pow2Matrix[15] = 1.0f;
        texture->baseTexture.target = GL_TEXTURE_2D;
        texture->baseTexture.cond_np2 = TRUE;
        texture->baseTexture.minMipLookup = minMipLookup_noFilter;
    }
    else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (width != pow2_width || height != pow2_height)
             && !(format->id == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE]
                  && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
    {
        if ((width != 1) || (height != 1)) texture->baseTexture.pow2Matrix_identity = FALSE;

        texture->baseTexture.pow2Matrix[0] = (float)width;
        texture->baseTexture.pow2Matrix[5] = (float)height;
        texture->baseTexture.pow2Matrix[10] = 1.0f;
        texture->baseTexture.pow2Matrix[15] = 1.0f;
        texture->baseTexture.target = GL_TEXTURE_RECTANGLE_ARB;
        texture->baseTexture.cond_np2 = TRUE;

        if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
        {
            texture->baseTexture.minMipLookup = minMipLookup_noMip;
        }
        else
        {
            texture->baseTexture.minMipLookup = minMipLookup_noFilter;
        }
    }
    else
    {
        if ((width != pow2_width) || (height != pow2_height))
        {
            texture->baseTexture.pow2Matrix_identity = FALSE;
            texture->baseTexture.pow2Matrix[0] = (((float)width) / ((float)pow2_width));
            texture->baseTexture.pow2Matrix[5] = (((float)height) / ((float)pow2_height));
        }
        else
        {
            texture->baseTexture.pow2Matrix[0] = 1.0f;
            texture->baseTexture.pow2Matrix[5] = 1.0f;
        }

        texture->baseTexture.pow2Matrix[10] = 1.0f;
        texture->baseTexture.pow2Matrix[15] = 1.0f;
        texture->baseTexture.target = GL_TEXTURE_2D;
        texture->baseTexture.cond_np2 = FALSE;
    }
    TRACE("xf(%f) yf(%f)\n", texture->baseTexture.pow2Matrix[0], texture->baseTexture.pow2Matrix[5]);

    /* Generate all the surfaces. */
    tmp_w = width;
    tmp_h = height;
    for (i = 0; i < texture->baseTexture.level_count; ++i)
    {
        IWineD3DSurface *surface;

        /* Use the callback to create the texture surface. */
        hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h,
                                                format->id, usage, pool, i, 0, &surface);
        if (FAILED(hr))
        {
            FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
            texture_cleanup(texture);
            return hr;
        }

        surface_set_container((IWineD3DSurfaceImpl *)surface, WINED3D_CONTAINER_TEXTURE, (IWineD3DBase *)texture);
        surface_set_texture_target((IWineD3DSurfaceImpl *)surface, texture->baseTexture.target);
        texture->baseTexture.sub_resources[i] = &((IWineD3DSurfaceImpl *)surface)->resource;
        TRACE("Created surface level %u @ %p.\n", i, surface);
        /* Calculate the next mipmap level. */
        tmp_w = max(1, tmp_w >> 1);
        tmp_h = max(1, tmp_h >> 1);
    }

    return WINED3D_OK;
}
示例#3
0
HRESULT texture_init(IWineD3DTextureImpl *texture, UINT width, UINT height, UINT levels,
        IWineD3DDeviceImpl *device, DWORD usage, WINED3DFORMAT format, WINED3DPOOL pool,
        IUnknown *parent, const struct wined3d_parent_ops *parent_ops
#ifdef VBOX_WITH_WDDM
        , HANDLE *shared_handle
        , void **pavClientMem
#endif
        )
{
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
    const struct wined3d_format_desc *format_desc = getFormatDescEntry(format, gl_info);
    UINT pow2_width, pow2_height;
    UINT tmp_w, tmp_h;
    unsigned int i;
    HRESULT hr;

    /* TODO: It should only be possible to create textures for formats
     * that are reported as supported. */
    if (WINED3DFMT_UNKNOWN >= format)
    {
        WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture);
        return WINED3DERR_INVALIDCALL;
    }

    /* Non-power2 support. */
    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
    {
        pow2_width = width;
        pow2_height = height;
    }
    else
    {
        /* Find the nearest pow2 match. */
        pow2_width = pow2_height = 1;
        while (pow2_width < width) pow2_width <<= 1;
        while (pow2_height < height) pow2_height <<= 1;

        if (pow2_width != width || pow2_height != height)
        {
            if (levels > 1)
            {
                WARN("Attempted to create a mipmapped np2 texture without unconditional np2 support.\n");
                return WINED3DERR_INVALIDCALL;
            }
            levels = 1;
        }
    }

    /* Calculate levels for mip mapping. */
    if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
    {
        if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
        {
            WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n");
            return WINED3DERR_INVALIDCALL;
        }

        if (levels > 1)
        {
            WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n");
            return WINED3DERR_INVALIDCALL;
        }

        levels = 1;
    }
    else if (!levels)
    {
        levels = wined3d_log2i(max(width, height)) + 1;
        TRACE("Calculated levels = %u.\n", levels);
    }

    texture->lpVtbl = &IWineD3DTexture_Vtbl;

    hr = basetexture_init((IWineD3DBaseTextureImpl *)texture, levels, WINED3DRTYPE_TEXTURE,
            device, 0, usage, format_desc, pool, parent, parent_ops
#ifdef VBOX_WITH_WDDM
            , shared_handle, pavClientMem
#endif
        );
    if (FAILED(hr))
    {
        WARN("Failed to initialize basetexture, returning %#x.\n", hr);
        return hr;
    }

    /* Precalculated scaling for 'faked' non power of two texture coords.
     * Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
     * is used in combination with texture uploads (RTL_READTEX). The reason is that EXT_PALETTED_TEXTURE
     * doesn't work in combination with ARB_TEXTURE_RECTANGLE. */
    if (gl_info->supported[WINE_NORMALIZED_TEXRECT] && (width != pow2_width || height != pow2_height))
    {
        texture->baseTexture.pow2Matrix[0] = 1.0f;
        texture->baseTexture.pow2Matrix[5] = 1.0f;
        texture->baseTexture.pow2Matrix[10] = 1.0f;
        texture->baseTexture.pow2Matrix[15] = 1.0f;
        texture->target = GL_TEXTURE_2D;
        texture->cond_np2 = TRUE;
        texture->baseTexture.minMipLookup = minMipLookup_noFilter;
    }
    else if (gl_info->supported[ARB_TEXTURE_RECTANGLE] && (width != pow2_width || height != pow2_height)
            && !(format_desc->format == WINED3DFMT_P8_UINT && gl_info->supported[EXT_PALETTED_TEXTURE]
            && wined3d_settings.rendertargetlock_mode == RTL_READTEX))
    {
        if ((width != 1) || (height != 1)) texture->baseTexture.pow2Matrix_identity = FALSE;

        texture->baseTexture.pow2Matrix[0] = (float)width;
        texture->baseTexture.pow2Matrix[5] = (float)height;
        texture->baseTexture.pow2Matrix[10] = 1.0f;
        texture->baseTexture.pow2Matrix[15] = 1.0f;
        texture->target = GL_TEXTURE_RECTANGLE_ARB;
        texture->cond_np2 = TRUE;

        if(texture->resource.format_desc->Flags & WINED3DFMT_FLAG_FILTERING)
        {
            texture->baseTexture.minMipLookup = minMipLookup_noMip;
        }
        else
        {
            texture->baseTexture.minMipLookup = minMipLookup_noFilter;
        }
    }
    else
    {
        if ((width != pow2_width) || (height != pow2_height))
        {
            texture->baseTexture.pow2Matrix_identity = FALSE;
            texture->baseTexture.pow2Matrix[0] = (((float)width) / ((float)pow2_width));
            texture->baseTexture.pow2Matrix[5] = (((float)height) / ((float)pow2_height));
        }
        else
        {
            texture->baseTexture.pow2Matrix[0] = 1.0f;
            texture->baseTexture.pow2Matrix[5] = 1.0f;
        }

        texture->baseTexture.pow2Matrix[10] = 1.0f;
        texture->baseTexture.pow2Matrix[15] = 1.0f;
        texture->target = GL_TEXTURE_2D;
        texture->cond_np2 = FALSE;
    }
    TRACE("xf(%f) yf(%f)\n", texture->baseTexture.pow2Matrix[0], texture->baseTexture.pow2Matrix[5]);

    /* Generate all the surfaces. */
    tmp_w = width;
    tmp_h = height;
    for (i = 0; i < texture->baseTexture.levels; ++i)
    {
#ifdef VBOX_WITH_WDDM
        /* Use the callback to create the texture surface. */
        hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h, format_desc->format,
                usage, pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &texture->surfaces[i]
                , NULL /* <- we first create a surface in an everage "non-shared" fashion and initialize its share properties later (see below)
                        * this is done this way because the surface does not have its parent (texture) setup properly
                        * thus we can not initialize texture at this stage */
                , pavClientMem ? pavClientMem[i] : NULL);

#else
        /* Use the callback to create the texture surface. */
        hr = IWineD3DDeviceParent_CreateSurface(device->device_parent, parent, tmp_w, tmp_h, format_desc->format,
                usage, pool, i, WINED3DCUBEMAP_FACE_POSITIVE_X, &texture->surfaces[i]);
#endif

        if (FAILED(hr))
        {
            FIXME("Failed to create surface %p, hr %#x\n", texture, hr);
            texture->surfaces[i] = NULL;
            texture_cleanup(texture);
            return hr;
        }

        IWineD3DSurface_SetContainer(texture->surfaces[i], (IWineD3DBase *)texture);
        TRACE("Created surface level %u @ %p.\n", i, texture->surfaces[i]);
        surface_set_texture_target(texture->surfaces[i], texture->target);
        /* Calculate the next mipmap level. */
        tmp_w = max(1, tmp_w >> 1);
        tmp_h = max(1, tmp_h >> 1);
    }
    texture->baseTexture.internal_preload = texture_internal_preload;

#ifdef VBOX_WITH_WDDM
    if (VBOXSHRC_IS_SHARED(texture))
    {
        Assert(shared_handle);
        for (i = 0; i < texture->baseTexture.levels; ++i)
        {
            VBOXSHRC_COPY_SHAREDATA((IWineD3DSurfaceImpl*)texture->surfaces[i], texture);
        }
#ifdef DEBUG
        for (i = 0; i < texture->baseTexture.levels; ++i)
        {
            Assert(!((IWineD3DSurfaceImpl*)texture->surfaces[i])->texture_name);
        }
#endif
        for (i = 0; i < texture->baseTexture.levels; ++i)
        {
            if (!VBOXSHRC_IS_SHARED_OPENED(texture))
            {
                IWineD3DSurface_LoadLocation(texture->surfaces[i], SFLAG_INTEXTURE, NULL);
                Assert(!(*shared_handle));
                *shared_handle = VBOXSHRC_GET_SHAREHANDLE(texture);
            }
            else
            {
                surface_setup_location_onopen((IWineD3DSurfaceImpl*)texture->surfaces[i]);
                Assert(*shared_handle);
                Assert(*shared_handle == VBOXSHRC_GET_SHAREHANDLE(texture));
            }
        }
#ifdef DEBUG
        for (i = 0; i < texture->baseTexture.levels; ++i)
        {
            Assert((GLuint)(*shared_handle) == ((IWineD3DSurfaceImpl*)texture->surfaces[i])->texture_name);
        }
#endif

        if (!VBOXSHRC_IS_SHARED_OPENED(texture))
        {
            struct wined3d_context * context;

            Assert(!device->isInDraw);

            /* flush to ensure the texture is allocated before it is used by another
             * process opening it */
            context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
            if (context->valid)
            {
                wglFlush();
            }
            else
            {
                ERR("invalid context!");
            }
            context_release(context);
        }
    }
    else
    {
        Assert(!shared_handle);
    }
#endif

    return WINED3D_OK;
}