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
swzsurf_format(gl_format format)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
surf2d_format(gl_format format)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
rect_format(gl_format format)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
sifm_format(gl_format format)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
nv04_surface_copy_swizzle(struct gl_context * ctx,struct nouveau_surface * dst,struct nouveau_surface * src,int dx,int dy,int sx,int sy,int w,int h)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_pushbuf_refn refs[] = {
200 { src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
201 { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
202 };
203 struct nouveau_pushbuf *push = context_push(ctx);
204 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
205 struct nouveau_object *swzsurf = hw->swzsurf;
206 struct nv04_fifo *fifo = hw->chan->data;
207 /* Max width & height may not be the same on all HW, but must be POT */
208 const unsigned max_w = 1024;
209 const unsigned max_h = 1024;
210 unsigned sub_w = w > max_w ? max_w : w;
211 unsigned sub_h = h > max_h ? max_h : h;
212 unsigned x, y;
213
214 /* Swizzled surfaces must be POT */
215 assert(_mesa_is_pow_two(dst->width) &&
216 _mesa_is_pow_two(dst->height));
217
218 if (context_chipset(ctx) < 0x10) {
219 BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
220 PUSH_DATA (push, swzsurf->handle);
221 }
222
223 for (y = 0; y < h; y += sub_h) {
224 sub_h = MIN2(sub_h, h - y);
225
226 for (x = 0; x < w; x += sub_w) {
227 sub_w = MIN2(sub_w, w - x);
228
229 if (nouveau_pushbuf_space(push, 64, 4, 0) ||
230 nouveau_pushbuf_refn (push, refs, 2))
231 return;
232
233 BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
234 PUSH_DATA (push, fifo->vram);
235 BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
236 PUSH_DATA (push, swzsurf_format(dst->format) |
237 log2i(dst->width) << 16 |
238 log2i(dst->height) << 24);
239 PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
240
241 BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
242 PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
243 BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
244 PUSH_DATA (push, swzsurf->handle);
245
246 BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
247 PUSH_DATA (push, sifm_format(src->format));
248 PUSH_DATA (push, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
249 PUSH_DATA (push, (y + dy) << 16 | (x + dx));
250 PUSH_DATA (push, sub_h << 16 | sub_w);
251 PUSH_DATA (push, (y + dy) << 16 | (x + dx));
252 PUSH_DATA (push, sub_h << 16 | sub_w);
253 PUSH_DATA (push, 1 << 20);
254 PUSH_DATA (push, 1 << 20);
255
256 BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
257 PUSH_DATA (push, align(sub_h, 2) << 16 | align(sub_w, 2));
258 PUSH_DATA (push, src->pitch |
259 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
260 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
261 PUSH_RELOC(push, src->bo, src->offset + (y + sy) * src->pitch +
262 (x + sx) * src->cpp, NOUVEAU_BO_LOW, 0, 0);
263 PUSH_DATA (push, 0);
264 }
265 }
266
267 if (context_chipset(ctx) < 0x10) {
268 BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
269 PUSH_DATA (push, hw->surf3d->handle);
270 }
271 }
272
273 static void
nv04_surface_copy_m2mf(struct gl_context * ctx,struct nouveau_surface * dst,struct nouveau_surface * src,int dx,int dy,int sx,int sy,int w,int h)274 nv04_surface_copy_m2mf(struct gl_context *ctx,
275 struct nouveau_surface *dst,
276 struct nouveau_surface *src,
277 int dx, int dy, int sx, int sy,
278 int w, int h)
279 {
280 struct nouveau_pushbuf_refn refs[] = {
281 { src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
282 { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
283 };
284 struct nouveau_pushbuf *push = context_push(ctx);
285 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
286 struct nv04_fifo *fifo = hw->chan->data;
287 unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
288 unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;
289
290 while (h) {
291 int count = (h > 2047) ? 2047 : h;
292
293 if (nouveau_pushbuf_space(push, 16, 4, 0) ||
294 nouveau_pushbuf_refn (push, refs, 2))
295 return;
296
297 BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
298 PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
299 PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
300 BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
301 PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
302 PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
303 PUSH_DATA (push, src->pitch);
304 PUSH_DATA (push, dst->pitch);
305 PUSH_DATA (push, w * src->cpp);
306 PUSH_DATA (push, count);
307 PUSH_DATA (push, 0x0101);
308 PUSH_DATA (push, 0);
309
310 src_offset += src->pitch * count;
311 dst_offset += dst->pitch * count;
312 h -= count;
313 }
314 }
315
316 typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
317 unsigned x, unsigned y);
318
319 static unsigned
get_linear_offset(struct nouveau_surface * s,unsigned x,unsigned y)320 get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y)
321 {
322 return x * s->cpp + y * s->pitch;
323 }
324
325 static unsigned
get_swizzled_offset(struct nouveau_surface * s,unsigned x,unsigned y)326 get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
327 {
328 unsigned k = log2i(MIN2(s->width, s->height));
329
330 unsigned u = (x & 0x001) << 0 |
331 (x & 0x002) << 1 |
332 (x & 0x004) << 2 |
333 (x & 0x008) << 3 |
334 (x & 0x010) << 4 |
335 (x & 0x020) << 5 |
336 (x & 0x040) << 6 |
337 (x & 0x080) << 7 |
338 (x & 0x100) << 8 |
339 (x & 0x200) << 9 |
340 (x & 0x400) << 10 |
341 (x & 0x800) << 11;
342
343 unsigned v = (y & 0x001) << 1 |
344 (y & 0x002) << 2 |
345 (y & 0x004) << 3 |
346 (y & 0x008) << 4 |
347 (y & 0x010) << 5 |
348 (y & 0x020) << 6 |
349 (y & 0x040) << 7 |
350 (y & 0x080) << 8 |
351 (y & 0x100) << 9 |
352 (y & 0x200) << 10 |
353 (y & 0x400) << 11 |
354 (y & 0x800) << 12;
355
356 return s->cpp * (((u | v) & ~(~0 << 2*k)) |
357 (x & (~0 << k)) << k |
358 (y & (~0 << k)) << k);
359 }
360
361 static void
nv04_surface_copy_cpu(struct gl_context * ctx,struct nouveau_surface * dst,struct nouveau_surface * src,int dx,int dy,int sx,int sy,int w,int h)362 nv04_surface_copy_cpu(struct gl_context *ctx,
363 struct nouveau_surface *dst,
364 struct nouveau_surface *src,
365 int dx, int dy, int sx, int sy,
366 int w, int h)
367 {
368 int x, y;
369 get_offset_t get_dst = (dst->layout == SWIZZLED ?
370 get_swizzled_offset : get_linear_offset);
371 get_offset_t get_src = (src->layout == SWIZZLED ?
372 get_swizzled_offset : get_linear_offset);
373 void *dp, *sp;
374
375 nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, context_client(ctx));
376 nouveau_bo_map(src->bo, NOUVEAU_BO_RD, context_client(ctx));
377
378 dp = dst->bo->map + dst->offset;
379 sp = src->bo->map + src->offset;
380
381 for (y = 0; y < h; y++) {
382 for (x = 0; x < w; x++) {
383 memcpy(dp + get_dst(dst, dx + x, dy + y),
384 sp + get_src(src, sx + x, sy + y), dst->cpp);
385 }
386 }
387 }
388
389 void
nv04_surface_copy(struct gl_context * ctx,struct nouveau_surface * dst,struct nouveau_surface * src,int dx,int dy,int sx,int sy,int w,int h)390 nv04_surface_copy(struct gl_context *ctx,
391 struct nouveau_surface *dst,
392 struct nouveau_surface *src,
393 int dx, int dy, int sx, int sy,
394 int w, int h)
395 {
396 if (_mesa_is_format_compressed(src->format)) {
397 sx = get_format_blocksx(src->format, sx);
398 sy = get_format_blocksy(src->format, sy);
399 dx = get_format_blocksx(dst->format, dx);
400 dy = get_format_blocksy(dst->format, dy);
401 w = get_format_blocksx(src->format, w);
402 h = get_format_blocksy(src->format, h);
403 }
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
nv04_surface_fill(struct gl_context * ctx,struct nouveau_surface * dst,unsigned mask,unsigned value,int dx,int dy,int w,int h)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_pushbuf_refn refs[] = {
430 { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
431 };
432 struct nouveau_pushbuf *push = context_push(ctx);
433 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
434 struct nv04_fifo *fifo = hw->chan->data;
435
436 if (nouveau_pushbuf_space(push, 64, 4, 0) ||
437 nouveau_pushbuf_refn (push, refs, 1))
438 return;
439
440 BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
441 PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
442 PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
443 BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
444 PUSH_DATA (push, surf2d_format(dst->format));
445 PUSH_DATA (push, (dst->pitch << 16) | dst->pitch);
446 PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
447 PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
448
449 BEGIN_NV04(push, NV01_PATT(COLOR_FORMAT), 1);
450 PUSH_DATA (push, rect_format(dst->format));
451 BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR1), 1);
452 PUSH_DATA (push, mask | ~0ll << (8 * dst->cpp));
453
454 BEGIN_NV04(push, NV04_GDI(COLOR_FORMAT), 1);
455 PUSH_DATA (push, rect_format(dst->format));
456 BEGIN_NV04(push, NV04_GDI(COLOR1_A), 1);
457 PUSH_DATA (push, value);
458 BEGIN_NV04(push, NV04_GDI(UNCLIPPED_RECTANGLE_POINT(0)), 2);
459 PUSH_DATA (push, (dx << 16) | dy);
460 PUSH_DATA (push, ( w << 16) | h);
461 }
462
463 void
nv04_surface_takedown(struct gl_context * ctx)464 nv04_surface_takedown(struct gl_context *ctx)
465 {
466 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
467
468 nouveau_object_del(&hw->swzsurf);
469 nouveau_object_del(&hw->sifm);
470 nouveau_object_del(&hw->rect);
471 nouveau_object_del(&hw->rop);
472 nouveau_object_del(&hw->patt);
473 nouveau_object_del(&hw->surf2d);
474 nouveau_object_del(&hw->m2mf);
475 nouveau_object_del(&hw->ntfy);
476 }
477
478 GLboolean
nv04_surface_init(struct gl_context * ctx)479 nv04_surface_init(struct gl_context *ctx)
480 {
481 struct nouveau_pushbuf *push = context_push(ctx);
482 struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
483 struct nouveau_object *chan = hw->chan;
484 unsigned handle = 0x88000000, class;
485 int ret;
486
487 /* Notifier object. */
488 ret = nouveau_object_new(chan, handle++, NOUVEAU_NOTIFIER_CLASS,
489 &(struct nv04_notify) {
490 .length = 32,
491 }, sizeof(struct nv04_notify), &hw->ntfy);
492 if (ret)
493 goto fail;
494
495 /* Memory to memory format. */
496 ret = nouveau_object_new(chan, handle++, NV03_M2MF_CLASS,
497 NULL, 0, &hw->m2mf);
498 if (ret)
499 goto fail;
500
501 BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
502 PUSH_DATA (push, hw->m2mf->handle);
503 BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
504 PUSH_DATA (push, hw->ntfy->handle);
505
506 /* Context surfaces 2D. */
507 if (context_chipset(ctx) < 0x10)
508 class = NV04_SURFACE_2D_CLASS;
509 else
510 class = NV10_SURFACE_2D_CLASS;
511
512 ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->surf2d);
513 if (ret)
514 goto fail;
515
516 BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
517 PUSH_DATA (push, hw->surf2d->handle);
518
519 /* Raster op. */
520 ret = nouveau_object_new(chan, handle++, NV03_ROP_CLASS,
521 NULL, 0, &hw->rop);
522 if (ret)
523 goto fail;
524
525 BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
526 PUSH_DATA (push, hw->rop->handle);
527 BEGIN_NV04(push, NV01_ROP(DMA_NOTIFY), 1);
528 PUSH_DATA (push, hw->ntfy->handle);
529
530 BEGIN_NV04(push, NV01_ROP(ROP), 1);
531 PUSH_DATA (push, 0xca); /* DPSDxax in the GDI speech. */
532
533 /* Image pattern. */
534 ret = nouveau_object_new(chan, handle++, NV04_PATTERN_CLASS,
535 NULL, 0, &hw->patt);
536 if (ret)
537 goto fail;
538
539 BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
540 PUSH_DATA (push, hw->patt->handle);
541 BEGIN_NV04(push, NV01_PATT(DMA_NOTIFY), 1);
542 PUSH_DATA (push, hw->ntfy->handle);
543
544 BEGIN_NV04(push, NV01_PATT(MONOCHROME_FORMAT), 3);
545 PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
546 PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
547 PUSH_DATA (push, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
548
549 BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR0), 4);
550 PUSH_DATA (push, 0);
551 PUSH_DATA (push, 0);
552 PUSH_DATA (push, ~0);
553 PUSH_DATA (push, ~0);
554
555 /* GDI rectangle text. */
556 ret = nouveau_object_new(chan, handle++, NV04_GDI_CLASS,
557 NULL, 0, &hw->rect);
558 if (ret)
559 goto fail;
560
561 BEGIN_NV04(push, NV01_SUBC(GDI, OBJECT), 1);
562 PUSH_DATA (push, hw->rect->handle);
563 BEGIN_NV04(push, NV04_GDI(DMA_NOTIFY), 1);
564 PUSH_DATA (push, hw->ntfy->handle);
565 BEGIN_NV04(push, NV04_GDI(SURFACE), 1);
566 PUSH_DATA (push, hw->surf2d->handle);
567 BEGIN_NV04(push, NV04_GDI(ROP), 1);
568 PUSH_DATA (push, hw->rop->handle);
569 BEGIN_NV04(push, NV04_GDI(PATTERN), 1);
570 PUSH_DATA (push, hw->patt->handle);
571
572 BEGIN_NV04(push, NV04_GDI(OPERATION), 1);
573 PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
574 BEGIN_NV04(push, NV04_GDI(MONOCHROME_FORMAT), 1);
575 PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
576
577 /* Swizzled surface. */
578 if (context_chipset(ctx) < 0x20)
579 class = NV04_SURFACE_SWZ_CLASS;
580 else
581 class = NV20_SURFACE_SWZ_CLASS;
582
583 ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->swzsurf);
584 if (ret)
585 goto fail;
586
587 BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
588 PUSH_DATA (push, hw->swzsurf->handle);
589
590 /* Scaled image from memory. */
591 if (context_chipset(ctx) < 0x10)
592 class = NV04_SIFM_CLASS;
593 else
594 class = NV10_SIFM_CLASS;
595
596 ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->sifm);
597 if (ret)
598 goto fail;
599
600 BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
601 PUSH_DATA (push, hw->sifm->handle);
602
603 if (context_chipset(ctx) >= 0x10) {
604 BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
605 PUSH_DATA (push, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
606 }
607
608 return GL_TRUE;
609
610 fail:
611 nv04_surface_takedown(ctx);
612 return GL_FALSE;
613 }
614