1 #include "pipe/p_state.h"
2 #include "pipe/p_defines.h"
3 #include "util/u_inlines.h"
4 #include "util/u_format.h"
5 #include "util/u_memory.h"
6 #include "util/u_math.h"
7 #include "util/u_staging.h"
8 #include "state_tracker/drm_driver.h"
9 #include "nouveau/nouveau_winsys.h"
10 #include "nouveau/nouveau_screen.h"
11 #include "nvfx_screen.h"
12 #include "nvfx_resource.h"
13 #include "nvfx_transfer.h"
16 nvfx_miptree_choose_format(struct nvfx_miptree
*mt
)
18 struct pipe_resource
*pt
= &mt
->base
.base
;
19 unsigned uniform_pitch
= 0;
20 static int no_swizzle
= -1;
22 no_swizzle
= debug_get_bool_option("NV40_NO_SWIZZLE", FALSE
); /* this will break things on nv30 */
24 if (!util_is_pot(pt
->width0
) ||
25 !util_is_pot(pt
->height0
) ||
26 !util_is_pot(pt
->depth0
) ||
27 (!nvfx_screen(pt
->screen
)->is_nv4x
&& pt
->target
== PIPE_TEXTURE_RECT
)
32 (pt
->bind
& (PIPE_BIND_SCANOUT
| PIPE_BIND_DISPLAY_TARGET
))
33 || (pt
->usage
& PIPE_USAGE_DYNAMIC
) || (pt
->usage
& PIPE_USAGE_STAGING
)
34 || util_format_is_compressed(pt
->format
)
37 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
39 /* non compressed formats with uniform pitch must be linear, and vice versa */
40 if(!util_format_is_s3tc(pt
->format
)
41 && (uniform_pitch
|| mt
->base
.base
.flags
& NVFX_RESOURCE_FLAG_LINEAR
))
43 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
49 mt
->linear_pitch
= util_format_get_stride(pt
->format
, pt
->width0
);
51 // TODO: this is only a constraint for rendering and not sampling, apparently
52 // we may also want this unconditionally
53 if(pt
->bind
& (PIPE_BIND_SAMPLER_VIEW
|
54 PIPE_BIND_DEPTH_STENCIL
|
55 PIPE_BIND_RENDER_TARGET
|
56 PIPE_BIND_DISPLAY_TARGET
|
58 mt
->linear_pitch
= align(mt
->linear_pitch
, 64);
65 nvfx_miptree_layout(struct nvfx_miptree
*mt
)
67 struct pipe_resource
* pt
= &mt
->base
.base
;
70 if(!nvfx_screen(pt
->screen
)->is_nv4x
)
72 assert(pt
->target
== PIPE_TEXTURE_RECT
73 || (util_is_pot(pt
->width0
) && util_is_pot(pt
->height0
)));
76 for (unsigned l
= 0; l
<= pt
->last_level
; l
++)
79 mt
->level_offset
[l
] = offset
;
82 size
= mt
->linear_pitch
;
84 size
= util_format_get_stride(pt
->format
, u_minify(pt
->width0
, l
));
85 size
= util_format_get_2d_size(pt
->format
, size
, u_minify(pt
->height0
, l
));
87 if(pt
->target
== PIPE_TEXTURE_3D
)
88 size
*= u_minify(pt
->depth0
, l
);
93 offset
= align(offset
, 128);
94 mt
->face_size
= offset
;
95 if(mt
->base
.base
.target
== PIPE_TEXTURE_CUBE
)
96 offset
+= 5 * mt
->face_size
;
101 nvfx_miptree_get_handle(struct pipe_screen
*pscreen
,
102 struct pipe_resource
*ptexture
,
103 struct winsys_handle
*whandle
)
105 struct nvfx_miptree
* mt
= (struct nvfx_miptree
*)ptexture
;
107 if (!mt
|| !mt
->base
.bo
)
110 return nouveau_screen_bo_get_handle(pscreen
,
118 nvfx_miptree_destroy(struct pipe_screen
*screen
, struct pipe_resource
*pt
)
120 struct nvfx_miptree
*mt
= (struct nvfx_miptree
*)pt
;
121 nouveau_screen_bo_release(screen
, mt
->base
.bo
);
128 struct u_resource_vtbl nvfx_miptree_vtbl
=
130 nvfx_miptree_get_handle
, /* get_handle */
131 nvfx_miptree_destroy
, /* resource_destroy */
132 NULL
, /* is_resource_referenced */
133 nvfx_transfer_new
, /* get_transfer */
134 util_staging_transfer_destroy
, /* transfer_destroy */
135 nvfx_transfer_map
, /* transfer_map */
136 u_default_transfer_flush_region
, /* transfer_flush_region */
137 nvfx_transfer_unmap
, /* transfer_unmap */
138 u_default_transfer_inline_write
/* transfer_inline_write */
141 static struct nvfx_miptree
*
142 nvfx_miptree_create_skeleton(struct pipe_screen
*pscreen
, const struct pipe_resource
*pt
)
144 struct nvfx_miptree
*mt
;
146 if(pt
->width0
> 4096 || pt
->height0
> 4096)
149 mt
= CALLOC_STRUCT(nvfx_miptree
);
154 mt
->base
.vtbl
= &nvfx_miptree_vtbl
;
155 pipe_reference_init(&mt
->base
.base
.reference
, 1);
156 mt
->base
.base
.screen
= pscreen
;
158 // set this to the actual capabilities, we use it to decide whether to use the 3D engine for copies
159 // TODO: is this the correct way to use Gallium?
160 mt
->base
.base
.bind
= pt
->bind
| PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_DEPTH_STENCIL
;
162 // on our current driver (and the driver too), format support does not depend on geometry, so don't bother computing it
163 // TODO: may want to revisit this
164 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_RENDER_TARGET
, 0))
165 mt
->base
.base
.bind
&=~ PIPE_BIND_RENDER_TARGET
;
166 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_SAMPLER_VIEW
, 0))
167 mt
->base
.base
.bind
&=~ PIPE_BIND_SAMPLER_VIEW
;
168 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_DEPTH_STENCIL
, 0))
169 mt
->base
.base
.bind
&=~ PIPE_BIND_DEPTH_STENCIL
;
175 struct pipe_resource
*
176 nvfx_miptree_create(struct pipe_screen
*pscreen
, const struct pipe_resource
*pt
)
178 struct nvfx_miptree
* mt
= nvfx_miptree_create_skeleton(pscreen
, pt
);
179 nvfx_miptree_choose_format(mt
);
181 unsigned size
= nvfx_miptree_layout(mt
);
183 mt
->base
.bo
= nouveau_screen_bo_new(pscreen
, 256, pt
->usage
, pt
->bind
, size
);
189 return &mt
->base
.base
;
192 // TODO: redo this, just calling miptree_layout
193 struct pipe_resource
*
194 nvfx_miptree_from_handle(struct pipe_screen
*pscreen
, const struct pipe_resource
*template, struct winsys_handle
*whandle
)
196 struct nvfx_miptree
* mt
= nvfx_miptree_create_skeleton(pscreen
, template);
197 if(whandle
->stride
) {
198 mt
->linear_pitch
= whandle
->stride
;
199 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
201 nvfx_miptree_choose_format(mt
);
203 nvfx_miptree_layout(mt
);
206 mt
->base
.bo
= nouveau_screen_bo_from_handle(pscreen
, whandle
, &stride
);
207 if (mt
->base
.bo
== NULL
) {
211 return &mt
->base
.base
;
214 /* Surface helpers, not strictly required to implement the resource vtbl:
216 struct pipe_surface
*
217 nvfx_miptree_surface_new(struct pipe_screen
*pscreen
, struct pipe_resource
*pt
,
218 unsigned face
, unsigned level
, unsigned zslice
,
221 struct nvfx_surface
*ns
;
223 ns
= CALLOC_STRUCT(nvfx_surface
);
226 pipe_resource_reference(&ns
->base
.texture
, pt
);
227 ns
->base
.format
= pt
->format
;
228 ns
->base
.width
= u_minify(pt
->width0
, level
);
229 ns
->base
.height
= u_minify(pt
->height0
, level
);
230 ns
->base
.usage
= flags
;
231 pipe_reference_init(&ns
->base
.reference
, 1);
232 ns
->base
.face
= face
;
233 ns
->base
.level
= level
;
234 ns
->base
.zslice
= zslice
;
235 ns
->pitch
= nvfx_subresource_pitch(pt
, level
);
236 ns
->base
.offset
= nvfx_subresource_offset(pt
, face
, level
, zslice
);
242 nvfx_miptree_surface_del(struct pipe_surface
*ps
)
244 pipe_resource_reference(&ps
->texture
, NULL
);