blit WIP
[mesa.git] / src / mesa / drivers / dri / r300 / r300_blit.c
1 /*
2 * Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com>
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28 #include "radeon_common.h"
29 #include "r300_context.h"
30
31 #include "r300_blit.h"
32 #include "r300_cmdbuf.h"
33 #include "r300_emit.h"
34 #include "r300_tex.h"
35 #include "compiler/radeon_compiler.h"
36 #include "compiler/radeon_opcodes.h"
37
38 /**
39 * TODO:
40 * - handle depth buffer
41 * - r300 fp and rs setup
42 */
43
44 static void vp_ins_outs(struct r300_vertex_program_compiler *c)
45 {
46 c->code->inputs[VERT_ATTRIB_POS] = 0;
47 c->code->inputs[VERT_ATTRIB_TEX0] = 1;
48 c->code->outputs[VERT_RESULT_HPOS] = 0;
49 c->code->outputs[VERT_RESULT_TEX0] = 1;
50 }
51
52 static void fp_allocate_hw_inputs(
53 struct r300_fragment_program_compiler * c,
54 void (*allocate)(void * data, unsigned input, unsigned hwreg),
55 void * mydata)
56 {
57 allocate(mydata, FRAG_ATTRIB_TEX0, 0);
58 }
59
60 static void create_vertex_program(struct r300_context *r300)
61 {
62 struct r300_vertex_program_compiler compiler;
63 struct rc_instruction *inst;
64
65 rc_init(&compiler.Base);
66
67 inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
68 inst->U.I.Opcode = RC_OPCODE_MOV;
69 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
70 inst->U.I.DstReg.Index = VERT_RESULT_HPOS;
71 inst->U.I.DstReg.RelAddr = 0;
72 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
73 inst->U.I.SrcReg[0].Abs = 0;
74 inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
75 inst->U.I.SrcReg[0].Index = VERT_ATTRIB_POS;
76 inst->U.I.SrcReg[0].Negate = 0;
77 inst->U.I.SrcReg[0].RelAddr = 0;
78 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
79
80 inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
81 inst->U.I.Opcode = RC_OPCODE_MOV;
82 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
83 inst->U.I.DstReg.Index = VERT_RESULT_TEX0;
84 inst->U.I.DstReg.RelAddr = 0;
85 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
86 inst->U.I.SrcReg[0].Abs = 0;
87 inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
88 inst->U.I.SrcReg[0].Index = VERT_ATTRIB_TEX0;
89 inst->U.I.SrcReg[0].Negate = 0;
90 inst->U.I.SrcReg[0].RelAddr = 0;
91 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
92
93 compiler.Base.Program.InputsRead = (1 << VERT_ATTRIB_POS) | (1 << VERT_ATTRIB_TEX0);
94 compiler.RequiredOutputs = compiler.Base.Program.OutputsWritten = (1 << VERT_RESULT_HPOS) | (1 << VERT_RESULT_TEX0);
95 compiler.SetHwInputOutput = vp_ins_outs;
96 compiler.code = &r300->blit.vp_code;
97
98 r3xx_compile_vertex_program(&compiler);
99 }
100
101 static void create_fragment_program(struct r300_context *r300)
102 {
103 struct r300_fragment_program_compiler compiler;
104 struct rc_instruction *inst;
105
106 rc_init(&compiler.Base);
107
108 inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
109 inst->U.I.Opcode = RC_OPCODE_TEX;
110 inst->U.I.TexSrcTarget = RC_TEXTURE_2D;
111 inst->U.I.TexSrcUnit = 0;
112 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
113 inst->U.I.DstReg.Index = FRAG_RESULT_COLOR;
114 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
115 inst->U.I.SrcReg[0].Abs = 0;
116 inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
117 inst->U.I.SrcReg[0].Index = FRAG_ATTRIB_TEX0;
118 inst->U.I.SrcReg[0].Negate = 0;
119 inst->U.I.SrcReg[0].RelAddr = 0;
120 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
121
122 compiler.Base.Program.InputsRead = (1 << FRAG_ATTRIB_TEX0);
123 compiler.OutputColor = FRAG_RESULT_COLOR;
124 compiler.OutputDepth = FRAG_RESULT_DEPTH;
125 compiler.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515);
126 compiler.code = &r300->blit.fp_code;
127 compiler.AllocateHwInputs = fp_allocate_hw_inputs;
128
129 r3xx_compile_fragment_program(&compiler);
130 }
131
132 void r300_blit_init(struct r300_context *r300)
133 {
134 create_vertex_program(r300);
135 create_fragment_program(r300);
136 }
137
138 static void r500_emit_rs_setup(struct r300_context *r300)
139 {
140 BATCH_LOCALS(&r300->radeon);
141
142 BEGIN_BATCH(7);
143 OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
144 OUT_BATCH((4 << R300_IT_COUNT_SHIFT) | R300_HIRES_EN);
145 OUT_BATCH(0);
146 OUT_BATCH_REGVAL(R500_RS_INST_0,
147 (0 << R500_RS_INST_TEX_ID_SHIFT) |
148 (0 << R500_RS_INST_TEX_ADDR_SHIFT) |
149 R500_RS_INST_TEX_CN_WRITE |
150 R500_RS_INST_COL_CN_NO_WRITE);
151 OUT_BATCH_REGVAL(R500_RS_IP_0,
152 (0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
153 (1 << R500_RS_IP_TEX_PTR_T_SHIFT) |
154 (2 << R500_RS_IP_TEX_PTR_R_SHIFT) |
155 (3 << R500_RS_IP_TEX_PTR_Q_SHIFT));
156 END_BATCH();
157 }
158
159 static void r300_emit_fp_setup(struct r300_context *r300)
160 {
161 assert(0);
162 }
163
164 static void r300_emit_rs_setup(struct r300_context *r300)
165 {
166 assert(0);
167 }
168
169 static void r300_emit_tx_setup(struct r300_context *r300,
170 gl_format mesa_format,
171 struct radeon_bo *bo,
172 intptr_t offset,
173 unsigned width,
174 unsigned height,
175 unsigned pitch)
176 {
177 BATCH_LOCALS(&r300->radeon);
178
179 assert(width <= 2048);
180 assert(height <= 2048);
181 assert(r300TranslateTexFormat(mesa_format) != 0);
182 assert(offset % 32 == 0);
183
184 BEGIN_BATCH(17);
185 OUT_BATCH_REGVAL(R300_TX_FILTER0_0,
186 (R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_S_SHIFT) |
187 (R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_T_SHIFT) |
188 (R300_TX_CLAMP_TO_EDGE << R300_TX_WRAP_R_SHIFT) |
189 R300_TX_MIN_FILTER_MIP_NONE |
190 R300_TX_MIN_FILTER_LINEAR |
191 R300_TX_MAG_FILTER_LINEAR |
192 (0 << 28));
193 OUT_BATCH_REGVAL(R300_TX_FILTER1_0, 0);
194 OUT_BATCH_REGVAL(R300_TX_SIZE_0,
195 ((width-1) << R300_TX_WIDTHMASK_SHIFT) |
196 ((height-1) << R300_TX_HEIGHTMASK_SHIFT) |
197 (0 << R300_TX_DEPTHMASK_SHIFT) |
198 (0 << R300_TX_MAX_MIP_LEVEL_SHIFT) |
199 R300_TX_SIZE_TXPITCH_EN);
200
201 OUT_BATCH_REGVAL(R300_TX_FORMAT_0, r300TranslateTexFormat(mesa_format));
202 OUT_BATCH_REGVAL(R300_TX_FORMAT2_0, pitch/_mesa_get_format_bytes(mesa_format) - 1);
203 OUT_BATCH_REGSEQ(R300_TX_OFFSET_0, 1);
204 OUT_BATCH_RELOC(0, bo, offset, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
205
206 OUT_BATCH_REGSEQ(R300_TX_INVALTAGS, 2);
207 OUT_BATCH(0);
208 OUT_BATCH(1);
209
210 END_BATCH();
211 }
212
213 #define EASY_US_FORMAT(FMT, C0, C1, C2, C3, SIGN) \
214 (FMT | R500_C0_SEL_##C0 | R500_C1_SEL_##C1 | \
215 R500_C2_SEL_##C2 | R500_C3_SEL_##C3 | R500_OUT_SIGN(SIGN))
216
217 static uint32_t mesa_format_to_us_format(gl_format mesa_format)
218 {
219 switch(mesa_format)
220 {
221 case MESA_FORMAT_RGBA8888: // x
222 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, B, G, R, 0);
223 case MESA_FORMAT_RGB565: // x
224 case MESA_FORMAT_ARGB1555: // x
225 case MESA_FORMAT_RGBA8888_REV: // x
226 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, R, G, B, A, 0);
227 case MESA_FORMAT_ARGB8888: // x
228 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, B, G, R, A, 0);
229 case MESA_FORMAT_ARGB8888_REV:
230 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, R, G, B, 0);
231 case MESA_FORMAT_XRGB8888:
232 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, R, G, B, 0);
233
234 case MESA_FORMAT_RGB332:
235 return EASY_US_FORMAT(R500_OUT_FMT_C_3_3_2, A, R, G, B, 0);
236
237 case MESA_FORMAT_RGBA_FLOAT32:
238 return EASY_US_FORMAT(R500_OUT_FMT_C4_32_FP, R, G, B, A, 0);
239 case MESA_FORMAT_RGBA_FLOAT16:
240 return EASY_US_FORMAT(R500_OUT_FMT_C4_16_FP, R, G, B, A, 0);
241 case MESA_FORMAT_ALPHA_FLOAT32:
242 return EASY_US_FORMAT(R500_OUT_FMT_C_32_FP, A, A, A, A, 0);
243 case MESA_FORMAT_ALPHA_FLOAT16:
244 return EASY_US_FORMAT(R500_OUT_FMT_C_16_FP, A, A, A, A, 0);
245
246 case MESA_FORMAT_SIGNED_RGBA8888:
247 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, R, G, B, A, 0xf);
248 case MESA_FORMAT_SIGNED_RGBA8888_REV:
249 return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, B, G, R, 0xf);
250 case MESA_FORMAT_SIGNED_RGBA_16:
251 return EASY_US_FORMAT(R500_OUT_FMT_C4_16, R, G, B, A, 0xf);
252
253 default:
254 assert(!"Invalid format for US output\n");
255 return 0;
256 }
257 }
258 #undef EASY_US_FORMAT
259
260 static void r500_emit_fp_setup(struct r300_context *r300,
261 struct r500_fragment_program_code *fp,
262 gl_format dst_format)
263 {
264 r500_emit_fp(r300, (uint32_t *)fp->inst, (fp->inst_end + 1) * 6, 0, 0, 0);
265 BATCH_LOCALS(&r300->radeon);
266
267 BEGIN_BATCH(10);
268 OUT_BATCH_REGSEQ(R500_US_CODE_ADDR, 3);
269 OUT_BATCH(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(fp->inst_end));
270 OUT_BATCH(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(fp->inst_end));
271 OUT_BATCH(0);
272 OUT_BATCH_REGVAL(R500_US_CONFIG, 0);
273 OUT_BATCH_REGVAL(R500_US_OUT_FMT_0, mesa_format_to_us_format(dst_format));
274 OUT_BATCH_REGVAL(R500_US_PIXSIZE, fp->max_temp_idx);
275 END_BATCH();
276 }
277
278 static void emit_pvs_setup(struct r300_context *r300,
279 uint32_t *vp_code,
280 unsigned vp_len)
281 {
282 BATCH_LOCALS(&r300->radeon);
283
284 r300_emit_vpu(r300, vp_code, vp_len * 4, R300_PVS_CODE_START);
285
286 BEGIN_BATCH(4);
287 OUT_BATCH_REGSEQ(R300_VAP_PVS_CODE_CNTL_0, 3);
288 OUT_BATCH((0 << R300_PVS_FIRST_INST_SHIFT) |
289 ((vp_len - 1) << R300_PVS_XYZW_VALID_INST_SHIFT) |
290 ((vp_len - 1)<< R300_PVS_LAST_INST_SHIFT));
291 OUT_BATCH(0);
292 OUT_BATCH((vp_len - 1) << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
293 END_BATCH();
294 }
295
296 static void emit_vap_setup(struct r300_context *r300, unsigned width, unsigned height)
297 {
298 BATCH_LOCALS(&r300->radeon);
299
300 BEGIN_BATCH(12);
301 OUT_BATCH_REGSEQ(R300_SE_VTE_CNTL, 2);
302 OUT_BATCH(R300_VTX_XY_FMT | R300_VTX_Z_FMT);
303 OUT_BATCH(4);
304
305 OUT_BATCH_REGVAL(R300_VAP_PSC_SGN_NORM_CNTL, 0xaaaaaaaa);
306 OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_0,
307 ((R300_DATA_TYPE_FLOAT_2 | (0 << R300_DST_VEC_LOC_SHIFT)) << 0) |
308 (((1 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_2 | R300_LAST_VEC) << 16));
309 OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_EXT_0,
310 ((((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
311 (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
312 (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) |
313 (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) |
314 (0xf << R300_WRITE_ENA_SHIFT) ) << 0) |
315 (((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
316 (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
317 (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) |
318 (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) |
319 (0xf << R300_WRITE_ENA_SHIFT) ) << 16) ) );
320 OUT_BATCH_REGSEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
321 OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT);
322 OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_1__4_COMPONENTS);
323 END_BATCH();
324 }
325
326 static GLboolean validate_buffers(struct r300_context *r300,
327 struct radeon_bo *src_bo,
328 struct radeon_bo *dst_bo)
329 {
330 int ret;
331 radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
332 src_bo, RADEON_GEM_DOMAIN_VRAM, 0);
333
334 radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
335 dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
336
337 ret = radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs,
338 first_elem(&r300->radeon.dma.reserved)->bo,
339 RADEON_GEM_DOMAIN_GTT, 0);
340 if (ret)
341 return GL_FALSE;
342
343 return GL_TRUE;
344 }
345
346 static void emit_draw_packet(struct r300_context *r300, float width, float height)
347 {
348 float verts[] = { 0.0, 0.0, 0.0, 1.0,
349 0.0, height, 0.0, 0.0,
350 width, height, 1.0, 0.0,
351 width, 0.0, 1.0, 1.0 };
352
353 BATCH_LOCALS(&r300->radeon);
354
355 BEGIN_BATCH(19);
356 OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_IMMD_2, 16);
357 OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED |
358 (4 << 16) | R300_VAP_VF_CNTL__PRIM_QUADS);
359 OUT_BATCH_TABLE(verts, 16);
360 END_BATCH();
361 }
362
363 static void other_stuff(struct r300_context *r300)
364 {
365 BATCH_LOCALS(&r300->radeon);
366
367 BEGIN_BATCH(15);
368 OUT_BATCH_REGVAL(R300_GA_POLY_MODE,
369 R300_GA_POLY_MODE_FRONT_PTYPE_TRI | R300_GA_POLY_MODE_BACK_PTYPE_TRI);
370 OUT_BATCH_REGVAL(R300_SU_CULL_MODE, R300_FRONT_FACE_CCW);
371 OUT_BATCH_REGVAL(R300_FG_FOG_BLEND, 0);
372 OUT_BATCH_REGVAL(R300_FG_ALPHA_FUNC, 0);
373 OUT_BATCH_REGSEQ(R300_RB3D_CBLEND, 2);
374 OUT_BATCH(0x0);
375 OUT_BATCH(0x0);
376 OUT_BATCH_REGVAL(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
377 OUT_BATCH_REGVAL(R300_ZB_CNTL, 0);
378 END_BATCH();
379 }
380
381 static void emit_cb_setup(struct r300_context *r300,
382 struct radeon_bo *bo,
383 intptr_t offset,
384 gl_format mesa_format,
385 unsigned width,
386 unsigned height)
387 {
388 BATCH_LOCALS(&r300->radeon);
389
390 unsigned x1, y1, x2, y2;
391 x1 = 0;
392 y1 = 0;
393 x2 = width - 1;
394 y2 = height - 1;
395
396 if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
397 x1 += R300_SCISSORS_OFFSET;
398 y1 += R300_SCISSORS_OFFSET;
399 x2 += R300_SCISSORS_OFFSET;
400 y2 += R300_SCISSORS_OFFSET;
401 }
402
403 r300_emit_cb_setup(r300, bo, offset, mesa_format,
404 _mesa_get_format_bytes(mesa_format),
405 _mesa_format_row_stride(mesa_format, width));
406
407 BEGIN_BATCH_NO_AUTOSTATE(3);
408 OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
409 OUT_BATCH((x1 << R300_SCISSORS_X_SHIFT)|(y1 << R300_SCISSORS_Y_SHIFT));
410 OUT_BATCH((x2 << R300_SCISSORS_X_SHIFT)|(y2 << R300_SCISSORS_Y_SHIFT));
411 END_BATCH();
412 }
413
414 GLboolean r300_blit(struct r300_context *r300,
415 struct radeon_bo *src_bo,
416 intptr_t src_offset,
417 gl_format src_mesaformat,
418 unsigned src_pitch,
419 unsigned src_width,
420 unsigned src_height,
421 struct radeon_bo *dst_bo,
422 intptr_t dst_offset,
423 gl_format dst_mesaformat,
424 unsigned dst_width,
425 unsigned dst_height)
426 {
427 //assert(src_width == dst_width);
428 //assert(src_height == dst_height);
429
430 if (src_bo == dst_bo) {
431 return GL_FALSE;
432 }
433
434 //return GL_FALSE;
435
436 if (1) {
437 fprintf(stderr, "src: width %d, height %d, pitch %d vs %d, format %s\n",
438 src_width, src_height, src_pitch,
439 _mesa_format_row_stride(src_mesaformat, src_width),
440 _mesa_get_format_name(src_mesaformat));
441 fprintf(stderr, "dst: width %d, height %d, pitch %d, format %s\n",
442 dst_width, dst_height,
443 _mesa_format_row_stride(dst_mesaformat, dst_width),
444 _mesa_get_format_name(dst_mesaformat));
445 }
446
447 if (!validate_buffers(r300, src_bo, dst_bo))
448 return GL_FALSE;
449
450 rcommonEnsureCmdBufSpace(&r300->radeon, 200, __FUNCTION__);
451
452 other_stuff(r300);
453
454 r300_emit_tx_setup(r300, src_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch);
455
456 if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
457 r500_emit_fp_setup(r300, &r300->blit.fp_code.code.r500, dst_mesaformat);
458 r500_emit_rs_setup(r300);
459 } else {
460 r300_emit_fp_setup(r300);
461 r300_emit_rs_setup(r300);
462 }
463
464 emit_pvs_setup(r300, r300->blit.vp_code.body.d, 2);
465 emit_vap_setup(r300, dst_width, dst_height);
466
467 emit_cb_setup(r300, dst_bo, dst_offset, dst_mesaformat, dst_width, dst_height);
468
469 emit_draw_packet(r300, dst_width, dst_height);
470
471 r300EmitCacheFlush(r300);
472
473 radeonFlush(r300->radeon.glCtx);
474 //r300ResetHwState(r300);
475
476 return GL_TRUE;
477 }