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
00028
00029
00030
00031
00032
00033 #include "main/imports.h"
00034 #include "main/image.h"
00035 #include "main/macros.h"
00036 #include "shader/prog_uniform.h"
00037
00038 #include "vbo/vbo.h"
00039
00040 #include "st_context.h"
00041 #include "st_atom.h"
00042 #include "st_cb_bufferobjects.h"
00043 #include "st_draw.h"
00044 #include "st_program.h"
00045
00046 #include "pipe/p_context.h"
00047 #include "pipe/p_defines.h"
00048 #include "pipe/p_inlines.h"
00049
00050
00051 static GLuint double_types[4] = {
00052 PIPE_FORMAT_R64_FLOAT,
00053 PIPE_FORMAT_R64G64_FLOAT,
00054 PIPE_FORMAT_R64G64B64_FLOAT,
00055 PIPE_FORMAT_R64G64B64A64_FLOAT
00056 };
00057
00058 static GLuint float_types[4] = {
00059 PIPE_FORMAT_R32_FLOAT,
00060 PIPE_FORMAT_R32G32_FLOAT,
00061 PIPE_FORMAT_R32G32B32_FLOAT,
00062 PIPE_FORMAT_R32G32B32A32_FLOAT
00063 };
00064
00065 static GLuint uint_types_norm[4] = {
00066 PIPE_FORMAT_R32_UNORM,
00067 PIPE_FORMAT_R32G32_UNORM,
00068 PIPE_FORMAT_R32G32B32_UNORM,
00069 PIPE_FORMAT_R32G32B32A32_UNORM
00070 };
00071
00072 static GLuint uint_types_scale[4] = {
00073 PIPE_FORMAT_R32_USCALED,
00074 PIPE_FORMAT_R32G32_USCALED,
00075 PIPE_FORMAT_R32G32B32_USCALED,
00076 PIPE_FORMAT_R32G32B32A32_USCALED
00077 };
00078
00079 static GLuint int_types_norm[4] = {
00080 PIPE_FORMAT_R32_SNORM,
00081 PIPE_FORMAT_R32G32_SNORM,
00082 PIPE_FORMAT_R32G32B32_SNORM,
00083 PIPE_FORMAT_R32G32B32A32_SNORM
00084 };
00085
00086 static GLuint int_types_scale[4] = {
00087 PIPE_FORMAT_R32_SSCALED,
00088 PIPE_FORMAT_R32G32_SSCALED,
00089 PIPE_FORMAT_R32G32B32_SSCALED,
00090 PIPE_FORMAT_R32G32B32A32_SSCALED
00091 };
00092
00093 static GLuint ushort_types_norm[4] = {
00094 PIPE_FORMAT_R16_UNORM,
00095 PIPE_FORMAT_R16G16_UNORM,
00096 PIPE_FORMAT_R16G16B16_UNORM,
00097 PIPE_FORMAT_R16G16B16A16_UNORM
00098 };
00099
00100 static GLuint ushort_types_scale[4] = {
00101 PIPE_FORMAT_R16_USCALED,
00102 PIPE_FORMAT_R16G16_USCALED,
00103 PIPE_FORMAT_R16G16B16_USCALED,
00104 PIPE_FORMAT_R16G16B16A16_USCALED
00105 };
00106
00107 static GLuint short_types_norm[4] = {
00108 PIPE_FORMAT_R16_SNORM,
00109 PIPE_FORMAT_R16G16_SNORM,
00110 PIPE_FORMAT_R16G16B16_SNORM,
00111 PIPE_FORMAT_R16G16B16A16_SNORM
00112 };
00113
00114 static GLuint short_types_scale[4] = {
00115 PIPE_FORMAT_R16_SSCALED,
00116 PIPE_FORMAT_R16G16_SSCALED,
00117 PIPE_FORMAT_R16G16B16_SSCALED,
00118 PIPE_FORMAT_R16G16B16A16_SSCALED
00119 };
00120
00121 static GLuint ubyte_types_norm[4] = {
00122 PIPE_FORMAT_R8_UNORM,
00123 PIPE_FORMAT_R8G8_UNORM,
00124 PIPE_FORMAT_R8G8B8_UNORM,
00125 PIPE_FORMAT_R8G8B8A8_UNORM
00126 };
00127
00128 static GLuint ubyte_types_scale[4] = {
00129 PIPE_FORMAT_R8_USCALED,
00130 PIPE_FORMAT_R8G8_USCALED,
00131 PIPE_FORMAT_R8G8B8_USCALED,
00132 PIPE_FORMAT_R8G8B8A8_USCALED
00133 };
00134
00135 static GLuint byte_types_norm[4] = {
00136 PIPE_FORMAT_R8_SNORM,
00137 PIPE_FORMAT_R8G8_SNORM,
00138 PIPE_FORMAT_R8G8B8_SNORM,
00139 PIPE_FORMAT_R8G8B8A8_SNORM
00140 };
00141
00142 static GLuint byte_types_scale[4] = {
00143 PIPE_FORMAT_R8_SSCALED,
00144 PIPE_FORMAT_R8G8_SSCALED,
00145 PIPE_FORMAT_R8G8B8_SSCALED,
00146 PIPE_FORMAT_R8G8B8A8_SSCALED
00147 };
00148
00149 static GLuint fixed_types[4] = {
00150 PIPE_FORMAT_R32_FIXED,
00151 PIPE_FORMAT_R32G32_FIXED,
00152 PIPE_FORMAT_R32G32B32_FIXED,
00153 PIPE_FORMAT_R32G32B32A32_FIXED
00154 };
00155
00156
00157
00161 GLuint
00162 st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized)
00163 {
00164 assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
00165 type == GL_FIXED);
00166 assert(size >= 1);
00167 assert(size <= 4);
00168
00169 if (normalized) {
00170 switch (type) {
00171 case GL_DOUBLE: return double_types[size-1];
00172 case GL_FLOAT: return float_types[size-1];
00173 case GL_INT: return int_types_norm[size-1];
00174 case GL_SHORT: return short_types_norm[size-1];
00175 case GL_BYTE: return byte_types_norm[size-1];
00176 case GL_UNSIGNED_INT: return uint_types_norm[size-1];
00177 case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
00178 case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
00179 case GL_FIXED: return fixed_types[size-1];
00180 default: assert(0); return 0;
00181 }
00182 }
00183 else {
00184 switch (type) {
00185 case GL_DOUBLE: return double_types[size-1];
00186 case GL_FLOAT: return float_types[size-1];
00187 case GL_INT: return int_types_scale[size-1];
00188 case GL_SHORT: return short_types_scale[size-1];
00189 case GL_BYTE: return byte_types_scale[size-1];
00190 case GL_UNSIGNED_INT: return uint_types_scale[size-1];
00191 case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
00192 case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
00193 case GL_FIXED: return fixed_types[size-1];
00194 default: assert(0); return 0;
00195 }
00196 }
00197 return 0;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206 static void *
00207 setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
00208 const struct gl_client_array *array)
00209 {
00210 struct pipe_context *pipe = ctx->st->pipe;
00211
00212 if ((primMode == GL_TRIANGLES ||
00213 primMode == GL_QUADS ||
00214 primMode == GL_POLYGON) &&
00215 (ctx->Polygon.FrontMode != GL_FILL ||
00216 ctx->Polygon.BackMode != GL_FILL)) {
00217
00218 GLint i;
00219 unsigned *vec;
00220 struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
00221 ubyte *map;
00222
00223 if (!stobj)
00224 return NULL;
00225
00226 vec = (unsigned *) calloc(sizeof(unsigned), (count + 31) / 32);
00227 if (!vec)
00228 return NULL;
00229
00230 map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
00231 map = ADD_POINTERS(map, array->Ptr);
00232
00233 for (i = 0; i < count; i++) {
00234 if (*((float *) map))
00235 vec[i/32] |= 1 << (i % 32);
00236
00237 map += array->StrideB;
00238 }
00239
00240 pipe_buffer_unmap(pipe->screen, stobj->buffer);
00241
00242 pipe->set_edgeflags(pipe, vec);
00243
00244 return vec;
00245 }
00246 else {
00247
00248 pipe->set_edgeflags(pipe, NULL);
00249 return NULL;
00250 }
00251 }
00252
00253
00259 static GLboolean
00260 is_interleaved_arrays(const struct st_vertex_program *vp,
00261 const struct gl_client_array **arrays,
00262 GLboolean *userSpace)
00263 {
00264 GLuint attr;
00265 const struct gl_buffer_object *firstBufObj = NULL;
00266 GLint firstStride = -1;
00267 GLuint num_client_arrays = 0;
00268 const GLubyte *client_addr = NULL;
00269
00270 for (attr = 0; attr < vp->num_inputs; attr++) {
00271 const GLuint mesaAttr = vp->index_to_input[attr];
00272 const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
00273 const GLsizei stride = arrays[mesaAttr]->StrideB;
00274
00275 if (firstStride < 0) {
00276 firstStride = stride;
00277 }
00278 else if (firstStride != stride) {
00279 return GL_FALSE;
00280 }
00281
00282 if (!bufObj || !bufObj->Name) {
00283 num_client_arrays++;
00284
00285
00286
00287 if (!client_addr) {
00288 client_addr = arrays[mesaAttr]->Ptr;
00289 }
00290 else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) {
00291
00292 return GL_FALSE;
00293 }
00294 }
00295 else if (!firstBufObj) {
00296 firstBufObj = bufObj;
00297 }
00298 else if (bufObj != firstBufObj) {
00299 return GL_FALSE;
00300 }
00301 }
00302
00303 *userSpace = (num_client_arrays == vp->num_inputs);
00304
00305
00306 return GL_TRUE;
00307 }
00308
00309
00314 static void
00315 get_user_arrays_bounds(const struct st_vertex_program *vp,
00316 const struct gl_client_array **arrays,
00317 GLuint max_index,
00318 const GLubyte **low, const GLubyte **high)
00319 {
00320 const GLubyte *low_addr = NULL;
00321 GLuint attr;
00322 GLint stride;
00323
00324 for (attr = 0; attr < vp->num_inputs; attr++) {
00325 const GLuint mesaAttr = vp->index_to_input[attr];
00326 const GLubyte *start = arrays[mesaAttr]->Ptr;
00327 stride = arrays[mesaAttr]->StrideB;
00328 if (attr == 0) {
00329 low_addr = start;
00330 }
00331 else {
00332 low_addr = MIN2(low_addr, start);
00333 }
00334 }
00335
00336 *low = low_addr;
00337 *high = low_addr + (max_index + 1) * stride;
00338 }
00339
00340
00347 static void
00348 setup_interleaved_attribs(GLcontext *ctx,
00349 const struct st_vertex_program *vp,
00350 const struct gl_client_array **arrays,
00351 GLuint max_index,
00352 GLboolean userSpace,
00353 struct pipe_vertex_buffer *vbuffer,
00354 struct pipe_vertex_element velements[])
00355 {
00356 struct pipe_context *pipe = ctx->st->pipe;
00357 GLuint attr;
00358 const GLubyte *offset0;
00359
00360 for (attr = 0; attr < vp->num_inputs; attr++) {
00361 const GLuint mesaAttr = vp->index_to_input[attr];
00362 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
00363 struct st_buffer_object *stobj = st_buffer_object(bufobj);
00364 GLsizei stride = arrays[mesaAttr]->StrideB;
00365
00366
00367
00368 if (attr == 0) {
00369 if (userSpace) {
00370 const GLubyte *low, *high;
00371 get_user_arrays_bounds(vp, arrays, max_index, &low, &high);
00372
00373 vbuffer->buffer =
00374 pipe_user_buffer_create(pipe->screen, (void *) low, high - low);
00375 vbuffer->buffer_offset = 0;
00376 offset0 = low;
00377 }
00378 else {
00379 vbuffer->buffer = NULL;
00380 pipe_buffer_reference(pipe->screen, &vbuffer->buffer, stobj->buffer);
00381 vbuffer->buffer_offset = (unsigned) arrays[mesaAttr]->Ptr;
00382 offset0 = arrays[mesaAttr]->Ptr;
00383 }
00384 vbuffer->pitch = stride;
00385 vbuffer->max_index = max_index;
00386 }
00387
00388 velements[attr].src_offset =
00389 (unsigned) (arrays[mesaAttr]->Ptr - offset0);
00390 velements[attr].vertex_buffer_index = 0;
00391 velements[attr].nr_components = arrays[mesaAttr]->Size;
00392 velements[attr].src_format =
00393 st_pipe_vertex_format(arrays[mesaAttr]->Type,
00394 arrays[mesaAttr]->Size,
00395 arrays[mesaAttr]->Normalized);
00396 assert(velements[attr].src_format);
00397 }
00398 }
00399
00400
00407 static void
00408 setup_non_interleaved_attribs(GLcontext *ctx,
00409 const struct st_vertex_program *vp,
00410 const struct gl_client_array **arrays,
00411 GLuint max_index,
00412 GLboolean *userSpace,
00413 struct pipe_vertex_buffer vbuffer[],
00414 struct pipe_vertex_element velements[])
00415 {
00416 struct pipe_context *pipe = ctx->st->pipe;
00417 GLuint attr;
00418
00419 for (attr = 0; attr < vp->num_inputs; attr++) {
00420 const GLuint mesaAttr = vp->index_to_input[attr];
00421 struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
00422 GLsizei stride = arrays[mesaAttr]->StrideB;
00423
00424 *userSpace = GL_FALSE;
00425
00426 if (bufobj && bufobj->Name) {
00427
00428
00429
00430
00431 struct st_buffer_object *stobj = st_buffer_object(bufobj);
00432 assert(stobj->buffer);
00433
00434
00435 vbuffer[attr].buffer = NULL;
00436 pipe_buffer_reference(pipe->screen, &vbuffer[attr].buffer, stobj->buffer);
00437 vbuffer[attr].buffer_offset = (unsigned) arrays[mesaAttr]->Ptr;
00438 velements[attr].src_offset = 0;
00439 }
00440 else {
00441
00442 uint bytes;
00443
00444
00445 *userSpace = GL_TRUE;
00446
00447
00448 if (arrays[mesaAttr]->Ptr) {
00449
00450 if (arrays[mesaAttr]->StrideB) {
00451 bytes = arrays[mesaAttr]->StrideB * (max_index + 1);
00452 }
00453 else {
00454 bytes = arrays[mesaAttr]->Size
00455 * _mesa_sizeof_type(arrays[mesaAttr]->Type);
00456 }
00457 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
00458 (void *) arrays[mesaAttr]->Ptr, bytes);
00459 }
00460 else {
00461
00462 bytes = sizeof(ctx->Current.Attrib[0]);
00463 vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen,
00464 (void *) ctx->Current.Attrib[mesaAttr], bytes);
00465 stride = 0;
00466 }
00467
00468 vbuffer[attr].buffer_offset = 0;
00469 velements[attr].src_offset = 0;
00470 }
00471
00472 assert(velements[attr].src_offset <= 2048);
00473
00474
00475 vbuffer[attr].pitch = stride;
00476 vbuffer[attr].max_index = max_index;
00477 velements[attr].vertex_buffer_index = attr;
00478 velements[attr].nr_components = arrays[mesaAttr]->Size;
00479 velements[attr].src_format
00480 = st_pipe_vertex_format(arrays[mesaAttr]->Type,
00481 arrays[mesaAttr]->Size,
00482 arrays[mesaAttr]->Normalized);
00483 assert(velements[attr].src_format);
00484 }
00485 }
00486
00487
00488
00494 static void
00495 check_uniforms(GLcontext *ctx)
00496 {
00497 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
00498 if (shProg && shProg->LinkStatus) {
00499 GLuint i;
00500 for (i = 0; i < shProg->Uniforms->NumUniforms; i++) {
00501 const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i];
00502 if (!u->Initialized) {
00503 _mesa_warning(ctx,
00504 "Using shader with uninitialized uniform: %s",
00505 u->Name);
00506 }
00507 }
00508 }
00509 }
00510
00511
00517 void
00518 st_draw_vbo(GLcontext *ctx,
00519 const struct gl_client_array **arrays,
00520 const struct _mesa_prim *prims,
00521 GLuint nr_prims,
00522 const struct _mesa_index_buffer *ib,
00523 GLuint min_index,
00524 GLuint max_index)
00525 {
00526 struct pipe_context *pipe = ctx->st->pipe;
00527 const struct st_vertex_program *vp;
00528 const struct pipe_shader_state *vs;
00529 struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
00530 GLuint attr;
00531 struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
00532 unsigned num_vbuffers, num_velements;
00533 GLboolean userSpace;
00534
00535
00536 assert(sizeof(arrays[0]->Ptr[0]) == 1);
00537
00538 st_validate_state(ctx->st);
00539
00540
00541 vp = ctx->st->vp;
00542 vs = &ctx->st->vp->state;
00543
00544 if (MESA_VERBOSE & VERBOSE_GLSL) {
00545 check_uniforms(ctx);
00546 }
00547
00548
00549
00550
00551 if (is_interleaved_arrays(vp, arrays, &userSpace)) {
00552
00553 setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace,
00554 vbuffer, velements);
00555 num_vbuffers = 1;
00556 num_velements = vp->num_inputs;
00557 if (num_velements == 0)
00558 num_vbuffers = 0;
00559 }
00560 else {
00561
00562 setup_non_interleaved_attribs(ctx, vp, arrays, max_index,
00563 &userSpace, vbuffer, velements);
00564 num_vbuffers = vp->num_inputs;
00565 num_velements = vp->num_inputs;
00566 }
00567
00568 #if 0
00569 {
00570 GLuint i;
00571 for (i = 0; i < num_vbuffers; i++) {
00572 printf("buffers[%d].pitch = %u\n", i, vbuffer[i].pitch);
00573 printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index);
00574 printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset);
00575 printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer);
00576 }
00577 for (i = 0; i < num_velements; i++) {
00578 printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index);
00579 printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset);
00580 printf("vlements[%d].nr_comps = %u\n", i, velements[i].nr_components);
00581 printf("vlements[%d].format = %s\n", i, pf_name(velements[i].src_format));
00582 }
00583 }
00584 #endif
00585
00586 pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
00587 pipe->set_vertex_elements(pipe, num_velements, velements);
00588
00589 if (num_vbuffers == 0 || num_velements == 0)
00590 return;
00591
00592
00593 if (ib) {
00594
00595 struct gl_buffer_object *bufobj = ib->obj;
00596 struct pipe_buffer *indexBuf = NULL;
00597 unsigned indexSize, indexOffset, i;
00598
00599 switch (ib->type) {
00600 case GL_UNSIGNED_INT:
00601 indexSize = 4;
00602 break;
00603 case GL_UNSIGNED_SHORT:
00604 indexSize = 2;
00605 break;
00606 case GL_UNSIGNED_BYTE:
00607 indexSize = 1;
00608 break;
00609 default:
00610 assert(0);
00611 return;
00612 }
00613
00614
00615 if (bufobj && bufobj->Name) {
00616
00617 struct st_buffer_object *stobj = st_buffer_object(bufobj);
00618 pipe_buffer_reference(pipe->screen, &indexBuf, stobj->buffer);
00619 indexOffset = (unsigned) ib->ptr / indexSize;
00620 }
00621 else {
00622
00623 indexBuf = pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
00624 ib->count * indexSize);
00625 indexOffset = 0;
00626 }
00627
00628
00629 if (nr_prims == 1 && pipe->draw_range_elements != NULL) {
00630 i = 0;
00631
00632
00633
00634
00635
00636 setup_edgeflags(ctx, prims[i].mode,
00637 prims[i].start + indexOffset, prims[i].count,
00638 arrays[VERT_ATTRIB_EDGEFLAG]);
00639
00640 pipe->draw_range_elements(pipe, indexBuf, indexSize,
00641 min_index,
00642 max_index,
00643 prims[i].mode,
00644 prims[i].start + indexOffset, prims[i].count);
00645 }
00646 else {
00647 for (i = 0; i < nr_prims; i++) {
00648 setup_edgeflags(ctx, prims[i].mode,
00649 prims[i].start + indexOffset, prims[i].count,
00650 arrays[VERT_ATTRIB_EDGEFLAG]);
00651
00652 pipe->draw_elements(pipe, indexBuf, indexSize,
00653 prims[i].mode,
00654 prims[i].start + indexOffset, prims[i].count);
00655 }
00656 }
00657
00658 pipe_buffer_reference(pipe->screen, &indexBuf, NULL);
00659 }
00660 else {
00661
00662 GLuint i;
00663 for (i = 0; i < nr_prims; i++) {
00664 setup_edgeflags(ctx, prims[i].mode,
00665 prims[i].start, prims[i].count,
00666 arrays[VERT_ATTRIB_EDGEFLAG]);
00667
00668 pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
00669 }
00670 }
00671
00672
00673 for (attr = 0; attr < num_vbuffers; attr++) {
00674 pipe_buffer_reference(pipe->screen, &vbuffer[attr].buffer, NULL);
00675 assert(!vbuffer[attr].buffer);
00676 }
00677
00678 if (userSpace)
00679 {
00680 pipe->set_vertex_buffers(pipe, 0, NULL);
00681 }
00682 }
00683
00684
00685 void st_init_draw( struct st_context *st )
00686 {
00687 GLcontext *ctx = st->ctx;
00688
00689 vbo_set_draw_func(ctx, st_draw_vbo);
00690 }
00691
00692
00693 void st_destroy_draw( struct st_context *st )
00694 {
00695 }
00696
00697