aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r300_cmdbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/r300_cmdbuf.c')
-rw-r--r--drivers/gpu/drm/radeon/r300_cmdbuf.c80
1 files changed, 64 insertions, 16 deletions
diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c
index 4b3bd6303daf..b1fdfc61f27d 100644
--- a/drivers/gpu/drm/radeon/r300_cmdbuf.c
+++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c
@@ -577,22 +577,23 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
577 return 0; 577 return 0;
578} 578}
579 579
580static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, 580static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv,
581 drm_radeon_kcmd_buffer_t *cmdbuf) 581 drm_radeon_kcmd_buffer_t *cmdbuf)
582{ 582{
583 u32 *cmd = (u32 *) cmdbuf->buf; 583 u32 *cmd;
584 int count, ret; 584 int count;
585 int expected_count;
585 RING_LOCALS; 586 RING_LOCALS;
586 587
587 count=(cmd[0]>>16) & 0x3fff; 588 cmd = (u32 *) cmdbuf->buf;
589 count = (cmd[0]>>16) & 0x3fff;
590 expected_count = cmd[1] >> 16;
591 if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit))
592 expected_count = (expected_count+1)/2;
588 593
589 if ((cmd[1] & 0x8000ffff) != 0x80000810) { 594 if (count && count != expected_count) {
590 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); 595 DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n",
591 return -EINVAL; 596 count, expected_count);
592 }
593 ret = !radeon_check_offset(dev_priv, cmd[2]);
594 if (ret) {
595 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
596 return -EINVAL; 597 return -EINVAL;
597 } 598 }
598 599
@@ -604,6 +605,50 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
604 cmdbuf->buf += (count+2)*4; 605 cmdbuf->buf += (count+2)*4;
605 cmdbuf->bufsz -= (count+2)*4; 606 cmdbuf->bufsz -= (count+2)*4;
606 607
608 if (!count) {
609 drm_r300_cmd_header_t header;
610
611 if (cmdbuf->bufsz < 4*4 + sizeof(header)) {
612 DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n");
613 return -EINVAL;
614 }
615
616 header.u = *(unsigned int *)cmdbuf->buf;
617
618 cmdbuf->buf += sizeof(header);
619 cmdbuf->bufsz -= sizeof(header);
620 cmd = (u32 *) cmdbuf->buf;
621
622 if (header.header.cmd_type != R300_CMD_PACKET3 ||
623 header.packet3.packet != R300_CMD_PACKET3_RAW ||
624 cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) {
625 DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n");
626 return -EINVAL;
627 }
628
629 if ((cmd[1] & 0x8000ffff) != 0x80000810) {
630 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
631 return -EINVAL;
632 }
633 if (!radeon_check_offset(dev_priv, cmd[2])) {
634 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
635 return -EINVAL;
636 }
637 if (cmd[3] != expected_count) {
638 DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n",
639 cmd[3], expected_count);
640 return -EINVAL;
641 }
642
643 BEGIN_RING(4);
644 OUT_RING(cmd[0]);
645 OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3);
646 ADVANCE_RING();
647
648 cmdbuf->buf += 4*4;
649 cmdbuf->bufsz -= 4*4;
650 }
651
607 return 0; 652 return 0;
608} 653}
609 654
@@ -648,18 +693,21 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
648 return r300_emit_bitblt_multi(dev_priv, cmdbuf); 693 return r300_emit_bitblt_multi(dev_priv, cmdbuf);
649 694
650 case RADEON_CP_INDX_BUFFER: 695 case RADEON_CP_INDX_BUFFER:
651 /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ 696 DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n");
652 return r300_emit_indx_buffer(dev_priv, cmdbuf); 697 return -EINVAL;
653 case RADEON_CP_3D_DRAW_IMMD_2: 698 case RADEON_CP_3D_DRAW_IMMD_2:
654 /* triggers drawing using in-packet vertex data */ 699 /* triggers drawing using in-packet vertex data */
655 case RADEON_CP_3D_DRAW_VBUF_2: 700 case RADEON_CP_3D_DRAW_VBUF_2:
656 /* triggers drawing of vertex buffers setup elsewhere */ 701 /* triggers drawing of vertex buffers setup elsewhere */
702 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
703 RADEON_PURGE_EMITED);
704 break;
657 case RADEON_CP_3D_DRAW_INDX_2: 705 case RADEON_CP_3D_DRAW_INDX_2:
658 /* triggers drawing using indices to vertex buffer */ 706 /* triggers drawing using indices to vertex buffer */
659 /* whenever we send vertex we clear flush & purge */ 707 /* whenever we send vertex we clear flush & purge */
660 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | 708 dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED |
661 RADEON_PURGE_EMITED); 709 RADEON_PURGE_EMITED);
662 break; 710 return r300_emit_draw_indx_2(dev_priv, cmdbuf);
663 case RADEON_WAIT_FOR_IDLE: 711 case RADEON_WAIT_FOR_IDLE:
664 case RADEON_CP_NOP: 712 case RADEON_CP_NOP:
665 /* these packets are safe */ 713 /* these packets are safe */
@@ -757,7 +805,7 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
757{ 805{
758 uint32_t cache_z, cache_3d, cache_2d; 806 uint32_t cache_z, cache_3d, cache_2d;
759 RING_LOCALS; 807 RING_LOCALS;
760 808
761 cache_z = R300_ZC_FLUSH; 809 cache_z = R300_ZC_FLUSH;
762 cache_2d = R300_RB2D_DC_FLUSH; 810 cache_2d = R300_RB2D_DC_FLUSH;
763 cache_3d = R300_RB3D_DC_FLUSH; 811 cache_3d = R300_RB3D_DC_FLUSH;