예제 #1
0
파일: volume.c 프로젝트: klickverbot/wine
static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_device *device, UINT width,
        UINT height, UINT depth, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool 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);
    HRESULT hr;

    if (!gl_info->supported[EXT_TEXTURE3D])
    {
        WARN("Volume cannot be created - no volume texture support.\n");
        return WINED3DERR_INVALIDCALL;
    }

    hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format,
            WINED3D_MULTISAMPLE_NONE, 0, usage, pool, width, height, depth,
            width * height * depth * format->byte_count, parent, parent_ops,
            &volume_resource_ops);
    if (FAILED(hr))
    {
        WARN("Failed to initialize resource, returning %#x.\n", hr);
        return hr;
    }

    volume->lockable = TRUE;
    volume->locked = FALSE;
    memset(&volume->lockedBox, 0, sizeof(volume->lockedBox));
    volume->dirty = TRUE;

    volume_add_dirty_box(volume, NULL);

    return WINED3D_OK;
}
예제 #2
0
파일: volume.c 프로젝트: kholia/wine
HRESULT wined3d_volume_init(struct wined3d_volume *volume, struct wined3d_texture *container,
        const struct wined3d_resource_desc *desc, UINT level)
{
    struct wined3d_device *device = container->resource.device;
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
    const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format);
    HRESULT hr;
    UINT size;

    size = wined3d_format_calculate_size(format, device->surface_alignment, desc->width, desc->height, desc->depth);

    if (FAILED(hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format,
            WINED3D_MULTISAMPLE_NONE, 0, desc->usage, desc->pool, desc->width, desc->height, desc->depth,
            size, NULL, &wined3d_null_parent_ops, &volume_resource_ops)))
    {
        WARN("Failed to initialize resource, returning %#x.\n", hr);
        return hr;
    }

    if (container->resource.map_binding == WINED3D_LOCATION_BUFFER)
        wined3d_resource_free_sysmem(&volume->resource);

    volume->texture_level = level;
    container->sub_resources[level].locations = WINED3D_LOCATION_DISCARDED;

    volume->container = container;

    return WINED3D_OK;
}
예제 #3
0
파일: view.c 프로젝트: vindo-app/wine
static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
        const struct wined3d_rendertarget_view_desc *desc, struct wined3d_resource *resource,
        void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;

    view->refcount = 1;
    view->parent = parent;
    view->parent_ops = parent_ops;

    view->format = wined3d_get_format(gl_info, desc->format_id);
    view->format_flags = view->format->flags[resource->gl_type];

    if (wined3d_format_is_typeless(view->format))
    {
        WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view->format->id));
        return E_INVALIDARG;
    }

    if (resource->type == WINED3D_RTYPE_BUFFER)
    {
        view->sub_resource_idx = 0;
        view->buffer_offset = desc->u.buffer.start_idx;
        view->width = desc->u.buffer.count;
        view->height = 1;
        view->depth = 1;
    }
    else
    {
        struct wined3d_texture *texture = texture_from_resource(resource);
        unsigned int depth_or_layer_count;

        if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
            depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
        else
            depth_or_layer_count = texture->layer_count;

        if (desc->u.texture.level_idx >= texture->level_count
                || desc->u.texture.layer_idx >= depth_or_layer_count
                || !desc->u.texture.layer_count
                || desc->u.texture.layer_count > depth_or_layer_count - desc->u.texture.layer_idx)
            return E_INVALIDARG;

        view->sub_resource_idx = desc->u.texture.level_idx;
        if (resource->type != WINED3D_RTYPE_TEXTURE_3D)
            view->sub_resource_idx += desc->u.texture.layer_idx * texture->level_count;
        view->buffer_offset = 0;
        view->width = wined3d_texture_get_level_width(texture, desc->u.texture.level_idx);
        view->height = wined3d_texture_get_level_height(texture, desc->u.texture.level_idx);
        view->depth = desc->u.texture.layer_count;
    }
    wined3d_resource_incref(view->resource = resource);

    return WINED3D_OK;
}
예제 #4
0
파일: volume.c 프로젝트: Kelimion/wine
static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_device *device, UINT width,
        UINT height, UINT depth, UINT level, DWORD usage, enum wined3d_format_id format_id,
        enum wined3d_pool 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);
    HRESULT hr;
    UINT size;

    if (!gl_info->supported[EXT_TEXTURE3D])
    {
        WARN("Volume cannot be created - no volume texture support.\n");
        return WINED3DERR_INVALIDCALL;
    }
    /* TODO: Write tests for other resources and move this check
     * to resource_init, if applicable. */
    if (usage & WINED3DUSAGE_DYNAMIC
            && (pool == WINED3D_POOL_MANAGED || pool == WINED3D_POOL_SCRATCH))
    {
        WARN("Attempted to create a DYNAMIC texture in pool %u.\n", pool);
        return WINED3DERR_INVALIDCALL;
    }

    size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, depth);

    hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format,
            WINED3D_MULTISAMPLE_NONE, 0, usage, pool, width, height, depth,
            size, parent, parent_ops, &volume_resource_ops);
    if (FAILED(hr))
    {
        WARN("Failed to initialize resource, returning %#x.\n", hr);
        return hr;
    }

    volume->texture_level = level;
    volume->locations = WINED3D_LOCATION_DISCARDED;

    if (pool == WINED3D_POOL_DEFAULT && usage & WINED3DUSAGE_DYNAMIC
            && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT])
    {
        wined3d_resource_free_sysmem(volume->resource.heap_memory);
        volume->resource.heap_memory = NULL;
        volume->resource.allocatedMemory = NULL;
        volume->flags |= WINED3D_VFLAG_PBO;
    }

    return WINED3D_OK;
}
예제 #5
0
파일: volume.c 프로젝트: alexwgo/wine
static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture *container,
        const struct wined3d_resource_desc *desc, UINT level)
{
    struct wined3d_device *device = container->resource.device;
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
    const struct wined3d_format *format = wined3d_get_format(gl_info, desc->format);
    HRESULT hr;
    UINT size;

    if (!gl_info->supported[EXT_TEXTURE3D])
    {
        WARN("Volume cannot be created - no volume texture support.\n");
        return WINED3DERR_INVALIDCALL;
    }
    /* TODO: Write tests for other resources and move this check
     * to resource_init, if applicable. */
    if (desc->usage & WINED3DUSAGE_DYNAMIC
            && (desc->pool == WINED3D_POOL_MANAGED || desc->pool == WINED3D_POOL_SCRATCH))
    {
        WARN("Attempted to create a DYNAMIC texture in pool %s.\n", debug_d3dpool(desc->pool));
        return WINED3DERR_INVALIDCALL;
    }

    size = wined3d_format_calculate_size(format, device->surface_alignment, desc->width, desc->height, desc->depth);

    if (FAILED(hr = resource_init(&volume->resource, device, WINED3D_RTYPE_VOLUME, format,
            WINED3D_MULTISAMPLE_NONE, 0, desc->usage, desc->pool, desc->width, desc->height, desc->depth,
            size, NULL, &wined3d_null_parent_ops, &volume_resource_ops)))
    {
        WARN("Failed to initialize resource, returning %#x.\n", hr);
        return hr;
    }

    volume->texture_level = level;
    volume->locations = WINED3D_LOCATION_DISCARDED;

    if (desc->pool == WINED3D_POOL_DEFAULT && desc->usage & WINED3DUSAGE_DYNAMIC
            && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]
            && !format->convert)
    {
        wined3d_resource_free_sysmem(&volume->resource);
        volume->flags |= WINED3D_VFLAG_PBO;
    }

    volume->container = container;

    return WINED3D_OK;
}
예제 #6
0
static HRESULT wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
        const struct wined3d_rendertarget_view_desc *desc, struct wined3d_resource *resource,
        void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;

    view->refcount = 1;
    view->parent = parent;
    view->parent_ops = parent_ops;

    view->format = wined3d_get_format(gl_info, desc->format_id);
    view->format_flags = view->format->flags[resource->gl_type];
    if (resource->type == WINED3D_RTYPE_BUFFER)
    {
        view->sub_resource_idx = 0;
        view->buffer_offset = desc->u.buffer.start_idx;
        view->width = desc->u.buffer.count;
        view->height = 1;
        view->depth = 1;
    }
    else
    {
        struct wined3d_texture *texture = texture_from_resource(resource);

        if (desc->u.texture.level_idx >= texture->level_count
                || desc->u.texture.layer_idx >= texture->layer_count
                || desc->u.texture.layer_count > texture->layer_count - desc->u.texture.layer_idx)
            return WINED3DERR_INVALIDCALL;
        view->sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
        view->buffer_offset = 0;
        view->width = wined3d_texture_get_level_width(texture, desc->u.texture.level_idx);
        view->height = wined3d_texture_get_level_height(texture, desc->u.texture.level_idx);
        view->depth = desc->u.texture.layer_count;
    }
    wined3d_resource_incref(view->resource = resource);

    return WINED3D_OK;
}
예제 #7
0
파일: view.c 프로젝트: vindo-app/wine
static HRESULT wined3d_unordered_access_view_init(struct wined3d_unordered_access_view *view,
        const struct wined3d_unordered_access_view_desc *desc, struct wined3d_resource *resource,
        void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;

    view->refcount = 1;
    view->parent = parent;
    view->parent_ops = parent_ops;

    view->format = wined3d_get_format(gl_info, desc->format_id);

    if (wined3d_format_is_typeless(view->format))
    {
        WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view->format->id));
        return E_INVALIDARG;
    }

    if (resource->type != WINED3D_RTYPE_BUFFER)
    {
        struct wined3d_texture *texture = texture_from_resource(resource);
        unsigned int depth_or_layer_count;

        if (resource->type == WINED3D_RTYPE_TEXTURE_3D)
            depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
        else
            depth_or_layer_count = texture->layer_count;

        if (desc->u.texture.level_idx >= texture->level_count
                || desc->u.texture.layer_idx >= depth_or_layer_count
                || !desc->u.texture.layer_count
                || desc->u.texture.layer_count > depth_or_layer_count - desc->u.texture.layer_idx)
            return E_INVALIDARG;
    }
    wined3d_resource_incref(view->resource = resource);

    return WINED3D_OK;
}
예제 #8
0
HRESULT volume_init(IWineD3DVolumeImpl *volume, IWineD3DDeviceImpl *device, UINT width,
        UINT height, UINT depth, 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);
    HRESULT hr;

    if (!gl_info->supported[EXT_TEXTURE3D])
    {
        WARN("Volume cannot be created - no volume texture support.\n");
        return WINED3DERR_INVALIDCALL;
    }

    volume->lpVtbl = &IWineD3DVolume_Vtbl;

    hr = resource_init((IWineD3DResource *)volume, WINED3DRTYPE_VOLUME, device,
            width * height * depth * format->byte_count, usage, format, pool, parent, parent_ops);
    if (FAILED(hr))
    {
        WARN("Failed to initialize resource, returning %#x.\n", hr);
        return hr;
    }

    volume->currentDesc.Width = width;
    volume->currentDesc.Height = height;
    volume->currentDesc.Depth = depth;
    volume->lockable = TRUE;
    volume->locked = FALSE;
    memset(&volume->lockedBox, 0, sizeof(volume->lockedBox));
    volume->dirty = TRUE;

    volume_add_dirty_box((IWineD3DVolume *)volume, NULL);

    return WINED3D_OK;
}
예제 #9
0
파일: view.c 프로젝트: Strongc/reactos
static void wined3d_rendertarget_view_init(struct wined3d_rendertarget_view *view,
        const struct wined3d_rendertarget_view_desc *desc, struct wined3d_resource *resource,
        void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;

    view->refcount = 1;
    view->resource = resource;
    wined3d_resource_incref(resource);
    view->parent = parent;
    view->parent_ops = parent_ops;

    view->format = wined3d_get_format(gl_info, desc->format_id);
    view->format_flags = view->format->flags[resource->gl_type];
    if (resource->type == WINED3D_RTYPE_BUFFER)
    {
        view->sub_resource_idx = 0;
        view->buffer_offset = desc->u.buffer.start_idx;
        view->width = desc->u.buffer.count;
        view->height = 1;
        view->depth = 1;
    }
    else
    {
        struct wined3d_texture *texture = wined3d_texture_from_resource(resource);
        struct wined3d_resource *sub_resource;

        view->sub_resource_idx = desc->u.texture.layer_idx * texture->level_count + desc->u.texture.level_idx;
        sub_resource = wined3d_texture_get_sub_resource(texture, view->sub_resource_idx);

        view->buffer_offset = 0;
        view->width = sub_resource->width;
        view->height = sub_resource->height;
        view->depth = desc->u.texture.layer_count;
    }
}
예제 #10
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;
}
예제 #11
0
파일: volumetexture.c 프로젝트: dvdhoo/wine
HRESULT volumetexture_init(IWineD3DBaseTextureImpl *texture, UINT width, UINT height,
        UINT depth, 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 tmp_w, tmp_h, tmp_d;
    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;
    }

    if (!gl_info->supported[EXT_TEXTURE3D])
    {
        WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture);
        return WINED3DERR_INVALIDCALL;
    }

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

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

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

    texture->lpVtbl = &IWineD3DVolumeTexture_Vtbl;

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

    /* Is NP2 support for volumes needed? */
    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_3D;

    /* Generate all the surfaces. */
    tmp_w = width;
    tmp_h = height;
    tmp_d = depth;

    for (i = 0; i < texture->baseTexture.level_count; ++i)
    {
        IWineD3DVolume *volume;

        /* Create the volume. */
        hr = IWineD3DDeviceParent_CreateVolume(device->device_parent, parent,
                tmp_w, tmp_h, tmp_d, format_id, pool, usage, &volume);
        if (FAILED(hr))
        {
            ERR("Creating a volume for the volume texture failed, hr %#x.\n", hr);
            volumetexture_cleanup(texture);
            return hr;
        }

        /* Set its container to this texture. */
        volume_set_container((IWineD3DVolumeImpl *)volume, texture);
        texture->baseTexture.sub_resources[i] = &((IWineD3DVolumeImpl *)volume)->resource;

        /* Calculate the next mipmap level. */
        tmp_w = max(1, tmp_w >> 1);
        tmp_h = max(1, tmp_h >> 1);
        tmp_d = max(1, tmp_d >> 1);
    }

    return WINED3D_OK;
}
예제 #12
0
파일: view.c 프로젝트: Moteesh/reactos
static const struct wined3d_format *validate_resource_view(const struct wined3d_view_desc *desc,
        struct wined3d_resource *resource, BOOL mip_slice, BOOL allow_srgb_toggle)
{
    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
    const struct wined3d_format *format;

    format = wined3d_get_format(gl_info, desc->format_id, resource->usage);
    if (resource->type == WINED3D_RTYPE_BUFFER && (desc->flags & WINED3D_VIEW_BUFFER_RAW))
    {
        if (format->id != WINED3DFMT_R32_TYPELESS)
        {
            WARN("Invalid format %s for raw buffer view.\n", debug_d3dformat(format->id));
            return NULL;
        }

        format = wined3d_get_format(gl_info, WINED3DFMT_R32_UINT, resource->usage);
    }

    if (wined3d_format_is_typeless(format))
    {
        WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(format->id));
        return NULL;
    }

    if (resource->type == WINED3D_RTYPE_BUFFER)
    {
        struct wined3d_buffer *buffer = buffer_from_resource(resource);
        unsigned int buffer_size, element_size;

        if (buffer->desc.structure_byte_stride)
        {
            if (desc->format_id != WINED3DFMT_UNKNOWN)
            {
                WARN("Invalid format %s for structured buffer view.\n", debug_d3dformat(desc->format_id));
                return NULL;
            }

            format = wined3d_get_format(gl_info, WINED3DFMT_R32_UINT, resource->usage);
            element_size = buffer->desc.structure_byte_stride;
        }
        else
        {
            element_size = format->byte_count;
        }

        if (!element_size)
            return NULL;

        buffer_size = buffer->resource.size / element_size;
        if (desc->u.buffer.start_idx >= buffer_size
                || desc->u.buffer.count > buffer_size - desc->u.buffer.start_idx)
            return NULL;
    }
    else
    {
        struct wined3d_texture *texture = texture_from_resource(resource);
        unsigned int depth_or_layer_count;

        if (resource->format->id != format->id && !wined3d_format_is_typeless(resource->format)
                && (!allow_srgb_toggle || !wined3d_formats_are_srgb_variants(resource->format->id, format->id)))
        {
            WARN("Trying to create incompatible view for non typeless format %s.\n",
                    debug_d3dformat(format->id));
            return NULL;
        }

        if (mip_slice && resource->type == WINED3D_RTYPE_TEXTURE_3D)
            depth_or_layer_count = wined3d_texture_get_level_depth(texture, desc->u.texture.level_idx);
        else
            depth_or_layer_count = texture->layer_count;

        if (!desc->u.texture.level_count
                || (mip_slice && desc->u.texture.level_count != 1)
                || desc->u.texture.level_idx >= texture->level_count
                || desc->u.texture.level_count > texture->level_count - desc->u.texture.level_idx
                || !desc->u.texture.layer_count
                || desc->u.texture.layer_idx >= depth_or_layer_count
                || desc->u.texture.layer_count > depth_or_layer_count - desc->u.texture.layer_idx)
            return NULL;
    }

    return format;
}
예제 #13
0
static HRESULT swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in,
        const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags)
{
    struct wined3d_surface *back_buffer = swapchain->back_buffers[0];
    const struct wined3d_fb_state *fb = &swapchain->device->fb;
    const struct wined3d_gl_info *gl_info;
    struct wined3d_context *context;
    RECT src_rect, dst_rect;
    BOOL render_to_fbo;

    context = context_acquire(swapchain->device, back_buffer);
    if (!context->valid)
    {
        context_release(context);
        WARN("Invalid context, skipping present.\n");
        return WINED3D_OK;
    }

    gl_info = context->gl_info;

    /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */
    if (swapchain->device->bCursorVisible &&
        swapchain->device->cursorTexture &&
        !swapchain->device->hardwareCursor)
    {
        struct wined3d_surface cursor;
        RECT destRect =
        {
            swapchain->device->xScreenSpace - swapchain->device->xHotSpot,
            swapchain->device->yScreenSpace - swapchain->device->yHotSpot,
            swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot,
            swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot,
        };
        TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor);
        /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by
         * the application because we are only supposed to copy the information out. Using a fake surface
         * allows to use the Blitting engine and avoid copying the whole texture -> render target blitting code.
         */
        memset(&cursor, 0, sizeof(cursor));
        cursor.resource.ref = 1;
        cursor.resource.device = swapchain->device;
        cursor.resource.pool = WINED3D_POOL_SCRATCH;
        cursor.resource.format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
        cursor.resource.type = WINED3D_RTYPE_SURFACE;
        cursor.texture_name = swapchain->device->cursorTexture;
        cursor.texture_target = GL_TEXTURE_2D;
        cursor.texture_level = 0;
        cursor.resource.width = swapchain->device->cursorWidth;
        cursor.resource.height = swapchain->device->cursorHeight;
        /* The cursor must have pow2 sizes */
        cursor.pow2Width = cursor.resource.width;
        cursor.pow2Height = cursor.resource.height;
        /* The surface is in the texture */
        cursor.flags |= SFLAG_INTEXTURE;
        /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0,
         * which is exactly what we want :-)
         */
        if (swapchain->desc.windowed)
            MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2);
        wined3d_surface_blt(back_buffer, &destRect, &cursor, NULL, WINEDDBLT_KEYSRC,
                NULL, WINED3D_TEXF_POINT);
    }

    if (swapchain->device->logo_surface)
    {
        struct wined3d_surface *src_surface = swapchain->device->logo_surface;
        RECT rect = {0, 0, src_surface->resource.width, src_surface->resource.height};

        /* Blit the logo into the upper left corner of the drawable. */
        wined3d_surface_blt(back_buffer, &rect, src_surface, &rect, WINEDDBLT_KEYSRC,
                NULL, WINED3D_TEXF_POINT);
    }

    TRACE("Presenting HDC %p.\n", context->hdc);

    render_to_fbo = swapchain->render_to_fbo;

    if (src_rect_in)
    {
        src_rect = *src_rect_in;
        if (!render_to_fbo && (src_rect.left || src_rect.top
                || src_rect.right != swapchain->desc.backbuffer_width
                || src_rect.bottom != swapchain->desc.backbuffer_height))
        {
            render_to_fbo = TRUE;
        }
    }
    else
    {
        src_rect.left = 0;
        src_rect.top = 0;
        src_rect.right = swapchain->desc.backbuffer_width;
        src_rect.bottom = swapchain->desc.backbuffer_height;
    }

    if (dst_rect_in)
        dst_rect = *dst_rect_in;
    else
        GetClientRect(swapchain->win_handle, &dst_rect);

    if (!render_to_fbo && (dst_rect.left || dst_rect.top
            || dst_rect.right != swapchain->desc.backbuffer_width
            || dst_rect.bottom != swapchain->desc.backbuffer_height))
        render_to_fbo = TRUE;

    /* Rendering to a window of different size, presenting partial rectangles,
     * or rendering to a different window needs help from FBO_blit or a textured
     * draw. Render the swapchain to a FBO in the future.
     *
     * Note that FBO_blit from the backbuffer to the frontbuffer cannot solve
     * all these issues - this fails if the window is smaller than the backbuffer.
     */
    if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO)
    {
        surface_load_location(back_buffer, SFLAG_INTEXTURE, NULL);
        surface_modify_location(back_buffer, SFLAG_INDRAWABLE, FALSE);
        swapchain->render_to_fbo = TRUE;
        swapchain_update_draw_bindings(swapchain);
    }
    else
    {
        surface_load_location(back_buffer, back_buffer->draw_binding, NULL);
    }

    if (swapchain->render_to_fbo)
    {
        /* This codepath should only be hit with the COPY swapeffect. Otherwise a backbuffer-
         * window size mismatch is impossible(fullscreen) and src and dst rectangles are
         * not allowed(they need the COPY swapeffect)
         *
         * The DISCARD swap effect is ok as well since any backbuffer content is allowed after
         * the swap. */
        if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP)
            FIXME("Render-to-fbo with WINED3D_SWAP_EFFECT_FLIP\n");

        swapchain_blit(swapchain, context, &src_rect, &dst_rect);
    }

    if (swapchain->num_contexts > 1)
        wglFinish();
    SwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */

    TRACE("SwapBuffers called, Starting new frame\n");
    /* FPS support */
    if (TRACE_ON(fps))
    {
        DWORD time = GetTickCount();
        ++swapchain->frames;

        /* every 1.5 seconds */
        if (time - swapchain->prev_time > 1500)
        {
            TRACE_(fps)("%p @ approx %.2ffps\n",
                    swapchain, 1000.0 * swapchain->frames / (time - swapchain->prev_time));
            swapchain->prev_time = time;
            swapchain->frames = 0;
        }
    }

    /* This is disabled, but the code left in for debug purposes.
     *
     * Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip,
     * we can clear it with some ugly color to make bad drawing visible and ease debugging.
     * The Debug runtime does the same on Windows. However, a few games do not redraw the
     * screen properly, like Max Payne 2, which leaves a few pixels undefined.
     *
     * Tests show that the content of the back buffer after a discard flip is indeed not
     * reliable, so no game can depend on the exact content. However, it resembles the
     * old contents in some way, for example by showing fragments at other locations. In
     * general, the color theme is still intact. So Max payne, which draws rather dark scenes
     * gets a dark background image. If we clear it with a bright ugly color, the game's
     * bug shows up much more than it does on Windows, and the players see single pixels
     * with wrong colors.
     * (The Max Payne bug has been confirmed on Windows with the debug runtime) */
    if (FALSE && swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_DISCARD)
    {
        static const struct wined3d_color cyan = {0.0f, 1.0f, 1.0f, 1.0f};

        TRACE("Clearing the color buffer with cyan color\n");

        wined3d_device_clear(swapchain->device, 0, NULL,
                WINED3DCLEAR_TARGET, &cyan, 1.0f, 0);
    }

    if (!swapchain->render_to_fbo && ((swapchain->front_buffer->flags & SFLAG_INSYSMEM)
            || (back_buffer->flags & SFLAG_INSYSMEM)))
    {
        /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying
         * Doesn't work with render_to_fbo because we're not flipping
         */
        struct wined3d_surface *front = swapchain->front_buffer;

        if (front->resource.size == back_buffer->resource.size)
        {
            DWORD fbflags;
            flip_surface(front, back_buffer);

            /* Tell the front buffer surface that is has been modified. However,
             * the other locations were preserved during that, so keep the flags.
             * This serves to update the emulated overlay, if any. */
            fbflags = front->flags;
            surface_modify_location(front, SFLAG_INDRAWABLE, TRUE);
            front->flags = fbflags;
        }
        else
        {
            surface_modify_location(front, SFLAG_INDRAWABLE, TRUE);
            surface_modify_location(back_buffer, SFLAG_INDRAWABLE, TRUE);
        }
    }
    else
    {
        surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE);
        /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM
         * and INTEXTURE copies can keep their old content if they have any defined content.
         * If the swapeffect is COPY, the content remains the same. If it is FLIP however,
         * the texture / sysmem copy needs to be reloaded from the drawable
         */
        if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP)
            surface_modify_location(back_buffer, back_buffer->draw_binding, TRUE);
    }

    if (fb->depth_stencil)
    {
        if (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
                || fb->depth_stencil->flags & SFLAG_DISCARD)
        {
            surface_modify_ds_location(fb->depth_stencil, SFLAG_DISCARDED,
                    fb->depth_stencil->resource.width,
                    fb->depth_stencil->resource.height);
            if (fb->depth_stencil == swapchain->device->onscreen_depth_stencil)
            {
                wined3d_surface_decref(swapchain->device->onscreen_depth_stencil);
                swapchain->device->onscreen_depth_stencil = NULL;
            }
        }
    }

    context_release(context);

    TRACE("returning\n");
    return WINED3D_OK;
}
예제 #14
0
HRESULT vertexdeclaration_init(IWineD3DVertexDeclarationImpl *declaration, IWineD3DDeviceImpl *device,
        const WINED3DVERTEXELEMENT *elements, UINT element_count,
        void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
    WORD preloaded = 0; /* MAX_STREAMS, 16 */
    unsigned int i;

    if (TRACE_ON(d3d_decl))
    {
        for (i = 0; i < element_count; ++i)
        {
            dump_wined3dvertexelement(elements + i);
        }
    }

    declaration->lpVtbl = &IWineD3DVertexDeclaration_Vtbl;
    declaration->ref = 1;
    declaration->parent = parent;
    declaration->parent_ops = parent_ops;
    declaration->device = device;
    declaration->elements = HeapAlloc(GetProcessHeap(), 0, sizeof(*declaration->elements) * element_count);
    if (!declaration->elements)
    {
        ERR("Failed to allocate elements memory.\n");
        return E_OUTOFMEMORY;
    }
    declaration->element_count = element_count;

    /* Do some static analysis on the elements to make reading the
     * declaration more comfortable for the drawing code. */
    for (i = 0; i < element_count; ++i)
    {
        struct wined3d_vertex_declaration_element *e = &declaration->elements[i];

        e->format = wined3d_get_format(gl_info, elements[i].format);
        e->ffp_valid = declaration_element_valid_ffp(&elements[i]);
        e->input_slot = elements[i].input_slot;
        e->offset = elements[i].offset;
        e->output_slot = elements[i].output_slot;
        e->method = elements[i].method;
        e->usage = elements[i].usage;
        e->usage_idx = elements[i].usage_idx;

        if (e->usage == WINED3DDECLUSAGE_POSITIONT) declaration->position_transformed = TRUE;

        /* Find the streams used in the declaration. The vertex buffers have
         * to be loaded when drawing, but filter tesselation pseudo streams. */
        if (e->input_slot >= MAX_STREAMS) continue;

        if (!e->format->gl_vtx_format)
        {
            FIXME("The application tries to use an unsupported format (%s), returning E_FAIL.\n",
                    debug_d3dformat(elements[i].format));
            HeapFree(GetProcessHeap(), 0, declaration->elements);
            return E_FAIL;
        }

        if (e->offset & 0x3)
        {
            WARN("Declaration element %u is not 4 byte aligned(%u), returning E_FAIL.\n", i, e->offset);
            HeapFree(GetProcessHeap(), 0, declaration->elements);
            return E_FAIL;
        }

        if (!(preloaded & (1 << e->input_slot)))
        {
            declaration->streams[declaration->num_streams] = e->input_slot;
            ++declaration->num_streams;
            preloaded |= 1 << e->input_slot;
        }

        if (elements[i].format == WINED3DFMT_R16G16_FLOAT || elements[i].format == WINED3DFMT_R16G16B16A16_FLOAT)
        {
            if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX]) declaration->half_float_conv_needed = TRUE;
        }
    }

    return WINED3D_OK;
}
예제 #15
0
파일: view.c 프로젝트: vindo-app/wine
static HRESULT wined3d_shader_resource_view_init(struct wined3d_shader_resource_view *view,
        const struct wined3d_shader_resource_view_desc *desc, struct wined3d_resource *resource,
        void *parent, const struct wined3d_parent_ops *parent_ops)
{
    static const struct
    {
        GLenum texture_target;
        unsigned int view_flags;
        GLenum view_target;
    }
    view_types[] =
    {
        {GL_TEXTURE_1D,       0,                          GL_TEXTURE_1D},
        {GL_TEXTURE_1D,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
        {GL_TEXTURE_1D_ARRAY, 0,                          GL_TEXTURE_1D},
        {GL_TEXTURE_1D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_1D_ARRAY},
        {GL_TEXTURE_2D,       0,                          GL_TEXTURE_2D},
        {GL_TEXTURE_2D,       WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
        {GL_TEXTURE_2D_ARRAY, 0,                          GL_TEXTURE_2D},
        {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_ARRAY, GL_TEXTURE_2D_ARRAY},
        {GL_TEXTURE_2D_ARRAY, WINED3D_VIEW_TEXTURE_CUBE,  GL_TEXTURE_CUBE_MAP},
        {GL_TEXTURE_3D,       0,                          GL_TEXTURE_3D},
    };

    const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
    const struct wined3d_format *view_format;

    view_format = wined3d_get_format(gl_info, desc->format_id);
    if (wined3d_format_is_typeless(view_format))
    {
        WARN("Trying to create view for typeless format %s.\n", debug_d3dformat(view_format->id));
        return E_INVALIDARG;
    }

    view->refcount = 1;
    view->parent = parent;
    view->parent_ops = parent_ops;

    view->target = GL_NONE;
    view->object = 0;

    if (resource->type == WINED3D_RTYPE_BUFFER)
    {
        FIXME("Buffer shader resource views not supported.\n");
    }
    else
    {
        struct wined3d_texture *texture = texture_from_resource(resource);
        unsigned int i;

        if (!desc->u.texture.level_count
                || desc->u.texture.level_idx >= texture->level_count
                || desc->u.texture.level_count > texture->level_count - desc->u.texture.level_idx
                || !desc->u.texture.layer_count
                || desc->u.texture.layer_idx >= texture->layer_count
                || desc->u.texture.layer_count > texture->layer_count - desc->u.texture.layer_idx)
            return E_INVALIDARG;

        view->target = texture->target;
        for (i = 0; i < ARRAY_SIZE(view_types); ++i)
        {
            if (view_types[i].texture_target == texture->target && view_types[i].view_flags == desc->flags)
            {
                view->target = view_types[i].view_target;
                break;
            }
        }
        if (i == ARRAY_SIZE(view_types))
            FIXME("Unhandled view flags %#x for texture target %#x.\n", desc->flags, texture->target);

        if (resource->format->id == view_format->id && texture->target == view->target
                && !desc->u.texture.level_idx && desc->u.texture.level_count == texture->level_count
                && !desc->u.texture.layer_idx && desc->u.texture.layer_count == texture->layer_count)
        {
            TRACE("Creating identity shader resource view.\n");
        }
        else if (texture->swapchain && texture->swapchain->desc.backbuffer_count > 1)
        {
            FIXME("Swapchain shader resource views not supported.\n");
        }
        else if (resource->format->typeless_id == view_format->typeless_id
                && resource->format->gl_view_class == view_format->gl_view_class)
        {
            wined3d_shader_resource_view_create_texture_view(view, desc, texture, view_format);
        }
        else
        {
            FIXME("Shader resource view not supported, resource format %s, view format %s.\n",
                    debug_d3dformat(resource->format->id), debug_d3dformat(view_format->id));
        }
    }
    wined3d_resource_incref(view->resource = resource);

    return WINED3D_OK;
}
예제 #16
0
static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
        struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_adapter *adapter = device->adapter;
    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
    struct wined3d_resource_desc surface_desc;
    BOOL displaymode_set = FALSE;
    RECT client_rect;
    HWND window;
    HRESULT hr;
    UINT i;

    if (desc->backbuffer_count > WINED3DPRESENT_BACK_BUFFER_MAX)
    {
        FIXME("The application requested %u back buffers, this is not supported.\n",
                desc->backbuffer_count);
        return WINED3DERR_INVALIDCALL;
    }

    if (desc->backbuffer_count > 1)
    {
        FIXME("The application requested more than one back buffer, this is not properly supported.\n"
                "Please configure the application to use double buffering (1 back buffer) if possible.\n");
    }

    if (device->wined3d->flags & WINED3D_NO3D)
        swapchain->swapchain_ops = &swapchain_gdi_ops;
    else
        swapchain->swapchain_ops = &swapchain_gl_ops;

    window = desc->device_window ? desc->device_window : device->create_parms.focus_window;

    swapchain->device = device;
    swapchain->parent = parent;
    swapchain->parent_ops = parent_ops;
    swapchain->ref = 1;
    swapchain->win_handle = window;
    swapchain->device_window = window;

    if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d,
            adapter->ordinal, &swapchain->original_mode, NULL)))
    {
        ERR("Failed to get current display mode, hr %#x.\n", hr);
        goto err;
    }

    GetClientRect(window, &client_rect);
    if (desc->windowed
            && (!desc->backbuffer_width || !desc->backbuffer_height
            || desc->backbuffer_format == WINED3DFMT_UNKNOWN))
    {

        if (!desc->backbuffer_width)
        {
            desc->backbuffer_width = client_rect.right;
            TRACE("Updating width to %u.\n", desc->backbuffer_width);
        }

        if (!desc->backbuffer_height)
        {
            desc->backbuffer_height = client_rect.bottom;
            TRACE("Updating height to %u.\n", desc->backbuffer_height);
        }

        if (desc->backbuffer_format == WINED3DFMT_UNKNOWN)
        {
            desc->backbuffer_format = swapchain->original_mode.format_id;
            TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->original_mode.format_id));
        }
    }
    swapchain->desc = *desc;
    swapchain_update_render_to_fbo(swapchain);
    swapchain_update_surface(swapchain);

    TRACE("Creating front buffer.\n");

    surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
    surface_desc.format = swapchain->desc.backbuffer_format;
    surface_desc.multisample_type = swapchain->desc.multisample_type;
    surface_desc.multisample_quality = swapchain->desc.multisample_quality;
    surface_desc.usage = 0;
    surface_desc.pool = WINED3D_POOL_DEFAULT;
    surface_desc.width = swapchain->desc.backbuffer_width;
    surface_desc.height = swapchain->desc.backbuffer_height;
    surface_desc.depth = 1;
    surface_desc.size = 0;

    if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
            parent, &surface_desc, &swapchain->front_buffer)))
    {
        WARN("Failed to create front buffer, hr %#x.\n", hr);
        goto err;
    }

    surface_set_swapchain(swapchain->front_buffer, swapchain);
    if (!(device->wined3d->flags & WINED3D_NO3D))
    {
        surface_validate_location(swapchain->front_buffer, WINED3D_LOCATION_DRAWABLE);
        surface_invalidate_location(swapchain->front_buffer, ~WINED3D_LOCATION_DRAWABLE);
    }

    /* MSDN says we're only allowed a single fullscreen swapchain per device,
     * so we should really check to see if there is a fullscreen swapchain
     * already. Does a single head count as full screen? */

    if (!desc->windowed)
    {
        struct wined3d_display_mode mode;

        /* Change the display settings */
        mode.width = desc->backbuffer_width;
        mode.height = desc->backbuffer_height;
        mode.format_id = desc->backbuffer_format;
        mode.refresh_rate = desc->refresh_rate;
        mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;

        if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, adapter->ordinal, &mode)))
        {
            WARN("Failed to set display mode, hr %#x.\n", hr);
            goto err;
        }
        displaymode_set = TRUE;
    }

    if (!(device->wined3d->flags & WINED3D_NO3D))
    {
        static const enum wined3d_format_id formats[] =
        {
            WINED3DFMT_D24_UNORM_S8_UINT,
            WINED3DFMT_D32_UNORM,
            WINED3DFMT_R24_UNORM_X8_TYPELESS,
            WINED3DFMT_D16_UNORM,
            WINED3DFMT_S1_UINT_D15_UNORM
        };

        swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
        if (!swapchain->context)
        {
            ERR("Failed to create the context array.\n");
            hr = E_OUTOFMEMORY;
            goto err;
        }
        swapchain->num_contexts = 1;

        /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
         * You are able to add a depth + stencil surface at a later stage when you need it.
         * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
         * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
         * context, need torecreate shaders, textures and other resources.
         *
         * The context manager already takes care of the state problem and for the other tasks code from Reset
         * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
         * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
         * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
         * issue needs to be fixed. */
        for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
        {
            swapchain->ds_format = wined3d_get_format(gl_info, formats[i]);
            swapchain->context[0] = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format);
            if (swapchain->context[0]) break;
            TRACE("Depth stencil format %s is not supported, trying next format\n",
                  debug_d3dformat(formats[i]));
        }

        if (!swapchain->context[0])
        {
            WARN("Failed to create context.\n");
            hr = WINED3DERR_NOTAVAILABLE;
            goto err;
        }

        if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
                && (!desc->enable_auto_depth_stencil
                || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id))
        {
            FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n");
        }
        context_release(swapchain->context[0]);
    }

    if (swapchain->desc.backbuffer_count > 0)
    {
        swapchain->back_buffers = HeapAlloc(GetProcessHeap(), 0,
                sizeof(*swapchain->back_buffers) * swapchain->desc.backbuffer_count);
        if (!swapchain->back_buffers)
        {
            ERR("Failed to allocate backbuffer array memory.\n");
            hr = E_OUTOFMEMORY;
            goto err;
        }

        surface_desc.usage |= WINED3DUSAGE_RENDERTARGET;
        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
        {
            TRACE("Creating back buffer %u.\n", i);
            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
                    parent, &surface_desc, &swapchain->back_buffers[i])))
            {
                WARN("Failed to create back buffer %u, hr %#x.\n", i, hr);
                swapchain->desc.backbuffer_count = i;
                goto err;
            }
            surface_set_swapchain(swapchain->back_buffers[i], swapchain);
        }
    }

    /* Swapchains share the depth/stencil buffer, so only create a single depthstencil surface. */
    if (desc->enable_auto_depth_stencil && !(device->wined3d->flags & WINED3D_NO3D))
    {
        TRACE("Creating depth/stencil buffer.\n");
        if (!device->auto_depth_stencil)
        {
            surface_desc.format = swapchain->desc.auto_depth_stencil_format;
            surface_desc.usage = WINED3DUSAGE_DEPTHSTENCIL;

            if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
                    device->device_parent, &surface_desc, &device->auto_depth_stencil)))
            {
                WARN("Failed to create the auto depth stencil, hr %#x.\n", hr);
                goto err;
            }
        }
    }

    wined3d_swapchain_get_gamma_ramp(swapchain, &swapchain->orig_gamma);

    return WINED3D_OK;

err:
    if (displaymode_set)
    {
        if (FAILED(wined3d_set_adapter_display_mode(device->wined3d,
                adapter->ordinal, &swapchain->original_mode)))
            ERR("Failed to restore display mode.\n");
        ClipCursor(NULL);
    }

    if (swapchain->back_buffers)
    {
        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
        {
            if (swapchain->back_buffers[i])
            {
                surface_set_swapchain(swapchain->back_buffers[i], NULL);
                wined3d_surface_decref(swapchain->back_buffers[i]);
            }
        }
        HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
    }

    if (swapchain->context)
    {
        if (swapchain->context[0])
        {
            context_release(swapchain->context[0]);
            context_destroy(device, swapchain->context[0]);
            swapchain->num_contexts = 0;
        }
        HeapFree(GetProcessHeap(), 0, swapchain->context);
    }

    if (swapchain->front_buffer)
    {
        surface_set_swapchain(swapchain->front_buffer, NULL);
        wined3d_surface_decref(swapchain->front_buffer);
    }

    if (swapchain->surface && !GL_EXTCALL(wglDestroySurfaceWINE(swapchain->surface)))
        ERR("wglDestroySurfaceWINE failed to destroy surface %p\n", swapchain->surface);

    return hr;
}
예제 #17
0
파일: texture.c 프로젝트: pombredanne/wine
static HRESULT cubetexture_init(struct wined3d_texture *texture, UINT edge_length, UINT levels,
                                struct wined3d_device *device, DWORD usage, enum wined3d_format_id format_id, enum wined3d_pool 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_edge_length;
    unsigned int i, j;
    UINT tmp_w;
    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;
    }

    if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && pool != WINED3D_POOL_SCRATCH)
    {
        WARN("(%p) : Tried to create not supported cube texture.\n", texture);
        return WINED3DERR_INVALIDCALL;
    }

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

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

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

    hr = wined3d_texture_init(texture, &texture2d_ops, 6, levels,
                              WINED3D_RTYPE_CUBE_TEXTURE, device, usage, format, pool,
                              parent, parent_ops, &texture2d_resource_ops);
    if (FAILED(hr))
    {
        WARN("Failed to initialize texture, returning %#x\n", hr);
        return hr;
    }

    /* Find the nearest pow2 match. */
    pow2_edge_length = 1;
    while (pow2_edge_length < edge_length) pow2_edge_length <<= 1;

    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || (edge_length == pow2_edge_length))
    {
        /* Precalculated scaling for 'faked' non power of two texture coords. */
        texture->pow2_matrix[0] = 1.0f;
        texture->pow2_matrix[5] = 1.0f;
        texture->pow2_matrix[10] = 1.0f;
        texture->pow2_matrix[15] = 1.0f;
    }
    else
    {
        /* Precalculated scaling for 'faked' non power of two texture coords. */
        texture->pow2_matrix[0] = ((float)edge_length) / ((float)pow2_edge_length);
        texture->pow2_matrix[5] = ((float)edge_length) / ((float)pow2_edge_length);
        texture->pow2_matrix[10] = ((float)edge_length) / ((float)pow2_edge_length);
        texture->pow2_matrix[15] = 1.0f;
        texture->flags &= ~WINED3D_TEXTURE_POW2_MAT_IDENT;
    }
    texture->target = GL_TEXTURE_CUBE_MAP_ARB;

    /* Generate all the surfaces. */
    tmp_w = edge_length;
    for (i = 0; i < texture->level_count; ++i)
    {
        /* Create the 6 faces. */
        for (j = 0; j < 6; ++j)
        {
            static const GLenum cube_targets[6] =
            {
                GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
                GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
                GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
                GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
                GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
                GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
            };
            UINT idx = j * texture->level_count + i;
            struct wined3d_surface *surface;

            if (FAILED(hr = device->device_parent->ops->create_texture_surface(device->device_parent,
                            parent, tmp_w, tmp_w, format_id, usage, pool, idx, &surface)))
            {
                FIXME("(%p) Failed to create surface, hr %#x.\n", texture, hr);
                wined3d_texture_cleanup(texture);
                return hr;
            }

            surface_set_container(surface, WINED3D_CONTAINER_TEXTURE, texture);
            surface_set_texture_target(surface, cube_targets[j], i);
            texture->sub_resources[idx] = &surface->resource;
            TRACE("Created surface level %u @ %p.\n", i, surface);
        }
        tmp_w = max(1, tmp_w >> 1);
    }

    return WINED3D_OK;
}
예제 #18
0
파일: swapchain.c 프로젝트: Dimillian/wine
HRESULT swapchain_create_context_cs(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
{
    const struct wined3d_adapter *adapter = device->adapter;
    unsigned int i;
    static const enum wined3d_format_id formats[] =
    {
        WINED3DFMT_D24_UNORM_S8_UINT,
        WINED3DFMT_D32_UNORM,
        WINED3DFMT_R24_UNORM_X8_TYPELESS,
        WINED3DFMT_D16_UNORM,
        WINED3DFMT_S1_UINT_D15_UNORM
    };

    const struct wined3d_gl_info *gl_info = &adapter->gl_info;

    swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
    if (!swapchain->context)
    {
        ERR("Failed to create the context array.\n");
        return E_OUTOFMEMORY;
    }
    swapchain->num_contexts = 1;

    /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
     * You are able to add a depth + stencil surface at a later stage when you need it.
     * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
     * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
     * context, need torecreate shaders, textures and other resources.
     *
     * The context manager already takes care of the state problem and for the other tasks code from Reset
     * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
     * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
     * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
     * issue needs to be fixed. */
    for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
    {
        swapchain->ds_format = wined3d_get_format(gl_info, formats[i]);
        swapchain->context[0] = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format);
        if (swapchain->context[0]) break;
        TRACE("Depth stencil format %s is not supported, trying next format\n",
                debug_d3dformat(formats[i]));
    }

    if (!swapchain->context[0])
    {
        WARN("Failed to create context.\n");
        HeapFree(GetProcessHeap(), 0, swapchain->context);
        swapchain->context = NULL;
        return WINED3DERR_NOTAVAILABLE;
    }

    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
            && (!swapchain->desc.enable_auto_depth_stencil
            || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id))
    {
        FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n");
    }
    context_release(swapchain->context[0]);

    return WINED3D_OK;
}
예제 #19
0
/* Do not call while under the GL lock. */
static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, enum wined3d_surface_type surface_type,
        struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
        void *parent, const struct wined3d_parent_ops *parent_ops)
{
    const struct wined3d_adapter *adapter = device->adapter;
    const struct wined3d_format *format;
    struct wined3d_display_mode mode;
    BOOL displaymode_set = FALSE;
    RECT client_rect;
    HWND window;
    HRESULT hr;
    UINT i;

    if (desc->backbuffer_count > WINED3DPRESENT_BACK_BUFFER_MAX)
    {
        FIXME("The application requested %u back buffers, this is not supported.\n",
                desc->backbuffer_count);
        return WINED3DERR_INVALIDCALL;
    }

    if (desc->backbuffer_count > 1)
    {
        FIXME("The application requested more than one back buffer, this is not properly supported.\n"
                "Please configure the application to use double buffering (1 back buffer) if possible.\n");
    }

    switch (surface_type)
    {
        case WINED3D_SURFACE_TYPE_GDI:
            swapchain->swapchain_ops = &swapchain_gdi_ops;
            break;

        case WINED3D_SURFACE_TYPE_OPENGL:
            swapchain->swapchain_ops = &swapchain_gl_ops;
            break;

        default:
            ERR("Invalid surface type %#x.\n", surface_type);
            return WINED3DERR_INVALIDCALL;
    }

    window = desc->device_window ? desc->device_window : device->create_parms.focus_window;

    swapchain->device = device;
    swapchain->parent = parent;
    swapchain->parent_ops = parent_ops;
    swapchain->ref = 1;
    swapchain->win_handle = window;
    swapchain->device_window = window;

    wined3d_get_adapter_display_mode(device->wined3d, adapter->ordinal, &mode);
    swapchain->orig_width = mode.width;
    swapchain->orig_height = mode.height;
    swapchain->orig_fmt = mode.format_id;
    format = wined3d_get_format(&adapter->gl_info, mode.format_id);

    GetClientRect(window, &client_rect);
    if (desc->windowed
            && (!desc->backbuffer_width || !desc->backbuffer_height
            || desc->backbuffer_format == WINED3DFMT_UNKNOWN))
    {

        if (!desc->backbuffer_width)
        {
            desc->backbuffer_width = client_rect.right;
            TRACE("Updating width to %u.\n", desc->backbuffer_width);
        }

        if (!desc->backbuffer_height)
        {
            desc->backbuffer_height = client_rect.bottom;
            TRACE("Updating height to %u.\n", desc->backbuffer_height);
        }

        if (desc->backbuffer_format == WINED3DFMT_UNKNOWN)
        {
            desc->backbuffer_format = swapchain->orig_fmt;
            TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->orig_fmt));
        }
    }
    swapchain->desc = *desc;
    swapchain_update_render_to_fbo(swapchain);

    TRACE("Creating front buffer.\n");
    hr = device->device_parent->ops->create_rendertarget(device->device_parent, parent,
            swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height,
            swapchain->desc.backbuffer_format, swapchain->desc.multisample_type,
            swapchain->desc.multisample_quality, TRUE /* Lockable */,
            &swapchain->front_buffer);
    if (FAILED(hr))
    {
        WARN("Failed to create front buffer, hr %#x.\n", hr);
        goto err;
    }

    surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_SWAPCHAIN, swapchain);
    if (surface_type == WINED3D_SURFACE_TYPE_OPENGL)
        surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE);

    /* MSDN says we're only allowed a single fullscreen swapchain per device,
     * so we should really check to see if there is a fullscreen swapchain
     * already. Does a single head count as full screen? */

    if (!desc->windowed)
    {
        struct wined3d_display_mode mode;

        /* Change the display settings */
        mode.width = desc->backbuffer_width;
        mode.height = desc->backbuffer_height;
        mode.format_id = desc->backbuffer_format;
        mode.refresh_rate = desc->refresh_rate;

        hr = wined3d_device_set_display_mode(device, 0, &mode);
        if (FAILED(hr))
        {
            WARN("Failed to set display mode, hr %#x.\n", hr);
            goto err;
        }
        displaymode_set = TRUE;
    }

    if (surface_type == WINED3D_SURFACE_TYPE_OPENGL)
    {
        static const enum wined3d_format_id formats[] =
        {
            WINED3DFMT_D24_UNORM_S8_UINT,
            WINED3DFMT_D32_UNORM,
            WINED3DFMT_R24_UNORM_X8_TYPELESS,
            WINED3DFMT_D16_UNORM,
            WINED3DFMT_S1_UINT_D15_UNORM
        };

        const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;

        swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
        if (!swapchain->context)
        {
            ERR("Failed to create the context array.\n");
            hr = E_OUTOFMEMORY;
            goto err;
        }
        swapchain->num_contexts = 1;

        /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
         * You are able to add a depth + stencil surface at a later stage when you need it.
         * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
         * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
         * context, need torecreate shaders, textures and other resources.
         *
         * The context manager already takes care of the state problem and for the other tasks code from Reset
         * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
         * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
         * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
         * issue needs to be fixed. */
        for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
        {
            swapchain->ds_format = wined3d_get_format(gl_info, formats[i]);
            swapchain->context[0] = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format);
            if (swapchain->context[0]) break;
            TRACE("Depth stencil format %s is not supported, trying next format\n",
                  debug_d3dformat(formats[i]));
        }

        if (!swapchain->context[0])
        {
            WARN("Failed to create context.\n");
            hr = WINED3DERR_NOTAVAILABLE;
            goto err;
        }

        if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
                && (!desc->enable_auto_depth_stencil
                || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id))
        {
            FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n");
        }
        context_release(swapchain->context[0]);
    }

    if (swapchain->desc.backbuffer_count > 0)
    {
        swapchain->back_buffers = HeapAlloc(GetProcessHeap(), 0,
                sizeof(*swapchain->back_buffers) * swapchain->desc.backbuffer_count);
        if (!swapchain->back_buffers)
        {
            ERR("Failed to allocate backbuffer array memory.\n");
            hr = E_OUTOFMEMORY;
            goto err;
        }

        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
        {
            TRACE("Creating back buffer %u.\n", i);
            hr = device->device_parent->ops->create_rendertarget(device->device_parent, parent,
                    swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height,
                    swapchain->desc.backbuffer_format, swapchain->desc.multisample_type,
                    swapchain->desc.multisample_quality, TRUE /* Lockable */,
                    &swapchain->back_buffers[i]);
            if (FAILED(hr))
            {
                WARN("Failed to create back buffer %u, hr %#x.\n", i, hr);
                goto err;
            }

            surface_set_container(swapchain->back_buffers[i], WINED3D_CONTAINER_SWAPCHAIN, swapchain);
        }
    }

    /* Swapchains share the depth/stencil buffer, so only create a single depthstencil surface. */
    if (desc->enable_auto_depth_stencil && surface_type == WINED3D_SURFACE_TYPE_OPENGL)
    {
        TRACE("Creating depth/stencil buffer.\n");
        if (!device->auto_depth_stencil)
        {
            hr = device->device_parent->ops->create_depth_stencil(device->device_parent,
                    swapchain->desc.backbuffer_width, swapchain->desc.backbuffer_height,
                    swapchain->desc.auto_depth_stencil_format, swapchain->desc.multisample_type,
                    swapchain->desc.multisample_quality, FALSE /* FIXME: Discard */,
                    &device->auto_depth_stencil);
            if (FAILED(hr))
            {
                WARN("Failed to create the auto depth stencil, hr %#x.\n", hr);
                goto err;
            }

            surface_set_container(device->auto_depth_stencil, WINED3D_CONTAINER_NONE, NULL);
        }
    }

    wined3d_swapchain_get_gamma_ramp(swapchain, &swapchain->orig_gamma);

    return WINED3D_OK;

err:
    if (displaymode_set)
    {
        DEVMODEW devmode;

        ClipCursor(NULL);

        /* Change the display settings */
        memset(&devmode, 0, sizeof(devmode));
        devmode.dmSize = sizeof(devmode);
        devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
        devmode.dmBitsPerPel = format->byte_count * CHAR_BIT;
        devmode.dmPelsWidth = swapchain->orig_width;
        devmode.dmPelsHeight = swapchain->orig_height;
        ChangeDisplaySettingsExW(adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL);
    }

    if (swapchain->back_buffers)
    {
        for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
        {
            if (swapchain->back_buffers[i])
            {
                surface_set_container(swapchain->back_buffers[i], WINED3D_CONTAINER_NONE, NULL);
                wined3d_surface_decref(swapchain->back_buffers[i]);
            }
        }
        HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
    }

    if (swapchain->context)
    {
        if (swapchain->context[0])
        {
            context_release(swapchain->context[0]);
            context_destroy(device, swapchain->context[0]);
            swapchain->num_contexts = 0;
        }
        HeapFree(GetProcessHeap(), 0, swapchain->context);
    }

    if (swapchain->front_buffer)
    {
        surface_set_container(swapchain->front_buffer, WINED3D_CONTAINER_NONE, NULL);
        wined3d_surface_decref(swapchain->front_buffer);
    }

    return hr;
}
예제 #20
0
파일: texture.c 프로젝트: alexwgo/wine
static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struct wined3d_texture_ops *texture_ops,
        UINT layer_count, UINT level_count, const struct wined3d_resource_desc *desc, struct wined3d_device *device,
        void *parent, const struct wined3d_parent_ops *parent_ops, const struct wined3d_resource_ops *resource_ops)
{
    const struct wined3d_format *format = wined3d_get_format(&device->adapter->gl_info, desc->format);
    HRESULT hr;

    TRACE("texture %p, texture_ops %p, layer_count %u, level_count %u, resource_type %s, format %s, "
            "multisample_type %#x, multisample_quality %#x, usage %s, pool %s, width %u, height %u, depth %u, "
            "device %p, parent %p, parent_ops %p, resource_ops %p.\n",
            texture, texture_ops, layer_count, level_count, debug_d3dresourcetype(desc->resource_type),
            debug_d3dformat(desc->format), desc->multisample_type, desc->multisample_quality,
            debug_d3dusage(desc->usage), debug_d3dpool(desc->pool), desc->width, desc->height, desc->depth,
            device, parent, parent_ops, resource_ops);

    if ((format->flags & (WINED3DFMT_FLAG_BLOCKS | WINED3DFMT_FLAG_BLOCKS_NO_VERIFY)) == WINED3DFMT_FLAG_BLOCKS)
    {
        UINT width_mask = format->block_width - 1;
        UINT height_mask = format->block_height - 1;
        if (desc->width & width_mask || desc->height & height_mask)
            return WINED3DERR_INVALIDCALL;
    }

    if (FAILED(hr = resource_init(&texture->resource, device, desc->resource_type, format,
            desc->multisample_type, desc->multisample_quality, desc->usage, desc->pool,
            desc->width, desc->height, desc->depth, 0, parent, parent_ops, resource_ops)))
    {
        static unsigned int once;

        if ((desc->format == WINED3DFMT_DXT1 || desc->format == WINED3DFMT_DXT2 || desc->format == WINED3DFMT_DXT3
                || desc->format == WINED3DFMT_DXT4 || desc->format == WINED3DFMT_DXT5)
                && !(format->flags & WINED3DFMT_FLAG_TEXTURE) && !once++)
            ERR_(winediag)("The application tried to create a DXTn texture, but the driver does not support them.\n");

        WARN("Failed to initialize resource, returning %#x\n", hr);
        return hr;
    }
    wined3d_resource_update_draw_binding(&texture->resource);

    texture->texture_ops = texture_ops;
    texture->sub_resources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
            level_count * layer_count * sizeof(*texture->sub_resources));
    if (!texture->sub_resources)
    {
        ERR("Failed to allocate sub-resource array.\n");
        resource_cleanup(&texture->resource);
        return E_OUTOFMEMORY;
    }

    texture->layer_count = layer_count;
    texture->level_count = level_count;
    texture->filter_type = (desc->usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3D_TEXF_LINEAR : WINED3D_TEXF_NONE;
    texture->lod = 0;
    texture->flags = WINED3D_TEXTURE_POW2_MAT_IDENT;

    if (texture->resource.format->flags & WINED3DFMT_FLAG_FILTERING)
    {
        texture->min_mip_lookup = minMipLookup;
        texture->mag_lookup = magLookup;
    }
    else
    {
        texture->min_mip_lookup = minMipLookup_noFilter;
        texture->mag_lookup = magLookup_noFilter;
    }

    return WINED3D_OK;
}