Merge branch 'nouveau-gallium-0.1' into darktama-gallium-0.1
[mesa.git] / src / mesa / drivers / dri / nouveau_winsys / nv04_surface.c
1 #include "pipe/p_context.h"
2
3 #include "nouveau_context.h"
4
5 static INLINE int
6 nv04_surface_format(int cpp)
7 {
8 switch (cpp) {
9 case 1: return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
10 case 2: return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
11 case 4: return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
12 default:
13 return -1;
14 }
15 }
16
17 static INLINE int
18 nv04_rect_format(int cpp)
19 {
20 switch (cpp) {
21 case 1: return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
22 case 2: return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
23 case 4: return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
24 default:
25 return -1;
26 }
27 }
28
29 static void
30 nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
31 unsigned sx, unsigned sy, unsigned w, unsigned h)
32 {
33 struct pipe_surface *dst = nv->surf_dst;
34 struct pipe_surface *src = nv->surf_dst;
35 unsigned dst_offset, src_offset;
36
37 dst_offset = dst->offset + (dy * dst->pitch + dx) * dst->cpp;
38 src_offset = src->offset + (sy * src->pitch + sx) * src->cpp;
39
40 while (h) {
41 int count = (h > 2047) ? 2047 : h;
42
43 BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
44 OUT_RELOCl(src->buffer, src_offset, NOUVEAU_BO_VRAM |
45 NOUVEAU_BO_GART | NOUVEAU_BO_RD);
46 OUT_RELOCl(dst->buffer, dst_offset, NOUVEAU_BO_VRAM |
47 NOUVEAU_BO_GART | NOUVEAU_BO_WR);
48 OUT_RING (src->pitch * src->cpp);
49 OUT_RING (dst->pitch * dst->cpp);
50 OUT_RING (w * src->cpp);
51 OUT_RING (count);
52 OUT_RING (0x0101);
53 OUT_RING (0);
54
55 h -= count;
56 src_offset += src->pitch * count;
57 dst_offset += dst->pitch * count;
58 }
59 }
60
61 static void
62 nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy,
63 unsigned sx, unsigned sy, unsigned w, unsigned h)
64 {
65 BEGIN_RING(NvImageBlit, 0x0300, 3);
66 OUT_RING ((sy << 16) | sx);
67 OUT_RING ((dy << 16) | dx);
68 OUT_RING (( h << 16) | w);
69 }
70
71 static int
72 nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
73 struct pipe_surface *src)
74 {
75 int format;
76
77 if (src->cpp != dst->cpp)
78 return 1;
79
80 /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
81 * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
82 */
83 if ((src->offset & 63) || (dst->offset & 63)) {
84 BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
85 OUT_RELOCo(src->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
86 NOUVEAU_BO_RD);
87 OUT_RELOCo(dst->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
88 NOUVEAU_BO_WR);
89
90 nv->surface_copy = nv04_surface_copy_m2mf;
91 nv->surf_dst = dst;
92 nv->surf_src = src;
93 return 0;
94
95 }
96
97 if ((format = nv04_surface_format(dst->cpp)) < 0) {
98 NOUVEAU_ERR("Bad cpp = %d\n", dst->cpp);
99 return 1;
100 }
101 nv->surface_copy = nv04_surface_copy_blit;
102
103 BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
104 OUT_RELOCo(src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
105 OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
106
107 BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
108 OUT_RING (format);
109 OUT_RING (((dst->pitch * dst->cpp) << 16) | (src->pitch * src->cpp));
110 OUT_RELOCl(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
111 OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
112
113 return 0;
114 }
115
116 static void
117 nv04_surface_copy_done(struct nouveau_context *nv)
118 {
119 FIRE_RING();
120 }
121
122 static int
123 nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
124 unsigned dx, unsigned dy, unsigned w, unsigned h,
125 unsigned value)
126 {
127 int cs2d_format, gdirect_format;
128
129 if ((cs2d_format = nv04_surface_format(dst->cpp)) < 0) {
130 NOUVEAU_ERR("Bad cpp = %d\n", dst->cpp);
131 return 1;
132 }
133
134 if ((gdirect_format = nv04_rect_format(dst->cpp)) < 0) {
135 NOUVEAU_ERR("Bad cpp = %d\n", dst->cpp);
136 return 1;
137 }
138
139 BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
140 OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
141 OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
142 BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
143 OUT_RING (cs2d_format);
144 OUT_RING (((dst->pitch * dst->cpp) << 16) | (dst->pitch * dst->cpp));
145 OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
146 OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
147
148 BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
149 OUT_RING (gdirect_format);
150 BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
151 OUT_RING (value);
152 BEGIN_RING(NvGdiRect,
153 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
154 OUT_RING ((dx << 16) | dy);
155 OUT_RING (( w << 16) | h);
156
157 FIRE_RING();
158 return 0;
159 }
160
161 static int
162 nv04_surface_data(struct nouveau_context *nv, struct pipe_surface *dst,
163 unsigned dx, unsigned dy, const void *src, unsigned src_pitch,
164 unsigned sx, unsigned sy, unsigned w, unsigned h)
165 {
166 NOUVEAU_ERR("unimplemented!!\n");
167 return 0;
168 }
169
170 int
171 nouveau_surface_init_nv04(struct nouveau_context *nv)
172 {
173 unsigned class;
174 int ret;
175
176 if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, 0x39,
177 &nv->NvM2MF))) {
178 NOUVEAU_ERR("Error creating m2mf object: %d\n", ret);
179 return 1;
180 }
181 BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
182 OUT_RING (nv->sync_notifier->handle);
183
184 class = nv->chipset < 0x10 ? NV04_CONTEXT_SURFACES_2D :
185 NV10_CONTEXT_SURFACES_2D;
186 if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, class,
187 &nv->NvCtxSurf2D))) {
188 NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret);
189 return 1;
190 }
191 BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
192 OUT_RING (nv->channel->vram->handle);
193 OUT_RING (nv->channel->vram->handle);
194
195 class = nv->chipset < 0x10 ? NV_IMAGE_BLIT :
196 NV12_IMAGE_BLIT;
197 if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, class,
198 &nv->NvImageBlit))) {
199 NOUVEAU_ERR("Error creating blit object: %d\n", ret);
200 return 1;
201 }
202 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_DMA_NOTIFY, 1);
203 OUT_RING (nv->sync_notifier->handle);
204 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_SURFACE, 1);
205 OUT_RING (nv->NvCtxSurf2D->handle);
206 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
207 OUT_RING (NV_IMAGE_BLIT_OPERATION_SRCCOPY);
208
209 class = NV04_GDI_RECTANGLE_TEXT;
210 if ((ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, class,
211 &nv->NvGdiRect))) {
212 NOUVEAU_ERR("Error creating rect object: %d\n", ret);
213 return 1;
214 }
215 BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
216 OUT_RING (nv->sync_notifier->handle);
217 BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
218 OUT_RING (nv->NvCtxSurf2D->handle);
219 BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
220 OUT_RING (NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY);
221 BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
222 OUT_RING (NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
223
224 nv->surface_copy_prep = nv04_surface_copy_prep;
225 nv->surface_copy = nv04_surface_copy_blit;
226 nv->surface_copy_done = nv04_surface_copy_done;
227 nv->surface_fill = nv04_surface_fill;
228 nv->surface_data = nv04_surface_data;
229 return 0;
230 }
231