OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [drm-4.0/] [r128_state.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.