texture.c 15.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Copyright 2009 Henri Verbeet for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 */

#include "config.h"
#include "wine/port.h"

#include "d3d10core_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d10core);

27 28 29 30 31
static inline struct d3d10_texture2d *impl_from_ID3D10Texture2D(ID3D10Texture2D *iface)
{
    return CONTAINING_RECORD(iface, struct d3d10_texture2d, ID3D10Texture2D_iface);
}

32 33 34 35
/* IUnknown methods */

static HRESULT STDMETHODCALLTYPE d3d10_texture2d_QueryInterface(ID3D10Texture2D *iface, REFIID riid, void **object)
{
36
    struct d3d10_texture2d *This = impl_from_ID3D10Texture2D(iface);
37

38 39 40 41 42 43 44 45 46 47 48 49
    TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);

    if (IsEqualGUID(riid, &IID_ID3D10Texture2D)
            || IsEqualGUID(riid, &IID_ID3D10Resource)
            || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
        IUnknown_AddRef(iface);
        *object = iface;
        return S_OK;
    }

50 51 52 53 54 55
    if (This->dxgi_surface)
    {
        TRACE("Forwarding to dxgi surface\n");
        return IDXGISurface_QueryInterface(This->dxgi_surface, riid, object);
    }

56 57 58 59 60 61 62 63
    WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));

    *object = NULL;
    return E_NOINTERFACE;
}

static ULONG STDMETHODCALLTYPE d3d10_texture2d_AddRef(ID3D10Texture2D *iface)
{
64
    struct d3d10_texture2d *This = impl_from_ID3D10Texture2D(iface);
65 66 67 68
    ULONG refcount = InterlockedIncrement(&This->refcount);

    TRACE("%p increasing refcount to %u\n", This, refcount);

69 70
    if (refcount == 1)
        wined3d_texture_incref(This->wined3d_texture);
71

72 73 74
    return refcount;
}

75 76 77 78 79 80 81 82
static void STDMETHODCALLTYPE d3d10_texture2d_wined3d_object_released(void *parent)
{
    struct d3d10_texture2d *This = parent;

    if (This->dxgi_surface) IDXGISurface_Release(This->dxgi_surface);
    HeapFree(GetProcessHeap(), 0, This);
}

83 84
static ULONG STDMETHODCALLTYPE d3d10_texture2d_Release(ID3D10Texture2D *iface)
{
85
    struct d3d10_texture2d *This = impl_from_ID3D10Texture2D(iface);
86 87 88 89
    ULONG refcount = InterlockedDecrement(&This->refcount);

    TRACE("%p decreasing refcount to %u\n", This, refcount);

90
    if (!refcount)
91
        wined3d_texture_decref(This->wined3d_texture);
92

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
    return refcount;
}

/* ID3D10DeviceChild methods */

static void STDMETHODCALLTYPE d3d10_texture2d_GetDevice(ID3D10Texture2D *iface, ID3D10Device **device)
{
    FIXME("iface %p, device %p stub!\n", iface, device);
}

static HRESULT STDMETHODCALLTYPE d3d10_texture2d_GetPrivateData(ID3D10Texture2D *iface,
        REFGUID guid, UINT *data_size, void *data)
{
    FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
            iface, debugstr_guid(guid), data_size, data);

    return E_NOTIMPL;
}

static HRESULT STDMETHODCALLTYPE d3d10_texture2d_SetPrivateData(ID3D10Texture2D *iface,
        REFGUID guid, UINT data_size, const void *data)
{
    FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
            iface, debugstr_guid(guid), data_size, data);

    return E_NOTIMPL;
}

static HRESULT STDMETHODCALLTYPE d3d10_texture2d_SetPrivateDataInterface(ID3D10Texture2D *iface,
        REFGUID guid, const IUnknown *data)
{
    FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);

    return E_NOTIMPL;
}

/* ID3D10Resource methods */

static void STDMETHODCALLTYPE d3d10_texture2d_GetType(ID3D10Texture2D *iface,
        D3D10_RESOURCE_DIMENSION *resource_dimension)
{
134 135 136
    TRACE("iface %p, resource_dimension %p\n", iface, resource_dimension);

    *resource_dimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
}

static void STDMETHODCALLTYPE d3d10_texture2d_SetEvictionPriority(ID3D10Texture2D *iface, UINT eviction_priority)
{
    FIXME("iface %p, eviction_priority %u stub!\n", iface, eviction_priority);
}

static UINT STDMETHODCALLTYPE d3d10_texture2d_GetEvictionPriority(ID3D10Texture2D *iface)
{
    FIXME("iface %p stub!\n", iface);

    return 0;
}

/* ID3D10Texture2D methods */

153
static HRESULT STDMETHODCALLTYPE d3d10_texture2d_Map(ID3D10Texture2D *iface, UINT sub_resource_idx,
154 155
        D3D10_MAP map_type, UINT map_flags, D3D10_MAPPED_TEXTURE2D *mapped_texture)
{
156 157 158 159
    struct d3d10_texture2d *texture = impl_from_ID3D10Texture2D(iface);
    struct wined3d_map_desc wined3d_map_desc;
    struct wined3d_resource *sub_resource;
    HRESULT hr;
160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
    TRACE("iface %p, sub_resource_idx %u, map_type %u, map_flags %#x, mapped_texture %p.\n",
            iface, sub_resource_idx, map_type, map_flags, mapped_texture);

    if (map_type != D3D10_MAP_READ_WRITE)
        FIXME("Ignoring map_type %#x.\n", map_type);
    if (map_flags)
        FIXME("Ignoring map_flags %#x.\n", map_flags);

    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
        hr = E_INVALIDARG;
    else if (SUCCEEDED(hr = wined3d_surface_map(wined3d_surface_from_resource(sub_resource),
            &wined3d_map_desc, NULL, 0)))
    {
        mapped_texture->pData = wined3d_map_desc.data;
        mapped_texture->RowPitch = wined3d_map_desc.row_pitch;
    }

    return hr;
179 180
}

181
static void STDMETHODCALLTYPE d3d10_texture2d_Unmap(ID3D10Texture2D *iface, UINT sub_resource_idx)
182
{
183 184 185 186 187 188 189 190 191
    struct d3d10_texture2d *texture = impl_from_ID3D10Texture2D(iface);
    struct wined3d_resource *sub_resource;

    TRACE("iface %p, sub_resource_idx %u.\n", iface, sub_resource_idx);

    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
        return;

    wined3d_surface_unmap(wined3d_surface_from_resource(sub_resource));
192 193 194 195
}

static void STDMETHODCALLTYPE d3d10_texture2d_GetDesc(ID3D10Texture2D *iface, D3D10_TEXTURE2D_DESC *desc)
{
196
    struct d3d10_texture2d *This = impl_from_ID3D10Texture2D(iface);
197 198 199 200

    TRACE("iface %p, desc %p\n", iface, desc);

    *desc = This->desc;
201 202
}

203
static const struct ID3D10Texture2DVtbl d3d10_texture2d_vtbl =
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
{
    /* IUnknown methods */
    d3d10_texture2d_QueryInterface,
    d3d10_texture2d_AddRef,
    d3d10_texture2d_Release,
    /* ID3D10DeviceChild methods */
    d3d10_texture2d_GetDevice,
    d3d10_texture2d_GetPrivateData,
    d3d10_texture2d_SetPrivateData,
    d3d10_texture2d_SetPrivateDataInterface,
    /* ID3D10Resource methods */
    d3d10_texture2d_GetType,
    d3d10_texture2d_SetEvictionPriority,
    d3d10_texture2d_GetEvictionPriority,
    /* ID3D10Texture2D methods */
    d3d10_texture2d_Map,
    d3d10_texture2d_Unmap,
    d3d10_texture2d_GetDesc,
};
223

224 225 226 227 228
static const struct wined3d_parent_ops d3d10_texture2d_wined3d_parent_ops =
{
    d3d10_texture2d_wined3d_object_released,
};

229 230 231 232 233
HRESULT d3d10_texture2d_init(struct d3d10_texture2d *texture, struct d3d10_device *device,
        const D3D10_TEXTURE2D_DESC *desc)
{
    HRESULT hr;

234
    texture->ID3D10Texture2D_iface.lpVtbl = &d3d10_texture2d_vtbl;
235 236 237 238 239 240 241
    texture->refcount = 1;
    texture->desc = *desc;

    if (desc->MipLevels == 1 && desc->ArraySize == 1)
    {
        IWineDXGIDevice *wine_device;

242 243
        hr = ID3D10Device_QueryInterface(&device->ID3D10Device_iface, &IID_IWineDXGIDevice,
                (void **)&wine_device);
244 245 246 247 248 249 250
        if (FAILED(hr))
        {
            ERR("Device should implement IWineDXGIDevice\n");
            return E_FAIL;
        }

        hr = IWineDXGIDevice_create_surface(wine_device, NULL, 0, NULL,
251
                (IUnknown *)&texture->ID3D10Texture2D_iface, (void **)&texture->dxgi_surface);
252 253 254 255 256 257
        IWineDXGIDevice_Release(wine_device);
        if (FAILED(hr))
        {
            ERR("Failed to create DXGI surface, returning %#x\n", hr);
            return hr;
        }
258
    }
259

260 261 262 263 264
    FIXME("Implement DXGI<->wined3d usage conversion\n");
    if (desc->ArraySize != 1)
        FIXME("Array textures not implemented.\n");
    if (desc->SampleDesc.Count > 1)
        FIXME("Multisampled textures not implemented.\n");
265

266 267 268 269 270 271 272
    hr = wined3d_texture_create_2d(device->wined3d_device, desc->Width, desc->Height,
            desc->MipLevels, desc->Usage, wined3dformat_from_dxgi_format(desc->Format), WINED3D_POOL_DEFAULT,
            texture, &d3d10_texture2d_wined3d_parent_ops, &texture->wined3d_texture);
    if (FAILED(hr))
    {
        WARN("Failed to create wined3d texture, hr %#x.\n", hr);
        if (texture->dxgi_surface)
273
            IDXGISurface_Release(texture->dxgi_surface);
274
        return hr;
275 276 277 278
    }

    return S_OK;
}
279

280 281 282 283 284
static inline struct d3d10_texture3d *impl_from_ID3D10Texture3D(ID3D10Texture3D *iface)
{
    return CONTAINING_RECORD(iface, struct d3d10_texture3d, ID3D10Texture3D_iface);
}

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
static HRESULT STDMETHODCALLTYPE d3d10_texture3d_QueryInterface(ID3D10Texture3D *iface, REFIID riid, void **object)
{
    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);

    if (IsEqualGUID(riid, &IID_ID3D10Texture3D)
            || IsEqualGUID(riid, &IID_ID3D10Resource)
            || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
            || IsEqualGUID(riid, &IID_IUnknown))
    {
        IUnknown_AddRef(iface);
        *object = iface;
        return S_OK;
    }

    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));

    *object = NULL;
    return E_NOINTERFACE;
}

static ULONG STDMETHODCALLTYPE d3d10_texture3d_AddRef(ID3D10Texture3D *iface)
{
307
    struct d3d10_texture3d *texture = impl_from_ID3D10Texture3D(iface);
308 309 310 311
    ULONG refcount = InterlockedIncrement(&texture->refcount);

    TRACE("%p increasing refcount to %u.\n", texture, refcount);

312
    if (refcount == 1)
313
        wined3d_texture_incref(texture->wined3d_texture);
314 315 316 317 318 319 320 321 322 323 324

    return refcount;
}

static void STDMETHODCALLTYPE d3d10_texture3d_wined3d_object_released(void *parent)
{
    HeapFree(GetProcessHeap(), 0, parent);
}

static ULONG STDMETHODCALLTYPE d3d10_texture3d_Release(ID3D10Texture3D *iface)
{
325
    struct d3d10_texture3d *texture = impl_from_ID3D10Texture3D(iface);
326 327 328 329 330
    ULONG refcount = InterlockedDecrement(&texture->refcount);

    TRACE("%p decreasing refcount to %u.\n", texture, refcount);

    if (!refcount)
331
        wined3d_texture_decref(texture->wined3d_texture);
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386

    return refcount;
}

static void STDMETHODCALLTYPE d3d10_texture3d_GetDevice(ID3D10Texture3D *iface, ID3D10Device **device)
{
    FIXME("iface %p, device %p stub!\n", iface, device);
}

static HRESULT STDMETHODCALLTYPE d3d10_texture3d_GetPrivateData(ID3D10Texture3D *iface,
        REFGUID guid, UINT *data_size, void *data)
{
    FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
            iface, debugstr_guid(guid), data_size, data);

    return E_NOTIMPL;
}

static HRESULT STDMETHODCALLTYPE d3d10_texture3d_SetPrivateData(ID3D10Texture3D *iface,
        REFGUID guid, UINT data_size, const void *data)
{
    FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
            iface, debugstr_guid(guid), data_size, data);

    return E_NOTIMPL;
}

static HRESULT STDMETHODCALLTYPE d3d10_texture3d_SetPrivateDataInterface(ID3D10Texture3D *iface,
        REFGUID guid, const IUnknown *data)
{
    FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);

    return E_NOTIMPL;
}

static void STDMETHODCALLTYPE d3d10_texture3d_GetType(ID3D10Texture3D *iface,
        D3D10_RESOURCE_DIMENSION *resource_dimension)
{
    TRACE("iface %p, resource_dimension %p.\n", iface, resource_dimension);

    *resource_dimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
}

static void STDMETHODCALLTYPE d3d10_texture3d_SetEvictionPriority(ID3D10Texture3D *iface, UINT eviction_priority)
{
    FIXME("iface %p, eviction_priority %u stub!\n", iface, eviction_priority);
}

static UINT STDMETHODCALLTYPE d3d10_texture3d_GetEvictionPriority(ID3D10Texture3D *iface)
{
    FIXME("iface %p stub!\n", iface);

    return 0;
}

387
static HRESULT STDMETHODCALLTYPE d3d10_texture3d_Map(ID3D10Texture3D *iface, UINT sub_resource_idx,
388 389
        D3D10_MAP map_type, UINT map_flags, D3D10_MAPPED_TEXTURE3D *mapped_texture)
{
390
    struct d3d10_texture3d *texture = impl_from_ID3D10Texture3D(iface);
391
    struct wined3d_map_desc wined3d_map_desc;
392
    struct wined3d_resource *sub_resource;
393 394
    HRESULT hr;

395 396
    TRACE("iface %p, sub_resource_idx %u, map_type %u, map_flags %#x, mapped_texture %p.\n",
            iface, sub_resource_idx, map_type, map_flags, mapped_texture);
397

398 399 400 401 402
    if (map_type != D3D10_MAP_READ_WRITE)
        FIXME("Ignoring map_type %#x.\n", map_type);
    if (map_flags)
        FIXME("Ignoring map_flags %#x.\n", map_flags);

403
    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
404
        hr = E_INVALIDARG;
405
    else if (SUCCEEDED(hr = wined3d_volume_map(wined3d_volume_from_resource(sub_resource),
406
            &wined3d_map_desc, NULL, 0)))
407
    {
408 409 410
        mapped_texture->pData = wined3d_map_desc.data;
        mapped_texture->RowPitch = wined3d_map_desc.row_pitch;
        mapped_texture->DepthPitch = wined3d_map_desc.slice_pitch;
411 412 413
    }

    return hr;
414 415
}

416
static void STDMETHODCALLTYPE d3d10_texture3d_Unmap(ID3D10Texture3D *iface, UINT sub_resource_idx)
417
{
418
    struct d3d10_texture3d *texture = impl_from_ID3D10Texture3D(iface);
419 420 421 422
    struct wined3d_resource *sub_resource;

    TRACE("iface %p, sub_resource_idx %u.\n", iface, sub_resource_idx);

423
    if (!(sub_resource = wined3d_texture_get_sub_resource(texture->wined3d_texture, sub_resource_idx)))
424
        return;
425

426
    wined3d_volume_unmap(wined3d_volume_from_resource(sub_resource));
427 428 429 430
}

static void STDMETHODCALLTYPE d3d10_texture3d_GetDesc(ID3D10Texture3D *iface, D3D10_TEXTURE3D_DESC *desc)
{
431
    struct d3d10_texture3d *texture = impl_from_ID3D10Texture3D(iface);
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468

    TRACE("iface %p, desc %p.\n", iface, desc);

    *desc = texture->desc;
}

static const struct ID3D10Texture3DVtbl d3d10_texture3d_vtbl =
{
    /* IUnknown methods */
    d3d10_texture3d_QueryInterface,
    d3d10_texture3d_AddRef,
    d3d10_texture3d_Release,
    /* ID3D10DeviceChild methods */
    d3d10_texture3d_GetDevice,
    d3d10_texture3d_GetPrivateData,
    d3d10_texture3d_SetPrivateData,
    d3d10_texture3d_SetPrivateDataInterface,
    /* ID3D10Resource methods */
    d3d10_texture3d_GetType,
    d3d10_texture3d_SetEvictionPriority,
    d3d10_texture3d_GetEvictionPriority,
    /* ID3D10Texture3D methods */
    d3d10_texture3d_Map,
    d3d10_texture3d_Unmap,
    d3d10_texture3d_GetDesc,
};

static const struct wined3d_parent_ops d3d10_texture3d_wined3d_parent_ops =
{
    d3d10_texture3d_wined3d_object_released,
};

HRESULT d3d10_texture3d_init(struct d3d10_texture3d *texture, struct d3d10_device *device,
        const D3D10_TEXTURE3D_DESC *desc)
{
    HRESULT hr;

469
    texture->ID3D10Texture3D_iface.lpVtbl = &d3d10_texture3d_vtbl;
470 471 472 473 474
    texture->refcount = 1;
    texture->desc = *desc;

    FIXME("Implement DXGI<->wined3d usage conversion.\n");

475
    hr = wined3d_texture_create_3d(device->wined3d_device, desc->Width, desc->Height, desc->Depth,
476
            desc->MipLevels, desc->Usage, wined3dformat_from_dxgi_format(desc->Format), WINED3D_POOL_DEFAULT,
477 478 479 480 481 482 483 484 485
            texture, &d3d10_texture3d_wined3d_parent_ops, &texture->wined3d_texture);
    if (FAILED(hr))
    {
        WARN("Failed to create wined3d texture, hr %#x.\n", hr);
        return hr;
    }

    return S_OK;
}