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 uint32_t rt_enable
= 0, rt_format
= 0;
13 int i
, colour_format
= 0, zeta_format
= 0;
15 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
16 unsigned w
= fb
->width
;
17 unsigned h
= fb
->height
;
18 int colour_bits
= 32, zeta_bits
= 32;
21 assert(fb
->nr_cbufs
<= 2);
23 assert(fb
->nr_cbufs
<= 4);
25 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
27 assert(colour_format
== fb
->cbufs
[i
]->format
);
29 colour_format
= fb
->cbufs
[i
]->format
;
31 rt_enable
|= (NV34TCL_RT_ENABLE_COLOR0
<< i
);
32 nvfx
->hw_rt
[i
].bo
= nvfx_surface_buffer(fb
->cbufs
[i
]);
33 nvfx
->hw_rt
[i
].offset
= fb
->cbufs
[i
]->offset
;
34 nvfx
->hw_rt
[i
].pitch
= ((struct nv04_surface
*)fb
->cbufs
[i
])->pitch
;
37 nvfx
->hw_rt
[i
].bo
= 0;
39 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR1
|
40 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
))
41 rt_enable
|= NV34TCL_RT_ENABLE_MRT
;
44 zeta_format
= fb
->zsbuf
->format
;
45 nvfx
->hw_zeta
.bo
= nvfx_surface_buffer(fb
->zsbuf
);
46 nvfx
->hw_zeta
.offset
= fb
->zsbuf
->offset
;
47 nvfx
->hw_zeta
.pitch
= ((struct nv04_surface
*)fb
->zsbuf
)->pitch
;
52 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR0
| NV34TCL_RT_ENABLE_COLOR1
|
53 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
)) {
54 /* Render to at least a colour buffer */
55 if (!(fb
->cbufs
[0]->texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
)) {
56 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
57 for (i
= 1; i
< fb
->nr_cbufs
; i
++)
58 assert(!(fb
->cbufs
[i
]->texture
->flags
& NVFX_RESOURCE_FLAG_LINEAR
));
60 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
61 (log2i(fb
->cbufs
[0]->width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
62 (log2i(fb
->cbufs
[0]->height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
65 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
66 } else if (fb
->zsbuf
) {
69 /* Render to depth buffer only */
70 if (!(fb
->zsbuf
->texture
->usage
& NVFX_RESOURCE_FLAG_LINEAR
)) {
71 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
73 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
74 (log2i(fb
->zsbuf
->width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
75 (log2i(fb
->zsbuf
->height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
78 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
83 switch (colour_format
) {
84 case PIPE_FORMAT_B8G8R8X8_UNORM
:
85 rt_format
|= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8
;
87 case PIPE_FORMAT_B8G8R8A8_UNORM
:
89 rt_format
|= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8
;
91 case PIPE_FORMAT_B5G6R5_UNORM
:
92 rt_format
|= NV34TCL_RT_FORMAT_COLOR_R5G6B5
;
99 switch (zeta_format
) {
100 case PIPE_FORMAT_Z16_UNORM
:
101 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z16
;
104 case PIPE_FORMAT_S8_USCALED_Z24_UNORM
:
105 case PIPE_FORMAT_X8Z24_UNORM
:
107 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z24S8
;
113 if ((!nvfx
->is_nv4x
) && colour_bits
> zeta_bits
) {
114 /* TODO: does this limitation really exist?
115 TODO: can it be worked around somehow? */
119 if ((rt_enable
& NV34TCL_RT_ENABLE_COLOR0
)
120 || ((!nvfx
->is_nv4x
) && depth_only
)) {
121 struct nvfx_render_target
*rt0
= (depth_only
? &nvfx
->hw_zeta
: &nvfx
->hw_rt
[0]);
122 uint32_t pitch
= rt0
->pitch
;
126 if (nvfx
->hw_zeta
.bo
) {
127 pitch
|= (nvfx
->hw_zeta
.pitch
<< 16);
129 pitch
|= (pitch
<< 16);
133 OUT_RING(chan
, RING_3D(NV34TCL_DMA_COLOR0
, 1));
134 OUT_RELOC(chan
, rt0
->bo
, 0,
135 rt_flags
| NOUVEAU_BO_OR
,
136 chan
->vram
->handle
, chan
->gart
->handle
);
137 OUT_RING(chan
, RING_3D(NV34TCL_COLOR0_PITCH
, 2));
138 OUT_RING(chan
, pitch
);
139 OUT_RELOC(chan
, rt0
->bo
,
140 rt0
->offset
, rt_flags
| NOUVEAU_BO_LOW
,
144 if (rt_enable
& NV34TCL_RT_ENABLE_COLOR1
) {
145 OUT_RING(chan
, RING_3D(NV34TCL_DMA_COLOR1
, 1));
146 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
, 0,
147 rt_flags
| NOUVEAU_BO_OR
,
148 chan
->vram
->handle
, chan
->gart
->handle
);
149 OUT_RING(chan
, RING_3D(NV34TCL_COLOR1_OFFSET
, 2));
150 OUT_RELOC(chan
, nvfx
->hw_rt
[1].bo
,
151 nvfx
->hw_rt
[1].offset
, rt_flags
| NOUVEAU_BO_LOW
,
153 OUT_RING(chan
, nvfx
->hw_rt
[1].pitch
);
158 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR2
) {
159 OUT_RING(chan
, RING_3D(NV40TCL_DMA_COLOR2
, 1));
160 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
, 0,
161 rt_flags
| NOUVEAU_BO_OR
,
162 chan
->vram
->handle
, chan
->gart
->handle
);
163 OUT_RING(chan
, RING_3D(NV40TCL_COLOR2_OFFSET
, 1));
164 OUT_RELOC(chan
, nvfx
->hw_rt
[2].bo
,
165 nvfx
->hw_rt
[2].offset
, rt_flags
| NOUVEAU_BO_LOW
,
167 OUT_RING(chan
, RING_3D(NV40TCL_COLOR2_PITCH
, 1));
168 OUT_RING(chan
, nvfx
->hw_rt
[2].pitch
);
171 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR3
) {
172 OUT_RING(chan
, RING_3D(NV40TCL_DMA_COLOR3
, 1));
173 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
, 0,
174 rt_flags
| NOUVEAU_BO_OR
,
175 chan
->vram
->handle
, chan
->gart
->handle
);
176 OUT_RING(chan
, RING_3D(NV40TCL_COLOR3_OFFSET
, 1));
177 OUT_RELOC(chan
, nvfx
->hw_rt
[3].bo
,
178 nvfx
->hw_rt
[3].offset
, rt_flags
| NOUVEAU_BO_LOW
,
180 OUT_RING(chan
, RING_3D(NV40TCL_COLOR3_PITCH
, 1));
181 OUT_RING(chan
, nvfx
->hw_rt
[3].pitch
);
186 OUT_RING(chan
, RING_3D(NV34TCL_DMA_ZETA
, 1));
187 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
, 0,
188 rt_flags
| NOUVEAU_BO_OR
,
189 chan
->vram
->handle
, chan
->gart
->handle
);
190 OUT_RING(chan
, RING_3D(NV34TCL_ZETA_OFFSET
, 1));
191 /* TODO: reverse engineer LMA */
192 OUT_RELOC(chan
, nvfx
->hw_zeta
.bo
,
193 nvfx
->hw_zeta
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
195 OUT_RING(chan
, RING_3D(NV40TCL_ZETA_PITCH
, 1));
196 OUT_RING(chan
, nvfx
->hw_zeta
.pitch
);
200 OUT_RING(chan
, RING_3D(NV34TCL_RT_ENABLE
, 1));
201 OUT_RING(chan
, rt_enable
);
202 OUT_RING(chan
, RING_3D(NV34TCL_RT_HORIZ
, 3));
203 OUT_RING(chan
, (w
<< 16) | 0);
204 OUT_RING(chan
, (h
<< 16) | 0);
205 OUT_RING(chan
, rt_format
);
206 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_HORIZ
, 2));
207 OUT_RING(chan
, (w
<< 16) | 0);
208 OUT_RING(chan
, (h
<< 16) | 0);
209 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2));
210 OUT_RING(chan
, ((w
- 1) << 16) | 0);
211 OUT_RING(chan
, ((h
- 1) << 16) | 0);
212 OUT_RING(chan
, RING_3D(0x1d88, 1));
213 OUT_RING(chan
, (1 << 12) | h
);
216 /* Wonder why this is needed, context should all be set to zero on init */
217 /* TODO: we can most likely remove this, after putting it in context init */
218 OUT_RING(chan
, RING_3D(NV34TCL_VIEWPORT_TX_ORIGIN
, 1));
224 nvfx_framebuffer_relocate(struct nvfx_context
*nvfx
)
226 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
227 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
228 rt_flags
|= NOUVEAU_BO_DUMMY
;
229 MARK_RING(chan
, 20, 20);
231 #define DO_(var, pfx, name) \
233 OUT_RELOC(chan, var.bo, RING_3D(pfx##TCL_DMA_##name, 1), rt_flags, 0, 0); \
234 OUT_RELOC(chan, var.bo, 0, \
235 rt_flags | NOUVEAU_BO_OR, \
236 chan->vram->handle, chan->gart->handle); \
237 OUT_RELOC(chan, var.bo, RING_3D(pfx##TCL_##name##_OFFSET, 1), rt_flags, 0, 0); \
238 OUT_RELOC(chan, var.bo, \
239 var.offset, rt_flags | NOUVEAU_BO_LOW, \
243 #define DO(pfx, num) DO_(nvfx->hw_rt[num], pfx, COLOR##num)
249 DO_(nvfx
->hw_zeta
, NV34
, ZETA
);