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