00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00041 #include "draw/draw_context.h"
00042 #include "draw/draw_vbuf.h"
00043 #include "pipe/p_debug.h"
00044 #include "pipe/p_inlines.h"
00045 #include "pipe/p_winsys.h"
00046 #include "util/u_math.h"
00047 #include "util/u_memory.h"
00048
00049 #include "i915_context.h"
00050 #include "i915_reg.h"
00051 #include "i915_winsys.h"
00052 #include "i915_batch.h"
00053 #include "i915_state.h"
00054
00055
00059 struct i915_vbuf_render {
00060 struct vbuf_render base;
00061
00062 struct i915_context *i915;
00063
00065 unsigned vertex_size;
00066
00068 unsigned prim;
00069
00071 unsigned hwprim;
00072
00074 unsigned fallback;
00075
00076
00077 struct pipe_buffer *vbo;
00078 size_t vbo_size;
00079 size_t vbo_offset;
00080 void *vbo_ptr;
00081 size_t vbo_alloc_size;
00082 };
00083
00084
00088 static INLINE struct i915_vbuf_render *
00089 i915_vbuf_render( struct vbuf_render *render )
00090 {
00091 assert(render);
00092 return (struct i915_vbuf_render *)render;
00093 }
00094
00095
00096 static const struct vertex_info *
00097 i915_vbuf_render_get_vertex_info( struct vbuf_render *render )
00098 {
00099 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00100 struct i915_context *i915 = i915_render->i915;
00101
00102 if (i915->dirty) {
00103
00104 i915_update_derived( i915 );
00105 }
00106
00107 return &i915->current.vertex_info;
00108 }
00109
00110
00111 static void *
00112 i915_vbuf_render_allocate_vertices( struct vbuf_render *render,
00113 ushort vertex_size,
00114 ushort nr_vertices )
00115 {
00116 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00117 struct i915_context *i915 = i915_render->i915;
00118 struct pipe_screen *screen = i915->pipe.screen;
00119 size_t size = (size_t)vertex_size * (size_t)nr_vertices;
00120
00121
00122 assert(!i915->vbo);
00123
00124 if (i915_render->vbo_size > size + i915_render->vbo_offset && !i915->vbo_flushed) {
00125 } else {
00126 i915->vbo_flushed = 0;
00127 pipe_buffer_reference(screen, &i915_render->vbo, NULL);
00128 }
00129
00130 if (!i915_render->vbo) {
00131 i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size);
00132 i915_render->vbo_offset = 0;
00133 i915_render->vbo = pipe_buffer_create(screen,
00134 64,
00135 I915_BUFFER_USAGE_LIT_VERTEX,
00136 i915_render->vbo_size);
00137 i915_render->vbo_ptr = pipe_buffer_map(screen,
00138 i915_render->vbo,
00139 PIPE_BUFFER_USAGE_CPU_WRITE);
00140 pipe_buffer_unmap(screen, i915_render->vbo);
00141 }
00142
00143 i915->vbo = i915_render->vbo;
00144 i915->vbo_offset = i915_render->vbo_offset;
00145 i915->dirty |= I915_NEW_VBO;
00146
00147 return (unsigned char *)i915_render->vbo_ptr + i915->vbo_offset;
00148 }
00149
00150
00151 static boolean
00152 i915_vbuf_render_set_primitive( struct vbuf_render *render,
00153 unsigned prim )
00154 {
00155 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00156 i915_render->prim = prim;
00157
00158 switch(prim) {
00159 case PIPE_PRIM_POINTS:
00160 i915_render->hwprim = PRIM3D_POINTLIST;
00161 i915_render->fallback = 0;
00162 return TRUE;
00163 case PIPE_PRIM_LINES:
00164 i915_render->hwprim = PRIM3D_LINELIST;
00165 i915_render->fallback = 0;
00166 return TRUE;
00167 case PIPE_PRIM_LINE_LOOP:
00168 i915_render->hwprim = PRIM3D_LINELIST;
00169 i915_render->fallback = PIPE_PRIM_LINE_LOOP;
00170 return TRUE;
00171 case PIPE_PRIM_LINE_STRIP:
00172 i915_render->hwprim = PRIM3D_LINESTRIP;
00173 i915_render->fallback = 0;
00174 return TRUE;
00175 case PIPE_PRIM_TRIANGLES:
00176 i915_render->hwprim = PRIM3D_TRILIST;
00177 i915_render->fallback = 0;
00178 return TRUE;
00179 case PIPE_PRIM_TRIANGLE_STRIP:
00180 i915_render->hwprim = PRIM3D_TRISTRIP;
00181 i915_render->fallback = 0;
00182 return TRUE;
00183 case PIPE_PRIM_TRIANGLE_FAN:
00184 i915_render->hwprim = PRIM3D_TRIFAN;
00185 i915_render->fallback = 0;
00186 return TRUE;
00187 case PIPE_PRIM_QUADS:
00188 i915_render->hwprim = PRIM3D_TRILIST;
00189 i915_render->fallback = PIPE_PRIM_QUADS;
00190 return TRUE;
00191 case PIPE_PRIM_QUAD_STRIP:
00192 i915_render->hwprim = PRIM3D_TRILIST;
00193 i915_render->fallback = PIPE_PRIM_QUAD_STRIP;
00194 return TRUE;
00195 case PIPE_PRIM_POLYGON:
00196 i915_render->hwprim = PRIM3D_POLY;
00197 i915_render->fallback = 0;
00198 return TRUE;
00199 default:
00200 assert((int)"Error unkown primtive type" & 0);
00201
00202
00203 return FALSE;
00204 }
00205 }
00206
00207
00208
00212 static void
00213 draw_arrays_generate_indices( struct vbuf_render *render,
00214 unsigned start, uint nr,
00215 unsigned type )
00216 {
00217 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00218 struct i915_context *i915 = i915_render->i915;
00219 unsigned i;
00220 unsigned end = start + nr;
00221 switch(type) {
00222 case 0:
00223 for (i = start; i+1 < end; i += 2)
00224 OUT_BATCH( (i+0) | (i+1) << 16 );
00225 if (i < end)
00226 OUT_BATCH( i );
00227 break;
00228 case PIPE_PRIM_LINE_LOOP:
00229 if (nr >= 2) {
00230 for (i = start + 1; i < end; i++)
00231 OUT_BATCH( (i-0) | (i+0) << 16 );
00232 OUT_BATCH( (i-0) | ( start) << 16 );
00233 }
00234 break;
00235 case PIPE_PRIM_QUADS:
00236 for (i = start; i + 3 < end; i += 4) {
00237 OUT_BATCH( (i+0) | (i+1) << 16 );
00238 OUT_BATCH( (i+3) | (i+1) << 16 );
00239 OUT_BATCH( (i+2) | (i+3) << 16 );
00240 }
00241 break;
00242 case PIPE_PRIM_QUAD_STRIP:
00243 for (i = start; i + 3 < end; i += 2) {
00244 OUT_BATCH( (i+0) | (i+1) << 16 );
00245 OUT_BATCH( (i+3) | (i+2) << 16 );
00246 OUT_BATCH( (i+0) | (i+3) << 16 );
00247 }
00248 break;
00249 default:
00250 assert(0);
00251 }
00252 }
00253
00254 static unsigned
00255 draw_arrays_calc_nr_indices( uint nr, unsigned type )
00256 {
00257 switch (type) {
00258 case 0:
00259 return nr;
00260 case PIPE_PRIM_LINE_LOOP:
00261 if (nr >= 2)
00262 return nr * 2;
00263 else
00264 return 0;
00265 case PIPE_PRIM_QUADS:
00266 return (nr / 4) * 6;
00267 case PIPE_PRIM_QUAD_STRIP:
00268 return ((nr - 2) / 2) * 6;
00269 default:
00270 assert(0);
00271 return 0;
00272 }
00273 }
00274
00275 static void
00276 draw_arrays_fallback( struct vbuf_render *render,
00277 unsigned start,
00278 uint nr )
00279 {
00280 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00281 struct i915_context *i915 = i915_render->i915;
00282 unsigned nr_indices;
00283
00284 if (i915->dirty)
00285 i915_update_derived( i915 );
00286
00287 if (i915->hardware_dirty)
00288 i915_emit_hardware_state( i915 );
00289
00290 nr_indices = draw_arrays_calc_nr_indices( nr, i915_render->fallback );
00291 if (!nr_indices)
00292 return;
00293
00294 if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
00295 FLUSH_BATCH(NULL);
00296
00297
00298
00299 i915_update_derived( i915 );
00300 i915_emit_hardware_state( i915 );
00301 i915->vbo_flushed = 1;
00302
00303 if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
00304 assert(0);
00305 goto out;
00306 }
00307 }
00308 OUT_BATCH( _3DPRIMITIVE |
00309 PRIM_INDIRECT |
00310 i915_render->hwprim |
00311 PRIM_INDIRECT_ELTS |
00312 nr_indices );
00313
00314 draw_arrays_generate_indices( render, start, nr, i915_render->fallback );
00315
00316 out:
00317 return;
00318 }
00319
00320 static void
00321 i915_vbuf_render_draw_arrays( struct vbuf_render *render,
00322 unsigned start,
00323 uint nr )
00324 {
00325 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00326
00327 if (i915_render->fallback) {
00328 draw_arrays_fallback( render, start, nr );
00329 return;
00330 }
00331
00332
00333 draw_arrays_fallback( render, start, nr );
00334 }
00335
00340 static void
00341 draw_generate_indices( struct vbuf_render *render,
00342 const ushort *indices,
00343 uint nr_indices,
00344 unsigned type )
00345 {
00346 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00347 struct i915_context *i915 = i915_render->i915;
00348 unsigned i;
00349
00350 switch(type) {
00351 case 0:
00352 for (i = 0; i + 1 < nr_indices; i += 2) {
00353 OUT_BATCH( indices[i] | indices[i+1] << 16 );
00354 }
00355 if (i < nr_indices) {
00356 OUT_BATCH( indices[i] );
00357 }
00358 break;
00359 case PIPE_PRIM_LINE_LOOP:
00360 if (nr_indices >= 2) {
00361 for (i = 1; i < nr_indices; i++)
00362 OUT_BATCH( indices[i-1] | indices[i] << 16 );
00363 OUT_BATCH( indices[i-1] | indices[0] << 16 );
00364 }
00365 break;
00366 case PIPE_PRIM_QUADS:
00367 for (i = 0; i + 3 < nr_indices; i += 4) {
00368 OUT_BATCH( indices[i+0] | indices[i+1] << 16 );
00369 OUT_BATCH( indices[i+3] | indices[i+1] << 16 );
00370 OUT_BATCH( indices[i+2] | indices[i+3] << 16 );
00371 }
00372 break;
00373 case PIPE_PRIM_QUAD_STRIP:
00374 for (i = 0; i + 3 < nr_indices; i += 2) {
00375 OUT_BATCH( indices[i+0] | indices[i+1] << 16 );
00376 OUT_BATCH( indices[i+3] | indices[i+2] << 16 );
00377 OUT_BATCH( indices[i+0] | indices[i+3] << 16 );
00378 }
00379 break;
00380 default:
00381 assert(0);
00382 break;
00383 }
00384 }
00385
00386 static unsigned
00387 draw_calc_nr_indices( uint nr_indices, unsigned type )
00388 {
00389 switch (type) {
00390 case 0:
00391 return nr_indices;
00392 case PIPE_PRIM_LINE_LOOP:
00393 if (nr_indices >= 2)
00394 return nr_indices * 2;
00395 else
00396 return 0;
00397 case PIPE_PRIM_QUADS:
00398 return (nr_indices / 4) * 6;
00399 case PIPE_PRIM_QUAD_STRIP:
00400 return ((nr_indices - 2) / 2) * 6;
00401 default:
00402 assert(0);
00403 return 0;
00404 }
00405 }
00406
00407 static void
00408 i915_vbuf_render_draw( struct vbuf_render *render,
00409 const ushort *indices,
00410 uint nr_indices)
00411 {
00412 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00413 struct i915_context *i915 = i915_render->i915;
00414 unsigned save_nr_indices;
00415
00416 save_nr_indices = nr_indices;
00417
00418 nr_indices = draw_calc_nr_indices( nr_indices, i915_render->fallback );
00419 if (!nr_indices)
00420 return;
00421
00422 if (i915->dirty)
00423 i915_update_derived( i915 );
00424
00425 if (i915->hardware_dirty)
00426 i915_emit_hardware_state( i915 );
00427
00428 if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
00429 FLUSH_BATCH(NULL);
00430
00431
00432
00433 i915_update_derived( i915 );
00434 i915_emit_hardware_state( i915 );
00435 i915->vbo_flushed = 1;
00436
00437 if (!BEGIN_BATCH( 1 + (nr_indices + 1)/2, 1 )) {
00438 assert(0);
00439 goto out;
00440 }
00441 }
00442
00443 OUT_BATCH( _3DPRIMITIVE |
00444 PRIM_INDIRECT |
00445 i915_render->hwprim |
00446 PRIM_INDIRECT_ELTS |
00447 nr_indices );
00448 draw_generate_indices( render,
00449 indices,
00450 save_nr_indices,
00451 i915_render->fallback );
00452
00453 out:
00454 return;
00455 }
00456
00457
00458 static void
00459 i915_vbuf_render_release_vertices( struct vbuf_render *render,
00460 void *vertices,
00461 unsigned vertex_size,
00462 unsigned vertices_used )
00463 {
00464 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00465 struct i915_context *i915 = i915_render->i915;
00466 size_t size = (size_t)vertex_size * (size_t)vertices_used;
00467
00468 assert(i915->vbo);
00469
00470 i915_render->vbo_offset += size;
00471 i915->vbo = NULL;
00472 i915->dirty |= I915_NEW_VBO;
00473 }
00474
00475
00476 static void
00477 i915_vbuf_render_destroy( struct vbuf_render *render )
00478 {
00479 struct i915_vbuf_render *i915_render = i915_vbuf_render(render);
00480 FREE(i915_render);
00481 }
00482
00483
00487 static struct vbuf_render *
00488 i915_vbuf_render_create( struct i915_context *i915 )
00489 {
00490 struct i915_vbuf_render *i915_render = CALLOC_STRUCT(i915_vbuf_render);
00491 struct pipe_screen *screen = i915->pipe.screen;
00492
00493 i915_render->i915 = i915;
00494
00495 i915_render->base.max_vertex_buffer_bytes = 128*1024;
00496
00497
00498
00499
00500 i915_render->base.max_indices = 16*1024;
00501
00502 i915_render->base.get_vertex_info = i915_vbuf_render_get_vertex_info;
00503 i915_render->base.allocate_vertices = i915_vbuf_render_allocate_vertices;
00504 i915_render->base.set_primitive = i915_vbuf_render_set_primitive;
00505 i915_render->base.draw = i915_vbuf_render_draw;
00506 i915_render->base.draw_arrays = i915_vbuf_render_draw_arrays;
00507 i915_render->base.release_vertices = i915_vbuf_render_release_vertices;
00508 i915_render->base.destroy = i915_vbuf_render_destroy;
00509
00510 i915_render->vbo_alloc_size = 128 * 4096;
00511 i915_render->vbo_size = i915_render->vbo_alloc_size;
00512 i915_render->vbo_offset = 0;
00513 i915_render->vbo = pipe_buffer_create(screen,
00514 64,
00515 I915_BUFFER_USAGE_LIT_VERTEX,
00516 i915_render->vbo_size);
00517 i915_render->vbo_ptr = pipe_buffer_map(screen,
00518 i915_render->vbo,
00519 PIPE_BUFFER_USAGE_CPU_WRITE);
00520 pipe_buffer_unmap(screen, i915_render->vbo);
00521
00522 return &i915_render->base;
00523 }
00524
00525
00529 struct draw_stage *i915_draw_vbuf_stage( struct i915_context *i915 )
00530 {
00531 struct vbuf_render *render;
00532 struct draw_stage *stage;
00533
00534 render = i915_vbuf_render_create(i915);
00535 if(!render)
00536 return NULL;
00537
00538 stage = draw_vbuf_stage( i915->draw, render );
00539 if(!stage) {
00540 render->destroy(render);
00541 return NULL;
00542 }
00544 draw_set_render(i915->draw, render);
00545
00546 return stage;
00547 }