dri/nv04: Mipmapping fixes.
[mesa.git] / src / mesa / drivers / dri / nouveau / nv04_surface.c
1 /*
2 * Copyright (C) 2007-2010 The Nouveau Project.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_class.h"
29 #include "nouveau_context.h"
30 #include "nouveau_util.h"
31 #include "nv04_driver.h"
32
33 static inline int
34 swzsurf_format(gl_format format)
35 {
36 switch (format) {
37 case MESA_FORMAT_A8:
38 case MESA_FORMAT_L8:
39 case MESA_FORMAT_I8:
40 case MESA_FORMAT_RGB332:
41 case MESA_FORMAT_CI8:
42 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8;
43
44 case MESA_FORMAT_RGB565:
45 case MESA_FORMAT_RGB565_REV:
46 case MESA_FORMAT_ARGB4444:
47 case MESA_FORMAT_ARGB4444_REV:
48 case MESA_FORMAT_ARGB1555:
49 case MESA_FORMAT_RGBA5551:
50 case MESA_FORMAT_ARGB1555_REV:
51 case MESA_FORMAT_AL88:
52 case MESA_FORMAT_AL88_REV:
53 case MESA_FORMAT_YCBCR:
54 case MESA_FORMAT_YCBCR_REV:
55 case MESA_FORMAT_Z16:
56 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5;
57
58 case MESA_FORMAT_RGBA8888:
59 case MESA_FORMAT_RGBA8888_REV:
60 case MESA_FORMAT_XRGB8888:
61 case MESA_FORMAT_ARGB8888:
62 case MESA_FORMAT_ARGB8888_REV:
63 case MESA_FORMAT_S8_Z24:
64 case MESA_FORMAT_Z24_S8:
65 case MESA_FORMAT_Z32:
66 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8;
67
68 default:
69 assert(0);
70 }
71 }
72
73 static inline int
74 surf2d_format(gl_format format)
75 {
76 switch (format) {
77 case MESA_FORMAT_A8:
78 case MESA_FORMAT_L8:
79 case MESA_FORMAT_I8:
80 case MESA_FORMAT_RGB332:
81 case MESA_FORMAT_CI8:
82 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
83
84 case MESA_FORMAT_RGB565:
85 case MESA_FORMAT_RGB565_REV:
86 case MESA_FORMAT_ARGB4444:
87 case MESA_FORMAT_ARGB4444_REV:
88 case MESA_FORMAT_ARGB1555:
89 case MESA_FORMAT_RGBA5551:
90 case MESA_FORMAT_ARGB1555_REV:
91 case MESA_FORMAT_AL88:
92 case MESA_FORMAT_AL88_REV:
93 case MESA_FORMAT_YCBCR:
94 case MESA_FORMAT_YCBCR_REV:
95 case MESA_FORMAT_Z16:
96 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
97
98 case MESA_FORMAT_RGBA8888:
99 case MESA_FORMAT_RGBA8888_REV:
100 case MESA_FORMAT_XRGB8888:
101 case MESA_FORMAT_ARGB8888:
102 case MESA_FORMAT_ARGB8888_REV:
103 case MESA_FORMAT_S8_Z24:
104 case MESA_FORMAT_Z24_S8:
105 case MESA_FORMAT_Z32:
106 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
107
108 default:
109 assert(0);
110 }
111 }
112
113 static inline int
114 rect_format(gl_format format)
115 {
116 switch (format) {
117 case MESA_FORMAT_A8:
118 case MESA_FORMAT_L8:
119 case MESA_FORMAT_I8:
120 case MESA_FORMAT_RGB332:
121 case MESA_FORMAT_CI8:
122 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
123
124 case MESA_FORMAT_RGB565:
125 case MESA_FORMAT_RGB565_REV:
126 case MESA_FORMAT_ARGB4444:
127 case MESA_FORMAT_ARGB4444_REV:
128 case MESA_FORMAT_ARGB1555:
129 case MESA_FORMAT_RGBA5551:
130 case MESA_FORMAT_ARGB1555_REV:
131 case MESA_FORMAT_AL88:
132 case MESA_FORMAT_AL88_REV:
133 case MESA_FORMAT_YCBCR:
134 case MESA_FORMAT_YCBCR_REV:
135 case MESA_FORMAT_Z16:
136 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
137
138 case MESA_FORMAT_RGBA8888:
139 case MESA_FORMAT_RGBA8888_REV:
140 case MESA_FORMAT_XRGB8888:
141 case MESA_FORMAT_ARGB8888:
142 case MESA_FORMAT_ARGB8888_REV:
143 case MESA_FORMAT_S8_Z24:
144 case MESA_FORMAT_Z24_S8:
145 case MESA_FORMAT_Z32:
146 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
147
148 default:
149 assert(0);
150 }
151 }
152
153 static inline int
154 sifm_format(gl_format format)
155 {
156 switch (format) {
157 case MESA_FORMAT_A8:
158 case MESA_FORMAT_L8:
159 case MESA_FORMAT_I8:
160 case MESA_FORMAT_RGB332:
161 case MESA_FORMAT_CI8:
162 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8;
163
164 case MESA_FORMAT_RGB565:
165 case MESA_FORMAT_RGB565_REV:
166 case MESA_FORMAT_ARGB4444:
167 case MESA_FORMAT_ARGB4444_REV:
168 case MESA_FORMAT_ARGB1555:
169 case MESA_FORMAT_RGBA5551:
170 case MESA_FORMAT_ARGB1555_REV:
171 case MESA_FORMAT_AL88:
172 case MESA_FORMAT_AL88_REV:
173 case MESA_FORMAT_YCBCR:
174 case MESA_FORMAT_YCBCR_REV:
175 case MESA_FORMAT_Z16:
176 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
177
178 case MESA_FORMAT_RGBA8888:
179 case MESA_FORMAT_RGBA8888_REV:
180 case MESA_FORMAT_XRGB8888:
181 case MESA_FORMAT_ARGB8888:
182 case MESA_FORMAT_ARGB8888_REV:
183 case MESA_FORMAT_S8_Z24:
184 case MESA_FORMAT_Z24_S8:
185 case MESA_FORMAT_Z32:
186 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
187
188 default:
189 assert(0);
190 }
191 }
192
193 static void
194 nv04_surface_copy_swizzle(GLcontext *ctx,
195 struct nouveau_surface *dst,
196 struct nouveau_surface *src,
197 int dx, int dy, int sx, int sy,
198 int w, int h)
199 {
200 struct nouveau_channel *chan = context_chan(ctx);
201 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
202 struct nouveau_grobj *swzsurf = hw->swzsurf;
203 struct nouveau_grobj *sifm = hw->sifm;
204 struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE);
205 const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
206 /* Max width & height may not be the same on all HW, but must be POT */
207 const unsigned max_w = 1024;
208 const unsigned max_h = 1024;
209 unsigned sub_w = w > max_w ? max_w : w;
210 unsigned sub_h = h > max_h ? max_h : h;
211 unsigned x, y;
212
213 /* Swizzled surfaces must be POT */
214 assert(_mesa_is_pow_two(dst->width) &&
215 _mesa_is_pow_two(dst->height));
216
217 /* If area is too large to copy in one shot we must copy it in
218 * POT chunks to meet alignment requirements */
219 assert(sub_w == w || _mesa_is_pow_two(w));
220 assert(sub_h == h || _mesa_is_pow_two(h));
221
222 nouveau_bo_marko(bctx, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE,
223 src->bo, bo_flags | NOUVEAU_BO_RD);
224 nouveau_bo_marko(bctx, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE,
225 dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
226 nouveau_bo_markl(bctx, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET,
227 dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
228
229 BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
230 OUT_RING (chan, swzsurf_format(dst->format) |
231 log2i(dst->width) << 16 |
232 log2i(dst->height) << 24);
233
234 BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
235 OUT_RING (chan, swzsurf->handle);
236
237 for (y = 0; y < h; y += sub_h) {
238 sub_h = MIN2(sub_h, h - y);
239
240 for (x = 0; x < w; x += sub_w) {
241 sub_w = MIN2(sub_w, w - x);
242
243 MARK_RING(chan, 15, 1);
244
245 BEGIN_RING(chan, sifm,
246 NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 8);
247 OUT_RING(chan, sifm_format(src->format));
248 OUT_RING(chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
249 OUT_RING(chan, (y + dy) << 16 | (x + dx));
250 OUT_RING(chan, sub_h << 16 | sub_w);
251 OUT_RING(chan, (y + dy) << 16 | (x + dx));
252 OUT_RING(chan, sub_h << 16 | sub_w);
253 OUT_RING(chan, 1 << 20);
254 OUT_RING(chan, 1 << 20);
255
256 BEGIN_RING(chan, sifm,
257 NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
258 OUT_RING(chan, sub_h << 16 | sub_w);
259 OUT_RING(chan, src->pitch |
260 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
261 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
262 OUT_RELOCl(chan, src->bo, src->offset +
263 (y + sy) * src->pitch +
264 (x + sx) * src->cpp,
265 bo_flags | NOUVEAU_BO_RD);
266 OUT_RING(chan, 0);
267 }
268 }
269
270 nouveau_bo_context_reset(bctx);
271
272 if (context_chipset(ctx) < 0x10)
273 FIRE_RING(chan);
274 }
275
276 static void
277 nv04_surface_copy_m2mf(GLcontext *ctx,
278 struct nouveau_surface *dst,
279 struct nouveau_surface *src,
280 int dx, int dy, int sx, int sy,
281 int w, int h)
282 {
283 struct nouveau_channel *chan = context_chan(ctx);
284 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
285 struct nouveau_grobj *m2mf = hw->m2mf;
286 struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE);
287 const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
288 unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
289 unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;
290
291 nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN,
292 src->bo, bo_flags | NOUVEAU_BO_RD);
293 nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT,
294 dst->bo, bo_flags | NOUVEAU_BO_WR);
295
296 while (h) {
297 int count = (h > 2047) ? 2047 : h;
298
299 MARK_RING(chan, 9, 2);
300
301 BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
302 OUT_RELOCl(chan, src->bo, src_offset,
303 bo_flags | NOUVEAU_BO_RD);
304 OUT_RELOCl(chan, dst->bo, dst_offset,
305 bo_flags | NOUVEAU_BO_WR);
306 OUT_RING (chan, src->pitch);
307 OUT_RING (chan, dst->pitch);
308 OUT_RING (chan, w * src->cpp);
309 OUT_RING (chan, count);
310 OUT_RING (chan, 0x0101);
311 OUT_RING (chan, 0);
312
313 h -= count;
314 src_offset += src->pitch * count;
315 dst_offset += dst->pitch * count;
316 }
317
318 nouveau_bo_context_reset(bctx);
319
320 if (context_chipset(ctx) < 0x10)
321 FIRE_RING(chan);
322 }
323
324 typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
325 unsigned x, unsigned y);
326
327 static unsigned
328 get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y)
329 {
330 return x * s->cpp + y * s->pitch;
331 }
332
333 static unsigned
334 get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
335 {
336 unsigned k = log2i(MIN2(s->width, s->height));
337
338 unsigned u = (x & 0x001) << 0 |
339 (x & 0x002) << 1 |
340 (x & 0x004) << 2 |
341 (x & 0x008) << 3 |
342 (x & 0x010) << 4 |
343 (x & 0x020) << 5 |
344 (x & 0x040) << 6 |
345 (x & 0x080) << 7 |
346 (x & 0x100) << 8 |
347 (x & 0x200) << 9 |
348 (x & 0x400) << 10 |
349 (x & 0x800) << 11;
350
351 unsigned v = (y & 0x001) << 1 |
352 (y & 0x002) << 2 |
353 (y & 0x004) << 3 |
354 (y & 0x008) << 4 |
355 (y & 0x010) << 5 |
356 (y & 0x020) << 6 |
357 (y & 0x040) << 7 |
358 (y & 0x080) << 8 |
359 (y & 0x100) << 9 |
360 (y & 0x200) << 10 |
361 (y & 0x400) << 11 |
362 (y & 0x800) << 12;
363
364 return s->cpp * (((u | v) & ~(~0 << 2*k)) |
365 (x & (~0 << k)) << k |
366 (y & (~0 << k)) << k);
367 }
368
369 static void
370 nv04_surface_copy_cpu(GLcontext *ctx,
371 struct nouveau_surface *dst,
372 struct nouveau_surface *src,
373 int dx, int dy, int sx, int sy,
374 int w, int h)
375 {
376 int x, y;
377 get_offset_t get_dst = (dst->layout == SWIZZLED ?
378 get_swizzled_offset : get_linear_offset);
379 get_offset_t get_src = (src->layout == SWIZZLED ?
380 get_swizzled_offset : get_linear_offset);
381 void *dp, *sp;
382
383 nouveau_bo_map(dst->bo, NOUVEAU_BO_WR);
384 nouveau_bo_map(src->bo, NOUVEAU_BO_RD);
385
386 dp = dst->bo->map + dst->offset;
387 sp = src->bo->map + src->offset;
388
389 for (y = 0; y < h; y++) {
390 for (x = 0; x < w; x++) {
391 memcpy(dp + get_dst(dst, dx + x, dy + y),
392 sp + get_src(src, sx + x, sy + y), dst->cpp);
393 }
394 }
395
396 nouveau_bo_unmap(src->bo);
397 nouveau_bo_unmap(dst->bo);
398 }
399
400 void
401 nv04_surface_copy(GLcontext *ctx,
402 struct nouveau_surface *dst,
403 struct nouveau_surface *src,
404 int dx, int dy, int sx, int sy,
405 int w, int h)
406 {
407 /* Linear texture copy. */
408 if ((src->layout == LINEAR && dst->layout == LINEAR) ||
409 dst->width <= 2 || dst->height <= 1) {
410 nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
411 return;
412 }
413
414 /* Swizzle using sifm+swzsurf. */
415 if (src->layout == LINEAR && dst->layout == SWIZZLED &&
416 dst->cpp != 1 && !(dst->offset & 63)) {
417 nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h);
418 return;
419 }
420
421 /* Fallback to CPU copy. */
422 nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h);
423 }
424
425 void
426 nv04_surface_fill(GLcontext *ctx,
427 struct nouveau_surface *dst,
428 unsigned mask, unsigned value,
429 int dx, int dy, int w, int h)
430 {
431 struct nouveau_channel *chan = context_chan(ctx);
432 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
433 struct nouveau_grobj *surf2d = hw->surf2d;
434 struct nouveau_grobj *patt = hw->patt;
435 struct nouveau_grobj *rect = hw->rect;
436 unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
437
438 MARK_RING (chan, 19, 4);
439
440 BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
441 OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR);
442 OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR);
443 BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
444 OUT_RING (chan, surf2d_format(dst->format));
445 OUT_RING (chan, (dst->pitch << 16) | dst->pitch);
446 OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR);
447 OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR);
448
449 BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_COLOR_FORMAT, 1);
450 OUT_RING (chan, rect_format(dst->format));
451 BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR1, 1);
452 OUT_RING (chan, mask | ~0ll << (8 * dst->cpp));
453
454 BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
455 OUT_RING (chan, rect_format(dst->format));
456 BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
457 OUT_RING (chan, value);
458 BEGIN_RING(chan, rect,
459 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
460 OUT_RING (chan, (dx << 16) | dy);
461 OUT_RING (chan, ( w << 16) | h);
462
463 if (context_chipset(ctx) < 0x10)
464 FIRE_RING(chan);
465 }
466
467 void
468 nv04_surface_takedown(GLcontext *ctx)
469 {
470 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
471
472 nouveau_grobj_free(&hw->swzsurf);
473 nouveau_grobj_free(&hw->sifm);
474 nouveau_grobj_free(&hw->rect);
475 nouveau_grobj_free(&hw->rop);
476 nouveau_grobj_free(&hw->patt);
477 nouveau_grobj_free(&hw->surf2d);
478 nouveau_grobj_free(&hw->m2mf);
479 nouveau_notifier_free(&hw->ntfy);
480 }
481
482 GLboolean
483 nv04_surface_init(GLcontext *ctx)
484 {
485 struct nouveau_channel *chan = context_chan(ctx);
486 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
487 unsigned handle = 0x88000000, class;
488 int ret;
489
490 /* Notifier object. */
491 ret = nouveau_notifier_alloc(chan, handle++, 1, &hw->ntfy);
492 if (ret)
493 goto fail;
494
495 /* Memory to memory format. */
496 ret = nouveau_grobj_alloc(chan, handle++, NV04_MEMORY_TO_MEMORY_FORMAT,
497 &hw->m2mf);
498 if (ret)
499 goto fail;
500
501 BEGIN_RING(chan, hw->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
502 OUT_RING (chan, hw->ntfy->handle);
503
504 /* Context surfaces 2D. */
505 if (context_chipset(ctx) < 0x10)
506 class = NV04_CONTEXT_SURFACES_2D;
507 else
508 class = NV10_CONTEXT_SURFACES_2D;
509
510 ret = nouveau_grobj_alloc(chan, handle++, class, &hw->surf2d);
511 if (ret)
512 goto fail;
513
514 /* Raster op. */
515 ret = nouveau_grobj_alloc(chan, handle++, NV03_CONTEXT_ROP, &hw->rop);
516 if (ret)
517 goto fail;
518
519 BEGIN_RING(chan, hw->rop, NV03_CONTEXT_ROP_DMA_NOTIFY, 1);
520 OUT_RING (chan, hw->ntfy->handle);
521
522 BEGIN_RING(chan, hw->rop, NV03_CONTEXT_ROP_ROP, 1);
523 OUT_RING (chan, 0xca); /* DPSDxax in the GDI speech. */
524
525 /* Image pattern. */
526 ret = nouveau_grobj_alloc(chan, handle++, NV04_IMAGE_PATTERN,
527 &hw->patt);
528 if (ret)
529 goto fail;
530
531 BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_DMA_NOTIFY, 1);
532 OUT_RING (chan, hw->ntfy->handle);
533
534 BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT, 3);
535 OUT_RING (chan, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
536 OUT_RING (chan, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
537 OUT_RING (chan, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
538
539 BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4);
540 OUT_RING (chan, 0);
541 OUT_RING (chan, 0);
542 OUT_RING (chan, ~0);
543 OUT_RING (chan, ~0);
544
545 /* GDI rectangle text. */
546 ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT,
547 &hw->rect);
548 if (ret)
549 goto fail;
550
551 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
552 OUT_RING (chan, hw->ntfy->handle);
553 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
554 OUT_RING (chan, hw->surf2d->handle);
555 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_ROP, 1);
556 OUT_RING (chan, hw->rop->handle);
557 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1);
558 OUT_RING (chan, hw->patt->handle);
559
560 BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
561 OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
562 BEGIN_RING(chan, hw->rect,
563 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
564 OUT_RING (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
565
566 /* Swizzled surface. */
567 if (context_chipset(ctx) < 0x20)
568 class = NV04_SWIZZLED_SURFACE;
569 else
570 class = NV20_SWIZZLED_SURFACE;
571
572 ret = nouveau_grobj_alloc(chan, handle++, class, &hw->swzsurf);
573 if (ret)
574 goto fail;
575
576 /* Scaled image from memory. */
577 if (context_chipset(ctx) < 0x10)
578 class = NV04_SCALED_IMAGE_FROM_MEMORY;
579 else
580 class = NV10_SCALED_IMAGE_FROM_MEMORY;
581
582 ret = nouveau_grobj_alloc(chan, handle++, class, &hw->sifm);
583 if (ret)
584 goto fail;
585
586 if (context_chipset(ctx) >= 0x10) {
587 BEGIN_RING(chan, hw->sifm,
588 NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 1);
589 OUT_RING(chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
590 }
591
592 return GL_TRUE;
593
594 fail:
595 nv04_surface_takedown(ctx);
596 return GL_FALSE;
597 }