radeon_state.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:38k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* radeon_state.c -- State support for Radeon -*- linux-c -*-
  2.  *
  3.  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the next
  14.  * paragraph) shall be included in all copies or substantial portions of the
  15.  * Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  *
  25.  * Authors:
  26.  *    Gareth Hughes <gareth@valinux.com>
  27.  *    Kevin E. Martin <martin@valinux.com>
  28.  */
  29. #define __NO_VERSION__
  30. #include "radeon.h"
  31. #include "drmP.h"
  32. #include "radeon_drv.h"
  33. #include "drm.h"
  34. #include <linux/delay.h>
  35. /* ================================================================
  36.  * CP hardware state programming functions
  37.  */
  38. static inline void radeon_emit_clip_rect( drm_radeon_private_t *dev_priv,
  39.   drm_clip_rect_t *box )
  40. {
  41. RING_LOCALS;
  42. DRM_DEBUG( "   box:  x1=%d y1=%d  x2=%d y2=%dn",
  43.    box->x1, box->y1, box->x2, box->y2 );
  44. BEGIN_RING( 4 );
  45. OUT_RING( CP_PACKET0( RADEON_RE_TOP_LEFT, 0 ) );
  46. OUT_RING( (box->y1 << 16) | box->x1 );
  47. OUT_RING( CP_PACKET0( RADEON_RE_WIDTH_HEIGHT, 0 ) );
  48. OUT_RING( ((box->y2 - 1) << 16) | (box->x2 - 1) );
  49. ADVANCE_RING();
  50. }
  51. static inline void radeon_emit_context( drm_radeon_private_t *dev_priv )
  52. {
  53. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  54. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  55. RING_LOCALS;
  56. DRM_DEBUG( "    %sn", __FUNCTION__ );
  57. BEGIN_RING( 14 );
  58. OUT_RING( CP_PACKET0( RADEON_PP_MISC, 6 ) );
  59. OUT_RING( ctx->pp_misc );
  60. OUT_RING( ctx->pp_fog_color );
  61. OUT_RING( ctx->re_solid_color );
  62. OUT_RING( ctx->rb3d_blendcntl );
  63. OUT_RING( ctx->rb3d_depthoffset );
  64. OUT_RING( ctx->rb3d_depthpitch );
  65. OUT_RING( ctx->rb3d_zstencilcntl );
  66. OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 2 ) );
  67. OUT_RING( ctx->pp_cntl );
  68. OUT_RING( ctx->rb3d_cntl );
  69. OUT_RING( ctx->rb3d_coloroffset );
  70. OUT_RING( CP_PACKET0( RADEON_RB3D_COLORPITCH, 0 ) );
  71. OUT_RING( ctx->rb3d_colorpitch );
  72. ADVANCE_RING();
  73. }
  74. static inline void radeon_emit_vertfmt( drm_radeon_private_t *dev_priv )
  75. {
  76. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  77. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  78. RING_LOCALS;
  79. DRM_DEBUG( "    %sn", __FUNCTION__ );
  80. BEGIN_RING( 2 );
  81. OUT_RING( CP_PACKET0( RADEON_SE_COORD_FMT, 0 ) );
  82. OUT_RING( ctx->se_coord_fmt );
  83. ADVANCE_RING();
  84. }
  85. static inline void radeon_emit_line( drm_radeon_private_t *dev_priv )
  86. {
  87. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  88. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  89. RING_LOCALS;
  90. DRM_DEBUG( "    %sn", __FUNCTION__ );
  91. BEGIN_RING( 5 );
  92. OUT_RING( CP_PACKET0( RADEON_RE_LINE_PATTERN, 1 ) );
  93. OUT_RING( ctx->re_line_pattern );
  94. OUT_RING( ctx->re_line_state );
  95. OUT_RING( CP_PACKET0( RADEON_SE_LINE_WIDTH, 0 ) );
  96. OUT_RING( ctx->se_line_width );
  97. ADVANCE_RING();
  98. }
  99. static inline void radeon_emit_bumpmap( drm_radeon_private_t *dev_priv )
  100. {
  101. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  102. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  103. RING_LOCALS;
  104. DRM_DEBUG( "    %sn", __FUNCTION__ );
  105. BEGIN_RING( 5 );
  106. OUT_RING( CP_PACKET0( RADEON_PP_LUM_MATRIX, 0 ) );
  107. OUT_RING( ctx->pp_lum_matrix );
  108. OUT_RING( CP_PACKET0( RADEON_PP_ROT_MATRIX_0, 1 ) );
  109. OUT_RING( ctx->pp_rot_matrix_0 );
  110. OUT_RING( ctx->pp_rot_matrix_1 );
  111. ADVANCE_RING();
  112. }
  113. static inline void radeon_emit_masks( drm_radeon_private_t *dev_priv )
  114. {
  115. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  116. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  117. RING_LOCALS;
  118. DRM_DEBUG( "    %sn", __FUNCTION__ );
  119. BEGIN_RING( 4 );
  120. OUT_RING( CP_PACKET0( RADEON_RB3D_STENCILREFMASK, 2 ) );
  121. OUT_RING( ctx->rb3d_stencilrefmask );
  122. OUT_RING( ctx->rb3d_ropcntl );
  123. OUT_RING( ctx->rb3d_planemask );
  124. ADVANCE_RING();
  125. }
  126. static inline void radeon_emit_viewport( drm_radeon_private_t *dev_priv )
  127. {
  128. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  129. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  130. RING_LOCALS;
  131. DRM_DEBUG( "    %sn", __FUNCTION__ );
  132. BEGIN_RING( 7 );
  133. OUT_RING( CP_PACKET0( RADEON_SE_VPORT_XSCALE, 5 ) );
  134. OUT_RING( ctx->se_vport_xscale );
  135. OUT_RING( ctx->se_vport_xoffset );
  136. OUT_RING( ctx->se_vport_yscale );
  137. OUT_RING( ctx->se_vport_yoffset );
  138. OUT_RING( ctx->se_vport_zscale );
  139. OUT_RING( ctx->se_vport_zoffset );
  140. ADVANCE_RING();
  141. }
  142. static inline void radeon_emit_setup( drm_radeon_private_t *dev_priv )
  143. {
  144. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  145. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  146. RING_LOCALS;
  147. DRM_DEBUG( "    %sn", __FUNCTION__ );
  148. BEGIN_RING( 4 );
  149. OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
  150. OUT_RING( ctx->se_cntl );
  151. OUT_RING( CP_PACKET0( RADEON_SE_CNTL_STATUS, 0 ) );
  152. OUT_RING( ctx->se_cntl_status );
  153. ADVANCE_RING();
  154. }
  155. static inline void radeon_emit_tcl( drm_radeon_private_t *dev_priv )
  156. {
  157. #ifdef TCL_ENABLE
  158. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  159. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  160. RING_LOCALS;
  161. DRM_DEBUG( "    %sn", __FUNCTION__ );
  162. BEGIN_RING( 29 );
  163. OUT_RING( CP_PACKET0( RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 27 ) );
  164. OUT_RING( ctx->se_tcl_material_emmissive.red );
  165. OUT_RING( ctx->se_tcl_material_emmissive.green );
  166. OUT_RING( ctx->se_tcl_material_emmissive.blue );
  167. OUT_RING( ctx->se_tcl_material_emmissive.alpha );
  168. OUT_RING( ctx->se_tcl_material_ambient.red );
  169. OUT_RING( ctx->se_tcl_material_ambient.green );
  170. OUT_RING( ctx->se_tcl_material_ambient.blue );
  171. OUT_RING( ctx->se_tcl_material_ambient.alpha );
  172. OUT_RING( ctx->se_tcl_material_diffuse.red );
  173. OUT_RING( ctx->se_tcl_material_diffuse.green );
  174. OUT_RING( ctx->se_tcl_material_diffuse.blue );
  175. OUT_RING( ctx->se_tcl_material_diffuse.alpha );
  176. OUT_RING( ctx->se_tcl_material_specular.red );
  177. OUT_RING( ctx->se_tcl_material_specular.green );
  178. OUT_RING( ctx->se_tcl_material_specular.blue );
  179. OUT_RING( ctx->se_tcl_material_specular.alpha );
  180. OUT_RING( ctx->se_tcl_shininess );
  181. OUT_RING( ctx->se_tcl_output_vtx_fmt );
  182. OUT_RING( ctx->se_tcl_output_vtx_sel );
  183. OUT_RING( ctx->se_tcl_matrix_select_0 );
  184. OUT_RING( ctx->se_tcl_matrix_select_1 );
  185. OUT_RING( ctx->se_tcl_ucp_vert_blend_ctl );
  186. OUT_RING( ctx->se_tcl_texture_proc_ctl );
  187. OUT_RING( ctx->se_tcl_light_model_ctl );
  188. for ( i = 0 ; i < 4 ; i++ ) {
  189. OUT_RING( ctx->se_tcl_per_light_ctl[i] );
  190. }
  191. ADVANCE_RING();
  192. #else
  193. DRM_ERROR( "TCL not enabled!n" );
  194. #endif
  195. }
  196. static inline void radeon_emit_misc( drm_radeon_private_t *dev_priv )
  197. {
  198. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  199. drm_radeon_context_regs_t *ctx = &sarea_priv->context_state;
  200. RING_LOCALS;
  201. DRM_DEBUG( "    %sn", __FUNCTION__ );
  202. BEGIN_RING( 2 );
  203. OUT_RING( CP_PACKET0( RADEON_RE_MISC, 0 ) );
  204. OUT_RING( ctx->re_misc );
  205. ADVANCE_RING();
  206. }
  207. static inline void radeon_emit_tex0( drm_radeon_private_t *dev_priv )
  208. {
  209. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  210. drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[0];
  211. RING_LOCALS;
  212. DRM_DEBUG( "    %s: offset=0x%xn", __FUNCTION__, tex->pp_txoffset );
  213. BEGIN_RING( 9 );
  214. OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_0, 5 ) );
  215. OUT_RING( tex->pp_txfilter );
  216. OUT_RING( tex->pp_txformat );
  217. OUT_RING( tex->pp_txoffset );
  218. OUT_RING( tex->pp_txcblend );
  219. OUT_RING( tex->pp_txablend );
  220. OUT_RING( tex->pp_tfactor );
  221. OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_0, 0 ) );
  222. OUT_RING( tex->pp_border_color );
  223. ADVANCE_RING();
  224. }
  225. static inline void radeon_emit_tex1( drm_radeon_private_t *dev_priv )
  226. {
  227. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  228. drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[1];
  229. RING_LOCALS;
  230. DRM_DEBUG( "    %s: offset=0x%xn", __FUNCTION__, tex->pp_txoffset );
  231. BEGIN_RING( 9 );
  232. OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_1, 5 ) );
  233. OUT_RING( tex->pp_txfilter );
  234. OUT_RING( tex->pp_txformat );
  235. OUT_RING( tex->pp_txoffset );
  236. OUT_RING( tex->pp_txcblend );
  237. OUT_RING( tex->pp_txablend );
  238. OUT_RING( tex->pp_tfactor );
  239. OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_1, 0 ) );
  240. OUT_RING( tex->pp_border_color );
  241. ADVANCE_RING();
  242. }
  243. static inline void radeon_emit_tex2( drm_radeon_private_t *dev_priv )
  244. {
  245. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  246. drm_radeon_texture_regs_t *tex = &sarea_priv->tex_state[2];
  247. RING_LOCALS;
  248. DRM_DEBUG( "    %sn", __FUNCTION__ );
  249. BEGIN_RING( 9 );
  250. OUT_RING( CP_PACKET0( RADEON_PP_TXFILTER_2, 5 ) );
  251. OUT_RING( tex->pp_txfilter );
  252. OUT_RING( tex->pp_txformat );
  253. OUT_RING( tex->pp_txoffset );
  254. OUT_RING( tex->pp_txcblend );
  255. OUT_RING( tex->pp_txablend );
  256. OUT_RING( tex->pp_tfactor );
  257. OUT_RING( CP_PACKET0( RADEON_PP_BORDER_COLOR_2, 0 ) );
  258. OUT_RING( tex->pp_border_color );
  259. ADVANCE_RING();
  260. }
  261. static inline void radeon_emit_state( drm_radeon_private_t *dev_priv )
  262. {
  263. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  264. unsigned int dirty = sarea_priv->dirty;
  265. DRM_DEBUG( "%s: dirty=0x%08xn", __FUNCTION__, dirty );
  266. if ( dirty & RADEON_UPLOAD_CONTEXT ) {
  267. radeon_emit_context( dev_priv );
  268. sarea_priv->dirty &= ~RADEON_UPLOAD_CONTEXT;
  269. }
  270. if ( dirty & RADEON_UPLOAD_VERTFMT ) {
  271. radeon_emit_vertfmt( dev_priv );
  272. sarea_priv->dirty &= ~RADEON_UPLOAD_VERTFMT;
  273. }
  274. if ( dirty & RADEON_UPLOAD_LINE ) {
  275. radeon_emit_line( dev_priv );
  276. sarea_priv->dirty &= ~RADEON_UPLOAD_LINE;
  277. }
  278. if ( dirty & RADEON_UPLOAD_BUMPMAP ) {
  279. radeon_emit_bumpmap( dev_priv );
  280. sarea_priv->dirty &= ~RADEON_UPLOAD_BUMPMAP;
  281. }
  282. if ( dirty & RADEON_UPLOAD_MASKS ) {
  283. radeon_emit_masks( dev_priv );
  284. sarea_priv->dirty &= ~RADEON_UPLOAD_MASKS;
  285. }
  286. if ( dirty & RADEON_UPLOAD_VIEWPORT ) {
  287. radeon_emit_viewport( dev_priv );
  288. sarea_priv->dirty &= ~RADEON_UPLOAD_VIEWPORT;
  289. }
  290. if ( dirty & RADEON_UPLOAD_SETUP ) {
  291. radeon_emit_setup( dev_priv );
  292. sarea_priv->dirty &= ~RADEON_UPLOAD_SETUP;
  293. }
  294. if ( dirty & RADEON_UPLOAD_TCL ) {
  295. #ifdef TCL_ENABLE
  296. radeon_emit_tcl( dev_priv );
  297. #endif
  298. sarea_priv->dirty &= ~RADEON_UPLOAD_TCL;
  299. }
  300. if ( dirty & RADEON_UPLOAD_MISC ) {
  301. radeon_emit_misc( dev_priv );
  302. sarea_priv->dirty &= ~RADEON_UPLOAD_MISC;
  303. }
  304. if ( dirty & RADEON_UPLOAD_TEX0 ) {
  305. radeon_emit_tex0( dev_priv );
  306. sarea_priv->dirty &= ~RADEON_UPLOAD_TEX0;
  307. }
  308. if ( dirty & RADEON_UPLOAD_TEX1 ) {
  309. radeon_emit_tex1( dev_priv );
  310. sarea_priv->dirty &= ~RADEON_UPLOAD_TEX1;
  311. }
  312. if ( dirty & RADEON_UPLOAD_TEX2 ) {
  313. #if 0
  314. radeon_emit_tex2( dev_priv );
  315. #endif
  316. sarea_priv->dirty &= ~RADEON_UPLOAD_TEX2;
  317. }
  318. sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES |
  319.        RADEON_UPLOAD_TEX1IMAGES |
  320.        RADEON_UPLOAD_TEX2IMAGES |
  321.        RADEON_REQUIRE_QUIESCENCE);
  322. }
  323. #if RADEON_PERFORMANCE_BOXES
  324. /* ================================================================
  325.  * Performance monitoring functions
  326.  */
  327. static void radeon_clear_box( drm_radeon_private_t *dev_priv,
  328.       int x, int y, int w, int h,
  329.       int r, int g, int b )
  330. {
  331. u32 pitch, offset;
  332. u32 color;
  333. RING_LOCALS;
  334. switch ( dev_priv->color_fmt ) {
  335. case RADEON_COLOR_FORMAT_RGB565:
  336. color = (((r & 0xf8) << 8) |
  337.  ((g & 0xfc) << 3) |
  338.  ((b & 0xf8) >> 3));
  339. break;
  340. case RADEON_COLOR_FORMAT_ARGB8888:
  341. default:
  342. color = (((0xff) << 24) | (r << 16) | (g <<  8) | b);
  343. break;
  344. }
  345. offset = dev_priv->back_offset;
  346. pitch = dev_priv->back_pitch >> 3;
  347. BEGIN_RING( 6 );
  348. OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
  349. OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
  350.   RADEON_GMC_BRUSH_SOLID_COLOR |
  351.   (dev_priv->color_fmt << 8) |
  352.   RADEON_GMC_SRC_DATATYPE_COLOR |
  353.   RADEON_ROP3_P |
  354.   RADEON_GMC_CLR_CMP_CNTL_DIS );
  355. OUT_RING( (pitch << 22) | (offset >> 5) );
  356. OUT_RING( color );
  357. OUT_RING( (x << 16) | y );
  358. OUT_RING( (w << 16) | h );
  359. ADVANCE_RING();
  360. }
  361. static void radeon_cp_performance_boxes( drm_radeon_private_t *dev_priv )
  362. {
  363. if ( atomic_read( &dev_priv->idle_count ) == 0 ) {
  364. radeon_clear_box( dev_priv, 64, 4, 8, 8, 0, 255, 0 );
  365. } else {
  366. atomic_set( &dev_priv->idle_count, 0 );
  367. }
  368. }
  369. #endif
  370. /* ================================================================
  371.  * CP command dispatch functions
  372.  */
  373. static void radeon_print_dirty( const char *msg, unsigned int flags )
  374. {
  375. DRM_DEBUG( "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%sn",
  376.    msg,
  377.    flags,
  378.    (flags & RADEON_UPLOAD_CONTEXT)     ? "context, " : "",
  379.    (flags & RADEON_UPLOAD_VERTFMT)     ? "vertfmt, " : "",
  380.    (flags & RADEON_UPLOAD_LINE)        ? "line, " : "",
  381.    (flags & RADEON_UPLOAD_BUMPMAP)     ? "bumpmap, " : "",
  382.    (flags & RADEON_UPLOAD_MASKS)       ? "masks, " : "",
  383.    (flags & RADEON_UPLOAD_VIEWPORT)    ? "viewport, " : "",
  384.    (flags & RADEON_UPLOAD_SETUP)       ? "setup, " : "",
  385.    (flags & RADEON_UPLOAD_TCL)         ? "tcl, " : "",
  386.    (flags & RADEON_UPLOAD_MISC)        ? "misc, " : "",
  387.    (flags & RADEON_UPLOAD_TEX0)        ? "tex0, " : "",
  388.    (flags & RADEON_UPLOAD_TEX1)        ? "tex1, " : "",
  389.    (flags & RADEON_UPLOAD_TEX2)        ? "tex2, " : "",
  390.    (flags & RADEON_UPLOAD_CLIPRECTS)   ? "cliprects, " : "",
  391.    (flags & RADEON_REQUIRE_QUIESCENCE) ? "quiescence, " : "" );
  392. }
  393. static void radeon_cp_dispatch_clear( drm_device_t *dev,
  394.       drm_radeon_clear_t *clear,
  395.       drm_radeon_clear_rect_t *depth_boxes )
  396. {
  397. drm_radeon_private_t *dev_priv = dev->dev_private;
  398. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  399. int nbox = sarea_priv->nbox;
  400. drm_clip_rect_t *pbox = sarea_priv->boxes;
  401. unsigned int flags = clear->flags;
  402. int i;
  403. RING_LOCALS;
  404. DRM_DEBUG( "%sn", __FUNCTION__ );
  405. if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) {
  406. unsigned int tmp = flags;
  407. flags &= ~(RADEON_FRONT | RADEON_BACK);
  408. if ( tmp & RADEON_FRONT ) flags |= RADEON_BACK;
  409. if ( tmp & RADEON_BACK )  flags |= RADEON_FRONT;
  410. }
  411. for ( i = 0 ; i < nbox ; i++ ) {
  412. int x = pbox[i].x1;
  413. int y = pbox[i].y1;
  414. int w = pbox[i].x2 - x;
  415. int h = pbox[i].y2 - y;
  416. DRM_DEBUG( "dispatch clear %d,%d-%d,%d flags 0x%xn",
  417.    x, y, w, h, flags );
  418. if ( flags & (RADEON_FRONT | RADEON_BACK) ) {
  419. BEGIN_RING( 4 );
  420. /* Ensure the 3D stream is idle before doing a
  421.  * 2D fill to clear the front or back buffer.
  422.  */
  423. RADEON_WAIT_UNTIL_3D_IDLE();
  424. OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) );
  425. OUT_RING( clear->color_mask );
  426. ADVANCE_RING();
  427. /* Make sure we restore the 3D state next time.
  428.  */
  429. dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
  430. RADEON_UPLOAD_MASKS);
  431. }
  432. if ( flags & RADEON_FRONT ) {
  433. BEGIN_RING( 6 );
  434. OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
  435. OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
  436.   RADEON_GMC_BRUSH_SOLID_COLOR |
  437.   (dev_priv->color_fmt << 8) |
  438.   RADEON_GMC_SRC_DATATYPE_COLOR |
  439.   RADEON_ROP3_P |
  440.   RADEON_GMC_CLR_CMP_CNTL_DIS );
  441. OUT_RING( dev_priv->front_pitch_offset );
  442. OUT_RING( clear->clear_color );
  443. OUT_RING( (x << 16) | y );
  444. OUT_RING( (w << 16) | h );
  445. ADVANCE_RING();
  446. }
  447. if ( flags & RADEON_BACK ) {
  448. BEGIN_RING( 6 );
  449. OUT_RING( CP_PACKET3( RADEON_CNTL_PAINT_MULTI, 4 ) );
  450. OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL |
  451.   RADEON_GMC_BRUSH_SOLID_COLOR |
  452.   (dev_priv->color_fmt << 8) |
  453.   RADEON_GMC_SRC_DATATYPE_COLOR |
  454.   RADEON_ROP3_P |
  455.   RADEON_GMC_CLR_CMP_CNTL_DIS );
  456. OUT_RING( dev_priv->back_pitch_offset );
  457. OUT_RING( clear->clear_color );
  458. OUT_RING( (x << 16) | y );
  459. OUT_RING( (w << 16) | h );
  460. ADVANCE_RING();
  461. }
  462. if ( flags & RADEON_DEPTH ) {
  463. drm_radeon_depth_clear_t *depth_clear =
  464.    &dev_priv->depth_clear;
  465. if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
  466. radeon_emit_state( dev_priv );
  467. }
  468. /* FIXME: Render a rectangle to clear the depth
  469.  * buffer.  So much for those "fast Z clears"...
  470.  */
  471. BEGIN_RING( 23 );
  472. RADEON_WAIT_UNTIL_2D_IDLE();
  473. OUT_RING( CP_PACKET0( RADEON_PP_CNTL, 1 ) );
  474. OUT_RING( 0x00000000 );
  475. OUT_RING( depth_clear->rb3d_cntl );
  476. OUT_RING( CP_PACKET0( RADEON_RB3D_ZSTENCILCNTL, 0 ) );
  477. OUT_RING( depth_clear->rb3d_zstencilcntl );
  478. OUT_RING( CP_PACKET0( RADEON_RB3D_PLANEMASK, 0 ) );
  479. OUT_RING( 0x00000000 );
  480. OUT_RING( CP_PACKET0( RADEON_SE_CNTL, 0 ) );
  481. OUT_RING( depth_clear->se_cntl );
  482. OUT_RING( CP_PACKET3( RADEON_3D_DRAW_IMMD, 10 ) );
  483. OUT_RING( RADEON_VTX_Z_PRESENT );
  484. OUT_RING( (RADEON_PRIM_TYPE_RECT_LIST |
  485.    RADEON_PRIM_WALK_RING |
  486.    RADEON_MAOS_ENABLE |
  487.    RADEON_VTX_FMT_RADEON_MODE |
  488.    (3 << RADEON_NUM_VERTICES_SHIFT)) );
  489. OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
  490. OUT_RING( depth_boxes[i].ui[CLEAR_Y1] );
  491. OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
  492. OUT_RING( depth_boxes[i].ui[CLEAR_X1] );
  493. OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
  494. OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
  495. OUT_RING( depth_boxes[i].ui[CLEAR_X2] );
  496. OUT_RING( depth_boxes[i].ui[CLEAR_Y2] );
  497. OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] );
  498. ADVANCE_RING();
  499. /* Make sure we restore the 3D state next time.
  500.  */
  501. dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
  502. RADEON_UPLOAD_SETUP |
  503. RADEON_UPLOAD_MASKS);
  504. }
  505. }
  506. /* Increment the clear counter.  The client-side 3D driver must
  507.  * wait on this value before performing the clear ioctl.  We
  508.  * need this because the card's so damned fast...
  509.  */
  510. dev_priv->sarea_priv->last_clear++;
  511. BEGIN_RING( 4 );
  512. RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear );
  513. RADEON_WAIT_UNTIL_IDLE();
  514. ADVANCE_RING();
  515. }
  516. static void radeon_cp_dispatch_swap( drm_device_t *dev )
  517. {
  518. drm_radeon_private_t *dev_priv = dev->dev_private;
  519. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  520. int nbox = sarea_priv->nbox;
  521. drm_clip_rect_t *pbox = sarea_priv->boxes;
  522. int i;
  523. RING_LOCALS;
  524. DRM_DEBUG( "%sn", __FUNCTION__ );
  525. #if RADEON_PERFORMANCE_BOXES
  526. /* Do some trivial performance monitoring...
  527.  */
  528. radeon_cp_performance_boxes( dev_priv );
  529. #endif
  530. /* Wait for the 3D stream to idle before dispatching the bitblt.
  531.  * This will prevent data corruption between the two streams.
  532.  */
  533. BEGIN_RING( 2 );
  534. RADEON_WAIT_UNTIL_3D_IDLE();
  535. ADVANCE_RING();
  536. for ( i = 0 ; i < nbox ; i++ ) {
  537. int x = pbox[i].x1;
  538. int y = pbox[i].y1;
  539. int w = pbox[i].x2 - x;
  540. int h = pbox[i].y2 - y;
  541. DRM_DEBUG( "dispatch swap %d,%d-%d,%dn",
  542.    x, y, w, h );
  543. BEGIN_RING( 7 );
  544. OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) );
  545. OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
  546.   RADEON_GMC_DST_PITCH_OFFSET_CNTL |
  547.   RADEON_GMC_BRUSH_NONE |
  548.   (dev_priv->color_fmt << 8) |
  549.   RADEON_GMC_SRC_DATATYPE_COLOR |
  550.   RADEON_ROP3_S |
  551.   RADEON_DP_SRC_SOURCE_MEMORY |
  552.   RADEON_GMC_CLR_CMP_CNTL_DIS |
  553.   RADEON_GMC_WR_MSK_DIS );
  554. OUT_RING( dev_priv->back_pitch_offset );
  555. OUT_RING( dev_priv->front_pitch_offset );
  556. OUT_RING( (x << 16) | y );
  557. OUT_RING( (x << 16) | y );
  558. OUT_RING( (w << 16) | h );
  559. ADVANCE_RING();
  560. }
  561. /* Increment the frame counter.  The client-side 3D driver must
  562.  * throttle the framerate by waiting for this value before
  563.  * performing the swapbuffer ioctl.
  564.  */
  565. dev_priv->sarea_priv->last_frame++;
  566. BEGIN_RING( 4 );
  567. RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
  568. RADEON_WAIT_UNTIL_2D_IDLE();
  569. ADVANCE_RING();
  570. }
  571. static void radeon_cp_dispatch_flip( drm_device_t *dev )
  572. {
  573. drm_radeon_private_t *dev_priv = dev->dev_private;
  574. RING_LOCALS;
  575. DRM_DEBUG( "%s: page=%dn", __FUNCTION__, dev_priv->current_page );
  576. #if RADEON_PERFORMANCE_BOXES
  577. /* Do some trivial performance monitoring...
  578.  */
  579. radeon_cp_performance_boxes( dev_priv );
  580. #endif
  581. BEGIN_RING( 6 );
  582. RADEON_WAIT_UNTIL_3D_IDLE();
  583. RADEON_WAIT_UNTIL_PAGE_FLIPPED();
  584. OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) );
  585. if ( dev_priv->current_page == 0 ) {
  586. OUT_RING( dev_priv->back_offset );
  587. dev_priv->current_page = 1;
  588. } else {
  589. OUT_RING( dev_priv->front_offset );
  590. dev_priv->current_page = 0;
  591. }
  592. ADVANCE_RING();
  593. /* Increment the frame counter.  The client-side 3D driver must
  594.  * throttle the framerate by waiting for this value before
  595.  * performing the swapbuffer ioctl.
  596.  */
  597. dev_priv->sarea_priv->last_frame++;
  598. BEGIN_RING( 2 );
  599. RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame );
  600. ADVANCE_RING();
  601. }
  602. static void radeon_cp_dispatch_vertex( drm_device_t *dev,
  603.        drm_buf_t *buf )
  604. {
  605. drm_radeon_private_t *dev_priv = dev->dev_private;
  606. drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
  607. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  608. int format = sarea_priv->vc_format;
  609. int offset = dev_priv->agp_buffers_offset + buf->offset;
  610. int size = buf->used;
  611. int prim = buf_priv->prim;
  612. int i = 0;
  613. RING_LOCALS;
  614. DRM_DEBUG( "%s: nbox=%dn", __FUNCTION__, sarea_priv->nbox );
  615. if ( 0 )
  616. radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty );
  617. if ( buf->used ) {
  618. buf_priv->dispatched = 1;
  619. if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
  620. radeon_emit_state( dev_priv );
  621. }
  622. do {
  623. /* Emit the next set of up to three cliprects */
  624. if ( i < sarea_priv->nbox ) {
  625. radeon_emit_clip_rect( dev_priv,
  626.        &sarea_priv->boxes[i] );
  627. }
  628. /* Emit the vertex buffer rendering commands */
  629. BEGIN_RING( 5 );
  630. OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) );
  631. OUT_RING( offset );
  632. OUT_RING( size );
  633. OUT_RING( format );
  634. OUT_RING( prim | RADEON_PRIM_WALK_LIST |
  635.   RADEON_COLOR_ORDER_RGBA |
  636.   RADEON_VTX_FMT_RADEON_MODE |
  637.   (size << RADEON_NUM_VERTICES_SHIFT) );
  638. ADVANCE_RING();
  639. i++;
  640. } while ( i < sarea_priv->nbox );
  641. }
  642. if ( buf_priv->discard ) {
  643. buf_priv->age = dev_priv->sarea_priv->last_dispatch;
  644. /* Emit the vertex buffer age */
  645. BEGIN_RING( 2 );
  646. RADEON_DISPATCH_AGE( buf_priv->age );
  647. ADVANCE_RING();
  648. buf->pending = 1;
  649. buf->used = 0;
  650. /* FIXME: Check dispatched field */
  651. buf_priv->dispatched = 0;
  652. }
  653. dev_priv->sarea_priv->last_dispatch++;
  654. sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
  655. sarea_priv->nbox = 0;
  656. }
  657. static void radeon_cp_dispatch_indirect( drm_device_t *dev,
  658.  drm_buf_t *buf,
  659.  int start, int end )
  660. {
  661. drm_radeon_private_t *dev_priv = dev->dev_private;
  662. drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
  663. RING_LOCALS;
  664. DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%xn",
  665.    buf->idx, start, end );
  666. if ( start != end ) {
  667. int offset = (dev_priv->agp_buffers_offset
  668.       + buf->offset + start);
  669. int dwords = (end - start + 3) / sizeof(u32);
  670. /* Indirect buffer data must be an even number of
  671.  * dwords, so if we've been given an odd number we must
  672.  * pad the data with a Type-2 CP packet.
  673.  */
  674. if ( dwords & 1 ) {
  675. u32 *data = (u32 *)
  676. ((char *)dev_priv->buffers->handle
  677.  + buf->offset + start);
  678. data[dwords++] = RADEON_CP_PACKET2;
  679. }
  680. buf_priv->dispatched = 1;
  681. /* Fire off the indirect buffer */
  682. BEGIN_RING( 3 );
  683. OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) );
  684. OUT_RING( offset );
  685. OUT_RING( dwords );
  686. ADVANCE_RING();
  687. }
  688. if ( buf_priv->discard ) {
  689. buf_priv->age = dev_priv->sarea_priv->last_dispatch;
  690. /* Emit the indirect buffer age */
  691. BEGIN_RING( 2 );
  692. RADEON_DISPATCH_AGE( buf_priv->age );
  693. ADVANCE_RING();
  694. buf->pending = 1;
  695. buf->used = 0;
  696. /* FIXME: Check dispatched field */
  697. buf_priv->dispatched = 0;
  698. }
  699. dev_priv->sarea_priv->last_dispatch++;
  700. }
  701. static void radeon_cp_dispatch_indices( drm_device_t *dev,
  702. drm_buf_t *buf,
  703. int start, int end,
  704. int count )
  705. {
  706. drm_radeon_private_t *dev_priv = dev->dev_private;
  707. drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
  708. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  709. int format = sarea_priv->vc_format;
  710. int offset = dev_priv->agp_buffers_offset;
  711. int prim = buf_priv->prim;
  712. u32 *data;
  713. int dwords;
  714. int i = 0;
  715. RING_LOCALS;
  716. DRM_DEBUG( "indices: s=%d e=%d c=%dn", start, end, count );
  717. if ( 0 )
  718. radeon_print_dirty( "dispatch_indices", sarea_priv->dirty );
  719. if ( start != end ) {
  720. buf_priv->dispatched = 1;
  721. if ( sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS ) {
  722. radeon_emit_state( dev_priv );
  723. }
  724. dwords = (end - start + 3) / sizeof(u32);
  725. data = (u32 *)((char *)dev_priv->buffers->handle
  726.        + buf->offset + start);
  727. data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
  728. data[1] = offset;
  729. data[2] = RADEON_MAX_VB_VERTS;
  730. data[3] = format;
  731. data[4] = (prim | RADEON_PRIM_WALK_IND |
  732.    RADEON_COLOR_ORDER_RGBA |
  733.    RADEON_VTX_FMT_RADEON_MODE |
  734.    (count << RADEON_NUM_VERTICES_SHIFT) );
  735. if ( count & 0x1 ) {
  736. data[dwords-1] &= 0x0000ffff;
  737. }
  738. do {
  739. /* Emit the next set of up to three cliprects */
  740. if ( i < sarea_priv->nbox ) {
  741. radeon_emit_clip_rect( dev_priv,
  742.        &sarea_priv->boxes[i] );
  743. }
  744. radeon_cp_dispatch_indirect( dev, buf, start, end );
  745. i++;
  746. } while ( i < sarea_priv->nbox );
  747. }
  748. if ( buf_priv->discard ) {
  749. buf_priv->age = dev_priv->sarea_priv->last_dispatch;
  750. /* Emit the vertex buffer age */
  751. BEGIN_RING( 2 );
  752. RADEON_DISPATCH_AGE( buf_priv->age );
  753. ADVANCE_RING();
  754. buf->pending = 1;
  755. /* FIXME: Check dispatched field */
  756. buf_priv->dispatched = 0;
  757. }
  758. dev_priv->sarea_priv->last_dispatch++;
  759. sarea_priv->dirty &= ~RADEON_UPLOAD_CLIPRECTS;
  760. sarea_priv->nbox = 0;
  761. }
  762. #define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))
  763. static int radeon_cp_dispatch_texture( drm_device_t *dev,
  764.        drm_radeon_texture_t *tex,
  765.        drm_radeon_tex_image_t *image )
  766. {
  767. drm_radeon_private_t *dev_priv = dev->dev_private;
  768. drm_buf_t *buf;
  769. drm_radeon_buf_priv_t *buf_priv;
  770. u32 format;
  771. u32 *buffer;
  772. u8 *data;
  773. int size, dwords, tex_width, blit_width;
  774. u32 y, height;
  775. int ret = 0, i;
  776. RING_LOCALS;
  777. /* FIXME: Be smarter about this...
  778.  */
  779. buf = radeon_freelist_get( dev );
  780. if ( !buf ) return -EAGAIN;
  781. DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hdn",
  782.    tex->offset >> 10, tex->pitch, tex->format,
  783.    image->x, image->y, image->width, image->height );
  784. buf_priv = buf->dev_private;
  785. /* The compiler won't optimize away a division by a variable,
  786.  * even if the only legal values are powers of two.  Thus, we'll
  787.  * use a shift instead.
  788.  */
  789. switch ( tex->format ) {
  790. case RADEON_TXFORMAT_ARGB8888:
  791. case RADEON_TXFORMAT_RGBA8888:
  792. format = RADEON_COLOR_FORMAT_ARGB8888;
  793. tex_width = tex->width * 4;
  794. blit_width = image->width * 4;
  795. break;
  796. case RADEON_TXFORMAT_AI88:
  797. case RADEON_TXFORMAT_ARGB1555:
  798. case RADEON_TXFORMAT_RGB565:
  799. case RADEON_TXFORMAT_ARGB4444:
  800. format = RADEON_COLOR_FORMAT_RGB565;
  801. tex_width = tex->width * 2;
  802. blit_width = image->width * 2;
  803. break;
  804. case RADEON_TXFORMAT_I8:
  805. case RADEON_TXFORMAT_RGB332:
  806. format = RADEON_COLOR_FORMAT_CI8;
  807. tex_width = tex->width * 1;
  808. blit_width = image->width * 1;
  809. break;
  810. default:
  811. DRM_ERROR( "invalid texture format %dn", tex->format );
  812. return -EINVAL;
  813. }
  814. DRM_DEBUG( "   tex=%dx%d  blit=%dn",
  815.    tex_width, tex->height, blit_width );
  816. /* Flush the pixel cache.  This ensures no pixel data gets mixed
  817.  * up with the texture data from the host data blit, otherwise
  818.  * part of the texture image may be corrupted.
  819.  */
  820. BEGIN_RING( 4 );
  821. RADEON_FLUSH_CACHE();
  822. RADEON_WAIT_UNTIL_IDLE();
  823. ADVANCE_RING();
  824. /* Make a copy of the parameters in case we have to update them
  825.  * for a multi-pass texture blit.
  826.  */
  827. y = image->y;
  828. height = image->height;
  829. data = (u8 *)image->data;
  830. size = height * blit_width;
  831. if ( size > RADEON_MAX_TEXTURE_SIZE ) {
  832. /* Texture image is too large, do a multipass upload */
  833. ret = -EAGAIN;
  834. /* Adjust the blit size to fit the indirect buffer */
  835. height = RADEON_MAX_TEXTURE_SIZE / blit_width;
  836. size = height * blit_width;
  837. /* Update the input parameters for next time */
  838. image->y += height;
  839. image->height -= height;
  840. image->data = (char *)image->data + size;
  841. if ( copy_to_user( tex->image, image, sizeof(*image) ) ) {
  842. DRM_ERROR( "EFAULT on tex->imagen" );
  843. return -EFAULT;
  844. }
  845. } else if ( size < 4 ) {
  846. size = 4;
  847. }
  848. dwords = size / 4;
  849. /* Dispatch the indirect buffer.
  850.  */
  851. buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
  852. buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
  853. buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
  854.      RADEON_GMC_BRUSH_NONE |
  855.      (format << 8) |
  856.      RADEON_GMC_SRC_DATATYPE_COLOR |
  857.      RADEON_ROP3_S |
  858.      RADEON_DP_SRC_SOURCE_HOST_DATA |
  859.      RADEON_GMC_CLR_CMP_CNTL_DIS |
  860.      RADEON_GMC_WR_MSK_DIS);
  861. buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
  862. buffer[3] = 0xffffffff;
  863. buffer[4] = 0xffffffff;
  864. buffer[5] = (y << 16) | image->x;
  865. buffer[6] = (height << 16) | image->width;
  866. buffer[7] = dwords;
  867. buffer += 8;
  868. if ( tex_width >= 32 ) {
  869. /* Texture image width is larger than the minimum, so we
  870.  * can upload it directly.
  871.  */
  872. if ( copy_from_user( buffer, data, dwords * sizeof(u32) ) ) {
  873. DRM_ERROR( "EFAULT on data, %d dwordsn", dwords );
  874. return -EFAULT;
  875. }
  876. } else {
  877. /* Texture image width is less than the minimum, so we
  878.  * need to pad out each image scanline to the minimum
  879.  * width.
  880.  */
  881. for ( i = 0 ; i < tex->height ; i++ ) {
  882. if ( copy_from_user( buffer, data, tex_width ) ) {
  883. DRM_ERROR( "EFAULT on pad, %d bytesn",
  884.    tex_width );
  885. return -EFAULT;
  886. }
  887. buffer += 8;
  888. data += tex_width;
  889. }
  890. }
  891. buf->pid = current->pid;
  892. buf->used = (dwords + 8) * sizeof(u32);
  893. buf_priv->discard = 1;
  894. radeon_cp_dispatch_indirect( dev, buf, 0, buf->used );
  895. /* Flush the pixel cache after the blit completes.  This ensures
  896.  * the texture data is written out to memory before rendering
  897.  * continues.
  898.  */
  899. BEGIN_RING( 4 );
  900. RADEON_FLUSH_CACHE();
  901. RADEON_WAIT_UNTIL_2D_IDLE();
  902. ADVANCE_RING();
  903. return ret;
  904. }
  905. static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple )
  906. {
  907. drm_radeon_private_t *dev_priv = dev->dev_private;
  908. int i;
  909. RING_LOCALS;
  910. DRM_DEBUG( "%sn", __FUNCTION__ );
  911. BEGIN_RING( 35 );
  912. OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) );
  913. OUT_RING( 0x00000000 );
  914. OUT_RING( CP_PACKET0_TABLE( RADEON_RE_STIPPLE_DATA, 31 ) );
  915. for ( i = 0 ; i < 32 ; i++ ) {
  916. OUT_RING( stipple[i] );
  917. }
  918. ADVANCE_RING();
  919. }
  920. /* ================================================================
  921.  * IOCTL functions
  922.  */
  923. int radeon_cp_clear( struct inode *inode, struct file *filp,
  924.      unsigned int cmd, unsigned long arg )
  925. {
  926. drm_file_t *priv = filp->private_data;
  927. drm_device_t *dev = priv->dev;
  928. drm_radeon_private_t *dev_priv = dev->dev_private;
  929. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  930. drm_radeon_clear_t clear;
  931. drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
  932. DRM_DEBUG( "%sn", __FUNCTION__ );
  933. LOCK_TEST_WITH_RETURN( dev );
  934. if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg,
  935.      sizeof(clear) ) )
  936. return -EFAULT;
  937. RING_SPACE_TEST_WITH_RETURN( dev_priv );
  938. if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
  939. sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
  940. if ( copy_from_user( &depth_boxes, clear.depth_boxes,
  941.      sarea_priv->nbox * sizeof(depth_boxes[0]) ) )
  942. return -EFAULT;
  943. radeon_cp_dispatch_clear( dev, &clear, depth_boxes );
  944. return 0;
  945. }
  946. int radeon_cp_swap( struct inode *inode, struct file *filp,
  947.     unsigned int cmd, unsigned long arg )
  948. {
  949. drm_file_t *priv = filp->private_data;
  950. drm_device_t *dev = priv->dev;
  951. drm_radeon_private_t *dev_priv = dev->dev_private;
  952. drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
  953. DRM_DEBUG( "%sn", __FUNCTION__ );
  954. LOCK_TEST_WITH_RETURN( dev );
  955. RING_SPACE_TEST_WITH_RETURN( dev_priv );
  956. if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS )
  957. sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
  958. if ( !dev_priv->page_flipping ) {
  959. radeon_cp_dispatch_swap( dev );
  960. dev_priv->sarea_priv->dirty |= (RADEON_UPLOAD_CONTEXT |
  961. RADEON_UPLOAD_MASKS);
  962. } else {
  963. radeon_cp_dispatch_flip( dev );
  964. }
  965. return 0;
  966. }
  967. int radeon_cp_vertex( struct inode *inode, struct file *filp,
  968.       unsigned int cmd, unsigned long arg )
  969. {
  970. drm_file_t *priv = filp->private_data;
  971. drm_device_t *dev = priv->dev;
  972. drm_radeon_private_t *dev_priv = dev->dev_private;
  973. drm_device_dma_t *dma = dev->dma;
  974. drm_buf_t *buf;
  975. drm_radeon_buf_priv_t *buf_priv;
  976. drm_radeon_vertex_t vertex;
  977. LOCK_TEST_WITH_RETURN( dev );
  978. if ( !dev_priv ) {
  979. DRM_ERROR( "%s called with no initializationn", __FUNCTION__ );
  980. return -EINVAL;
  981. }
  982. if ( copy_from_user( &vertex, (drm_radeon_vertex_t *)arg,
  983.      sizeof(vertex) ) )
  984. return -EFAULT;
  985. DRM_DEBUG( "%s: pid=%d index=%d count=%d discard=%dn",
  986.    __FUNCTION__, current->pid,
  987.    vertex.idx, vertex.count, vertex.discard );
  988. if ( vertex.idx < 0 || vertex.idx >= dma->buf_count ) {
  989. DRM_ERROR( "buffer index %d (of %d max)n",
  990.    vertex.idx, dma->buf_count - 1 );
  991. return -EINVAL;
  992. }
  993. if ( vertex.prim < 0 ||
  994.      vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
  995. DRM_ERROR( "buffer prim %dn", vertex.prim );
  996. return -EINVAL;
  997. }
  998. RING_SPACE_TEST_WITH_RETURN( dev_priv );
  999. VB_AGE_TEST_WITH_RETURN( dev_priv );
  1000. buf = dma->buflist[vertex.idx];
  1001. buf_priv = buf->dev_private;
  1002. if ( buf->pid != current->pid ) {
  1003. DRM_ERROR( "process %d using buffer owned by %dn",
  1004.    current->pid, buf->pid );
  1005. return -EINVAL;
  1006. }
  1007. if ( buf->pending ) {
  1008. DRM_ERROR( "sending pending buffer %dn", vertex.idx );
  1009. return -EINVAL;
  1010. }
  1011. buf->used = vertex.count;
  1012. buf_priv->prim = vertex.prim;
  1013. buf_priv->discard = vertex.discard;
  1014. radeon_cp_dispatch_vertex( dev, buf );
  1015. return 0;
  1016. }
  1017. int radeon_cp_indices( struct inode *inode, struct file *filp,
  1018.        unsigned int cmd, unsigned long arg )
  1019. {
  1020. drm_file_t *priv = filp->private_data;
  1021. drm_device_t *dev = priv->dev;
  1022. drm_radeon_private_t *dev_priv = dev->dev_private;
  1023. drm_device_dma_t *dma = dev->dma;
  1024. drm_buf_t *buf;
  1025. drm_radeon_buf_priv_t *buf_priv;
  1026. drm_radeon_indices_t elts;
  1027. int count;
  1028. LOCK_TEST_WITH_RETURN( dev );
  1029. if ( !dev_priv ) {
  1030. DRM_ERROR( "%s called with no initializationn", __FUNCTION__ );
  1031. return -EINVAL;
  1032. }
  1033. if ( copy_from_user( &elts, (drm_radeon_indices_t *)arg,
  1034.      sizeof(elts) ) )
  1035. return -EFAULT;
  1036. DRM_DEBUG( "%s: pid=%d index=%d start=%d end=%d discard=%dn",
  1037.    __FUNCTION__, current->pid,
  1038.    elts.idx, elts.start, elts.end, elts.discard );
  1039. if ( elts.idx < 0 || elts.idx >= dma->buf_count ) {
  1040. DRM_ERROR( "buffer index %d (of %d max)n",
  1041.    elts.idx, dma->buf_count - 1 );
  1042. return -EINVAL;
  1043. }
  1044. if ( elts.prim < 0 ||
  1045.      elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
  1046. DRM_ERROR( "buffer prim %dn", elts.prim );
  1047. return -EINVAL;
  1048. }
  1049. RING_SPACE_TEST_WITH_RETURN( dev_priv );
  1050. VB_AGE_TEST_WITH_RETURN( dev_priv );
  1051. buf = dma->buflist[elts.idx];
  1052. buf_priv = buf->dev_private;
  1053. if ( buf->pid != current->pid ) {
  1054. DRM_ERROR( "process %d using buffer owned by %dn",
  1055.    current->pid, buf->pid );
  1056. return -EINVAL;
  1057. }
  1058. if ( buf->pending ) {
  1059. DRM_ERROR( "sending pending buffer %dn", elts.idx );
  1060. return -EINVAL;
  1061. }
  1062. count = (elts.end - elts.start) / sizeof(u16);
  1063. elts.start -= RADEON_INDEX_PRIM_OFFSET;
  1064. if ( elts.start & 0x7 ) {
  1065. DRM_ERROR( "misaligned buffer 0x%xn", elts.start );
  1066. return -EINVAL;
  1067. }
  1068. if ( elts.start < buf->used ) {
  1069. DRM_ERROR( "no header 0x%x - 0x%xn", elts.start, buf->used );
  1070. return -EINVAL;
  1071. }
  1072. buf->used = elts.end;
  1073. buf_priv->prim = elts.prim;
  1074. buf_priv->discard = elts.discard;
  1075. radeon_cp_dispatch_indices( dev, buf, elts.start, elts.end, count );
  1076. return 0;
  1077. }
  1078. int radeon_cp_texture( struct inode *inode, struct file *filp,
  1079.        unsigned int cmd, unsigned long arg )
  1080. {
  1081. drm_file_t *priv = filp->private_data;
  1082. drm_device_t *dev = priv->dev;
  1083. drm_radeon_private_t *dev_priv = dev->dev_private;
  1084. drm_radeon_texture_t tex;
  1085. drm_radeon_tex_image_t image;
  1086. LOCK_TEST_WITH_RETURN( dev );
  1087. if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) )
  1088. return -EFAULT;
  1089. if ( tex.image == NULL ) {
  1090. DRM_ERROR( "null texture image!n" );
  1091. return -EINVAL;
  1092. }
  1093. if ( copy_from_user( &image,
  1094.      (drm_radeon_tex_image_t *)tex.image,
  1095.      sizeof(image) ) )
  1096. return -EFAULT;
  1097. RING_SPACE_TEST_WITH_RETURN( dev_priv );
  1098. VB_AGE_TEST_WITH_RETURN( dev_priv );
  1099. return radeon_cp_dispatch_texture( dev, &tex, &image );
  1100. }
  1101. int radeon_cp_stipple( struct inode *inode, struct file *filp,
  1102.        unsigned int cmd, unsigned long arg )
  1103. {
  1104. drm_file_t *priv = filp->private_data;
  1105. drm_device_t *dev = priv->dev;
  1106. drm_radeon_private_t *dev_priv = dev->dev_private;
  1107. drm_radeon_stipple_t stipple;
  1108. u32 mask[32];
  1109. LOCK_TEST_WITH_RETURN( dev );
  1110. if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg,
  1111.      sizeof(stipple) ) )
  1112. return -EFAULT;
  1113. if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) )
  1114. return -EFAULT;
  1115. RING_SPACE_TEST_WITH_RETURN( dev_priv );
  1116. radeon_cp_dispatch_stipple( dev, mask );
  1117. return 0;
  1118. }
  1119. int radeon_cp_indirect( struct inode *inode, struct file *filp,
  1120. unsigned int cmd, unsigned long arg )
  1121. {
  1122. drm_file_t *priv = filp->private_data;
  1123. drm_device_t *dev = priv->dev;
  1124. drm_radeon_private_t *dev_priv = dev->dev_private;
  1125. drm_device_dma_t *dma = dev->dma;
  1126. drm_buf_t *buf;
  1127. drm_radeon_buf_priv_t *buf_priv;
  1128. drm_radeon_indirect_t indirect;
  1129. RING_LOCALS;
  1130. LOCK_TEST_WITH_RETURN( dev );
  1131. if ( !dev_priv ) {
  1132. DRM_ERROR( "%s called with no initializationn", __FUNCTION__ );
  1133. return -EINVAL;
  1134. }
  1135. if ( copy_from_user( &indirect, (drm_radeon_indirect_t *)arg,
  1136.      sizeof(indirect) ) )
  1137. return -EFAULT;
  1138. DRM_DEBUG( "indirect: idx=%d s=%d e=%d d=%dn",
  1139.    indirect.idx, indirect.start,
  1140.    indirect.end, indirect.discard );
  1141. if ( indirect.idx < 0 || indirect.idx >= dma->buf_count ) {
  1142. DRM_ERROR( "buffer index %d (of %d max)n",
  1143.    indirect.idx, dma->buf_count - 1 );
  1144. return -EINVAL;
  1145. }
  1146. buf = dma->buflist[indirect.idx];
  1147. buf_priv = buf->dev_private;
  1148. if ( buf->pid != current->pid ) {
  1149. DRM_ERROR( "process %d using buffer owned by %dn",
  1150.    current->pid, buf->pid );
  1151. return -EINVAL;
  1152. }
  1153. if ( buf->pending ) {
  1154. DRM_ERROR( "sending pending buffer %dn", indirect.idx );
  1155. return -EINVAL;
  1156. }
  1157. if ( indirect.start < buf->used ) {
  1158. DRM_ERROR( "reusing indirect: start=0x%x actual=0x%xn",
  1159.    indirect.start, buf->used );
  1160. return -EINVAL;
  1161. }
  1162. RING_SPACE_TEST_WITH_RETURN( dev_priv );
  1163. VB_AGE_TEST_WITH_RETURN( dev_priv );
  1164. buf->used = indirect.end;
  1165. buf_priv->discard = indirect.discard;
  1166. /* Wait for the 3D stream to idle before the indirect buffer
  1167.  * containing 2D acceleration commands is processed.
  1168.  */
  1169. BEGIN_RING( 2 );
  1170. RADEON_WAIT_UNTIL_3D_IDLE();
  1171. ADVANCE_RING();
  1172. /* Dispatch the indirect buffer full of commands from the
  1173.  * X server.  This is insecure and is thus only available to
  1174.  * privileged clients.
  1175.  */
  1176. radeon_cp_dispatch_indirect( dev, buf, indirect.start, indirect.end );
  1177. return 0;
  1178. }