1 /*
2 * Copyright 2011 Joakim Sindholt <[email protected]>
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "resource9.h"
7 #include "device9.h"
8 #include "nine_helpers.h"
9 #include "nine_defines.h"
10
11 #include "util/u_inlines.h"
12 #include "util/u_resource.h"
13
14 #include "pipe/p_screen.h"
15
16 #define DBG_CHANNEL DBG_RESOURCE
17
18 HRESULT
NineResource9_ctor(struct NineResource9 * This,struct NineUnknownParams * pParams,struct pipe_resource * initResource,BOOL Allocate,D3DRESOURCETYPE Type,D3DPOOL Pool,DWORD Usage)19 NineResource9_ctor( struct NineResource9 *This,
20 struct NineUnknownParams *pParams,
21 struct pipe_resource *initResource,
22 BOOL Allocate,
23 D3DRESOURCETYPE Type,
24 D3DPOOL Pool,
25 DWORD Usage)
26 {
27 struct pipe_screen *screen;
28 HRESULT hr;
29
30 DBG("This=%p pParams=%p initResource=%p Allocate=%d "
31 "Type=%d Pool=%d Usage=%d\n",
32 This, pParams, initResource, (int) Allocate,
33 Type, Pool, Usage);
34
35 hr = NineUnknown_ctor(&This->base, pParams);
36 if (FAILED(hr))
37 return hr;
38
39 This->info.screen = screen = This->base.device->screen;
40 if (initResource)
41 pipe_resource_reference(&This->resource, initResource);
42
43 if (Allocate) {
44 assert(!initResource);
45
46 /* On Windows it is possible allocation fails when
47 * IDirect3DDevice9::GetAvailableTextureMem() still reports
48 * enough free space.
49 *
50 * Some games allocate surfaces
51 * in a loop until they receive D3DERR_OUTOFVIDEOMEMORY to measure
52 * the available texture memory size.
53 *
54 * We are not using the drivers VRAM statistics because:
55 * * This would add overhead to each resource allocation.
56 * * Freeing memory is lazy and takes some time, but applications
57 * expects the memory counter to change immediately after allocating
58 * or freeing memory.
59 *
60 * Vertexbuffers and indexbuffers are not accounted !
61 */
62 if (This->info.target != PIPE_BUFFER) {
63 This->size = util_resource_size(&This->info);
64
65 p_atomic_add(&This->base.device->available_texture_mem, -This->size);
66 /* Before failing allocation, evict MANAGED memory */
67 if (This->base.device &&
68 p_atomic_read(&This->base.device->available_texture_mem) <=
69 This->base.device->available_texture_limit)
70 NineDevice9_EvictManagedResourcesInternal(This->base.device);
71 if (p_atomic_read(&This->base.device->available_texture_mem) <=
72 This->base.device->available_texture_limit) {
73 DBG("Memory allocation failure: software limit\n");
74 return D3DERR_OUTOFVIDEOMEMORY;
75 }
76 }
77
78 DBG("(%p) Creating pipe_resource.\n", This);
79 This->resource = nine_resource_create_with_retry(This->base.device, screen, &This->info);
80 if (!This->resource)
81 return D3DERR_OUTOFVIDEOMEMORY;
82 }
83
84 DBG("Current texture memory count: (%d/%d)KB\n",
85 (int)(This->base.device->available_texture_mem >> 10),
86 (int)(This->base.device->available_texture_limit >> 10));
87
88 This->type = Type;
89 This->pool = Pool;
90 This->usage = Usage;
91 This->priority = 0;
92
93 return D3D_OK;
94 }
95
96 void
NineResource9_dtor(struct NineResource9 * This)97 NineResource9_dtor( struct NineResource9 *This )
98 {
99 DBG("This=%p\n", This);
100
101 /* NOTE: We do have to use refcounting, the driver might
102 * still hold a reference. */
103 pipe_resource_reference(&This->resource, NULL);
104
105 /* NOTE: size is 0, unless something has actually been allocated */
106 if (This->base.device)
107 p_atomic_add(&This->base.device->available_texture_mem, This->size);
108
109 NineUnknown_dtor(&This->base);
110 }
111
112 struct pipe_resource *
NineResource9_GetResource(struct NineResource9 * This)113 NineResource9_GetResource( struct NineResource9 *This )
114 {
115 return This->resource;
116 }
117
118 D3DPOOL
NineResource9_GetPool(struct NineResource9 * This)119 NineResource9_GetPool( struct NineResource9 *This )
120 {
121 return This->pool;
122 }
123
124 DWORD NINE_WINAPI
NineResource9_SetPriority(struct NineResource9 * This,DWORD PriorityNew)125 NineResource9_SetPriority( struct NineResource9 *This,
126 DWORD PriorityNew )
127 {
128 DWORD prev;
129 DBG("This=%p, PriorityNew=%d\n", This, PriorityNew);
130
131 if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
132 return 0;
133
134 prev = This->priority;
135 This->priority = PriorityNew;
136 return prev;
137 }
138
139 DWORD NINE_WINAPI
NineResource9_GetPriority(struct NineResource9 * This)140 NineResource9_GetPriority( struct NineResource9 *This )
141 {
142 if (This->pool != D3DPOOL_MANAGED || This->type == D3DRTYPE_SURFACE)
143 return 0;
144
145 return This->priority;
146 }
147
148 /* NOTE: Don't forget to adjust locked vtable if you change this ! */
149 void NINE_WINAPI
NineResource9_PreLoad(struct NineResource9 * This)150 NineResource9_PreLoad( struct NineResource9 *This )
151 {
152 if (This->pool != D3DPOOL_MANAGED)
153 return;
154 /* We don't treat managed vertex or index buffers different from
155 * default ones (are managed vertex buffers even allowed ?), and
156 * the PreLoad for textures is overridden by superclass.
157 */
158 }
159
160 D3DRESOURCETYPE NINE_WINAPI
NineResource9_GetType(struct NineResource9 * This)161 NineResource9_GetType( struct NineResource9 *This )
162 {
163 return This->type;
164 }
165