Browse Source

drm/radeon/kms: manage r300 CMASK RAM access and allow CMASK clear

The CMASK RAM is for colorbuffer compression (used in conjunction
with MSAA). Only one user (filp) can access it.

The CMASK RAM access is managed in the same way as Hyper-Z, but there is
a separate ioctl, because an app that uses MSAA does not necessarily
have to use zbuffering.

Signed-off-by: Marek Olšák <maraeo@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Marek Olšák 14 years ago
parent
commit
9eba4a93ce

+ 9 - 0
drivers/gpu/drm/radeon/r300.c

@@ -745,6 +745,11 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
 		break;
 		break;
 	case 0x4E00:
 	case 0x4E00:
 		/* RB3D_CCTL */
 		/* RB3D_CCTL */
+		if ((idx_value & (1 << 10)) && /* CMASK_ENABLE */
+		    p->rdev->cmask_filp != p->filp) {
+			DRM_ERROR("Invalid RB3D_CCTL: Cannot enable CMASK.\n");
+			return -EINVAL;
+		}
 		track->num_cb = ((idx_value >> 5) & 0x3) + 1;
 		track->num_cb = ((idx_value >> 5) & 0x3) + 1;
 		break;
 		break;
 	case 0x4E38:
 	case 0x4E38:
@@ -1206,6 +1211,10 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
 		if (p->rdev->hyperz_filp != p->filp)
 		if (p->rdev->hyperz_filp != p->filp)
 			return -EINVAL;
 			return -EINVAL;
 		break;
 		break;
+	case PACKET3_3D_CLEAR_CMASK:
+		if (p->rdev->cmask_filp != p->filp)
+			return -EINVAL;
+		break;
 	case PACKET3_NOP:
 	case PACKET3_NOP:
 		break;
 		break;
 	default:
 	default:

+ 1 - 0
drivers/gpu/drm/radeon/r300d.h

@@ -54,6 +54,7 @@
 #define		PACKET3_3D_DRAW_IMMD_2		0x35
 #define		PACKET3_3D_DRAW_IMMD_2		0x35
 #define		PACKET3_3D_DRAW_INDX_2		0x36
 #define		PACKET3_3D_DRAW_INDX_2		0x36
 #define		PACKET3_3D_CLEAR_HIZ		0x37
 #define		PACKET3_3D_CLEAR_HIZ		0x37
+#define		PACKET3_3D_CLEAR_CMASK		0x38
 #define		PACKET3_BITBLT_MULTI		0x9B
 #define		PACKET3_BITBLT_MULTI		0x9B
 
 
 #define PACKET0(reg, n)	(CP_PACKET0 |					\
 #define PACKET0(reg, n)	(CP_PACKET0 |					\

+ 2 - 1
drivers/gpu/drm/radeon/radeon.h

@@ -1168,8 +1168,9 @@ struct radeon_device {
 	uint8_t			audio_category_code;
 	uint8_t			audio_category_code;
 
 
 	struct notifier_block acpi_nb;
 	struct notifier_block acpi_nb;
-	/* only one userspace can use Hyperz features at a time */
+	/* only one userspace can use Hyperz features or CMASK at a time */
 	struct drm_file *hyperz_filp;
 	struct drm_file *hyperz_filp;
+	struct drm_file *cmask_filp;
 	/* i2c buses */
 	/* i2c buses */
 	struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS];
 	struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS];
 };
 };

+ 1 - 1
drivers/gpu/drm/radeon/radeon_drv.c

@@ -48,7 +48,7 @@
  * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
  * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
  * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500)
  * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500)
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
- *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf
+ *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK
  */
  */
 #define KMS_DRIVER_MAJOR	2
 #define KMS_DRIVER_MAJOR	2
 #define KMS_DRIVER_MINOR	8
 #define KMS_DRIVER_MINOR	8

+ 27 - 12
drivers/gpu/drm/radeon/radeon_kms.c

@@ -96,9 +96,27 @@ out:
 	return r;
 	return r;
 }
 }
 
 
+static void radeon_set_filp_rights(struct drm_device *dev,
+				   struct drm_file **owner,
+				   struct drm_file *applier,
+				   uint32_t *value)
+{
+	mutex_lock(&dev->struct_mutex);
+	if (*value == 1) {
+		/* wants rights */
+		if (!*owner)
+			*owner = applier;
+	} else if (*value == 0) {
+		/* revokes rights */
+		if (*owner == applier)
+			*owner = NULL;
+	}
+	*value = *owner == applier ? 1 : 0;
+	mutex_unlock(&dev->struct_mutex);
+}
 
 
 /*
 /*
- * Userspace get informations ioctl
+ * Userspace get information ioctl
  */
  */
 int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 {
 {
@@ -173,18 +191,15 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 			DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value);
 			DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
-		mutex_lock(&dev->struct_mutex);
-		if (value == 1) {
-			/* wants hyper-z */
-			if (!rdev->hyperz_filp)
-				rdev->hyperz_filp = filp;
-		} else if (value == 0) {
-			/* revokes hyper-z */
-			if (rdev->hyperz_filp == filp)
-				rdev->hyperz_filp = NULL;
+		radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value);
+		break;
+	case RADEON_INFO_WANT_CMASK:
+		/* The same logic as Hyper-Z. */
+		if (value >= 2) {
+			DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value);
+			return -EINVAL;
 		}
 		}
-		value = rdev->hyperz_filp == filp ?  1 : 0;
-		mutex_unlock(&dev->struct_mutex);
+		radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value);
 		break;
 		break;
 	default:
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);

+ 1 - 0
include/drm/radeon_drm.h

@@ -906,6 +906,7 @@ struct drm_radeon_cs {
 #define RADEON_INFO_ACCEL_WORKING2	0x05
 #define RADEON_INFO_ACCEL_WORKING2	0x05
 #define RADEON_INFO_TILING_CONFIG	0x06
 #define RADEON_INFO_TILING_CONFIG	0x06
 #define RADEON_INFO_WANT_HYPERZ		0x07
 #define RADEON_INFO_WANT_HYPERZ		0x07
+#define RADEON_INFO_WANT_CMASK		0x08 /* get access to CMASK on r300 */
 
 
 struct drm_radeon_info {
 struct drm_radeon_info {
 	uint32_t		request;
 	uint32_t		request;