1 /* r128_state.c -- State support for r128 -*- linux-c -*-
2 * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com */
3 /*-
4 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 *
29 * $FreeBSD$
30 */
31
32 #include "dev/drm/r128.h"
33 #include "dev/drm/drmP.h"
34 #include "dev/drm/drm.h"
35 #include "dev/drm/r128_drm.h"
36 #include "dev/drm/r128_drv.h"
37
38
39 /* ================================================================
40 * CCE hardware state programming functions
41 */
42
43 static void r128_emit_clip_rects( drm_r128_private_t *dev_priv,
44 drm_clip_rect_t *boxes, int count )
45 {
46 u32 aux_sc_cntl = 0x00000000;
47 RING_LOCALS;
48 DRM_DEBUG( " %s\n", __FUNCTION__ );
49
50 BEGIN_RING( (count < 3? count: 3) * 5 + 2 );
51
52 if ( count >= 1 ) {
53 OUT_RING( CCE_PACKET0( R128_AUX1_SC_LEFT, 3 ) );
54 OUT_RING( boxes[0].x1 );
55 OUT_RING( boxes[0].x2 - 1 );
56 OUT_RING( boxes[0].y1 );
57 OUT_RING( boxes[0].y2 - 1 );
58
59 aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
60 }
61 if ( count >= 2 ) {
62 OUT_RING( CCE_PACKET0( R128_AUX2_SC_LEFT, 3 ) );
63 OUT_RING( boxes[1].x1 );
64 OUT_RING( boxes[1].x2 - 1 );
65 OUT_RING( boxes[1].y1 );
66 OUT_RING( boxes[1].y2 - 1 );
67
68 aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
69 }
70 if ( count >= 3 ) {
71 OUT_RING( CCE_PACKET0( R128_AUX3_SC_LEFT, 3 ) );
72 OUT_RING( boxes[2].x1 );
73 OUT_RING( boxes[2].x2 - 1 );
74 OUT_RING( boxes[2].y1 );
75 OUT_RING( boxes[2].y2 - 1 );
76
77 aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
78 }
79
80 OUT_RING( CCE_PACKET0( R128_AUX_SC_CNTL, 0 ) );
81 OUT_RING( aux_sc_cntl );
82
83 ADVANCE_RING();
84 }
85
86 static __inline__ void r128_emit_core( drm_r128_private_t *dev_priv )
87 {
88 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
89 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
90 RING_LOCALS;
91 DRM_DEBUG( " %s\n", __FUNCTION__ );
92
93 BEGIN_RING( 2 );
94
95 OUT_RING( CCE_PACKET0( R128_SCALE_3D_CNTL, 0 ) );
96 OUT_RING( ctx->scale_3d_cntl );
97
98 ADVANCE_RING();
99 }
100
101 static __inline__ void r128_emit_context( drm_r128_private_t *dev_priv )
102 {
103 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
104 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
105 RING_LOCALS;
106 DRM_DEBUG( " %s\n", __FUNCTION__ );
107
108 BEGIN_RING( 13 );
109
110 OUT_RING( CCE_PACKET0( R128_DST_PITCH_OFFSET_C, 11 ) );
111 OUT_RING( ctx->dst_pitch_offset_c );
112 OUT_RING( ctx->dp_gui_master_cntl_c );
113 OUT_RING( ctx->sc_top_left_c );
114 OUT_RING( ctx->sc_bottom_right_c );
115 OUT_RING( ctx->z_offset_c );
116 OUT_RING( ctx->z_pitch_c );
117 OUT_RING( ctx->z_sten_cntl_c );
118 OUT_RING( ctx->tex_cntl_c );
119 OUT_RING( ctx->misc_3d_state_cntl_reg );
120 OUT_RING( ctx->texture_clr_cmp_clr_c );
121 OUT_RING( ctx->texture_clr_cmp_msk_c );
122 OUT_RING( ctx->fog_color_c );
123
124 ADVANCE_RING();
125 }
126
127 static __inline__ void r128_emit_setup( drm_r128_private_t *dev_priv )
128 {
129 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
130 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
131 RING_LOCALS;
132 DRM_DEBUG( " %s\n", __FUNCTION__ );
133
134 BEGIN_RING( 3 );
135
136 OUT_RING( CCE_PACKET1( R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP ) );
137 OUT_RING( ctx->setup_cntl );
138 OUT_RING( ctx->pm4_vc_fpu_setup );
139
140 ADVANCE_RING();
141 }
142
143 static __inline__ void r128_emit_masks( drm_r128_private_t *dev_priv )
144 {
145 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
146 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
147 RING_LOCALS;
148 DRM_DEBUG( " %s\n", __FUNCTION__ );
149
150 BEGIN_RING( 5 );
151
152 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
153 OUT_RING( ctx->dp_write_mask );
154
155 OUT_RING( CCE_PACKET0( R128_STEN_REF_MASK_C, 1 ) );
156 OUT_RING( ctx->sten_ref_mask_c );
157 OUT_RING( ctx->plane_3d_mask_c );
158
159 ADVANCE_RING();
160 }
161
162 static __inline__ void r128_emit_window( drm_r128_private_t *dev_priv )
163 {
164 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
165 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
166 RING_LOCALS;
167 DRM_DEBUG( " %s\n", __FUNCTION__ );
168
169 BEGIN_RING( 2 );
170
171 OUT_RING( CCE_PACKET0( R128_WINDOW_XY_OFFSET, 0 ) );
172 OUT_RING( ctx->window_xy_offset );
173
174 ADVANCE_RING();
175 }
176
177 static __inline__ void r128_emit_tex0( drm_r128_private_t *dev_priv )
178 {
179 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
180 drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
181 drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
182 int i;
183 RING_LOCALS;
184 DRM_DEBUG( " %s\n", __FUNCTION__ );
185
186 BEGIN_RING( 7 + R128_MAX_TEXTURE_LEVELS );
187
188 OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C,
189 2 + R128_MAX_TEXTURE_LEVELS ) );
190 OUT_RING( tex->tex_cntl );
191 OUT_RING( tex->tex_combine_cntl );
192 OUT_RING( ctx->tex_size_pitch_c );
193 for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
194 OUT_RING( tex->tex_offset[i] );
195 }
196
197 OUT_RING( CCE_PACKET0( R128_CONSTANT_COLOR_C, 1 ) );
198 OUT_RING( ctx->constant_color_c );
199 OUT_RING( tex->tex_border_color );
200
201 ADVANCE_RING();
202 }
203
204 static __inline__ void r128_emit_tex1( drm_r128_private_t *dev_priv )
205 {
206 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
207 drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
208 int i;
209 RING_LOCALS;
210 DRM_DEBUG( " %s\n", __FUNCTION__ );
211
212 BEGIN_RING( 5 + R128_MAX_TEXTURE_LEVELS );
213
214 OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C,
215 1 + R128_MAX_TEXTURE_LEVELS ) );
216 OUT_RING( tex->tex_cntl );
217 OUT_RING( tex->tex_combine_cntl );
218 for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
219 OUT_RING( tex->tex_offset[i] );
220 }
221
222 OUT_RING( CCE_PACKET0( R128_SEC_TEXTURE_BORDER_COLOR_C, 0 ) );
223 OUT_RING( tex->tex_border_color );
224
225 ADVANCE_RING();
226 }
227
228 static __inline__ void r128_emit_state( drm_r128_private_t *dev_priv )
229 {
230 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
231 unsigned int dirty = sarea_priv->dirty;
232
233 DRM_DEBUG( "%s: dirty=0x%08x\n", __FUNCTION__, dirty );
234
235 if ( dirty & R128_UPLOAD_CORE ) {
236 r128_emit_core( dev_priv );
237 sarea_priv->dirty &= ~R128_UPLOAD_CORE;
238 }
239
240 if ( dirty & R128_UPLOAD_CONTEXT ) {
241 r128_emit_context( dev_priv );
242 sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
243 }
244
245 if ( dirty & R128_UPLOAD_SETUP ) {
246 r128_emit_setup( dev_priv );
247 sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
248 }
249
250 if ( dirty & R128_UPLOAD_MASKS ) {
251 r128_emit_masks( dev_priv );
252 sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
253 }
254
255 if ( dirty & R128_UPLOAD_WINDOW ) {
256 r128_emit_window( dev_priv );
257 sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
258 }
259
260 if ( dirty & R128_UPLOAD_TEX0 ) {
261 r128_emit_tex0( dev_priv );
262 sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
263 }
264
265 if ( dirty & R128_UPLOAD_TEX1 ) {
266 r128_emit_tex1( dev_priv );
267 sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
268 }
269
270 /* Turn off the texture cache flushing */
271 sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
272
273 sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
274 }
275
276
277 #if R128_PERFORMANCE_BOXES
278 /* ================================================================
279 * Performance monitoring functions
280 */
281
282 static void r128_clear_box( drm_r128_private_t *dev_priv,
283 int x, int y, int w, int h,
284 int r, int g, int b )
285 {
286 u32 pitch, offset;
287 u32 fb_bpp, color;
288 RING_LOCALS;
289
290 switch ( dev_priv->fb_bpp ) {
291 case 16:
292 fb_bpp = R128_GMC_DST_16BPP;
293 color = (((r & 0xf8) << 8) |
294 ((g & 0xfc) << 3) |
295 ((b & 0xf8) >> 3));
296 break;
297 case 24:
298 fb_bpp = R128_GMC_DST_24BPP;
299 color = ((r << 16) | (g << 8) | b);
300 break;
301 case 32:
302 fb_bpp = R128_GMC_DST_32BPP;
303 color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
304 break;
305 default:
306 return;
307 }
308
309 offset = dev_priv->back_offset;
310 pitch = dev_priv->back_pitch >> 3;
311
312 BEGIN_RING( 6 );
313
314 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
315 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
316 R128_GMC_BRUSH_SOLID_COLOR |
317 fb_bpp |
318 R128_GMC_SRC_DATATYPE_COLOR |
319 R128_ROP3_P |
320 R128_GMC_CLR_CMP_CNTL_DIS |
321 R128_GMC_AUX_CLIP_DIS );
322
323 OUT_RING( (pitch << 21) | (offset >> 5) );
324 OUT_RING( color );
325
326 OUT_RING( (x << 16) | y );
327 OUT_RING( (w << 16) | h );
328
329 ADVANCE_RING();
330 }
331
332 static void r128_cce_performance_boxes( drm_r128_private_t *dev_priv )
333 {
334 if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
335 r128_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
336 } else {
337 atomic_set( &dev_priv->idle_count, 0 );
338 }
339 }
340
341 #endif
342
343
344 /* ================================================================
345 * CCE command dispatch functions
346 */
347
348 static void r128_print_dirty( const char *msg, unsigned int flags )
349 {
350 DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
351 msg,
352 flags,
353 (flags & R128_UPLOAD_CORE) ? "core, " : "",
354 (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
355 (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
356 (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
357 (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
358 (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
359 (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
360 (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
361 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
362 }
363
364 static void r128_cce_dispatch_clear( drm_device_t *dev,
365 drm_r128_clear_t *clear )
366 {
367 drm_r128_private_t *dev_priv = dev->dev_private;
368 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
369 int nbox = sarea_priv->nbox;
370 drm_clip_rect_t *pbox = sarea_priv->boxes;
371 unsigned int flags = clear->flags;
372 int i;
373 RING_LOCALS;
374 DRM_DEBUG( "%s\n", __FUNCTION__ );
375
376 if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
377 unsigned int tmp = flags;
378
379 flags &= ~(R128_FRONT | R128_BACK);
380 if ( tmp & R128_FRONT ) flags |= R128_BACK;
381 if ( tmp & R128_BACK ) flags |= R128_FRONT;
382 }
383
384 for ( i = 0 ; i < nbox ; i++ ) {
385 int x = pbox[i].x1;
386 int y = pbox[i].y1;
387 int w = pbox[i].x2 - x;
388 int h = pbox[i].y2 - y;
389
390 DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%x\n",
391 pbox[i].x1, pbox[i].y1, pbox[i].x2,
392 pbox[i].y2, flags );
393
394 if ( flags & (R128_FRONT | R128_BACK) ) {
395 BEGIN_RING( 2 );
396
397 OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) );
398 OUT_RING( clear->color_mask );
399
400 ADVANCE_RING();
401 }
402
403 if ( flags & R128_FRONT ) {
404 BEGIN_RING( 6 );
405
406 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
407 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
408 R128_GMC_BRUSH_SOLID_COLOR |
409 (dev_priv->color_fmt << 8) |
410 R128_GMC_SRC_DATATYPE_COLOR |
411 R128_ROP3_P |
412 R128_GMC_CLR_CMP_CNTL_DIS |
413 R128_GMC_AUX_CLIP_DIS );
414
415 OUT_RING( dev_priv->front_pitch_offset_c );
416 OUT_RING( clear->clear_color );
417
418 OUT_RING( (x << 16) | y );
419 OUT_RING( (w << 16) | h );
420
421 ADVANCE_RING();
422 }
423
424 if ( flags & R128_BACK ) {
425 BEGIN_RING( 6 );
426
427 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
428 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
429 R128_GMC_BRUSH_SOLID_COLOR |
430 (dev_priv->color_fmt << 8) |
431 R128_GMC_SRC_DATATYPE_COLOR |
432 R128_ROP3_P |
433 R128_GMC_CLR_CMP_CNTL_DIS |
434 R128_GMC_AUX_CLIP_DIS );
435
436 OUT_RING( dev_priv->back_pitch_offset_c );
437 OUT_RING( clear->clear_color );
438
439 OUT_RING( (x << 16) | y );
440 OUT_RING( (w << 16) | h );
441
442 ADVANCE_RING();
443 }
444
445 if ( flags & R128_DEPTH ) {
446 BEGIN_RING( 6 );
447
448 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
449 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
450 R128_GMC_BRUSH_SOLID_COLOR |
451 (dev_priv->depth_fmt << 8) |
452 R128_GMC_SRC_DATATYPE_COLOR |
453 R128_ROP3_P |
454 R128_GMC_CLR_CMP_CNTL_DIS |
455 R128_GMC_AUX_CLIP_DIS |
456 R128_GMC_WR_MSK_DIS );
457
458 OUT_RING( dev_priv->depth_pitch_offset_c );
459 OUT_RING( clear->clear_depth );
460
461 OUT_RING( (x << 16) | y );
462 OUT_RING( (w << 16) | h );
463
464 ADVANCE_RING();
465 }
466 }
467 }
468
469 static void r128_cce_dispatch_swap( drm_device_t *dev )
470 {
471 drm_r128_private_t *dev_priv = dev->dev_private;
472 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
473 int nbox = sarea_priv->nbox;
474 drm_clip_rect_t *pbox = sarea_priv->boxes;
475 int i;
476 RING_LOCALS;
477 DRM_DEBUG( "%s\n", __FUNCTION__ );
478
479 #if R128_PERFORMANCE_BOXES
480 /* Do some trivial performance monitoring...
481 */
482 r128_cce_performance_boxes( dev_priv );
483 #endif
484
485 for ( i = 0 ; i < nbox ; i++ ) {
486 int x = pbox[i].x1;
487 int y = pbox[i].y1;
488 int w = pbox[i].x2 - x;
489 int h = pbox[i].y2 - y;
490
491 BEGIN_RING( 7 );
492
493 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
494 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
495 R128_GMC_DST_PITCH_OFFSET_CNTL |
496 R128_GMC_BRUSH_NONE |
497 (dev_priv->color_fmt << 8) |
498 R128_GMC_SRC_DATATYPE_COLOR |
499 R128_ROP3_S |
500 R128_DP_SRC_SOURCE_MEMORY |
501 R128_GMC_CLR_CMP_CNTL_DIS |
502 R128_GMC_AUX_CLIP_DIS |
503 R128_GMC_WR_MSK_DIS );
504
505 /* Make this work even if front & back are flipped:
506 */
507 if (dev_priv->current_page == 0) {
508 OUT_RING( dev_priv->back_pitch_offset_c );
509 OUT_RING( dev_priv->front_pitch_offset_c );
510 }
511 else {
512 OUT_RING( dev_priv->front_pitch_offset_c );
513 OUT_RING( dev_priv->back_pitch_offset_c );
514 }
515
516 OUT_RING( (x << 16) | y );
517 OUT_RING( (x << 16) | y );
518 OUT_RING( (w << 16) | h );
519
520 ADVANCE_RING();
521 }
522
523 /* Increment the frame counter. The client-side 3D driver must
524 * throttle the framerate by waiting for this value before
525 * performing the swapbuffer ioctl.
526 */
527 dev_priv->sarea_priv->last_frame++;
528
529 BEGIN_RING( 2 );
530
531 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
532 OUT_RING( dev_priv->sarea_priv->last_frame );
533
534 ADVANCE_RING();
535 }
536
537 static void r128_cce_dispatch_flip( drm_device_t *dev )
538 {
539 drm_r128_private_t *dev_priv = dev->dev_private;
540 RING_LOCALS;
541 DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
542 __FUNCTION__,
543 dev_priv->current_page,
544 dev_priv->sarea_priv->pfCurrentPage);
545
546 #if R128_PERFORMANCE_BOXES
547 /* Do some trivial performance monitoring...
548 */
549 r128_cce_performance_boxes( dev_priv );
550 #endif
551
552 BEGIN_RING( 4 );
553
554 R128_WAIT_UNTIL_PAGE_FLIPPED();
555 OUT_RING( CCE_PACKET0( R128_CRTC_OFFSET, 0 ) );
556
557 if ( dev_priv->current_page == 0 ) {
558 OUT_RING( dev_priv->back_offset );
559 } else {
560 OUT_RING( dev_priv->front_offset );
561 }
562
563 ADVANCE_RING();
564
565 /* Increment the frame counter. The client-side 3D driver must
566 * throttle the framerate by waiting for this value before
567 * performing the swapbuffer ioctl.
568 */
569 dev_priv->sarea_priv->last_frame++;
570 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
571 1 - dev_priv->current_page;
572
573 BEGIN_RING( 2 );
574
575 OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) );
576 OUT_RING( dev_priv->sarea_priv->last_frame );
577
578 ADVANCE_RING();
579 }
580
581 static void r128_cce_dispatch_vertex( drm_device_t *dev,
582 drm_buf_t *buf )
583 {
584 drm_r128_private_t *dev_priv = dev->dev_private;
585 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
586 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
587 int format = sarea_priv->vc_format;
588 int offset = buf->bus_address;
589 int size = buf->used;
590 int prim = buf_priv->prim;
591 int i = 0;
592 RING_LOCALS;
593 DRM_DEBUG( "buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox );
594
595 if ( 0 )
596 r128_print_dirty( "dispatch_vertex", sarea_priv->dirty );
597
598 if ( buf->used ) {
599 buf_priv->dispatched = 1;
600
601 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
602 r128_emit_state( dev_priv );
603 }
604
605 do {
606 /* Emit the next set of up to three cliprects */
607 if ( i < sarea_priv->nbox ) {
608 r128_emit_clip_rects( dev_priv,
609 &sarea_priv->boxes[i],
610 sarea_priv->nbox - i );
611 }
612
613 /* Emit the vertex buffer rendering commands */
614 BEGIN_RING( 5 );
615
616 OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) );
617 OUT_RING( offset );
618 OUT_RING( size );
619 OUT_RING( format );
620 OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
621 (size << R128_CCE_VC_CNTL_NUM_SHIFT) );
622
623 ADVANCE_RING();
624
625 i += 3;
626 } while ( i < sarea_priv->nbox );
627 }
628
629 if ( buf_priv->discard ) {
630 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
631
632 /* Emit the vertex buffer age */
633 BEGIN_RING( 2 );
634
635 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
636 OUT_RING( buf_priv->age );
637
638 ADVANCE_RING();
639
640 buf->pending = 1;
641 buf->used = 0;
642 /* FIXME: Check dispatched field */
643 buf_priv->dispatched = 0;
644 }
645
646 dev_priv->sarea_priv->last_dispatch++;
647
648 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
649 sarea_priv->nbox = 0;
650 }
651
652 static void r128_cce_dispatch_indirect( drm_device_t *dev,
653 drm_buf_t *buf,
654 int start, int end )
655 {
656 drm_r128_private_t *dev_priv = dev->dev_private;
657 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
658 RING_LOCALS;
659 DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n",
660 buf->idx, start, end );
661
662 if ( start != end ) {
663 int offset = buf->bus_address + start;
664 int dwords = (end - start + 3) / sizeof(u32);
665
666 /* Indirect buffer data must be an even number of
667 * dwords, so if we've been given an odd number we must
668 * pad the data with a Type-2 CCE packet.
669 */
670 if ( dwords & 1 ) {
671 u32 *data = (u32 *)
672 ((char *)dev_priv->buffers->handle
673 + buf->offset + start);
674 data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
675 }
676
677 buf_priv->dispatched = 1;
678
679 /* Fire off the indirect buffer */
680 BEGIN_RING( 3 );
681
682 OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) );
683 OUT_RING( offset );
684 OUT_RING( dwords );
685
686 ADVANCE_RING();
687 }
688
689 if ( buf_priv->discard ) {
690 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
691
692 /* Emit the indirect buffer age */
693 BEGIN_RING( 2 );
694
695 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
696 OUT_RING( buf_priv->age );
697
698 ADVANCE_RING();
699
700 buf->pending = 1;
701 buf->used = 0;
702 /* FIXME: Check dispatched field */
703 buf_priv->dispatched = 0;
704 }
705
706 dev_priv->sarea_priv->last_dispatch++;
707 }
708
709 static void r128_cce_dispatch_indices( drm_device_t *dev,
710 drm_buf_t *buf,
711 int start, int end,
712 int count )
713 {
714 drm_r128_private_t *dev_priv = dev->dev_private;
715 drm_r128_buf_priv_t *buf_priv = buf->dev_private;
716 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
717 int format = sarea_priv->vc_format;
718 int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
719 int prim = buf_priv->prim;
720 u32 *data;
721 int dwords;
722 int i = 0;
723 RING_LOCALS;
724 DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count );
725
726 if ( 0 )
727 r128_print_dirty( "dispatch_indices", sarea_priv->dirty );
728
729 if ( start != end ) {
730 buf_priv->dispatched = 1;
731
732 if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) {
733 r128_emit_state( dev_priv );
734 }
735
736 dwords = (end - start + 3) / sizeof(u32);
737
738 data = (u32 *)((char *)dev_priv->buffers->handle
739 + buf->offset + start);
740
741 data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
742 dwords-2 ) );
743
744 data[1] = cpu_to_le32( offset );
745 data[2] = cpu_to_le32( R128_MAX_VB_VERTS );
746 data[3] = cpu_to_le32( format );
747 data[4] = cpu_to_le32( (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
748 (count << 16)) );
749
750 if ( count & 0x1 ) {
751 #ifdef __LITTLE_ENDIAN
752 data[dwords-1] &= 0x0000ffff;
753 #else
754 data[dwords-1] &= 0xffff0000;
755 #endif
756 }
757
758 do {
759 /* Emit the next set of up to three cliprects */
760 if ( i < sarea_priv->nbox ) {
761 r128_emit_clip_rects( dev_priv,
762 &sarea_priv->boxes[i],
763 sarea_priv->nbox - i );
764 }
765
766 r128_cce_dispatch_indirect( dev, buf, start, end );
767
768 i += 3;
769 } while ( i < sarea_priv->nbox );
770 }
771
772 if ( buf_priv->discard ) {
773 buf_priv->age = dev_priv->sarea_priv->last_dispatch;
774
775 /* Emit the vertex buffer age */
776 BEGIN_RING( 2 );
777
778 OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) );
779 OUT_RING( buf_priv->age );
780
781 ADVANCE_RING();
782
783 buf->pending = 1;
784 /* FIXME: Check dispatched field */
785 buf_priv->dispatched = 0;
786 }
787
788 dev_priv->sarea_priv->last_dispatch++;
789
790 sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
791 sarea_priv->nbox = 0;
792 }
793
794 static int r128_cce_dispatch_blit( DRMFILE filp,
795 drm_device_t *dev,
796 drm_r128_blit_t *blit )
797 {
798 drm_r128_private_t *dev_priv = dev->dev_private;
799 drm_device_dma_t *dma = dev->dma;
800 drm_buf_t *buf;
801 drm_r128_buf_priv_t *buf_priv;
802 u32 *data;
803 int dword_shift, dwords;
804 RING_LOCALS;
805 DRM_DEBUG( "\n" );
806
807 /* The compiler won't optimize away a division by a variable,
808 * even if the only legal values are powers of two. Thus, we'll
809 * use a shift instead.
810 */
811 switch ( blit->format ) {
812 case R128_DATATYPE_ARGB8888:
813 dword_shift = 0;
814 break;
815 case R128_DATATYPE_ARGB1555:
816 case R128_DATATYPE_RGB565:
817 case R128_DATATYPE_ARGB4444:
818 case R128_DATATYPE_YVYU422:
819 case R128_DATATYPE_VYUY422:
820 dword_shift = 1;
821 break;
822 case R128_DATATYPE_CI8:
823 case R128_DATATYPE_RGB8:
824 dword_shift = 2;
825 break;
826 default:
827 DRM_ERROR( "invalid blit format %d\n", blit->format );
828 return DRM_ERR(EINVAL);
829 }
830
831 /* Flush the pixel cache, and mark the contents as Read Invalid.
832 * This ensures no pixel data gets mixed up with the texture
833 * data from the host data blit, otherwise part of the texture
834 * image may be corrupted.
835 */
836 BEGIN_RING( 2 );
837
838 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
839 OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI );
840
841 ADVANCE_RING();
842
843 /* Dispatch the indirect buffer.
844 */
845 buf = dma->buflist[blit->idx];
846 buf_priv = buf->dev_private;
847
848 if ( buf->filp != filp ) {
849 DRM_ERROR( "process %d using buffer owned by %p\n",
850 DRM_CURRENTPID, buf->filp );
851 return DRM_ERR(EINVAL);
852 }
853 if ( buf->pending ) {
854 DRM_ERROR( "sending pending buffer %d\n", blit->idx );
855 return DRM_ERR(EINVAL);
856 }
857
858 buf_priv->discard = 1;
859
860 dwords = (blit->width * blit->height) >> dword_shift;
861
862 data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
863
864 data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
865 data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
866 R128_GMC_BRUSH_NONE |
867 (blit->format << 8) |
868 R128_GMC_SRC_DATATYPE_COLOR |
869 R128_ROP3_S |
870 R128_DP_SRC_SOURCE_HOST_DATA |
871 R128_GMC_CLR_CMP_CNTL_DIS |
872 R128_GMC_AUX_CLIP_DIS |
873 R128_GMC_WR_MSK_DIS) );
874
875 data[2] = cpu_to_le32( (blit->pitch << 21) | (blit->offset >> 5) );
876 data[3] = cpu_to_le32( 0xffffffff );
877 data[4] = cpu_to_le32( 0xffffffff );
878 data[5] = cpu_to_le32( (blit->y << 16) | blit->x );
879 data[6] = cpu_to_le32( (blit->height << 16) | blit->width );
880 data[7] = cpu_to_le32( dwords );
881
882 buf->used = (dwords + 8) * sizeof(u32);
883
884 r128_cce_dispatch_indirect( dev, buf, 0, buf->used );
885
886 /* Flush the pixel cache after the blit completes. This ensures
887 * the texture data is written out to memory before rendering
888 * continues.
889 */
890 BEGIN_RING( 2 );
891
892 OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) );
893 OUT_RING( R128_PC_FLUSH_GUI );
894
895 ADVANCE_RING();
896
897 return 0;
898 }
899
900
901 /* ================================================================
902 * Tiled depth buffer management
903 *
904 * FIXME: These should all set the destination write mask for when we
905 * have hardware stencil support.
906 */
907
908 static int r128_cce_dispatch_write_span( drm_device_t *dev,
909 drm_r128_depth_t *depth )
910 {
911 drm_r128_private_t *dev_priv = dev->dev_private;
912 int count, x, y;
913 u32 *buffer;
914 u8 *mask;
915 int i, buffer_size, mask_size;
916 RING_LOCALS;
917 DRM_DEBUG( "\n" );
918
919 count = depth->n;
920 if (count > 4096 || count <= 0)
921 return DRM_ERR(EMSGSIZE);
922
923 if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
924 return DRM_ERR(EFAULT);
925 }
926 if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
927 return DRM_ERR(EFAULT);
928 }
929
930 buffer_size = depth->n * sizeof(u32);
931 buffer = DRM_MALLOC( buffer_size );
932 if ( buffer == NULL )
933 return DRM_ERR(ENOMEM);
934 if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
935 DRM_FREE( buffer, buffer_size);
936 return DRM_ERR(EFAULT);
937 }
938
939 mask_size = depth->n * sizeof(u8);
940 if ( depth->mask ) {
941 mask = DRM_MALLOC( mask_size );
942 if ( mask == NULL ) {
943 DRM_FREE( buffer, buffer_size );
944 return DRM_ERR(ENOMEM);
945 }
946 if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
947 DRM_FREE( buffer, buffer_size );
948 DRM_FREE( mask, mask_size );
949 return DRM_ERR(EFAULT);
950 }
951
952 for ( i = 0 ; i < count ; i++, x++ ) {
953 if ( mask[i] ) {
954 BEGIN_RING( 6 );
955
956 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
957 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
958 R128_GMC_BRUSH_SOLID_COLOR |
959 (dev_priv->depth_fmt << 8) |
960 R128_GMC_SRC_DATATYPE_COLOR |
961 R128_ROP3_P |
962 R128_GMC_CLR_CMP_CNTL_DIS |
963 R128_GMC_WR_MSK_DIS );
964
965 OUT_RING( dev_priv->depth_pitch_offset_c );
966 OUT_RING( buffer[i] );
967
968 OUT_RING( (x << 16) | y );
969 OUT_RING( (1 << 16) | 1 );
970
971 ADVANCE_RING();
972 }
973 }
974
975 DRM_FREE( mask, mask_size );
976 } else {
977 for ( i = 0 ; i < count ; i++, x++ ) {
978 BEGIN_RING( 6 );
979
980 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
981 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
982 R128_GMC_BRUSH_SOLID_COLOR |
983 (dev_priv->depth_fmt << 8) |
984 R128_GMC_SRC_DATATYPE_COLOR |
985 R128_ROP3_P |
986 R128_GMC_CLR_CMP_CNTL_DIS |
987 R128_GMC_WR_MSK_DIS );
988
989 OUT_RING( dev_priv->depth_pitch_offset_c );
990 OUT_RING( buffer[i] );
991
992 OUT_RING( (x << 16) | y );
993 OUT_RING( (1 << 16) | 1 );
994
995 ADVANCE_RING();
996 }
997 }
998
999 DRM_FREE( buffer, buffer_size );
1000
1001 return 0;
1002 }
1003
1004 static int r128_cce_dispatch_write_pixels( drm_device_t *dev,
1005 drm_r128_depth_t *depth )
1006 {
1007 drm_r128_private_t *dev_priv = dev->dev_private;
1008 int count, *x, *y;
1009 u32 *buffer;
1010 u8 *mask;
1011 int i, xbuf_size, ybuf_size, buffer_size, mask_size;
1012 RING_LOCALS;
1013 DRM_DEBUG( "\n" );
1014
1015 count = depth->n;
1016 if (count > 4096 || count <= 0)
1017 return DRM_ERR(EMSGSIZE);
1018
1019 xbuf_size = count * sizeof(*x);
1020 ybuf_size = count * sizeof(*y);
1021
1022 x = DRM_MALLOC( xbuf_size );
1023 if ( x == NULL ) {
1024 return DRM_ERR(ENOMEM);
1025 }
1026 y = DRM_MALLOC( ybuf_size );
1027 if ( y == NULL ) {
1028 DRM_FREE( x, xbuf_size );
1029 return DRM_ERR(ENOMEM);
1030 }
1031 if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1032 DRM_FREE( x, xbuf_size );
1033 DRM_FREE( y, ybuf_size );
1034 return DRM_ERR(EFAULT);
1035 }
1036 if ( DRM_COPY_FROM_USER( y, depth->y, xbuf_size ) ) {
1037 DRM_FREE( x, xbuf_size );
1038 DRM_FREE( y, ybuf_size );
1039 return DRM_ERR(EFAULT);
1040 }
1041
1042 buffer_size = depth->n * sizeof(u32);
1043 buffer = DRM_MALLOC( buffer_size );
1044 if ( buffer == NULL ) {
1045 DRM_FREE( x, xbuf_size );
1046 DRM_FREE( y, ybuf_size );
1047 return DRM_ERR(ENOMEM);
1048 }
1049 if ( DRM_COPY_FROM_USER( buffer, depth->buffer, buffer_size ) ) {
1050 DRM_FREE( x, xbuf_size );
1051 DRM_FREE( y, ybuf_size );
1052 DRM_FREE( buffer, buffer_size );
1053 return DRM_ERR(EFAULT);
1054 }
1055
1056 if ( depth->mask ) {
1057 mask_size = depth->n * sizeof(u8);
1058 mask = DRM_MALLOC( mask_size );
1059 if ( mask == NULL ) {
1060 DRM_FREE( x, xbuf_size );
1061 DRM_FREE( y, ybuf_size );
1062 DRM_FREE( buffer, buffer_size );
1063 return DRM_ERR(ENOMEM);
1064 }
1065 if ( DRM_COPY_FROM_USER( mask, depth->mask, mask_size ) ) {
1066 DRM_FREE( x, xbuf_size );
1067 DRM_FREE( y, ybuf_size );
1068 DRM_FREE( buffer, buffer_size );
1069 DRM_FREE( mask, mask_size );
1070 return DRM_ERR(EFAULT);
1071 }
1072
1073 for ( i = 0 ; i < count ; i++ ) {
1074 if ( mask[i] ) {
1075 BEGIN_RING( 6 );
1076
1077 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1078 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1079 R128_GMC_BRUSH_SOLID_COLOR |
1080 (dev_priv->depth_fmt << 8) |
1081 R128_GMC_SRC_DATATYPE_COLOR |
1082 R128_ROP3_P |
1083 R128_GMC_CLR_CMP_CNTL_DIS |
1084 R128_GMC_WR_MSK_DIS );
1085
1086 OUT_RING( dev_priv->depth_pitch_offset_c );
1087 OUT_RING( buffer[i] );
1088
1089 OUT_RING( (x[i] << 16) | y[i] );
1090 OUT_RING( (1 << 16) | 1 );
1091
1092 ADVANCE_RING();
1093 }
1094 }
1095
1096 DRM_FREE( mask, mask_size );
1097 } else {
1098 for ( i = 0 ; i < count ; i++ ) {
1099 BEGIN_RING( 6 );
1100
1101 OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) );
1102 OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL |
1103 R128_GMC_BRUSH_SOLID_COLOR |
1104 (dev_priv->depth_fmt << 8) |
1105 R128_GMC_SRC_DATATYPE_COLOR |
1106 R128_ROP3_P |
1107 R128_GMC_CLR_CMP_CNTL_DIS |
1108 R128_GMC_WR_MSK_DIS );
1109
1110 OUT_RING( dev_priv->depth_pitch_offset_c );
1111 OUT_RING( buffer[i] );
1112
1113 OUT_RING( (x[i] << 16) | y[i] );
1114 OUT_RING( (1 << 16) | 1 );
1115
1116 ADVANCE_RING();
1117 }
1118 }
1119
1120 DRM_FREE( x, xbuf_size );
1121 DRM_FREE( y, ybuf_size );
1122 DRM_FREE( buffer, buffer_size );
1123
1124 return 0;
1125 }
1126
1127 static int r128_cce_dispatch_read_span( drm_device_t *dev,
1128 drm_r128_depth_t *depth )
1129 {
1130 drm_r128_private_t *dev_priv = dev->dev_private;
1131 int count, x, y;
1132 RING_LOCALS;
1133 DRM_DEBUG( "\n" );
1134
1135 count = depth->n;
1136 if (count > 4096 || count <= 0)
1137 return DRM_ERR(EMSGSIZE);
1138
1139 if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) {
1140 return DRM_ERR(EFAULT);
1141 }
1142 if ( DRM_COPY_FROM_USER( &y, depth->y, sizeof(y) ) ) {
1143 return DRM_ERR(EFAULT);
1144 }
1145
1146 BEGIN_RING( 7 );
1147
1148 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1149 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1150 R128_GMC_DST_PITCH_OFFSET_CNTL |
1151 R128_GMC_BRUSH_NONE |
1152 (dev_priv->depth_fmt << 8) |
1153 R128_GMC_SRC_DATATYPE_COLOR |
1154 R128_ROP3_S |
1155 R128_DP_SRC_SOURCE_MEMORY |
1156 R128_GMC_CLR_CMP_CNTL_DIS |
1157 R128_GMC_WR_MSK_DIS );
1158
1159 OUT_RING( dev_priv->depth_pitch_offset_c );
1160 OUT_RING( dev_priv->span_pitch_offset_c );
1161
1162 OUT_RING( (x << 16) | y );
1163 OUT_RING( (0 << 16) | 0 );
1164 OUT_RING( (count << 16) | 1 );
1165
1166 ADVANCE_RING();
1167
1168 return 0;
1169 }
1170
1171 static int r128_cce_dispatch_read_pixels( drm_device_t *dev,
1172 drm_r128_depth_t *depth )
1173 {
1174 drm_r128_private_t *dev_priv = dev->dev_private;
1175 int count, *x, *y;
1176 int i, xbuf_size, ybuf_size;
1177 RING_LOCALS;
1178 DRM_DEBUG( "%s\n", __FUNCTION__ );
1179
1180 count = depth->n;
1181 if (count > 4096 || count <= 0)
1182 return DRM_ERR(EMSGSIZE);
1183
1184 if ( count > dev_priv->depth_pitch ) {
1185 count = dev_priv->depth_pitch;
1186 }
1187
1188 xbuf_size = count * sizeof(*x);
1189 ybuf_size = count * sizeof(*y);
1190 x = DRM_MALLOC( xbuf_size );
1191 if ( x == NULL ) {
1192 return DRM_ERR(ENOMEM);
1193 }
1194 y = DRM_MALLOC( ybuf_size );
1195 if ( y == NULL ) {
1196 DRM_FREE( x, xbuf_size );
1197 return DRM_ERR(ENOMEM);
1198 }
1199 if ( DRM_COPY_FROM_USER( x, depth->x, xbuf_size ) ) {
1200 DRM_FREE( x, xbuf_size );
1201 DRM_FREE( y, ybuf_size );
1202 return DRM_ERR(EFAULT);
1203 }
1204 if ( DRM_COPY_FROM_USER( y, depth->y, ybuf_size ) ) {
1205 DRM_FREE( x, xbuf_size );
1206 DRM_FREE( y, ybuf_size );
1207 return DRM_ERR(EFAULT);
1208 }
1209
1210 for ( i = 0 ; i < count ; i++ ) {
1211 BEGIN_RING( 7 );
1212
1213 OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) );
1214 OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL |
1215 R128_GMC_DST_PITCH_OFFSET_CNTL |
1216 R128_GMC_BRUSH_NONE |
1217 (dev_priv->depth_fmt << 8) |
1218 R128_GMC_SRC_DATATYPE_COLOR |
1219 R128_ROP3_S |
1220 R128_DP_SRC_SOURCE_MEMORY |
1221 R128_GMC_CLR_CMP_CNTL_DIS |
1222 R128_GMC_WR_MSK_DIS );
1223
1224 OUT_RING( dev_priv->depth_pitch_offset_c );
1225 OUT_RING( dev_priv->span_pitch_offset_c );
1226
1227 OUT_RING( (x[i] << 16) | y[i] );
1228 OUT_RING( (i << 16) | 0 );
1229 OUT_RING( (1 << 16) | 1 );
1230
1231 ADVANCE_RING();
1232 }
1233
1234 DRM_FREE( x, xbuf_size );
1235 DRM_FREE( y, ybuf_size );
1236
1237 return 0;
1238 }
1239
1240
1241 /* ================================================================
1242 * Polygon stipple
1243 */
1244
1245 static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
1246 {
1247 drm_r128_private_t *dev_priv = dev->dev_private;
1248 int i;
1249 RING_LOCALS;
1250 DRM_DEBUG( "%s\n", __FUNCTION__ );
1251
1252 BEGIN_RING( 33 );
1253
1254 OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) );
1255 for ( i = 0 ; i < 32 ; i++ ) {
1256 OUT_RING( stipple[i] );
1257 }
1258
1259 ADVANCE_RING();
1260 }
1261
1262
1263 /* ================================================================
1264 * IOCTL functions
1265 */
1266
1267 int r128_cce_clear( DRM_IOCTL_ARGS )
1268 {
1269 DRM_DEVICE;
1270 drm_r128_private_t *dev_priv = dev->dev_private;
1271 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1272 drm_r128_clear_t clear;
1273 DRM_DEBUG( "\n" );
1274
1275 LOCK_TEST_WITH_RETURN( dev, filp );
1276
1277 DRM_COPY_FROM_USER_IOCTL( clear, (drm_r128_clear_t *) data,
1278 sizeof(clear) );
1279
1280 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1281
1282 if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1283 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1284
1285 r128_cce_dispatch_clear( dev, &clear );
1286 COMMIT_RING();
1287
1288 /* Make sure we restore the 3D state next time.
1289 */
1290 dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
1291
1292 return 0;
1293 }
1294
1295 static int r128_do_init_pageflip( drm_device_t *dev )
1296 {
1297 drm_r128_private_t *dev_priv = dev->dev_private;
1298 DRM_DEBUG( "\n" );
1299
1300 dev_priv->crtc_offset = R128_READ( R128_CRTC_OFFSET );
1301 dev_priv->crtc_offset_cntl = R128_READ( R128_CRTC_OFFSET_CNTL );
1302
1303 R128_WRITE( R128_CRTC_OFFSET, dev_priv->front_offset );
1304 R128_WRITE( R128_CRTC_OFFSET_CNTL,
1305 dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL );
1306
1307 dev_priv->page_flipping = 1;
1308 dev_priv->current_page = 0;
1309 dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
1310
1311 return 0;
1312 }
1313
1314 int r128_do_cleanup_pageflip( drm_device_t *dev )
1315 {
1316 drm_r128_private_t *dev_priv = dev->dev_private;
1317 DRM_DEBUG( "\n" );
1318
1319 R128_WRITE( R128_CRTC_OFFSET, dev_priv->crtc_offset );
1320 R128_WRITE( R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl );
1321
1322 if (dev_priv->current_page != 0) {
1323 r128_cce_dispatch_flip( dev );
1324 COMMIT_RING();
1325 }
1326
1327 dev_priv->page_flipping = 0;
1328 return 0;
1329 }
1330
1331 /* Swapping and flipping are different operations, need different ioctls.
1332 * They can & should be intermixed to support multiple 3d windows.
1333 */
1334
1335 int r128_cce_flip( DRM_IOCTL_ARGS )
1336 {
1337 DRM_DEVICE;
1338 drm_r128_private_t *dev_priv = dev->dev_private;
1339 DRM_DEBUG( "%s\n", __FUNCTION__ );
1340
1341 LOCK_TEST_WITH_RETURN( dev, filp );
1342
1343 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1344
1345 if (!dev_priv->page_flipping)
1346 r128_do_init_pageflip( dev );
1347
1348 r128_cce_dispatch_flip( dev );
1349
1350 COMMIT_RING();
1351 return 0;
1352 }
1353
1354 int r128_cce_swap( DRM_IOCTL_ARGS )
1355 {
1356 DRM_DEVICE;
1357 drm_r128_private_t *dev_priv = dev->dev_private;
1358 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1359 DRM_DEBUG( "%s\n", __FUNCTION__ );
1360
1361 LOCK_TEST_WITH_RETURN( dev, filp );
1362
1363 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1364
1365 if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS )
1366 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1367
1368 r128_cce_dispatch_swap( dev );
1369 dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
1370 R128_UPLOAD_MASKS);
1371
1372 COMMIT_RING();
1373 return 0;
1374 }
1375
1376 int r128_cce_vertex( DRM_IOCTL_ARGS )
1377 {
1378 DRM_DEVICE;
1379 drm_r128_private_t *dev_priv = dev->dev_private;
1380 drm_device_dma_t *dma = dev->dma;
1381 drm_buf_t *buf;
1382 drm_r128_buf_priv_t *buf_priv;
1383 drm_r128_vertex_t vertex;
1384
1385 LOCK_TEST_WITH_RETURN( dev, filp );
1386
1387 if ( !dev_priv ) {
1388 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1389 return DRM_ERR(EINVAL);
1390 }
1391
1392 DRM_COPY_FROM_USER_IOCTL( vertex, (drm_r128_vertex_t *) data,
1393 sizeof(vertex) );
1394
1395 DRM_DEBUG( "pid=%d index=%d count=%d discard=%d\n",
1396 DRM_CURRENTPID,
1397 vertex.idx, vertex.count, vertex.discard );
1398
1399 if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
1400 DRM_ERROR( "buffer index %d (of %d max)\n",
1401 vertex.idx, dma->buf_count - 1 );
1402 return DRM_ERR(EINVAL);
1403 }
1404 if ( vertex.prim < 0 ||
1405 vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1406 DRM_ERROR( "buffer prim %d\n", vertex.prim );
1407 return DRM_ERR(EINVAL);
1408 }
1409
1410 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1411 VB_AGE_TEST_WITH_RETURN( dev_priv );
1412
1413 buf = dma->buflist[vertex.idx];
1414 buf_priv = buf->dev_private;
1415
1416 if ( buf->filp != filp ) {
1417 DRM_ERROR( "process %d using buffer owned by %p\n",
1418 DRM_CURRENTPID, buf->filp );
1419 return DRM_ERR(EINVAL);
1420 }
1421 if ( buf->pending ) {
1422 DRM_ERROR( "sending pending buffer %d\n", vertex.idx );
1423 return DRM_ERR(EINVAL);
1424 }
1425
1426 buf->used = vertex.count;
1427 buf_priv->prim = vertex.prim;
1428 buf_priv->discard = vertex.discard;
1429
1430 r128_cce_dispatch_vertex( dev, buf );
1431
1432 COMMIT_RING();
1433 return 0;
1434 }
1435
1436 int r128_cce_indices( DRM_IOCTL_ARGS )
1437 {
1438 DRM_DEVICE;
1439 drm_r128_private_t *dev_priv = dev->dev_private;
1440 drm_device_dma_t *dma = dev->dma;
1441 drm_buf_t *buf;
1442 drm_r128_buf_priv_t *buf_priv;
1443 drm_r128_indices_t elts;
1444 int count;
1445
1446 LOCK_TEST_WITH_RETURN( dev, filp );
1447
1448 if ( !dev_priv ) {
1449 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1450 return DRM_ERR(EINVAL);
1451 }
1452
1453 DRM_COPY_FROM_USER_IOCTL( elts, (drm_r128_indices_t *) data,
1454 sizeof(elts) );
1455
1456 DRM_DEBUG( "pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
1457 elts.idx, elts.start, elts.end, elts.discard );
1458
1459 if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
1460 DRM_ERROR( "buffer index %d (of %d max)\n",
1461 elts.idx, dma->buf_count - 1 );
1462 return DRM_ERR(EINVAL);
1463 }
1464 if ( elts.prim < 0 ||
1465 elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 ) {
1466 DRM_ERROR( "buffer prim %d\n", elts.prim );
1467 return DRM_ERR(EINVAL);
1468 }
1469
1470 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1471 VB_AGE_TEST_WITH_RETURN( dev_priv );
1472
1473 buf = dma->buflist[elts.idx];
1474 buf_priv = buf->dev_private;
1475
1476 if ( buf->filp != filp ) {
1477 DRM_ERROR( "process %d using buffer owned by %p\n",
1478 DRM_CURRENTPID, buf->filp );
1479 return DRM_ERR(EINVAL);
1480 }
1481 if ( buf->pending ) {
1482 DRM_ERROR( "sending pending buffer %d\n", elts.idx );
1483 return DRM_ERR(EINVAL);
1484 }
1485
1486 count = (elts.end - elts.start) / sizeof(u16);
1487 elts.start -= R128_INDEX_PRIM_OFFSET;
1488
1489 if ( elts.start & 0x7 ) {
1490 DRM_ERROR( "misaligned buffer 0x%x\n", elts.start );
1491 return DRM_ERR(EINVAL);
1492 }
1493 if ( elts.start < buf->used ) {
1494 DRM_ERROR( "no header 0x%x - 0x%x\n", elts.start, buf->used );
1495 return DRM_ERR(EINVAL);
1496 }
1497
1498 buf->used = elts.end;
1499 buf_priv->prim = elts.prim;
1500 buf_priv->discard = elts.discard;
1501
1502 r128_cce_dispatch_indices( dev, buf, elts.start, elts.end, count );
1503
1504 COMMIT_RING();
1505 return 0;
1506 }
1507
1508 int r128_cce_blit( DRM_IOCTL_ARGS )
1509 {
1510 DRM_DEVICE;
1511 drm_device_dma_t *dma = dev->dma;
1512 drm_r128_private_t *dev_priv = dev->dev_private;
1513 drm_r128_blit_t blit;
1514 int ret;
1515
1516 LOCK_TEST_WITH_RETURN( dev, filp );
1517
1518 DRM_COPY_FROM_USER_IOCTL( blit, (drm_r128_blit_t *) data,
1519 sizeof(blit) );
1520
1521 DRM_DEBUG( "pid=%d index=%d\n", DRM_CURRENTPID, blit.idx );
1522
1523 if ( blit.idx < 0 || blit.idx >= dma->buf_count ) {
1524 DRM_ERROR( "buffer index %d (of %d max)\n",
1525 blit.idx, dma->buf_count - 1 );
1526 return DRM_ERR(EINVAL);
1527 }
1528
1529 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1530 VB_AGE_TEST_WITH_RETURN( dev_priv );
1531
1532 ret = r128_cce_dispatch_blit( filp, dev, &blit );
1533
1534 COMMIT_RING();
1535 return ret;
1536 }
1537
1538 int r128_cce_depth( DRM_IOCTL_ARGS )
1539 {
1540 DRM_DEVICE;
1541 drm_r128_private_t *dev_priv = dev->dev_private;
1542 drm_r128_depth_t depth;
1543 int ret;
1544
1545 LOCK_TEST_WITH_RETURN( dev, filp );
1546
1547 DRM_COPY_FROM_USER_IOCTL( depth, (drm_r128_depth_t *) data,
1548 sizeof(depth) );
1549
1550 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1551
1552 ret = DRM_ERR(EINVAL);
1553 switch ( depth.func ) {
1554 case R128_WRITE_SPAN:
1555 ret = r128_cce_dispatch_write_span( dev, &depth );
1556 case R128_WRITE_PIXELS:
1557 ret = r128_cce_dispatch_write_pixels( dev, &depth );
1558 case R128_READ_SPAN:
1559 ret = r128_cce_dispatch_read_span( dev, &depth );
1560 case R128_READ_PIXELS:
1561 ret = r128_cce_dispatch_read_pixels( dev, &depth );
1562 }
1563
1564 COMMIT_RING();
1565 return ret;
1566 }
1567
1568 int r128_cce_stipple( DRM_IOCTL_ARGS )
1569 {
1570 DRM_DEVICE;
1571 drm_r128_private_t *dev_priv = dev->dev_private;
1572 drm_r128_stipple_t stipple;
1573 u32 mask[32];
1574
1575 LOCK_TEST_WITH_RETURN( dev, filp );
1576
1577 DRM_COPY_FROM_USER_IOCTL( stipple, (drm_r128_stipple_t *) data,
1578 sizeof(stipple) );
1579
1580 if ( DRM_COPY_FROM_USER( &mask, stipple.mask,
1581 32 * sizeof(u32) ) )
1582 return DRM_ERR( EFAULT );
1583
1584 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1585
1586 r128_cce_dispatch_stipple( dev, mask );
1587
1588 COMMIT_RING();
1589 return 0;
1590 }
1591
1592 int r128_cce_indirect( DRM_IOCTL_ARGS )
1593 {
1594 DRM_DEVICE;
1595 drm_r128_private_t *dev_priv = dev->dev_private;
1596 drm_device_dma_t *dma = dev->dma;
1597 drm_buf_t *buf;
1598 drm_r128_buf_priv_t *buf_priv;
1599 drm_r128_indirect_t indirect;
1600 #if 0
1601 RING_LOCALS;
1602 #endif
1603
1604 LOCK_TEST_WITH_RETURN( dev, filp );
1605
1606 if ( !dev_priv ) {
1607 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1608 return DRM_ERR(EINVAL);
1609 }
1610
1611 DRM_COPY_FROM_USER_IOCTL( indirect, (drm_r128_indirect_t *) data,
1612 sizeof(indirect) );
1613
1614 DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%d\n",
1615 indirect.idx, indirect.start,
1616 indirect.end, indirect.discard );
1617
1618 if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
1619 DRM_ERROR( "buffer index %d (of %d max)\n",
1620 indirect.idx, dma->buf_count - 1 );
1621 return DRM_ERR(EINVAL);
1622 }
1623
1624 buf = dma->buflist[indirect.idx];
1625 buf_priv = buf->dev_private;
1626
1627 if ( buf->filp != filp ) {
1628 DRM_ERROR( "process %d using buffer owned by %p\n",
1629 DRM_CURRENTPID, buf->filp );
1630 return DRM_ERR(EINVAL);
1631 }
1632 if ( buf->pending ) {
1633 DRM_ERROR( "sending pending buffer %d\n", indirect.idx );
1634 return DRM_ERR(EINVAL);
1635 }
1636
1637 if ( indirect.start < buf->used ) {
1638 DRM_ERROR( "reusing indirect: start=0x%x actual=0x%x\n",
1639 indirect.start, buf->used );
1640 return DRM_ERR(EINVAL);
1641 }
1642
1643 RING_SPACE_TEST_WITH_RETURN( dev_priv );
1644 VB_AGE_TEST_WITH_RETURN( dev_priv );
1645
1646 buf->used = indirect.end;
1647 buf_priv->discard = indirect.discard;
1648
1649 #if 0
1650 /* Wait for the 3D stream to idle before the indirect buffer
1651 * containing 2D acceleration commands is processed.
1652 */
1653 BEGIN_RING( 2 );
1654 RADEON_WAIT_UNTIL_3D_IDLE();
1655 ADVANCE_RING();
1656 #endif
1657
1658 /* Dispatch the indirect buffer full of commands from the
1659 * X server. This is insecure and is thus only available to
1660 * privileged clients.
1661 */
1662 r128_cce_dispatch_indirect( dev, buf, indirect.start, indirect.end );
1663
1664 COMMIT_RING();
1665 return 0;
1666 }
1667
1668 int r128_getparam( DRM_IOCTL_ARGS )
1669 {
1670 DRM_DEVICE;
1671 drm_r128_private_t *dev_priv = dev->dev_private;
1672 drm_r128_getparam_t param;
1673 int value;
1674
1675 if ( !dev_priv ) {
1676 DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
1677 return DRM_ERR(EINVAL);
1678 }
1679
1680 DRM_COPY_FROM_USER_IOCTL( param, (drm_r128_getparam_t *)data,
1681 sizeof(param) );
1682
1683 DRM_DEBUG( "pid=%d\n", DRM_CURRENTPID );
1684
1685 switch( param.param ) {
1686 case R128_PARAM_IRQ_NR:
1687 value = dev->irq;
1688 break;
1689 default:
1690 return DRM_ERR(EINVAL);
1691 }
1692
1693 if ( DRM_COPY_TO_USER( param.value, &value, sizeof(int) ) ) {
1694 DRM_ERROR( "copy_to_user\n" );
1695 return DRM_ERR(EFAULT);
1696 }
1697
1698 return 0;
1699 }
Cache object: 36975e63707db9b57a207baf64aaa696
|