Merge branch 'lp-offset-twoside'
[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 "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 }