#include "radeon_drm.h"
#include "radeon_drv.h"
-drm_ioctl_desc_t radeon_ioctls[] = {
- [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = { radeon_cp_start, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_FREE)] = { radeon_mem_free, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = { radeon_mem_init_heap,1, 1 },
- [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },
- [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = { radeon_surface_free, 1, 0 }
-};
-
-int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
-
/* ================================================================
* Helper functions for client state checking and fixup
*/
break;
}
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
+ int i;
+ for (i = 0; i < 5; i++) {
+ if (radeon_check_and_fixup_offset(dev_priv,
+ filp_priv,
+ &data[i])) {
+ DRM_ERROR
+ ("Invalid R100 cubic texture offset\n");
+ return DRM_ERR(EINVAL);
+ }
+ }
+ }
+ break;
+
case RADEON_EMIT_RB3D_COLORPITCH:
case RADEON_EMIT_RE_LINE_PATTERN:
case RADEON_EMIT_SE_LINE_WIDTH:
case RADEON_EMIT_PP_TEX_SIZE_2:
case R200_EMIT_RB3D_BLENDCOLOR:
case R200_EMIT_TCL_POINT_SPRITE_CNTL:
+ case RADEON_EMIT_PP_CUBIC_FACES_0:
+ case RADEON_EMIT_PP_CUBIC_FACES_1:
+ case RADEON_EMIT_PP_CUBIC_FACES_2:
+ case R200_EMIT_PP_TRI_PERF_CNTL:
/* These packets don't contain memory offsets */
break;
{ RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
{ R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" },
{ R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" },
+ { RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+ { RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+ { RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+ { RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+ { RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
+ { RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
+ { R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
};
int size, dwords, tex_width, blit_width;
u32 height;
int i;
+ u32 texpitch, microtile;
RING_LOCALS;
DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
DRM_ERROR( "invalid texture format %d\n", tex->format );
return DRM_ERR(EINVAL);
}
+ texpitch = tex->pitch;
+ if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
+ microtile = 1;
+ if (tex_width < 64) {
+ texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
+ /* we got tiled coordinates, untile them */
+ image->x *= 2;
+ }
+ }
+ else microtile = 0;
DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
RADEON_GMC_CLR_CMP_CNTL_DIS |
RADEON_GMC_WR_MSK_DIS);
- buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
+ buffer[2] = (texpitch << 22) | (tex->offset >> 10);
buffer[3] = 0xffffffff;
buffer[4] = 0xffffffff;
buffer[5] = (image->y << 16) | image->x;
buffer[7] = dwords;
buffer += 8;
- if ( tex_width >= 32 ) {
- /* Texture image width is larger than the minimum, so we
- * can upload it directly.
- */
- if ( DRM_COPY_FROM_USER( buffer, data,
- dwords * sizeof(u32) ) ) {
- DRM_ERROR( "EFAULT on data, %d dwords\n",
- dwords );
- return DRM_ERR(EFAULT);
+
+
+ if (microtile) {
+ /* texture micro tiling in use, minimum texture width is thus 16 bytes.
+ however, we cannot use blitter directly for texture width < 64 bytes,
+ since minimum tex pitch is 64 bytes and we need this to match
+ the texture width, otherwise the blitter will tile it wrong.
+ Thus, tiling manually in this case. Additionally, need to special
+ case tex height = 1, since our actual image will have height 2
+ and we need to ensure we don't read beyond the texture size
+ from user space. */
+ if (tex->height == 1) {
+ if (tex_width >= 64 || tex_width <= 16) {
+ if (DRM_COPY_FROM_USER(buffer, data,
+ tex_width * sizeof(u32))) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ } else if (tex_width == 32) {
+ if (DRM_COPY_FROM_USER(buffer, data, 16)) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ if (DRM_COPY_FROM_USER(buffer + 8, data + 16, 16)) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ }
+ } else if (tex_width >= 64 || tex_width == 16) {
+ if (DRM_COPY_FROM_USER(buffer, data,
+ dwords * sizeof(u32))) {
+ DRM_ERROR("EFAULT on data, %d dwords\n",
+ dwords);
+ return DRM_ERR(EFAULT);
+ }
+ } else if (tex_width < 16) {
+ for (i = 0; i < tex->height; i++) {
+ if (DRM_COPY_FROM_USER(buffer, data, tex_width)) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ buffer += 4;
+ data += tex_width;
+ }
+ } else if (tex_width == 32) {
+ /* TODO: make sure this works when not fitting in one buffer
+ (i.e. 32bytes x 2048...) */
+ for (i = 0; i < tex->height; i += 2) {
+ if (DRM_COPY_FROM_USER(buffer, data, 16)) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+ if (DRM_COPY_FROM_USER(buffer + 8, data, 16)) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+ if (DRM_COPY_FROM_USER(buffer + 4, data, 16)) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+ if (DRM_COPY_FROM_USER(buffer + 12, data, 16)) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n",
+ tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ data += 16;
+ buffer += 16;
+ }
}
- } else {
- /* Texture image width is less than the minimum, so we
- * need to pad out each image scanline to the minimum
- * width.
- */
- for ( i = 0 ; i < tex->height ; i++ ) {
- if ( DRM_COPY_FROM_USER( buffer, data,
- tex_width ) ) {
- DRM_ERROR( "EFAULT on pad, %d bytes\n",
- tex_width );
+ }
+ else {
+ if (tex_width >= 32) {
+ /* Texture image width is larger than the minimum, so we
+ * can upload it directly.
+ */
+ if (DRM_COPY_FROM_USER(buffer, data,
+ dwords * sizeof(u32))) {
+ DRM_ERROR("EFAULT on data, %d dwords\n",
+ dwords);
return DRM_ERR(EFAULT);
}
- buffer += 8;
- data += tex_width;
+ } else {
+ /* Texture image width is less than the minimum, so we
+ * need to pad out each image scanline to the minimum
+ * width.
+ */
+ for (i = 0 ; i < tex->height ; i++) {
+ if (DRM_COPY_FROM_USER(buffer, data, tex_width )) {
+ DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width);
+ return DRM_ERR(EFAULT);
+ }
+ buffer += 8;
+ data += tex_width;
+ }
}
}
dev_priv->surfaces[s->surface_index].refcount--;
if (dev_priv->surfaces[s->surface_index].refcount == 0)
dev_priv->surfaces[s->surface_index].flags = 0;
- s->filp = 0;
+ s->filp = NULL;
radeon_apply_surface_regs(s->surface_index, dev_priv);
return 0;
}
/* ================================================================
* IOCTL functions
*/
-int radeon_surface_alloc(DRM_IOCTL_ARGS)
+static int radeon_surface_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_surface_free(DRM_IOCTL_ARGS)
+static int radeon_surface_free(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_clear( DRM_IOCTL_ARGS )
+static int radeon_cp_clear( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
/* Called whenever a client dies, from drm_release.
* NOTE: Lock isn't necessarily held when this is called!
*/
-int radeon_do_cleanup_pageflip( drm_device_t *dev )
+static int radeon_do_cleanup_pageflip( drm_device_t *dev )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
/* Swapping and flipping are different operations, need different ioctls.
* They can & should be intermixed to support multiple 3d windows.
*/
-int radeon_cp_flip( DRM_IOCTL_ARGS )
+static int radeon_cp_flip( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_swap( DRM_IOCTL_ARGS )
+static int radeon_cp_swap( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_vertex( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_indices( DRM_IOCTL_ARGS )
+static int radeon_cp_indices( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_texture( DRM_IOCTL_ARGS )
+static int radeon_cp_texture( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return ret;
}
-int radeon_cp_stipple( DRM_IOCTL_ARGS )
+static int radeon_cp_stipple( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_indirect( DRM_IOCTL_ARGS )
+static int radeon_cp_indirect( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_vertex2( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
+static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
if (kbuf == NULL)
return DRM_ERR(ENOMEM);
- if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz))
+ if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) {
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
return DRM_ERR(EFAULT);
+ }
cmdbuf.buf = kbuf;
}
-int radeon_cp_getparam( DRM_IOCTL_ARGS )
+static int radeon_cp_getparam( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
return 0;
}
-int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+static int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_file_t *filp_priv;
drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
}
+
+drm_ioctl_desc_t radeon_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = { radeon_cp_init, 1, 1 },
+ [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = { radeon_cp_start, 1, 1 },
+ [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 },
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 },
+ [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_RESET)] = { radeon_engine_reset, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 },
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = { radeon_cp_vertex2, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = { radeon_cp_cmdbuf, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = { radeon_cp_getparam, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = { radeon_cp_flip, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = { radeon_mem_alloc, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_FREE)] = { radeon_mem_free, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = { radeon_mem_init_heap,1, 1 },
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = { radeon_cp_setparam, 1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = { radeon_surface_free, 1, 0 }
+};
+
+int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);