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"
17 nvfx_miptree_choose_format(struct nvfx_miptree
*mt
)
19 struct pipe_resource
*pt
= &mt
->base
.base
;
20 unsigned uniform_pitch
= 0;
21 static int no_swizzle
= -1;
23 no_swizzle
= debug_get_bool_option("NV40_NO_SWIZZLE", FALSE
); /* this will break things on nv30 */
25 if (!util_is_pot(pt
->width0
) ||
26 !util_is_pot(pt
->height0
) ||
27 !util_is_pot(pt
->depth0
) ||
28 (!nvfx_screen(pt
->screen
)->is_nv4x
&& pt
->target
== PIPE_TEXTURE_RECT
)
33 (pt
->bind
& (PIPE_BIND_SCANOUT
| PIPE_BIND_DISPLAY_TARGET
))
34 || (pt
->usage
& PIPE_USAGE_DYNAMIC
) || (pt
->usage
& PIPE_USAGE_STAGING
)
35 || util_format_is_compressed(pt
->format
)
38 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
40 /* non compressed formats with uniform pitch must be linear, and vice versa */
41 if(!util_format_is_s3tc(pt
->format
)
42 && (uniform_pitch
|| mt
->base
.base
.flags
& NVFX_RESOURCE_FLAG_LINEAR
))
44 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
50 mt
->linear_pitch
= util_format_get_stride(pt
->format
, pt
->width0
);
52 // TODO: this is only a constraint for rendering and not sampling, apparently
53 // we may also want this unconditionally
54 if(pt
->bind
& (PIPE_BIND_SAMPLER_VIEW
|
55 PIPE_BIND_DEPTH_STENCIL
|
56 PIPE_BIND_RENDER_TARGET
|
57 PIPE_BIND_DISPLAY_TARGET
|
59 mt
->linear_pitch
= align(mt
->linear_pitch
, 64);
66 nvfx_miptree_layout(struct nvfx_miptree
*mt
)
68 struct pipe_resource
* pt
= &mt
->base
.base
;
71 if(!nvfx_screen(pt
->screen
)->is_nv4x
)
73 assert(pt
->target
== PIPE_TEXTURE_RECT
74 || (util_is_pot(pt
->width0
) && util_is_pot(pt
->height0
)));
77 for (unsigned l
= 0; l
<= pt
->last_level
; l
++)
80 mt
->level_offset
[l
] = offset
;
83 size
= mt
->linear_pitch
;
85 size
= util_format_get_stride(pt
->format
, u_minify(pt
->width0
, l
));
86 size
= util_format_get_2d_size(pt
->format
, size
, u_minify(pt
->height0
, l
));
88 if(pt
->target
== PIPE_TEXTURE_3D
)
89 size
*= u_minify(pt
->depth0
, l
);
94 offset
= align(offset
, 128);
95 mt
->face_size
= offset
;
96 if(mt
->base
.base
.target
== PIPE_TEXTURE_CUBE
)
97 offset
+= 5 * mt
->face_size
;
102 nvfx_miptree_surface_final_destroy(struct pipe_surface
* ps
)
104 struct nvfx_surface
* ns
= (struct nvfx_surface
*)ps
;
105 pipe_resource_reference(&ps
->texture
, 0);
106 pipe_resource_reference((struct pipe_resource
**)&ns
->temp
, 0);
111 nvfx_miptree_destroy(struct pipe_screen
*screen
, struct pipe_resource
*pt
)
113 struct nvfx_miptree
*mt
= (struct nvfx_miptree
*)pt
;
114 util_surfaces_destroy(&mt
->surfaces
, pt
, nvfx_miptree_surface_final_destroy
);
115 nouveau_screen_bo_release(screen
, mt
->base
.bo
);
119 static struct nvfx_miptree
*
120 nvfx_miptree_create_skeleton(struct pipe_screen
*pscreen
, const struct pipe_resource
*pt
)
122 struct nvfx_miptree
*mt
;
124 if(pt
->width0
> 4096 || pt
->height0
> 4096)
127 mt
= CALLOC_STRUCT(nvfx_miptree
);
132 util_dirty_surfaces_init(&mt
->dirty_surfaces
);
134 pipe_reference_init(&mt
->base
.base
.reference
, 1);
135 mt
->base
.base
.screen
= pscreen
;
137 // set this to the actual capabilities, we use it to decide whether to use the 3D engine for copies
138 // TODO: is this the correct way to use Gallium?
139 mt
->base
.base
.bind
= pt
->bind
| PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_DEPTH_STENCIL
;
141 // on our current driver (and the driver too), format support does not depend on geometry, so don't bother computing it
142 // TODO: may want to revisit this
143 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_RENDER_TARGET
, 0))
144 mt
->base
.base
.bind
&=~ PIPE_BIND_RENDER_TARGET
;
145 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_SAMPLER_VIEW
, 0))
146 mt
->base
.base
.bind
&=~ PIPE_BIND_SAMPLER_VIEW
;
147 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_DEPTH_STENCIL
, 0))
148 mt
->base
.base
.bind
&=~ PIPE_BIND_DEPTH_STENCIL
;
154 struct pipe_resource
*
155 nvfx_miptree_create(struct pipe_screen
*pscreen
, const struct pipe_resource
*pt
)
157 struct nvfx_miptree
* mt
= nvfx_miptree_create_skeleton(pscreen
, pt
);
158 nvfx_miptree_choose_format(mt
);
160 unsigned size
= nvfx_miptree_layout(mt
);
162 mt
->base
.bo
= nouveau_screen_bo_new(pscreen
, 256, pt
->usage
, pt
->bind
, size
);
168 return &mt
->base
.base
;
171 // TODO: redo this, just calling miptree_layout
172 struct pipe_resource
*
173 nvfx_miptree_from_handle(struct pipe_screen
*pscreen
, const struct pipe_resource
*template, struct winsys_handle
*whandle
)
175 struct nvfx_miptree
* mt
= nvfx_miptree_create_skeleton(pscreen
, template);
176 if(whandle
->stride
) {
177 mt
->linear_pitch
= whandle
->stride
;
178 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
180 nvfx_miptree_choose_format(mt
);
182 nvfx_miptree_layout(mt
);
185 mt
->base
.bo
= nouveau_screen_bo_from_handle(pscreen
, whandle
, &stride
);
186 if (mt
->base
.bo
== NULL
) {
190 return &mt
->base
.base
;
193 struct pipe_surface
*
194 nvfx_miptree_surface_new(struct pipe_screen
*pscreen
, struct pipe_resource
*pt
,
195 unsigned face
, unsigned level
, unsigned zslice
,
198 struct nvfx_miptree
* mt
= (struct nvfx_miptree
*)pt
;
199 struct nvfx_surface
*ns
;
201 ns
= (struct nvfx_surface
*)util_surfaces_get(&mt
->surfaces
, sizeof(struct nvfx_surface
), pscreen
, pt
, face
, level
, zslice
, flags
);
202 if(ns
->base
.base
.offset
== ~0) {
203 util_dirty_surface_init(&ns
->base
);
204 ns
->pitch
= nvfx_subresource_pitch(pt
, level
);
205 ns
->base
.base
.offset
= nvfx_subresource_offset(pt
, face
, level
, zslice
);
208 return &ns
->base
.base
;
212 nvfx_miptree_surface_del(struct pipe_surface
*ps
)
214 struct nvfx_surface
* ns
= (struct nvfx_surface
*)ps
;
218 util_surfaces_detach(&((struct nvfx_miptree
*)ps
->texture
)->surfaces
, ps
);
219 pipe_resource_reference(&ps
->texture
, 0);