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 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
100 uint32_t rt_enable
, rt_format
;
102 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
103 unsigned w
= fb
->width
;
104 unsigned h
= fb
->height
;
106 rt_enable
= (NV30_3D_RT_ENABLE_COLOR0
<< fb
->nr_cbufs
) - 1;
107 if (rt_enable
& (NV30_3D_RT_ENABLE_COLOR1
|
108 NV40_3D_RT_ENABLE_COLOR2
| NV40_3D_RT_ENABLE_COLOR3
))
109 rt_enable
|= NV30_3D_RT_ENABLE_MRT
;
111 nvfx
->state
.render_temps
= 0;
113 for (i
= 0; i
< fb
->nr_cbufs
; i
++)
114 nvfx
->state
.render_temps
|= nvfx_surface_get_render_target(fb
->cbufs
[i
], prepare_result
, &nvfx
->hw_rt
[i
]) << i
;
117 nvfx
->hw_rt
[i
].bo
= NULL
;
119 nvfx
->hw_zeta
.bo
= NULL
;
122 nvfx
->state
.render_temps
|= nvfx_surface_get_render_target(fb
->zsbuf
, prepare_result
, &nvfx
->hw_zeta
) << 7;
124 assert(util_format_get_stride(fb
->zsbuf
->format
, fb
->width
) <= nvfx
->hw_zeta
.pitch
);
125 assert(nvfx
->hw_zeta
.offset
+ nvfx
->hw_zeta
.pitch
* fb
->height
<= nvfx
->hw_zeta
.bo
->size
);
128 if (prepare_result
) {
129 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
131 rt_format
= NV30_3D_RT_FORMAT_TYPE_SWIZZLED
|
132 (util_logbase2(fb
->width
) << NV30_3D_RT_FORMAT_LOG2_WIDTH__SHIFT
) |
133 (util_logbase2(fb
->height
) << NV30_3D_RT_FORMAT_LOG2_HEIGHT__SHIFT
);
135 rt_format
= NV30_3D_RT_FORMAT_TYPE_LINEAR
;
137 if(fb
->nr_cbufs
> 0) {
138 switch (fb
->cbufs
[0]->format
) {
139 case PIPE_FORMAT_B8G8R8X8_UNORM
:
140 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8R8G8B8
;
142 case PIPE_FORMAT_B8G8R8A8_UNORM
:
144 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
146 case PIPE_FORMAT_R8G8B8X8_UNORM
:
147 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8B8G8R8
;
149 case PIPE_FORMAT_R8G8B8A8_UNORM
:
150 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8B8G8R8
;
152 case PIPE_FORMAT_B5G6R5_UNORM
:
153 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
155 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
156 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A32B32G32R32_FLOAT
;
158 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
159 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A16B16G16R16_FLOAT
;
164 } else if(fb
->zsbuf
&& util_format_get_blocksize(fb
->zsbuf
->format
) == 2)
165 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
167 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
170 switch (fb
->zsbuf
->format
) {
171 case PIPE_FORMAT_Z16_UNORM
:
172 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
174 case PIPE_FORMAT_S8_USCALED_Z24_UNORM
:
175 case PIPE_FORMAT_X8Z24_UNORM
:
177 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
182 } else if(fb
->nr_cbufs
&& util_format_get_blocksize(fb
->cbufs
[0]->format
) == 2)
183 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
185 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
187 MARK_RING(chan
, 42, 10);
189 if ((rt_enable
& NV30_3D_RT_ENABLE_COLOR0
) || fb
->zsbuf
) {
190 struct nvfx_render_target
*rt0
= &nvfx
->hw_rt
[0];
193 if(!(rt_enable
& NV30_3D_RT_ENABLE_COLOR0
))
194 rt0
= &nvfx
->hw_zeta
;
200 if (nvfx
->hw_zeta
.bo
)
201 pitch
|= (nvfx
->hw_zeta
.pitch
<< 16);
203 pitch
|= (pitch
<< 16);
206 //printf("rendering to bo %p [%i] at offset %i with pitch %i\n", rt0->bo, rt0->bo->handle, rt0->offset, pitch);
208 BEGIN_RING(chan
, eng3d
, NV30_3D_DMA_COLOR0
, 1);
209 OUT_RELOC(chan
, rt0
->bo
, 0,
210 rt_flags
| NOUVEAU_BO_OR
,
211 chan
->vram
->handle
, chan
->gart
->handle
);
212 BEGIN_RING(chan
, eng3d
, NV30_3D_COLOR0_PITCH
, 2);
213 OUT_RING(chan
, pitch
);
214 OUT_RELOC(chan
, rt0
->bo
,
215 rt0
->offset
, rt_flags
| NOUVEAU_BO_LOW
,
219 if (rt_enable
& NV30_3D_RT_ENABLE_COLOR1
) {
220 BEGIN_RING(chan
, eng3d
, NV30_3D_DMA_COLOR1
, 1);
221 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
, 0,
222 rt_flags
| NOUVEAU_BO_OR
,
223 chan
->vram
->handle
, chan
->gart
->handle
);
224 BEGIN_RING(chan
, eng3d
, NV30_3D_COLOR1_OFFSET
, 2);
225 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
,
226 nvfx
->hw_rt
[1].offset
, rt_flags
| NOUVEAU_BO_LOW
,
228 OUT_RING(chan
, nvfx
->hw_rt
[1].pitch
);
233 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR2
) {
234 BEGIN_RING(chan
, eng3d
, NV40_3D_DMA_COLOR2
, 1);
235 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
, 0,
236 rt_flags
| NOUVEAU_BO_OR
,
237 chan
->vram
->handle
, chan
->gart
->handle
);
238 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR2_OFFSET
, 1);
239 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
,
240 nvfx
->hw_rt
[2].offset
, rt_flags
| NOUVEAU_BO_LOW
,
242 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR2_PITCH
, 1);
243 OUT_RING(chan
, nvfx
->hw_rt
[2].pitch
);
246 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR3
) {
247 BEGIN_RING(chan
, eng3d
, NV40_3D_DMA_COLOR3
, 1);
248 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
, 0,
249 rt_flags
| NOUVEAU_BO_OR
,
250 chan
->vram
->handle
, chan
->gart
->handle
);
251 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR3_OFFSET
, 1);
252 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
,
253 nvfx
->hw_rt
[3].offset
, rt_flags
| NOUVEAU_BO_LOW
,
255 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR3_PITCH
, 1);
256 OUT_RING(chan
, nvfx
->hw_rt
[3].pitch
);
261 BEGIN_RING(chan
, eng3d
, NV30_3D_DMA_ZETA
, 1);
262 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
, 0,
263 rt_flags
| NOUVEAU_BO_OR
,
264 chan
->vram
->handle
, chan
->gart
->handle
);
265 BEGIN_RING(chan
, eng3d
, NV30_3D_ZETA_OFFSET
, 1);
266 /* TODO: reverse engineer LMA */
267 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
,
268 nvfx
->hw_zeta
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
270 BEGIN_RING(chan
, eng3d
, NV40_3D_ZETA_PITCH
, 1);
271 OUT_RING(chan
, nvfx
->hw_zeta
.pitch
);
274 else if(nvfx
->is_nv4x
) {
275 BEGIN_RING(chan
, eng3d
, NV40_3D_ZETA_PITCH
, 1);
279 BEGIN_RING(chan
, eng3d
, NV30_3D_RT_ENABLE
, 1);
280 OUT_RING(chan
, rt_enable
);
281 BEGIN_RING(chan
, eng3d
, NV30_3D_RT_HORIZ
, 3);
282 OUT_RING(chan
, (w
<< 16) | 0);
283 OUT_RING(chan
, (h
<< 16) | 0);
284 OUT_RING(chan
, rt_format
);
285 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_HORIZ
, 2);
286 OUT_RING(chan
, (w
<< 16) | 0);
287 OUT_RING(chan
, (h
<< 16) | 0);
288 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_CLIP_HORIZ(0), 2);
289 OUT_RING(chan
, ((w
- 1) << 16) | 0);
290 OUT_RING(chan
, ((h
- 1) << 16) | 0);
293 /* Wonder why this is needed, context should all be set to zero on init */
294 /* TODO: we can most likely remove this, after putting it in context init */
295 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_TX_ORIGIN
, 1);
298 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;
302 nvfx_framebuffer_relocate(struct nvfx_context
*nvfx
)
304 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
305 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
306 rt_flags
|= NOUVEAU_BO_DUMMY
;
307 MARK_RING(chan
, 20, 20);
309 #define DO_(var, pfx, name) \
311 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_DMA_##name, 1), rt_flags, 0, 0); \
312 OUT_RELOC(chan, var.bo, 0, \
313 rt_flags | NOUVEAU_BO_OR, \
314 chan->vram->handle, chan->gart->handle); \
315 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_##name##_OFFSET, 1), rt_flags, 0, 0); \
316 OUT_RELOC(chan, var.bo, \
317 var.offset, rt_flags | NOUVEAU_BO_LOW, \
321 #define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
327 DO_(nvfx
->hw_zeta
, NV30
, ZETA
);
328 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;