1 #include "nvfx_context.h"
2 #include "nvfx_resource.h"
3 #include "util/u_format.h"
6 nvfx_surface_linear_renderable(struct pipe_surface
* surf
)
8 /* TODO: precompute this in nvfx_surface creation */
9 return (surf
->texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
)
10 && !(surf
->offset
& 63)
11 && !(((struct nvfx_surface
*)surf
)->pitch
& 63);
15 nvfx_surface_swizzled_renderable(struct pipe_framebuffer_state
* fb
, struct pipe_surface
* surf
)
17 /* TODO: precompute this in nvfx_surface creation */
18 return !((struct nvfx_miptree
*)surf
->texture
)->linear_pitch
19 && (surf
->texture
->target
!= PIPE_TEXTURE_3D
|| u_minify(surf
->texture
->depth0
, surf
->level
) <= 1)
20 && !(surf
->offset
& 127)
21 && (surf
->width
== fb
->width
)
22 && (surf
->height
== fb
->height
)
23 && !((struct nvfx_surface
*)surf
)->temp
24 && (surf
->format
== PIPE_FORMAT_B8G8R8A8_UNORM
|| surf
->format
== PIPE_FORMAT_B8G8R8X8_UNORM
|| surf
->format
== PIPE_FORMAT_B5G6R5_UNORM
);
28 nvfx_surface_get_render_target(struct pipe_surface
* surf
, int all_swizzled
, struct nvfx_render_target
* target
)
30 struct nvfx_surface
* ns
= (struct nvfx_surface
*)surf
;
33 target
->bo
= ((struct nvfx_miptree
*)surf
->texture
)->base
.bo
;
34 target
->offset
= surf
->offset
;
35 target
->pitch
= align(ns
->pitch
, 64);
36 assert(target
->pitch
);
42 target
->pitch
= ns
->temp
->linear_pitch
;
43 target
->bo
= ns
->temp
->base
.bo
;
44 assert(target
->pitch
);
50 nvfx_framebuffer_prepare(struct nvfx_context
*nvfx
)
52 struct pipe_framebuffer_state
*fb
= &nvfx
->framebuffer
;
53 int i
, color_format
= 0, zeta_format
= 0;
57 assert(fb
->nr_cbufs
<= 2);
59 assert(fb
->nr_cbufs
<= 4);
61 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
63 if(color_format
!= fb
->cbufs
[i
]->format
)
66 color_format
= fb
->cbufs
[i
]->format
;
68 if(!nvfx_surface_swizzled_renderable(fb
, fb
->cbufs
[i
]))
73 /* TODO: return FALSE if we have a format not supporting a depth buffer (e.g. r8); currently those are not supported at all */
74 if(!nvfx_surface_swizzled_renderable(fb
, fb
->zsbuf
))
77 if(all_swizzled
&& util_format_get_blocksize(color_format
) != util_format_get_blocksize(zeta_format
))
81 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
82 if(!((struct nvfx_surface
*)fb
->cbufs
[i
])->temp
&& !all_swizzled
&& !nvfx_surface_linear_renderable(fb
->cbufs
[i
]))
83 nvfx_surface_create_temp(&nvfx
->pipe
, fb
->cbufs
[i
]);
87 if(!((struct nvfx_surface
*)fb
->zsbuf
)->temp
&& !all_swizzled
&& !nvfx_surface_linear_renderable(fb
->zsbuf
))
88 nvfx_surface_create_temp(&nvfx
->pipe
, fb
->zsbuf
);
95 nvfx_framebuffer_validate(struct nvfx_context
*nvfx
, unsigned prepare_result
)
97 struct pipe_framebuffer_state
*fb
= &nvfx
->framebuffer
;
98 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
99 uint32_t rt_enable
, rt_format
;
101 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
102 unsigned w
= fb
->width
;
103 unsigned h
= fb
->height
;
105 rt_enable
= (NV30_3D_RT_ENABLE_COLOR0
<< fb
->nr_cbufs
) - 1;
106 if (rt_enable
& (NV30_3D_RT_ENABLE_COLOR1
|
107 NV40_3D_RT_ENABLE_COLOR2
| NV40_3D_RT_ENABLE_COLOR3
))
108 rt_enable
|= NV30_3D_RT_ENABLE_MRT
;
110 nvfx
->state
.render_temps
= 0;
112 for (i
= 0; i
< fb
->nr_cbufs
; i
++)
113 nvfx
->state
.render_temps
|= nvfx_surface_get_render_target(fb
->cbufs
[i
], prepare_result
, &nvfx
->hw_rt
[i
]) << i
;
116 nvfx
->hw_rt
[i
].bo
= 0;
119 nvfx
->state
.render_temps
|= nvfx_surface_get_render_target(fb
->zsbuf
, prepare_result
, &nvfx
->hw_zeta
) << 7;
121 assert(util_format_get_stride(fb
->zsbuf
->format
, fb
->width
) <= nvfx
->hw_zeta
.pitch
);
122 assert(nvfx
->hw_zeta
.offset
+ nvfx
->hw_zeta
.pitch
* fb
->height
<= nvfx
->hw_zeta
.bo
->size
);
125 if (prepare_result
) {
126 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
128 rt_format
= NV30_3D_RT_FORMAT_TYPE_SWIZZLED
|
129 (util_logbase2(fb
->width
) << NV30_3D_RT_FORMAT_LOG2_WIDTH__SHIFT
) |
130 (util_logbase2(fb
->height
) << NV30_3D_RT_FORMAT_LOG2_HEIGHT__SHIFT
);
132 rt_format
= NV30_3D_RT_FORMAT_TYPE_LINEAR
;
134 if(fb
->nr_cbufs
> 0) {
135 switch (fb
->cbufs
[0]->format
) {
136 case PIPE_FORMAT_B8G8R8X8_UNORM
:
137 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8R8G8B8
;
139 case PIPE_FORMAT_B8G8R8A8_UNORM
:
141 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
143 case PIPE_FORMAT_R8G8B8X8_UNORM
:
144 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8B8G8R8
;
146 case PIPE_FORMAT_R8G8B8A8_UNORM
:
147 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8B8G8R8
;
149 case PIPE_FORMAT_B5G6R5_UNORM
:
150 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
152 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
153 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A32B32G32R32_FLOAT
;
155 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
156 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A16B16G16R16_FLOAT
;
161 } else if(fb
->zsbuf
&& util_format_get_blocksize(fb
->zsbuf
->format
) == 2)
162 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
164 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
167 switch (fb
->zsbuf
->format
) {
168 case PIPE_FORMAT_Z16_UNORM
:
169 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
171 case PIPE_FORMAT_S8_USCALED_Z24_UNORM
:
172 case PIPE_FORMAT_X8Z24_UNORM
:
174 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
179 } else if(fb
->nr_cbufs
&& util_format_get_blocksize(fb
->cbufs
[0]->format
) == 2)
180 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
182 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
184 MARK_RING(chan
, 42, 10);
186 if ((rt_enable
& NV30_3D_RT_ENABLE_COLOR0
) || fb
->zsbuf
) {
187 struct nvfx_render_target
*rt0
= &nvfx
->hw_rt
[0];
190 if(!(rt_enable
& NV30_3D_RT_ENABLE_COLOR0
))
191 rt0
= &nvfx
->hw_zeta
;
197 if (nvfx
->hw_zeta
.bo
)
198 pitch
|= (nvfx
->hw_zeta
.pitch
<< 16);
200 pitch
|= (pitch
<< 16);
203 //printf("rendering to bo %p [%i] at offset %i with pitch %i\n", rt0->bo, rt0->bo->handle, rt0->offset, pitch);
205 OUT_RING(chan
, RING_3D(NV30_3D_DMA_COLOR0
, 1));
206 OUT_RELOC(chan
, rt0
->bo
, 0,
207 rt_flags
| NOUVEAU_BO_OR
,
208 chan
->vram
->handle
, chan
->gart
->handle
);
209 OUT_RING(chan
, RING_3D(NV30_3D_COLOR0_PITCH
, 2));
210 OUT_RING(chan
, pitch
);
211 OUT_RELOC(chan
, rt0
->bo
,
212 rt0
->offset
, rt_flags
| NOUVEAU_BO_LOW
,
216 if (rt_enable
& NV30_3D_RT_ENABLE_COLOR1
) {
217 OUT_RING(chan
, RING_3D(NV30_3D_DMA_COLOR1
, 1));
218 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
, 0,
219 rt_flags
| NOUVEAU_BO_OR
,
220 chan
->vram
->handle
, chan
->gart
->handle
);
221 OUT_RING(chan
, RING_3D(NV30_3D_COLOR1_OFFSET
, 2));
222 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
,
223 nvfx
->hw_rt
[1].offset
, rt_flags
| NOUVEAU_BO_LOW
,
225 OUT_RING(chan
, nvfx
->hw_rt
[1].pitch
);
230 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR2
) {
231 OUT_RING(chan
, RING_3D(NV40_3D_DMA_COLOR2
, 1));
232 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
, 0,
233 rt_flags
| NOUVEAU_BO_OR
,
234 chan
->vram
->handle
, chan
->gart
->handle
);
235 OUT_RING(chan
, RING_3D(NV40_3D_COLOR2_OFFSET
, 1));
236 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
,
237 nvfx
->hw_rt
[2].offset
, rt_flags
| NOUVEAU_BO_LOW
,
239 OUT_RING(chan
, RING_3D(NV40_3D_COLOR2_PITCH
, 1));
240 OUT_RING(chan
, nvfx
->hw_rt
[2].pitch
);
243 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR3
) {
244 OUT_RING(chan
, RING_3D(NV40_3D_DMA_COLOR3
, 1));
245 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
, 0,
246 rt_flags
| NOUVEAU_BO_OR
,
247 chan
->vram
->handle
, chan
->gart
->handle
);
248 OUT_RING(chan
, RING_3D(NV40_3D_COLOR3_OFFSET
, 1));
249 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
,
250 nvfx
->hw_rt
[3].offset
, rt_flags
| NOUVEAU_BO_LOW
,
252 OUT_RING(chan
, RING_3D(NV40_3D_COLOR3_PITCH
, 1));
253 OUT_RING(chan
, nvfx
->hw_rt
[3].pitch
);
258 OUT_RING(chan
, RING_3D(NV30_3D_DMA_ZETA
, 1));
259 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
, 0,
260 rt_flags
| NOUVEAU_BO_OR
,
261 chan
->vram
->handle
, chan
->gart
->handle
);
262 OUT_RING(chan
, RING_3D(NV30_3D_ZETA_OFFSET
, 1));
263 /* TODO: reverse engineer LMA */
264 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
,
265 nvfx
->hw_zeta
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
267 OUT_RING(chan
, RING_3D(NV40_3D_ZETA_PITCH
, 1));
268 OUT_RING(chan
, nvfx
->hw_zeta
.pitch
);
271 else if(nvfx
->is_nv4x
) {
272 OUT_RING(chan
, RING_3D(NV40_3D_ZETA_PITCH
, 1));
276 OUT_RING(chan
, RING_3D(NV30_3D_RT_ENABLE
, 1));
277 OUT_RING(chan
, rt_enable
);
278 OUT_RING(chan
, RING_3D(NV30_3D_RT_HORIZ
, 3));
279 OUT_RING(chan
, (w
<< 16) | 0);
280 OUT_RING(chan
, (h
<< 16) | 0);
281 OUT_RING(chan
, rt_format
);
282 OUT_RING(chan
, RING_3D(NV30_3D_VIEWPORT_HORIZ
, 2));
283 OUT_RING(chan
, (w
<< 16) | 0);
284 OUT_RING(chan
, (h
<< 16) | 0);
285 OUT_RING(chan
, RING_3D(NV30_3D_VIEWPORT_CLIP_HORIZ(0), 2));
286 OUT_RING(chan
, ((w
- 1) << 16) | 0);
287 OUT_RING(chan
, ((h
- 1) << 16) | 0);
290 /* Wonder why this is needed, context should all be set to zero on init */
291 /* TODO: we can most likely remove this, after putting it in context init */
292 OUT_RING(chan
, RING_3D(NV30_3D_VIEWPORT_TX_ORIGIN
, 1));
295 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;
299 nvfx_framebuffer_relocate(struct nvfx_context
*nvfx
)
301 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
302 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
303 rt_flags
|= NOUVEAU_BO_DUMMY
;
304 MARK_RING(chan
, 20, 20);
306 #define DO_(var, pfx, name) \
308 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_DMA_##name, 1), rt_flags, 0, 0); \
309 OUT_RELOC(chan, var.bo, 0, \
310 rt_flags | NOUVEAU_BO_OR, \
311 chan->vram->handle, chan->gart->handle); \
312 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_##name##_OFFSET, 1), rt_flags, 0, 0); \
313 OUT_RELOC(chan, var.bo, \
314 var.offset, rt_flags | NOUVEAU_BO_LOW, \
318 #define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
324 DO_(nvfx
->hw_zeta
, NV30
, ZETA
);
325 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;