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 && !(((struct nvfx_surface
*)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
->u
.tex
.level
) <= 1)
20 && !(((struct nvfx_surface
*)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
= ns
->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
<= 1);
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
= NULL
;
118 nvfx
->hw_zeta
.bo
= NULL
;
121 nvfx
->state
.render_temps
|= nvfx_surface_get_render_target(fb
->zsbuf
, prepare_result
, &nvfx
->hw_zeta
) << 7;
123 assert(util_format_get_stride(fb
->zsbuf
->format
, fb
->width
) <= nvfx
->hw_zeta
.pitch
);
124 assert(nvfx
->hw_zeta
.offset
+ nvfx
->hw_zeta
.pitch
* fb
->height
<= nvfx
->hw_zeta
.bo
->size
);
127 if (prepare_result
) {
128 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
130 rt_format
= NV30_3D_RT_FORMAT_TYPE_SWIZZLED
|
131 (util_logbase2(fb
->width
) << NV30_3D_RT_FORMAT_LOG2_WIDTH__SHIFT
) |
132 (util_logbase2(fb
->height
) << NV30_3D_RT_FORMAT_LOG2_HEIGHT__SHIFT
);
134 rt_format
= NV30_3D_RT_FORMAT_TYPE_LINEAR
;
136 if(fb
->nr_cbufs
> 0) {
137 switch (fb
->cbufs
[0]->format
) {
138 case PIPE_FORMAT_B8G8R8X8_UNORM
:
139 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8R8G8B8
;
141 case PIPE_FORMAT_B8G8R8A8_UNORM
:
143 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
145 case PIPE_FORMAT_R8G8B8X8_UNORM
:
146 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8B8G8R8
;
148 case PIPE_FORMAT_R8G8B8A8_UNORM
:
149 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8B8G8R8
;
151 case PIPE_FORMAT_B5G6R5_UNORM
:
152 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
154 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
155 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A32B32G32R32_FLOAT
;
157 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
158 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A16B16G16R16_FLOAT
;
163 } else if(fb
->zsbuf
&& util_format_get_blocksize(fb
->zsbuf
->format
) == 2)
164 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
166 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
169 switch (fb
->zsbuf
->format
) {
170 case PIPE_FORMAT_Z16_UNORM
:
171 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
173 case PIPE_FORMAT_S8_USCALED_Z24_UNORM
:
174 case PIPE_FORMAT_X8Z24_UNORM
:
176 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
181 } else if(fb
->nr_cbufs
&& util_format_get_blocksize(fb
->cbufs
[0]->format
) == 2)
182 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
184 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
186 MARK_RING(chan
, 42, 10);
188 if ((rt_enable
& NV30_3D_RT_ENABLE_COLOR0
) || fb
->zsbuf
) {
189 struct nvfx_render_target
*rt0
= &nvfx
->hw_rt
[0];
192 if(!(rt_enable
& NV30_3D_RT_ENABLE_COLOR0
))
193 rt0
= &nvfx
->hw_zeta
;
199 if (nvfx
->hw_zeta
.bo
)
200 pitch
|= (nvfx
->hw_zeta
.pitch
<< 16);
202 pitch
|= (pitch
<< 16);
205 //printf("rendering to bo %p [%i] at offset %i with pitch %i\n", rt0->bo, rt0->bo->handle, rt0->offset, pitch);
207 OUT_RING(chan
, RING_3D(NV30_3D_DMA_COLOR0
, 1));
208 OUT_RELOC(chan
, rt0
->bo
, 0,
209 rt_flags
| NOUVEAU_BO_OR
,
210 chan
->vram
->handle
, chan
->gart
->handle
);
211 OUT_RING(chan
, RING_3D(NV30_3D_COLOR0_PITCH
, 2));
212 OUT_RING(chan
, pitch
);
213 OUT_RELOC(chan
, rt0
->bo
,
214 rt0
->offset
, rt_flags
| NOUVEAU_BO_LOW
,
218 if (rt_enable
& NV30_3D_RT_ENABLE_COLOR1
) {
219 OUT_RING(chan
, RING_3D(NV30_3D_DMA_COLOR1
, 1));
220 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
, 0,
221 rt_flags
| NOUVEAU_BO_OR
,
222 chan
->vram
->handle
, chan
->gart
->handle
);
223 OUT_RING(chan
, RING_3D(NV30_3D_COLOR1_OFFSET
, 2));
224 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
,
225 nvfx
->hw_rt
[1].offset
, rt_flags
| NOUVEAU_BO_LOW
,
227 OUT_RING(chan
, nvfx
->hw_rt
[1].pitch
);
232 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR2
) {
233 OUT_RING(chan
, RING_3D(NV40_3D_DMA_COLOR2
, 1));
234 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
, 0,
235 rt_flags
| NOUVEAU_BO_OR
,
236 chan
->vram
->handle
, chan
->gart
->handle
);
237 OUT_RING(chan
, RING_3D(NV40_3D_COLOR2_OFFSET
, 1));
238 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
,
239 nvfx
->hw_rt
[2].offset
, rt_flags
| NOUVEAU_BO_LOW
,
241 OUT_RING(chan
, RING_3D(NV40_3D_COLOR2_PITCH
, 1));
242 OUT_RING(chan
, nvfx
->hw_rt
[2].pitch
);
245 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR3
) {
246 OUT_RING(chan
, RING_3D(NV40_3D_DMA_COLOR3
, 1));
247 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
, 0,
248 rt_flags
| NOUVEAU_BO_OR
,
249 chan
->vram
->handle
, chan
->gart
->handle
);
250 OUT_RING(chan
, RING_3D(NV40_3D_COLOR3_OFFSET
, 1));
251 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
,
252 nvfx
->hw_rt
[3].offset
, rt_flags
| NOUVEAU_BO_LOW
,
254 OUT_RING(chan
, RING_3D(NV40_3D_COLOR3_PITCH
, 1));
255 OUT_RING(chan
, nvfx
->hw_rt
[3].pitch
);
260 OUT_RING(chan
, RING_3D(NV30_3D_DMA_ZETA
, 1));
261 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
, 0,
262 rt_flags
| NOUVEAU_BO_OR
,
263 chan
->vram
->handle
, chan
->gart
->handle
);
264 OUT_RING(chan
, RING_3D(NV30_3D_ZETA_OFFSET
, 1));
265 /* TODO: reverse engineer LMA */
266 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
,
267 nvfx
->hw_zeta
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
269 OUT_RING(chan
, RING_3D(NV40_3D_ZETA_PITCH
, 1));
270 OUT_RING(chan
, nvfx
->hw_zeta
.pitch
);
273 else if(nvfx
->is_nv4x
) {
274 OUT_RING(chan
, RING_3D(NV40_3D_ZETA_PITCH
, 1));
278 OUT_RING(chan
, RING_3D(NV30_3D_RT_ENABLE
, 1));
279 OUT_RING(chan
, rt_enable
);
280 OUT_RING(chan
, RING_3D(NV30_3D_RT_HORIZ
, 3));
281 OUT_RING(chan
, (w
<< 16) | 0);
282 OUT_RING(chan
, (h
<< 16) | 0);
283 OUT_RING(chan
, rt_format
);
284 OUT_RING(chan
, RING_3D(NV30_3D_VIEWPORT_HORIZ
, 2));
285 OUT_RING(chan
, (w
<< 16) | 0);
286 OUT_RING(chan
, (h
<< 16) | 0);
287 OUT_RING(chan
, RING_3D(NV30_3D_VIEWPORT_CLIP_HORIZ(0), 2));
288 OUT_RING(chan
, ((w
- 1) << 16) | 0);
289 OUT_RING(chan
, ((h
- 1) << 16) | 0);
292 /* Wonder why this is needed, context should all be set to zero on init */
293 /* TODO: we can most likely remove this, after putting it in context init */
294 OUT_RING(chan
, RING_3D(NV30_3D_VIEWPORT_TX_ORIGIN
, 1));
297 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;
301 nvfx_framebuffer_relocate(struct nvfx_context
*nvfx
)
303 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
304 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
305 rt_flags
|= NOUVEAU_BO_DUMMY
;
306 MARK_RING(chan
, 20, 20);
308 #define DO_(var, pfx, name) \
310 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_DMA_##name, 1), rt_flags, 0, 0); \
311 OUT_RELOC(chan, var.bo, 0, \
312 rt_flags | NOUVEAU_BO_OR, \
313 chan->vram->handle, chan->gart->handle); \
314 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_##name##_OFFSET, 1), rt_flags, 0, 0); \
315 OUT_RELOC(chan, var.bo, \
316 var.offset, rt_flags | NOUVEAU_BO_LOW, \
320 #define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
326 DO_(nvfx
->hw_zeta
, NV30
, ZETA
);
327 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;