1 #include "nvfx_context.h"
2 #include "nvfx_resource.h"
3 #include "nouveau/nouveau_util.h"
8 nvfx_state_framebuffer_validate(struct nvfx_context
*nvfx
)
10 struct pipe_framebuffer_state
*fb
= &nvfx
->framebuffer
;
11 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
12 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
13 struct nv04_surface
*rt
[4], *zeta
= NULL
;
14 uint32_t rt_enable
= 0, rt_format
= 0;
15 int i
, colour_format
= 0, zeta_format
= 0;
17 struct nouveau_stateobj
*so
= so_new(18, 24, 10);
18 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
19 unsigned w
= fb
->width
;
20 unsigned h
= fb
->height
;
21 int colour_bits
= 32, zeta_bits
= 32;
24 assert(fb
->nr_cbufs
<= 2);
26 assert(fb
->nr_cbufs
<= 4);
28 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
30 assert(colour_format
== fb
->cbufs
[i
]->format
);
32 colour_format
= fb
->cbufs
[i
]->format
;
33 rt_enable
|= (NV34TCL_RT_ENABLE_COLOR0
<< i
);
34 rt
[i
] = (struct nv04_surface
*)fb
->cbufs
[i
];
38 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR1
|
39 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
))
40 rt_enable
|= NV34TCL_RT_ENABLE_MRT
;
43 zeta_format
= fb
->zsbuf
->format
;
44 zeta
= (struct nv04_surface
*)fb
->zsbuf
;
47 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR0
| NV34TCL_RT_ENABLE_COLOR1
|
48 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
)) {
49 /* Render to at least a colour buffer */
50 if (!(rt
[0]->base
.texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
)) {
51 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
52 for (i
= 1; i
< fb
->nr_cbufs
; i
++)
53 assert(!(rt
[i
]->base
.texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
));
55 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
56 (log2i(rt
[0]->base
.width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
57 (log2i(rt
[0]->base
.height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
60 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
61 } else if (fb
->zsbuf
) {
64 /* Render to depth buffer only */
65 if (!(zeta
->base
.texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
)) {
66 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
68 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
69 (log2i(zeta
->base
.width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
70 (log2i(zeta
->base
.height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
73 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
78 switch (colour_format
) {
79 case PIPE_FORMAT_B8G8R8X8_UNORM
:
80 rt_format
|= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8
;
82 case PIPE_FORMAT_B8G8R8A8_UNORM
:
84 rt_format
|= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8
;
86 case PIPE_FORMAT_B5G6R5_UNORM
:
87 rt_format
|= NV34TCL_RT_FORMAT_COLOR_R5G6B5
;
94 switch (zeta_format
) {
95 case PIPE_FORMAT_Z16_UNORM
:
96 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z16
;
99 case PIPE_FORMAT_S8_USCALED_Z24_UNORM
:
100 case PIPE_FORMAT_X8Z24_UNORM
:
102 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z24S8
;
108 if ((!nvfx
->is_nv4x
) && colour_bits
> zeta_bits
) {
109 /* TODO: does this limitation really exist?
110 TODO: can it be worked around somehow? */
114 if ((rt_enable
& NV34TCL_RT_ENABLE_COLOR0
)
115 || ((!nvfx
->is_nv4x
) && depth_only
)) {
116 struct nv04_surface
*rt0
= (depth_only
? zeta
: rt
[0]);
117 uint32_t pitch
= rt0
->pitch
;
122 pitch
|= (zeta
->pitch
<< 16);
124 pitch
|= (pitch
<< 16);
128 so_method(so
, eng3d
, NV34TCL_DMA_COLOR0
, 1);
129 so_reloc (so
, nvfx_surface_buffer(&rt0
->base
), 0,
130 rt_flags
| NOUVEAU_BO_OR
,
131 chan
->vram
->handle
, chan
->gart
->handle
);
132 so_method(so
, eng3d
, NV34TCL_COLOR0_PITCH
, 2);
134 so_reloc (so
, nvfx_surface_buffer(&rt
[0]->base
),
135 rt0
->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
139 if (rt_enable
& NV34TCL_RT_ENABLE_COLOR1
) {
140 so_method(so
, eng3d
, NV34TCL_DMA_COLOR1
, 1);
141 so_reloc (so
, nvfx_surface_buffer(&rt
[1]->base
), 0,
142 rt_flags
| NOUVEAU_BO_OR
,
143 chan
->vram
->handle
, chan
->gart
->handle
);
144 so_method(so
, eng3d
, NV34TCL_COLOR1_OFFSET
, 2);
145 so_reloc (so
, nvfx_surface_buffer(&rt
[1]->base
),
146 rt
[1]->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
148 so_data (so
, rt
[1]->pitch
);
153 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR2
) {
154 so_method(so
, eng3d
, NV40TCL_DMA_COLOR2
, 1);
155 so_reloc (so
, nvfx_surface_buffer(&rt
[2]->base
), 0,
156 rt_flags
| NOUVEAU_BO_OR
,
157 chan
->vram
->handle
, chan
->gart
->handle
);
158 so_method(so
, eng3d
, NV40TCL_COLOR2_OFFSET
, 1);
159 so_reloc (so
, nvfx_surface_buffer(&rt
[2]->base
),
160 rt
[2]->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
162 so_method(so
, eng3d
, NV40TCL_COLOR2_PITCH
, 1);
163 so_data (so
, rt
[2]->pitch
);
166 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR3
) {
167 so_method(so
, eng3d
, NV40TCL_DMA_COLOR3
, 1);
168 so_reloc (so
, nvfx_surface_buffer(&rt
[3]->base
), 0,
169 rt_flags
| NOUVEAU_BO_OR
,
170 chan
->vram
->handle
, chan
->gart
->handle
);
171 so_method(so
, eng3d
, NV40TCL_COLOR3_OFFSET
, 1);
172 so_reloc (so
, nvfx_surface_buffer(&rt
[3]->base
),
173 rt
[3]->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
175 so_method(so
, eng3d
, NV40TCL_COLOR3_PITCH
, 1);
176 so_data (so
, rt
[3]->pitch
);
181 so_method(so
, eng3d
, NV34TCL_DMA_ZETA
, 1);
182 so_reloc (so
, nvfx_surface_buffer(&zeta
->base
), 0,
183 rt_flags
| NOUVEAU_BO_OR
,
184 chan
->vram
->handle
, chan
->gart
->handle
);
185 so_method(so
, eng3d
, NV34TCL_ZETA_OFFSET
, 1);
186 /* TODO: reverse engineer LMA */
187 so_reloc (so
, nvfx_surface_buffer(&zeta
->base
),
188 zeta
->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
190 so_method(so
, eng3d
, NV40TCL_ZETA_PITCH
, 1);
191 so_data (so
, zeta
->pitch
);
195 so_method(so
, eng3d
, NV34TCL_RT_ENABLE
, 1);
196 so_data (so
, rt_enable
);
197 so_method(so
, eng3d
, NV34TCL_RT_HORIZ
, 3);
198 so_data (so
, (w
<< 16) | 0);
199 so_data (so
, (h
<< 16) | 0);
200 so_data (so
, rt_format
);
201 so_method(so
, eng3d
, NV34TCL_VIEWPORT_HORIZ
, 2);
202 so_data (so
, (w
<< 16) | 0);
203 so_data (so
, (h
<< 16) | 0);
204 so_method(so
, eng3d
, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
205 so_data (so
, ((w
- 1) << 16) | 0);
206 so_data (so
, ((h
- 1) << 16) | 0);
207 so_method(so
, eng3d
, 0x1d88, 1);
208 so_data (so
, (1 << 12) | h
);
211 /* Wonder why this is needed, context should all be set to zero on init */
212 /* TODO: we can most likely remove this, after putting it in context init */
213 so_method(so
, eng3d
, NV34TCL_VIEWPORT_TX_ORIGIN
, 1);
217 so_ref(so
, &nvfx
->state
.hw
[NVFX_STATE_FB
]);
222 struct nvfx_state_entry nvfx_state_framebuffer
= {
223 .validate
= nvfx_state_framebuffer_validate
,