1 #include "nvfx_context.h"
2 #include "nouveau/nouveau_util.h"
4 static struct pipe_buffer
*
5 nvfx_do_surface_buffer(struct pipe_surface
*surface
)
7 struct nvfx_miptree
*mt
= (struct nvfx_miptree
*)surface
->texture
;
11 #define nvfx_surface_buffer(ps) nouveau_bo(nvfx_do_surface_buffer(ps))
14 nvfx_state_framebuffer_validate(struct nvfx_context
*nvfx
)
16 struct pipe_framebuffer_state
*fb
= &nvfx
->framebuffer
;
17 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
18 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
19 struct nv04_surface
*rt
[4], *zeta
= NULL
;
20 uint32_t rt_enable
= 0, rt_format
= 0;
21 int i
, colour_format
= 0, zeta_format
= 0;
23 struct nouveau_stateobj
*so
= so_new(18, 24, 10);
24 unsigned rt_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
25 unsigned w
= fb
->width
;
26 unsigned h
= fb
->height
;
27 int colour_bits
= 32, zeta_bits
= 32;
30 assert(fb
->nr_cbufs
<= 2);
32 assert(fb
->nr_cbufs
<= 4);
34 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
36 assert(colour_format
== fb
->cbufs
[i
]->format
);
38 colour_format
= fb
->cbufs
[i
]->format
;
39 rt_enable
|= (NV34TCL_RT_ENABLE_COLOR0
<< i
);
40 rt
[i
] = (struct nv04_surface
*)fb
->cbufs
[i
];
44 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR1
|
45 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
))
46 rt_enable
|= NV34TCL_RT_ENABLE_MRT
;
49 zeta_format
= fb
->zsbuf
->format
;
50 zeta
= (struct nv04_surface
*)fb
->zsbuf
;
53 if (rt_enable
& (NV34TCL_RT_ENABLE_COLOR0
| NV34TCL_RT_ENABLE_COLOR1
|
54 NV40TCL_RT_ENABLE_COLOR2
| NV40TCL_RT_ENABLE_COLOR3
)) {
55 /* Render to at least a colour buffer */
56 if (!(rt
[0]->base
.texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
)) {
57 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
58 for (i
= 1; i
< fb
->nr_cbufs
; i
++)
59 assert(!(rt
[i
]->base
.texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
));
61 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
62 (log2i(rt
[0]->base
.width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
63 (log2i(rt
[0]->base
.height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
66 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
67 } else if (fb
->zsbuf
) {
70 /* Render to depth buffer only */
71 if (!(zeta
->base
.texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
)) {
72 assert(!(fb
->width
& (fb
->width
- 1)) && !(fb
->height
& (fb
->height
- 1)));
74 rt_format
= NV34TCL_RT_FORMAT_TYPE_SWIZZLED
|
75 (log2i(zeta
->base
.width
) << NV34TCL_RT_FORMAT_LOG2_WIDTH_SHIFT
) |
76 (log2i(zeta
->base
.height
) << NV34TCL_RT_FORMAT_LOG2_HEIGHT_SHIFT
);
79 rt_format
= NV34TCL_RT_FORMAT_TYPE_LINEAR
;
84 switch (colour_format
) {
85 case PIPE_FORMAT_B8G8R8X8_UNORM
:
86 rt_format
|= NV34TCL_RT_FORMAT_COLOR_X8R8G8B8
;
88 case PIPE_FORMAT_B8G8R8A8_UNORM
:
90 rt_format
|= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8
;
92 case PIPE_FORMAT_B5G6R5_UNORM
:
93 rt_format
|= NV34TCL_RT_FORMAT_COLOR_R5G6B5
;
100 switch (zeta_format
) {
101 case PIPE_FORMAT_Z16_UNORM
:
102 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z16
;
105 case PIPE_FORMAT_S8Z24_UNORM
:
106 case PIPE_FORMAT_X8Z24_UNORM
:
108 rt_format
|= NV34TCL_RT_FORMAT_ZETA_Z24S8
;
114 if ((!nvfx
->is_nv4x
) && colour_bits
> zeta_bits
) {
115 /* TODO: does this limitation really exist?
116 TODO: can it be worked around somehow? */
120 if ((rt_enable
& NV34TCL_RT_ENABLE_COLOR0
)
121 || ((!nvfx
->is_nv4x
) && depth_only
)) {
122 struct nv04_surface
*rt0
= (depth_only
? zeta
: rt
[0]);
123 uint32_t pitch
= rt0
->pitch
;
128 pitch
|= (zeta
->pitch
<< 16);
130 pitch
|= (pitch
<< 16);
134 so_method(so
, eng3d
, NV34TCL_DMA_COLOR0
, 1);
135 so_reloc (so
, nvfx_surface_buffer(&rt0
->base
), 0,
136 rt_flags
| NOUVEAU_BO_OR
,
137 chan
->vram
->handle
, chan
->gart
->handle
);
138 so_method(so
, eng3d
, NV34TCL_COLOR0_PITCH
, 2);
140 so_reloc (so
, nvfx_surface_buffer(&rt
[0]->base
),
141 rt0
->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
145 if (rt_enable
& NV34TCL_RT_ENABLE_COLOR1
) {
146 so_method(so
, eng3d
, NV34TCL_DMA_COLOR1
, 1);
147 so_reloc (so
, nvfx_surface_buffer(&rt
[1]->base
), 0,
148 rt_flags
| NOUVEAU_BO_OR
,
149 chan
->vram
->handle
, chan
->gart
->handle
);
150 so_method(so
, eng3d
, NV34TCL_COLOR1_OFFSET
, 2);
151 so_reloc (so
, nvfx_surface_buffer(&rt
[1]->base
),
152 rt
[1]->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
154 so_data (so
, rt
[1]->pitch
);
159 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR2
) {
160 so_method(so
, eng3d
, NV40TCL_DMA_COLOR2
, 1);
161 so_reloc (so
, nvfx_surface_buffer(&rt
[2]->base
), 0,
162 rt_flags
| NOUVEAU_BO_OR
,
163 chan
->vram
->handle
, chan
->gart
->handle
);
164 so_method(so
, eng3d
, NV40TCL_COLOR2_OFFSET
, 1);
165 so_reloc (so
, nvfx_surface_buffer(&rt
[2]->base
),
166 rt
[2]->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
168 so_method(so
, eng3d
, NV40TCL_COLOR2_PITCH
, 1);
169 so_data (so
, rt
[2]->pitch
);
172 if (rt_enable
& NV40TCL_RT_ENABLE_COLOR3
) {
173 so_method(so
, eng3d
, NV40TCL_DMA_COLOR3
, 1);
174 so_reloc (so
, nvfx_surface_buffer(&rt
[3]->base
), 0,
175 rt_flags
| NOUVEAU_BO_OR
,
176 chan
->vram
->handle
, chan
->gart
->handle
);
177 so_method(so
, eng3d
, NV40TCL_COLOR3_OFFSET
, 1);
178 so_reloc (so
, nvfx_surface_buffer(&rt
[3]->base
),
179 rt
[3]->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
,
181 so_method(so
, eng3d
, NV40TCL_COLOR3_PITCH
, 1);
182 so_data (so
, rt
[3]->pitch
);
187 so_method(so
, eng3d
, NV34TCL_DMA_ZETA
, 1);
188 so_reloc (so
, nvfx_surface_buffer(&zeta
->base
), 0,
189 rt_flags
| NOUVEAU_BO_OR
,
190 chan
->vram
->handle
, chan
->gart
->handle
);
191 so_method(so
, eng3d
, NV34TCL_ZETA_OFFSET
, 1);
192 /* TODO: reverse engineer LMA */
193 so_reloc (so
, nvfx_surface_buffer(&zeta
->base
),
194 zeta
->base
.offset
, rt_flags
| NOUVEAU_BO_LOW
, 0, 0);
196 so_method(so
, eng3d
, NV40TCL_ZETA_PITCH
, 1);
197 so_data (so
, zeta
->pitch
);
201 so_method(so
, eng3d
, NV34TCL_RT_ENABLE
, 1);
202 so_data (so
, rt_enable
);
203 so_method(so
, eng3d
, NV34TCL_RT_HORIZ
, 3);
204 so_data (so
, (w
<< 16) | 0);
205 so_data (so
, (h
<< 16) | 0);
206 so_data (so
, rt_format
);
207 so_method(so
, eng3d
, NV34TCL_VIEWPORT_HORIZ
, 2);
208 so_data (so
, (w
<< 16) | 0);
209 so_data (so
, (h
<< 16) | 0);
210 so_method(so
, eng3d
, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
211 so_data (so
, ((w
- 1) << 16) | 0);
212 so_data (so
, ((h
- 1) << 16) | 0);
213 so_method(so
, eng3d
, 0x1d88, 1);
214 so_data (so
, (1 << 12) | h
);
217 /* Wonder why this is needed, context should all be set to zero on init */
218 /* TODO: we can most likely remove this, after putting it in context init */
219 so_method(so
, eng3d
, NV34TCL_VIEWPORT_TX_ORIGIN
, 1);
223 so_ref(so
, &nvfx
->state
.hw
[NVFX_STATE_FB
]);
228 struct nvfx_state_entry nvfx_state_framebuffer
= {
229 .validate
= nvfx_state_framebuffer_validate
,