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"
15 nvfx_miptree_choose_format(struct nvfx_miptree
*mt
)
17 struct pipe_resource
*pt
= &mt
->base
.base
;
18 unsigned uniform_pitch
= 0;
19 static int no_swizzle
= -1;
21 no_swizzle
= debug_get_bool_option("NV40_NO_SWIZZLE", FALSE
); /* this will break things on nv30 */
23 if (!util_is_power_of_two(pt
->width0
) ||
24 !util_is_power_of_two(pt
->height0
) ||
25 !util_is_power_of_two(pt
->depth0
) ||
26 (!nvfx_screen(pt
->screen
)->is_nv4x
&& pt
->target
== PIPE_TEXTURE_RECT
)
31 (pt
->bind
& (PIPE_BIND_SCANOUT
| PIPE_BIND_DISPLAY_TARGET
))
32 || (pt
->usage
& PIPE_USAGE_DYNAMIC
) || (pt
->usage
& PIPE_USAGE_STAGING
)
33 || util_format_is_compressed(pt
->format
)
36 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
38 /* non compressed formats with uniform pitch must be linear, and vice versa */
39 if(!util_format_is_s3tc(pt
->format
)
40 && (uniform_pitch
|| mt
->base
.base
.flags
& NVFX_RESOURCE_FLAG_LINEAR
))
42 mt
->base
.base
.flags
|= NVFX_RESOURCE_FLAG_LINEAR
;
48 mt
->linear_pitch
= util_format_get_stride(pt
->format
, pt
->width0
);
50 // TODO: this is only a constraint for rendering and not sampling, apparently
51 // we may also want this unconditionally
52 if(pt
->bind
& (PIPE_BIND_SAMPLER_VIEW
|
53 PIPE_BIND_DEPTH_STENCIL
|
54 PIPE_BIND_RENDER_TARGET
|
55 PIPE_BIND_DISPLAY_TARGET
|
57 mt
->linear_pitch
= align(mt
->linear_pitch
, 64);
64 nvfx_miptree_layout(struct nvfx_miptree
*mt
)
66 struct pipe_resource
* pt
= &mt
->base
.base
;
69 if(!nvfx_screen(pt
->screen
)->is_nv4x
)
71 assert(pt
->target
== PIPE_TEXTURE_RECT
72 || (util_is_power_of_two(pt
->width0
) && util_is_power_of_two(pt
->height0
)));
75 for (unsigned l
= 0; l
<= pt
->last_level
; l
++)
78 mt
->level_offset
[l
] = offset
;
81 size
= mt
->linear_pitch
;
83 size
= util_format_get_stride(pt
->format
, u_minify(pt
->width0
, l
));
84 size
= util_format_get_2d_size(pt
->format
, size
, u_minify(pt
->height0
, l
));
86 if(pt
->target
== PIPE_TEXTURE_3D
)
87 size
*= u_minify(pt
->depth0
, l
);
92 offset
= align(offset
, 128);
93 mt
->face_size
= offset
;
94 if(mt
->base
.base
.target
== PIPE_TEXTURE_CUBE
)
95 offset
+= 5 * mt
->face_size
;
100 nvfx_miptree_surface_final_destroy(struct pipe_surface
* ps
)
102 struct nvfx_surface
* ns
= (struct nvfx_surface
*)ps
;
103 pipe_resource_reference(&ps
->texture
, 0);
104 pipe_resource_reference((struct pipe_resource
**)&ns
->temp
, 0);
109 nvfx_miptree_destroy(struct pipe_screen
*screen
, struct pipe_resource
*pt
)
111 struct nvfx_miptree
*mt
= (struct nvfx_miptree
*)pt
;
112 util_surfaces_destroy(&mt
->surfaces
, pt
, nvfx_miptree_surface_final_destroy
);
113 nouveau_screen_bo_release(screen
, mt
->base
.bo
);
117 static struct nvfx_miptree
*
118 nvfx_miptree_create_skeleton(struct pipe_screen
*pscreen
, const struct pipe_resource
*pt
)
120 struct nvfx_miptree
*mt
;
122 if(pt
->width0
> 4096 || pt
->height0
> 4096)
125 mt
= CALLOC_STRUCT(nvfx_miptree
);
130 util_dirty_surfaces_init(&mt
->dirty_surfaces
);
132 pipe_reference_init(&mt
->base
.base
.reference
, 1);
133 mt
->base
.base
.screen
= pscreen
;
135 // set this to the actual capabilities, we use it to decide whether to use the 3D engine for copies
136 // TODO: is this the correct way to use Gallium?
137 mt
->base
.base
.bind
= pt
->bind
| PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_DEPTH_STENCIL
;
139 // on our current driver (and the driver too), format support does not depend on geometry, so don't bother computing it
140 // TODO: may want to revisit this
141 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_RENDER_TARGET
))
142 mt
->base
.base
.bind
&=~ PIPE_BIND_RENDER_TARGET
;
143 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_SAMPLER_VIEW
))
144 mt
->base
.base
.bind
&=~ PIPE_BIND_SAMPLER_VIEW
;
145 if(!pscreen
->is_format_supported(pscreen
, pt
->format
, pt
->target
, 0, PIPE_BIND_DEPTH_STENCIL
))
146 mt
->base
.base
.bind
&=~ PIPE_BIND_DEPTH_STENCIL
;
152 struct pipe_resource
*
153 nvfx_miptree_create(struct pipe_screen
*pscreen
, const struct pipe_resource
*pt
)
155 struct nvfx_miptree
* mt
= nvfx_miptree_create_skeleton(pscreen
, pt
);
157 nvfx_miptree_choose_format(mt
);
159 size
= nvfx_miptree_layout(mt
);
161 mt
->base
.bo
= nouveau_screen_bo_new(pscreen
, 256, pt
->usage
, pt
->bind
, size
);
167 return &mt
->base
.base
;
170 // TODO: redo this, just calling miptree_layout
171 struct pipe_resource
*
172 nvfx_miptree_from_handle(struct pipe_screen
*pscreen
, const struct pipe_resource
*template, struct winsys_handle
*whandle
)
174 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
);
184 mt
->base
.bo
= nouveau_screen_bo_from_handle(pscreen
, whandle
, &stride
);
185 if (mt
->base
.bo
== NULL
) {
189 return &mt
->base
.base
;
192 struct pipe_surface
*
193 nvfx_miptree_surface_new(struct pipe_context
*pipe
, struct pipe_resource
*pt
,
194 const struct pipe_surface
*surf_tmpl
)
196 struct nvfx_miptree
*mt
= (struct nvfx_miptree
*)pt
;
197 unsigned level
= surf_tmpl
->u
.tex
.level
;
198 struct nvfx_surface
*ns
= NULL
;
200 assert(surf_tmpl
->u
.tex
.first_layer
== surf_tmpl
->u
.tex
.last_layer
);
201 if(util_surfaces_get(&mt
->surfaces
, sizeof(struct nvfx_surface
), pipe
,
202 pt
, level
, surf_tmpl
->u
.tex
.first_layer
,
203 surf_tmpl
->usage
, (struct pipe_surface
**)&ns
)) {
204 util_dirty_surface_init(&ns
->base
);
205 ns
->pitch
= nvfx_subresource_pitch(pt
, level
);
206 ns
->offset
= nvfx_subresource_offset(pt
, surf_tmpl
->u
.tex
.first_layer
, level
, surf_tmpl
->u
.tex
.first_layer
);
209 return &ns
->base
.base
;
213 nvfx_miptree_surface_del(struct pipe_context
*pipe
, struct pipe_surface
*ps
)
215 struct nvfx_surface
* ns
= (struct nvfx_surface
*)ps
;
219 assert(!util_dirty_surface_is_dirty(&ns
->base
));
220 util_surfaces_detach(&((struct nvfx_miptree
*)ps
->texture
)->surfaces
, ps
);
221 pipe_resource_reference(&ps
->texture
, 0);