0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include "vmwgfx_devcaps.h"
0029
0030 #include "vmwgfx_drv.h"
0031
0032
0033 struct svga_3d_compat_cap {
0034 SVGA3dFifoCapsRecordHeader header;
0035 SVGA3dFifoCapPair pairs[SVGA3D_DEVCAP_MAX];
0036 };
0037
0038
0039 static u32 vmw_mask_legacy_multisample(unsigned int cap, u32 fmt_value)
0040 {
0041
0042
0043
0044
0045
0046
0047
0048
0049 if (cap == SVGA3D_DEVCAP_DEAD5)
0050 return 0;
0051
0052 return fmt_value;
0053 }
0054
0055 static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
0056 size_t size)
0057 {
0058 struct svga_3d_compat_cap *compat_cap =
0059 (struct svga_3d_compat_cap *) bounce;
0060 unsigned int i;
0061 size_t pair_offset = offsetof(struct svga_3d_compat_cap, pairs);
0062 unsigned int max_size;
0063
0064 if (size < pair_offset)
0065 return -EINVAL;
0066
0067 max_size = (size - pair_offset) / sizeof(SVGA3dFifoCapPair);
0068
0069 if (max_size > SVGA3D_DEVCAP_MAX)
0070 max_size = SVGA3D_DEVCAP_MAX;
0071
0072 compat_cap->header.length =
0073 (pair_offset + max_size * sizeof(SVGA3dFifoCapPair)) / sizeof(u32);
0074 compat_cap->header.type = SVGA3D_FIFO_CAPS_RECORD_DEVCAPS;
0075
0076 for (i = 0; i < max_size; ++i) {
0077 compat_cap->pairs[i][0] = i;
0078 compat_cap->pairs[i][1] = vmw_mask_legacy_multisample
0079 (i, dev_priv->devcaps[i]);
0080 }
0081
0082 return 0;
0083 }
0084
0085 int vmw_devcaps_create(struct vmw_private *vmw)
0086 {
0087 bool gb_objects = !!(vmw->capabilities & SVGA_CAP_GBOBJECTS);
0088 uint32_t i;
0089
0090 if (gb_objects) {
0091 vmw->devcaps = vzalloc(sizeof(uint32_t) * SVGA3D_DEVCAP_MAX);
0092 if (!vmw->devcaps)
0093 return -ENOMEM;
0094 for (i = 0; i < SVGA3D_DEVCAP_MAX; ++i) {
0095 vmw_write(vmw, SVGA_REG_DEV_CAP, i);
0096 vmw->devcaps[i] = vmw_read(vmw, SVGA_REG_DEV_CAP);
0097 }
0098 }
0099 return 0;
0100 }
0101
0102 void vmw_devcaps_destroy(struct vmw_private *vmw)
0103 {
0104 vfree(vmw->devcaps);
0105 vmw->devcaps = NULL;
0106 }
0107
0108
0109 uint32 vmw_devcaps_size(const struct vmw_private *vmw,
0110 bool gb_aware)
0111 {
0112 bool gb_objects = !!(vmw->capabilities & SVGA_CAP_GBOBJECTS);
0113 if (gb_objects && gb_aware)
0114 return SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
0115 else if (gb_objects)
0116 return sizeof(struct svga_3d_compat_cap) +
0117 sizeof(uint32_t);
0118 else if (vmw->fifo_mem != NULL)
0119 return (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) *
0120 sizeof(uint32_t);
0121 else
0122 return 0;
0123 }
0124
0125 int vmw_devcaps_copy(struct vmw_private *vmw, bool gb_aware,
0126 void *dst, uint32_t dst_size)
0127 {
0128 int ret;
0129 bool gb_objects = !!(vmw->capabilities & SVGA_CAP_GBOBJECTS);
0130 if (gb_objects && gb_aware) {
0131 memcpy(dst, vmw->devcaps, dst_size);
0132 } else if (gb_objects) {
0133 ret = vmw_fill_compat_cap(vmw, dst, dst_size);
0134 if (unlikely(ret != 0))
0135 return ret;
0136 } else if (vmw->fifo_mem) {
0137 u32 *fifo_mem = vmw->fifo_mem;
0138 memcpy(dst, &fifo_mem[SVGA_FIFO_3D_CAPS], dst_size);
0139 } else
0140 return -EINVAL;
0141 return 0;
0142 }