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