1 #include "nvfx_context.h"
2 #include "nvfx_resource.h"
3 #include "util/u_format.h"
6 nvfx_surface_linear_target(struct pipe_surface
* surf
)
8 return !!((struct nvfx_miptree
*)surf
->texture
)->linear_pitch
;
12 nvfx_surface_get_render_target(struct pipe_surface
* surf
,
13 struct nvfx_render_target
* target
)
15 struct nvfx_surface
* ns
= (struct nvfx_surface
*)surf
;
17 target
->bo
= ((struct nvfx_miptree
*)surf
->texture
)->base
.bo
;
18 target
->offset
= ns
->offset
;
19 target
->pitch
= align(ns
->pitch
, 64);
20 assert(target
->pitch
);
24 nvfx_framebuffer_validate(struct nvfx_context
*nvfx
)
26 struct pipe_framebuffer_state
*fb
= &nvfx
->framebuffer
;
27 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
28 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
29 uint32_t rt_enable
, rt_format
;
31 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
32 unsigned w
= fb
->width
;
33 unsigned h
= fb
->height
;
34 int all_swizzled
=1 , cb_format
= 0;
36 /* do some sanity checks on the render target state and check if the targets
39 nvfx
->is_nv4x
? assert(fb
->nr_cbufs
<= 4) : assert(fb
->nr_cbufs
<= 1);
40 if(fb
->nr_cbufs
&& fb
->zsbuf
)
41 assert(util_format_get_blocksize(fb
->cbufs
[0]->format
) ==
42 util_format_get_blocksize(fb
->zsbuf
->format
));
44 for(i
= 0; i
< fb
->nr_cbufs
; i
++) {
46 assert(cb_format
== fb
->cbufs
[i
]->format
);
48 cb_format
= fb
->cbufs
[i
]->format
;
50 if(nvfx_surface_linear_target(fb
->cbufs
[i
]))
54 if(fb
->zsbuf
&& nvfx_surface_linear_target(fb
->zsbuf
))
57 rt_enable
= (NV30_3D_RT_ENABLE_COLOR0
<< fb
->nr_cbufs
) - 1;
58 if(rt_enable
& (NV30_3D_RT_ENABLE_COLOR1
|
59 NV40_3D_RT_ENABLE_COLOR2
| NV40_3D_RT_ENABLE_COLOR3
))
60 rt_enable
|= NV30_3D_RT_ENABLE_MRT
;
62 for(i
= 0; i
< fb
->nr_cbufs
; i
++)
63 nvfx_surface_get_render_target(fb
->cbufs
[i
], &nvfx
->hw_rt
[i
]);
66 nvfx
->hw_rt
[i
].bo
= NULL
;
68 nvfx
->hw_zeta
.bo
= NULL
;
71 nvfx_surface_get_render_target(fb
->zsbuf
, &nvfx
->hw_zeta
);
72 assert(util_format_get_stride(fb
->zsbuf
->format
, fb
->width
) <=
77 /* hardware rounds down render target offset to 64 bytes,
78 * but surfaces with a size of 2x2 pixel (16bpp) or 1x1 pixel (32bpp)
79 * have an unaligned start address, for those two important square
80 * formats we can hack around this limitation by adjusting the viewport
82 if(nvfx
->hw_rt
[0].offset
& 63) {
83 int delta
= nvfx
->hw_rt
[0].offset
& 63;
86 nvfx
->viewport
.translate
[0] += delta
/
87 (util_format_get_blocksize(fb
->cbufs
[0]->format
) * 2);
88 nvfx
->dirty
|= NVFX_NEW_VIEWPORT
;
91 rt_format
= NV30_3D_RT_FORMAT_TYPE_SWIZZLED
|
92 (util_logbase2(w
) << NV30_3D_RT_FORMAT_LOG2_WIDTH__SHIFT
) |
93 (util_logbase2(h
) << NV30_3D_RT_FORMAT_LOG2_HEIGHT__SHIFT
);
95 rt_format
= NV30_3D_RT_FORMAT_TYPE_LINEAR
;
98 if(fb
->nr_cbufs
> 0) {
99 switch (fb
->cbufs
[0]->format
) {
100 case PIPE_FORMAT_B8G8R8X8_UNORM
:
101 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8R8G8B8
;
103 case PIPE_FORMAT_B8G8R8A8_UNORM
:
105 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
107 case PIPE_FORMAT_R8G8B8X8_UNORM
:
108 rt_format
|= NV30_3D_RT_FORMAT_COLOR_X8B8G8R8
;
110 case PIPE_FORMAT_R8G8B8A8_UNORM
:
111 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8B8G8R8
;
113 case PIPE_FORMAT_B5G6R5_UNORM
:
114 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
116 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
117 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A32B32G32R32_FLOAT
;
119 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
120 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A16B16G16R16_FLOAT
;
125 } else if(fb
->zsbuf
&& util_format_get_blocksize(fb
->zsbuf
->format
) == 2)
126 rt_format
|= NV30_3D_RT_FORMAT_COLOR_R5G6B5
;
128 rt_format
|= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8
;
131 switch (fb
->zsbuf
->format
) {
132 case PIPE_FORMAT_Z16_UNORM
:
133 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
135 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
136 case PIPE_FORMAT_X8Z24_UNORM
:
138 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
143 } else if(fb
->nr_cbufs
&& util_format_get_blocksize(fb
->cbufs
[0]->format
) == 2)
144 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z16
;
146 rt_format
|= NV30_3D_RT_FORMAT_ZETA_Z24S8
;
148 MARK_RING(chan
, 42, 10);
150 if ((rt_enable
& NV30_3D_RT_ENABLE_COLOR0
) || fb
->zsbuf
) {
151 struct nvfx_render_target
*rt0
= &nvfx
->hw_rt
[0];
154 if(!(rt_enable
& NV30_3D_RT_ENABLE_COLOR0
))
155 rt0
= &nvfx
->hw_zeta
;
161 if (nvfx
->hw_zeta
.bo
)
162 pitch
|= (nvfx
->hw_zeta
.pitch
<< 16);
164 pitch
|= (pitch
<< 16);
167 //printf("rendering to bo %p [%i] at offset %i with pitch %i\n", rt0->bo, rt0->bo->handle, rt0->offset, pitch);
169 BEGIN_RING(chan
, eng3d
, NV30_3D_DMA_COLOR0
, 1);
170 OUT_RELOC(chan
, rt0
->bo
, 0,
171 rt_flags
| NOUVEAU_BO_OR
,
172 chan
->vram
->handle
, chan
->gart
->handle
);
173 BEGIN_RING(chan
, eng3d
, NV30_3D_COLOR0_PITCH
, 2);
174 OUT_RING(chan
, pitch
);
175 OUT_RELOC(chan
, rt0
->bo
,
176 rt0
->offset
, rt_flags
| NOUVEAU_BO_LOW
,
180 if (rt_enable
& NV30_3D_RT_ENABLE_COLOR1
) {
181 BEGIN_RING(chan
, eng3d
, NV30_3D_DMA_COLOR1
, 1);
182 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
, 0,
183 rt_flags
| NOUVEAU_BO_OR
,
184 chan
->vram
->handle
, chan
->gart
->handle
);
185 BEGIN_RING(chan
, eng3d
, NV30_3D_COLOR1_OFFSET
, 2);
186 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
,
187 nvfx
->hw_rt
[1].offset
, rt_flags
| NOUVEAU_BO_LOW
,
189 OUT_RING(chan
, nvfx
->hw_rt
[1].pitch
);
194 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR2
) {
195 BEGIN_RING(chan
, eng3d
, NV40_3D_DMA_COLOR2
, 1);
196 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
, 0,
197 rt_flags
| NOUVEAU_BO_OR
,
198 chan
->vram
->handle
, chan
->gart
->handle
);
199 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR2_OFFSET
, 1);
200 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
,
201 nvfx
->hw_rt
[2].offset
, rt_flags
| NOUVEAU_BO_LOW
,
203 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR2_PITCH
, 1);
204 OUT_RING(chan
, nvfx
->hw_rt
[2].pitch
);
207 if (rt_enable
& NV40_3D_RT_ENABLE_COLOR3
) {
208 BEGIN_RING(chan
, eng3d
, NV40_3D_DMA_COLOR3
, 1);
209 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
, 0,
210 rt_flags
| NOUVEAU_BO_OR
,
211 chan
->vram
->handle
, chan
->gart
->handle
);
212 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR3_OFFSET
, 1);
213 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
,
214 nvfx
->hw_rt
[3].offset
, rt_flags
| NOUVEAU_BO_LOW
,
216 BEGIN_RING(chan
, eng3d
, NV40_3D_COLOR3_PITCH
, 1);
217 OUT_RING(chan
, nvfx
->hw_rt
[3].pitch
);
222 BEGIN_RING(chan
, eng3d
, NV30_3D_DMA_ZETA
, 1);
223 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
, 0,
224 rt_flags
| NOUVEAU_BO_OR
,
225 chan
->vram
->handle
, chan
->gart
->handle
);
226 BEGIN_RING(chan
, eng3d
, NV30_3D_ZETA_OFFSET
, 1);
227 /* TODO: reverse engineer LMA */
228 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
,
229 nvfx
->hw_zeta
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
231 BEGIN_RING(chan
, eng3d
, NV40_3D_ZETA_PITCH
, 1);
232 OUT_RING(chan
, nvfx
->hw_zeta
.pitch
);
235 else if(nvfx
->is_nv4x
) {
236 BEGIN_RING(chan
, eng3d
, NV40_3D_ZETA_PITCH
, 1);
240 BEGIN_RING(chan
, eng3d
, NV30_3D_RT_ENABLE
, 1);
241 OUT_RING(chan
, rt_enable
);
242 BEGIN_RING(chan
, eng3d
, NV30_3D_RT_HORIZ
, 3);
243 OUT_RING(chan
, (w
<< 16) | 0);
244 OUT_RING(chan
, (h
<< 16) | 0);
245 OUT_RING(chan
, rt_format
);
246 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_HORIZ
, 2);
247 OUT_RING(chan
, (w
<< 16) | 0);
248 OUT_RING(chan
, (h
<< 16) | 0);
249 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_CLIP_HORIZ(0), 2);
250 OUT_RING(chan
, ((w
- 1) << 16) | 0);
251 OUT_RING(chan
, ((h
- 1) << 16) | 0);
254 /* Wonder why this is needed, context should all be set to zero on init */
255 /* TODO: we can most likely remove this, after putting it in context init */
256 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_TX_ORIGIN
, 1);
259 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;
263 nvfx_framebuffer_relocate(struct nvfx_context
*nvfx
)
265 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
266 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
267 rt_flags
|= NOUVEAU_BO_DUMMY
;
268 MARK_RING(chan
, 20, 20);
270 #define DO_(var, pfx, name) \
272 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_DMA_##name, 1), rt_flags, 0, 0); \
273 OUT_RELOC(chan, var.bo, 0, \
274 rt_flags | NOUVEAU_BO_OR, \
275 chan->vram->handle, chan->gart->handle); \
276 OUT_RELOC(chan, var.bo, RING_3D(pfx##_3D_##name##_OFFSET, 1), rt_flags, 0, 0); \
277 OUT_RELOC(chan, var.bo, \
278 var.offset, rt_flags | NOUVEAU_BO_LOW, \
282 #define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
288 DO_(nvfx
->hw_zeta
, NV30
, ZETA
);
289 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_FRAMEBUFFER
;