1 #include "nvfx_context.h"
2 #include "nvfx_resource.h"
3 #include "nouveau/nouveau_util.h"
6 nvfx_state_framebuffer_validate(struct nvfx_context
*nvfx
)
8 struct pipe_framebuffer_state
*fb
= &nvfx
->framebuffer
;
9 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
10 uint32_t rt_enable
= 0, rt_format
= 0;
11 int i
, colour_format
= 0, zeta_format
= 0;
13 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
14 unsigned w
= fb
->width
;
15 unsigned h
= fb
->height
;
16 int colour_bits
= 32, zeta_bits
= 32;
19 assert(fb
->nr_cbufs
<= 2);
21 assert(fb
->nr_cbufs
<= 4);
23 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
25 assert(colour_format
== fb
->cbufs
[i
]->format
);
27 colour_format
= fb
->cbufs
[i
]->format
;
29 rt_enable
|= (NV34TCL_RT_ENABLE_COLOR0
<< i
);
30 nvfx
->hw_rt
[i
].bo
= ((struct nvfx_miptree
*)fb
->cbufs
[i
]->texture
)->base
.bo
;
31 nvfx
->hw_rt
[i
].offset
= fb
->cbufs
[i
]->offset
;
32 nvfx
->hw_rt
[i
].pitch
= ((struct nvfx_surface
*)fb
->cbufs
[i
])->pitch
;
35 nvfx
->hw_rt
[i
].bo
= 0;
37 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR1
|
38 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
))
39 rt_enable
|= NV34TCL_RT_ENABLE_MRT
;
42 zeta_format
= fb
->zsbuf
->format
;
43 nvfx
->hw_zeta
.bo
= ((struct nvfx_miptree
*)fb
->zsbuf
->texture
)->base
.bo
;
44 nvfx
->hw_zeta
.offset
= fb
->zsbuf
->offset
;
45 nvfx
->hw_zeta
.pitch
= ((struct nvfx_surface
*)fb
->zsbuf
)->pitch
;
50 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR0
| NV34TCL_RT_ENABLE_COLOR1
|
51 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
)) {
52 /* Render to at least a colour buffer */
53 if (!(fb
->cbufs
[0]->texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
)) {
54 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
55 for (i
= 1; i
< fb
->nr_cbufs
; i
++)
56 assert(!(fb
->cbufs
[i
]->texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
));
58 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
59 (log2i(fb
->cbufs
[0]->width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
60 (log2i(fb
->cbufs
[0]->height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
63 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
64 } else if (fb
->zsbuf
) {
67 /* Render to depth buffer only */
68 if (!(fb
->zsbuf
->texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
)) {
69 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
71 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
72 (log2i(fb
->zsbuf
->width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
73 (log2i(fb
->zsbuf
->height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
76 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
81 switch (colour_format
) {
82 case PIPE_FORMAT_B8G8R8X8_UNORM
:
83 rt_format
|= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8
;
85 case PIPE_FORMAT_B8G8R8A8_UNORM
:
87 rt_format
|= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8
;
89 case PIPE_FORMAT_B5G6R5_UNORM
:
90 rt_format
|= NV34TCL_RT_FORMAT_COLOR_R5G6B5
;
97 switch (zeta_format
) {
98 case PIPE_FORMAT_Z16_UNORM
:
99 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z16
;
102 case PIPE_FORMAT_S8_USCALED_Z24_UNORM
:
103 case PIPE_FORMAT_X8Z24_UNORM
:
105 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z24S8
;
111 if ((!nvfx
->is_nv4x
) && colour_bits
> zeta_bits
) {
112 /* TODO: does this limitation really exist?
113 TODO: can it be worked around somehow? */
117 if ((rt_enable
& NV34TCL_RT_ENABLE_COLOR0
)
118 || ((!nvfx
->is_nv4x
) && depth_only
)) {
119 struct nvfx_render_target
*rt0
= (depth_only
? &nvfx
->hw_zeta
: &nvfx
->hw_rt
[0]);
120 uint32_t pitch
= rt0
->pitch
;
124 if (nvfx
->hw_zeta
.bo
) {
125 pitch
|= (nvfx
->hw_zeta
.pitch
<< 16);
127 pitch
|= (pitch
<< 16);
131 OUT_RING(chan
, RING_3D(NV34TCL_DMA_COLOR0
, 1));
132 OUT_RELOC(chan
, rt0
->bo
, 0,
133 rt_flags
| NOUVEAU_BO_OR
,
134 chan
->vram
->handle
, chan
->gart
->handle
);
135 OUT_RING(chan
, RING_3D(NV34TCL_COLOR0_PITCH
, 2));
136 OUT_RING(chan
, pitch
);
137 OUT_RELOC(chan
, rt0
->bo
,
138 rt0
->offset
, rt_flags
| NOUVEAU_BO_LOW
,
142 if (rt_enable
& NV34TCL_RT_ENABLE_COLOR1
) {
143 OUT_RING(chan
, RING_3D(NV34TCL_DMA_COLOR1
, 1));
144 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
, 0,
145 rt_flags
| NOUVEAU_BO_OR
,
146 chan
->vram
->handle
, chan
->gart
->handle
);
147 OUT_RING(chan
, RING_3D(NV34TCL_COLOR1_OFFSET
, 2));
148 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
,
149 nvfx
->hw_rt
[1].offset
, rt_flags
| NOUVEAU_BO_LOW
,
151 OUT_RING(chan
, nvfx
->hw_rt
[1].pitch
);
156 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR2
) {
157 OUT_RING(chan
, RING_3D(NV40TCL_DMA_COLOR2
, 1));
158 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
, 0,
159 rt_flags
| NOUVEAU_BO_OR
,
160 chan
->vram
->handle
, chan
->gart
->handle
);
161 OUT_RING(chan
, RING_3D(NV40TCL_COLOR2_OFFSET
, 1));
162 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
,
163 nvfx
->hw_rt
[2].offset
, rt_flags
| NOUVEAU_BO_LOW
,
165 OUT_RING(chan
, RING_3D(NV40TCL_COLOR2_PITCH
, 1));
166 OUT_RING(chan
, nvfx
->hw_rt
[2].pitch
);
169 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR3
) {
170 OUT_RING(chan
, RING_3D(NV40TCL_DMA_COLOR3
, 1));
171 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
, 0,
172 rt_flags
| NOUVEAU_BO_OR
,
173 chan
->vram
->handle
, chan
->gart
->handle
);
174 OUT_RING(chan
, RING_3D(NV40TCL_COLOR3_OFFSET
, 1));
175 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
,
176 nvfx
->hw_rt
[3].offset
, rt_flags
| NOUVEAU_BO_LOW
,
178 OUT_RING(chan
, RING_3D(NV40TCL_COLOR3_PITCH
, 1));
179 OUT_RING(chan
, nvfx
->hw_rt
[3].pitch
);
184 OUT_RING(chan
, RING_3D(NV34TCL_DMA_ZETA
, 1));
185 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
, 0,
186 rt_flags
| NOUVEAU_BO_OR
,
187 chan
->vram
->handle
, chan
->gart
->handle
);
188 OUT_RING(chan
, RING_3D(NV34TCL_ZETA_OFFSET
, 1));
189 /* TODO: reverse engineer LMA */
190 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
,
191 nvfx
->hw_zeta
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
193 OUT_RING(chan
, RING_3D(NV40TCL_ZETA_PITCH
, 1));
194 OUT_RING(chan
, nvfx
->hw_zeta
.pitch
);
198 OUT_RING(chan
, RING_3D(NV34TCL_RT_ENABLE
, 1));
199 OUT_RING(chan
, rt_enable
);
200 OUT_RING(chan
, RING_3D(NV34TCL_RT_HORIZ
, 3));
201 OUT_RING(chan
, (w
<< 16) | 0);
202 OUT_RING(chan
, (h
<< 16) | 0);
203 OUT_RING(chan
, rt_format
);
204 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_HORIZ
, 2));
205 OUT_RING(chan
, (w
<< 16) | 0);
206 OUT_RING(chan
, (h
<< 16) | 0);
207 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2));
208 OUT_RING(chan
, ((w
- 1) << 16) | 0);
209 OUT_RING(chan
, ((h
- 1) << 16) | 0);
210 OUT_RING(chan
, RING_3D(0x1d88, 1));
211 OUT_RING(chan
, (1 << 12) | h
);
214 /* Wonder why this is needed, context should all be set to zero on init */
215 /* TODO: we can most likely remove this, after putting it in context init */
216 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_TX_ORIGIN
, 1));
222 nvfx_framebuffer_relocate(struct nvfx_context
*nvfx
)
224 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
225 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
226 rt_flags
|= NOUVEAU_BO_DUMMY
;
227 MARK_RING(chan
, 20, 20);
229 #define DO_(var, pfx, name) \
231 OUT_RELOC(chan, var.bo, RING_3D(pfx##TCL_DMA_##name, 1), rt_flags, 0, 0); \
232 OUT_RELOC(chan, var.bo, 0, \
233 rt_flags | NOUVEAU_BO_OR, \
234 chan->vram->handle, chan->gart->handle); \
235 OUT_RELOC(chan, var.bo, RING_3D(pfx##TCL_##name##_OFFSET, 1), rt_flags, 0, 0); \
236 OUT_RELOC(chan, var.bo, \
237 var.offset, rt_flags | NOUVEAU_BO_LOW, \
241 #define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
247 DO_(nvfx
->hw_zeta
, NV34
, ZETA
);