summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv30/nv30_state_fb.c
blob: d93e2bb5c897ce79fc996325c6757d0b6aa15302 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "nv30_context.h"

static boolean
nv30_state_framebuffer_validate(struct nv30_context *nv30)
{
	struct pipe_framebuffer_state *fb = &nv30->framebuffer;
	struct pipe_surface *rt[2], *zeta = NULL;
	uint32_t rt_enable, rt_format;
	int i, colour_format = 0, zeta_format = 0;
	struct nouveau_stateobj *so = so_new(64, 10);
	unsigned rt_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM;
	unsigned w = fb->width;
	unsigned h = fb->height;

	rt_enable = 0;
	for (i = 0; i < fb->num_cbufs; i++) {
		if (colour_format) {
			assert(colour_format == fb->cbufs[i]->format);
		} else {
			colour_format = fb->cbufs[i]->format;
			rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);
			rt[i] = fb->cbufs[i];
		}
	}

	if (rt_enable & NV34TCL_RT_ENABLE_COLOR1)
		rt_enable |= NV34TCL_RT_ENABLE_MRT;

	if (fb->zsbuf) {
		zeta_format = fb->zsbuf->format;
		zeta = fb->zsbuf;
	}

	rt_format = NV34TCL_RT_FORMAT_TYPE_LINEAR;

	switch (colour_format) {
	case PIPE_FORMAT_A8R8G8B8_UNORM:
	case 0:
		rt_format |= NV34TCL_RT_FORMAT_COLOR_A8R8G8B8;
		break;
	case PIPE_FORMAT_R5G6B5_UNORM:
		rt_format |= NV34TCL_RT_FORMAT_COLOR_R5G6B5;
		break;
	default:
		assert(0);
	}

	switch (zeta_format) {
	case PIPE_FORMAT_Z16_UNORM:
		rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16;
		break;
	case PIPE_FORMAT_Z24S8_UNORM:
	case 0:
		rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8;
		break;
	default:
		assert(0);
	}

	if (rt_enable & NV34TCL_RT_ENABLE_COLOR0) {
		uint32_t pitch = rt[0]->stride;
		if (zeta) {
			pitch |= (zeta->stride << 16);
		} else {
			pitch |= (pitch << 16);
		}

		so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR0, 1);
		so_reloc (so, rt[0]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
			  nv30->nvws->channel->vram->handle,
			  nv30->nvws->channel->gart->handle);
		so_method(so, nv30->screen->rankine, NV34TCL_COLOR0_PITCH, 2);
		so_data  (so, pitch);
		so_reloc (so, rt[0]->buffer, rt[0]->offset, rt_flags |
			  NOUVEAU_BO_LOW, 0, 0);
	}

	if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) {
		so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR1, 1);
		so_reloc (so, rt[1]->buffer, 0, rt_flags | NOUVEAU_BO_OR,
			  nv30->nvws->channel->vram->handle,
			  nv30->nvws->channel->gart->handle);
		so_method(so, nv30->screen->rankine, NV34TCL_COLOR1_OFFSET, 2);
		so_reloc (so, rt[1]->buffer, rt[1]->offset, rt_flags |
			  NOUVEAU_BO_LOW, 0, 0);
		so_data  (so, rt[1]->stride);
	}

	if (zeta_format) {
		so_method(so, nv30->screen->rankine, NV34TCL_DMA_ZETA, 1);
		so_reloc (so, zeta->buffer, 0, rt_flags | NOUVEAU_BO_OR,
			  nv30->nvws->channel->vram->handle,
			  nv30->nvws->channel->gart->handle);
		so_method(so, nv30->screen->rankine, NV34TCL_ZETA_OFFSET, 1);
		so_reloc (so, zeta->buffer, zeta->offset, rt_flags |
			  NOUVEAU_BO_LOW, 0, 0);
		/* TODO: allocate LMA depth buffer */
	}

	so_method(so, nv30->screen->rankine, NV34TCL_RT_ENABLE, 1);
	so_data  (so, rt_enable);
	so_method(so, nv30->screen->rankine, NV34TCL_RT_HORIZ, 3);
	so_data  (so, (w << 16) | 0);
	so_data  (so, (h << 16) | 0);
	so_data  (so, rt_format);
	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_HORIZ, 2);
	so_data  (so, (w << 16) | 0);
	so_data  (so, (h << 16) | 0);
	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2);
	so_data  (so, ((w - 1) << 16) | 0);
	so_data  (so, ((h - 1) << 16) | 0);
	so_method(so, nv30->screen->rankine, 0x1d88, 1);
	so_data  (so, (1 << 12) | h);
	/* Wonder why this is needed, context should all be set to zero on init */
	so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1);
	so_data  (so, 0);

	so_ref(so, &nv30->state.hw[NV30_STATE_FB]);
	return TRUE;
}

struct nv30_state_entry nv30_state_framebuffer = {
	.validate = nv30_state_framebuffer_validate,
	.dirty = {
		.pipe = NV30_NEW_FB,
		.hw = NV30_STATE_FB
	}
};