• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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