17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
227ec681f3Smrg
237ec681f3Smrg#include "resource9.h"
247ec681f3Smrg#include "device9.h"
257ec681f3Smrg#include "nine_helpers.h"
267ec681f3Smrg#include "nine_defines.h"
277ec681f3Smrg
287ec681f3Smrg#include "util/u_inlines.h"
297ec681f3Smrg#include "util/u_resource.h"
307ec681f3Smrg
317ec681f3Smrg#include "pipe/p_screen.h"
327ec681f3Smrg
337ec681f3Smrg#define DBG_CHANNEL DBG_RESOURCE
347ec681f3Smrg
357ec681f3SmrgHRESULT
367ec681f3SmrgNineResource9_ctor( struct NineResource9 *This,
377ec681f3Smrg                    struct NineUnknownParams *pParams,
387ec681f3Smrg                    struct pipe_resource *initResource,
397ec681f3Smrg                    BOOL Allocate,
407ec681f3Smrg                    D3DRESOURCETYPE Type,
417ec681f3Smrg                    D3DPOOL Pool,
427ec681f3Smrg                    DWORD Usage)
437ec681f3Smrg{
447ec681f3Smrg    struct pipe_screen *screen;
457ec681f3Smrg    HRESULT hr;
467ec681f3Smrg
477ec681f3Smrg    DBG("This=%p pParams=%p initResource=%p Allocate=%d "
487ec681f3Smrg        "Type=%d Pool=%d Usage=%d\n",
497ec681f3Smrg        This, pParams, initResource, (int) Allocate,
507ec681f3Smrg        Type, Pool, Usage);
517ec681f3Smrg
527ec681f3Smrg    hr = NineUnknown_ctor(&This->base, pParams);
537ec681f3Smrg    if (FAILED(hr))
547ec681f3Smrg        return hr;
557ec681f3Smrg
567ec681f3Smrg    This->info.screen = screen = This->base.device->screen;
577ec681f3Smrg    if (initResource)
587ec681f3Smrg        pipe_resource_reference(&This->resource, initResource);
597ec681f3Smrg
607ec681f3Smrg    if (Allocate) {
617ec681f3Smrg        assert(!initResource);
627ec681f3Smrg
637ec681f3Smrg        /* On Windows it is possible allocation fails when
647ec681f3Smrg         * IDirect3DDevice9::GetAvailableTextureMem() still reports
657ec681f3Smrg         * enough free space.
667ec681f3Smrg         *
677ec681f3Smrg         * Some games allocate surfaces
687ec681f3Smrg         * in a loop until they receive D3DERR_OUTOFVIDEOMEMORY to measure
697ec681f3Smrg         * the available texture memory size.
707ec681f3Smrg         *
717ec681f3Smrg         * We are not using the drivers VRAM statistics because:
727ec681f3Smrg         *  * This would add overhead to each resource allocation.
737ec681f3Smrg         *  * Freeing memory is lazy and takes some time, but applications
747ec681f3Smrg         *    expects the memory counter to change immediately after allocating
757ec681f3Smrg         *    or freeing memory.
767ec681f3Smrg         *
777ec681f3Smrg         * Vertexbuffers and indexbuffers are not accounted !
787ec681f3Smrg         */
797ec681f3Smrg        if (This->info.target != PIPE_BUFFER) {
807ec681f3Smrg            This->size = util_resource_size(&This->info);
817ec681f3Smrg
827ec681f3Smrg            p_atomic_add(&This->base.device->available_texture_mem, -This->size);
837ec681f3Smrg            /* Before failing allocation, evict MANAGED memory */
847ec681f3Smrg            if (This->base.device &&
857ec681f3Smrg                p_atomic_read(&This->base.device->available_texture_mem) <=
867ec681f3Smrg                    This->base.device->available_texture_limit)
877ec681f3Smrg                NineDevice9_EvictManagedResourcesInternal(This->base.device);
887ec681f3Smrg            if (p_atomic_read(&This->base.device->available_texture_mem) <=
897ec681f3Smrg                    This->base.device->available_texture_limit) {
907ec681f3Smrg                DBG("Memory allocation failure: software limit\n");
917ec681f3Smrg                return D3DERR_OUTOFVIDEOMEMORY;
927ec681f3Smrg            }
937ec681f3Smrg        }
947ec681f3Smrg
957ec681f3Smrg        DBG("(%p) Creating pipe_resource.\n", This);
967ec681f3Smrg        This->resource = nine_resource_create_with_retry(This->base.device, screen, &This->info);
977ec681f3Smrg        if (!This->resource)
987ec681f3Smrg            return D3DERR_OUTOFVIDEOMEMORY;
997ec681f3Smrg    }
1007ec681f3Smrg
1017ec681f3Smrg    DBG("Current texture memory count: (%d/%d)KB\n",
1027ec681f3Smrg        (int)(This->base.device->available_texture_mem >> 10),
1037ec681f3Smrg        (int)(This->base.device->available_texture_limit >> 10));
1047ec681f3Smrg
1057ec681f3Smrg    This->type = Type;
1067ec681f3Smrg    This->pool = Pool;
1077ec681f3Smrg    This->usage = Usage;
1087ec681f3Smrg    This->priority = 0;
1097ec681f3Smrg
1107ec681f3Smrg    return D3D_OK;
1117ec681f3Smrg}
1127ec681f3Smrg
1137ec681f3Smrgvoid
1147ec681f3SmrgNineResource9_dtor( struct NineResource9 *This )
1157ec681f3Smrg{
1167ec681f3Smrg    DBG("This=%p\n", This);
1177ec681f3Smrg
1187ec681f3Smrg    /* NOTE: We do have to use refcounting, the driver might
1197ec681f3Smrg     * still hold a reference. */
1207ec681f3Smrg    pipe_resource_reference(&This->resource, NULL);
1217ec681f3Smrg
1227ec681f3Smrg    /* NOTE: size is 0, unless something has actually been allocated */
1237ec681f3Smrg    if (This->base.device)
1247ec681f3Smrg        p_atomic_add(&This->base.device->available_texture_mem, This->size);
1257ec681f3Smrg
1267ec681f3Smrg    NineUnknown_dtor(&This->base);
1277ec681f3Smrg}
1287ec681f3Smrg
1297ec681f3Smrgstruct pipe_resource *
1307ec681f3SmrgNineResource9_GetResource( struct NineResource9 *This )
1317ec681f3Smrg{
1327ec681f3Smrg    return This->resource;
1337ec681f3Smrg}
1347ec681f3Smrg
1357ec681f3SmrgD3DPOOL
1367ec681f3SmrgNineResource9_GetPool( struct NineResource9 *This )
1377ec681f3Smrg{
1387ec681f3Smrg    return This->pool;
1397ec681f3Smrg}
1407ec681f3Smrg
1417ec681f3SmrgDWORD NINE_WINAPI
1427ec681f3SmrgNineResource9_SetPriority( struct NineResource9 *This,
1437ec681f3Smrg                           DWORD PriorityNew )
1447ec681f3Smrg{
1457ec681f3Smrg    DWORD prev;
1467ec681f3Smrg    DBG("This=%p, PriorityNew=%d\n", This, PriorityNew);
1477ec681f3Smrg
1487ec681f3Smrg    if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
1497ec681f3Smrg        return 0;
1507ec681f3Smrg
1517ec681f3Smrg    prev = This->priority;
1527ec681f3Smrg    This->priority = PriorityNew;
1537ec681f3Smrg    return prev;
1547ec681f3Smrg}
1557ec681f3Smrg
1567ec681f3SmrgDWORD NINE_WINAPI
1577ec681f3SmrgNineResource9_GetPriority( struct NineResource9 *This )
1587ec681f3Smrg{
1597ec681f3Smrg    if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
1607ec681f3Smrg        return 0;
1617ec681f3Smrg
1627ec681f3Smrg    return This->priority;
1637ec681f3Smrg}
1647ec681f3Smrg
1657ec681f3Smrg/* NOTE: Don't forget to adjust locked vtable if you change this ! */
1667ec681f3Smrgvoid NINE_WINAPI
1677ec681f3SmrgNineResource9_PreLoad( struct NineResource9 *This )
1687ec681f3Smrg{
1697ec681f3Smrg    if (This->pool != D3DPOOL_MANAGED)
1707ec681f3Smrg        return;
1717ec681f3Smrg    /* We don't treat managed vertex or index buffers different from
1727ec681f3Smrg     * default ones (are managed vertex buffers even allowed ?), and
1737ec681f3Smrg     * the PreLoad for textures is overridden by superclass.
1747ec681f3Smrg     */
1757ec681f3Smrg}
1767ec681f3Smrg
1777ec681f3SmrgD3DRESOURCETYPE NINE_WINAPI
1787ec681f3SmrgNineResource9_GetType( struct NineResource9 *This )
1797ec681f3Smrg{
1807ec681f3Smrg    return This->type;
1817ec681f3Smrg}
182